diff --git a/src/components/BrtPlayer.vue b/src/components/BrtPlayer.vue index d8ea4458..5ee7da90 100644 --- a/src/components/BrtPlayer.vue +++ b/src/components/BrtPlayer.vue @@ -678,6 +678,7 @@ import { import { useMemoControl } from "src/composibles/memo-control" import { C_URL, + CONFIRMATION_TIME_IS_ACTUALLY_WATCHING, DELAY_SAVE_VIEWING_PROGRESS, playbackRates, } from "src/constants" @@ -737,6 +738,11 @@ const props = defineProps<{ fetchSeason: (season: string) => Promise progressWatchStore: ProgressWatchStore }>() +const uidChap = computed(() => { + const uid = `${props.currentSeason}/${props.currentChap ?? ""}` // 255 byte + + return uid +}) // ===== setup effect ===== @@ -842,7 +848,7 @@ watch( if ((err as Error)?.message !== "NOT_RESET") console.error(err) } - progressRestored = `${currentSeason}/${currentChap}` + progressRestored = uidChap.value } }, { immediate: true } @@ -937,36 +943,32 @@ function onVideoCanPlay() { activeTime = Date.now() } -// eslint-disable-next-line functional/no-let -let seasonReady = false -watch( - [ - () => authStore.user, - () => props.currentSeason, - () => props.nameCurrentSeason, - () => props.poster, - ], +const seasonMetaCreated = new Set() + +async function createSeason(): Promise { // eslint-disable-next-line camelcase - async ([user_data, currentSeason, seasonName, poster]) => { - seasonReady = false - if ( - // eslint-disable-next-line camelcase - !user_data || - !currentSeason || - typeof seasonName !== "string" || - !poster - ) - return - console.log("set new season poster %s", poster) - await historyStore.createSeason(currentSeason, { - poster, - seasonName, - name: props.name, - }) - seasonReady = true - }, - { immediate: true } -) + const { user_data } = authStore + const { currentSeason, nameCurrentChap: seasonName, poster } = props + + if (seasonMetaCreated.has(currentSeason)) return true + + if ( + // eslint-disable-next-line camelcase + !user_data || + !currentSeason || + typeof seasonName !== "string" || + !poster + ) + return false + console.log("set new season poster %s", poster) + await historyStore.createSeason(currentSeason, { + poster, + seasonName, + name: props.name, + }) + seasonMetaCreated.add(currentSeason) + return true +} const emit = defineEmits<{ ( @@ -978,6 +980,38 @@ const emit = defineEmits<{ } ): void }>() + +const storeFirstSaving = new Set() +{ + // eslint-disable-next-line functional/no-let, no-undef + let timeout: NodeJS.Timeout | number | null = null + // eslint-disable-next-line functional/no-let + let uidChapTimeout: string | null = null + onBeforeUnmount(() => { + if (timeout) clearTimeout(timeout) + }) + const watcher = watch(artPlaying, (artPlaying) => { + if (artPlaying) { + if (timeout) { + if (uidChapTimeout === uidChap.value) return + console.log("stop timeout add first saving because change chap") + clearTimeout(timeout) + } + timeout = setTimeout(() => { + console.log("allow first saving") + storeFirstSaving.add(uidChap.value) + }, CONFIRMATION_TIME_IS_ACTUALLY_WATCHING) + uidChapTimeout = uidChap.value + } else { + if (timeout) { + console.log("stop timeout add first saving") + clearTimeout(timeout) + uidChapTimeout = null + watcher() + } + } + }) +} // eslint-disable-next-line functional/no-let let processingSaveCurTimeIn: string | null = null const saveCurTimeToPer = throttle( @@ -988,7 +1022,8 @@ const saveCurTimeToPer = throttle( dur: number, nameCurrentChap: string ) => { - const uid = `${currentSeason}/${currentChap}` // 255 byte + const uid = uidChap.value // 255 byte + if (!(await createSeason())) return if (processingSaveCurTimeIn === uid) return // in progressing save this processingSaveCurTimeIn = uid @@ -999,19 +1034,28 @@ const saveCurTimeToPer = throttle( dur, name: nameCurrentChap, }) - .finally(() => (processingSaveCurTimeIn = null)) - .catch(() => console.warn("save viewing progress failed")) - - emit("cur-update", { - cur, - dur, - id: currentChap, - }) - console.log("save viewing progress") + .catch((err) => console.warn("save viewing progress failed: ", err)) + .finally(() => { + emit("cur-update", { + cur, + dur, + id: currentChap, + }) + console.log("save viewing progress") + + processingSaveCurTimeIn = null + }) }, DELAY_SAVE_VIEWING_PROGRESS ) - +const throttleEmitCurUpdate = throttle(() => { + if (props.currentChap) + emit("cur-update", { + cur: artCurrentTime.value, + dur: artDuration.value, + id: props.currentChap, + }) +}, DELAY_SAVE_VIEWING_PROGRESS) function onVideoTimeUpdate() { if ( artPlaying.value && @@ -1023,10 +1067,13 @@ function onVideoTimeUpdate() { } if (!progressRestored) return - if (!seasonReady) return if (!props.currentChap) return if (typeof props.nameCurrentChap !== "string") return + if (!storeFirstSaving.has(uidChap.value)) { + throttleEmitCurUpdate() + return console.log("bypass because not first saving") + } saveCurTimeToPer( props.currentSeason, props.currentChap, @@ -1292,7 +1339,7 @@ function remount(resetCurrentTime?: boolean) { if ( resetCurrentTime ? props.currentChap && - progressRestored === `${props.currentSeason}/${props.currentChap}` + progressRestored === uidChap.value : true ) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/src/constants.ts b/src/constants.ts index 1d4415ac..a73fb4ff 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -30,6 +30,7 @@ export const playbackRates = [ ] export const DELAY_SAVE_VIEWING_PROGRESS = 20_000 // x4 6s +export const CONFIRMATION_TIME_IS_ACTUALLY_WATCHING = DELAY_SAVE_VIEWING_PROGRESS / 4 export const REGEXP_OLD_HOST_CURL = /animevietsub\.(?:tv|cc|me)/i