refactor: improve typing
Signed-off-by: Varun Patil <radialapps@gmail.com>pull/803/head
parent
fbcec52de4
commit
65cd1952ff
|
@ -40,8 +40,10 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import config from '../services/static-config';
|
import type { Component } from 'vue';
|
||||||
|
|
||||||
import axios from '@nextcloud/axios';
|
import axios from '@nextcloud/axios';
|
||||||
|
import { translate as t } from '@nextcloud/l10n';
|
||||||
|
|
||||||
import ClusterHList from './ClusterHList.vue';
|
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 MapIcon from 'vue-material-design-icons/Map.vue';
|
||||||
import CogIcon from 'vue-material-design-icons/Cog.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 { API } from '../services/API';
|
||||||
import { translate as t } from '@nextcloud/l10n';
|
|
||||||
|
import type { ICluster, IConfig } from '../types';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Explore',
|
name: 'Explore',
|
||||||
|
@ -110,7 +113,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
] as {
|
] as {
|
||||||
name: string;
|
name: string;
|
||||||
icon: any;
|
icon: Component;
|
||||||
link?: string;
|
link?: string;
|
||||||
click?: () => void;
|
click?: () => void;
|
||||||
}[],
|
}[],
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import type { Component } from 'vue';
|
||||||
|
|
||||||
import NcActions from '@nextcloud/vue/dist/Components/NcActions';
|
import NcActions from '@nextcloud/vue/dist/Components/NcActions';
|
||||||
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton';
|
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton';
|
||||||
|
@ -97,7 +98,7 @@ interface TopField {
|
||||||
id?: string;
|
id?: string;
|
||||||
title: string;
|
title: string;
|
||||||
subtitle: string[];
|
subtitle: string[];
|
||||||
icon: any;
|
icon: Component;
|
||||||
href?: string;
|
href?: string;
|
||||||
edit?: () => void;
|
edit?: () => void;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +118,7 @@ export default defineComponent({
|
||||||
data: () => ({
|
data: () => ({
|
||||||
fileid: null as number | null,
|
fileid: null as number | null,
|
||||||
filename: '',
|
filename: '',
|
||||||
exif: {} as { [prop: string]: any },
|
exif: {} as NonNullable<IImageInfo['exif']>,
|
||||||
baseInfo: {} as IImageInfo,
|
baseInfo: {} as IImageInfo,
|
||||||
|
|
||||||
loading: 0,
|
loading: 0,
|
||||||
|
@ -210,8 +211,8 @@ export default defineComponent({
|
||||||
// The fallback to datetaken can be eventually removed
|
// The fallback to datetaken can be eventually removed
|
||||||
// and then this can be discarded
|
// and then this can be discarded
|
||||||
if (this.exif.DateTimeEpoch) {
|
if (this.exif.DateTimeEpoch) {
|
||||||
const tzOffset: string = this.exif.OffsetTimeOriginal || this.exif.OffsetTime; // e.g. -05:00
|
const tzOffset = this.exif.OffsetTimeOriginal || this.exif.OffsetTime; // e.g. -05:00
|
||||||
const tzId: string = this.exif.LocationTZID; // e.g. America/New_York
|
const tzId = this.exif.LocationTZID; // e.g. America/New_York
|
||||||
|
|
||||||
let dateWithTz: DateTime | undefined = undefined;
|
let dateWithTz: DateTime | undefined = undefined;
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import type { Route } from 'vue-router';
|
||||||
|
|
||||||
import axios from '@nextcloud/axios';
|
import axios from '@nextcloud/axios';
|
||||||
import { showError } from '@nextcloud/dialogs';
|
import { showError } from '@nextcloud/dialogs';
|
||||||
|
@ -182,7 +183,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
async $route(to: any, from?: any) {
|
async $route(to: Route, from?: Route) {
|
||||||
await this.routeChange(to, from);
|
await this.routeChange(to, from);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -228,7 +229,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async routeChange(to: any, from?: any) {
|
async routeChange(to: Route, from?: Route) {
|
||||||
// Always do a hard refresh if the path changes
|
// Always do a hard refresh if the path changes
|
||||||
if (from?.path !== to.path) {
|
if (from?.path !== to.path) {
|
||||||
await this.refresh();
|
await this.refresh();
|
||||||
|
@ -444,7 +445,7 @@ export default defineComponent({
|
||||||
* This does NOT indicate the items have changed, only that
|
* This does NOT indicate the items have changed, only that
|
||||||
* the pixel position of the recycler has changed.
|
* the pixel position of the recycler has changed.
|
||||||
*/
|
*/
|
||||||
scrollPositionChange(event?: any) {
|
scrollPositionChange(event?: Event) {
|
||||||
this.scrollerManager().recyclerScrolled(event);
|
this.scrollerManager().recyclerScrolled(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -549,40 +550,41 @@ export default defineComponent({
|
||||||
|
|
||||||
/** Get query string for API calls */
|
/** Get query string for API calls */
|
||||||
getQuery() {
|
getQuery() {
|
||||||
const query: { [key: string]: string } = {};
|
const query: { [key in DaysFilterType]?: string } = {};
|
||||||
|
const set = (filter: DaysFilterType, value: string = '1') => (query[filter] = value);
|
||||||
|
|
||||||
// Favorites
|
// Favorites
|
||||||
if (this.$route.name === 'favorites') {
|
if (this.routeIsFavorites) {
|
||||||
API.DAYS_FILTER(query, DaysFilterType.FAVORITES);
|
set(DaysFilterType.FAVORITES);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Videos
|
// Videos
|
||||||
if (this.$route.name === 'videos') {
|
if (this.routeIsVideos) {
|
||||||
API.DAYS_FILTER(query, DaysFilterType.VIDEOS);
|
set(DaysFilterType.VIDEOS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Folder
|
// Folder
|
||||||
if (this.$route.name === 'folders') {
|
if (this.routeIsFolders) {
|
||||||
const path = utils.getFolderRoutePath(this.config.folders_path);
|
const path = utils.getFolderRoutePath(this.config.folders_path);
|
||||||
API.DAYS_FILTER(query, DaysFilterType.FOLDER, path);
|
set(DaysFilterType.FOLDER, path);
|
||||||
if (this.$route.query.recursive) {
|
if (this.$route.query.recursive) {
|
||||||
API.DAYS_FILTER(query, DaysFilterType.RECURSIVE);
|
set(DaysFilterType.RECURSIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Archive
|
// Archive
|
||||||
if (this.$route.name === 'archive') {
|
if (this.routeIsArchive) {
|
||||||
API.DAYS_FILTER(query, DaysFilterType.ARCHIVE);
|
set(DaysFilterType.ARCHIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Albums
|
// Albums
|
||||||
const user = <string>this.$route.params.user;
|
const user = <string>this.$route.params.user;
|
||||||
const name = <string>this.$route.params.name;
|
const name = <string>this.$route.params.name;
|
||||||
if (this.$route.name === 'albums') {
|
if (this.routeIsAlbums) {
|
||||||
if (!user || !name) {
|
if (!user || !name) {
|
||||||
throw new Error('Invalid album route');
|
throw new Error('Invalid album route');
|
||||||
}
|
}
|
||||||
API.DAYS_FILTER(query, DaysFilterType.ALBUM, `${user}/${name}`);
|
set(DaysFilterType.ALBUM, `${user}/${name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// People
|
// People
|
||||||
|
@ -591,47 +593,48 @@ export default defineComponent({
|
||||||
throw new Error('Invalid album route');
|
throw new Error('Invalid album route');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// name is "recognize" or "facerecognition"
|
||||||
const filter = <DaysFilterType>this.$route.name;
|
const filter = <DaysFilterType>this.$route.name;
|
||||||
API.DAYS_FILTER(query, filter, `${user}/${name}`);
|
set(filter, `${user}/${name}`);
|
||||||
|
|
||||||
// Face rect
|
// Face rect
|
||||||
if (this.config.show_face_rect || this.routeIsRecognizeUnassigned) {
|
if (this.config.show_face_rect || this.routeIsRecognizeUnassigned) {
|
||||||
API.DAYS_FILTER(query, DaysFilterType.FACE_RECT);
|
set(DaysFilterType.FACE_RECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Places
|
// Places
|
||||||
if (this.$route.name === 'places') {
|
if (this.routeIsPlaces) {
|
||||||
if (!name || !name.includes('-')) {
|
if (!name || !name.includes('-')) {
|
||||||
throw new Error('Invalid place route');
|
throw new Error('Invalid place route');
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = <string>name.split('-', 1)[0];
|
const id = <string>name.split('-', 1)[0];
|
||||||
API.DAYS_FILTER(query, DaysFilterType.PLACE, id);
|
set(DaysFilterType.PLACE, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
if (this.$route.name === 'tags') {
|
if (this.routeIsTags) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new Error('Invalid tag route');
|
throw new Error('Invalid tag route');
|
||||||
}
|
}
|
||||||
API.DAYS_FILTER(query, DaysFilterType.TAG, name);
|
set(DaysFilterType.TAG, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map Bounds
|
// Map Bounds
|
||||||
if (this.$route.name === 'map') {
|
if (this.routeIsMap) {
|
||||||
const bounds = <string>this.$route.query.b;
|
const bounds = <string>this.$route.query.b;
|
||||||
if (!bounds) {
|
if (!bounds) {
|
||||||
throw new Error('Missing map bounds');
|
throw new Error('Missing map bounds');
|
||||||
}
|
}
|
||||||
|
|
||||||
API.DAYS_FILTER(query, DaysFilterType.MAP_BOUNDS, bounds);
|
set(DaysFilterType.MAP_BOUNDS, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Month view
|
// Month view
|
||||||
if (this.isMonthView) {
|
if (this.isMonthView) {
|
||||||
API.DAYS_FILTER(query, DaysFilterType.MONTH_VIEW);
|
set(DaysFilterType.MONTH_VIEW);
|
||||||
API.DAYS_FILTER(query, DaysFilterType.REVERSE);
|
set(DaysFilterType.REVERSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
|
|
@ -226,7 +226,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Error in loading image */
|
/** Error in loading image */
|
||||||
error(e: any) {
|
error(e: Event) {
|
||||||
this.data.flag |= this.c.FLAG_LOAD_FAIL;
|
this.data.flag |= this.c.FLAG_LOAD_FAIL;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ const expirationManager = new CacheExpiration(cacheName, {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start fetching with multipreview
|
// Start fetching with multipreview
|
||||||
let fetchPreviewTimer: any;
|
let fetchPreviewTimer: number;
|
||||||
|
|
||||||
/** Flushes the queue of preview image requests */
|
/** Flushes the queue of preview image requests */
|
||||||
async function flushPreviewQueue() {
|
async function flushPreviewQueue() {
|
||||||
|
|
|
@ -62,7 +62,7 @@ export default defineComponent({
|
||||||
this.$emit('close');
|
this.$emit('close');
|
||||||
},
|
},
|
||||||
|
|
||||||
done({ album }: any) {
|
done({ album }: { album: { basename: string; filename: string } }) {
|
||||||
if (!this.album || album.basename !== this.album.basename) {
|
if (!this.album || album.basename !== this.album.basename) {
|
||||||
const user = album.filename.split('/')[2];
|
const user = album.filename.split('/')[2];
|
||||||
const name = album.basename;
|
const name = album.basename;
|
||||||
|
|
|
@ -41,7 +41,7 @@ export default defineComponent({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route: async function (from: any, to: any) {
|
$route() {
|
||||||
this.refreshParams();
|
this.refreshParams();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -163,7 +163,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
submit(collaborators: any = []) {
|
submit(collaborators: any[] = []) {
|
||||||
if (this.albumName === '' || this.loading) {
|
if (this.albumName === '' || this.loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async handleCreateAlbum(collaborators = []) {
|
async handleCreateAlbum(collaborators: any[] = []) {
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
let album = {
|
let album = {
|
||||||
|
|
|
@ -64,7 +64,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
click($event: any, album: IAlbum) {
|
click($event: Event, album: IAlbum) {
|
||||||
if (!this.link) {
|
if (!this.link) {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@ const NcTextField = () => import('@nextcloud/vue/dist/Components/NcTextField');
|
||||||
|
|
||||||
import { translate as t } from '@nextcloud/l10n';
|
import { translate as t } from '@nextcloud/l10n';
|
||||||
|
|
||||||
|
interface IField {
|
||||||
|
field: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
NcTextField,
|
NcTextField,
|
||||||
|
@ -41,8 +46,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
exif: null as any,
|
exif: null! as Record<string, string>,
|
||||||
dirty: {},
|
dirty: {} as Record<string, boolean>,
|
||||||
|
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
|
@ -73,7 +78,7 @@ export default defineComponent({
|
||||||
field: 'Copyright',
|
field: 'Copyright',
|
||||||
label: t('memories', 'Copyright'),
|
label: t('memories', 'Copyright'),
|
||||||
},
|
},
|
||||||
],
|
] as IField[],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -95,7 +100,7 @@ export default defineComponent({
|
||||||
if (ePhoto && (eCurr === null || ePhoto === eCurr)) {
|
if (ePhoto && (eCurr === null || ePhoto === eCurr)) {
|
||||||
exif[field.field] = String(ePhoto);
|
exif[field.field] = String(ePhoto);
|
||||||
} else {
|
} else {
|
||||||
exif[field.field] = '';
|
exif[field.field] = String();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,15 +119,15 @@ export default defineComponent({
|
||||||
return diff;
|
return diff;
|
||||||
},
|
},
|
||||||
|
|
||||||
label(field: any) {
|
label(field: IField) {
|
||||||
return field.label + (this.dirty[field.field] ? '*' : '');
|
return field.label + (this.dirty[field.field] ? '*' : '');
|
||||||
},
|
},
|
||||||
|
|
||||||
placeholder(field: any) {
|
placeholder(field: IField) {
|
||||||
return this.dirty[field.field] ? t('memories', 'Empty') : t('memories', 'Unchanged');
|
return this.dirty[field.field] ? t('memories', 'Empty') : t('memories', 'Unchanged');
|
||||||
},
|
},
|
||||||
|
|
||||||
reset(field: any) {
|
reset(field: IField) {
|
||||||
this.exif[field.field] = '';
|
this.exif[field.field] = '';
|
||||||
this.dirty[field.field] = false;
|
this.dirty[field.field] = false;
|
||||||
},
|
},
|
||||||
|
|
|
@ -44,7 +44,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route: async function (from: any, to: any) {
|
$route() {
|
||||||
this.refreshParams();
|
this.refreshParams();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -55,7 +55,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route: async function (from: any, to: any) {
|
$route() {
|
||||||
this.refreshParams();
|
this.refreshParams();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -63,7 +63,7 @@ export default defineComponent({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route: async function (from: any, to: any) {
|
$route() {
|
||||||
this.refreshParams();
|
this.refreshParams();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -135,7 +135,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
isLocal(): boolean {
|
isLocal(): boolean {
|
||||||
return utils.isLocalPhoto(this.photo);
|
return utils.isLocalPhoto(this.photo!);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { Component } from 'vue';
|
||||||
|
|
||||||
import UserMixin from '../../mixins/UserConfig';
|
import UserMixin from '../../mixins/UserConfig';
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ export default defineComponent({
|
||||||
mixins: [UserMixin],
|
mixins: [UserMixin],
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
currentmatter(): any {
|
currentmatter(): Component | null {
|
||||||
if (this.routeIsFolders) {
|
if (this.routeIsFolders) {
|
||||||
return FolderDynamicTopMatter;
|
return FolderDynamicTopMatter;
|
||||||
} else if (this.routeIsPlaces) {
|
} else if (this.routeIsPlaces) {
|
||||||
|
|
|
@ -340,7 +340,7 @@ export default defineComponent({
|
||||||
|
|
||||||
/** Is the current slide a local photo */
|
/** Is the current slide a local photo */
|
||||||
isLocal(): boolean {
|
isLocal(): boolean {
|
||||||
return utils.isLocalPhoto(this.currentPhoto);
|
return utils.isLocalPhoto(this.currentPhoto!);
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Show bottom bar info such as date taken */
|
/** Show bottom bar info such as date taken */
|
||||||
|
@ -418,16 +418,16 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
/** User interacted with the page with mouse */
|
/** User interacted with the page with mouse */
|
||||||
setUiVisible(evt: any) {
|
setUiVisible(event: PointerEvent | false) {
|
||||||
clearTimeout(this.activityTimer);
|
clearTimeout(this.activityTimer);
|
||||||
if (evt) {
|
if (event) {
|
||||||
// If directly triggered, always update ui visibility
|
// If directly triggered, always update ui visibility
|
||||||
// If triggered through a pointer event, only update if this is not
|
// If triggered through a pointer event, only update if this is not
|
||||||
// a touch event (i.e. a mouse move).
|
// a touch event (i.e. a mouse move).
|
||||||
// On touch devices, tapAction directly handles the ui visibility
|
// On touch devices, tapAction directly handles the ui visibility
|
||||||
// through Photoswipe.
|
// through Photoswipe.
|
||||||
const isPointer = evt instanceof PointerEvent;
|
const isPointer = event instanceof PointerEvent;
|
||||||
const isMouse = isPointer && evt.pointerType !== 'touch';
|
const isMouse = isPointer && event.pointerType !== 'touch';
|
||||||
if (this.isOpen && (!isPointer || isMouse)) {
|
if (this.isOpen && (!isPointer || isMouse)) {
|
||||||
this.photoswipe?.template?.classList.add('pswp--ui-visible');
|
this.photoswipe?.template?.classList.add('pswp--ui-visible');
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,12 @@ export default defineComponent({
|
||||||
routeIsBase(): boolean {
|
routeIsBase(): boolean {
|
||||||
return this.$route.name === 'timeline';
|
return this.$route.name === 'timeline';
|
||||||
},
|
},
|
||||||
|
routeIsFavorites(): boolean {
|
||||||
|
return this.$route.name === 'favorites';
|
||||||
|
},
|
||||||
|
routeIsVideos(): boolean {
|
||||||
|
return this.$route.name === 'videos';
|
||||||
|
},
|
||||||
routeIsFolders(): boolean {
|
routeIsFolders(): boolean {
|
||||||
return this.$route.name === 'folders';
|
return this.$route.name === 'folders';
|
||||||
},
|
},
|
||||||
|
|
|
@ -76,10 +76,6 @@ export class API {
|
||||||
return tok(gen(`${BASE}/days/{id}`, { id }));
|
return tok(gen(`${BASE}/days/{id}`, { id }));
|
||||||
}
|
}
|
||||||
|
|
||||||
static DAYS_FILTER(query: any, filter: DaysFilterType, value: string = '1') {
|
|
||||||
query[filter] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FOLDERS_SUB() {
|
static FOLDERS_SUB() {
|
||||||
return tok(gen(`${BASE}/folders/sub`));
|
return tok(gen(`${BASE}/folders/sub`));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* @param elem Element to search for
|
* @param elem Element to search for
|
||||||
* @param key Key to use for comparison
|
* @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;
|
if (arr.length === 0) return 0;
|
||||||
|
|
||||||
const desc = key ? arr[0][key] > arr[arr.length - 1][key] : arr[0] > arr[arr.length - 1];
|
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 */
|
/** 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)];
|
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
|
* Choose a random sub array from an array
|
||||||
* https://stackoverflow.com/a/11935263/4745239
|
* 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;
|
if (arr.length <= size) return arr;
|
||||||
var shuffled = arr.slice(0),
|
var shuffled = arr.slice(0),
|
||||||
i = arr.length,
|
i = arr.length,
|
||||||
|
@ -81,7 +81,7 @@ export function randomSubarray(arr: any[], size: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set a timer that renews if existing */
|
/** 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]);
|
if (ctx[name]) window.clearTimeout(ctx[name]);
|
||||||
ctx[name] = window.setTimeout(() => {
|
ctx[name] = window.setTimeout(() => {
|
||||||
ctx[name] = 0;
|
ctx[name] = 0;
|
||||||
|
@ -90,7 +90,7 @@ export function setRenewingTimeout(ctx: any, name: string, callback: (() => void
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks if a object is numeric */
|
/** Checks if a object is numeric */
|
||||||
export function isNumber(num: any): boolean {
|
export function isNumber<T>(num: T): boolean {
|
||||||
const cast = Number(num);
|
const cast = Number(num);
|
||||||
return !isNaN(cast) && isFinite(cast);
|
return !isNaN(cast) && isFinite(cast);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,8 +90,8 @@ export function getPreviewUrl(opts: PreviewOptsSize | PreviewOptsMsize | Preview
|
||||||
* Check if the object is a local photo
|
* Check if the object is a local photo
|
||||||
* @param photo Photo object
|
* @param photo Photo object
|
||||||
*/
|
*/
|
||||||
export function isLocalPhoto(photo: any): boolean {
|
export function isLocalPhoto(photo: IPhoto): boolean {
|
||||||
return typeof photo === 'object' && photo?.fileid && Boolean((photo?.flag ?? 0) & constants.c.FLAG_IS_LOCAL);
|
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 {
|
export function getImageInfoUrl(photo: IPhoto | number): string {
|
||||||
const fileid = typeof photo === 'number' ? photo : photo.fileid;
|
const fileid = typeof photo === 'number' ? photo : photo.fileid;
|
||||||
|
|
||||||
if (isLocalPhoto(photo)) {
|
if (typeof photo === 'object' && isLocalPhoto(photo)) {
|
||||||
return nativex.API.IMAGE_INFO(fileid);
|
return nativex.API.IMAGE_INFO(fileid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,8 +111,17 @@ export interface IImageInfo {
|
||||||
Orientation?: number;
|
Orientation?: number;
|
||||||
ImageWidth?: number;
|
ImageWidth?: number;
|
||||||
ImageHeight?: number;
|
ImageHeight?: number;
|
||||||
|
|
||||||
Title?: string;
|
Title?: string;
|
||||||
Description?: string;
|
Description?: string;
|
||||||
|
Make?: string;
|
||||||
|
Model?: string;
|
||||||
|
|
||||||
|
DateTimeEpoch?: number;
|
||||||
|
OffsetTimeOriginal?: string;
|
||||||
|
OffsetTime?: string;
|
||||||
|
LocationTZID?: string;
|
||||||
|
|
||||||
[other: string]: unknown;
|
[other: string]: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ declare module 'vue' {
|
||||||
state_noDownload: boolean;
|
state_noDownload: boolean;
|
||||||
|
|
||||||
routeIsBase: boolean;
|
routeIsBase: boolean;
|
||||||
|
routeIsFavorites: boolean;
|
||||||
|
routeIsVideos: boolean;
|
||||||
routeIsFolders: boolean;
|
routeIsFolders: boolean;
|
||||||
routeIsAlbums: boolean;
|
routeIsAlbums: boolean;
|
||||||
routeIsPeople: boolean;
|
routeIsPeople: boolean;
|
||||||
|
|
Loading…
Reference in New Issue