Fix shared album photo viewing

old-stable24^2
Varun Patil 2022-10-28 14:26:56 -07:00
parent a463e82f83
commit f2d61c3e07
7 changed files with 83 additions and 18 deletions

View File

@ -691,6 +691,12 @@ class ApiController extends Controller
{ {
$transforms = []; $transforms = [];
// Add extra information, basename and mimetype
if (!$aggregateOnly && ($fields = $this->request->getParam('fields'))) {
$fields = explode(',', $fields);
$transforms[] = [$this->timelineQuery, 'transformExtraFields', $fields];
}
// Filter only favorites // Filter only favorites
if ($this->request->getParam('fav')) { if ($this->request->getParam('fav')) {
$transforms[] = [$this->timelineQuery, 'transformFavoriteFilter']; $transforms[] = [$this->timelineQuery, 'transformFavoriteFilter'];

View File

@ -43,6 +43,18 @@ class TimelineQuery
return $sql; return $sql;
} }
public function transformExtraFields(IQueryBuilder &$query, string $uid, array &$fields)
{
if (\in_array('basename', $fields, true)) {
$query->addSelect('f.name AS basename');
}
if (\in_array('mimetype', $fields, true)) {
$query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id'));
$query->addSelect('mimetypes.mimetype');
}
}
public function getInfoById(int $id): array public function getInfoById(int $id): array
{ {
$qb = $this->connection->getQueryBuilder(); $qb = $this->connection->getQueryBuilder();

View File

@ -108,17 +108,17 @@ export default class SelectionHandler extends Mixins(GlobalMixin, UserConfig) {
// Make default actions // Make default actions
this.defaultActions = [ this.defaultActions = [
{
// This is at the top because otherwise it is confusing
name: t("memories", "Remove from album"),
icon: AlbumRemoveIcon,
callback: this.removeFromAlbum.bind(this),
if: () => this.$route.name === "albums",
},
{ {
name: t("memories", "Delete"), name: t("memories", "Delete"),
icon: DeleteIcon, icon: DeleteIcon,
callback: this.deleteSelection.bind(this), callback: this.deleteSelection.bind(this),
if: () => !this.routeIsAlbum(),
},
{
name: t("memories", "Remove from album"),
icon: AlbumRemoveIcon,
callback: this.removeFromAlbum.bind(this),
if: () => this.routeIsAlbum(),
}, },
{ {
name: t("memories", "Download"), name: t("memories", "Download"),
@ -134,7 +134,8 @@ export default class SelectionHandler extends Mixins(GlobalMixin, UserConfig) {
name: t("memories", "Archive"), name: t("memories", "Archive"),
icon: ArchiveIcon, icon: ArchiveIcon,
callback: this.archiveSelection.bind(this), callback: this.archiveSelection.bind(this),
if: () => this.allowArchive() && !this.routeIsArchive(), if: () =>
this.allowArchive() && !this.routeIsArchive() && !this.routeIsAlbum(),
}, },
{ {
name: t("memories", "Unarchive"), name: t("memories", "Unarchive"),
@ -151,13 +152,14 @@ export default class SelectionHandler extends Mixins(GlobalMixin, UserConfig) {
name: t("memories", "View in folder"), name: t("memories", "View in folder"),
icon: OpenInNewIcon, icon: OpenInNewIcon,
callback: this.viewInFolder.bind(this), callback: this.viewInFolder.bind(this),
if: () => this.selection.size === 1, if: () => this.selection.size === 1 && !this.routeIsAlbum(),
}, },
{ {
name: t("memories", "Add to album"), name: t("memories", "Add to album"),
icon: AlbumsIcon, icon: AlbumsIcon,
callback: this.addToAlbum.bind(this), callback: this.addToAlbum.bind(this),
if: (self: any) => self.config_albumsEnabled, if: (self: typeof this) =>
self.config_albumsEnabled && !self.routeIsAlbum(),
}, },
{ {
name: t("memories", "Move to another person"), name: t("memories", "Move to another person"),
@ -402,6 +404,11 @@ export default class SelectionHandler extends Mixins(GlobalMixin, UserConfig) {
return this.$route.name === "archive"; return this.$route.name === "archive";
} }
/** Is album route */
private routeIsAlbum() {
return this.config_albumsEnabled && this.$route.name === "albums";
}
/** /**
* Move selected photos to album * Move selected photos to album
*/ */

View File

@ -219,7 +219,8 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
/** Nextcloud viewer proxy */ /** Nextcloud viewer proxy */
private viewerManager = new ViewerManager( private viewerManager = new ViewerManager(
this.deleteFromViewWithAnimation.bind(this), this.deleteFromViewWithAnimation.bind(this),
this.updateLoading.bind(this) this.updateLoading.bind(this),
this.$route
); );
mounted() { mounted() {
@ -530,6 +531,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
"album", "album",
`${this.$route.params.user}/${this.$route.params.name}` `${this.$route.params.user}/${this.$route.params.name}`
); );
query.set("fields", "basename,mimetype");
} }
// Create query string and append to URL // Create query string and append to URL

View File

@ -2,6 +2,7 @@ import { IFileInfo, IPhoto } from "../types";
import { showError } from "@nextcloud/dialogs"; import { showError } from "@nextcloud/dialogs";
import { subscribe } from "@nextcloud/event-bus"; import { subscribe } from "@nextcloud/event-bus";
import { translate as t, translatePlural as n } from "@nextcloud/l10n"; import { translate as t, translatePlural as n } from "@nextcloud/l10n";
import { Route } from "vue-router";
import * as dav from "./DavRequests"; import * as dav from "./DavRequests";
// Key to store sidebar state // Key to store sidebar state
@ -13,7 +14,8 @@ export class ViewerManager {
constructor( constructor(
ondelete: (photos: IPhoto[]) => void, ondelete: (photos: IPhoto[]) => void,
private updateLoading: (delta: number) => void private updateLoading: (delta: number) => void,
private $route: Route
) { ) {
subscribe("files:file:deleted", ({ fileid }: { fileid: number }) => { subscribe("files:file:deleted", ({ fileid }: { fileid: number }) => {
const photo = this.photoMap.get(fileid); const photo = this.photoMap.get(fileid);
@ -23,7 +25,7 @@ export class ViewerManager {
public async open(photo: IPhoto, list?: IPhoto[]) { public async open(photo: IPhoto, list?: IPhoto[]) {
list = list || photo.d?.detail; list = list || photo.d?.detail;
if (!list) return; if (!list?.length) return;
// Repopulate map // Repopulate map
this.photoMap.clear(); this.photoMap.clear();
@ -36,7 +38,14 @@ export class ViewerManager {
const ids = list.map((p) => p.fileid); const ids = list.map((p) => p.fileid);
try { try {
this.updateLoading(1); this.updateLoading(1);
fileInfos = await dav.getFiles(ids);
if (this.$route.name === "albums") {
const user = this.$route.params.user;
const name = this.$route.params.name;
fileInfos = dav.getAlbumFileInfos(list, user, name);
} else {
fileInfos = await dav.getFiles(ids);
}
} catch (e) { } catch (e) {
console.error("Failed to load fileInfos", e); console.error("Failed to load fileInfos", e);
showError("Failed to load fileInfos"); showError("Failed to load fileInfos");
@ -66,7 +75,7 @@ export class ViewerManager {
// Open Nextcloud viewer // Open Nextcloud viewer
globalThis.OCA.Viewer.open({ globalThis.OCA.Viewer.open({
path: fInfo.filename, // path fileInfo: fInfo,
list: fileInfos, // file list list: fileInfos, // file list
canLoop: false, // don't loop canLoop: false, // don't loop
onClose: () => { onClose: () => {

View File

@ -3,7 +3,7 @@ import { getCurrentUser } from "@nextcloud/auth";
import { generateUrl } from "@nextcloud/router"; import { generateUrl } from "@nextcloud/router";
import { showError } from "@nextcloud/dialogs"; import { showError } from "@nextcloud/dialogs";
import { translate as t, translatePlural as n } from "@nextcloud/l10n"; import { translate as t, translatePlural as n } from "@nextcloud/l10n";
import { IAlbum, IDay, ITag } from "../../types"; import { IAlbum, IDay, IFileInfo, IPhoto, ITag } from "../../types";
import { constants } from "../Utils"; import { constants } from "../Utils";
import axios from "@nextcloud/axios"; import axios from "@nextcloud/axios";
import client from "../DavClient"; import client from "../DavClient";
@ -256,3 +256,32 @@ export async function renameAlbum(
return album; return album;
} }
} }
/** Get fileinfo objects from album photos */
export function getAlbumFileInfos(
photos: IPhoto[],
albumUser: string,
albumName: string
): IFileInfo[] {
const uid = getCurrentUser()?.uid;
const collection =
albumUser === uid
? `/photos/${uid}/albums/${albumName}`
: `/photos/${uid}/sharedalbums/${albumName} (${albumUser})`;
return photos.map((photo) => {
const basename =
albumUser === uid
? `${photo.fileid}-${(<any>photo).basename}`
: `${photo.fileid}-${albumName} (${albumUser})`;
return {
fileid: photo.fileid,
filename: `${collection}/${basename}`,
basename: basename,
mime: (<any>photo).mimetype,
hasPreview: true,
etag: photo.etag,
};
});
}

View File

@ -6,7 +6,7 @@ export type IFileInfo = {
/** Full file name, e.g. /pi/test/Qx0dq7dvEXA.jpg */ /** Full file name, e.g. /pi/test/Qx0dq7dvEXA.jpg */
filename: string; filename: string;
/** Original file name, e.g. /files/admin/pi/test/Qx0dq7dvEXA.jpg */ /** Original file name, e.g. /files/admin/pi/test/Qx0dq7dvEXA.jpg */
originalFilename: string; originalFilename?: string;
/** Base name of file e.g. Qx0dq7dvEXA.jpg */ /** Base name of file e.g. Qx0dq7dvEXA.jpg */
basename: string; basename: string;
/** Etag identifier */ /** Etag identifier */
@ -14,7 +14,7 @@ export type IFileInfo = {
/** File has preview available */ /** File has preview available */
hasPreview: boolean; hasPreview: boolean;
/** File is marked favorite */ /** File is marked favorite */
favorite: boolean; favorite?: boolean;
/** Vue flags */ /** Vue flags */
flag?: number; flag?: number;
}; };