Skip to content

Commit 70c965c

Browse files
committed
chore(upgrade): from OC.Files to nextcloud/files
Signed-off-by: Max <max@nextcloud.com>
1 parent b08cf8f commit 70c965c

8 files changed

Lines changed: 321 additions & 263 deletions

File tree

src/components/Menu/ActionInsertLink.vue

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
ref="buttonFile"
3939
:disabled="!networkOnline"
4040
:data-text-action-entry="`${actionEntry.key}-file`"
41-
@click="linkFile">
41+
@click="linkFileAndCloseMenu">
4242
<template #icon>
4343
<Document />
4444
</template>
@@ -81,7 +81,6 @@
8181

8282
<script>
8383
import { loadState } from '@nextcloud/initial-state'
84-
import { generateUrl } from '@nextcloud/router'
8584
import NcActionButton from '@nextcloud/vue/components/NcActionButton'
8685
import NcActionInput from '@nextcloud/vue/components/NcActionInput'
8786
import NcActions from '@nextcloud/vue/components/NcActions'
@@ -90,10 +89,9 @@ import { getLinkWithPicker } from '@nextcloud/vue/dist/Components/NcRichText.js'
9089
import { getMarkAttributes, isActive } from '@tiptap/core'
9190
9291
import { t } from '@nextcloud/l10n'
93-
import { ref } from 'vue'
9492
import { useFileProps } from '../../composables/useFileProps.ts'
93+
import { useLinkFile } from '../../composables/useLinkFile.ts'
9594
import { useNetworkState } from '../../composables/useNetworkState.ts'
96-
import { buildFilePicker } from '../../helpers/filePicker.js'
9795
import { Document, LinkOff, Loading, Shape, Web } from '../icons.js'
9896
import { BaseActionEntry } from './BaseActionEntry.js'
9997
import { useMenuIDMixin } from './MenuBar.provider.js'
@@ -113,14 +111,14 @@ export default {
113111
extends: BaseActionEntry,
114112
mixins: [useMenuIDMixin],
115113
setup() {
114+
const base = BaseActionEntry.setup()
116115
const { networkOnline } = useNetworkState()
117116
const { relativePath } = useFileProps()
118-
const parentPath = (relativePath ?? '/').split('/').slice(0, -1).join('/')
119-
const startPath = ref(parentPath)
117+
const { linkFile } = useLinkFile({ editor: base.editor, relativePath })
120118
return {
121-
...BaseActionEntry.setup(),
119+
...base,
120+
linkFile,
122121
networkOnline,
123-
startPath,
124122
}
125123
},
126124
data: () => {
@@ -143,30 +141,11 @@ export default {
143141
* Open dialog and ask user which file to link to
144142
* Triggered by the "link file" button
145143
*/
146-
linkFile() {
147-
const filePicker = buildFilePicker(this.startPath)
148-
149-
filePicker
150-
.pick()
151-
.then((file) => {
152-
const client = OC.Files.getClient()
153-
client.getFileInfo(file).then((_status, fileInfo) => {
154-
const url = new URL(
155-
generateUrl(`/f/${fileInfo.id}`),
156-
window.origin,
157-
)
158-
this.setLink(url.href, fileInfo.name)
159-
this.startPath =
160-
fileInfo.path
161-
+ (fileInfo.type === 'dir' ? `/${fileInfo.name}/` : '')
162-
})
163-
this.menuOpen = false
164-
})
165-
.catch(() => {
166-
// do not close menu but keep focus
167-
this.$refs.buttonFile?.$el.focus()
168-
})
144+
async linkFileAndCloseMenu() {
145+
await this.linkFile()
146+
this.menuOpen = false
169147
},
148+
170149
/**
171150
* Allow user to enter an URL manually
172151
* Triggered when by the "link url" button

src/components/SuggestionsBar.vue

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,14 @@
5858

5959
<script>
6060
import { t } from '@nextcloud/l10n'
61-
import { generateUrl } from '@nextcloud/router'
6261
import NcButton from '@nextcloud/vue/components/NcButton'
6362
import { getLinkWithPicker } from '@nextcloud/vue/dist/Components/NcRichText.js'
64-
import { ref } from 'vue'
6563
import { Document, Shape, Table as TableIcon, Upload } from '../components/icons.js'
6664
import { useConnection } from '../composables/useConnection.ts'
6765
import { useEditor } from '../composables/useEditor.ts'
6866
import { useFileProps } from '../composables/useFileProps.ts'
67+
import { useLinkFile } from '../composables/useLinkFile.ts'
6968
import { useNetworkState } from '../composables/useNetworkState.ts'
70-
import { buildFilePicker } from '../helpers/filePicker.js'
7169
import { isMobileDevice } from '../helpers/isMobileDevice.js'
7270
import { useActionChooseLocalAttachmentMixin } from './Editor/MediaHandler.provider.js'
7371
@@ -88,14 +86,13 @@ export default {
8886
const { openData } = useConnection()
8987
const { networkOnline } = useNetworkState()
9088
const { relativePath } = useFileProps()
91-
const parentPath = (relativePath ?? '/').split('/').slice(0, -1).join('/')
92-
const startPath = ref(parentPath)
89+
const { linkFile } = useLinkFile({ editor, relativePath })
9390
return {
9491
editor,
9592
isMobileDevice,
93+
linkFile,
9694
networkOnline,
9795
openData,
98-
startPath,
9996
}
10097
},
10198
@@ -106,9 +103,6 @@ export default {
106103
},
107104
108105
computed: {
109-
relativePath() {
110-
return this.$file?.relativePath ?? '/'
111-
},
112106
isUploadDisabled() {
113107
return !this.openData?.hasOwner || !this.networkOnline
114108
},
@@ -163,45 +157,6 @@ export default {
163157
this.editor.chain().focus().insertTable()?.run()
164158
},
165159
166-
/**
167-
* Open dialog and ask user which file to link to
168-
* Triggered by the "link to file or folder" button
169-
*/
170-
linkFile() {
171-
const filePicker = buildFilePicker(this.startPath)
172-
173-
filePicker
174-
.pick()
175-
.then((file) => {
176-
const client = OC.Files.getClient()
177-
client.getFileInfo(file).then((_status, fileInfo) => {
178-
const url = new URL(
179-
generateUrl(`/f/${fileInfo.id}`),
180-
window.origin,
181-
)
182-
this.setLink(url.href, fileInfo.name)
183-
this.startPath =
184-
fileInfo.path
185-
+ (fileInfo.type === 'dir' ? `/${fileInfo.name}/` : '')
186-
})
187-
})
188-
.catch(() => {
189-
// do not close menu but keep focus
190-
this.$refs.linkFileOrFolder.$el.focus()
191-
})
192-
},
193-
194-
/**
195-
* Save user entered URL as a link markup
196-
* Triggered when the user submits the ActionInput
197-
*
198-
* @param {string} url href attribute of the link
199-
* @param {string} text Text part of the link
200-
*/
201-
setLink(url, text) {
202-
this.editor.chain().insertOrSetLink(text, { href: url }).focus().run()
203-
},
204-
205160
onUpdate({ editor }) {
206161
/**
207162
* Empty document has an empty document and an empty paragraph (open and close blocks)

src/composables/useLinkFile.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { generateUrl } from '@nextcloud/router'
7+
import type { Editor } from '@tiptap/core'
8+
import { ref } from 'vue'
9+
import { buildFilePicker } from '../helpers/filePicker.js'
10+
import {
11+
getClient,
12+
getDefaultPropfind,
13+
resultToNode,
14+
defaultRootPath,
15+
} from '@nextcloud/files/dav'
16+
import type { FileStat, ResponseDataDetailed } from 'webdav'
17+
18+
export const useLinkFile = ({ editor, relativePath }: { editor: Editor, relativePath?: string }) => {
19+
const parentPath = (relativePath ?? '/').split('/').slice(0, -1).join('/')
20+
const startPath = ref(parentPath)
21+
const setLink = (url: string, text: string) => {
22+
editor.chain().insertOrSetLink(text, { href: url }).focus().run()
23+
}
24+
25+
/**
26+
* Open dialog and ask user which file to link to
27+
* @param event click that triggered the call.
28+
*/
29+
const linkFile = async (event: MouseEvent) => {
30+
const node = await pickFile(startPath.value)
31+
.catch(() => {
32+
// TODO: check if this works.
33+
// return focus to the trigger.
34+
if (event.target instanceof HTMLElement) {
35+
event.target.focus()
36+
}
37+
})
38+
if (!node) {
39+
return
40+
}
41+
const url = new URL(generateUrl(`/f/${node.id}`), window.origin)
42+
setLink(url.href, node.displayname)
43+
startPath.value =
44+
node.path
45+
+ (node.type === 'folder' ? `/${node.basename}/` : '')
46+
}
47+
48+
return { linkFile }
49+
}
50+
51+
/**
52+
* Pick a file with the file picker and return the node
53+
* @param startPath path to start the file picker on
54+
*/
55+
async function pickFile(startPath: string) {
56+
const filePicker = buildFilePicker(startPath)
57+
const file = await filePicker.pick()
58+
const client = getClient()
59+
const result = await client.stat(`${defaultRootPath}${file}`, {
60+
details: true,
61+
data: getDefaultPropfind(),
62+
}) as ResponseDataDetailed<FileStat>
63+
return resultToNode(result.data)
64+
}

0 commit comments

Comments
 (0)