Skip to content

Commit

Permalink
feat: CldVideoPlayer support for Next.js 13 App Router (#265)
Browse files Browse the repository at this point in the history
# Description

With the App Router, we no longer have access to the <Head component.
CldVideoPlayer was utilizing this component in order to load a
stylesheet, preventing the need to include it from the project, but
without <Head, the player breaks.

Given this is no longer an option, this includes the CSS and associated
files on build so that they're able to be imported from within the App
Router project, allowing the stylesheet to be imported for a working
player.

This is currently downloading the assets from unpkg, where the player is
officially hosted, though future iterations may include these files from
the cloudinary-video-player node_module, though thats currently on hold
for performance reasons. See #181

This also deprecates the `version` prop as we're no longer able to
reliably grab assets based on the configured version (or at all for that
matter). In future versions using the node module, the assets will be
synced based on the installed dependency via next-cloudinary without
configuration available.

## Issue Ticket Number

Fixes #248 

<!-- Specify above which issue this fixes by referencing the issue
number (`#<ISSUE_NUMBER>`) or issue URL. -->
<!-- Example: Fixes
https://github.com/colbyfayock/next-cloudinary/issues/<ISSUE_NUMBER> -->

## Type of change

<!-- Please select all options that are applicable. -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Fix or improve the documentation
- [ ] This change requires a documentation update


# Checklist

<!-- These must all be followed and checked. -->

- [ ] I have followed the contributing guidelines of this project as
mentioned in [CONTRIBUTING.md](/CONTRIBUTING.md)
- [ ] I have created an
[issue](https://github.com/colbyfayock/next-cloudinary/issues) ticket
for this PR
- [ ] I have checked to ensure there aren't other open [Pull
Requests](https://github.com/colbyfayock/next-cloudinary/pulls) for the
same update/change?
- [ ] I have performed a self-review of my own code
- [ ] I have run tests locally to ensure they all pass
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes needed to the documentation
  • Loading branch information
colbyfayock authored Aug 28, 2023
1 parent 52bad18 commit 8674b95
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 5 deletions.
6 changes: 6 additions & 0 deletions docs/pages/cldvideoplayer/basic-usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ import { CldVideoPlayer } from 'next-cloudinary';
/>
```

If you're using the Next.js 13 App Router, you must additionally import the Cloudinary Video Player stylesheet:

```jsx
import 'next-cloudinary/dist/cld-video-player.css';
```

<CldVideoPlayer
width="1620"
height="1080"
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/cldvideoplayer/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import OgImage from '../../components/OgImage';
| showLogo | boolea | `true` | Show the Cloudinary logo on Player | `false` |
| src | string | - | **Required**: Video public ID | `"videos/my-video"` |
| transformation | object/array | - | Transformations to apply to the video | `{ width: 200, height: 200, crop: 'fill' }` |
| version | string | `"1.9.4"` | Cloudinary Video Player version | `"1.9.4"` |
| videoRef | Ref | - | React ref to access video element | See Refs Below |
| version | string | `"1.9.14"` | **Deprecated** | - ` |
| videoRef | Ref | - | React ref to access video element | See Refs Below |
| width | string/number | - | **Required**: Player width | `1920` |

Missing an option from the [Video Player docs](https://cloudinary.com/documentation/video_player_api_reference) you'd like to see? [Create an issue](https://github.com/colbyfayock/next-cloudinary/issues/new?assignees=&labels=Type%3A+Feature&template=feature_request.md&title=%5BFeature%5D+)!
Expand Down
1 change: 1 addition & 0 deletions next-cloudinary/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"dotenv": "^16.0.3",
"jest": "^29.2.2",
"jest-environment-jsdom": "^29.2.2",
"mkdirp": "^3.0.1",
"ts-jest": "^29.0.3",
"tsup": "^6.6.3",
"typescript": "^4.9.4"
Expand Down
68 changes: 68 additions & 0 deletions next-cloudinary/plugins/copy-assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Plugin } from 'esbuild'
import path from 'path';
import { createWriteStream } from 'fs';
import { mkdirp } from 'mkdirp';
import https from 'https';

const version = '1.9.14';

const assets = [
`https://unpkg.com/cloudinary-video-player@${version}/dist/cld-video-player.css`,
{
directory: 'fonts',
assets: [
`https://unpkg.com/cloudinary-video-player@${version}/dist/fonts/cloudinary_icon_for_black_bg.svg`,
`https://unpkg.com/cloudinary-video-player@${version}/dist/fonts/cloudinary_icon_for_white_bg.svg`,
]
}
];

let hasWrittenAssets = false;

export const plugin: Plugin = {
name: 'copy-assets',
setup: async () => {
const rootPath = path.join(__dirname, '../');
const distPath = path.join(rootPath, 'dist');

if ( hasWrittenAssets ) return;

await mkdirp(distPath);

for ( const asset of assets ) {

if ( typeof asset === 'string' ) {
const writePath = path.join(distPath, path.basename(asset));
await downloadFile(asset, writePath);
console.log(`Wrote ${asset} to ${writePath}`);
} else if ( typeof asset.directory === 'string' ) {
await mkdirp(path.join(distPath, asset.directory));

for ( const dirAsset of asset.assets ) {
const writePath = path.join(distPath, asset.directory, path.basename(dirAsset));
await downloadFile(dirAsset, writePath);
console.log(`Wrote ${dirAsset} to ${writePath}`);
}
}
}

hasWrittenAssets = true;
}
}

/**
* downloadFile
*/

function downloadFile(assetUrl: string, writePath: string) {
return new Promise<void>((resolve) => {
const file = createWriteStream(writePath);
https.get(assetUrl, function(response) {
response.pipe(file);
file.on('finish', () => {
file.close();
resolve();
});
});
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ const CldVideoPlayer = (props: CldVideoPlayerProps) => {
onEnded,
src,
transformation,
version = '1.9.4',
version = '1.9.14',
quality = 'auto',
width,
} = props as CldVideoPlayerProps;

const playerTransformations = Array.isArray(transformation) ? transformation : [transformation];
let publicId = src;

if ( typeof props.version === 'string' ) {
console.warn('The version prop will no longer be supported in future versions due to the unreliability of coordinating assets');
}

// If the publicId/src is a URL, attempt to parse it as a Cloudinary URL
// to get the public ID alone

Expand Down
10 changes: 9 additions & 1 deletion next-cloudinary/tests/nextjs-app/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"use client";

import { CldImage, CldUploadWidget } from '../../../';
import { CldImage, CldUploadWidget, CldVideoPlayer } from '../../../';

import '../../../dist/cld-video-player.css';

export default function Home() {
return (
Expand All @@ -12,6 +14,12 @@ export default function Home() {
sources: ['local', 'camera']
}}
/>
<CldVideoPlayer
id="test"
width="1620"
height="1080"
src={`videos/mountain-stars`}
/>
</>
)
}
4 changes: 3 additions & 1 deletion next-cloudinary/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { defineConfig } from 'tsup'
import { plugin as CopyAssetsPlugin } from './plugins/copy-assets';

export default defineConfig({
minify: true,
target: 'es2018',
external: ['react'],
sourcemap: true,
dts: true,
format: ['esm', 'cjs']
format: ['esm', 'cjs'],
esbuildPlugins: [CopyAssetsPlugin]
})
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4990,6 +4990,11 @@ minimatch@^3.0.4, minimatch@^3.1.1:
dependencies:
brace-expansion "^1.1.7"

mkdirp@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==

mri@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
Expand Down

1 comment on commit 8674b95

@vercel
Copy link

@vercel vercel bot commented on 8674b95 Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.