Skip to content

Commit

Permalink
feat: Allow multiple source folders
Browse files Browse the repository at this point in the history
Signed-off-by: Louis Chemineau <louis@chmn.me>
  • Loading branch information
artonge committed Apr 8, 2024
1 parent 16d6cda commit e6394bd
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 39 deletions.
3 changes: 2 additions & 1 deletion lib/Service/UserConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class UserConfigService {
public const DEFAULT_CONFIGS = [
'croppedLayout' => 'false',
'photosLocation' => '/Photos',
'photosSourceFolder' => '/Photos',
// TODO: add migration to retrieve value in photosSourceFolders
'photosSourceFolders' => '["/Photos"]',
];

private IConfig $config;
Expand Down
37 changes: 17 additions & 20 deletions src/components/Settings/PhotosSourceLocationsSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,22 @@
<template>
<div class="photos-locations-container">
<div class="photos-locations">
<PhotosFolder :path="photosSourceFolder" :root-folder-label="t('photos', 'All folders')" :root-folder-icon="FolderMultiple" />
<!-- TODO: uncomment when SEARCH on multiple folders is implemented. -->
<!-- <li v-for="(source, index) in photosSourceFolder"
<li v-for="(source, index) in photosSourceFolders"
:key="index">
<PhotosFolder :path="source"
:can-delete="photosSourceFolder.length !== 1"
:can-delete="photosSourceFolders.length !== 1"
:root-folder-label="t('photos', 'All folders')"
:root-folder-icon="FolderMultiple"
@remove-folder="removeSourceFolder(index)" />
</li> -->
</li>
</div>

<NcButton :aria-label="t('photos', 'Choose a Photos source for the timelines')"
<NcButton :aria-label="t('photos', 'Add a Photos source for the timelines')"
@click="debounceAddSourceFolder">
<!-- TODO: uncomment when SEARCH on multiple folders is implemented. -->
<!-- <template #icon>
<template #icon>
<Plus :size="20" />
</template> -->
{{ t('photos', 'Choose a different folder') }}
</template>
{{ t('photos', 'Add folder') }}
</NcButton>
</div>
</template>
Expand Down Expand Up @@ -72,9 +70,9 @@ export default defineComponent({
},
computed: {
/** @return {string} */
photosSourceFolder() {
return this.$store.state.userConfig.photosSourceFolder
/** @return {string[]} */
photosSourceFolders() {
return this.$store.state.userConfig.photosSourceFolders
},
},
Expand All @@ -97,17 +95,16 @@ export default defineComponent({
async addSourceFolder() {
const pickedFolder = await this.openFilePicker(t('photos', 'Select a source folder for your media'))
// TODO: uncomment when SEARCH on multiple folders is implemented.
// if (this.photosSourceFolder.includes(pickedFolder)) {
// return
// }
this.$store.dispatch('updateUserConfig', { key: 'photosSourceFolder', value: pickedFolder })
if (this.photosSourceFolders.includes(pickedFolder)) {
return
}
this.$store.dispatch('updateUserConfig', { key: 'photosSourceFolders', value: [...this.photosSourceFolders, pickedFolder] })
},
removeSourceFolder(index) {
const folders = [...this.photosSourceFolder]
const folders = [...this.photosSourceFolders]
folders.splice(index, 1)
this.$store.dispatch('updateUserConfig', { key: 'photosSourceFolder', value: folders })
this.$store.dispatch('updateUserConfig', { key: 'photosSourceFolders', value: folders })
},
t,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Settings/SettingsDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<CroppedLayoutSettings />
</NcAppSettingsSection>

<NcAppSettingsSection id="source-directories-settings" :name="t('photos', 'Media folder')">
<NcAppSettingsSection id="source-directories-settings" :name="t('photos', 'Media folders')">
<div class="setting-section-subline">
{{ t('photos', 'Choose the folders from where photos and videos are shown.') }}
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/mixins/FetchFilesMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export default {
} catch (error) {
if (error.response?.status === 404) {
this.errorFetchingFiles = 404
const source = joinPaths(davRootPath, store.state.userConfig.photosSourceFolder ?? '/Photos') + '/'
// TODO improve error handling
const source = joinPaths(davRootPath, store.state.userConfig.photosSourceFolders ?? ['/Photos']) + '/'
logger.debug('Photo source does not exist, creating it.')
try {
await davGetClient().createDirectory(source)
Expand Down
23 changes: 10 additions & 13 deletions src/services/PhotoSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import client from './DavClient.js'
import { props } from './DavRequest.js'
import moment from '@nextcloud/moment'
import store from '../store/index.js'
import { davRootPath } from '@nextcloud/files'

/**
* List files from a folder and filter out unwanted mimes
Expand Down Expand Up @@ -95,15 +96,14 @@ export default async function(options = {}) {
}).join('\n')}</d:or>`
: ''

// TODO: uncomment when SEARCH on multiple folders is implemented.
// const sourceFolders = store.state.userConfig.photosSourceFolder
// .map(folder => `
// <d:scope>
// <d:href>${davRootPath}/${folder}</d:href>
// <d:depth>infinity</d:depth>
// </d:scope>
// `)
// .join('\n')
const sourceFolders = store.state.userConfig.photosSourceFolders
.map(folder => `
<d:scope>
<d:href>${davRootPath}/${folder}</d:href>
<d:depth>infinity</d:depth>
</d:scope>`
)
.join('\n')

options = Object.assign({
method: 'SEARCH',
Expand All @@ -123,10 +123,7 @@ export default async function(options = {}) {
</d:prop>
</d:select>
<d:from>
<d:scope>
<d:href>${prefixPath}/${store.state.userConfig.photosSourceFolder ?? '/Photos'}</d:href>
<d:depth>infinity</d:depth>
</d:scope>
${sourceFolders}
</d:from>
<d:where>
<d:and>
Expand Down
4 changes: 2 additions & 2 deletions src/store/userConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export async function getFolder(path) {
/**
* @typedef {object} UserConfigState
* @property {boolean} croppedLayout
* @property {string} photosSourceFolder
* @property {string[]} photosSourceFolders
* @property {string} photosLocation
* @property {import('@nextcloud/files').Folder} [photosLocationFolder]
*/
Expand All @@ -68,7 +68,7 @@ const module = {
state() {
return {
croppedLayout: loadState('photos', 'croppedLayout', 'false') === 'true',
photosSourceFolder: loadState('photos', 'photosSourceFolder', ''),
photosSourceFolders: loadState('photos', 'photosSourceFolders', ''),
photosLocation: loadState('photos', 'photosLocation', ''),
photosLocationFolder: undefined,
}
Expand Down
2 changes: 1 addition & 1 deletion src/views/Timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ export default {
},
handleUserConfigChange({ key }) {
if (key === 'photosSourceFolder') {
if (key === 'photosSourceFolders') {
this.resetFetchFilesState()
}
},
Expand Down

0 comments on commit e6394bd

Please sign in to comment.