@samitouri / QOSami-HFS / commits / 2aa93f49

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