@aigamo/nostalgic-diva 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +125 -0
- package/dist/components/AudioPlayer.d.ts +3 -0
- package/dist/components/NiconicoPlayer.d.ts +3 -0
- package/dist/components/NostalgicDiva.d.ts +9 -0
- package/dist/components/NostalgicDivaProvider.d.ts +11 -0
- package/dist/components/PlayerContainer.d.ts +16 -0
- package/dist/components/SoundCloudPlayer.d.ts +3 -0
- package/dist/components/VimeoPlayer.d.ts +3 -0
- package/dist/components/YouTubePlayer.d.ts +3 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/useFirstMountState.d.ts +1 -0
- package/dist/components/usePreviousDistinct.d.ts +2 -0
- package/dist/global.d.ts +757 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +802 -0
- package/dist/index.es.js.map +1 -0
- package/dist/players/AudioPlayerApi.d.ts +17 -0
- package/dist/players/NiconicoPlayerApi.d.ts +27 -0
- package/dist/players/PlayerApi.d.ts +58 -0
- package/dist/players/PlayerApiImpl.d.ts +18 -0
- package/dist/players/PlayerConsole.d.ts +8 -0
- package/dist/players/SoundCloudPlayerApi.d.ts +20 -0
- package/dist/players/VimeoPlayerApi.d.ts +17 -0
- package/dist/players/YouTubePlayerApi.d.ts +28 -0
- package/dist/players/ensureScriptLoaded.d.ts +1 -0
- package/dist/players/getScript.d.ts +1 -0
- package/dist/players/index.d.ts +6 -0
- package/package.json +69 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/players/PlayerApiImpl.ts","../src/players/AudioPlayerApi.ts","../src/players/PlayerConsole.ts","../src/players/PlayerApi.ts","../src/components/useFirstMountState.ts","../src/components/usePreviousDistinct.ts","../src/components/PlayerContainer.tsx","../src/components/AudioPlayer.tsx","../src/players/NiconicoPlayerApi.ts","../src/components/NiconicoPlayer.tsx","../src/components/NostalgicDivaProvider.tsx","../src/players/SoundCloudPlayerApi.ts","../src/players/getScript.ts","../src/players/ensureScriptLoaded.ts","../src/components/SoundCloudPlayer.tsx","../src/players/VimeoPlayerApi.ts","../src/components/VimeoPlayer.tsx","../src/players/YouTubePlayerApi.ts","../src/components/YouTubePlayer.tsx","../src/components/NostalgicDiva.tsx"],"sourcesContent":["import React from 'react';\n\nimport { IPlayerApi, Logger, PlayerOptions } from './PlayerApi';\n\nexport abstract class PlayerApiImpl<TElement extends HTMLElement>\n\timplements IPlayerApi\n{\n\tprotected constructor(\n\t\tprotected readonly logger: Logger,\n\t\tprotected readonly playerElementRef: React.MutableRefObject<TElement>,\n\t\tprotected readonly options: PlayerOptions | undefined,\n\t) {\n\t\tthis.logger.debug('ctor');\n\t}\n\n\tabstract attach(id: string): Promise<void>;\n\tabstract detach(): Promise<void>;\n\tabstract loadVideo(id: string): Promise<void>;\n\tabstract play(): Promise<void>;\n\tabstract pause(): Promise<void>;\n\tabstract setCurrentTime(seconds: number): Promise<void>;\n\tabstract setVolume(volume: number): Promise<void>;\n\tabstract setMuted(muted: boolean): Promise<void>;\n\tabstract getDuration(): Promise<number | undefined>;\n\tabstract getCurrentTime(): Promise<number | undefined>;\n}\n","import React from 'react';\n\nimport { Logger, PlayerOptions } from './PlayerApi';\nimport { PlayerApiImpl } from './PlayerApiImpl';\n\n// https://github.com/VocaDB/vocadb/blob/61b8c54f3eca906a477101dab4fdd9b154be310e/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerFile.ts.\nexport class AudioPlayerApi extends PlayerApiImpl<HTMLAudioElement> {\n\tprivate readonly player: HTMLAudioElement;\n\n\tconstructor(\n\t\tlogger: Logger,\n\t\tplayerElementRef: React.MutableRefObject<HTMLAudioElement>,\n\t\toptions: PlayerOptions | undefined,\n\t) {\n\t\tsuper(logger, playerElementRef, options);\n\n\t\tthis.player = playerElementRef.current;\n\t}\n\n\tasync attach(): Promise<void> {\n\t\tthis.player.onerror = (event): void => this.options?.onError?.(event);\n\t\tthis.player.onloadeddata = (): void =>\n\t\t\tthis.options?.onLoaded?.({ id: this.player.src });\n\t\tthis.player.onplay = (): void => this.options?.onPlay?.();\n\t\tthis.player.onpause = (): void => this.options?.onPause?.();\n\t\tthis.player.onended = (): void => this.options?.onEnded?.();\n\t\tthis.player.ontimeupdate = (): void => {\n\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\tduration: this.player.duration,\n\t\t\t\tpercent: this.player.currentTime / this.player.duration,\n\t\t\t\tseconds: this.player.currentTime,\n\t\t\t});\n\t\t};\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.onerror = null;\n\t\tthis.player.onloadeddata = null;\n\t\tthis.player.onplay = null;\n\t\tthis.player.onpause = null;\n\t\tthis.player.onended = null;\n\t\tthis.player.ontimeupdate = null;\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.src = id;\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.currentTime = seconds;\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.volume = volume;\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.muted = muted;\n\t}\n\n\tasync getDuration(): Promise<number | undefined> {\n\t\treturn this.player.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number | undefined> {\n\t\treturn this.player.currentTime;\n\t}\n}\n","export class PlayerConsole {\n\tprivate static title = 'nostalgic-diva';\n\n\tprivate static createMessage(message: any): string {\n\t\treturn `[${PlayerConsole.title}] ${message}`;\n\t}\n\n\tpublic static assert(\n\t\tcondition?: boolean | undefined,\n\t\tmessage?: any,\n\t\t...optionalParams: any\n\t): void {\n\t\tconsole.assert(\n\t\t\tcondition,\n\t\t\tPlayerConsole.createMessage(message),\n\t\t\t...optionalParams,\n\t\t);\n\t}\n\n\tpublic static debug(message?: any, ...optionalParams: any): void {\n\t\tconsole.debug(PlayerConsole.createMessage(message), ...optionalParams);\n\t}\n\n\tpublic static error(message?: any, ...optionalParams: any): void {\n\t\tconsole.error(PlayerConsole.createMessage(message), ...optionalParams);\n\t}\n\n\tpublic static warn(message?: any, ...optionalParams: any): void {\n\t\tconsole.warn(PlayerConsole.createMessage(message), ...optionalParams);\n\t}\n}\n","import React from 'react';\n\nimport { PlayerApiImpl } from './PlayerApiImpl';\nimport { PlayerConsole } from './PlayerConsole';\n\nexport type PlayerType =\n\t| 'Audio'\n\t| 'Niconico'\n\t| 'SoundCloud'\n\t| 'Vimeo'\n\t| 'YouTube';\n\nexport interface LoadedEvent {\n\tid: string;\n}\n\nexport interface TimeEvent {\n\tduration: number | undefined;\n\tpercent: number | undefined;\n\tseconds: number | undefined;\n}\n\nexport interface PlayerOptions {\n\tonError?(event: any): void;\n\tonLoaded?(event: LoadedEvent): void;\n\tonPlay?(): void;\n\tonPause?(): void;\n\tonEnded?(): void;\n\tonTimeUpdate?(event: TimeEvent): void;\n}\n\nexport interface IPlayerApi {\n\tloadVideo(id: string): Promise<void>;\n\tplay(): Promise<void>;\n\tpause(): Promise<void>;\n\tsetCurrentTime(seconds: number): Promise<void>;\n\tsetVolume(volume: number): Promise<void>;\n\tsetMuted(muted: boolean): Promise<void>;\n\tgetDuration(): Promise<number | undefined>;\n\tgetCurrentTime(): Promise<number | undefined>;\n}\n\nexport interface Logger {\n\tdebug(message?: any, ...optionalParams: any): void;\n\terror(message?: any, ...optionalParams: any): void;\n}\n\nexport class PlayerApi<\n\tTElement extends HTMLElement,\n\tTPlayer extends PlayerApiImpl<TElement>,\n> implements IPlayerApi, Logger\n{\n\tprivate static nextId = 1;\n\n\tprivate readonly id: number;\n\tprivate impl?: TPlayer;\n\n\tconstructor(\n\t\tprivate readonly type: PlayerType,\n\t\tprivate readonly playerElementRef: React.MutableRefObject<TElement>,\n\t\tprivate readonly options: PlayerOptions | undefined,\n\t\tprivate readonly loadScript: (() => Promise<void>) | undefined,\n\t\tprivate readonly playerApiFactory: new (\n\t\t\tlogger: Logger,\n\t\t\tplayerElementRef: React.MutableRefObject<TElement>,\n\t\t\toptions: PlayerOptions | undefined,\n\t\t) => TPlayer,\n\t) {\n\t\tthis.id = PlayerApi.nextId++;\n\t}\n\n\tprivate createMessage(message: any): string {\n\t\treturn `${this.type}#${this.id} ${message}`;\n\t}\n\n\tpublic debug(message?: any, ...optionalParams: any): void {\n\t\tPlayerConsole.debug(this.createMessage(message), ...optionalParams);\n\t}\n\n\tpublic error(message?: any, ...optionalParams: any): void {\n\t\tPlayerConsole.error(this.createMessage(message), ...optionalParams);\n\t}\n\n\tasync attach(id: string): Promise<void> {\n\t\tthis.debug('attach', id);\n\n\t\tif (this.impl) {\n\t\t\tthis.debug('player is already attached');\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.loadScript?.();\n\n\t\tthis.debug('Attaching player...');\n\n\t\tthis.impl = new this.playerApiFactory(\n\t\t\tthis,\n\t\t\tthis.playerElementRef,\n\t\t\tthis.options,\n\t\t);\n\n\t\tawait this.impl.attach(id);\n\n\t\tthis.debug('player attached');\n\t}\n\n\tprivate assertPlayerAttached(): void {\n\t\tPlayerConsole.assert(!!this.impl, 'player is not attached');\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.debug('detach');\n\t\tthis.assertPlayerAttached();\n\n\t\tawait this.impl?.detach();\n\n\t\tthis.impl = undefined;\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.debug('loadVideo', id);\n\t\tthis.assertPlayerAttached();\n\n\t\tthis.debug('Loading video...');\n\n\t\tawait this.impl?.loadVideo(id);\n\n\t\tthis.debug('video loaded', id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.debug('play');\n\t\tthis.assertPlayerAttached();\n\n\t\tawait this.impl?.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.debug('pause');\n\t\tthis.assertPlayerAttached();\n\n\t\tawait this.impl?.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.debug('setCurrentTime', seconds);\n\t\tthis.assertPlayerAttached();\n\n\t\tawait this.impl?.setCurrentTime(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.debug('setVolume', volume);\n\t\tthis.assertPlayerAttached();\n\n\t\tawait this.impl?.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.debug('setMuted', muted);\n\t\tthis.assertPlayerAttached();\n\n\t\tawait this.impl?.setMuted(muted);\n\t}\n\n\tasync getDuration(): Promise<number | undefined> {\n\t\tthis.debug('getDuration');\n\t\tthis.assertPlayerAttached();\n\n\t\treturn await this.impl?.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number | undefined> {\n\t\tthis.debug('getCurrentTime');\n\t\tthis.assertPlayerAttached();\n\n\t\treturn await this.impl?.getCurrentTime();\n\t}\n}\n","// https://github.com/streamich/react-use/blob/8ceb4c0f0c5625124f487b435a2fd0d3b3bc2a4f/src/useFirstMountState.ts\nimport { useRef } from 'react';\n\nexport function useFirstMountState(): boolean {\n\tconst isFirst = useRef(true);\n\n\tif (isFirst.current) {\n\t\tisFirst.current = false;\n\n\t\treturn true;\n\t}\n\n\treturn isFirst.current;\n}\n","// https://github.com/streamich/react-use/blob/8ceb4c0f0c5625124f487b435a2fd0d3b3bc2a4f/src/usePreviousDistinct.ts.\nimport { useRef } from 'react';\n\nimport { useFirstMountState } from './useFirstMountState';\n\nexport type Predicate<T> = (prev: T | undefined, next: T) => boolean;\n\nconst strictEquals = <T>(prev: T | undefined, next: T): boolean =>\n\tprev === next;\n\nexport default function usePreviousDistinct<T>(\n\tvalue: T,\n\tcompare: Predicate<T> = strictEquals,\n): T | undefined {\n\tconst prevRef = useRef<T>();\n\tconst curRef = useRef<T>(value);\n\tconst isFirstMount = useFirstMountState();\n\n\tif (!isFirstMount && !compare(curRef.current, value)) {\n\t\tprevRef.current = curRef.current;\n\t\tcurRef.current = value;\n\t}\n\n\treturn prevRef.current;\n}\n","import React from 'react';\n\nimport {\n\tIPlayerApi,\n\tLogger,\n\tPlayerApi,\n\tPlayerOptions,\n\tPlayerType,\n} from '../players/PlayerApi';\nimport { PlayerApiImpl } from '../players/PlayerApiImpl';\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport usePreviousDistinct from './usePreviousDistinct';\n\nexport interface PlayerProps {\n\ttype: PlayerType;\n\tplayerApiRef: React.MutableRefObject<IPlayerApi | undefined> | undefined;\n\tvideoId: string;\n\toptions: PlayerOptions | undefined;\n}\n\ninterface PlayerContainerProps<\n\tTElement extends HTMLElement,\n\tTPlayer extends PlayerApiImpl<TElement>,\n> extends PlayerProps {\n\tloadScript: (() => Promise<void>) | undefined;\n\tplayerApiFactory: new (\n\t\tlogger: Logger,\n\t\tplayerElementRef: React.MutableRefObject<TElement>,\n\t\toptions: PlayerOptions | undefined,\n\t) => TPlayer;\n\tchildren: (\n\t\tplayerElementRef: React.MutableRefObject<TElement>,\n\t\tvideoId: string,\n\t) => React.ReactNode;\n}\n\nexport const PlayerContainer = <\n\tTElement extends HTMLElement,\n\tTPlayer extends PlayerApiImpl<TElement>,\n>({\n\ttype,\n\tplayerApiRef,\n\tvideoId,\n\toptions,\n\tloadScript,\n\tplayerApiFactory,\n\tchildren,\n}: PlayerContainerProps<TElement, TPlayer>): React.ReactElement<\n\tPlayerContainerProps<TElement, TPlayer>\n> => {\n\tPlayerConsole.debug('PlayerContainer');\n\n\tconst videoIdRef = React.useRef(videoId);\n\n\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\tconst playerElementRef = React.useRef<TElement>(undefined!);\n\n\tconst [playerApi, setPlayerApi] = React.useState<IPlayerApi>();\n\n\t// Make sure that `options` do not change between re-rendering.\n\tReact.useEffect(() => {\n\t\tconst playerApi = new PlayerApi(\n\t\t\ttype,\n\t\t\tplayerElementRef,\n\t\t\toptions,\n\t\t\tloadScript,\n\t\t\tplayerApiFactory,\n\t\t);\n\n\t\tif (playerApiRef) playerApiRef.current = playerApi;\n\n\t\tplayerApi\n\t\t\t.attach(videoIdRef.current)\n\t\t\t.then(() => setPlayerApi(playerApi));\n\n\t\treturn (): void => {\n\t\t\tif (playerApiRef) {\n\t\t\t\tPlayerConsole.assert(\n\t\t\t\t\tplayerApi === playerApiRef.current,\n\t\t\t\t\t'playerApi differs',\n\t\t\t\t\tplayerApi,\n\t\t\t\t\tplayerApiRef.current,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tplayerApi.detach().then(() => setPlayerApi(undefined));\n\t\t};\n\t}, [type, options, loadScript, playerApiFactory, playerApiRef]);\n\n\tconst previousVideoId = usePreviousDistinct(videoId);\n\tReact.useEffect(() => {\n\t\t// If `previousVideoId` is undefined, then it means that the video has already been loaded by either\n\t\t// 1. `<audio>`s `src` attribute (e.g. `AudioPlayer`),\n\t\t// 2. `<iframe>`'s `src` attribute (e.g. `NiconicoPlayer`, `SoundCloudPlayer` and `VimeoPlayer`), or\n\t\t// 3. the `attach` method of the player API (e.g. `YouTubePlayer`).\n\t\tif (previousVideoId === undefined) return;\n\n\t\tplayerApi?.loadVideo(videoId);\n\t}, [previousVideoId, videoId, playerApi]);\n\n\t// Make sure that `videoId` does not change between re-rendering.\n\treturn <>{children(playerElementRef, videoIdRef.current)}</>;\n};\n","import React from 'react';\n\nimport { AudioPlayerApi } from '../players/AudioPlayerApi';\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport { PlayerContainer, PlayerProps } from './PlayerContainer';\n\nexport const AudioPlayer = React.memo(\n\t({ ...props }: PlayerProps): React.ReactElement => {\n\t\tPlayerConsole.debug('AudioPlayer');\n\n\t\treturn (\n\t\t\t<PlayerContainer\n\t\t\t\t{...props}\n\t\t\t\tloadScript={undefined}\n\t\t\t\tplayerApiFactory={AudioPlayerApi}\n\t\t\t>\n\t\t\t\t{(playerElementRef, videoId): React.ReactElement => (\n\t\t\t\t\t<audio\n\t\t\t\t\t\tref={playerElementRef}\n\t\t\t\t\t\tsrc={videoId}\n\t\t\t\t\t\tstyle={{ width: '100%', height: '100%' }}\n\t\t\t\t\t\tpreload=\"auto\"\n\t\t\t\t\t\tautoPlay\n\t\t\t\t\t\tcontrols\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</PlayerContainer>\n\t\t);\n\t},\n);\n","import React from 'react';\n\nimport { Logger, PlayerOptions } from './PlayerApi';\nimport { PlayerApiImpl } from './PlayerApiImpl';\n\ndeclare global {\n\tinterface Window {\n\t\tonNicoPlayerFactoryReady: (callback: nico.NicoPlayerFactory) => void;\n\t}\n}\n\nenum PlayerStatus {\n\tPlay = 2,\n\tPause = 3,\n\tEnd = 4,\n}\n\n// https://github.com/VocaDB/vocadb/blob/a4b5f9d8186772d7e6f58f997bbcbb51509d2539/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerNico.ts.\nexport class NiconicoPlayerApi extends PlayerApiImpl<HTMLIFrameElement> {\n\tprivate static readonly origin = 'https://embed.nicovideo.jp';\n\n\tprivate readonly player: HTMLIFrameElement;\n\n\tprivate duration?: number;\n\tprivate currentTime?: number;\n\n\tconstructor(\n\t\tlogger: Logger,\n\t\tplayerElementRef: React.MutableRefObject<HTMLIFrameElement>,\n\t\toptions: PlayerOptions | undefined,\n\t) {\n\t\tsuper(logger, playerElementRef, options);\n\n\t\tthis.player = playerElementRef.current;\n\t}\n\n\tprivate handleMessage(e: nico.PlayerEvent): void {\n\t\tif (e.origin !== NiconicoPlayerApi.origin) return;\n\n\t\tconst data = e.data;\n\n\t\tswitch (data.eventName) {\n\t\t\tcase 'playerStatusChange':\n\t\t\t\tthis.logger.debug(\n\t\t\t\t\t`player status changed: ${\n\t\t\t\t\t\tPlayerStatus[data.data.playerStatus] ??\n\t\t\t\t\t\tdata.data.playerStatus\n\t\t\t\t\t}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase 'statusChange':\n\t\t\t\tthis.logger.debug(\n\t\t\t\t\t`status changed: ${\n\t\t\t\t\t\tPlayerStatus[data.data.playerStatus] ??\n\t\t\t\t\t\tdata.data.playerStatus\n\t\t\t\t\t}`,\n\t\t\t\t);\n\n\t\t\t\tswitch (data.data.playerStatus) {\n\t\t\t\t\tcase PlayerStatus.Play:\n\t\t\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PlayerStatus.Pause:\n\t\t\t\t\t\tthis.options?.onPause?.();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PlayerStatus.End:\n\t\t\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 'playerMetadataChange':\n\t\t\t\tif (data.data.duration !== undefined)\n\t\t\t\t\tthis.duration = data.data.duration / 1000;\n\n\t\t\t\tthis.currentTime =\n\t\t\t\t\tdata.data.currentTime === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: data.data.currentTime / 1000;\n\n\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\tduration: this.duration,\n\t\t\t\t\tpercent:\n\t\t\t\t\t\tthis.currentTime !== undefined &&\n\t\t\t\t\t\tthis.duration !== undefined\n\t\t\t\t\t\t\t? this.currentTime / this.duration\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\tseconds: this.currentTime,\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase 'loadComplete':\n\t\t\t\tthis.logger.debug('load completed');\n\n\t\t\t\tthis.duration = data.data.videoInfo.lengthInSeconds;\n\n\t\t\t\tthis.options?.onLoaded?.({ id: data.data.videoInfo.watchId });\n\t\t\t\tbreak;\n\n\t\t\tcase 'error':\n\t\t\t\t// TODO: Implement.\n\n\t\t\t\tthis.options?.onError?.(data);\n\t\t\t\tbreak;\n\n\t\t\tcase 'player-error:video:play':\n\t\t\tcase 'player-error:video:seek':\n\t\t\t\tthis.options?.onError?.(data);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthis.logger.debug(\n\t\t\t\t\t'message',\n\t\t\t\t\t(data as any).eventName,\n\t\t\t\t\t(data as any).data,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tasync attach(): Promise<void> {\n\t\twindow.addEventListener('message', this.handleMessage);\n\t}\n\n\tasync detach(): Promise<void> {\n\t\twindow.removeEventListener('message', this.handleMessage);\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\treturn new Promise((resolve, reject /* TODO: Reject. */) => {\n\t\t\tthis.duration = undefined;\n\t\t\tthis.currentTime = undefined;\n\n\t\t\t// Wait for iframe to load.\n\t\t\tthis.player.onload = (): void => {\n\t\t\t\tthis.player.onload = null;\n\t\t\t\tresolve();\n\t\t\t};\n\n\t\t\tthis.player.src = `https://embed.nicovideo.jp/watch/${id}?jsapi=1&playerId=1`;\n\t\t});\n\t}\n\n\t// https://blog.hayu.io/web/create/nicovideo-embed-player-api/.\n\tprivate postMessage(message: any): void {\n\t\tthis.player.contentWindow?.postMessage(\n\t\t\t{\n\t\t\t\t...message,\n\t\t\t\tplayerId: '1' /* Needs to be a string, not a number. */,\n\t\t\t\tsourceConnectorType: 1,\n\t\t\t},\n\t\t\tNiconicoPlayerApi.origin,\n\t\t);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.postMessage({ eventName: 'play' });\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.postMessage({ eventName: 'pause' });\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.postMessage({ eventName: 'seek', data: { time: seconds * 1000 } });\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.postMessage({\n\t\t\teventName: 'volumeChange',\n\t\t\tdata: { volume: volume },\n\t\t});\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.postMessage({\n\t\t\teventName: 'mute',\n\t\t\tdata: { mute: muted },\n\t\t});\n\t}\n\n\tasync getDuration(): Promise<number | undefined> {\n\t\treturn this.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number | undefined> {\n\t\treturn this.currentTime;\n\t}\n}\n","import React from 'react';\n\nimport { NiconicoPlayerApi } from '../players/NiconicoPlayerApi';\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport { PlayerContainer, PlayerProps } from './PlayerContainer';\n\nexport const NiconicoPlayer = React.memo(\n\t({ ...props }: PlayerProps): React.ReactElement => {\n\t\tPlayerConsole.debug('NiconicoPlayer');\n\n\t\treturn (\n\t\t\t<PlayerContainer\n\t\t\t\t{...props}\n\t\t\t\tloadScript={undefined}\n\t\t\t\tplayerApiFactory={NiconicoPlayerApi}\n\t\t\t>\n\t\t\t\t{(playerElementRef, videoId): React.ReactElement => (\n\t\t\t\t\t<div style={{ width: '100%', height: '100%' }}>\n\t\t\t\t\t\t{/* eslint-disable-next-line jsx-a11y/iframe-has-title */}\n\t\t\t\t\t\t<iframe\n\t\t\t\t\t\t\tref={playerElementRef}\n\t\t\t\t\t\t\tsrc={`https://embed.nicovideo.jp/watch/${videoId}?jsapi=1&playerId=1`}\n\t\t\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\t\t\theight=\"100%\"\n\t\t\t\t\t\t\tallowFullScreen\n\t\t\t\t\t\t\tstyle={{ border: 'none' }}\n\t\t\t\t\t\t\t// The player has to have the allow=\"autoplay\" attribute.\n\t\t\t\t\t\t\t// Otherwise it throws a NotAllowedError: \"play() failed because the user didn't interact with the document first\".\n\t\t\t\t\t\t\t// See also: https://github.com/vimeo/player.js/issues/389.\n\t\t\t\t\t\t\t// NOTE: An iframe element created by `PVPlayerNiconico.playerFactory.create` doesn't have the allow=\"autoplay\" attribute,\n\t\t\t\t\t\t\t// which causes the above issue when trying to autoplay a video.\n\t\t\t\t\t\t\tallow=\"autoplay; fullscreen\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</PlayerContainer>\n\t\t);\n\t},\n);\n","import React from 'react';\n\nimport { IPlayerApi } from '../players';\n\ninterface NostalgicDivaContextProps extends IPlayerApi {\n\tplayerApiRef: React.MutableRefObject<IPlayerApi | undefined>;\n}\n\nconst NostalgicDivaContext = React.createContext<NostalgicDivaContextProps>(\n\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\tundefined!,\n);\n\ninterface NostalgicDivaProviderProps {\n\tchildren?: React.ReactNode;\n}\n\nexport const NostalgicDivaProvider = ({\n\tchildren,\n}: NostalgicDivaProviderProps): React.ReactElement => {\n\tconst playerApiRef = React.useRef<IPlayerApi>();\n\n\tconst loadVideo = React.useCallback(async (id: string) => {\n\t\tawait playerApiRef.current?.loadVideo(id);\n\t}, []);\n\n\tconst play = React.useCallback(async () => {\n\t\tawait playerApiRef.current?.play();\n\t}, []);\n\n\tconst pause = React.useCallback(async () => {\n\t\tawait playerApiRef.current?.pause();\n\t}, []);\n\n\tconst setCurrentTime = React.useCallback(async (seconds: number) => {\n\t\tconst playerApi = playerApiRef.current;\n\t\tif (!playerApi) return;\n\n\t\tawait playerApi.setCurrentTime(seconds);\n\t\tawait playerApi.play();\n\t}, []);\n\n\tconst setVolume = React.useCallback(async (volume: number) => {\n\t\tawait playerApiRef.current?.setVolume(volume);\n\t}, []);\n\n\tconst setMuted = React.useCallback(async (muted: boolean) => {\n\t\tawait playerApiRef.current?.setMuted(muted);\n\t}, []);\n\n\tconst getDuration = React.useCallback(async () => {\n\t\treturn await playerApiRef.current?.getDuration();\n\t}, []);\n\n\tconst getCurrentTime = React.useCallback(async () => {\n\t\treturn await playerApiRef.current?.getCurrentTime();\n\t}, []);\n\n\tconst value = React.useMemo(\n\t\t(): NostalgicDivaContextProps => ({\n\t\t\tplayerApiRef,\n\t\t\tloadVideo,\n\t\t\tplay,\n\t\t\tpause,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tsetMuted,\n\t\t\tgetDuration,\n\t\t\tgetCurrentTime,\n\t\t}),\n\t\t[\n\t\t\tloadVideo,\n\t\t\tplay,\n\t\t\tpause,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tsetMuted,\n\t\t\tgetDuration,\n\t\t\tgetCurrentTime,\n\t\t],\n\t);\n\n\treturn (\n\t\t<NostalgicDivaContext.Provider value={value}>\n\t\t\t{children}\n\t\t</NostalgicDivaContext.Provider>\n\t);\n};\n\nexport const useNostalgicDiva = (): NostalgicDivaContextProps => {\n\treturn React.useContext(NostalgicDivaContext);\n};\n","import React from 'react';\n\nimport { Logger, PlayerOptions } from './PlayerApi';\nimport { PlayerApiImpl } from './PlayerApiImpl';\n\n// https://github.com/VocaDB/vocadb/blob/e147650a8f1f85c8fa865d0ab562126c278527ec/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerSoundCloud.ts.\nexport class SoundCloudPlayerApi extends PlayerApiImpl<HTMLIFrameElement> {\n\tprivate readonly player: SC.SoundCloudWidget;\n\n\tconstructor(\n\t\tlogger: Logger,\n\t\tplayerElementRef: React.MutableRefObject<HTMLIFrameElement>,\n\t\toptions: PlayerOptions | undefined,\n\t) {\n\t\tsuper(logger, playerElementRef, options);\n\n\t\tthis.player = SC.Widget(this.playerElementRef.current);\n\t}\n\n\tprivate static playerGetDurationAsync(\n\t\tplayer: SC.SoundCloudWidget,\n\t): Promise<number> {\n\t\treturn new Promise((resolve, reject /* TODO: Reject. */) => {\n\t\t\tplayer.getDuration(resolve);\n\t\t});\n\t}\n\n\tattach(id: string): Promise<void> {\n\t\treturn new Promise((resolve, reject /* TODO: reject */) => {\n\t\t\tthis.player.bind(SC.Widget.Events.READY, () => {\n\t\t\t\tthis.player.bind(\n\t\t\t\t\tSC.Widget.Events.PLAY_PROGRESS,\n\t\t\t\t\tasync (event) => {\n\t\t\t\t\t\tconst duration =\n\t\t\t\t\t\t\tawait SoundCloudPlayerApi.playerGetDurationAsync(\n\t\t\t\t\t\t\t\tthis.player,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\t\t\tduration: duration / 1000,\n\t\t\t\t\t\t\tpercent: event.currentPosition / duration,\n\t\t\t\t\t\t\tseconds: event.currentPosition / 1000,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.ERROR, (event) =>\n\t\t\t\t\tthis.options?.onError?.(event),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.PLAY, () =>\n\t\t\t\t\tthis.options?.onPlay?.(),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.PAUSE, () =>\n\t\t\t\t\tthis.options?.onPause?.(),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.FINISH, () =>\n\t\t\t\t\tthis.options?.onEnded?.(),\n\t\t\t\t);\n\n\t\t\t\tthis.options?.onLoaded?.({ id: id });\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.unbind(SC.Widget.Events.READY);\n\t\tthis.player.unbind(SC.Widget.Events.PLAY_PROGRESS);\n\t\tthis.player.unbind(SC.Widget.Events.ERROR);\n\t\tthis.player.unbind(SC.Widget.Events.PLAY);\n\t\tthis.player.unbind(SC.Widget.Events.PAUSE);\n\t\tthis.player.unbind(SC.Widget.Events.FINISH);\n\t}\n\n\tprivate static playerLoadAsync(\n\t\tplayer: SC.SoundCloudWidget,\n\t\turl: string,\n\t\toptions: Omit<SC.SoundCloudLoadOptions, 'callback'>,\n\t): Promise<void> {\n\t\treturn new Promise((resolve, reject /* TODO: Reject. */) => {\n\t\t\tplayer.load(url, { ...options, callback: resolve });\n\t\t});\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait SoundCloudPlayerApi.playerLoadAsync(this.player, id, {\n\t\t\tauto_play: true,\n\t\t});\n\n\t\tthis.options?.onLoaded?.({ id: id });\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seekTo(seconds * 1000);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume * 100);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.setVolume(muted ? 0 : 1 /* TODO */);\n\t}\n\n\tasync getDuration(): Promise<number | undefined> {\n\t\tconst duration = await SoundCloudPlayerApi.playerGetDurationAsync(\n\t\t\tthis.player,\n\t\t);\n\n\t\treturn duration / 1000;\n\t}\n\n\tprivate static playerGetPositionAsync(\n\t\tplayer: SC.SoundCloudWidget,\n\t): Promise<number> {\n\t\treturn new Promise((resolve, reject /* TODO: Reject. */) => {\n\t\t\tplayer.getPosition(resolve);\n\t\t});\n\t}\n\n\tasync getCurrentTime(): Promise<number | undefined> {\n\t\tconst position = await SoundCloudPlayerApi.playerGetPositionAsync(\n\t\t\tthis.player,\n\t\t);\n\n\t\treturn position / 1000;\n\t}\n}\n","// https://stackoverflow.com/a/61903296.\nexport function getScript(url: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst script = document.createElement('script') as any; /* TODO */\n\t\tscript.src = url;\n\t\tscript.async = true;\n\n\t\tscript.onerror = reject;\n\n\t\tscript.onload = script.onreadystatechange = function (): void {\n\t\t\tconst loadState = this.readyState;\n\n\t\t\tif (loadState && loadState !== 'loaded' && loadState !== 'complete')\n\t\t\t\treturn;\n\n\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\tresolve();\n\t\t};\n\n\t\tdocument.head.appendChild(script);\n\t});\n}\n","import { PlayerConsole } from './PlayerConsole';\nimport { getScript } from './getScript';\n\nconst urls: string[] = [];\n\nexport async function ensureScriptLoaded(url: string): Promise<boolean> {\n\tif (urls.includes(url)) {\n\t\tPlayerConsole.debug(url, 'script is already loaded');\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tPlayerConsole.debug(url, 'Loading script...');\n\n\t\tawait getScript(url);\n\n\t\tif (urls.includes(url)) {\n\t\t\tPlayerConsole.debug(url, 'script is already loaded');\n\t\t\treturn false;\n\t\t} else {\n\t\t\turls.push(url);\n\t\t\tPlayerConsole.debug(url, 'script loaded');\n\t\t\treturn true;\n\t\t}\n\t} catch (error) {\n\t\tPlayerConsole.error(url, 'Failed to load script');\n\t\tthrow error;\n\t}\n}\n","import React from 'react';\n\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport { SoundCloudPlayerApi } from '../players/SoundCloudPlayerApi';\nimport { ensureScriptLoaded } from '../players/ensureScriptLoaded';\nimport { PlayerContainer, PlayerProps } from './PlayerContainer';\n\nexport const SoundCloudPlayer = React.memo(\n\t({ ...props }: PlayerProps): React.ReactElement => {\n\t\tPlayerConsole.debug('SoundCloudPlayer');\n\n\t\tconst loadScript = React.useCallback(async () => {\n\t\t\tawait ensureScriptLoaded('https://w.soundcloud.com/player/api.js');\n\t\t}, []);\n\n\t\treturn (\n\t\t\t<PlayerContainer\n\t\t\t\t{...props}\n\t\t\t\tloadScript={loadScript}\n\t\t\t\tplayerApiFactory={SoundCloudPlayerApi}\n\t\t\t>\n\t\t\t\t{(playerElementRef, videoId): React.ReactElement => (\n\t\t\t\t\t// eslint-disable-next-line jsx-a11y/iframe-has-title\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tref={playerElementRef}\n\t\t\t\t\t\tsrc={`https://w.soundcloud.com/player/?url=${videoId}`}\n\t\t\t\t\t\tframeBorder={0}\n\t\t\t\t\t\tallow=\"autoplay\"\n\t\t\t\t\t\tstyle={{ width: '100%', height: '100%' }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</PlayerContainer>\n\t\t);\n\t},\n);\n","import React from 'react';\n\nimport { Logger, PlayerOptions } from './PlayerApi';\nimport { PlayerApiImpl } from './PlayerApiImpl';\n\n// https://github.com/cookpete/react-player/blob/e3c324bc6845698179d065fa408db515c2296b4b/src/players/Vimeo.js\nexport class VimeoPlayerApi extends PlayerApiImpl<HTMLIFrameElement> {\n\tprivate readonly player: Vimeo.Player;\n\n\tconstructor(\n\t\tlogger: Logger,\n\t\tplayerElementRef: React.MutableRefObject<HTMLIFrameElement>,\n\t\toptions: PlayerOptions | undefined,\n\t) {\n\t\tsuper(logger, playerElementRef, options);\n\n\t\tthis.player = new Vimeo.Player(this.playerElementRef.current);\n\t}\n\n\tasync attach(): Promise<void> {\n\t\tawait this.player.ready();\n\n\t\tthis.player.on('error', (data) => this.options?.onError?.(data));\n\t\tthis.player.on('loaded', (event) =>\n\t\t\tthis.options?.onLoaded?.({ id: event.id.toString() }),\n\t\t);\n\t\tthis.player.on('play', () => this.options?.onPlay?.());\n\t\tthis.player.on('pause', () => this.options?.onPause?.());\n\t\tthis.player.on('ended', () => this.options?.onEnded?.());\n\t\tthis.player.on('timeupdate', (data) => {\n\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\tduration: data.duration,\n\t\t\t\tpercent: data.percent,\n\t\t\t\tseconds: data.seconds,\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.off('error');\n\t\tthis.player.off('loaded');\n\t\tthis.player.off('play');\n\t\tthis.player.off('pause');\n\t\tthis.player.off('ended');\n\t\tthis.player.off('timeupdate');\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait this.player.loadVideo(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tawait this.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tawait this.player.setCurrentTime(seconds);\n\t}\n\n\tasync setVolume(fraction: number): Promise<void> {\n\t\tawait this.player.setVolume(fraction);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tawait this.player.setMuted(muted);\n\t}\n\n\tasync getDuration(): Promise<number | undefined> {\n\t\treturn await this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number | undefined> {\n\t\treturn await this.player.getCurrentTime();\n\t}\n}\n","import React from 'react';\n\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport { VimeoPlayerApi } from '../players/VimeoPlayerApi';\nimport { ensureScriptLoaded } from '../players/ensureScriptLoaded';\nimport { PlayerContainer, PlayerProps } from './PlayerContainer';\n\nexport const VimeoPlayer = React.memo(\n\t({ ...props }: PlayerProps): React.ReactElement => {\n\t\tPlayerConsole.debug('VimeoPlayer');\n\n\t\tconst loadScript = React.useCallback(async () => {\n\t\t\tawait ensureScriptLoaded('https://player.vimeo.com/api/player.js');\n\t\t}, []);\n\n\t\treturn (\n\t\t\t<PlayerContainer\n\t\t\t\t{...props}\n\t\t\t\tloadScript={loadScript}\n\t\t\t\tplayerApiFactory={VimeoPlayerApi}\n\t\t\t>\n\t\t\t\t{(playerElementRef, videoId): React.ReactElement => (\n\t\t\t\t\t// eslint-disable-next-line jsx-a11y/iframe-has-title\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tref={playerElementRef}\n\t\t\t\t\t\tsrc={`https://player.vimeo.com/video/${videoId}`}\n\t\t\t\t\t\tframeBorder={0}\n\t\t\t\t\t\tallow=\"autoplay\"\n\t\t\t\t\t\tstyle={{ width: '100%', height: '100%' }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</PlayerContainer>\n\t\t);\n\t},\n);\n","import React from 'react';\n\nimport { Logger, PlayerOptions } from './PlayerApi';\nimport { PlayerApiImpl } from './PlayerApiImpl';\n\ndeclare global {\n\tinterface Window {\n\t\tonYouTubeIframeAPIReady(): void;\n\t}\n}\n\nenum PlayerState {\n\tUNSTARTED = -1,\n\tENDED = 0,\n\tPLAYING = 1,\n\tPAUSED = 2,\n\tBUFFERING = 3,\n\tCUED = 5,\n}\n\n// https://github.com/VocaDB/vocadb/blob/076dac9f0808aba5da7332209fdfd2ff4e12c235/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerYoutube.ts.\nexport class YouTubePlayerApi extends PlayerApiImpl<HTMLDivElement> {\n\tprivate static readonly origin = 'https://www.youtube-nocookie.com';\n\n\tprivate readonly player: YT.Player;\n\n\tconstructor(\n\t\tlogger: Logger,\n\t\tplayerElementRef: React.MutableRefObject<HTMLDivElement>,\n\t\toptions: PlayerOptions | undefined,\n\t) {\n\t\tsuper(logger, playerElementRef, options);\n\n\t\tthis.player = new YT.Player(this.playerElementRef.current, {\n\t\t\thost: YouTubePlayerApi.origin,\n\t\t\twidth: '100%',\n\t\t\theight: '100%',\n\t\t});\n\t}\n\n\tprivate previousTime?: number;\n\n\tprivate timeUpdateIntervalId?: number;\n\n\tprivate clearTimeUpdateInterval(): void {\n\t\tthis.logger.debug('clearTimeUpdateInterval', this.timeUpdateIntervalId);\n\n\t\twindow.clearInterval(this.timeUpdateIntervalId);\n\n\t\tthis.timeUpdateIntervalId = undefined;\n\t}\n\n\tprivate invokeTimeUpdate(player: YT.Player): void {\n\t\tconst currentTime = player.getCurrentTime();\n\t\tif (currentTime === this.previousTime) return;\n\n\t\tconst duration = player.getDuration();\n\t\tthis.options?.onTimeUpdate?.({\n\t\t\tduration: duration,\n\t\t\tpercent: currentTime / duration,\n\t\t\tseconds: currentTime,\n\t\t});\n\n\t\tthis.previousTime = currentTime;\n\t}\n\n\tprivate setTimeUpdateInterval(): void {\n\t\tthis.logger.debug('setTimeUpdateInterval');\n\n\t\tthis.clearTimeUpdateInterval();\n\n\t\tthis.timeUpdateIntervalId = window.setInterval(\n\t\t\t() => this.invokeTimeUpdate(this.player),\n\t\t\t250,\n\t\t);\n\n\t\tthis.logger.debug('timeUpdateIntervalId', this.timeUpdateIntervalId);\n\n\t\tthis.invokeTimeUpdate(this.player);\n\t}\n\n\tattach(id: string): Promise<void> {\n\t\treturn new Promise((resolve, reject /* TODO: reject */) => {\n\t\t\tthis.player.addEventListener('onReady', async () => {\n\t\t\t\tthis.player.addEventListener('onError', (event) =>\n\t\t\t\t\tthis.options?.onError?.(event.data),\n\t\t\t\t);\n\t\t\t\tthis.player.addEventListener(\n\t\t\t\t\t'onStateChange',\n\t\t\t\t\t(event: YT.EventArgs): void => {\n\t\t\t\t\t\tthis.logger.debug(\n\t\t\t\t\t\t\t`state changed: ${PlayerState[event.data]}`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tswitch (event.data) {\n\t\t\t\t\t\t\tcase YT.PlayerState.CUED:\n\t\t\t\t\t\t\t\tthis.options?.onLoaded?.({ id: id });\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.PLAYING:\n\t\t\t\t\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\t\t\t\t\tthis.setTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.PAUSED:\n\t\t\t\t\t\t\t\tthis.options?.onPause?.();\n\t\t\t\t\t\t\t\tthis.clearTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.ENDED:\n\t\t\t\t\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\t\t\t\t\tthis.clearTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tawait this.loadVideo(id);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.clearTimeUpdateInterval();\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.previousTime = undefined;\n\t\tthis.player.cueVideoById(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.playVideo();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pauseVideo();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seekTo(seconds);\n\n\t\tthis.invokeTimeUpdate(this.player);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume * 100);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tif (muted) {\n\t\t\tthis.player.mute();\n\t\t} else {\n\t\t\tthis.player.unMute();\n\t\t}\n\t}\n\n\tasync getDuration(): Promise<number | undefined> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number | undefined> {\n\t\treturn this.player.getCurrentTime();\n\t}\n}\n","import React from 'react';\n\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport { YouTubePlayerApi } from '../players/YouTubePlayerApi';\nimport { ensureScriptLoaded } from '../players/ensureScriptLoaded';\nimport { PlayerContainer, PlayerProps } from './PlayerContainer';\n\nexport const YouTubePlayer = React.memo(\n\t({ ...props }: PlayerProps): React.ReactElement => {\n\t\tPlayerConsole.debug('YouTubePlayer');\n\n\t\tconst loadScript = React.useCallback((): Promise<void> => {\n\t\t\treturn new Promise(async (resolve, reject) => {\n\t\t\t\tconst first = await ensureScriptLoaded(\n\t\t\t\t\t'https://www.youtube.com/iframe_api',\n\t\t\t\t);\n\n\t\t\t\tif (first) {\n\t\t\t\t\t// https://stackoverflow.com/a/18154942.\n\t\t\t\t\twindow.onYouTubeIframeAPIReady = (): void => {\n\t\t\t\t\t\tPlayerConsole.debug('YouTube iframe API ready');\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t}, []);\n\n\t\treturn (\n\t\t\t<PlayerContainer\n\t\t\t\t{...props}\n\t\t\t\tloadScript={loadScript}\n\t\t\t\tplayerApiFactory={YouTubePlayerApi}\n\t\t\t>\n\t\t\t\t{(playerElementRef): React.ReactElement => (\n\t\t\t\t\t<div style={{ width: '100%', height: '100%' }}>\n\t\t\t\t\t\t<div ref={playerElementRef} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</PlayerContainer>\n\t\t);\n\t},\n);\n","import React from 'react';\n\nimport { PlayerOptions, PlayerType } from '../players/PlayerApi';\nimport { PlayerConsole } from '../players/PlayerConsole';\nimport { AudioPlayer } from './AudioPlayer';\nimport { NiconicoPlayer } from './NiconicoPlayer';\nimport { useNostalgicDiva } from './NostalgicDivaProvider';\nimport { PlayerProps } from './PlayerContainer';\nimport { SoundCloudPlayer } from './SoundCloudPlayer';\nimport { VimeoPlayer } from './VimeoPlayer';\nimport { YouTubePlayer } from './YouTubePlayer';\n\nconst players: Record<PlayerType, React.ElementType<PlayerProps>> = {\n\tAudio: AudioPlayer,\n\tNiconico: NiconicoPlayer,\n\tSoundCloud: SoundCloudPlayer,\n\tVimeo: VimeoPlayer,\n\tYouTube: YouTubePlayer,\n};\n\ninterface NostalgicDivaProps {\n\ttype: PlayerType;\n\tvideoId: string;\n\toptions?: PlayerOptions;\n}\n\nexport const NostalgicDiva = React.memo(\n\t({ type, videoId, options }: NostalgicDivaProps): React.ReactElement => {\n\t\tPlayerConsole.debug('NostalgicDiva');\n\n\t\tconst diva = useNostalgicDiva();\n\n\t\tconst Player = players[type];\n\t\treturn (\n\t\t\t<Player\n\t\t\t\ttype={type}\n\t\t\t\tplayerApiRef={diva.playerApiRef}\n\t\t\t\tvideoId={videoId}\n\t\t\t\toptions={options}\n\t\t\t/>\n\t\t);\n\t},\n);\n"],"names":["PlayerApiImpl","logger","playerElementRef","options","AudioPlayerApi","__publicField","event","_b","_a","id","seconds","volume","muted","_PlayerConsole","message","condition","optionalParams","PlayerConsole","_PlayerApi","type","loadScript","playerApiFactory","PlayerApi","useFirstMountState","isFirst","useRef","strictEquals","prev","next","usePreviousDistinct","value","compare","prevRef","curRef","PlayerContainer","playerApiRef","videoId","children","videoIdRef","React","playerApi","setPlayerApi","previousVideoId","AudioPlayer","props","PlayerStatus","_NiconicoPlayerApi","data","_d","_c","_f","_e","_h","_g","_j","_i","_l","_k","_n","_m","_p","_o","resolve","reject","NiconicoPlayerApi","NiconicoPlayer","NostalgicDivaContext","NostalgicDivaProvider","loadVideo","play","pause","setCurrentTime","setVolume","setMuted","getDuration","getCurrentTime","useNostalgicDiva","SoundCloudPlayerApi","player","duration","url","getScript","script","loadState","urls","ensureScriptLoaded","error","SoundCloudPlayer","VimeoPlayerApi","fraction","VimeoPlayer","PlayerState","_YouTubePlayerApi","currentTime","YouTubePlayerApi","YouTubePlayer","players","NostalgicDiva","diva","Player"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Logger, PlayerOptions } from './PlayerApi';
|
|
3
|
+
import { PlayerApiImpl } from './PlayerApiImpl';
|
|
4
|
+
export declare class AudioPlayerApi extends PlayerApiImpl<HTMLAudioElement> {
|
|
5
|
+
private readonly player;
|
|
6
|
+
constructor(logger: Logger, playerElementRef: React.MutableRefObject<HTMLAudioElement>, options: PlayerOptions | undefined);
|
|
7
|
+
attach(): Promise<void>;
|
|
8
|
+
detach(): Promise<void>;
|
|
9
|
+
loadVideo(id: string): Promise<void>;
|
|
10
|
+
play(): Promise<void>;
|
|
11
|
+
pause(): Promise<void>;
|
|
12
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
13
|
+
setVolume(volume: number): Promise<void>;
|
|
14
|
+
setMuted(muted: boolean): Promise<void>;
|
|
15
|
+
getDuration(): Promise<number | undefined>;
|
|
16
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Logger, PlayerOptions } from './PlayerApi';
|
|
3
|
+
import { PlayerApiImpl } from './PlayerApiImpl';
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
onNicoPlayerFactoryReady: (callback: nico.NicoPlayerFactory) => void;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare class NiconicoPlayerApi extends PlayerApiImpl<HTMLIFrameElement> {
|
|
10
|
+
private static readonly origin;
|
|
11
|
+
private readonly player;
|
|
12
|
+
private duration?;
|
|
13
|
+
private currentTime?;
|
|
14
|
+
constructor(logger: Logger, playerElementRef: React.MutableRefObject<HTMLIFrameElement>, options: PlayerOptions | undefined);
|
|
15
|
+
private handleMessage;
|
|
16
|
+
attach(): Promise<void>;
|
|
17
|
+
detach(): Promise<void>;
|
|
18
|
+
loadVideo(id: string): Promise<void>;
|
|
19
|
+
private postMessage;
|
|
20
|
+
play(): Promise<void>;
|
|
21
|
+
pause(): Promise<void>;
|
|
22
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
23
|
+
setVolume(volume: number): Promise<void>;
|
|
24
|
+
setMuted(muted: boolean): Promise<void>;
|
|
25
|
+
getDuration(): Promise<number | undefined>;
|
|
26
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { PlayerApiImpl } from './PlayerApiImpl';
|
|
3
|
+
export type PlayerType = 'Audio' | 'Niconico' | 'SoundCloud' | 'Vimeo' | 'YouTube';
|
|
4
|
+
export interface LoadedEvent {
|
|
5
|
+
id: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TimeEvent {
|
|
8
|
+
duration: number | undefined;
|
|
9
|
+
percent: number | undefined;
|
|
10
|
+
seconds: number | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface PlayerOptions {
|
|
13
|
+
onError?(event: any): void;
|
|
14
|
+
onLoaded?(event: LoadedEvent): void;
|
|
15
|
+
onPlay?(): void;
|
|
16
|
+
onPause?(): void;
|
|
17
|
+
onEnded?(): void;
|
|
18
|
+
onTimeUpdate?(event: TimeEvent): void;
|
|
19
|
+
}
|
|
20
|
+
export interface IPlayerApi {
|
|
21
|
+
loadVideo(id: string): Promise<void>;
|
|
22
|
+
play(): Promise<void>;
|
|
23
|
+
pause(): Promise<void>;
|
|
24
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
25
|
+
setVolume(volume: number): Promise<void>;
|
|
26
|
+
setMuted(muted: boolean): Promise<void>;
|
|
27
|
+
getDuration(): Promise<number | undefined>;
|
|
28
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
29
|
+
}
|
|
30
|
+
export interface Logger {
|
|
31
|
+
debug(message?: any, ...optionalParams: any): void;
|
|
32
|
+
error(message?: any, ...optionalParams: any): void;
|
|
33
|
+
}
|
|
34
|
+
export declare class PlayerApi<TElement extends HTMLElement, TPlayer extends PlayerApiImpl<TElement>> implements IPlayerApi, Logger {
|
|
35
|
+
private readonly type;
|
|
36
|
+
private readonly playerElementRef;
|
|
37
|
+
private readonly options;
|
|
38
|
+
private readonly loadScript;
|
|
39
|
+
private readonly playerApiFactory;
|
|
40
|
+
private static nextId;
|
|
41
|
+
private readonly id;
|
|
42
|
+
private impl?;
|
|
43
|
+
constructor(type: PlayerType, playerElementRef: React.MutableRefObject<TElement>, options: PlayerOptions | undefined, loadScript: (() => Promise<void>) | undefined, playerApiFactory: new (logger: Logger, playerElementRef: React.MutableRefObject<TElement>, options: PlayerOptions | undefined) => TPlayer);
|
|
44
|
+
private createMessage;
|
|
45
|
+
debug(message?: any, ...optionalParams: any): void;
|
|
46
|
+
error(message?: any, ...optionalParams: any): void;
|
|
47
|
+
attach(id: string): Promise<void>;
|
|
48
|
+
private assertPlayerAttached;
|
|
49
|
+
detach(): Promise<void>;
|
|
50
|
+
loadVideo(id: string): Promise<void>;
|
|
51
|
+
play(): Promise<void>;
|
|
52
|
+
pause(): Promise<void>;
|
|
53
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
54
|
+
setVolume(volume: number): Promise<void>;
|
|
55
|
+
setMuted(muted: boolean): Promise<void>;
|
|
56
|
+
getDuration(): Promise<number | undefined>;
|
|
57
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IPlayerApi, Logger, PlayerOptions } from './PlayerApi';
|
|
3
|
+
export declare abstract class PlayerApiImpl<TElement extends HTMLElement> implements IPlayerApi {
|
|
4
|
+
protected readonly logger: Logger;
|
|
5
|
+
protected readonly playerElementRef: React.MutableRefObject<TElement>;
|
|
6
|
+
protected readonly options: PlayerOptions | undefined;
|
|
7
|
+
protected constructor(logger: Logger, playerElementRef: React.MutableRefObject<TElement>, options: PlayerOptions | undefined);
|
|
8
|
+
abstract attach(id: string): Promise<void>;
|
|
9
|
+
abstract detach(): Promise<void>;
|
|
10
|
+
abstract loadVideo(id: string): Promise<void>;
|
|
11
|
+
abstract play(): Promise<void>;
|
|
12
|
+
abstract pause(): Promise<void>;
|
|
13
|
+
abstract setCurrentTime(seconds: number): Promise<void>;
|
|
14
|
+
abstract setVolume(volume: number): Promise<void>;
|
|
15
|
+
abstract setMuted(muted: boolean): Promise<void>;
|
|
16
|
+
abstract getDuration(): Promise<number | undefined>;
|
|
17
|
+
abstract getCurrentTime(): Promise<number | undefined>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class PlayerConsole {
|
|
2
|
+
private static title;
|
|
3
|
+
private static createMessage;
|
|
4
|
+
static assert(condition?: boolean | undefined, message?: any, ...optionalParams: any): void;
|
|
5
|
+
static debug(message?: any, ...optionalParams: any): void;
|
|
6
|
+
static error(message?: any, ...optionalParams: any): void;
|
|
7
|
+
static warn(message?: any, ...optionalParams: any): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Logger, PlayerOptions } from './PlayerApi';
|
|
3
|
+
import { PlayerApiImpl } from './PlayerApiImpl';
|
|
4
|
+
export declare class SoundCloudPlayerApi extends PlayerApiImpl<HTMLIFrameElement> {
|
|
5
|
+
private readonly player;
|
|
6
|
+
constructor(logger: Logger, playerElementRef: React.MutableRefObject<HTMLIFrameElement>, options: PlayerOptions | undefined);
|
|
7
|
+
private static playerGetDurationAsync;
|
|
8
|
+
attach(id: string): Promise<void>;
|
|
9
|
+
detach(): Promise<void>;
|
|
10
|
+
private static playerLoadAsync;
|
|
11
|
+
loadVideo(id: string): Promise<void>;
|
|
12
|
+
play(): Promise<void>;
|
|
13
|
+
pause(): Promise<void>;
|
|
14
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
15
|
+
setVolume(volume: number): Promise<void>;
|
|
16
|
+
setMuted(muted: boolean): Promise<void>;
|
|
17
|
+
getDuration(): Promise<number | undefined>;
|
|
18
|
+
private static playerGetPositionAsync;
|
|
19
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Logger, PlayerOptions } from './PlayerApi';
|
|
3
|
+
import { PlayerApiImpl } from './PlayerApiImpl';
|
|
4
|
+
export declare class VimeoPlayerApi extends PlayerApiImpl<HTMLIFrameElement> {
|
|
5
|
+
private readonly player;
|
|
6
|
+
constructor(logger: Logger, playerElementRef: React.MutableRefObject<HTMLIFrameElement>, options: PlayerOptions | undefined);
|
|
7
|
+
attach(): Promise<void>;
|
|
8
|
+
detach(): Promise<void>;
|
|
9
|
+
loadVideo(id: string): Promise<void>;
|
|
10
|
+
play(): Promise<void>;
|
|
11
|
+
pause(): Promise<void>;
|
|
12
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
13
|
+
setVolume(fraction: number): Promise<void>;
|
|
14
|
+
setMuted(muted: boolean): Promise<void>;
|
|
15
|
+
getDuration(): Promise<number | undefined>;
|
|
16
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Logger, PlayerOptions } from './PlayerApi';
|
|
3
|
+
import { PlayerApiImpl } from './PlayerApiImpl';
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
onYouTubeIframeAPIReady(): void;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export declare class YouTubePlayerApi extends PlayerApiImpl<HTMLDivElement> {
|
|
10
|
+
private static readonly origin;
|
|
11
|
+
private readonly player;
|
|
12
|
+
constructor(logger: Logger, playerElementRef: React.MutableRefObject<HTMLDivElement>, options: PlayerOptions | undefined);
|
|
13
|
+
private previousTime?;
|
|
14
|
+
private timeUpdateIntervalId?;
|
|
15
|
+
private clearTimeUpdateInterval;
|
|
16
|
+
private invokeTimeUpdate;
|
|
17
|
+
private setTimeUpdateInterval;
|
|
18
|
+
attach(id: string): Promise<void>;
|
|
19
|
+
detach(): Promise<void>;
|
|
20
|
+
loadVideo(id: string): Promise<void>;
|
|
21
|
+
play(): Promise<void>;
|
|
22
|
+
pause(): Promise<void>;
|
|
23
|
+
setCurrentTime(seconds: number): Promise<void>;
|
|
24
|
+
setVolume(volume: number): Promise<void>;
|
|
25
|
+
setMuted(muted: boolean): Promise<void>;
|
|
26
|
+
getDuration(): Promise<number | undefined>;
|
|
27
|
+
getCurrentTime(): Promise<number | undefined>;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureScriptLoaded(url: string): Promise<boolean>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getScript(url: string): Promise<void>;
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aigamo/nostalgic-diva",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"clean": "rimraf ./dist",
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "yarn clean && tsc && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@trivago/prettier-plugin-sort-imports": "^3.4.0",
|
|
13
|
+
"@types/react": "^18.0.24",
|
|
14
|
+
"@types/react-dom": "^18.0.8",
|
|
15
|
+
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
|
16
|
+
"@typescript-eslint/parser": "^5.43.0",
|
|
17
|
+
"@vitejs/plugin-react": "^2.2.0",
|
|
18
|
+
"eslint": "^8.27.0",
|
|
19
|
+
"eslint-config-prettier": "^8.5.0",
|
|
20
|
+
"eslint-config-react-app": "^7.0.1",
|
|
21
|
+
"eslint-plugin-flowtype": "^8.0.3",
|
|
22
|
+
"eslint-plugin-import": "^2.26.0",
|
|
23
|
+
"eslint-plugin-jsx-a11y": "^6.6.1",
|
|
24
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
25
|
+
"eslint-plugin-react": "^7.31.10",
|
|
26
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
27
|
+
"prettier": "^2.7.1",
|
|
28
|
+
"react": "^17.0.2",
|
|
29
|
+
"react-dom": "^17.0.2",
|
|
30
|
+
"rimraf": "^3.0.2",
|
|
31
|
+
"typescript": "^4.6.4",
|
|
32
|
+
"vite": "^3.2.3",
|
|
33
|
+
"vite-plugin-dts": "^1.7.1"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"react": "^17.0.2",
|
|
37
|
+
"react-dom": "^17.0.2"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist"
|
|
41
|
+
],
|
|
42
|
+
"main": "./dist/index.cjs.js",
|
|
43
|
+
"module": "./dist/index.es.js",
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"exports": {
|
|
46
|
+
".": {
|
|
47
|
+
"import": "./dist/index.es.js",
|
|
48
|
+
"require": "./dist/index.cjs.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"description": "React function components for imperatively controlling embedded players (audio, Niconico, SoundCloud and YouTube) using refs.",
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/ycanardeau/nostalgic-diva.git"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"react",
|
|
59
|
+
"player",
|
|
60
|
+
"audio",
|
|
61
|
+
"niconico",
|
|
62
|
+
"soundcloud",
|
|
63
|
+
"youtube"
|
|
64
|
+
],
|
|
65
|
+
"author": "Aigamo <51428094+ycanardeau@users.noreply.github.com>",
|
|
66
|
+
"bugs": {
|
|
67
|
+
"url": "https://github.com/ycanardeau/nostalgic-diva/issues"
|
|
68
|
+
}
|
|
69
|
+
}
|