sel: add fragment (fix #861)

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/888/head
Varun Patil 2023-10-24 01:07:00 -07:00
parent 8eefae4247
commit 937feff286
7 changed files with 40 additions and 29 deletions

View File

@ -77,7 +77,6 @@ const NcAppNavigationItem = () => import('@nextcloud/vue/dist/Components/NcAppNa
import { generateUrl } from '@nextcloud/router'; import { generateUrl } from '@nextcloud/router';
import { translate as t } from '@nextcloud/l10n'; import { translate as t } from '@nextcloud/l10n';
import fragment from './services/fragment';
import * as utils from './services/utils'; import * as utils from './services/utils';
import * as nativex from './native'; import * as nativex from './native';
import staticConfig from './services/static-config'; import staticConfig from './services/static-config';
@ -163,8 +162,7 @@ export default defineComponent({
watch: { watch: {
async $route(to: Route, from: Route) { async $route(to: Route, from: Route) {
// Global triggers utils.fragment.changeTrigger(to, from);
fragment.changeTrigger(to, from);
}, },
}, },

View File

@ -2,7 +2,7 @@
<div> <div>
<div v-if="show" class="top-bar"> <div v-if="show" class="top-bar">
<NcActions :inline="1"> <NcActions :inline="1">
<NcActionButton :aria-label="t('memories', 'Cancel')" @click="clearSelection()"> <NcActionButton :aria-label="t('memories', 'Cancel')" @click="clear()">
{{ t('memories', 'Cancel') }} {{ t('memories', 'Cancel') }}
<template #icon> <CloseIcon :size="20" /> </template> <template #icon> <CloseIcon :size="20" /> </template>
</NcActionButton> </NcActionButton>
@ -270,19 +270,22 @@ export default defineComponent({
} }
// Subscribe to global events // 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() { beforeDestroy() {
this.setHasTopBar(false); this.setHasTopBar(false);
// Unsubscribe from global events // 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: { watch: {
show(value: boolean) { show(value: boolean, from: boolean) {
this.setHasTopBar(value); this.setHasTopBar(value);
utils.fragment.if(value, utils.fragment.types.selection);
}, },
}, },
@ -701,10 +704,14 @@ export default defineComponent({
}, },
/** Clear all selected photos */ /** 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<IHeadRow>(); const heads = new Set<IHeadRow>();
const toClear = only || this.selection.values(); photos.forEach((photo: IPhoto) => {
Array.from(toClear).forEach((photo: IPhoto) => {
photo.flag &= ~this.c.FLAG_SELECTED; photo.flag &= ~this.c.FLAG_SELECTED;
heads.add(this.heads[photo.dayid]); heads.add(this.heads[photo.dayid]);
this.selection.deleteBy(photo); this.selection.deleteBy(photo);
@ -766,7 +773,7 @@ export default defineComponent({
for await (const ids of dav.favoritePhotos(selection.photosNoDupFileId(), val)) { for await (const ids of dav.favoritePhotos(selection.photosNoDupFileId(), val)) {
selection.photosFromFileIds(ids).forEach((photo) => dav.favoriteSetFlag(photo, val)); selection.photosFromFileIds(ids).forEach((photo) => dav.favoriteSetFlag(photo, val));
} }
this.clearSelection(); this.clear();
}, },
/** /**

View File

@ -108,7 +108,6 @@ import EmptyContent from './top-matter/EmptyContent.vue';
import TopMatter from './top-matter/TopMatter.vue'; import TopMatter from './top-matter/TopMatter.vue';
import DynamicTopMatter from './top-matter/DynamicTopMatter.vue'; import DynamicTopMatter from './top-matter/DynamicTopMatter.vue';
import fragment from '../services/fragment';
import * as dav from '../services/dav'; import * as dav from '../services/dav';
import * as utils from '../services/utils'; import * as utils from '../services/utils';
import * as nativex from '../native'; import * as nativex from '../native';
@ -267,9 +266,9 @@ export default defineComponent({
} }
// Check if viewer is supposed to be open // 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 // Open viewer
const [dayidStr, key] = fragment.viewer.args; const [dayidStr, key] = utils.fragment.viewer.args;
const dayid = parseInt(dayidStr); const dayid = parseInt(dayidStr);
if (isNaN(dayid) || !key) return; if (isNaN(dayid) || !key) return;
@ -330,7 +329,7 @@ export default defineComponent({
/** Reset all state */ /** Reset all state */
async resetState() { async resetState() {
this.refs.selectionManager.clearSelection(); this.refs.selectionManager.clear();
this.refs.scrollerManager.reset(); this.refs.scrollerManager.reset();
this.loading = 0; this.loading = 0;
this.list = []; this.list = [];
@ -366,7 +365,7 @@ export default defineComponent({
* Do not pass this function as a callback directly. * Do not pass this function as a callback directly.
*/ */
async softRefreshInternal(sync: boolean) { async softRefreshInternal(sync: boolean) {
this.refs.selectionManager.clearSelection(); this.refs.selectionManager.clear();
this.fetchDayQueue = []; // reset queue this.fetchDayQueue = []; // reset queue
// Fetch days // Fetch days
@ -1301,7 +1300,7 @@ export default defineComponent({
await new Promise((resolve) => setTimeout(resolve, 200)); await new Promise((resolve) => setTimeout(resolve, 200));
// clear selection at this point // clear selection at this point
this.refs.selectionManager.clearSelection(delPhotos); this.refs.selectionManager.deselect(delPhotos);
// Reflow all touched days // Reflow all touched days
for (const day of updatedDays) { for (const day of updatedDays) {

View File

@ -183,7 +183,6 @@ import { showError } from '@nextcloud/dialogs';
import axios from '@nextcloud/axios'; import axios from '@nextcloud/axios';
import { API } from '../../services/API'; import { API } from '../../services/API';
import fragment from '../../services/fragment';
import * as dav from '../../services/dav'; import * as dav from '../../services/dav';
import * as utils from '../../services/utils'; import * as utils from '../../services/utils';
import * as nativex from '../../native'; import * as nativex from '../../native';
@ -643,15 +642,12 @@ export default defineComponent({
setFragment(photo: IPhoto | null) { setFragment(photo: IPhoto | null) {
// Add or update fragment // Add or update fragment
if (photo) { if (photo) {
return fragment.push({ return utils.fragment.push(utils.fragment.types.viewer, String(photo.dayid), photo.key!);
type: fragment.types.viewer,
args: [String(photo.dayid), photo.key!],
});
} }
// Remove fragment if closed // Remove fragment if closed
if (!this.isOpen) { if (!this.isOpen) {
return fragment.pop(fragment.types.viewer); return utils.fragment.pop(utils.fragment.types.viewer);
} }
}, },

View File

@ -1,6 +1,6 @@
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'; import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus';
import type { IConfig, IPhoto } from '../../types'; import type { IConfig, IPhoto } from '../../types';
import type { FragmentName, Fragment } from '../fragment'; import type { FragmentName, Fragment } from './fragment';
export type BusEvent = { export type BusEvent = {
/** Open/close the navigation drawer */ /** Open/close the navigation drawer */

View File

@ -1,9 +1,10 @@
import type { Route } from 'vue-router'; import type { Route } from 'vue-router';
import * as utils from './utils'; import { bus } from './event-bus';
/** Mapping of route name to key type */ /** Mapping of route name to key type */
export enum FragmentType { enum FragmentType {
viewer = 'v', viewer = 'v',
selection = 's',
} }
/** Names of fragments */ /** Names of fragments */
@ -52,7 +53,7 @@ const cache = {
list: [] as Fragment[], list: [] as Fragment[],
}; };
export default { export const fragment = {
/** /**
* List of all fragment types. * List of all fragment types.
*/ */
@ -83,7 +84,8 @@ export default {
* Add fragment to route. * Add fragment to route.
* @param frag Fragment to add 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; const list = this.list;
// Get the top fragment // 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() { get viewer() {
return this.get(FragmentType.viewer); return this.get(FragmentType.viewer);
}, },
@ -167,7 +177,7 @@ export default {
for (const [key, type] of Object.entries(FragmentType)) { for (const [key, type] of Object.entries(FragmentType)) {
const name = key as FragmentName; const name = key as FragmentName;
if (type === frag.type) { if (type === frag.type) {
utils.bus.emit(`memories:fragment:pop:${name}`, frag); bus.emit(`memories:fragment:pop:${name}`, frag);
break; break;
} }
} }

View File

@ -5,3 +5,4 @@ export * from './date';
export * from './helpers'; export * from './helpers';
export * from './dialog'; export * from './dialog';
export * from './event-bus'; export * from './event-bus';
export * from './fragment';