diff --git a/src/YoutubePlayer/index.ts b/src/YoutubePlayer/index.ts index 22697a0..352c190 100644 --- a/src/YoutubePlayer/index.ts +++ b/src/YoutubePlayer/index.ts @@ -4,7 +4,7 @@ import { youtubeEnabled } from "$core/store/youtube.ts"; import { loadYoutubeAdapter } from "@/YoutubePlayer/adapter.ts"; export interface YoutubePlayer { - loadVideo(videoId: string): Promise; + loadVideo(videoId: string, startSeconds?: number, endSeconds?: number): Promise; play(): Promise; stop(): Promise; waitForStop(): Promise; @@ -12,7 +12,7 @@ export interface YoutubePlayer { export async function playVideo(youtubeLink: YoutubeLink): Promise { const player = await getOrCreatePlayer(); - await player.loadVideo(youtubeLink.videoId); + await player.loadVideo(youtubeLink.videoId, youtubeLink.startSeconds, youtubeLink.endSeconds); await player.play(); await player.waitForStop(); await player.stop(); @@ -43,8 +43,8 @@ async function createPlayer(): Promise { updatePlayerSize(); const result = { - loadVideo(videoId: string) { - return player.loadVideoById(videoId); + loadVideo(videoId: string, startSeconds?: number, endSeconds?: number) { + return player.loadVideoById(videoId, startSeconds, endSeconds); }, async play() { await player.playVideo(); diff --git a/src/components/solid/organisms/Reader/Reader.tsx b/src/components/solid/organisms/Reader/Reader.tsx index e2ecc82..35d653a 100644 --- a/src/components/solid/organisms/Reader/Reader.tsx +++ b/src/components/solid/organisms/Reader/Reader.tsx @@ -14,7 +14,7 @@ import { type DelayControl, DelayIndicator } from "@/components/solid/atoms/Dela import { youtubeEnabled } from "$core/store/youtube.ts"; import { usePersistentStore } from "@/components/solid/hooks/usePersistentStore.ts"; import { YoutubePlayButton } from "@/components/solid/atoms/YoutubePlayButton.tsx"; -import { coerceToArray } from "$core/utils/coerceToArray.ts"; +import { resolveYoutubeLinks } from "@/utils/resolveYoutubeLinks.ts"; export const Reader: Component<{ dojoInfo: DojoInfo; speechPack: SpeechPack }> = (props) => { const techniqueStore = createTechniqueStore(props.dojoInfo.id); @@ -57,7 +57,7 @@ export const Reader: Component<{ dojoInfo: DojoInfo; speechPack: SpeechPack }> = ready={playerLoaded()} onClickAutoPlay={() => setAutoPlay(!autoPlay())} autoPlayEnabled={autoPlay()} - youtube={coerceToArray(lastTechnique()?.metadata?.youtube)} + youtube={resolveYoutubeLinks(lastTechnique())} /> = (props) => { + const examTable = createMemo(() => + buildTechniqueTree(props.techniques, (technique) => { + return technique; + }), + ); return (
- + {(execution, attacks) => (

{execution}

@@ -49,7 +55,7 @@ export const ExamSheet: Component = (props) => { }; interface DirectionsProps { - directions: Record; + directions: Record; } const ShowDirections: Component = (props) => { @@ -60,7 +66,7 @@ const ShowDirections: Component = (props) => { return ( - + @@ -70,7 +76,7 @@ const ShowDirections: Component = (props) => { return ( {direction} - + ); }} @@ -82,14 +88,9 @@ const ShowDirections: Component = (props) => { ); }; -const YoutubeLink: Component<{ metadata: TechniqueMetadata }> = (props) => { +const YoutubeLink: Component<{ technique: BaseTechnique }> = (props) => { const showYoutube = usePersistentStore(youtubeEnabled, false); - const youtube = - props.metadata.youtube == null - ? [] - : Array.isArray(props.metadata.youtube) - ? props.metadata.youtube - : [props.metadata.youtube]; + const youtube = resolveYoutubeLinks(props.technique); return ( diff --git a/src/data/videopacks/aikido-kompendium/index.ts b/src/data/videopacks/aikido-kompendium/index.ts index 1094d7a..efb67ea 100644 --- a/src/data/videopacks/aikido-kompendium/index.ts +++ b/src/data/videopacks/aikido-kompendium/index.ts @@ -13,7 +13,7 @@ export default { videoId: "3yd1kGHIviA", durationSeconds: 20, id: "0", - startSeconds: 0, + startSeconds: 6, endSeconds: 20, }, ], @@ -27,7 +27,7 @@ export default { videoId: "HZOkvZDAh34", durationSeconds: 27, id: "13", - startSeconds: 0, + startSeconds: 6, endSeconds: 27, }, ], @@ -37,6 +37,8 @@ export default { videoId: "QUNg_jthIqM", durationSeconds: 21, id: "14", + startSeconds: 6, + endSeconds: 21, }, ], }, @@ -47,6 +49,8 @@ export default { videoId: "dHhOLufvx3U", durationSeconds: 24, id: "15", + startSeconds: 6, + endSeconds: 24, }, ], }, @@ -59,6 +63,8 @@ export default { videoId: "ODF1mKYFT50", durationSeconds: 21, id: "16", + startSeconds: 6, + endSeconds: 21, }, ], ura: [ @@ -67,6 +73,8 @@ export default { videoId: "dm7lj0RaEzw", durationSeconds: 19, id: "17", + startSeconds: 6, + endSeconds: 19, }, ], }, @@ -77,6 +85,8 @@ export default { videoId: "ZrvHAhQXyyE", durationSeconds: 22, id: "18", + startSeconds: 6, + endSeconds: 22, }, ], }, @@ -87,6 +97,8 @@ export default { videoId: "meNnP_iyjSY", durationSeconds: 30, id: "59", + startSeconds: 6, + endSeconds: 30, }, ], ura: [ @@ -95,6 +107,8 @@ export default { videoId: "2gWlA-rMtic", durationSeconds: 31, id: "60", + startSeconds: 6, + endSeconds: 31, }, ], }, @@ -105,6 +119,8 @@ export default { videoId: "OaKRmnjJdK8", durationSeconds: 29, id: "61", + startSeconds: 6, + endSeconds: 29, }, ], ura: [ @@ -113,6 +129,8 @@ export default { videoId: "f3gHuS8Bp3A", durationSeconds: 29, id: "62", + startSeconds: 6, + endSeconds: 29, }, ], }, @@ -123,6 +141,8 @@ export default { videoId: "X-fctXW0Lmg", durationSeconds: 21, id: "63", + startSeconds: 6, + endSeconds: 21, }, ], ura: [ @@ -131,6 +151,8 @@ export default { videoId: "a-jasPR2So0", durationSeconds: 26, id: "64", + startSeconds: 6, + endSeconds: 26, }, ], }, @@ -141,6 +163,8 @@ export default { videoId: "9HNkdOJmT3k", durationSeconds: 28, id: "65", + startSeconds: 6, + endSeconds: 28, }, ], }, @@ -151,6 +175,8 @@ export default { videoId: "t9aPIPxxdzs", durationSeconds: 22, id: "227", + startSeconds: 2, + endSeconds: 22, }, ], }, @@ -163,6 +189,8 @@ export default { videoId: "i3bgZsdTmyQ", durationSeconds: 24, id: "51", + startSeconds: 6, + endSeconds: 24, }, ], ura: [ @@ -171,6 +199,8 @@ export default { videoId: "dQF5oxxDD30", durationSeconds: 24, id: "52", + startSeconds: 6, + endSeconds: 24, }, ], }, @@ -181,6 +211,8 @@ export default { videoId: "ypXXzb2YHFY", durationSeconds: 29, id: "53", + startSeconds: 6, + endSeconds: 29, }, ], ura: [ @@ -189,6 +221,8 @@ export default { videoId: "6JBCfxORKJQ", durationSeconds: 29, id: "54", + startSeconds: 6, + endSeconds: 29, }, ], }, @@ -199,6 +233,8 @@ export default { videoId: "B5fVD3L47zg", durationSeconds: 25, id: "150", + startSeconds: 6, + endSeconds: 25, }, ], ura: [ @@ -207,6 +243,8 @@ export default { videoId: "sunQhz4qybw", durationSeconds: 24, id: "151", + startSeconds: 6, + endSeconds: 24, }, ], }, @@ -217,6 +255,8 @@ export default { videoId: "Y8Qym8RlPOw", durationSeconds: 20, id: "152", + startSeconds: 2, + endSeconds: 20, }, ], ura: [ @@ -225,6 +265,8 @@ export default { videoId: "cf9NaXqF_Ck", durationSeconds: 24, id: "153", + startSeconds: 6, + endSeconds: 24, }, ], }, diff --git a/src/utils/resolveYoutubeLinks.ts b/src/utils/resolveYoutubeLinks.ts new file mode 100644 index 0000000..540dc3f --- /dev/null +++ b/src/utils/resolveYoutubeLinks.ts @@ -0,0 +1,11 @@ +import type { BaseTechnique, YoutubeLink } from "$core/model"; +import aikidoKompendium from "@/data/videopacks/aikido-kompendium"; + +export function resolveYoutubeLinks(technique: BaseTechnique | null): YoutubeLink[] { + if (technique == null) return []; + + return ( + // @ts-expect-error Partial objects resolve to any, which is not relevant in our case. + aikidoKompendium.videos[technique.execution]?.[technique.attack]?.[technique.defence]?.[technique.direction] ?? [] + ); +}