file-show: full screen (in menu)
Massimo Melina committed
Jul 29, 2023 at 15:39 UTC
7c0bb2d9207e9b8246ae0ade7e58516d533ba10b
5 files changed
+35
-22
frontend/src/components.ts
+15
-18
@@ -2,25 +2,25 @@
2
3
import { getHFS, hfsEvent, hIcon } from './misc'
4
import {
5
- ButtonHTMLAttributes,
6
- ChangeEvent,
7
- createElement as h,
8
- FC,
9
- Fragment,
10
- HTMLAttributes,
11
- InputHTMLAttributes,
12
- isValidElement, MouseEventHandler,
13
- ReactNode,
14
- SelectHTMLAttributes,
15
- useMemo
5
+ ButtonHTMLAttributes, ChangeEvent, createElement as h, CSSProperties, FC, forwardRef, Fragment,
6
+ HTMLAttributes, InputHTMLAttributes, isValidElement, MouseEventHandler, ReactNode, SelectHTMLAttributes, useMemo
7
} from 'react'
8
9
export function Spinner(props: any) {
10
return hIcon('spinner', { className:'spinner', ...props })
11
}
12
22
-export function Flex({ gap='.8em', center=false, vert=false, children=null, className='', props={}, ...rest }) {
23
- return h('div', {
13
+interface FlexProps extends CSSProperties {
14
+ gap?: CSSProperties['gap'],
15
+ center?: boolean,
16
+ vert?: boolean,
17
+ children?: ReactNode,
18
+ className?: string,
19
+ props?: HTMLAttributes<HTMLDivElement>
20
+}
21
+export const Flex = forwardRef(({ gap='.8em', center=false, vert=false, children=null, className='', props={}, ...rest }: FlexProps, ref) =>
22
+ h('div', {
23
+ ref,
24
className,
25
style: {
26
display: 'flex',
@@ -30,12 +30,9 @@ export function Flex({ gap='.8em', center=false, vert=false, children=null, clas
30
...rest,
31
},
32
...props
33
- }, children)
34
-}
33
+ }, children) )
34
36
-export function FlexV(props:any) {
37
- return h(Flex, { vert:true, ...props })
38
-}
35
+export const FlexV = forwardRef((props: FlexProps, ref) => h(Flex, { ref, vert: true, ...props }))
36
37
interface CheckboxProps extends Omit<Partial<InputHTMLAttributes<any>>, 'onChange'> {
38
children?: ReactNode,
frontend/src/index.scss
+1
-1
@@ -557,7 +557,7 @@ button label {
557
height: 100%;
558
width: 100%;
559
}
560
- .showing-container { max-height: 100%; }
560
+ .showing-container { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center;}
561
.showing {
562
max-width: calc(100% - var(--nav-size)*2); // avoid overlapping of controls and nav buttons
563
max-height: 100%;
frontend/src/show.ts
+15
-1
@@ -7,6 +7,7 @@ import { Flex, FlexV, iconBtn, Spinner } from './components'
7
import { openFileMenu } from './fileMenu'
8
import { useI18N } from './i18n'
9
import md from '@hfs/admin/src/md'
10
+import { alertDialog } from './dialog'
11
12
enum ZoomMode {
13
fullWidth,
@@ -36,6 +37,8 @@ export function fileShow(entry: DirEntry) {
37
return location.href = cur.uri + '?dl'
38
if (key === 'z')
39
return switchZoomMode()
40
+ if (key === 'f')
41
+ return toggleFullScreen()
42
if (key === ' ') {
43
const sel = state.selected
44
if (sel[cur.uri])
@@ -53,6 +56,7 @@ export function fileShow(entry: DirEntry) {
56
const [loading, setLoading] = useState(false)
57
const [failed, setFailed] = useState<false | string>(false)
58
const containerRef = useRef<HTMLDivElement>()
59
+ const mainRef = useRef<HTMLDivElement>()
60
useEffect(() => { scrollY(-1E9) }, [cur])
61
const {t} = useI18N()
62
return h(Fragment, {},
@@ -74,11 +78,12 @@ export function fileShow(entry: DirEntry) {
78
iconBtn('menu', ev => openFileMenu(cur, ev, [
79
'open','delete',
80
{ icon: 'zoom', label: md(t`Switch _z_oom mode`), onClick: switchZoomMode },
81
+ { icon: 'fullscreen', label: md(t`_F_ull screen`), onClick: toggleFullScreen },
82
])),
83
iconBtn('close', close),
84
)
85
),
81
- h(FlexV, { center: true, className: 'main' },
86
+ h(FlexV, { center: true, className: 'main', ref: mainRef },
87
loading && h(Spinner, { style: { position: 'absolute', fontSize: '20vh', opacity: .5 } }),
88
failed === cur.n ? h(FlexV, { alignItems: 'center', textAlign: 'center' },
89
hIcon('error', { style: { fontSize: '20vh' } }),
@@ -122,6 +127,15 @@ export function fileShow(entry: DirEntry) {
127
setCur(e)
128
}
129
130
+ function toggleFullScreen() {
131
+ if (!document.fullscreenEnabled)
132
+ return alertDialog(t`Full-screen not supported`, 'error')
133
+ if (document.fullscreenElement)
134
+ document.exitFullscreen()
135
+ else
136
+ mainRef.current?.requestFullscreen()
137
+ }
138
+
139
function switchZoomMode() {
140
setMode(x => x ? x - 1 : ZoomMode.contain)
141
}
src/langs/hfs-lang-en.json
+2
-1
@@ -121,6 +121,7 @@
121
"Operation successful": "Operation successful",
122
"Uploader": "Uploader",
123
"Download counter": "Download counter",
124
- "Switch _z_oom mode": "Switch _z_oom mode"
124
+ "Switch _z_oom mode": "Switch _z_oom mode",
125
+ "_F_ull screen": "_F_ull screen"
126
}
127
}
src/langs/hfs-lang-it.json
+2
-1
@@ -115,6 +115,7 @@
115
"Operation successful": "Operazione riuscita",
116
"Uploader": "Upload da",
117
"Download counter": "Download conteggiati",
118
- "Switch _z_oom mode": "Cambia _z_oom"
118
+ "Switch _z_oom mode": "Cambia _z_oom",
119
+ "_F_ull screen": "Pieno schermo (_F_)"
120
}
121
}