@samitouri / QOSami-HFS / commits / c97b15d5

dev: responsive mobile detection

Massimo Melina committed Mar 26, 2024 at 18:11 UTC c97b15d5f385488760e10347c6aa0674ae0cc634
3 files changed +12 -7
admin/src/AccountForm.ts
+3 -3
@@ -5,12 +5,11 @@ import { BoolField, Form, MultiSelectField, NumberField } from '@hfs/mui-grid-fo
5 import { Alert } from '@mui/material'
6 import { apiCall } from './api'
7 import { alertDialog, toast, useDialogBarColors } from './dialog'
8 -import { isEqualLax, wantArray } from './misc'
8 +import { isEqualLax, useIsMobile, wantArray } from './misc'
9 import { IconBtn, modifiedProps } from './mui'
10 import { Account } from './AccountsPage'
11 import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
12 import { AutoDelete, Delete } from '@mui/icons-material'
13 -import { isMobile } from './misc'
13 import { state, useSnapState } from './state'
14 import VfsPathField from './VfsPathField'
15 import { DateTimeField } from './DateTimeField'
@@ -20,10 +19,11 @@ export default function AccountForm({ account, done, groups, addToBar, reload }:
19 const { username } = useSnapState()
20 const [values, setValues] = useState<Account & { password?: string, password2?: string }>(account)
21 const [belongsOptions, setBelongOptions] = useState<string[]>([])
22 + const isMobile = useIsMobile()
23 useEffect(() => {
24 setValues(account)
25 setBelongOptions(groups.filter(x => x !== account.username ))
26 - if (!isMobile())
26 + if (!isMobile)
27 ref.current?.querySelector('input')?.focus()
28 }, [JSON.stringify(account)]) //eslint-disable-line
29 const add = !account.username
frontend/src/upload.ts
+4 -3
@@ -2,7 +2,7 @@
2
3 import { createElement as h, DragEvent, Fragment, useMemo, CSSProperties } from 'react'
4 import { Flex, FlexV, iconBtn, Select } from './components'
5 -import { basename, closeDialog, formatBytes, formatPerc, hIcon, isMobile, newDialog, prefix, selectFiles, working,
5 +import { basename, closeDialog, formatBytes, formatPerc, hIcon, useIsMobile, newDialog, prefix, selectFiles, working,
6 HTTP_CONFLICT, HTTP_PAYLOAD_TOO_LARGE, formatSpeed, dirname, getHFS, onlyTruthy, with_ } from './misc'
7 import _ from 'lodash'
8 import { proxy, ref, subscribe, useSnapshot } from 'valtio'
@@ -110,6 +110,7 @@ export function showUpload() {
110 const inQ = _.sumBy(qs, q => q.entries.length) - (uploadState.uploading ? 1 : 0)
111 const queueStr = inQ && t('in_queue', { n: inQ }, "{n} in queue")
112 const size = formatBytes(adding.reduce((a, x) => a + x.file.size, 0))
113 + const isMobile = useIsMobile()
114
115 return h(FlexV, { gap: '.5em', props: acceptDropFiles(more => uploadState.adding.push(...more.map(f => ({ file: ref(f) })))) },
116 h(FlexV, { className: 'upload-toolbar' },
@@ -120,7 +121,7 @@ export function showUpload() {
121 className: 'upload-files',
122 onClick: () => pickFiles({ accept: normalizeAccept(props?.accept) })
123 }, t`Pick files`),
123 - !isMobile() && h('button', {
124 + !isMobile && h('button', {
125 className: 'upload-folder',
126 onClick: () => pickFiles({ folder: true })
127 }, t`Pick folder`),
@@ -137,7 +138,7 @@ export function showUpload() {
138 ])
139 }),
140 ),
140 - !isMobile() && h(Flex, { gap: 4 }, hIcon('info'), t('upload_dd_hint', "You can upload files doing drag&drop on the files list")),
141 + !isMobile && h(Flex, { gap: 4 }, hIcon('info'), t('upload_dd_hint', "You can upload files doing drag&drop on the files list")),
142 adding.length > 0 && h(Flex, { center: true, flexWrap: 'wrap' },
143 h('button', {
144 className: 'upload-send',
shared/react.ts
+5 -1
@@ -2,7 +2,7 @@
2
3 import { createElement as h, Fragment, KeyboardEvent, ReactElement, ReactNode,
4 useCallback, useEffect, useRef, useState } from 'react'
5 -import { useIsMounted, useWindowSize } from 'usehooks-ts'
5 +import { useIsMounted, useWindowSize, useMediaQuery } from 'usehooks-ts'
6 import { Falsy } from '.'
7
8 export function useStateMounted<T>(init: T) {
@@ -99,6 +99,10 @@ export function KeepInScreen({ margin, ...props }: any) {
99 return h('div', { ref, style: { maxHeight, overflow: 'auto' }, ...props })
100 }
101
102 +export function useIsMobile() {
103 + return useMediaQuery('(pointer:coarse)')
104 +}
105 +
106 export function AriaOnly({ children }: { children?: ReactNode }) {
107 return children ? h('div', { className: 'ariaOnly' }, children) : null
108 }