file show: zoom-mode (in menu)

Massimo Melina committed Jul 26, 2023 at 22:31 UTC d696c4882b3cd703ae83bc5b35ee2b89f8931af7
9 files changed +66 -22
frontend/fontello-config.json
+18
@@ -203,6 +203,24 @@
203 "css": "reload",
204 "code": 59416,
205 "src": "fontawesome"
206 + },
207 + {
208 + "uid": "b013f6403e5ab0326614e68d1850fd6b",
209 + "css": "zoom",
210 + "code": 61618,
211 + "src": "fontawesome"
212 + },
213 + {
214 + "uid": "757afacc32d82967975cbb3b45cfb41b",
215 + "css": "fullscreen",
216 + "code": 61704,
217 + "src": "fontawesome"
218 + },
219 + {
220 + "uid": "9c1376672bb4f1ed616fdd78a23667e9",
221 + "css": "comment",
222 + "code": 61669,
223 + "src": "fontawesome"
224 }
225 ]
226 }
\ No newline at end of file
frontend/public/fontello.css
+5 -2
@@ -1,6 +1,6 @@
1 @font-face {
2 font-family: 'fontello';
3 - src: url('fontello.woff2?26713191') format('woff2');
3 + src: url('fontello.woff2?44288867') format('woff2');
4 font-weight: normal;
5 font-style: normal;
6 }
@@ -10,7 +10,7 @@
10 @media screen and (-webkit-min-device-pixel-ratio:0) {
11 @font-face {
12 font-family: 'fontello';
13 - src: url('../font/fontello.svg?26713191#fontello') format('svg');
13 + src: url('../font/fontello.svg?44288867#fontello') format('svg');
14 }
15 }
16 */
@@ -78,7 +78,10 @@
78 .fa-download:before { content: '\f02e'; } /* '' */
79 .fa-upload:before { content: '\f02f'; } /* '' */
80 .fa-filter:before { content: '\f0b0'; } /* '' */
81 +.fa-zoom:before { content: '\f0b2'; } /* '' */
82 .fa-menu:before { content: '\f0c9'; } /* '' */
83 +.fa-comment:before { content: '\f0e5'; } /* '' */
84 +.fa-fullscreen:before { content: '\f108'; } /* '' */
85 .fa-quote:before { content: '\f10d'; } /* '' */
86 .fa-unlink:before { content: '\f127'; } /* '' */
87 .fa-archive:before { content: '\f1c6'; } /* '' */
frontend/public/fontello.woff2
Binary files a/frontend/public/fontello.woff2 and b/frontend/public/fontello.woff2 differ
frontend/src/components.ts
+1 -1
@@ -19,7 +19,7 @@ export function Spinner(props: any) {
19 return hIcon('spinner', { className:'spinner', ...props })
20 }
21
22 -export function Flex({ gap='.8em', center=false, vert=false, children=null, className=undefined, props={}, ...rest }) {
22 +export function Flex({ gap='.8em', center=false, vert=false, children=null, className='', props={}, ...rest }) {
23 return h('div', {
24 className,
25 style: {
frontend/src/icons.ts
+10 -6
@@ -3,7 +3,7 @@
3 import { state, useSnapState } from './state'
4 import { createElement as h, memo } from 'react'
5
6 -const SYS_ICONS: Record<string, string[]> = {
6 +const SYS_ICONS: Record<string, [string] | [string, string]> = {
7 login: ['👤','user'],
8 user: ['👤','user'],
9 filter: ['✂'],
@@ -33,6 +33,7 @@ const SYS_ICONS: Record<string, string[]> = {
33 list: ['☰','menu'],
34 play: ['▶'],
35 edit: ['✏️'],
36 + zoom: ['↔'],
37 }
38
39 document.fonts.ready.then(async ()=> {
@@ -43,17 +44,20 @@ document.fonts.ready.then(async ()=> {
44
45 interface IconProps { name:string, className?:string, alt?:string, [rest:string]: any }
46 export const Icon = memo(({ name, alt, className='', ...props }: IconProps) => {
46 - const [emoji,clazz] = SYS_ICONS[name] || name.split(':')
47 + if (!name) return null
48 + const [emoji, clazz=name] = SYS_ICONS[name] || []
49 const { iconsReady } = useSnapState()
50 className += ' icon'
49 - const nameIsEmoji = name.length <= 2
50 - const nameIsFile = name.includes('.')
51 - className += nameIsEmoji ? ' emoji-icon' : nameIsFile ? ' file-icon' : iconsReady ? ' fa-'+(clazz||name) : ' emoji-icon'
51 + const nameIsTheIcon = name.length === 1 ||
52 + name.match(/^[\uD800-\uDFFF\u2600-\u27BF\u2B50-\u2BFF\u3030-\u303F\u3297\u3299\u00A9\u00AE\u200D\u20E3\uFE0F\u2190-\u21FF\u2300-\u23FF\u2400-\u243F\u25A0-\u25FF\u2600-\u26FF\u2700-\u27BF]*$/)
53 + const nameIsFile = !nameIsTheIcon && name.includes('.')
54 + const isFontIcon = iconsReady && clazz
55 + className += nameIsFile ? ' file-icon' : isFontIcon ? ` fa-${clazz}` : ' emoji-icon'
56 return h('span',{
57 'aria-label': alt,
58 role: 'img',
59 ...props,
60 ...nameIsFile ? { style: { backgroundImage: `url(${JSON.stringify(name)})`, ...props?.style } } : undefined,
61 className,
58 - }, nameIsEmoji ? name : iconsReady ? null : (emoji||'#'))
62 + }, nameIsTheIcon ? name : isFontIcon ? null : (emoji||'#'))
63 })
frontend/src/index.scss
+6 -3
@@ -566,10 +566,13 @@ button label {
566 flex: 1; position: relative; max-height: 100%;
567 overflow: hidden; // without this <video> can make me go beyond the screen limit
568 }
569 - .fullY {
569 + .freeY, .fullWidth {
570 .main { overflow-y: auto; }
571 - .showing { max-height: initial }
572 - .showing-container { overflow: auto; }
571 + .showing { max-height: initial; margin: auto; }
572 + .showing-container { overflow: auto; align-items: flex-start;}
573 + }
574 + .fullWidth {
575 + .showing-container, .showing { width: 100%; }
576 }
577 --nav-size: min(25vh, 15vw);
578 .nav {
frontend/src/show.ts
+19 -5
@@ -6,6 +6,13 @@ import { EntryDetails, useMidnight } from './BrowseFiles'
6 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 +
11 +enum ZoomMode {
12 + fullWidth,
13 + freeY,
14 + contain, // leave this as last
15 +}
16
17 export function fileShow(entry: DirEntry) {
18 const { close } = newDialog({
@@ -15,7 +22,7 @@ export function fileShow(entry: DirEntry) {
22 const [cur, setCur] = useState(entry)
23 const moving = useRef(0)
24 const lastGood = useRef(entry)
18 - const [fullY, setFullY] = useState(false)
25 + const [mode, setMode] = useState(ZoomMode.contain)
26 useEventListener('keydown', ({ key }) => {
27 if (key === 'ArrowLeft')
28 return go(-1)
@@ -23,8 +30,8 @@ export function fileShow(entry: DirEntry) {
30 return go(+1)
31 if (key === 'd')
32 return location.href = cur.uri + '?dl'
26 - if (key === 'ArrowUp')
27 - return setFullY(x => !x)
33 + if (key === 'z')
34 + return switchZoomMode()
35 if (key === ' ') {
36 const sel = state.selected
37 if (sel[cur.uri])
@@ -41,13 +48,16 @@ export function fileShow(entry: DirEntry) {
48 useEffect(() => { containerRef.current?.scrollTo(0,0) }, [cur])
49 const {t} = useI18N()
50 return h(Fragment, {},
44 - h(FlexV, { gap: 0, alignItems: 'stretch', className: fullY ? 'fullY' : undefined, },
51 + h(FlexV, { gap: 0, alignItems: 'stretch', className: ZoomMode[mode] },
52 h('div', { className: 'bar' },
53 h('div', { className: 'filename' }, cur.n),
54 h(EntryDetails, { entry: cur, midnight: useMidnight() }),
55 h(Flex, {},
56 useWindowSize().width > 1280 && iconBtn('?', () => window.open(WIKI_URL + 'File-show')),
50 - iconBtn('menu', ev => openFileMenu(cur, ev, ['open','delete'])),
57 + iconBtn('menu', ev => openFileMenu(cur, ev, [
58 + 'open','delete',
59 + { icon: 'zoom', label: md(t`Switch _z_oom mode`), onClick: switchZoomMode },
60 + ])),
61 iconBtn('close', close),
62 )
63 ),
@@ -94,6 +104,10 @@ export function fileShow(entry: DirEntry) {
104 }
105 setCur(e)
106 }
107 +
108 + function switchZoomMode() {
109 + setMode(x => x ? x - 1 : ZoomMode.contain)
110 + }
111 }
112 })
113 }
src/langs/hfs-lang-en.json
+3 -2
@@ -1,7 +1,7 @@
1 {
2 "author": "YOUR NAME HERE",
3 "version": 1.0,
4 - "hfs_version": "0.46.0",
4 + "hfs_version": "0.47.0",
5 "translate": {
6 "Select": "Select",
7 "n_files": "{n,plural,one{# file} other{# files}}",
@@ -120,6 +120,7 @@
120 "off": "off",
121 "Operation successful": "Operation successful",
122 "Uploader": "Uploader",
123 - "Download counter": "Download counter"
123 + "Download counter": "Download counter",
124 + "Switch _z_oom mode": "Switch _z_oom mode"
125 }
126 }
src/langs/hfs-lang-it.json
+4 -3
@@ -1,7 +1,7 @@
1 {
2 "author": "Massimo Melina",
3 - "version": 1.6,
4 - "hfs_version": "0.46.0",
3 + "version": 1.7,
4 + "hfs_version": "0.47.0",
5 "translate": {
6 "Select": "Seleziona",
7 "n_files": "{n} file",
@@ -114,6 +114,7 @@
114 "off": "no",
115 "Operation successful": "Operazione riuscita",
116 "Uploader": "Upload da",
117 - "Download counter": "Download conteggiati"
117 + "Download counter": "Download conteggiati",
118 + "Switch _z_oom mode": "Cambia _z_oom"
119 }
120 }