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[]) {