memories/src/App.vue

362 lines
9.2 KiB
Vue
Raw Normal View History

2022-08-14 20:54:18 +00:00
<template>
2022-10-28 19:08:34 +00:00
<FirstStart v-if="isFirstStart" />
<NcContent
app-name="memories"
v-else
:class="{
'remove-gap': removeOuterGap,
}"
>
2022-11-11 13:55:47 +00:00
<NcAppNavigation v-if="showNavigation" ref="nav">
2022-10-28 19:08:34 +00:00
<template id="app-memories-navigation" #list>
<NcAppNavigationItem
2022-11-11 13:55:47 +00:00
v-for="item in navItems"
:key="item.name"
:to="{ name: item.name }"
:title="item.title"
2022-11-11 13:55:47 +00:00
@click="linkClick"
2022-10-28 19:08:34 +00:00
exact
>
2022-11-11 13:55:47 +00:00
<component :is="item.icon" slot="icon" :size="20" />
2022-10-28 19:08:34 +00:00
</NcAppNavigationItem>
</template>
2022-11-11 13:55:47 +00:00
2022-10-28 19:08:34 +00:00
<template #footer>
2023-02-09 21:03:06 +00:00
<NcAppNavigationItem
:title="t('memories', 'Settings')"
2023-02-09 21:03:06 +00:00
@click="showSettings"
>
<CogIcon slot="icon" :size="20" />
</NcAppNavigationItem>
2022-10-28 19:08:34 +00:00
</template>
</NcAppNavigation>
<NcAppContent>
2023-02-08 21:35:42 +00:00
<div
:class="{
outer: true,
'remove-gap': removeNavGap,
}"
>
2022-10-28 19:08:34 +00:00
<router-view />
</div>
</NcAppContent>
2023-02-09 21:03:06 +00:00
<Settings :open.sync="settingsOpen" />
2022-10-28 19:08:34 +00:00
</NcContent>
2022-08-14 20:54:18 +00:00
</template>
2022-09-13 01:33:24 +00:00
<script lang="ts">
2022-12-10 09:01:44 +00:00
import Vue, { defineComponent } from "vue";
2022-11-24 19:54:29 +00:00
import NcContent from "@nextcloud/vue/dist/Components/NcContent";
import NcAppContent from "@nextcloud/vue/dist/Components/NcAppContent";
import NcAppNavigation from "@nextcloud/vue/dist/Components/NcAppNavigation";
2022-11-24 21:07:09 +00:00
const NcAppNavigationItem = () =>
import("@nextcloud/vue/dist/Components/NcAppNavigationItem");
2022-11-24 19:54:29 +00:00
2022-10-28 19:08:34 +00:00
import { generateUrl } from "@nextcloud/router";
2022-11-11 13:55:47 +00:00
import { translate as t } from "@nextcloud/l10n";
2022-10-28 19:08:34 +00:00
import Timeline from "./components/Timeline.vue";
import Settings from "./components/Settings.vue";
import FirstStart from "./components/FirstStart.vue";
2022-11-07 21:55:11 +00:00
import Metadata from "./components/Metadata.vue";
2022-10-28 19:08:34 +00:00
import ImageMultiple from "vue-material-design-icons/ImageMultiple.vue";
import FolderIcon from "vue-material-design-icons/Folder.vue";
import Star from "vue-material-design-icons/Star.vue";
2022-10-30 21:38:31 +00:00
import Video from "vue-material-design-icons/PlayCircle.vue";
2022-10-28 19:08:34 +00:00
import AlbumIcon from "vue-material-design-icons/ImageAlbum.vue";
import ArchiveIcon from "vue-material-design-icons/PackageDown.vue";
import CalendarIcon from "vue-material-design-icons/Calendar.vue";
import PeopleIcon from "vue-material-design-icons/AccountBoxMultiple.vue";
2023-02-05 21:43:25 +00:00
import MarkerIcon from "vue-material-design-icons/MapMarker.vue";
2022-10-28 19:08:34 +00:00
import TagsIcon from "vue-material-design-icons/Tag.vue";
import MapIcon from "vue-material-design-icons/Map.vue";
2023-02-09 21:03:06 +00:00
import CogIcon from "vue-material-design-icons/Cog.vue";
2022-09-16 03:17:40 +00:00
2022-12-10 09:01:44 +00:00
export default defineComponent({
name: "App",
2022-10-28 19:08:34 +00:00
components: {
NcContent,
NcAppContent,
NcAppNavigation,
NcAppNavigationItem,
Timeline,
Settings,
FirstStart,
ImageMultiple,
FolderIcon,
Star,
Video,
AlbumIcon,
ArchiveIcon,
CalendarIcon,
PeopleIcon,
2023-02-05 21:43:25 +00:00
MarkerIcon,
2022-10-28 19:08:34 +00:00
TagsIcon,
MapIcon,
2023-02-09 21:03:06 +00:00
CogIcon,
2022-10-28 19:08:34 +00:00
},
2022-12-10 18:59:36 +00:00
data: () => ({
navItems: [],
metadataComponent: null as any,
2023-02-09 21:03:06 +00:00
settingsOpen: false,
2022-12-10 18:59:36 +00:00
}),
2022-11-07 21:55:11 +00:00
2022-12-10 09:01:44 +00:00
computed: {
2022-12-10 17:58:30 +00:00
ncVersion(): number {
2022-12-10 09:01:44 +00:00
const version = (<any>window.OC).config.version.split(".");
return Number(version[0]);
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
recognize(): string | boolean {
2022-12-10 09:01:44 +00:00
if (!this.config_recognizeEnabled) {
return false;
}
if (this.config_facerecognitionInstalled) {
return t("memories", "People (Recognize)");
}
return t("memories", "People");
2022-12-08 21:00:53 +00:00
},
2022-12-10 17:58:30 +00:00
facerecognition(): string | boolean {
2022-12-10 09:01:44 +00:00
if (!this.config_facerecognitionInstalled) {
return false;
}
if (this.config_recognizeEnabled) {
return t("memories", "People (Face Recognition)");
}
return t("memories", "People");
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
isFirstStart(): boolean {
2022-12-10 09:01:44 +00:00
return this.config_timelinePath === "EMPTY";
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
showAlbums(): boolean {
2022-12-10 09:01:44 +00:00
return this.config_albumsEnabled;
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
removeOuterGap(): boolean {
2022-12-10 09:01:44 +00:00
return this.ncVersion >= 25;
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
showNavigation(): boolean {
return !this.$route.name?.endsWith("-share");
2022-11-11 13:55:47 +00:00
},
2023-02-08 21:35:42 +00:00
removeNavGap(): boolean {
2023-02-08 22:13:13 +00:00
return this.$route.name === "map";
2023-02-08 21:35:42 +00:00
},
2022-12-10 09:01:44 +00:00
},
2022-10-29 01:34:17 +00:00
2022-12-10 09:01:44 +00:00
watch: {
route() {
this.doRouteChecks();
},
},
2022-10-29 01:58:40 +00:00
mounted() {
this.doRouteChecks();
2022-10-30 20:24:17 +00:00
2022-11-11 13:55:47 +00:00
// Populate navigation
2022-12-10 09:01:44 +00:00
this.navItems = this.navItemsAll().filter(
2022-12-08 21:00:53 +00:00
(item) => typeof item.if === "undefined" || Boolean(item.if)
2022-11-11 13:55:47 +00:00
);
2022-10-30 20:24:17 +00:00
// Store CSS variables modified
const root = document.documentElement;
const colorPrimary =
getComputedStyle(root).getPropertyValue("--color-primary");
root.style.setProperty("--color-primary-select-light", `${colorPrimary}40`);
2022-11-14 05:43:43 +00:00
root.style.setProperty("--plyr-color-main", colorPrimary);
2022-11-07 21:55:11 +00:00
// Register sidebar metadata tab
const OCA = globalThis.OCA;
if (OCA.Files && OCA.Files.Sidebar) {
OCA.Files.Sidebar.registerTab(
new OCA.Files.Sidebar.Tab({
id: "memories-metadata",
2022-11-08 00:33:45 +00:00
name: this.t("memories", "EXIF"),
2022-11-07 21:55:11 +00:00
icon: "icon-details",
async mount(el, fileInfo, context) {
if (this.metadataComponent) {
this.metadataComponent.$destroy();
}
2022-12-10 19:24:41 +00:00
this.metadataComponent = new Vue(Metadata as any);
2022-11-07 21:55:11 +00:00
// Only mount after we have all the info we need
await this.metadataComponent.update(fileInfo);
this.metadataComponent.$mount(el);
},
update(fileInfo) {
this.metadataComponent.update(fileInfo);
},
destroy() {
this.metadataComponent.$destroy();
this.metadataComponent = null;
},
})
);
}
2022-12-10 09:01:44 +00:00
},
2022-10-29 01:58:40 +00:00
2023-02-09 19:28:15 +00:00
async beforeMount() {
if ("serviceWorker" in navigator) {
// Use the window load event to keep the page load performant
window.addEventListener("load", async () => {
try {
const url = generateUrl("/apps/memories/service-worker.js");
const registration = await navigator.serviceWorker.register(url, {
scope: generateUrl("/apps/memories"),
});
console.log("SW registered: ", registration);
} catch (error) {
console.error("SW registration failed: ", error);
}
});
} else {
console.debug("Service Worker is not enabled on this browser.");
}
},
2022-12-10 09:01:44 +00:00
methods: {
navItemsAll() {
return [
{
name: "timeline",
icon: ImageMultiple,
title: t("memories", "Timeline"),
},
{
name: "folders",
icon: FolderIcon,
title: t("memories", "Folders"),
},
{
name: "favorites",
icon: Star,
title: t("memories", "Favorites"),
},
{
name: "videos",
icon: Video,
title: t("memories", "Videos"),
},
{
name: "albums",
icon: AlbumIcon,
title: t("memories", "Albums"),
if: this.showAlbums,
},
{
name: "recognize",
icon: PeopleIcon,
title: this.recognize,
if: this.recognize,
},
{
name: "facerecognition",
icon: PeopleIcon,
title: this.facerecognition,
if: this.facerecognition,
},
{
name: "archive",
icon: ArchiveIcon,
title: t("memories", "Archive"),
},
{
name: "thisday",
icon: CalendarIcon,
title: t("memories", "On this day"),
},
2023-02-05 21:43:25 +00:00
{
name: "places",
icon: MarkerIcon,
title: t("memories", "Places"),
if: this.config_placesGis > 0,
2023-02-05 21:43:25 +00:00
},
2023-02-08 22:13:13 +00:00
{
name: "map",
icon: MapIcon,
title: t("memories", "Map"),
},
2022-12-10 09:01:44 +00:00
{
name: "tags",
icon: TagsIcon,
title: t("memories", "Tags"),
if: this.config_tagsEnabled,
},
];
},
2022-10-29 01:58:40 +00:00
2022-12-10 09:01:44 +00:00
linkClick() {
const nav: any = this.$refs.nav;
if (globalThis.windowInnerWidth <= 1024) nav?.toggleNavigation(false);
},
2022-10-29 01:58:40 +00:00
2022-12-10 09:01:44 +00:00
doRouteChecks() {
if (this.$route.name.endsWith("-share")) {
this.putShareToken(<string>this.$route.params.token);
2022-12-10 09:01:44 +00:00
}
},
2022-10-29 01:58:40 +00:00
putShareToken(token: string) {
2022-12-10 09:01:44 +00:00
// Viewer looks for an input with ID sharingToken with the value as the token
// Create this element or update it otherwise files not gonna open
// https://github.com/nextcloud/viewer/blob/a8c46050fb687dcbb48a022a15a5d1275bf54a8e/src/utils/davUtils.js#L61
let tokenInput = document.getElementById(
"sharingToken"
) as HTMLInputElement;
if (!tokenInput) {
tokenInput = document.createElement("input");
tokenInput.id = "sharingToken";
tokenInput.type = "hidden";
tokenInput.style.display = "none";
document.body.appendChild(tokenInput);
}
tokenInput.value = token;
},
2023-02-09 21:03:06 +00:00
showSettings() {
this.settingsOpen = true;
},
2022-12-10 09:01:44 +00:00
},
});
2022-08-14 20:54:18 +00:00
</script>
2022-09-16 04:06:40 +00:00
2022-10-12 19:05:38 +00:00
<style scoped lang="scss">
.outer {
2022-10-28 19:08:34 +00:00
padding: 0 0 0 44px;
height: 100%;
width: 100%;
2023-02-08 21:35:42 +00:00
&.remove-gap {
padding: 0;
}
2022-10-12 19:05:38 +00:00
}
@media (max-width: 768px) {
2022-10-28 19:08:34 +00:00
.outer {
padding: 0px;
// Get rid of padding on img-outer (1px on mobile)
// Also need to make sure we don't end up with a scrollbar -- see below
margin-left: -1px;
width: calc(100% + 3px); // 1px extra here because ... reasons
}
2022-10-12 19:05:38 +00:00
}
</style>