diff --git a/src/App.vue b/src/App.vue index 1493d3bf..80d3da6c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -77,7 +77,6 @@ const NcAppNavigationItem = () => import('@nextcloud/vue/dist/Components/NcAppNa import { generateUrl } from '@nextcloud/router'; import { translate as t } from '@nextcloud/l10n'; -import fragment from './services/fragment'; import * as utils from './services/utils'; import * as nativex from './native'; import staticConfig from './services/static-config'; @@ -163,8 +162,7 @@ export default defineComponent({ watch: { async $route(to: Route, from: Route) { - // Global triggers - fragment.changeTrigger(to, from); + utils.fragment.changeTrigger(to, from); }, }, diff --git a/src/components/SelectionManager.vue b/src/components/SelectionManager.vue index 28a0ea7e..cfce9c2d 100644 --- a/src/components/SelectionManager.vue +++ b/src/components/SelectionManager.vue @@ -2,7 +2,7 @@
- + {{ t('memories', 'Cancel') }} @@ -270,19 +270,22 @@ export default defineComponent({ } // Subscribe to global events - utils.bus.on('memories:albums:update', this.clearSelection); + utils.bus.on('memories:albums:update', this.clear); + utils.bus.on('memories:fragment:pop:selection', this.clear); }, beforeDestroy() { this.setHasTopBar(false); // Unsubscribe from global events - utils.bus.off('memories:albums:update', this.clearSelection); + utils.bus.off('memories:albums:update', this.clear); + utils.bus.off('memories:fragment:pop:selection', this.clear); }, watch: { - show(value: boolean) { + show(value: boolean, from: boolean) { this.setHasTopBar(value); + utils.fragment.if(value, utils.fragment.types.selection); }, }, @@ -701,10 +704,14 @@ export default defineComponent({ }, /** Clear all selected photos */ - clearSelection(only?: IPhoto[]) { + clear() { + this.deselect(Array.from(this.selection.values())); + }, + + /** Deslect the given photos */ + deselect(photos: IPhoto[]) { const heads = new Set(); - const toClear = only || this.selection.values(); - Array.from(toClear).forEach((photo: IPhoto) => { + photos.forEach((photo: IPhoto) => { photo.flag &= ~this.c.FLAG_SELECTED; heads.add(this.heads[photo.dayid]); this.selection.deleteBy(photo); @@ -766,7 +773,7 @@ export default defineComponent({ for await (const ids of dav.favoritePhotos(selection.photosNoDupFileId(), val)) { selection.photosFromFileIds(ids).forEach((photo) => dav.favoriteSetFlag(photo, val)); } - this.clearSelection(); + this.clear(); }, /** diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue index 66c9529a..68247ab3 100644 --- a/src/components/Timeline.vue +++ b/src/components/Timeline.vue @@ -108,7 +108,6 @@ import EmptyContent from './top-matter/EmptyContent.vue'; import TopMatter from './top-matter/TopMatter.vue'; import DynamicTopMatter from './top-matter/DynamicTopMatter.vue'; -import fragment from '../services/fragment'; import * as dav from '../services/dav'; import * as utils from '../services/utils'; import * as nativex from '../native'; @@ -267,9 +266,9 @@ export default defineComponent({ } // Check if viewer is supposed to be open - if (from?.hash !== to.hash && !_m.viewer.isOpen && fragment.viewer) { + if (from?.hash !== to.hash && !_m.viewer.isOpen && utils.fragment.viewer) { // Open viewer - const [dayidStr, key] = fragment.viewer.args; + const [dayidStr, key] = utils.fragment.viewer.args; const dayid = parseInt(dayidStr); if (isNaN(dayid) || !key) return; @@ -330,7 +329,7 @@ export default defineComponent({ /** Reset all state */ async resetState() { - this.refs.selectionManager.clearSelection(); + this.refs.selectionManager.clear(); this.refs.scrollerManager.reset(); this.loading = 0; this.list = []; @@ -366,7 +365,7 @@ export default defineComponent({ * Do not pass this function as a callback directly. */ async softRefreshInternal(sync: boolean) { - this.refs.selectionManager.clearSelection(); + this.refs.selectionManager.clear(); this.fetchDayQueue = []; // reset queue // Fetch days @@ -1301,7 +1300,7 @@ export default defineComponent({ await new Promise((resolve) => setTimeout(resolve, 200)); // clear selection at this point - this.refs.selectionManager.clearSelection(delPhotos); + this.refs.selectionManager.deselect(delPhotos); // Reflow all touched days for (const day of updatedDays) { diff --git a/src/components/viewer/Viewer.vue b/src/components/viewer/Viewer.vue index 4d38de62..8126247a 100644 --- a/src/components/viewer/Viewer.vue +++ b/src/components/viewer/Viewer.vue @@ -183,7 +183,6 @@ import { showError } from '@nextcloud/dialogs'; import axios from '@nextcloud/axios'; import { API } from '../../services/API'; -import fragment from '../../services/fragment'; import * as dav from '../../services/dav'; import * as utils from '../../services/utils'; import * as nativex from '../../native'; @@ -643,15 +642,12 @@ export default defineComponent({ setFragment(photo: IPhoto | null) { // Add or update fragment if (photo) { - return fragment.push({ - type: fragment.types.viewer, - args: [String(photo.dayid), photo.key!], - }); + return utils.fragment.push(utils.fragment.types.viewer, String(photo.dayid), photo.key!); } // Remove fragment if closed if (!this.isOpen) { - return fragment.pop(fragment.types.viewer); + return utils.fragment.pop(utils.fragment.types.viewer); } }, diff --git a/src/services/utils/event-bus.ts b/src/services/utils/event-bus.ts index 64f6fa35..a8d9d2ea 100644 --- a/src/services/utils/event-bus.ts +++ b/src/services/utils/event-bus.ts @@ -1,6 +1,6 @@ import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'; import type { IConfig, IPhoto } from '../../types'; -import type { FragmentName, Fragment } from '../fragment'; +import type { FragmentName, Fragment } from './fragment'; export type BusEvent = { /** Open/close the navigation drawer */ diff --git a/src/services/fragment.ts b/src/services/utils/fragment.ts similarity index 90% rename from src/services/fragment.ts rename to src/services/utils/fragment.ts index fa17abf0..58328673 100644 --- a/src/services/fragment.ts +++ b/src/services/utils/fragment.ts @@ -1,9 +1,10 @@ import type { Route } from 'vue-router'; -import * as utils from './utils'; +import { bus } from './event-bus'; /** Mapping of route name to key type */ -export enum FragmentType { +enum FragmentType { viewer = 'v', + selection = 's', } /** Names of fragments */ @@ -52,7 +53,7 @@ const cache = { list: [] as Fragment[], }; -export default { +export const fragment = { /** * List of all fragment types. */ @@ -83,7 +84,8 @@ export default { * Add fragment to route. * @param frag Fragment to add to route */ - push(frag: Fragment) { + push(type: FragmentType, ...args: string[]) { + const frag: Fragment = { type, args }; const list = this.list; // Get the top fragment @@ -147,6 +149,14 @@ export default { } }, + /** + * Sync a fragment with a boolean condition. + */ + if(condition: boolean, type: FragmentType, ...args: string[]) { + if (condition) this.push(type, ...args); + else this.pop(type); + }, + get viewer() { return this.get(FragmentType.viewer); }, @@ -167,7 +177,7 @@ export default { for (const [key, type] of Object.entries(FragmentType)) { const name = key as FragmentName; if (type === frag.type) { - utils.bus.emit(`memories:fragment:pop:${name}`, frag); + bus.emit(`memories:fragment:pop:${name}`, frag); break; } } diff --git a/src/services/utils/index.ts b/src/services/utils/index.ts index 8daff01c..22ea6cd2 100644 --- a/src/services/utils/index.ts +++ b/src/services/utils/index.ts @@ -5,3 +5,4 @@ export * from './date'; export * from './helpers'; export * from './dialog'; export * from './event-bus'; +export * from './fragment';