albums: add list
parent
294b3b8a0c
commit
50bb55536f
|
@ -15,11 +15,24 @@ trait TimelineQueryAlbums
|
|||
$query = $this->connection->getQueryBuilder();
|
||||
|
||||
// SELECT everything from albums
|
||||
$query->select('*')->from('photos_albums', 'pa')->where(
|
||||
$count = $query->func()->count($query->createFunction('DISTINCT m.fileid'), 'count');
|
||||
$query->select('pa.*', $count)->from('photos_albums', 'pa')->where(
|
||||
$query->expr()->eq('user', $query->createNamedParameter($uid)),
|
||||
);
|
||||
|
||||
// WHERE there are items with this tag
|
||||
$query->innerJoin('pa', 'photos_albums_files', 'paf', $query->expr()->andX(
|
||||
$query->expr()->eq('paf.album_id', 'pa.album_id'),
|
||||
));
|
||||
|
||||
// WHERE these items are memories indexed photos
|
||||
$query->innerJoin('paf', 'memories', 'm', $query->expr()->eq('m.fileid', 'paf.file_id'));
|
||||
|
||||
// WHERE these photos are in the filecache
|
||||
$query->innerJoin('m', 'filecache', 'f', $query->expr()->eq('m.fileid', 'f.fileid'),);
|
||||
|
||||
// GROUP and ORDER by
|
||||
$query->groupBy('pa.album_id');
|
||||
$query->orderBy('pa.created', 'DESC');
|
||||
$query->addOrderBy('pa.album_id', 'DESC'); // tie-breaker
|
||||
|
||||
|
@ -28,8 +41,8 @@ trait TimelineQueryAlbums
|
|||
|
||||
// Post process
|
||||
foreach ($albums as &$row) {
|
||||
$row['album_id'] = (int) $row['id'];
|
||||
$row['created'] = (int) $row['count'];
|
||||
$row['album_id'] = (int) $row['album_id'];
|
||||
$row['created'] = (int) $row['created'];
|
||||
$row['last_added_photo'] = (int) $row['last_added_photo'];
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
{{ item.super }}
|
||||
</div>
|
||||
<div class="main" @click="selectionManager.selectHead(item)">
|
||||
<CheckCircle :size="18" class="select" />
|
||||
<CheckCircle :size="18" class="select" v-if="item.name" />
|
||||
<span class="name" > {{ item.name || getHeadName(item) }} </span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -516,9 +516,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
|||
}
|
||||
|
||||
// Special headers
|
||||
if (head.dayId === this.TagDayID.FOLDERS) {
|
||||
return (head.name = this.t("memories", "Folders"));
|
||||
} else if (head.dayId === this.TagDayID.TAGS || head.dayId === this.TagDayID.FACES) {
|
||||
if (this.TagDayIDValueSet.has(head.dayId)) {
|
||||
return (head.name = "");
|
||||
}
|
||||
|
||||
|
@ -637,8 +635,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
|||
};
|
||||
|
||||
// Special headers
|
||||
if (day.dayid === this.TagDayID.TAGS ||
|
||||
day.dayid === this.TagDayID.FACES) {
|
||||
if (this.TagDayIDValueSet.has(day.dayid)) {
|
||||
head.size = 10;
|
||||
} else if (this.$route.name === 'thisday' && (!prevDay || Math.abs(prevDay.dayid - day.dayid) > 30)) {
|
||||
// thisday view with new year title
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Watch, Mixins, Emit } from 'vue-property-decorator';
|
||||
import { IPhoto, ITag } from '../../types';
|
||||
import { IAlbum, IPhoto, ITag } from '../../types';
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { getPreviewUrl } from "../../services/FileUtils";
|
||||
|
||||
|
@ -77,6 +77,10 @@ export default class Tag extends Mixins(GlobalMixin) {
|
|||
return this.data.flag & constants.c.FLAG_IS_FACE;
|
||||
}
|
||||
|
||||
get isAlbum() {
|
||||
return this.data.flag & constants.c.FLAG_IS_ALBUM;
|
||||
}
|
||||
|
||||
async refreshPreviews() {
|
||||
// Reset state
|
||||
this.error = false;
|
||||
|
@ -87,6 +91,13 @@ export default class Tag extends Mixins(GlobalMixin) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Add preview from last photo if album
|
||||
if (this.isAlbum) {
|
||||
const album = this.data as IAlbum;
|
||||
this.previews = [{ fileid: album.last_added_photo, etag: '', flag: 0 }];
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for previews
|
||||
if (!this.data.previews) return;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { encodePath } from '@nextcloud/paths'
|
|||
import { showError } from '@nextcloud/dialogs'
|
||||
import { translate as t, translatePlural as n } from '@nextcloud/l10n'
|
||||
import { genFileInfo } from './FileUtils'
|
||||
import { IDay, IFileInfo, IPhoto, ITag } from '../types';
|
||||
import { IAlbum, IDay, IFileInfo, IPhoto, ITag } from '../types';
|
||||
import { constants, hashCode } from './Utils';
|
||||
import axios from '@nextcloud/axios'
|
||||
import client from './DavClient';
|
||||
|
@ -557,5 +557,24 @@ export async function* removeFaceImages(user: string, name: string, fileIds: num
|
|||
* Get list of albums and convert to Days response
|
||||
*/
|
||||
export async function getAlbumsData(): Promise<IDay[]> {
|
||||
return [];
|
||||
let data: IAlbum[] = [];
|
||||
try {
|
||||
const res = await axios.get<typeof data>(generateUrl('/apps/memories/api/albums'));
|
||||
data = res.data;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Convert to days response
|
||||
return [{
|
||||
dayid: constants.TagDayID.ALBUMS,
|
||||
count: data.length,
|
||||
detail: data.map((album) => ({
|
||||
...album,
|
||||
fileid: album.album_id,
|
||||
flag: constants.c.FLAG_IS_TAG & constants.c.FLAG_IS_ALBUM,
|
||||
istag: true,
|
||||
isalbum: true,
|
||||
} as ITag)),
|
||||
}]
|
||||
}
|
|
@ -173,6 +173,10 @@ export function convertFlags(photo: IPhoto) {
|
|||
photo.flag |= constants.c.FLAG_IS_TAG;
|
||||
delete photo.istag;
|
||||
}
|
||||
if (photo.isalbum) {
|
||||
photo.flag |= constants.c.FLAG_IS_ALBUM;
|
||||
delete photo.isalbum;
|
||||
}
|
||||
}
|
||||
|
||||
// Outside for set
|
||||
|
@ -181,6 +185,7 @@ const TagDayID = {
|
|||
FOLDERS: -(1 << 30) + 1,
|
||||
TAGS: -(1 << 30) + 2,
|
||||
FACES: -(1 << 30) + 3,
|
||||
ALBUMS: -(1 << 30) + 4,
|
||||
}
|
||||
|
||||
/** Global constants */
|
||||
|
@ -193,8 +198,9 @@ export const constants = {
|
|||
FLAG_IS_FOLDER: 1 << 4,
|
||||
FLAG_IS_TAG: 1 << 5,
|
||||
FLAG_IS_FACE: 1 << 6,
|
||||
FLAG_SELECTED: 1 << 7,
|
||||
FLAG_LEAVING: 1 << 8,
|
||||
FLAG_IS_ALBUM: 1 << 7,
|
||||
FLAG_SELECTED: 1 << 8,
|
||||
FLAG_LEAVING: 1 << 9,
|
||||
},
|
||||
|
||||
TagDayID: TagDayID,
|
||||
|
|
15
src/types.ts
15
src/types.ts
|
@ -67,6 +67,8 @@ export type IPhoto = {
|
|||
isfolder?: boolean;
|
||||
/** Is this a tag */
|
||||
istag?: boolean;
|
||||
/** Is this an album */
|
||||
isalbum?: boolean;
|
||||
/** Is this a face */
|
||||
isface?: boolean;
|
||||
/** Optional datetaken epoch */
|
||||
|
@ -93,6 +95,19 @@ export interface ITag extends IPhoto {
|
|||
previews?: IPhoto[];
|
||||
}
|
||||
|
||||
export interface IAlbum extends ITag {
|
||||
/** ID of album */
|
||||
album_id: number;
|
||||
/** Owner of album */
|
||||
user: string;
|
||||
/** Created timestamp */
|
||||
created: number;
|
||||
/** Location string */
|
||||
location: string;
|
||||
/** File ID of last added photo */
|
||||
last_added_photo: number;
|
||||
}
|
||||
|
||||
export interface IFaceRect {
|
||||
w: number;
|
||||
h: number;
|
||||
|
|
Loading…
Reference in New Issue