memories/src/App.vue

408 lines
10 KiB
Vue
Raw Normal View History

2022-08-14 20:54:18 +00:00
<template>
<router-view v-if="onlyRouterView" />
<FirstStart v-else-if="isFirstStart" />
2022-10-28 19:08:34 +00:00
<NcContent
app-name="memories"
2023-09-29 18:00:44 +00:00
v-else-if="!isConfigUnknown"
2022-10-28 19:08:34 +00:00
:class="{
'has-nav': showNavigation,
2022-10-28 19:08:34 +00:00
}"
>
<NcAppNavigation v-if="showNavigation">
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>
<ul class="app-navigation__settings">
<NcAppNavigationItem :name="t('memories', 'Settings')" @click="showSettings">
<CogIcon slot="icon" :size="20" />
</NcAppNavigationItem>
</ul>
2022-10-28 19:08:34 +00:00
</template>
</NcAppNavigation>
<NcAppContent>
2023-02-08 21:35:42 +00:00
<div
:class="{
outer: true,
'router-outlet': true,
2023-02-08 21:35:42 +00:00
'remove-gap': removeNavGap,
'has-nav': showNavigation,
'has-mobile-header': hasMobileHeader,
'is-native': native,
2023-02-08 21:35:42 +00:00
}"
>
2022-10-28 19:08:34 +00:00
<router-view />
</div>
<MobileHeader v-if="hasMobileHeader" />
<MobileNav v-if="showNavigation" />
2022-10-28 19:08:34 +00:00
</NcAppContent>
2023-02-09 21:03:06 +00:00
<Settings :open.sync="settingsOpen" />
2023-03-09 21:47:14 +00:00
<Viewer />
2023-03-09 21:47:14 +00:00
<Sidebar />
2023-03-10 20:45:04 +00:00
<EditMetadataModal />
<AddToAlbumModal />
2023-03-10 20:45:04 +00:00
<NodeShareModal />
<ShareModal />
<MoveToFolderModal />
<FaceMoveModal />
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">
import { defineComponent } from 'vue';
import NcContent from '@nextcloud/vue/dist/Components/NcContent';
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent';
import NcAppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation';
const NcAppNavigationItem = () => import('@nextcloud/vue/dist/Components/NcAppNavigationItem');
import { generateUrl } from '@nextcloud/router';
import { translate as t } from '@nextcloud/l10n';
import * as utils from './services/utils';
import * as nativex from './native';
import staticConfig from './services/static-config';
import UserConfig from './mixins/UserConfig';
import Timeline from './components/Timeline.vue';
import Settings from './components/Settings.vue';
import FirstStart from './components/FirstStart.vue';
import Viewer from './components/viewer/Viewer.vue';
import Sidebar from './components/Sidebar.vue';
import MobileNav from './components/MobileNav.vue';
import MobileHeader from './components/MobileHeader.vue';
import EditMetadataModal from './components/modal/EditMetadataModal.vue';
import AddToAlbumModal from './components/modal/AddToAlbumModal.vue';
import NodeShareModal from './components/modal/NodeShareModal.vue';
import ShareModal from './components/modal/ShareModal.vue';
import MoveToFolderModal from './components/modal/MoveToFolderModal.vue';
import FaceMoveModal from './components/modal/FaceMoveModal.vue';
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';
import Video from 'vue-material-design-icons/PlayCircle.vue';
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';
import MarkerIcon from 'vue-material-design-icons/MapMarker.vue';
import TagsIcon from 'vue-material-design-icons/Tag.vue';
import MapIcon from 'vue-material-design-icons/Map.vue';
import CogIcon from 'vue-material-design-icons/Cog.vue';
2022-09-16 03:17:40 +00:00
type NavItem = {
name: string;
title: string;
icon: any;
if?: any;
};
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,
Viewer,
2023-03-09 21:47:14 +00:00
Sidebar,
MobileNav,
MobileHeader,
2023-03-10 20:45:04 +00:00
EditMetadataModal,
AddToAlbumModal,
2023-03-10 20:45:04 +00:00
NodeShareModal,
ShareModal,
MoveToFolderModal,
FaceMoveModal,
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
},
mixins: [UserConfig],
2022-12-10 18:59:36 +00:00
data: () => ({
navItems: [] as NavItem[],
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: {
native(): boolean {
return nativex.has();
},
recognize(): string | false {
if (!this.config.recognize_enabled) {
2022-12-10 09:01:44 +00:00
return false;
}
if (this.config.facerecognition_installed) {
return t('memories', 'People (Recognize)');
2022-12-10 09:01:44 +00:00
}
return t('memories', 'People');
2022-12-08 21:00:53 +00:00
},
2022-12-10 17:58:30 +00:00
facerecognition(): string | false {
if (!this.config.facerecognition_installed) {
2022-12-10 09:01:44 +00:00
return false;
}
if (this.config.recognize_enabled) {
return t('memories', 'People (Face Recognition)');
2022-12-10 09:01:44 +00:00
}
return t('memories', 'People');
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
onlyRouterView(): boolean {
return this.routeIsNxSetup;
},
2022-12-10 17:58:30 +00:00
isFirstStart(): boolean {
2023-09-29 18:00:44 +00:00
return this.config.timeline_path === '_empty_' && !this.routeIsPublic && !this.$route.query.noinit;
},
isConfigUnknown(): boolean {
return this.config.timeline_path === '_unknown_';
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
showAlbums(): boolean {
return this.config.albums_enabled;
2022-11-11 13:55:47 +00:00
},
2022-12-10 17:58:30 +00:00
showNavigation(): boolean {
if (this.native) {
return this.routeIsBase || this.routeIsExplore || (this.routeIsAlbums && !this.$route.params.name);
}
return !this.routeIsPublic;
2022-11-11 13:55:47 +00:00
},
2023-02-08 21:35:42 +00:00
hasMobileHeader(): boolean {
return this.native && this.showNavigation && this.routeIsBase;
},
2023-02-08 21:35:42 +00:00
removeNavGap(): boolean {
return this.routeIsMap;
2023-02-08 21:35:42 +00:00
},
2022-12-10 09:01:44 +00:00
},
2022-10-29 01:34:17 +00:00
created() {
// No real need to unbind these, as the app is never destroyed
const onResize = () => {
_m.window.innerWidth = window.innerWidth;
_m.window.innerHeight = window.innerHeight;
utils.bus.emit('memories:window:resize', null);
};
window.addEventListener('resize', () => {
utils.setRenewingTimeout(this, 'resizeTimer', onResize, 100);
});
// Register navigation items on config change
utils.bus.on('memories:user-config-changed', this.refreshNav);
// Register global functions
_m.modals.showSettings = this.showSettings;
},
2022-10-29 01:58:40 +00:00
mounted() {
this.refreshNav();
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`);
root.style.setProperty('--plyr-color-main', colorPrimary);
2022-11-07 21:55:11 +00:00
// Set theme color to default
nativex.setTheme();
// Check for native interface
if (this.native) {
document.documentElement.classList.add('native');
}
// Close navigation by default if init is disabled
// This is the case for public folder/album shares
if (this.$route.query.noinit) {
utils.bus.emit('toggle-navigation', { open: false });
}
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 (window.location.hostname === 'localhost') {
// Disable on dev instances
console.warn('Service Worker is not enabled on localhost.');
} else if ('serviceWorker' in navigator) {
// Get the config before loading
const previousVersion = staticConfig.getSync('version');
2023-02-09 19:28:15 +00:00
// Use the window load event to keep the page load performant
window.addEventListener('load', async () => {
2023-02-09 19:28:15 +00:00
try {
const url = generateUrl('/apps/memories/static/service-worker.js');
2023-02-09 19:28:15 +00:00
const registration = await navigator.serviceWorker.register(url, {
scope: generateUrl('/apps/memories'),
2023-02-09 19:28:15 +00:00
});
console.info('SW registered: ', registration);
// Check for updates
const currentVersion = await staticConfig.get('version');
if (previousVersion !== currentVersion) {
registration.update();
}
2023-02-09 19:28:15 +00:00
} catch (error) {
console.error('SW registration failed: ', error);
2023-02-09 19:28:15 +00:00
}
});
} else {
console.debug('Service Worker is not enabled on this browser.');
2023-02-09 19:28:15 +00:00
}
},
2022-12-10 09:01:44 +00:00
methods: {
refreshNav() {
const navItems = [
2022-12-10 09:01:44 +00:00
{
name: 'timeline',
2022-12-10 09:01:44 +00:00
icon: ImageMultiple,
title: t('memories', 'Timeline'),
2022-12-10 09:01:44 +00:00
},
{
name: 'folders',
2022-12-10 09:01:44 +00:00
icon: FolderIcon,
title: t('memories', 'Folders'),
2022-12-10 09:01:44 +00:00
},
{
name: 'favorites',
2022-12-10 09:01:44 +00:00
icon: Star,
title: t('memories', 'Favorites'),
2022-12-10 09:01:44 +00:00
},
{
name: 'videos',
2022-12-10 09:01:44 +00:00
icon: Video,
title: t('memories', 'Videos'),
2022-12-10 09:01:44 +00:00
},
{
name: 'albums',
2022-12-10 09:01:44 +00:00
icon: AlbumIcon,
title: t('memories', 'Albums'),
2022-12-10 09:01:44 +00:00
if: this.showAlbums,
},
{
name: 'recognize',
2022-12-10 09:01:44 +00:00
icon: PeopleIcon,
title: this.recognize || '',
2022-12-10 09:01:44 +00:00
if: this.recognize,
},
{
name: 'facerecognition',
2022-12-10 09:01:44 +00:00
icon: PeopleIcon,
title: this.facerecognition || '',
2022-12-10 09:01:44 +00:00
if: this.facerecognition,
},
{
name: 'archive',
2022-12-10 09:01:44 +00:00
icon: ArchiveIcon,
title: t('memories', 'Archive'),
2022-12-10 09:01:44 +00:00
},
{
name: 'thisday',
2022-12-10 09:01:44 +00:00
icon: CalendarIcon,
title: t('memories', 'On this day'),
2022-12-10 09:01:44 +00:00
},
2023-02-05 21:43:25 +00:00
{
name: 'places',
2023-02-05 21:43:25 +00:00
icon: MarkerIcon,
title: t('memories', 'Places'),
if: this.config.places_gis > 0,
2023-02-05 21:43:25 +00:00
},
2023-02-08 22:13:13 +00:00
{
name: 'map',
2023-02-08 22:13:13 +00:00
icon: MapIcon,
title: t('memories', 'Map'),
2023-02-08 22:13:13 +00:00
},
2022-12-10 09:01:44 +00:00
{
name: 'tags',
2022-12-10 09:01:44 +00:00
icon: TagsIcon,
title: t('memories', 'Tags'),
if: this.config.systemtags_enabled,
2022-12-10 09:01:44 +00:00
},
];
this.navItems = navItems.filter((item) => typeof item.if === 'undefined' || Boolean(item.if));
2022-12-10 09:01:44 +00:00
},
2022-10-29 01:58:40 +00:00
2022-12-10 09:01:44 +00:00
linkClick() {
if (_m.window.innerWidth <= 1024) {
utils.bus.emit('toggle-navigation', { open: false });
}
2022-12-10 09:01:44 +00:00
},
2022-10-29 01:58:40 +00:00
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 {
// Fill up the whole space, e.g. on map
2023-02-08 21:35:42 +00:00
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;
}
2022-10-12 19:05:38 +00:00
}
ul.app-navigation__settings {
height: auto !important;
overflow: hidden !important;
padding-top: 0 !important;
flex: 0 0 auto;
}
2022-10-12 19:05:38 +00:00
</style>