Skip to content

Commit

Permalink
Refactor client: store $curVideo instead of individual variables
Browse files Browse the repository at this point in the history
  • Loading branch information
elonen committed Jun 6, 2024
1 parent fe4fb39 commit 892d1ed
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 61 deletions.
65 changes: 29 additions & 36 deletions client/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {fade, slide} from "svelte/transition";
import * as Proto3 from '@clapshot_protobuf/typescript';
import {allComments, allSubtitles, curUsername, curUserId, videoIsReady, videoPlaybackUrl, videoOrigUrl, mediaFileId, videoFps, videoTitle, curPageId, curPageItems, userMessages, latestProgressReports, collabId, userMenuItems, serverDefinedActions, curUserIsAdmin, connectionErrors, curSubtitle, defaultSubtitleId, videoOwnerId} from './stores';
import {allComments, curUsername, curUserId, videoIsReady, mediaFileId, curVideo, curPageId, curPageItems, userMessages, latestProgressReports, collabId, userMenuItems, serverDefinedActions, curUserIsAdmin, connectionErrors, curSubtitle} from './stores';
import {IndentedComment, type UserMenuItem, type StringMap, type MediaProgressReport} from "./types";
import CommentCard from './lib/player_view/CommentCard.svelte'
Expand Down Expand Up @@ -128,12 +128,13 @@ function onCommentInputButton(e: any) {
}
function onDisplayComment(e: any) {
if (!$curVideo) { throw Error("No video loaded"); }
videoPlayer.seekToSMPTE(e.detail.timecode);
// Close draw mode while showing (drawing from a saved) comment
videoPlayer.onToggleDraw(false);
commentInput.forceDrawMode(false);
if (e.detail.drawing) { videoPlayer.setDrawing(e.detail.drawing); }
if (e.detail.subtitleId) { $curSubtitle = $allSubtitles.find((s) => s.id == e.detail.subtitleId) ?? null; }
if (e.detail.subtitleId) { $curSubtitle = $curVideo.subtitles.find((s) => s.id == e.detail.subtitleId) ?? null; }
if ($collabId) {
logAbbrev("Collab: onDisplayComment. collab_id: '" + $collabId + "'");
wsEmit({collabReport: {
Expand Down Expand Up @@ -172,12 +173,8 @@ function closePlayerIfOpen() {
wsEmit({leaveCollab: {}});
$collabId = null;
$mediaFileId = null;
$videoPlaybackUrl = null;
$videoFps = null;
$videoTitle = null;
$videoOwnerId = null;
$curVideo = null;
$allComments = [];
$allSubtitles = [];
$videoIsReady = false;
}
Expand Down Expand Up @@ -207,11 +204,12 @@ function onCommentPinClicked(e: any) {
function onSubtitleChange(e: any) {
const sub_id = e.detail.id;
console.debug("onSubtitleChange, id:", sub_id, "allSubtitles:", $allSubtitles);
if (!$curVideo) { throw Error("No video loaded"); }
console.debug("onSubtitleChange, id:", sub_id, "allSubtitles:", $curVideo.subtitles);
if ($curSubtitle?.id == sub_id) {
$curSubtitle = null;
} else {
$curSubtitle = $allSubtitles.find((s) => s.id == sub_id) ?? null;
$curSubtitle = $curVideo.subtitles.find((s) => s.id == sub_id) ?? null;
if ($curSubtitle == null && sub_id != null) {
console.error("Subtitle not found: ", sub_id);
acts.add({mode: 'error', message: "Subtitle not found. See log.", lifetime: 5});
Expand Down Expand Up @@ -708,22 +706,15 @@ function connectWebsocketAfterAuthCheck(ws_url: string)
document.title = "Clapshot - " + (v.title ?? v.id);
}
$videoPlaybackUrl = v.playbackUrl;
$videoOrigUrl = v.origUrl ?? null;
$mediaFileId = v.id;
$videoFps = parseFloat(v.duration.fps);
if (isNaN($videoFps)) throw Error("Invalid FPS");
$videoTitle = v.title;
$videoOwnerId = v.userId;
$allSubtitles = [...v.subtitles];
$curVideo = v;
$allComments = [];
$defaultSubtitleId = v.defaultSubtitleId ?? null;
if ($defaultSubtitleId) {
$curSubtitle = $allSubtitles.find((s) => s.id == $defaultSubtitleId) ?? null;
if (v.defaultSubtitleId) {
$curSubtitle = $curVideo.subtitles.find((s) => s.id == v.defaultSubtitleId) ?? null;
} else {
let old_id = $curSubtitle?.id;
$curSubtitle = $allSubtitles.find((s) => s.id == old_id) ?? null;
$curSubtitle = $curVideo.subtitles.find((s) => s.id == old_id) ?? null;
}
if ($collabId)
Expand Down Expand Up @@ -927,15 +918,15 @@ function onMediaFileListPopupAction(e: { detail: { action: Proto3.ActionDef, ite
</div>
</div>

{:else if $mediaFileId}
{:else if $mediaFileId && $curVideo && $curVideo.playbackUrl}

<!-- ========== video review widgets ============= -->
<div transition:slide class="flex h-full w-full {debugLayout?'border-2 border-blue-700':''}">

<div transition:slide class="flex-1 flex flex-col {debugLayout?'border-2 border-purple-600':''}">
<div class="flex-1 bg-cyan-900">
<VideoPlayer
bind:this={videoPlayer} src={$videoPlaybackUrl}
bind:this={videoPlayer} src={$curVideo.playbackUrl}
on:seeked={onPlayerSeeked}
on:collabReport={onCollabReport}
on:commentPinClicked={onCommentPinClicked}
Expand Down Expand Up @@ -963,20 +954,22 @@ function onMediaFileListPopupAction(e: { detail: { action: Proto3.ActionDef, ite
{/each}
</div>
<div class="flex-none">
<!-- Subtitles -->
<div class="flex justify-between text-gray-500 items-center py-2 border-t border-gray-500">
<h6>Subtitles</h6>
<button class="fa fa-plus-circle" title="Upload subtitles" on:click={onUploadSubtitles}></button>
</div>
{#each $allSubtitles as sub}
<SubtitleCard
sub={sub}
isDefault={$defaultSubtitleId == sub.id}
on:change-subtitle={onSubtitleChange}
on:delete-subtitle={onSubtitleDelete}
on:update-subtitle={onSubtitleUpdate}
/>
{/each}
{#if $curVideo.subtitles}
<!-- Subtitles -->
<div class="flex justify-between text-gray-500 items-center py-2 border-t border-gray-500">
<h6>Subtitles</h6>
<button class="fa fa-plus-circle" title="Upload subtitles" on:click={onUploadSubtitles}></button>
</div>
{#each $curVideo.subtitles as sub}
<SubtitleCard
sub={sub}
isDefault={$curVideo.defaultSubtitleId == sub.id}
on:change-subtitle={onSubtitleChange}
on:delete-subtitle={onSubtitleDelete}
on:update-subtitle={onSubtitleUpdate}
/>
{/each}
{/if}
</div>
</div>
{/if}
Expand Down
8 changes: 4 additions & 4 deletions client/src/lib/NavBar.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { onMount, createEventDispatcher } from 'svelte';
import { curUsername, curUserPic, videoTitle, mediaFileId, videoOrigUrl, collabId, userMenuItems } from "@/stores";
import { curUsername, curUserPic, curVideo, mediaFileId, collabId, userMenuItems } from "@/stores";
import Avatar from '@/lib/Avatar.svelte';
import logo from "@/assets/clapshot-logo.svg";
import {latestProgressReports} from '@/stores';
Expand Down Expand Up @@ -74,16 +74,16 @@ const randomSessionId = Math.random().toString(36).substring(2, 15);
<h2 class=" text-lg text-center">
{$mediaFileId}
<a href="?vid={$mediaFileId}" class="text-gray-700 hover:text-gray-500"><i class="fas fa-share-square text-sm"></i></a>
{#if $videoOrigUrl}
<a href="{$videoOrigUrl}" download title="Download original file" class="text-gray-700 hover:text-gray-500"><i class="fas fa-download text-sm"></i></a>
{#if $curVideo?.origUrl}
<a href="{$curVideo?.origUrl}" download title="Download original file" class="text-gray-700 hover:text-gray-500"><i class="fas fa-download text-sm"></i></a>
{/if}
{#if $collabId}
<a href="?vid={$mediaFileId}" class="text-green-500 hover:text-orange-600" title="Collaborative session active. Click to exit."><i class="fas fa-users text-sm"></i></a>
{:else}
<a href="?vid={$mediaFileId}&collab={randomSessionId}" title="Start collaborative session" class="text-gray-700 hover:text-gray-500"><i class="fas fa-user-plus text-sm"></i></a>
{/if}
</h2>
<span class="mx-4 text-xs text-center">{$videoTitle}</span>
<span class="mx-4 text-xs text-center">{$curVideo?.title}</span>
{#if videoProgressMsg}
<span class="text-cyan-800 mx-4 text-xs text-center">{videoProgressMsg}</span>
{/if}
Expand Down
4 changes: 2 additions & 2 deletions client/src/lib/player_view/CommentCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { createEventDispatcher } from 'svelte';
import { scale, slide } from "svelte/transition";
import Avatar from '@/lib/Avatar.svelte';
import { curUserId, curUserIsAdmin, allComments, curSubtitle, allSubtitles } from '@/stores';
import { curUserId, curUserIsAdmin, allComments, curSubtitle, curVideo } from '@/stores';
import * as Proto3 from '@clapshot_protobuf/typescript';
const dispatch = createEventDispatcher();
Expand Down Expand Up @@ -64,7 +64,7 @@ function hasChildren(): boolean {
}
function getSubtitleLanguage(subtitleId: string): string {
let sub = $allSubtitles.find(s => s.id == subtitleId);
let sub = $curVideo?.subtitles.find(s => s.id == subtitleId);
return sub ? sub.languageCode.toUpperCase() : "";
}
Expand Down
4 changes: 2 additions & 2 deletions client/src/lib/player_view/SubtitleCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { createEventDispatcher } from 'svelte';
import { scale, slide } from "svelte/transition";
import { curSubtitle, curUserId, curUserIsAdmin, videoOwnerId } from '@/stores';
import { curSubtitle, curUserId, curUserIsAdmin, curVideo } from '@/stores';
import * as Proto3 from '@clapshot_protobuf/typescript';
const dispatch = createEventDispatcher();
Expand Down Expand Up @@ -35,7 +35,7 @@ function doDelete() {
<i class="fa {sub.id == $curSubtitle?.id ? 'fa-eye' : 'fa-eye-slash' }"></i>
<span class="text-ellipsis"><strong>{sub.languageCode.toUpperCase()}</strong> – {sub.title}</span>
</button>
{#if $videoOwnerId == $curUserId || $curUserIsAdmin}
{#if $curVideo?.userId == $curUserId || $curUserIsAdmin}
<span class="flex-shrink-0">
<button class="fa fa-pencil hover:text-white" title="Edit subtitle" on:click={() => { showEditor = !showEditor; }}></button>
</span>
Expand Down
13 changes: 8 additions & 5 deletions client/src/lib/player_view/VideoPlayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {scale} from "svelte/transition";
import '@fortawesome/fontawesome-free/css/all.min.css';
import * as Proto3 from '@clapshot_protobuf/typescript';
import {VideoFrame} from './VideoFrame';
import {allComments, curSubtitle, videoIsReady, videoFps, collabId, allSubtitles} from '@/stores';
import {allComments, curSubtitle, videoIsReady, collabId, curVideo} from '@/stores';
import CommentTimelinePin from './CommentTimelinePin.svelte';
Expand Down Expand Up @@ -70,9 +70,12 @@ function prepare_drawing(): void
{
$videoIsReady = true;
let frameRate = parseFloat($curVideo?.duration?.fps ?? "");
if (isNaN(frameRate)) { throw new Error("VideoPlayer: Invalid frame rate"); }
vframeCalc = new VideoFrame({
video: videoElem,
frameRate: $videoFps,
frameRate,
callback: function(response: any) { console.log(response); } });
refreshCommentPins(); // Creates CommentTimelinePin components, now that we can calculate timecodes properly
Expand Down Expand Up @@ -390,7 +393,7 @@ function changeSubtitleUploadIcon(upload_icon: boolean) {
let prev_subtitle: Proto3.Subtitle|null = null;
function toggleSubtitle() {
// Dispatch to parent instead of setting directly, to allow collab sessions to sync
if ($allSubtitles.find(s => s.id == prev_subtitle?.id) == undefined) {
if ($curVideo?.subtitles.find(s => s.id == prev_subtitle?.id) == undefined) {
prev_subtitle = null;
}
if ($curSubtitle) {
Expand All @@ -400,7 +403,7 @@ function toggleSubtitle() {
if (prev_subtitle) {
dispatch('change-subtitle', {id: prev_subtitle.id});
} else {
dispatch('change-subtitle', {id: $allSubtitles[0]?.id});
dispatch('change-subtitle', {id: $curVideo?.subtitles[0]?.id});
}
}
}
Expand Down Expand Up @@ -528,7 +531,7 @@ function offsetTextTracks() {

<!-- Closed captioning -->
<span class="flex-0 text-center whitespace-nowrap">
{#if $allSubtitles.length > 0}
{#if ($curVideo?.subtitles?.length ?? 0) > 0}
<button
class={ $curSubtitle ? 'fa-solid fa-closed-captioning text-amber-600' : 'fa-solid fa-closed-captioning text-gray-400' }
title="Toggle closed captioning"
Expand Down
17 changes: 5 additions & 12 deletions client/src/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ import type { IndentedComment, UserMenuItem, MediaProgressReport } from '@/types
import type { VideoListDefItem } from '@/lib/asset_browser/types';
import * as Proto3 from '@clapshot_protobuf/typescript';

export let videoPlaybackUrl: Writable<string|null> = writable(null);
export let videoOrigUrl: Writable<string|null> = writable(null);
export let mediaFileId: Writable<string|null> = writable(null);
export let videoFps: Writable<number|null> = writable(null);
export let videoTitle: Writable<string|null> = writable("(no video loaded)")
export let videoOwnerId: Writable<string|null> = writable(null);
export let curVideo: Writable<Proto3.MediaFile|null> = writable(null);

export let latestProgressReports: Writable<MediaProgressReport[]> = writable([]);
export let videoIsReady: Writable<boolean> = writable(false);

export let curPageItems: Writable<Proto3.PageItem[]> = writable([]);
export let curPageId: Writable<string|null> = writable(null);
Expand All @@ -20,14 +16,11 @@ export let curUserId: Writable<string|null> = writable(null);
export let curUserIsAdmin: Writable<boolean> = writable(false);
export let curUserPic: Writable<string|null> = writable(null);

export let videoIsReady: Writable<boolean> = writable(false);

export let allComments: Writable<IndentedComment[]> = writable([]);
export let userMessages: Writable<Proto3.UserMessage[]> = writable([]);

export let allSubtitles: Writable<Proto3.Subtitle[]> = writable([]);
export let curSubtitle: Writable<Proto3.Subtitle|null> = writable(null);
export let defaultSubtitleId: Writable<string|null> = writable(null);

export let userMessages: Writable<Proto3.UserMessage[]> = writable([]);
export let latestProgressReports: Writable<MediaProgressReport[]> = writable([]);

export let connectionErrors: Writable<string[]> = writable([]);

Expand Down

0 comments on commit 892d1ed

Please sign in to comment.