refactor: improve route typing

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/877/head
Varun Patil 2023-10-16 12:42:18 -07:00
parent c7f7d98d4f
commit 75881b33d0
21 changed files with 77 additions and 105 deletions

View File

@ -192,7 +192,7 @@ export default defineComponent({
},
onlyRouterView(): boolean {
return ['nxsetup'].includes(this.$route.name ?? '');
return this.routeIsNxSetup;
},
isFirstStart(): boolean {
@ -224,12 +224,6 @@ export default defineComponent({
},
},
watch: {
route() {
this.doRouteChecks();
},
},
created() {
// No real need to unbind these, as the app is never destroyed
const onResize = () => {
@ -249,7 +243,6 @@ export default defineComponent({
},
mounted() {
this.doRouteChecks();
this.refreshNav();
// Store CSS variables modified
@ -409,28 +402,6 @@ export default defineComponent({
}
},
doRouteChecks() {
if (this.$route.name?.endsWith('-share')) {
this.putShareToken(<string>this.$route.params.token);
}
},
putShareToken(token: string) {
// 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;
},
showSettings() {
this.settingsOpen = true;
},

View File

@ -12,7 +12,7 @@ import XLoadingIcon from './components/XLoadingIcon.vue';
import VueVirtualScroller from 'vue-virtual-scroller';
// Locals
import router from './router';
import router, { routes } from './router';
import { constants, initstate } from './services/utils';
// CSS for components
@ -28,6 +28,7 @@ globalThis._m = {
get route() {
return router.currentRoute;
},
routes: routes,
modals: {} as any,
sidebar: {} as any,

View File

@ -100,8 +100,10 @@ export default defineComponent({
this.items = await dav.getAlbums(this.config.album_list_sort);
} else if (this.routeIsTags) {
this.items = await dav.getTags();
} else if (this.routeIsPeople) {
this.items = await dav.getFaceList(<any>this.$route.name);
} else if (this.routeIsRecognize) {
this.items = await dav.getFaceList('recognize');
} else if (this.routeIsFaceRecognition) {
this.items = await dav.getFaceList('facerecognition');
} else if (this.routeIsPlaces) {
this.items = await dav.getPlaces();
}

View File

@ -840,9 +840,7 @@ export default defineComponent({
async removeSelectionFromPerson(selection: Selection) {
// Make sure route is valid
const { user, name } = this.$route.params;
if (this.$route.name !== 'recognize' || !user || !name) {
return;
}
if (!this.routeIsRecognize || !user || !name) return;
// Check photo ownership
if (this.$route.params.user !== utils.uid) {

View File

@ -63,10 +63,10 @@ export default defineComponent({
primary() {
switch (this.$route.name) {
case 'map':
case _m.routes.Map.name:
return MapSplitMatter;
default:
return 'None';
return null;
}
},

View File

@ -594,8 +594,7 @@ export default defineComponent({
}
// Albums
const user = <string>this.$route.params.user;
const name = <string>this.$route.params.name;
const { user, name } = this.$route.params;
if (this.routeIsAlbums) {
if (!user || !name) {
throw new Error('Invalid album route');
@ -606,7 +605,7 @@ export default defineComponent({
// People
if (this.routeIsPeople) {
if (!user || !name) {
throw new Error('Invalid album route');
throw new Error('Invalid face route');
}
// name is "recognize" or "facerecognition"
@ -625,7 +624,7 @@ export default defineComponent({
throw new Error('Invalid place route');
}
const id = <string>name.split('-', 1)[0];
const id = name.split('-', 1)[0];
set(DaysFilterType.PLACE, id);
}
@ -690,7 +689,7 @@ export default defineComponent({
const startState = this.state;
let data: IDay[] = [];
if (this.$route.name === 'thisday') {
if (this.routeIsThisDay) {
data = await dav.getOnThisDayData();
} else if (dav.isSingleItem()) {
data = await dav.getSingleItemData();
@ -793,7 +792,7 @@ export default defineComponent({
};
// Special headers
if (this.$route.name === 'thisday' && (!prevDay || Math.abs(prevDay.dayid - day.dayid) > 30)) {
if (this.routeIsThisDay && (!prevDay || Math.abs(prevDay.dayid - day.dayid) > 30)) {
// thisday view with new year title
head.size = 67;
head.super = utils.getFromNowStr(utils.dayIdToDate(day.dayid));

View File

@ -46,7 +46,7 @@ export default defineComponent({
async open(edit: boolean) {
if (edit) {
try {
this.album = await dav.getAlbum(<string>this.$route.params.user, <string>this.$route.params.name);
this.album = await dav.getAlbum(this.$route.params.user, this.$route.params.name);
} catch (e) {
console.error(e);
showError(this.t('photos', 'Could not load the selected album'));

View File

@ -65,8 +65,7 @@ export default defineComponent({
async open() {
this.show = true;
this.loadingAddCollaborators = true;
const user = <string>this.$route.params.user || '';
const name = <string>this.$route.params.name || '';
const { user, name } = this.$route.params;
this.album = await dav.getAlbum(user, name);
this.loadingAddCollaborators = false;
},

View File

@ -72,13 +72,13 @@ export default defineComponent({
},
refreshParams() {
this.user = <string>this.$route.params.user || '';
this.name = <string>this.$route.params.name || '';
this.user = this.$route.params.user;
this.name = this.$route.params.name;
},
async save() {
try {
if (this.$route.name === 'recognize') {
if (this.routeIsRecognize) {
await dav.recognizeDeleteFace(this.user, this.name);
} else {
await dav.faceRecognitionSetPersonVisibility(this.name, false);

View File

@ -103,7 +103,7 @@ export default defineComponent({
if (!this.canSave) return;
try {
if (this.$route.name === 'recognize') {
if (this.routeIsRecognize) {
await dav.recognizeRenameFace(this.user, this.oldName, this.name);
} else {
await dav.faceRecognitionRenamePerson(this.oldName, this.name);

View File

@ -85,12 +85,15 @@ export default defineComponent({
methods: {
async refreshParams() {
this.user = <string>this.$route.params.user || '';
this.name = <string>this.$route.params.name || '';
this.user = this.$route.params.user;
this.name = this.$route.params.name;
this.list = null;
this.search = '';
const faces = await dav.getFaceList(this.$route.name as any);
const backend = this.routeIsRecognize ? 'recognize' : this.routeIsFaceRecognition ? 'facerecognition' : null;
console.assert(backend, '[BUG] Invalid route for FaceList');
const faces = await dav.getFaceList(backend!);
this.list = faces.filter((c: IFace) => c.user_id === this.user && String(c.name || c.cluster_id) !== this.name);
this.fuse = new Fuse(this.list, { keys: ['name'] });

View File

@ -180,9 +180,7 @@ export default defineComponent({
},
async downloadAlbum() {
const res = await axios.post(
API.ALBUM_DOWNLOAD(<string>this.$route.params.user, <string>this.$route.params.name),
);
const res = await axios.post(API.ALBUM_DOWNLOAD(this.$route.params.user, this.$route.params.name));
if (res.status === 200 && res.data.handle) {
downloadWithHandle(res.data.handle);
}

View File

@ -29,14 +29,14 @@ export default defineComponent({
computed: {
viewname(): string {
return strings.viewName(this.$route.name);
return strings.viewName(this.$route.name!);
},
name(): string | null {
switch (this.$route.name) {
case 'tags':
case _m.routes.Tags.name:
return this.t('recognize', this.$route.params.name);
case 'places':
case _m.routes.Places.name:
return this.$route.params.name?.split('-').slice(1).join('-');
default:
return null;

View File

@ -63,7 +63,7 @@ export default defineComponent({
return '';
}
return strings.viewName(this.$route.name);
return strings.viewName(this.$route.name!);
},
},

View File

@ -38,7 +38,7 @@ export default defineComponent({
computed: {
emptyViewDescription(): string {
return strings.emptyDescription(this.$route.name);
return strings.emptyDescription(this.$route.name!);
},
},
});

View File

@ -44,15 +44,15 @@ export default defineComponent({
computed: {
currentmatter() {
switch (this.$route.name) {
case 'folders':
case _m.routes.Folders.name:
return FolderTopMatter;
case 'albums':
case _m.routes.Albums.name:
return AlbumTopMatter;
case 'tags':
case 'places':
case _m.routes.Tags.name:
case _m.routes.Places.name:
return ClusterTopMatter;
case 'recognize':
case 'facerecognition':
case _m.routes.Recognize.name:
case _m.routes.FaceRecognition.name:
return FaceTopMatter;
default:
return null;

3
src/globals.d.ts vendored
View File

@ -8,7 +8,7 @@ import type videojsType from 'video.js';
import type { IPhoto, IRow } from './types';
import type { constants, initstate } from './services/utils';
import type { GlobalRouteCheckers } from './router';
import type { GlobalRouteCheckers, routes } from './router';
// Global exposed variables
declare global {
@ -32,6 +32,7 @@ declare global {
var _m: {
mode: 'admin' | 'user';
route: Route;
routes: typeof routes;
modals: {
editMetadata: (photos: IPhoto[], sections?: number[]) => void;

View File

@ -31,7 +31,7 @@ export type RouteId =
| 'Explore'
| 'NxSetup';
const routes: { [key in RouteId]: RouteConfig } = {
export const routes: { [key in RouteId]: RouteConfig } = {
Base: {
path: '/',
component: Timeline,
@ -176,15 +176,17 @@ function defineRouteChecker(key: keyof GlobalRouteCheckers, condition: (route?:
});
}
// Defined routes
// Build basic route checkers
for (const [key, value] of Object.entries(routes)) {
defineRouteChecker(`routeIs${<keyof typeof routes>key}`, (route) => route?.name === value.name);
}
// Extra route checkers
defineRouteChecker('routeIsPublic', (route) => route?.name?.endsWith('-share') ?? false);
defineRouteChecker('routeIsPeople', (route) => ['recognize', 'facerecognition'].includes(route?.name ?? ''));
defineRouteChecker('routeIsPeople', (route) =>
[routes.Recognize.name, routes.FaceRecognition.name].includes(route?.name ?? ''),
);
defineRouteChecker(
'routeIsRecognizeUnassigned',
(route) => route?.name === 'recognize' && route.params.name === c.FACE_NULL,
(route) => route?.name === routes.Recognize.name && route!.params.name === c.FACE_NULL,
);

View File

@ -7,11 +7,11 @@ const gen = generateUrl;
/** Add auth token to this URL */
function tok(url: string) {
const token = <string>_m.route.params.token;
const { token } = _m.route.params;
switch (_m.route.name) {
case 'folder-share':
case _m.routes.FolderShare.name:
return API.Q(url, { token });
case 'album-share':
case _m.routes.AlbumShare.name:
return API.Q(url, { token, albums: token });
}
return url;

View File

@ -29,8 +29,8 @@ type GetFilesOpts = {
export async function getFiles(photos: IPhoto[], opts?: GetFilesOpts): Promise<IFileInfo[]> {
// Some routes may have special handling of filenames
if (!opts?.ignoreRoute) {
if (_m.route.name === 'albums') {
return getAlbumFileInfos(photos, <string>_m.route.params.user, <string>_m.route.params.name);
if (_m.route.name === _m.routes.Albums.name) {
return getAlbumFileInfos(photos, _m.route.params.user, _m.route.params.name);
}
}
@ -192,7 +192,7 @@ export async function* deletePhotos(photos: IPhoto[], confirm: boolean = true) {
if (photos.length === 0) return;
// Extend with Live Photos unless this is an album
const routeIsAlbums = _m.route.name === 'albums';
const routeIsAlbums = _m.route.name === _m.routes.Albums.name;
if (!routeIsAlbums) {
photos = await extendWithLivePhotos(photos);
}

View File

@ -1,59 +1,57 @@
import staticConfig from './static-config';
import { translate as t } from '@nextcloud/l10n';
type RouteNameType = string | null | undefined;
export function emptyDescription(routeName: RouteNameType): string {
export function emptyDescription(routeName: string): string {
switch (routeName) {
case 'timeline':
case _m.routes.Base.name:
return t('memories', 'Upload some photos and make sure the timeline path is configured');
case 'favorites':
case _m.routes.Favorites.name:
return t('memories', 'Mark photos as favorite to find them easily');
case 'thisday':
case _m.routes.ThisDay.name:
return t('memories', 'Memories from past years will appear here');
case 'facerecognition':
case _m.routes.Recognize.name:
return t('memories', 'Recognize is still working on your photos');
case _m.routes.FaceRecognition.name:
return staticConfig.getSync('facerecognition_enabled')
? t('memories', 'You will find your friends soon. Please be patient')
: t('memories', 'Face Recognition is disabled. Enable in settings to find your friends');
case 'videos':
case _m.routes.Videos.name:
return t('memories', 'Your videos will appear here');
case 'albums':
case _m.routes.Albums.name:
return _m.route.params.name
? t('memories', 'Add photos to albums by selecting them on your timeline.')
: t('memories', 'Create an album to get started');
case 'archive':
case _m.routes.Archive.name:
return t('memories', "Archive photos you don't want to see in your timeline");
case 'tags':
case _m.routes.Tags.name:
return t('memories', 'Tag photos to find them easily');
case 'recognize':
return t('memories', 'Recognize is still working on your photos');
case 'places':
case _m.routes.Places.name:
return t('memories', 'Places you have been to will appear here');
default:
return '';
return String();
}
}
export function viewName(routeName: RouteNameType): string {
export function viewName(routeName: string): string {
switch (routeName) {
case 'favorites':
case _m.routes.Favorites.name:
return t('memories', 'Favorites');
case 'recognize':
case 'facerecognition':
case _m.routes.Recognize.name:
case _m.routes.FaceRecognition.name:
return t('memories', 'People');
case 'videos':
case _m.routes.Videos.name:
return t('memories', 'Videos');
case 'albums':
case _m.routes.Albums.name:
return t('memories', 'Albums');
case 'archive':
case _m.routes.Archive.name:
return t('memories', 'Archive');
case 'thisday':
case _m.routes.ThisDay.name:
return t('memories', 'On this day');
case 'tags':
case _m.routes.Tags.name:
return t('memories', 'Tags');
case 'places':
case _m.routes.Places.name:
return t('memories', 'Places');
default:
return '';
return String();
}
}