refactor: improve typing

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/803/head
Varun Patil 2023-08-25 14:47:57 -07:00
parent fbcec52de4
commit 65cd1952ff
22 changed files with 95 additions and 69 deletions

View File

@ -40,8 +40,10 @@
<script lang="ts">
import { defineComponent } from 'vue';
import config from '../services/static-config';
import type { Component } from 'vue';
import axios from '@nextcloud/axios';
import { translate as t } from '@nextcloud/l10n';
import ClusterHList from './ClusterHList.vue';
@ -55,9 +57,10 @@ import CalendarIcon from 'vue-material-design-icons/Calendar.vue';
import MapIcon from 'vue-material-design-icons/Map.vue';
import CogIcon from 'vue-material-design-icons/Cog.vue';
import type { ICluster, IConfig } from '../types';
import config from '../services/static-config';
import { API } from '../services/API';
import { translate as t } from '@nextcloud/l10n';
import type { ICluster, IConfig } from '../types';
export default defineComponent({
name: 'Explore',
@ -110,7 +113,7 @@ export default defineComponent({
},
] as {
name: string;
icon: any;
icon: Component;
link?: string;
click?: () => void;
}[],

View File

@ -67,6 +67,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import type { Component } from 'vue';
import NcActions from '@nextcloud/vue/dist/Components/NcActions';
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton';
@ -97,7 +98,7 @@ interface TopField {
id?: string;
title: string;
subtitle: string[];
icon: any;
icon: Component;
href?: string;
edit?: () => void;
}
@ -117,7 +118,7 @@ export default defineComponent({
data: () => ({
fileid: null as number | null,
filename: '',
exif: {} as { [prop: string]: any },
exif: {} as NonNullable<IImageInfo['exif']>,
baseInfo: {} as IImageInfo,
loading: 0,
@ -210,8 +211,8 @@ export default defineComponent({
// The fallback to datetaken can be eventually removed
// and then this can be discarded
if (this.exif.DateTimeEpoch) {
const tzOffset: string = this.exif.OffsetTimeOriginal || this.exif.OffsetTime; // e.g. -05:00
const tzId: string = this.exif.LocationTZID; // e.g. America/New_York
const tzOffset = this.exif.OffsetTimeOriginal || this.exif.OffsetTime; // e.g. -05:00
const tzId = this.exif.LocationTZID; // e.g. America/New_York
let dateWithTz: DateTime | undefined = undefined;

View File

@ -90,6 +90,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import type { Route } from 'vue-router';
import axios from '@nextcloud/axios';
import { showError } from '@nextcloud/dialogs';
@ -182,7 +183,7 @@ export default defineComponent({
},
watch: {
async $route(to: any, from?: any) {
async $route(to: Route, from?: Route) {
await this.routeChange(to, from);
},
},
@ -228,7 +229,7 @@ export default defineComponent({
},
methods: {
async routeChange(to: any, from?: any) {
async routeChange(to: Route, from?: Route) {
// Always do a hard refresh if the path changes
if (from?.path !== to.path) {
await this.refresh();
@ -444,7 +445,7 @@ export default defineComponent({
* This does NOT indicate the items have changed, only that
* the pixel position of the recycler has changed.
*/
scrollPositionChange(event?: any) {
scrollPositionChange(event?: Event) {
this.scrollerManager().recyclerScrolled(event);
},
@ -549,40 +550,41 @@ export default defineComponent({
/** Get query string for API calls */
getQuery() {
const query: { [key: string]: string } = {};
const query: { [key in DaysFilterType]?: string } = {};
const set = (filter: DaysFilterType, value: string = '1') => (query[filter] = value);
// Favorites
if (this.$route.name === 'favorites') {
API.DAYS_FILTER(query, DaysFilterType.FAVORITES);
if (this.routeIsFavorites) {
set(DaysFilterType.FAVORITES);
}
// Videos
if (this.$route.name === 'videos') {
API.DAYS_FILTER(query, DaysFilterType.VIDEOS);
if (this.routeIsVideos) {
set(DaysFilterType.VIDEOS);
}
// Folder
if (this.$route.name === 'folders') {
if (this.routeIsFolders) {
const path = utils.getFolderRoutePath(this.config.folders_path);
API.DAYS_FILTER(query, DaysFilterType.FOLDER, path);
set(DaysFilterType.FOLDER, path);
if (this.$route.query.recursive) {
API.DAYS_FILTER(query, DaysFilterType.RECURSIVE);
set(DaysFilterType.RECURSIVE);
}
}
// Archive
if (this.$route.name === 'archive') {
API.DAYS_FILTER(query, DaysFilterType.ARCHIVE);
if (this.routeIsArchive) {
set(DaysFilterType.ARCHIVE);
}
// Albums
const user = <string>this.$route.params.user;
const name = <string>this.$route.params.name;
if (this.$route.name === 'albums') {
if (this.routeIsAlbums) {
if (!user || !name) {
throw new Error('Invalid album route');
}
API.DAYS_FILTER(query, DaysFilterType.ALBUM, `${user}/${name}`);
set(DaysFilterType.ALBUM, `${user}/${name}`);
}
// People
@ -591,47 +593,48 @@ export default defineComponent({
throw new Error('Invalid album route');
}
// name is "recognize" or "facerecognition"
const filter = <DaysFilterType>this.$route.name;
API.DAYS_FILTER(query, filter, `${user}/${name}`);
set(filter, `${user}/${name}`);
// Face rect
if (this.config.show_face_rect || this.routeIsRecognizeUnassigned) {
API.DAYS_FILTER(query, DaysFilterType.FACE_RECT);
set(DaysFilterType.FACE_RECT);
}
}
// Places
if (this.$route.name === 'places') {
if (this.routeIsPlaces) {
if (!name || !name.includes('-')) {
throw new Error('Invalid place route');
}
const id = <string>name.split('-', 1)[0];
API.DAYS_FILTER(query, DaysFilterType.PLACE, id);
set(DaysFilterType.PLACE, id);
}
// Tags
if (this.$route.name === 'tags') {
if (this.routeIsTags) {
if (!name) {
throw new Error('Invalid tag route');
}
API.DAYS_FILTER(query, DaysFilterType.TAG, name);
set(DaysFilterType.TAG, name);
}
// Map Bounds
if (this.$route.name === 'map') {
if (this.routeIsMap) {
const bounds = <string>this.$route.query.b;
if (!bounds) {
throw new Error('Missing map bounds');
}
API.DAYS_FILTER(query, DaysFilterType.MAP_BOUNDS, bounds);
set(DaysFilterType.MAP_BOUNDS, bounds);
}
// Month view
if (this.isMonthView) {
API.DAYS_FILTER(query, DaysFilterType.MONTH_VIEW);
API.DAYS_FILTER(query, DaysFilterType.REVERSE);
set(DaysFilterType.MONTH_VIEW);
set(DaysFilterType.REVERSE);
}
return query;

View File

@ -226,7 +226,7 @@ export default defineComponent({
},
/** Error in loading image */
error(e: any) {
error(e: Event) {
this.data.flag |= this.c.FLAG_LOAD_FAIL;
},

View File

@ -37,7 +37,7 @@ const expirationManager = new CacheExpiration(cacheName, {
});
// Start fetching with multipreview
let fetchPreviewTimer: any;
let fetchPreviewTimer: number;
/** Flushes the queue of preview image requests */
async function flushPreviewQueue() {

View File

@ -62,7 +62,7 @@ export default defineComponent({
this.$emit('close');
},
done({ album }: any) {
done({ album }: { album: { basename: string; filename: string } }) {
if (!this.album || album.basename !== this.album.basename) {
const user = album.filename.split('/')[2];
const name = album.basename;

View File

@ -41,7 +41,7 @@ export default defineComponent({
}),
watch: {
$route: async function (from: any, to: any) {
$route() {
this.refreshParams();
},
},

View File

@ -163,7 +163,7 @@ export default defineComponent({
},
methods: {
submit(collaborators: any = []) {
submit(collaborators: any[] = []) {
if (this.albumName === '' || this.loading) {
return;
}
@ -181,7 +181,7 @@ export default defineComponent({
}
},
async handleCreateAlbum(collaborators = []) {
async handleCreateAlbum(collaborators: any[] = []) {
try {
this.loading = true;
let album = {

View File

@ -64,7 +64,7 @@ export default defineComponent({
},
methods: {
click($event: any, album: IAlbum) {
click($event: Event, album: IAlbum) {
if (!this.link) {
$event.preventDefault();
}

View File

@ -28,6 +28,11 @@ const NcTextField = () => import('@nextcloud/vue/dist/Components/NcTextField');
import { translate as t } from '@nextcloud/l10n';
interface IField {
field: string;
label: string;
}
export default defineComponent({
components: {
NcTextField,
@ -41,8 +46,8 @@ export default defineComponent({
},
data: () => ({
exif: null as any,
dirty: {},
exif: null! as Record<string, string>,
dirty: {} as Record<string, boolean>,
fields: [
{
@ -73,7 +78,7 @@ export default defineComponent({
field: 'Copyright',
label: t('memories', 'Copyright'),
},
],
] as IField[],
}),
mounted() {
@ -95,7 +100,7 @@ export default defineComponent({
if (ePhoto && (eCurr === null || ePhoto === eCurr)) {
exif[field.field] = String(ePhoto);
} else {
exif[field.field] = '';
exif[field.field] = String();
}
}
}
@ -114,15 +119,15 @@ export default defineComponent({
return diff;
},
label(field: any) {
label(field: IField) {
return field.label + (this.dirty[field.field] ? '*' : '');
},
placeholder(field: any) {
placeholder(field: IField) {
return this.dirty[field.field] ? t('memories', 'Empty') : t('memories', 'Unchanged');
},
reset(field: any) {
reset(field: IField) {
this.exif[field.field] = '';
this.dirty[field.field] = false;
},

View File

@ -44,7 +44,7 @@ export default defineComponent({
},
watch: {
$route: async function (from: any, to: any) {
$route() {
this.refreshParams();
},
},

View File

@ -55,7 +55,7 @@ export default defineComponent({
},
watch: {
$route: async function (from: any, to: any) {
$route() {
this.refreshParams();
},
},

View File

@ -63,7 +63,7 @@ export default defineComponent({
}),
watch: {
$route: async function (from: any, to: any) {
$route() {
this.refreshParams();
},
},

View File

@ -135,7 +135,7 @@ export default defineComponent({
},
isLocal(): boolean {
return utils.isLocalPhoto(this.photo);
return utils.isLocalPhoto(this.photo!);
},
},

View File

@ -7,6 +7,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { Component } from 'vue';
import UserMixin from '../../mixins/UserConfig';
@ -23,7 +24,7 @@ export default defineComponent({
mixins: [UserMixin],
computed: {
currentmatter(): any {
currentmatter(): Component | null {
if (this.routeIsFolders) {
return FolderDynamicTopMatter;
} else if (this.routeIsPlaces) {

View File

@ -340,7 +340,7 @@ export default defineComponent({
/** Is the current slide a local photo */
isLocal(): boolean {
return utils.isLocalPhoto(this.currentPhoto);
return utils.isLocalPhoto(this.currentPhoto!);
},
/** Show bottom bar info such as date taken */
@ -418,16 +418,16 @@ export default defineComponent({
},
/** User interacted with the page with mouse */
setUiVisible(evt: any) {
setUiVisible(event: PointerEvent | false) {
clearTimeout(this.activityTimer);
if (evt) {
if (event) {
// If directly triggered, always update ui visibility
// If triggered through a pointer event, only update if this is not
// a touch event (i.e. a mouse move).
// On touch devices, tapAction directly handles the ui visibility
// through Photoswipe.
const isPointer = evt instanceof PointerEvent;
const isMouse = isPointer && evt.pointerType !== 'touch';
const isPointer = event instanceof PointerEvent;
const isMouse = isPointer && event.pointerType !== 'touch';
if (this.isOpen && (!isPointer || isMouse)) {
this.photoswipe?.template?.classList.add('pswp--ui-visible');

View File

@ -16,6 +16,12 @@ export default defineComponent({
routeIsBase(): boolean {
return this.$route.name === 'timeline';
},
routeIsFavorites(): boolean {
return this.$route.name === 'favorites';
},
routeIsVideos(): boolean {
return this.$route.name === 'videos';
},
routeIsFolders(): boolean {
return this.$route.name === 'folders';
},

View File

@ -76,10 +76,6 @@ export class API {
return tok(gen(`${BASE}/days/{id}`, { id }));
}
static DAYS_FILTER(query: any, filter: DaysFilterType, value: string = '1') {
query[filter] = value;
}
static FOLDERS_SUB() {
return tok(gen(`${BASE}/folders/sub`));
}

View File

@ -6,7 +6,7 @@
* @param elem Element to search for
* @param key Key to use for comparison
*/
export function binarySearch(arr: any, elem: any, key?: string) {
export function binarySearch<T, K extends keyof T>(arr: T[], elem: T | T[K], key?: K): number {
if (arr.length === 0) return 0;
const desc = key ? arr[0][key] > arr[arr.length - 1][key] : arr[0] > arr[arr.length - 1];
@ -56,7 +56,7 @@ export function roundHalf(num: number) {
}
/** Choose a random element from an array */
export function randomChoice(arr: any[]) {
export function randomChoice<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)];
}
@ -64,7 +64,7 @@ export function randomChoice(arr: any[]) {
* Choose a random sub array from an array
* https://stackoverflow.com/a/11935263/4745239
*/
export function randomSubarray(arr: any[], size: number) {
export function randomSubarray<T>(arr: T[], size: number): T[] {
if (arr.length <= size) return arr;
var shuffled = arr.slice(0),
i = arr.length,
@ -81,7 +81,7 @@ export function randomSubarray(arr: any[], size: number) {
}
/** Set a timer that renews if existing */
export function setRenewingTimeout(ctx: any, name: string, callback: (() => void) | null, delay: number) {
export function setRenewingTimeout<T>(ctx: T, name: string, callback: (() => void) | null, delay: number): void {
if (ctx[name]) window.clearTimeout(ctx[name]);
ctx[name] = window.setTimeout(() => {
ctx[name] = 0;
@ -90,7 +90,7 @@ export function setRenewingTimeout(ctx: any, name: string, callback: (() => void
}
/** Checks if a object is numeric */
export function isNumber(num: any): boolean {
export function isNumber<T>(num: T): boolean {
const cast = Number(num);
return !isNaN(cast) && isFinite(cast);
}

View File

@ -90,8 +90,8 @@ export function getPreviewUrl(opts: PreviewOptsSize | PreviewOptsMsize | Preview
* Check if the object is a local photo
* @param photo Photo object
*/
export function isLocalPhoto(photo: any): boolean {
return typeof photo === 'object' && photo?.fileid && Boolean((photo?.flag ?? 0) & constants.c.FLAG_IS_LOCAL);
export function isLocalPhoto(photo: IPhoto): boolean {
return Boolean(photo?.fileid) && Boolean((photo?.flag ?? 0) & constants.c.FLAG_IS_LOCAL);
}
/**
@ -102,7 +102,7 @@ export function isLocalPhoto(photo: any): boolean {
export function getImageInfoUrl(photo: IPhoto | number): string {
const fileid = typeof photo === 'number' ? photo : photo.fileid;
if (isLocalPhoto(photo)) {
if (typeof photo === 'object' && isLocalPhoto(photo)) {
return nativex.API.IMAGE_INFO(fileid);
}

View File

@ -111,8 +111,17 @@ export interface IImageInfo {
Orientation?: number;
ImageWidth?: number;
ImageHeight?: number;
Title?: string;
Description?: string;
Make?: string;
Model?: string;
DateTimeEpoch?: number;
OffsetTimeOriginal?: string;
OffsetTime?: string;
LocationTZID?: string;
[other: string]: unknown;
};

View File

@ -12,6 +12,8 @@ declare module 'vue' {
state_noDownload: boolean;
routeIsBase: boolean;
routeIsFavorites: boolean;
routeIsVideos: boolean;
routeIsFolders: boolean;
routeIsAlbums: boolean;
routeIsPeople: boolean;