fix: protected files were not displaying menu on click
Massimo Melina committed
Jul 2, 2024 at 12:34 UTC
2aa93f49ed83eed912dfa884ae5da832ef8b3674
2 files changed
+30
-20
frontend/src/BrowseFiles.ts
+5
-16
@@ -10,11 +10,11 @@ import { Head } from './Head'
10
import { DirEntry, state, useSnapState } from './state'
11
import { alertDialog } from './dialog'
12
import useFetchList from './useFetchList'
13
-import { loginDialog, useAuthorized } from './login'
13
+import { useAuthorized } from './login'
14
import { acceptDropFiles, enqueue } from './upload'
15
import _ from 'lodash'
16
import { t, useI18N } from './i18n'
17
-import { openFileMenu } from './fileMenu'
17
+import { makeOnClickOpen, openFileMenu } from './fileMenu'
18
import { ClipBar } from './clip'
19
import { fileShow } from './show'
20
@@ -202,22 +202,11 @@ const Entry = ({ entry, midnight, separator }: EntryProps) => {
202
if (separator)
203
className += ' ' + PAGE_SEPARATOR_CLASS
204
const ico = getEntryIcon(entry)
205
- const onClick = !isLink && !entry.web && file_menu_on_link && fileMenu || undefined
205
+ const onClick = !isFolder && !isLink && !entry.web && file_menu_on_link && fileMenu || makeOnClickOpen(entry)
206
const hasHover = useMediaQuery('(hover: hover)')
207
const showingButton = !file_menu_on_link || isFolder && !hasHover
208
const ariaId = useId()
209
const ariaProps = { id: ariaId, 'aria-label': prefix(name + ', ', isFolder ? t`Folder` : entry.web ? t`Web page` : isLink ? t`Link` : '') }
210
- const loginProps = entry.cantOpen && {
211
- async onClick(ev: any) {
212
- ev.preventDefault()
213
- if (entry.cantOpen === DirEntry.FORBIDDEN)
214
- return alertDialog(t`Forbidden`, 'warning')
215
- if (!await loginDialog(true, false)) return
216
- if (isFolder && !entry.web) // internal navigation
217
- return setTimeout(() => getHFS().navigate(uri)) // couldn't find the reason why navigating sync is reverted back
218
- location.href = uri
219
- }
220
- }
210
return h(CustomCode, {
211
name: 'entry',
212
entry,
@@ -235,14 +224,14 @@ const Entry = ({ entry, midnight, separator }: EntryProps) => {
224
h('span', { className: 'link-wrapper' }, // container to handle mouse over for both children
225
// we treat webpages as folders, with menu to comment
226
isFolder ? h(Fragment, {}, // internal navigation, use Link component
238
- h(Link, { to: uri, reloadDocument: entry.web, ...ariaProps, ...loginProps }, // without reloadDocument, once you enter the web page, the back button won't bring you back to the frontend
227
+ h(Link, { to: uri, reloadDocument: entry.web, onClick, ...ariaProps }, // without reloadDocument, once you enter the web page, the back button won't bring you back to the frontend
228
ico, entry.n.slice(0, -1)), // don't use name, as we want to include whole path in case of search
229
// popup button is here to be able to detect link-wrapper:hover
230
file_menu_on_link && !showingButton && h('button', {
231
className: 'popup-menu-button',
232
onClick: fileMenu
233
}, hIcon('menu'), t`Menu`)
245
- ) : h('a', { href: uri, onClick, target: entry.target, ...ariaProps, ...loginProps },
234
+ ) : h('a', { href: uri, onClick, target: entry.target, ...ariaProps },
235
ico, h('span', { className: 'container-folder' }, containerName), name ),
236
),
237
h(CustomCode, { name: 'afterEntryName', entry }),
frontend/src/fileMenu.ts
+25
-4
@@ -14,6 +14,7 @@ import { alertDialog, promptDialog } from './dialog'
14
import { apiCall, useApi } from '@hfs/shared/api'
15
import { inputComment } from './upload'
16
import { cut } from './clip'
17
+import { loginDialog } from './login'
18
19
interface FileMenuEntry {
20
id?: string
@@ -30,15 +31,23 @@ export function openFileMenu(entry: DirEntry, ev: MouseEvent, addToMenu: (FileMe
31
const canRead = !entry.p?.includes('r')
32
const canArchive = entry.p?.includes('A') || state.props?.can_archive && !entry.p?.includes('a')
33
const canList = !entry.p?.match(/L/i)
33
- const cantDownload = entry.cantOpen || isFolder && !(canRead && canArchive && canList) // folders needs list+read+archive
34
+ const forbidden = entry.cantOpen === DirEntry.FORBIDDEN
35
+ const cantDownload = forbidden || isFolder && !(canRead && canArchive && canList) // folders needs list+read+archive
36
const menu = [
37
!cantDownload && { id: 'download', label: t`Download`, href: uri + (isFolder ? '?get=zip' : '?dl'), icon: 'download' },
38
state.props?.can_comment && { id: 'comment', label: t`Comment`, icon: 'comment', onClick: () => editComment(entry) },
39
...addToMenu.map(x => {
40
if (x === 'open') {
39
- if (entry.cantOpen === DirEntry.FORBIDDEN) return
40
- const open = { id: 'open', icon: 'play', label: t('file_open', "Open"), href: uri, target: isFolder || entry.web ? undefined : '_blank' }
41
- return !isFolder ? open : h(LinkClosingDialog, { to: uri, reloadDocument: entry.web }, hIcon(open.icon), open.label)
41
+ if (forbidden) return
42
+ const open = {
43
+ id: 'open',
44
+ icon: 'play',
45
+ label: t('file_open', "Open"),
46
+ href: uri,
47
+ target: isFolder || entry.web ? undefined : '_blank',
48
+ onClick: makeOnClickOpen(entry)
49
+ }
50
+ return !isFolder || open.onClick ? open : h(LinkClosingDialog, { to: uri, reloadDocument: entry.web }, hIcon(open.icon), open.label)
51
}
52
if (x === 'delete')
53
return (state.props?.can_delete || entry.p?.includes('d')) && {
@@ -178,4 +187,16 @@ export function LinkClosingDialog(props: LinkProps) {
187
getHFS().navigate(props.to)
188
}
189
})
190
+}
191
+
192
+export function makeOnClickOpen(entry: DirEntry) {
193
+ return !entry.cantOpen ? undefined : async (ev: any) => {
194
+ ev.preventDefault()
195
+ if (entry.cantOpen === DirEntry.FORBIDDEN)
196
+ return alertDialog(t`Forbidden`, 'warning')
197
+ if (!await loginDialog(true, false)) return
198
+ if (entry.isFolder && !entry.web) // internal navigation
199
+ return setTimeout(() => getHFS().navigate(entry.uri)) // couldn't find the reason why navigating sync is reverted back
200
+ location.href = entry.uri
201
+ }
202
}
\ No newline at end of file