Skip to content

Commit 577032c

Browse files
Merge pull request #53176 from nextcloud/backport/53171/stable30
[stable30] fix(files): do nothing if `view local` dialog was just closed
2 parents 44dd428 + ed99adb commit 577032c

5 files changed

Lines changed: 81 additions & 71 deletions

File tree

apps/files/src/actions/editLocallyAction.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ describe('Edit locally action execute tests', () => {
122122
jest.spyOn(axios, 'post').mockImplementation(async () => ({
123123
data: { ocs: { data: { token: 'foobar' } } },
124124
}))
125+
const windowOpenSpy = jest.spyOn(window, 'open')
125126
const mockedShowError = jest.mocked(showError)
126127
const spyDialogBuilder = jest.spyOn(dialogBuilder, 'build')
127128

@@ -142,7 +143,7 @@ describe('Edit locally action execute tests', () => {
142143
expect(axios.post).toBeCalledTimes(1)
143144
expect(axios.post).toBeCalledWith('http://localhost/ocs/v2.php/apps/files/api/v1/openlocaleditor?format=json', { path: '/foobar.txt' })
144145
expect(mockedShowError).toBeCalledTimes(0)
145-
expect(window.location.href).toBe('nc://open/test@localhost/foobar.txt?token=foobar')
146+
expect(windowOpenSpy).toBeCalledWith('nc://open/test@localhost/foobar.txt?token=foobar', '_self')
146147
})
147148

148149
test('Edit locally fails and shows error', async () => {

apps/files/src/actions/editLocallyAction.ts

Lines changed: 73 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -12,71 +12,6 @@ import axios from '@nextcloud/axios'
1212
import IconWeb from '@mdi/svg/svg/web.svg?raw'
1313
import LaptopSvg from '@mdi/svg/svg/laptop.svg?raw'
1414

15-
const confirmLocalEditDialog = (
16-
localEditCallback: (openingLocally: boolean) => void = () => {},
17-
) => {
18-
let callbackCalled = false
19-
20-
return (new DialogBuilder())
21-
.setName(t('files', 'Edit file locally'))
22-
.setText(t('files', 'The file should now open on your device. If it doesn\'t, please check that you have the desktop app installed.'))
23-
.setButtons([
24-
{
25-
label: t('files', 'Retry and close'),
26-
type: 'secondary',
27-
callback: () => {
28-
callbackCalled = true
29-
localEditCallback(true)
30-
},
31-
},
32-
{
33-
label: t('files', 'Edit online'),
34-
icon: IconWeb,
35-
type: 'primary',
36-
callback: () => {
37-
callbackCalled = true
38-
localEditCallback(false)
39-
},
40-
},
41-
])
42-
.build()
43-
.show()
44-
.then(() => {
45-
// Ensure the callback is called even if the dialog is dismissed in other ways
46-
if (!callbackCalled) {
47-
localEditCallback(false)
48-
}
49-
})
50-
}
51-
52-
const attemptOpenLocalClient = async (path: string) => {
53-
openLocalClient(path)
54-
confirmLocalEditDialog(
55-
(openLocally: boolean) => {
56-
if (!openLocally) {
57-
window.OCA.Viewer.open({ path })
58-
return
59-
}
60-
openLocalClient(path)
61-
},
62-
)
63-
}
64-
65-
const openLocalClient = async function(path: string) {
66-
const link = generateOcsUrl('apps/files/api/v1') + '/openlocaleditor?format=json'
67-
68-
try {
69-
const result = await axios.post(link, { path })
70-
const uid = getCurrentUser()?.uid
71-
let url = `nc://open/${uid}@` + window.location.host + encodePath(path)
72-
url += '?token=' + result.data.ocs.data.token
73-
74-
window.location.href = url
75-
} catch (error) {
76-
showError(t('files', 'Failed to redirect to client'))
77-
}
78-
}
79-
8015
export const action = new FileAction({
8116
id: 'edit-locally',
8217
displayName: () => t('files', 'Edit locally'),
@@ -93,9 +28,81 @@ export const action = new FileAction({
9328
},
9429

9530
async exec(node: Node) {
96-
attemptOpenLocalClient(node.path)
31+
await attemptOpenLocalClient(node.path)
9732
return null
9833
},
9934

10035
order: 25,
10136
})
37+
38+
/**
39+
* Try to open the path in the Nextcloud client.
40+
*
41+
* If this fails a dialog is shown with 3 options:
42+
* 1. Retry: If it fails no further dialog is shown.
43+
* 2. Open online: The viewer is used to open the file.
44+
* 3. Close the dialog and nothing happens (abort).
45+
*
46+
* @param path - The path to open
47+
*/
48+
async function attemptOpenLocalClient(path: string) {
49+
await openLocalClient(path)
50+
const result = await confirmLocalEditDialog()
51+
if (result === 'local') {
52+
await openLocalClient(path)
53+
} else if (result === 'online') {
54+
window.OCA.Viewer.open({ path })
55+
}
56+
}
57+
58+
/**
59+
* Try to open a file in the Nextcloud client.
60+
* There is no way to get notified if this action was successfull.
61+
*
62+
* @param path - Path to open
63+
*/
64+
async function openLocalClient(path: string): Promise<void> {
65+
const link = generateOcsUrl('apps/files/api/v1') + '/openlocaleditor?format=json'
66+
67+
try {
68+
const result = await axios.post(link, { path })
69+
const uid = getCurrentUser()?.uid
70+
let url = `nc://open/${uid}@` + window.location.host + encodePath(path)
71+
url += '?token=' + result.data.ocs.data.token
72+
73+
window.open(url, '_self')
74+
} catch (error) {
75+
showError(t('files', 'Failed to redirect to client'))
76+
}
77+
}
78+
79+
/**
80+
* Open the confirmation dialog.
81+
*/
82+
async function confirmLocalEditDialog(): Promise<'online'|'local'|false> {
83+
let result: 'online'|'local'|false = false
84+
const dialog = (new DialogBuilder())
85+
.setName(t('files', 'Open file locally'))
86+
.setText(t('files', 'The file should now open on your device. If it doesn\'t, please check that you have the desktop app installed.'))
87+
.setButtons([
88+
{
89+
label: t('files', 'Retry and close'),
90+
type: 'secondary',
91+
callback: () => {
92+
result = 'local'
93+
},
94+
},
95+
{
96+
label: t('files', 'Open online'),
97+
icon: IconWeb,
98+
type: 'primary',
99+
callback: () => {
100+
result = 'online'
101+
},
102+
},
103+
])
104+
.build()
105+
106+
await dialog.show()
107+
return result
108+
}

dist/files-init.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/files-init.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webpack.common.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ const config = {
169169

170170
plugins: [
171171
new VueLoaderPlugin(),
172-
new NodePolyfillPlugin(),
172+
new NodePolyfillPlugin({
173+
additionalAliases: ['process'],
174+
}),
173175
new webpack.ProvidePlugin({
174176
// Provide jQuery to jquery plugins as some are loaded before $ is exposed globally.
175177
// We need to provide the path to node_moduels as otherwise npm link will fail due

0 commit comments

Comments
 (0)