2023-05-03 11:10:31 +00:00
|
|
|
<template>
|
2023-05-03 18:18:30 +00:00
|
|
|
<div class="explore-outer hide-scrollbar">
|
2023-05-03 18:25:58 +00:00
|
|
|
<XLoadingIcon v-if="loading" class="fill-block" />
|
|
|
|
|
|
|
|
<div v-else>
|
|
|
|
<ClusterHList
|
|
|
|
v-if="recognize.length"
|
|
|
|
:title="t('memories', 'Recognize')"
|
|
|
|
link="/recognize"
|
|
|
|
:clusters="recognize"
|
|
|
|
/>
|
|
|
|
<ClusterHList
|
|
|
|
v-if="facerecognition.length"
|
|
|
|
:title="t('memories', 'Face Recognition')"
|
|
|
|
link="/facerecognition"
|
|
|
|
:clusters="facerecognition"
|
|
|
|
/>
|
|
|
|
<ClusterHList v-if="places.length" :title="t('memories', 'Places')" link="/places" :clusters="places" />
|
|
|
|
<ClusterHList v-if="tags.length" :title="t('memories', 'Tags')" link="/tags" :clusters="tags" />
|
|
|
|
|
|
|
|
<div class="link-list">
|
|
|
|
<NcButton
|
|
|
|
class="link"
|
|
|
|
v-for="category of categories"
|
|
|
|
:ariaLabel="category.name"
|
|
|
|
:key="category.name"
|
|
|
|
:to="category.link"
|
|
|
|
@click="category.click?.()"
|
|
|
|
type="secondary"
|
|
|
|
>
|
|
|
|
<template #icon>
|
|
|
|
<component :is="category.icon" />
|
|
|
|
</template>
|
|
|
|
<template>{{ category.name }}</template>
|
|
|
|
</NcButton>
|
|
|
|
</div>
|
2023-05-03 11:10:31 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import { defineComponent } from 'vue';
|
|
|
|
import config from '../services/static-config';
|
|
|
|
import axios from '@nextcloud/axios';
|
|
|
|
|
|
|
|
import ClusterHList from './ClusterHList.vue';
|
|
|
|
|
|
|
|
import NcButton from '@nextcloud/vue/dist/Components/NcButton';
|
2023-05-22 04:55:16 +00:00
|
|
|
|
|
|
|
import FolderIcon from 'vue-material-design-icons/Folder.vue';
|
2023-05-03 11:10:31 +00:00
|
|
|
import StarIcon from 'vue-material-design-icons/Star.vue';
|
|
|
|
import VideoIcon from 'vue-material-design-icons/PlayCircle.vue';
|
|
|
|
import ArchiveIcon from 'vue-material-design-icons/PackageDown.vue';
|
|
|
|
import CalendarIcon from 'vue-material-design-icons/Calendar.vue';
|
2023-05-03 18:18:30 +00:00
|
|
|
import MapIcon from 'vue-material-design-icons/Map.vue';
|
|
|
|
import CogIcon from 'vue-material-design-icons/Cog.vue';
|
2023-05-03 11:10:31 +00:00
|
|
|
|
|
|
|
import type { ICluster, IConfig } from '../types';
|
|
|
|
import { API } from '../services/API';
|
|
|
|
import { translate as t } from '@nextcloud/l10n';
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
name: 'Explore',
|
|
|
|
|
|
|
|
data: () => ({
|
2023-05-03 18:25:58 +00:00
|
|
|
loading: 0,
|
|
|
|
|
2023-05-03 11:10:31 +00:00
|
|
|
config: {} as IConfig,
|
|
|
|
recognize: [] as ICluster[],
|
|
|
|
facerecognition: [] as ICluster[],
|
|
|
|
places: [] as ICluster[],
|
|
|
|
tags: [] as ICluster[],
|
|
|
|
|
|
|
|
categories: [
|
2023-05-22 04:55:16 +00:00
|
|
|
{
|
|
|
|
name: t('memories', 'Folders'),
|
|
|
|
icon: FolderIcon,
|
|
|
|
link: '/folders',
|
|
|
|
},
|
2023-05-03 11:10:31 +00:00
|
|
|
{
|
|
|
|
name: t('memories', 'Favorites'),
|
|
|
|
icon: StarIcon,
|
|
|
|
link: '/favorites',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: t('memories', 'Videos'),
|
|
|
|
icon: VideoIcon,
|
|
|
|
link: '/videos',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: t('memories', 'Archive'),
|
|
|
|
icon: ArchiveIcon,
|
|
|
|
link: '/archive',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: t('memories', 'On this day'),
|
|
|
|
icon: CalendarIcon,
|
|
|
|
link: '/thisday',
|
|
|
|
},
|
2023-05-03 18:18:30 +00:00
|
|
|
{
|
|
|
|
name: t('memories', 'Map'),
|
|
|
|
icon: MapIcon,
|
|
|
|
link: '/map',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: t('memories', 'Settings'),
|
|
|
|
icon: CogIcon,
|
|
|
|
link: undefined,
|
|
|
|
click: globalThis.showSettings,
|
|
|
|
},
|
|
|
|
] as {
|
|
|
|
name: string;
|
|
|
|
icon: any;
|
|
|
|
link?: string;
|
|
|
|
click?: () => void;
|
|
|
|
}[],
|
2023-05-03 11:10:31 +00:00
|
|
|
}),
|
|
|
|
|
|
|
|
components: {
|
|
|
|
ClusterHList,
|
|
|
|
NcButton,
|
|
|
|
StarIcon,
|
|
|
|
},
|
|
|
|
|
|
|
|
async mounted() {
|
2023-05-03 18:25:58 +00:00
|
|
|
const res: IConfig | undefined = await this.load(config.getAll.bind(config));
|
|
|
|
if (!res) return;
|
|
|
|
this.config = res;
|
2023-05-03 11:10:31 +00:00
|
|
|
|
|
|
|
if (this.config.recognize_enabled) {
|
2023-05-03 18:25:58 +00:00
|
|
|
this.load(this.getRecognize);
|
2023-05-03 11:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.config.facerecognition_enabled) {
|
2023-05-03 18:25:58 +00:00
|
|
|
this.load(this.getFaceRecognition);
|
2023-05-03 11:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.config.places_gis > 0) {
|
2023-05-03 18:25:58 +00:00
|
|
|
this.load(this.getPlaces);
|
2023-05-03 11:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.config.systemtags_enabled) {
|
2023-05-03 18:25:58 +00:00
|
|
|
this.load(this.getTags);
|
2023-05-03 11:10:31 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
2023-05-03 18:25:58 +00:00
|
|
|
async load<T>(fun: () => Promise<T>) {
|
|
|
|
try {
|
|
|
|
this.loading++;
|
|
|
|
return await fun();
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
} finally {
|
|
|
|
this.loading--;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2023-05-03 11:10:31 +00:00
|
|
|
async getRecognize() {
|
|
|
|
const res = await axios.get<ICluster[]>(API.FACE_LIST('recognize'));
|
|
|
|
this.recognize = res.data.slice(0, 10);
|
|
|
|
},
|
|
|
|
|
|
|
|
async getFaceRecognition() {
|
|
|
|
const res = await axios.get<ICluster[]>(API.FACE_LIST('facerecognition'));
|
|
|
|
this.facerecognition = res.data.slice(0, 10);
|
|
|
|
},
|
|
|
|
|
|
|
|
async getPlaces() {
|
|
|
|
const res = await axios.get<ICluster[]>(API.PLACE_LIST());
|
2023-08-04 20:32:09 +00:00
|
|
|
const places = res.data; // FIXME: performance
|
2023-05-24 04:13:01 +00:00
|
|
|
this.places = places.slice(0, 10);
|
2023-05-03 11:10:31 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
async getTags() {
|
|
|
|
const res = await axios.get<ICluster[]>(API.TAG_LIST());
|
2023-08-04 20:32:09 +00:00
|
|
|
const tags = res.data.sort((a, b) => b.count - a.count); // FIXME: performance
|
2023-05-24 04:13:01 +00:00
|
|
|
this.tags = tags.slice(0, 10);
|
2023-05-03 11:10:31 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.explore-outer {
|
2023-05-03 18:18:30 +00:00
|
|
|
height: 100%;
|
|
|
|
overflow: auto;
|
2023-05-11 10:28:26 +00:00
|
|
|
padding-top: 8px;
|
2023-05-03 18:18:30 +00:00
|
|
|
|
2023-05-03 18:25:58 +00:00
|
|
|
.link-list {
|
2023-05-22 02:00:04 +00:00
|
|
|
padding: 6px 7px;
|
2023-05-03 11:10:31 +00:00
|
|
|
|
|
|
|
> .link {
|
|
|
|
display: inline-block;
|
2023-05-22 02:11:36 +00:00
|
|
|
width: calc(50% - 6px);
|
|
|
|
margin: 3px;
|
2023-05-03 11:10:31 +00:00
|
|
|
border-radius: 10px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|