fix: (beta) file-show: faulty repeat

Massimo Melina committed Feb 16, 2024 at 10:11 UTC 083c5f8da1b24797bbeb3988fed54cd592add00b
2 files changed +25 -14
frontend/src/show.ts
+22 -13
@@ -1,6 +1,8 @@
1 import { DirEntry, DirList, ext2type, state, useSnapState } from './state'
2 import { createElement as h, Fragment, useEffect, useRef, useState } from 'react'
3 -import { basename, dirname, domOn, hfsEvent, hIcon, isMac, newDialog, pathEncode, restartAnimation } from './misc'
3 +import {
4 + basename, dirname, domOn, hfsEvent, hIcon, isMac, newDialog, pathEncode, restartAnimation, useStateMounted,
5 +} from './misc'
6 import { useEventListener, useWindowSize } from 'usehooks-ts'
7 import { EntryDetails, useMidnight } from './BrowseFiles'
8 import { Btn, FlexV, iconBtn, Spinner } from './components'
@@ -26,7 +28,7 @@ export function fileShow(entry: DirEntry, { startPlaying=false } = {}) {
28 const lastGood = useRef(entry)
29 const [mode, setMode] = useState(ZoomMode.contain)
30 const [shuffle, setShuffle] = useState<undefined|DirList>()
29 - const [repeat, setRepeat] = useState(false)
31 + const [repeat, setRepeat, { get: getRepeat }] = useStateMounted(false)
32 const [cover, setCover] = useState('')
33 useEffect(() => {
34 if (shuffle)
@@ -78,7 +80,7 @@ export function fileShow(entry: DirEntry, { startPlaying=false } = {}) {
80 return domOn('ended', goNext, { target: showElement as any })
81 }
82 // we are supposedly showing an image
81 - const h = setTimeout(() => go(+1), state.auto_play_seconds * 1000)
83 + const h = setTimeout(goNext, state.auto_play_seconds * 1000)
84 return () => clearTimeout(h)
85 }, [showElement, autoPlaying, cur])
86 const {mediaSession} = navigator
@@ -180,24 +182,31 @@ export function fileShow(entry: DirEntry, { startPlaying=false } = {}) {
182 setFailed(cur.n)
183 }
184
183 - function go(dir?: number) {
185 + function go(dir?: number, from=cur) {
186 if (dir)
187 moving.current = dir
186 - let e = cur
188 + let e = from
189 while (1) {
190 e = e.getSibling(moving.current, shuffle)
189 - if (!e) { // reached last
190 - if (dir! > 0) {
191 - if (repeat)
192 - return goTo(shuffle?.[0] || state.list[0])
193 - setAutoPlaying(false)
191 + if (anyGood()) break
192 + if (e) continue // try next
193 + // reached last/first
194 + if (dir! > 0) {
195 + if (getRepeat()) {
196 + e = shuffle?.[0] || state.list[0]
197 + if (anyGood()) break
198 + continue
199 }
195 - goTo(lastGood.current) // revert to last known supported file
196 - return restartAnimation(document.body, '.2s blink')
200 + setAutoPlaying(false)
201 }
198 - if (!e.isFolder && getShowType(e)) break // give it a chance
202 + goTo(lastGood.current) // revert to last known supported file
203 + return restartAnimation(document.body, '.2s blink')
204 }
205 goTo(e)
206 +
207 + function anyGood() {
208 + return e && !e.isFolder && getShowType(e)
209 + }
210 }
211
212 function goTo(to: typeof cur) {
shared/react.ts
+3 -1
@@ -8,11 +8,13 @@ import { Falsy } from '.'
8 export function useStateMounted<T>(init: T) {
9 const isMounted = useIsMounted()
10 const [v, set] = useState(init)
11 + const ref = useRef(init)
12 + ref.current = v
13 const setIfMounted = useCallback((newValue:T | ((previous:T)=>T)) => {
14 if (isMounted())
15 set(newValue)
16 }, [isMounted, set])
15 - return [v, setIfMounted, isMounted] as const
17 + return [v, setIfMounted, { isMounted, get: () => ref.current }] as const
18 }
19
20 export function reactFilter(elements: any[]) {