mirror of
https://git.vectorsigma.ru/public/tubearchivist.git
synced 2026-08-04 22:39:38 +00:00
Refac prepare updating watched state based on progress endpoint
This commit is contained in:
@@ -1,11 +1,23 @@
|
|||||||
import APIClient from '../../functions/APIClient';
|
import APIClient from '../../functions/APIClient';
|
||||||
|
|
||||||
|
type VideoProgressResponseType = {
|
||||||
|
watched: boolean;
|
||||||
|
duration: number;
|
||||||
|
duration_str: string;
|
||||||
|
watched_date: number;
|
||||||
|
position: number;
|
||||||
|
youtube_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
type VideoProgressProp = {
|
type VideoProgressProp = {
|
||||||
youtubeId: string;
|
youtubeId: string;
|
||||||
currentProgress: number;
|
currentProgress: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateVideoProgressById = async ({ youtubeId, currentProgress }: VideoProgressProp) => {
|
const updateVideoProgressById = async ({
|
||||||
|
youtubeId,
|
||||||
|
currentProgress,
|
||||||
|
}: VideoProgressProp): Promise<VideoProgressResponseType> => {
|
||||||
return APIClient(`/api/video/${youtubeId}/progress/`, {
|
return APIClient(`/api/video/${youtubeId}/progress/`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: { position: currentProgress },
|
body: { position: currentProgress },
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
|
|||||||
setSearchParams({});
|
setSearchParams({});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<WatchedCheckBox
|
<WatchedCheckBox
|
||||||
watched={watched}
|
watched={watched}
|
||||||
onClick={async status => {
|
onClick={async status => {
|
||||||
@@ -127,12 +128,16 @@ const EmbeddableVideoPlayer = ({ videoId }: EmbeddableVideoPlayerProps) => {
|
|||||||
setRefresh(true);
|
setRefresh(true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{cast && (
|
{cast && (
|
||||||
<GoogleCast
|
<GoogleCast
|
||||||
video={video}
|
video={video}
|
||||||
setRefresh={() => {
|
setRefresh={() => {
|
||||||
setRefresh(true);
|
setRefresh(true);
|
||||||
}}
|
}}
|
||||||
|
onWatchStateChanged={() => {
|
||||||
|
setRefresh(true);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { VideoType } from '../pages/Home';
|
import { VideoType } from '../pages/Home';
|
||||||
import updateWatchedState from '../api/actions/updateWatchedState';
|
|
||||||
import updateVideoProgressById from '../api/actions/updateVideoProgressById';
|
import updateVideoProgressById from '../api/actions/updateVideoProgressById';
|
||||||
import watchedThreshold from '../functions/watchedThreshold';
|
|
||||||
|
|
||||||
const getURL = () => {
|
const getURL = () => {
|
||||||
return window.location.origin;
|
return window.location.origin;
|
||||||
@@ -29,6 +27,7 @@ async function castVideoProgress(
|
|||||||
duration: number;
|
duration: number;
|
||||||
},
|
},
|
||||||
video: VideoType | undefined,
|
video: VideoType | undefined,
|
||||||
|
onWatchStateChanged?: (status: boolean) => void,
|
||||||
) {
|
) {
|
||||||
if (!video) {
|
if (!video) {
|
||||||
console.log('castVideoProgress: Video to cast not found...');
|
console.log('castVideoProgress: Video to cast not found...');
|
||||||
@@ -42,19 +41,13 @@ async function castVideoProgress(
|
|||||||
|
|
||||||
if (currentTime % 10 <= 1.0 && currentTime !== 0 && duration !== 0) {
|
if (currentTime % 10 <= 1.0 && currentTime !== 0 && duration !== 0) {
|
||||||
// Check progress every 10 seconds or else progress is checked a few times a second
|
// Check progress every 10 seconds or else progress is checked a few times a second
|
||||||
await updateVideoProgressById({
|
const videoProgressResponse = await updateVideoProgressById({
|
||||||
youtubeId: videoId,
|
youtubeId: videoId,
|
||||||
currentProgress: currentTime,
|
currentProgress: currentTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!video.player.watched) {
|
if (videoProgressResponse.watched && video.player.watched !== videoProgressResponse.watched) {
|
||||||
// Check if video is already marked as watched
|
onWatchStateChanged?.(true);
|
||||||
if (watchedThreshold(currentTime, duration)) {
|
|
||||||
await updateWatchedState({
|
|
||||||
id: videoId,
|
|
||||||
is_watched: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,9 +86,10 @@ async function castVideoPaused(
|
|||||||
type GoogleCastProps = {
|
type GoogleCastProps = {
|
||||||
video?: VideoType;
|
video?: VideoType;
|
||||||
setRefresh?: () => void;
|
setRefresh?: () => void;
|
||||||
|
onWatchStateChanged?: (status: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const GoogleCast = ({ video, setRefresh }: GoogleCastProps) => {
|
const GoogleCast = ({ video, setRefresh, onWatchStateChanged }: GoogleCastProps) => {
|
||||||
const [isConnected, setIsConnected] = useState(false);
|
const [isConnected, setIsConnected] = useState(false);
|
||||||
|
|
||||||
const setup = useCallback(() => {
|
const setup = useCallback(() => {
|
||||||
@@ -118,12 +112,14 @@ const GoogleCast = ({ video, setRefresh }: GoogleCastProps) => {
|
|||||||
setIsConnected(player.isConnected);
|
setIsConnected(player.isConnected);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
playerController.addEventListener(
|
playerController.addEventListener(
|
||||||
cast.framework.RemotePlayerEventType.CURRENT_TIME_CHANGED,
|
cast.framework.RemotePlayerEventType.CURRENT_TIME_CHANGED,
|
||||||
function () {
|
function () {
|
||||||
castVideoProgress(player, video);
|
castVideoProgress(player, video, onWatchStateChanged);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
playerController.addEventListener(
|
playerController.addEventListener(
|
||||||
cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
|
cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
|
||||||
function () {
|
function () {
|
||||||
@@ -131,6 +127,8 @@ const GoogleCast = ({ video, setRefresh }: GoogleCastProps) => {
|
|||||||
setRefresh?.();
|
setRefresh?.();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [setRefresh, video]);
|
}, [setRefresh, video]);
|
||||||
|
|
||||||
const startPlayback = useCallback(() => {
|
const startPlayback = useCallback(() => {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import updateVideoProgressById from '../api/actions/updateVideoProgressById';
|
import updateVideoProgressById from '../api/actions/updateVideoProgressById';
|
||||||
import updateWatchedState from '../api/actions/updateWatchedState';
|
import updateWatchedState from '../api/actions/updateWatchedState';
|
||||||
import { SponsorBlockSegmentType, SponsorBlockType, VideoResponseType } from '../pages/Video';
|
import { SponsorBlockSegmentType, SponsorBlockType, VideoResponseType } from '../pages/Video';
|
||||||
import watchedThreshold from '../functions/watchedThreshold';
|
|
||||||
import { Dispatch, Fragment, SetStateAction, SyntheticEvent, useState } from 'react';
|
import { Dispatch, Fragment, SetStateAction, SyntheticEvent, useState } from 'react';
|
||||||
import formatTime from '../functions/formatTime';
|
import formatTime from '../functions/formatTime';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
@@ -82,21 +81,13 @@ const handleTimeUpdate =
|
|||||||
if (currentTime < 10) return;
|
if (currentTime < 10) return;
|
||||||
if (Number((currentTime % 10).toFixed(1)) <= 0.2) {
|
if (Number((currentTime % 10).toFixed(1)) <= 0.2) {
|
||||||
// Check progress every 10 seconds or else progress is checked a few times a second
|
// Check progress every 10 seconds or else progress is checked a few times a second
|
||||||
await updateVideoProgressById({
|
const videoProgressResponse = await updateVideoProgressById({
|
||||||
youtubeId,
|
youtubeId,
|
||||||
currentProgress: currentTime,
|
currentProgress: currentTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!watched) {
|
if (videoProgressResponse.watched && watched !== videoProgressResponse.watched) {
|
||||||
// Check if video is already marked as watched
|
onWatchStateChanged?.(true);
|
||||||
if (watchedThreshold(currentTime, duration)) {
|
|
||||||
await updateWatchedState({
|
|
||||||
id: youtubeId,
|
|
||||||
is_watched: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
onWatchStateChanged?.(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
function watchedThreshold(currentTime: number, duration: number) {
|
|
||||||
let watched = false;
|
|
||||||
|
|
||||||
if (duration <= 1800) {
|
|
||||||
// If video is less than 30 min
|
|
||||||
if (currentTime / duration >= 0.9) {
|
|
||||||
// Mark as watched at 90%
|
|
||||||
watched = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If video is more than 30 min
|
|
||||||
if (currentTime >= duration - 120) {
|
|
||||||
// Mark as watched if there is two minutes left
|
|
||||||
watched = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return watched;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default watchedThreshold;
|
|
||||||
@@ -229,6 +229,9 @@ const Video = () => {
|
|||||||
setRefresh={() => {
|
setRefresh={() => {
|
||||||
setRefreshVideoList(true);
|
setRefreshVideoList(true);
|
||||||
}}
|
}}
|
||||||
|
onWatchStateChanged={() => {
|
||||||
|
setRefreshVideoList(true);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<h1 id="video-title">{video.title}</h1>
|
<h1 id="video-title">{video.title}</h1>
|
||||||
|
|||||||
Reference in New Issue
Block a user