admin/fs: Windows system integration let you pick a destination folder

Massimo Melina committed Dec 9, 2023 at 18:36 UTC 9e797370d5ec4d2e9811e2df5c729bae0dbf9952
3 files changed +37 -28
admin/src/VfsMenuBar.ts
+14 -10
@@ -1,7 +1,7 @@
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 import { createElement as h } from 'react'
4 -import { Alert, Box } from '@mui/material'
4 +import { Alert, Box, Button } from '@mui/material'
5 import { Add, Microsoft } from '@mui/icons-material'
6 import { reloadVfs } from './VfsPage'
7 import addFiles, { addLink, addVirtual } from './addFiles'
@@ -12,6 +12,7 @@ import { ConfigForm } from './ConfigForm'
12 import { ArrayField } from './ArrayField'
13 import { BoolField } from '@hfs/mui-grid-form'
14 import VfsPathField from './VfsPathField'
15 +import { promptDialog } from './dialog'
16
17 export default function VfsMenuBar({ statusApi }: { statusApi: ApiObject }) {
18 const isWindows = statusApi.data?.platform === 'win32'
@@ -41,15 +42,18 @@ export default function VfsMenuBar({ statusApi }: { statusApi: ApiObject }) {
42 doneMessage: true,
43 ...(!integrated?.is ? {
44 children: "System integration",
44 - onClick: () => apiCall('windows_integration').then(reload),
45 - confirm: h(Box, {}, "We are going to add a command in the right-click of Windows File Manager",
46 - h('img', { src: 'win-shell.png', style: {
47 - display: 'block',
48 - width: 'min(30em, 80vw)',
49 - marginTop: '1em',
50 - } }),
51 - h(Alert, { severity: 'info' }, "It will also automatically copy the URL, ready to paste!"),
52 - )
45 + async onClick() {
46 + const msg = h(Box, {}, "We are going to add a command in the right-click of Windows File Manager",
47 + h('img', { src: 'win-shell.png', style: {
48 + display: 'block',
49 + width: 'min(30em, 80vw)',
50 + marginTop: '1em',
51 + } }),
52 + h(Alert, { severity: 'info' }, "It will also automatically copy the URL, ready to paste!"),
53 + )
54 + const parent = await promptDialog(msg, { field: { comp: VfsPathField, label: "Add to this folder" }, form: { saveOnEnter: false } })
55 + return !parent ? false : apiCall('windows_integration', { parent }).then(reload)
56 + }
57 } : {
58 confirm: true,
59 children: "Remove integration",
admin/src/dialog.ts
+21 -16
@@ -187,22 +187,27 @@ export async function formDialog<T>(
187 }
188
189 export async function promptDialog(msg: ReactNode, { value, field, save, addToBar=[], ...props }:any={}) : Promise<string | undefined> {
190 - return formDialog<{ text: string }>({ ...props, values: { text: value }, form: {
191 - fields: [
192 - { k: 'text', label: null, autoFocus: true, ...field, before: h(Box, { mb: 2 }, msg) },
193 - ],
194 - save: {
195 - children: "Continue",
196 - startIcon: h(Forward),
197 - ...save,
198 - },
199 - saveOnEnter: true,
200 - barSx: { gap: 2 },
201 - addToBar: [
202 - h(Button, { onClick: closeDialog }, "Cancel"),
203 - ...addToBar,
204 - ]
205 - } }).then(values => values?.text)
190 + return formDialog<{ text: string }>({
191 + ...props,
192 + values: { text: value },
193 + form: {
194 + fields: [
195 + { k: 'text', label: null, autoFocus: true, ...field, before: h(Box, { mb: 2 }, msg) },
196 + ],
197 + save: {
198 + children: "Continue",
199 + startIcon: h(Forward),
200 + ...save,
201 + },
202 + saveOnEnter: true,
203 + barSx: { gap: 2 },
204 + addToBar: [
205 + h(Button, { onClick: closeDialog }, "Cancel"),
206 + ...addToBar,
207 + ],
208 + ...props.form,
209 + }
210 + }).then(values => values?.text)
211 }
212
213 export function waitDialog() {
src/api.vfs.ts
+2 -2
@@ -214,14 +214,14 @@ const apis: ApiHandlers = {
214 })
215 },
216
217 - async windows_integration() {
217 + async windows_integration({ parent }) {
218 const status = await getServerStatus(true)
219 const h = status.http.listening ? status.http : status.https
220 const url = h.srv!.name + '://localhost:' + h.port
221 for (const k of ['*', 'Directory']) {
222 await reg('add', WINDOWS_REG_KEY.replace('*', k), '/ve', '/f', '/d', 'Add to HFS (new)')
223 await reg('add', WINDOWS_REG_KEY.replace('*', k) + '\\command', '/ve', '/f', '/d', `powershell -Command "
224 - $j = '{ \\"source\\": "' + ('%1'|convertTo-json) + '" }'; $j = [System.Text.Encoding]::UTF8.GetBytes($j); $wsh = New-Object -ComObject Wscript.Shell;
224 + $j = '{ \\"parent\\": \\"${parent}\\", \\"source\\": "' + ('%1'|convertTo-json) + '" }'; $j = [System.Text.Encoding]::UTF8.GetBytes($j); $wsh = New-Object -ComObject Wscript.Shell;
225 try { $res = Invoke-WebRequest -Uri '${url}/~/api/add_vfs' -Method POST -Headers @{ 'x-hfs-anti-csrf' = '1' } -ContentType 'application/json' -TimeoutSec 1 -Body $j;
226 $json = $res.Content | ConvertFrom-Json; $link = $json.link; $link | Set-Clipboard; } catch { $wsh.Popup('Server is down', 0, 'Error', 16); }"`)
227 }