1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { encodePath } from '@nextcloud/paths'
import { generateOcsUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { FileAction, Permission, type Node } from '@nextcloud/files'
import { showError, DialogBuilder } from '@nextcloud/dialogs'
import { translate as t } from '@nextcloud/l10n'
import axios from '@nextcloud/axios'
import LaptopSvg from '@mdi/svg/svg/laptop.svg?raw'
import IconWeb from '@mdi/svg/svg/web.svg?raw'
import { isPublicShare } from '@nextcloud/sharing/public'
const confirmLocalEditDialog = (
localEditCallback: (openingLocally: boolean) => void = () => {},
) => {
let callbackCalled = false
return (new DialogBuilder())
.setName(t('files', 'Open file locally'))
.setText(t('files', 'The file should now open on your device. If it doesn\'t, please check that you have the desktop app installed.'))
.setButtons([
{
label: t('files', 'Retry and close'),
type: 'secondary',
callback: () => {
callbackCalled = true
localEditCallback(true)
},
},
{
label: t('files', 'Open online'),
icon: IconWeb,
type: 'primary',
callback: () => {
callbackCalled = true
localEditCallback(false)
},
},
])
.build()
.show()
.then(() => {
// Ensure the callback is called even if the dialog is dismissed in other ways
if (!callbackCalled) {
localEditCallback(false)
}
})
}
const attemptOpenLocalClient = async (path: string) => {
openLocalClient(path)
confirmLocalEditDialog(
(openLocally: boolean) => {
if (!openLocally) {
window.OCA.Viewer.open({ path })
return
}
openLocalClient(path)
},
)
}
const openLocalClient = async function(path: string) {
const link = generateOcsUrl('apps/files/api/v1') + '/openlocaleditor?format=json'
try {
const result = await axios.post(link, { path })
const uid = getCurrentUser()?.uid
let url = `nc://open/${uid}@` + window.location.host + encodePath(path)
url += '?token=' + result.data.ocs.data.token
window.open(url, '_self')
} catch (error) {
showError(t('files', 'Failed to redirect to client'))
}
}
export const action = new FileAction({
id: 'edit-locally',
displayName: () => t('files', 'Open locally'),
iconSvgInline: () => LaptopSvg,
// Only works on single files
enabled(nodes: Node[]) {
// Only works on single node
if (nodes.length !== 1) {
return false
}
// does not work with shares
if (isPublicShare()) {
return false
}
return (nodes[0].permissions & Permission.UPDATE) !== 0
},
async exec(node: Node) {
attemptOpenLocalClient(node.path)
return null
},
order: 25,
})
|