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">
|
2023-03-03 19:41:25 +00:00
|
|
|
<template #list>
|
2022-10-28 19:08:34 +00:00
|
|
|
<NcAppNavigationItem
|
2022-11-11 13:55:47 +00:00
|
|
|
v-for="item in navItems"
|
|
|
|
:key="item.name"
|
|
|
|
:to="{ name: item.name }"
|
2023-02-26 21:52:24 +00:00
|
|
|
:name="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
|
2023-02-26 21:52:24 +00:00
|
|
|
:name="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" />
|
2023-03-09 21:47:14 +00:00
|
|
|
|
|
|
|
<Sidebar />
|
2023-03-10 20:45:04 +00:00
|
|
|
<EditMetadataModal />
|
|
|
|
<NodeShareModal />
|
2023-03-10 23:27:12 +00:00
|
|
|
<ShareModal />
|
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
|
|
|
|
2023-03-03 20:47:46 +00:00
|
|
|
import UserConfig from "./mixins/UserConfig";
|
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";
|
2023-03-09 21:47:14 +00:00
|
|
|
import Sidebar from "./components/Sidebar.vue";
|
2023-03-10 20:45:04 +00:00
|
|
|
import EditMetadataModal from "./components/modal/EditMetadataModal.vue";
|
|
|
|
import NodeShareModal from "./components/modal/NodeShareModal.vue";
|
2023-03-10 23:27:12 +00:00
|
|
|
import ShareModal from "./components/modal/ShareModal.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,
|
2023-03-09 21:47:14 +00:00
|
|
|
Sidebar,
|
2023-03-10 20:45:04 +00:00
|
|
|
EditMetadataModal,
|
|
|
|
NodeShareModal,
|
2023-03-10 23:27:12 +00:00
|
|
|
ShareModal,
|
2022-10-28 19:08:34 +00:00
|
|
|
|
|
|
|
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
|
|
|
},
|
|
|
|
|
2023-03-03 20:47:46 +00:00
|
|
|
mixins: [UserConfig],
|
|
|
|
|
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 {
|
2023-01-18 03:02:00 +00:00
|
|
|
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",
|
2023-03-07 20:28:08 +00:00
|
|
|
name: this.t("memories", "Info"),
|
2022-11-07 21:55:11 +00:00
|
|
|
icon: "icon-details",
|
|
|
|
|
2023-03-03 19:41:25 +00:00
|
|
|
mount(el, fileInfo, context) {
|
|
|
|
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
|
|
|
this.metadataComponent.$mount(el);
|
2023-03-16 16:58:43 +00:00
|
|
|
this.metadataComponent.update(Number(fileInfo.id));
|
2022-11-07 21:55:11 +00:00
|
|
|
},
|
|
|
|
update(fileInfo) {
|
2023-03-16 16:58:43 +00:00
|
|
|
this.metadataComponent.update(Number(fileInfo.id));
|
2022-11-07 21:55:11 +00:00
|
|
|
},
|
|
|
|
destroy() {
|
2023-03-03 19:41:25 +00:00
|
|
|
this.metadataComponent?.$destroy?.();
|
2022-11-07 21:55:11 +00:00
|
|
|
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"),
|
2023-02-06 03:55:39 +00:00
|
|
|
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() {
|
2023-01-18 03:02:00 +00:00
|
|
|
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
|
|
|
|
2023-01-18 03:02:00 +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>
|