refactor: viewerManager
parent
156e0fc779
commit
1f0132b097
|
@ -71,8 +71,7 @@
|
|||
:day="item.day"
|
||||
:key="photo.fileid"
|
||||
@select="selectionManager.selectPhoto"
|
||||
@delete="deleteFromViewWithAnimation"
|
||||
@clickImg="clickPhoto" />
|
||||
@click="clickPhoto(photo)" />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
@ -103,6 +102,7 @@ import { NcEmptyContent } from '@nextcloud/vue';
|
|||
import GlobalMixin from '../mixins/GlobalMixin';
|
||||
import moment from 'moment';
|
||||
|
||||
import { ViewerManager } from "../services/Viewer";
|
||||
import * as dav from "../services/DavRequests";
|
||||
import * as utils from "../services/Utils";
|
||||
import justifiedLayout from "justified-layout";
|
||||
|
@ -179,6 +179,11 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
|||
/** Scroller manager component */
|
||||
private scrollerManager!: ScrollerManager & any;
|
||||
|
||||
/** Nextcloud viewer proxy */
|
||||
private viewerManager = new ViewerManager(
|
||||
this.deleteFromViewWithAnimation.bind(this),
|
||||
this.updateLoading.bind(this));
|
||||
|
||||
mounted() {
|
||||
this.selectionManager = this.$refs.selectionManager;
|
||||
this.scrollerManager = this.$refs.scrollerManager;
|
||||
|
@ -893,11 +898,13 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
|||
}
|
||||
|
||||
/** Clicking on photo */
|
||||
clickPhoto(photoComponent: any) {
|
||||
clickPhoto(photo: IPhoto) {
|
||||
if (photo.flag & this.c.FLAG_PLACEHOLDER) return;
|
||||
|
||||
if (this.selection.size > 0) { // selection mode
|
||||
photoComponent.toggleSelect();
|
||||
this.selectionManager.selectPhoto(photo);
|
||||
} else {
|
||||
photoComponent.openFile();
|
||||
this.viewerManager.open(photo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<Star :size="20" v-if="data.flag & c.FLAG_IS_FAVORITE" />
|
||||
|
||||
<div class="img-outer fill-block"
|
||||
@click="click"
|
||||
@click="emitClick"
|
||||
@contextmenu="contextmenu"
|
||||
@touchstart="touchstart"
|
||||
@touchmove="touchend"
|
||||
|
@ -33,11 +33,8 @@
|
|||
<script lang="ts">
|
||||
import { Component, Prop, Emit, Mixins } from 'vue-property-decorator';
|
||||
import { IDay, IPhoto } from "../../types";
|
||||
import { subscribe, unsubscribe } from '@nextcloud/event-bus';
|
||||
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { getPreviewUrl } from "../../services/FileUtils";
|
||||
import * as dav from "../../services/DavRequests";
|
||||
import errorsvg from "../../assets/error.svg";
|
||||
import GlobalMixin from '../../mixins/GlobalMixin';
|
||||
|
||||
|
@ -58,9 +55,8 @@ export default class Photo extends Mixins(GlobalMixin) {
|
|||
@Prop() data: IPhoto;
|
||||
@Prop() day: IDay;
|
||||
|
||||
@Emit('delete') emitDelete(remPhotos: IPhoto[]) {}
|
||||
@Emit('select') emitSelect(data: IPhoto) {}
|
||||
@Emit('clickImg') emitClickImg(component: any) {}
|
||||
@Emit('click') emitClick() {}
|
||||
|
||||
/** Get src for image to show */
|
||||
src() {
|
||||
|
@ -92,88 +88,8 @@ export default class Photo extends Mixins(GlobalMixin) {
|
|||
clearTimeout(this.touchTimer);
|
||||
}
|
||||
|
||||
/** Pass to parent */
|
||||
click() {
|
||||
this.emitClickImg(this);
|
||||
}
|
||||
|
||||
/** Open viewer */
|
||||
async openFile() {
|
||||
// Check if this is a placeholder
|
||||
if (this.data.flag & this.c.FLAG_PLACEHOLDER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if already loaded fileInfos or load
|
||||
let fileInfos = this.day.fileInfos;
|
||||
if (!fileInfos) {
|
||||
const ids = this.day.detail.map(p => p.fileid);
|
||||
try {
|
||||
fileInfos = await dav.getFiles(ids);
|
||||
} catch (e) {
|
||||
console.error('Failed to load fileInfos', e);
|
||||
}
|
||||
if (fileInfos.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fix sorting of the fileInfos
|
||||
const itemPositions = {};
|
||||
for (const [index, id] of ids.entries()) {
|
||||
itemPositions[id] = index;
|
||||
}
|
||||
fileInfos.sort(function (a, b) {
|
||||
return itemPositions[a.fileid] - itemPositions[b.fileid];
|
||||
});
|
||||
|
||||
// Store in day with a original copy
|
||||
this.day.fileInfos = fileInfos;
|
||||
this.day.origFileIds = new Set(fileInfos.map(f => f.fileid));
|
||||
}
|
||||
|
||||
// Get this photo in the fileInfos
|
||||
const photo = fileInfos.find(d => Number(d.fileid) === Number(this.data.fileid));
|
||||
if (!photo) {
|
||||
showError(this.t('memories', 'Cannot find this photo anymore!'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Key to store sidebar state
|
||||
const SIDEBAR_KEY = 'memories:sidebar-open';
|
||||
|
||||
// Subscribe to delete events
|
||||
const deleteHandler = ({ fileid }) => {
|
||||
const photo = this.day.detail.find(p => p.fileid === fileid);
|
||||
this.emitDelete([photo]);
|
||||
};
|
||||
subscribe('files:file:deleted', deleteHandler);
|
||||
|
||||
// Open viewer
|
||||
globalThis.OCA.Viewer.open({
|
||||
path: photo.filename, // path
|
||||
list: fileInfos, // file list
|
||||
canLoop: false, // don't loop
|
||||
onClose: () => { // on viewer close
|
||||
if (globalThis.OCA.Files.Sidebar.file) {
|
||||
localStorage.setItem(SIDEBAR_KEY, '1');
|
||||
} else {
|
||||
localStorage.removeItem(SIDEBAR_KEY);
|
||||
}
|
||||
globalThis.OCA.Files.Sidebar.close();
|
||||
unsubscribe('files:file:deleted', deleteHandler);
|
||||
},
|
||||
});
|
||||
|
||||
// Restore sidebar state
|
||||
if (localStorage.getItem(SIDEBAR_KEY) === '1') {
|
||||
globalThis.OCA.Files.Sidebar.open(photo.filename);
|
||||
}
|
||||
}
|
||||
|
||||
toggleSelect() {
|
||||
if (this.data.flag & this.c.FLAG_PLACEHOLDER) {
|
||||
return;
|
||||
}
|
||||
if (this.data.flag & this.c.FLAG_PLACEHOLDER) return;
|
||||
this.emitSelect(this.data);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
import { IFileInfo, IPhoto } from "../types";
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { subscribe } from '@nextcloud/event-bus';
|
||||
import { translate as t, translatePlural as n } from '@nextcloud/l10n'
|
||||
import * as dav from "./DavRequests";
|
||||
|
||||
// Key to store sidebar state
|
||||
const SIDEBAR_KEY = 'memories:sidebar-open';
|
||||
|
||||
export class ViewerManager {
|
||||
/** Map from fileid to Photo */
|
||||
private photoMap = new Map<number, IPhoto>();
|
||||
|
||||
constructor(
|
||||
ondelete: (photos: IPhoto[]) => void,
|
||||
private updateLoading: (delta: number) => void,
|
||||
) {
|
||||
subscribe('files:file:deleted', ({ fileid }: { fileid: number }) => {
|
||||
const photo = this.photoMap.get(fileid);
|
||||
ondelete([photo]);
|
||||
});
|
||||
}
|
||||
|
||||
public async open(photo: IPhoto) {
|
||||
const day = photo.d;
|
||||
if (!day) return;
|
||||
|
||||
// Repopulate map
|
||||
this.photoMap.clear();
|
||||
for (const p of day.detail) {
|
||||
this.photoMap.set(p.fileid, p);
|
||||
}
|
||||
|
||||
// Get file infos
|
||||
let fileInfos: IFileInfo[];
|
||||
const ids = day.detail.map(p => p.fileid);
|
||||
try {
|
||||
this.updateLoading(1);
|
||||
fileInfos = await dav.getFiles(ids);
|
||||
} catch (e) {
|
||||
console.error('Failed to load fileInfos', e);
|
||||
showError('Failed to load fileInfos');
|
||||
return;
|
||||
} finally {
|
||||
this.updateLoading(-1);
|
||||
}
|
||||
if (fileInfos.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fix sorting of the fileInfos
|
||||
const itemPositions = {};
|
||||
for (const [index, id] of ids.entries()) {
|
||||
itemPositions[id] = index;
|
||||
}
|
||||
fileInfos.sort(function (a, b) {
|
||||
return itemPositions[a.fileid] - itemPositions[b.fileid];
|
||||
});
|
||||
|
||||
// Get this photo in the fileInfos
|
||||
const fInfo = fileInfos.find(d => Number(d.fileid) === photo.fileid);
|
||||
if (!fInfo) {
|
||||
showError(t('memories', 'Cannot find this photo anymore!'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Open Nextcloud viewer
|
||||
globalThis.OCA.Viewer.open({
|
||||
path: fInfo.filename, // path
|
||||
list: fileInfos, // file list
|
||||
canLoop: false, // don't loop
|
||||
onClose: () => { // on viewer close
|
||||
if (globalThis.OCA.Files.Sidebar.file) {
|
||||
localStorage.setItem(SIDEBAR_KEY, '1');
|
||||
} else {
|
||||
localStorage.removeItem(SIDEBAR_KEY);
|
||||
}
|
||||
globalThis.OCA.Files.Sidebar.close();
|
||||
},
|
||||
});
|
||||
|
||||
// Restore sidebar state
|
||||
if (localStorage.getItem(SIDEBAR_KEY) === '1') {
|
||||
globalThis.OCA.Files.Sidebar.open(fInfo.filename);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,10 +24,6 @@ export type IDay = {
|
|||
rows?: IRow[];
|
||||
/** List of photos for this day */
|
||||
detail?: IPhoto[];
|
||||
/** WebDAV fileInfos, fetched before viewer open */
|
||||
fileInfos?: IFileInfo[];
|
||||
/** Original fileIds from fileInfos */
|
||||
origFileIds?: Set<number>;
|
||||
}
|
||||
|
||||
export type IPhoto = {
|
||||
|
|
Loading…
Reference in New Issue