diff --git a/src/components/Albums/CollaboratorsSelectionForm.vue b/src/components/Albums/CollaboratorsSelectionForm.vue
index ddd8f5510..a38db1738 100644
--- a/src/components/Albums/CollaboratorsSelectionForm.vue
+++ b/src/components/Albums/CollaboratorsSelectionForm.vue
@@ -349,7 +349,7 @@ export default {
await this.updateAlbumCollaborators()
await this.fetchCollection(
this.albumFileName,
- ['', '', '']
+ ['', '', ''],
)
},
diff --git a/src/components/FilesListViewer.vue b/src/components/FilesListViewer.vue
index 7954c8d75..73b1d0d4b 100644
--- a/src/components/FilesListViewer.vue
+++ b/src/components/FilesListViewer.vue
@@ -84,7 +84,7 @@ import { NcEmptyContent, NcLoadingIcon } from '@nextcloud/vue'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import TiledLayout from '../components/TiledLayout/TiledLayout.vue'
-import { fetchFile } from '../services/fileFetcher.js'
+import { fetchFile } from '../services/fileFetcher.ts'
import VirtualScrolling from '../components/VirtualScrolling.vue'
import EmptyBox from '../assets/Illustrations/empty.svg'
diff --git a/src/mixins/FetchFacesMixin.js b/src/mixins/FetchFacesMixin.js
index 0cff8cbf5..e39dbf1a5 100644
--- a/src/mixins/FetchFacesMixin.js
+++ b/src/mixins/FetchFacesMixin.js
@@ -20,17 +20,16 @@
*
*/
-import { mapActions, mapGetters } from 'vuex'
-
import { showError } from '@nextcloud/dialogs'
import { getCurrentUser } from '@nextcloud/auth'
+import { mapActions, mapGetters } from 'vuex'
+import he from 'he'
-import client from '../services/DavClient.js'
-import logger from '../services/logger.js'
-import DavRequest from '../services/DavRequest.js'
import { genFileInfo } from '../utils/fileUtils.js'
+import logger from '../services/logger.js'
import AbortControllerMixin from './AbortControllerMixin.js'
-import he from 'he'
+import { davClient } from '../services/DavClient.ts'
+import { getPropFind } from '../services/DavRequest.ts'
export default {
name: 'FetchFacesMixin',
@@ -76,8 +75,8 @@ export default {
this.loadingFaces = true
this.errorFetchingFaces = null
- const { data: faces } = await client.getDirectoryContents(`/recognize/${getCurrentUser()?.uid}/faces/`, {
- data: DavRequest,
+ const { data: faces } = await davClient.getDirectoryContents(`/recognize/${getCurrentUser()?.uid}/faces/`, {
+ data: getPropFind(),
details: true,
signal: this.abortController.signal,
})
@@ -111,13 +110,13 @@ export default {
this.errorFetchingFiles = null
this.loadingFiles = true
- let { data: fetchedFiles } = await client.getDirectoryContents(
+ let { data: fetchedFiles } = await davClient.getDirectoryContents(
`/recognize/${getCurrentUser()?.uid}/faces/${faceName}`,
{
- data: DavRequest,
+ data: getPropFind(),
details: true,
signal: this.abortController.signal,
- }
+ },
)
fetchedFiles = fetchedFiles
@@ -163,13 +162,13 @@ export default {
this.errorFetchingFiles = null
this.loadingFiles = true
- let { data: fetchedFiles } = await client.getDirectoryContents(
+ let { data: fetchedFiles } = await davClient.getDirectoryContents(
`/recognize/${getCurrentUser()?.uid}/unassigned-faces`,
{
- data: DavRequest,
+ data: getPropFind(),
details: true,
signal: this.abortController.signal,
- }
+ },
)
fetchedFiles = fetchedFiles
@@ -204,13 +203,13 @@ export default {
async fetchUnassignedFacesCount() {
try {
- const { data: unassignedFacesRoot } = await client.stat(
+ const { data: unassignedFacesRoot } = await davClient.stat(
`/recognize/${getCurrentUser()?.uid}/unassigned-faces`,
{
- data: DavRequest,
+ data: getPropFind(),
details: true,
signal: this.abortController.signal,
- }
+ },
)
const count = Number(unassignedFacesRoot.props.nbItems)
diff --git a/src/mixins/FetchFilesMixin.js b/src/mixins/FetchFilesMixin.js
index b58031973..794ffbad5 100644
--- a/src/mixins/FetchFilesMixin.js
+++ b/src/mixins/FetchFilesMixin.js
@@ -20,8 +20,11 @@
*
*/
-import { davGetClient, davRootPath } from '@nextcloud/files'
+import { showError } from '@nextcloud/dialogs'
+import { davRootPath } from '@nextcloud/files'
import { joinPaths } from '@nextcloud/paths'
+
+import { davClient } from '../services/DavClient.ts'
import logger from '../services/logger.js'
import getPhotos from '../services/PhotoSearch.js'
import SemaphoreWithPriority from '../utils/semaphoreWithPriority.js'
@@ -91,7 +94,7 @@ export default {
this.fetchedFileIds.push(
...fileIds
.map((fileId) => fileId.toString())
- .filter((fileId) => !blacklist.includes(fileId))
+ .filter((fileId) => !blacklist.includes(fileId)),
)
this.$store.dispatch('appendFiles', fetchedFiles)
@@ -105,7 +108,7 @@ export default {
const source = joinPaths(davRootPath, store.state.userConfig.photosSourceFolder ?? '/Photos') + '/'
logger.debug('Photo source does not exist, creating it.')
try {
- await davGetClient().createDirectory(source)
+ await davClient.createDirectory(source)
} catch (error) {
logger.error('Fail to create source directory', { error })
}
@@ -116,8 +119,8 @@ export default {
}
// cancelled request, moving on...
- logger.error('Error fetching files', { error })
- console.error(error)
+ showError(t('photos', 'Error fetching files'))
+ logger.error(error)
} finally {
this.loadingFiles = false
this.fetchSemaphore.release(fetchSemaphoreSymbol)
diff --git a/src/services/Albums.js b/src/services/Albums.js
index e1e8e7f6d..78878b4fc 100644
--- a/src/services/Albums.js
+++ b/src/services/Albums.js
@@ -23,10 +23,10 @@
import moment from '@nextcloud/moment'
import { translate as t } from '@nextcloud/l10n'
-import defaultClient from '../services/DavClient.js'
import logger from '../services/logger.js'
-import DavRequest from '../services/DavRequest.js'
import { genFileInfo } from '../utils/fileUtils.js'
+import { davClient } from './DavClient.ts'
+import { getPropFind } from './DavRequest.ts'
/**
* @typedef {object} Album
@@ -68,7 +68,7 @@ function getDavRequest(extraProps = '') {
* @param {import('webdav').WebDAVClient} client - The DAV client to use.
* @return {Promise}
*/
-export async function fetchAlbum(path, options, extraProps = '', client = defaultClient) {
+export async function fetchAlbum(path, options, extraProps = '', client = davClient) {
try {
const response = await client.stat(path, {
data: getDavRequest(extraProps),
@@ -96,7 +96,7 @@ export async function fetchAlbum(path, options, extraProps = '', client = defaul
* @param {import('webdav').WebDAVClient} client - The DAV client to use.
* @return {Promise}
*/
-export async function fetchAlbums(path, options, extraProps = '', client = defaultClient) {
+export async function fetchAlbums(path, options, extraProps = '', client = davClient) {
try {
const response = await client.getDirectoryContents(path, {
data: getDavRequest(extraProps),
@@ -164,10 +164,10 @@ function formatAlbum(album) {
* @param {import('webdav').WebDAVClient} client - The DAV client to use.
* @return {Promise}
*/
-export async function fetchAlbumContent(path, options, client = defaultClient) {
+export async function fetchAlbumContent(path, options, client = davClient) {
try {
const response = await client.getDirectoryContents(path, {
- data: DavRequest,
+ data: getPropFind(),
details: true,
...options,
})
diff --git a/src/services/DavClient.js b/src/services/DavClient.js
deleted file mode 100644
index c21ddfbe6..000000000
--- a/src/services/DavClient.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * @copyright Copyright (c) 2019 John Molakvoæ
- *
- * @author John Molakvoæ
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
- */
-
-import { createClient, getPatcher } from 'webdav'
-import axios from '@nextcloud/axios'
-import parseUrl from 'url-parse'
-import { generateRemoteUrl } from '@nextcloud/router'
-import { getCurrentUser } from '@nextcloud/auth'
-
-export const rootPath = 'dav'
-export const prefixPath = `/files/${getCurrentUser()?.uid}`
-
-// force our axios
-const patcher = getPatcher()
-patcher.patch('request', axios)
-
-// init webdav client on default dav endpoint
-const remote = generateRemoteUrl(rootPath)
-const client = createClient(remote)
-
-export const remotePath = parseUrl(remote).pathname
-export default client
diff --git a/src/services/FileInfo.js b/src/services/DavClient.ts
similarity index 51%
rename from src/services/FileInfo.js
rename to src/services/DavClient.ts
index 069590388..b4ff8f22e 100644
--- a/src/services/FileInfo.js
+++ b/src/services/DavClient.ts
@@ -1,7 +1,7 @@
/**
- * @copyright Copyright (c) 2019 John Molakvoæ
+ * @copyright Copyright (c) 2024 Ferdinand Thiessen
*
- * @author John Molakvoæ
+ * @author Ferdinand Thiessen
*
* @license AGPL-3.0-or-later
*
@@ -20,25 +20,7 @@
*
*/
-import client, { prefixPath } from './DavClient.js'
-import request from './DavRequest.js'
-import { genFileInfo } from '../utils/fileUtils.js'
+import type { WebDAVClient } from 'webdav'
+import { davGetClient } from '@nextcloud/files'
-/**
- * Get a file info
- *
- * @param {string} path the path relative to the user root
- * @return {FileInfo} the file info
- */
-export default async function(path) {
- // getDirectoryContents doesn't accept / for root
- const fixedPath = path === '/' ? '' : path
-
- // fetch listing
- const response = await client.stat(prefixPath + fixedPath, {
- data: request,
- details: true,
- })
-
- return genFileInfo(response.data)
-}
+export const davClient: WebDAVClient = davGetClient()
diff --git a/src/services/DavRequest.js b/src/services/DavRequest.ts
similarity index 55%
rename from src/services/DavRequest.js
rename to src/services/DavRequest.ts
index 28428db2e..987ac1394 100644
--- a/src/services/DavRequest.js
+++ b/src/services/DavRequest.ts
@@ -2,6 +2,7 @@
* @copyright Copyright (c) 2019 John Molakvoæ
*
* @author John Molakvoæ
+ * @author Ferdinand Thiessen
*
* @license AGPL-3.0-or-later
*
@@ -19,34 +20,48 @@
* along with this program. If not, see .
*
*/
-const props = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`
-export { props }
-export default `
+import { getDavProperties, registerDavProperty } from '@nextcloud/files'
+
+const photoDavProps = [
+ 'face-detections',
+ 'face-preview-image',
+ 'metadata-photos-size',
+ 'metadata-photos-original_date_time',
+ 'metadata-files-live-photo',
+ 'metadata-blurhash',
+ 'realpath',
+ 'nbItems',
+]
+
+/**
+ * Used to cache the props
+ */
+let props: string|null = null
+
+/**
+ * Get the default props
+ */
+const getDefaultDavProps = () => {
+ if (props === null) {
+ photoDavProps.forEach(prop => registerDavProperty(prop))
+ props = getDavProperties()
+ }
+ return props
+}
+
+/**
+ * @param extraProps - Extra properties to add to the DAV request.
+ */
+export function getPropFind(extraProps: string[] = []): string {
+ return `
- ${props}
+ ${getDefaultDavProps()}
+ ${extraProps.join('\n')}
`
+}
diff --git a/src/services/FolderInfo.js b/src/services/FolderInfo.js
deleted file mode 100644
index 9cf94c76a..000000000
--- a/src/services/FolderInfo.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @copyright Copyright (c) 2019 John Molakvoæ
- *
- * @author John Molakvoæ
- *
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- *
- */
-
-import client, { prefixPath } from './DavClient.js'
-import request from './DavRequest.js'
-import { genFileInfo } from '../utils/fileUtils.js'
-
-/**
- * List files from a folder and filter out unwanted mimes
- *
- * @param {string} path the path relative to the user root
- * @return {Array} the file list
- */
-export default async function(path) {
- // getDirectoryContents doesn't accept / for root
- const fixedPath = path === '/' ? '' : path
-
- // fetch listing
- const response = await client.stat(prefixPath + fixedPath, {
- data: request,
- details: true,
- })
-
- return genFileInfo(response.data)
-}
diff --git a/src/services/PhotoSearch.js b/src/services/PhotoSearch.js
index 435297da1..e82eef872 100644
--- a/src/services/PhotoSearch.js
+++ b/src/services/PhotoSearch.js
@@ -20,14 +20,15 @@
*
*/
-import { genFileInfo } from '../utils/fileUtils.js'
-import { getCurrentUser } from '@nextcloud/auth'
-import { allMimes } from './AllowedMimes.js'
-import client from './DavClient.js'
-import { props } from './DavRequest.js'
import moment from '@nextcloud/moment'
import store from '../store/index.js'
+import { allMimes } from './AllowedMimes.js'
+import { genFileInfo } from '../utils/fileUtils.js'
+import { davProps } from './DavRequest.ts'
+import { davClient } from './DavClient.ts'
+import { davRootPath } from '@nextcloud/files'
+
/**
* List files from a folder and filter out unwanted mimes
*
@@ -51,8 +52,6 @@ export default async function(options = {}) {
...options,
}
- const prefixPath = `/files/${getCurrentUser().uid}`
-
// generating the search or condition
// based on the allowed mimetypes
const orMime = options.mimesType.reduce((str, mime) => `${str}
@@ -119,12 +118,12 @@ export default async function(options = {}) {
- ${props}
+ ${davProps}
- ${prefixPath}/${store.state.userConfig.photosSourceFolder ?? '/Photos'}
+ ${davRootPath}/${store.state.userConfig.photosSourceFolder ?? '/Photos'}
infinity
@@ -157,7 +156,7 @@ export default async function(options = {}) {
details: true,
}, options)
- const response = await client.getDirectoryContents('', options)
+ const response = await davClient.search('/', options)
- return response.data.map(data => genFileInfo(data))
+ return response.data.results.map(data => genFileInfo(data))
}
diff --git a/src/services/SystemTags.js b/src/services/SystemTags.js
index 891d98fc1..0252f7cca 100644
--- a/src/services/SystemTags.js
+++ b/src/services/SystemTags.js
@@ -20,8 +20,8 @@
*
*/
-import client from './DavClient.js'
import { genFileInfo } from '../utils/fileUtils.js'
+import { davClient } from './DavClient.ts'
/**
* List system tags
@@ -31,7 +31,7 @@ import { genFileInfo } from '../utils/fileUtils.js'
* @return {Promise