nativex: use days

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/653/head
Varun Patil 2023-05-07 20:02:14 -07:00
parent c325d4466f
commit 3e88e2cab4
2 changed files with 74 additions and 16 deletions

View File

@ -227,6 +227,9 @@ export default defineComponent({
routeIsFolders(): boolean { routeIsFolders(): boolean {
return this.$route.name === 'folders'; return this.$route.name === 'folders';
}, },
routeHasNative(): boolean {
return this.routeIsBase && nativex.has();
},
isMonthView(): boolean { isMonthView(): boolean {
if (this.$route.query.sort === 'timeline') return false; if (this.$route.query.sort === 'timeline') return false;
@ -705,6 +708,10 @@ export default defineComponent({
if (!noCache) { if (!noCache) {
try { try {
if ((cache = await utils.getCachedData(cacheUrl))) { if ((cache = await utils.getCachedData(cacheUrl))) {
if (this.routeHasNative) {
await nativex.extendDaysWithLocal(cache);
}
await this.processDays(cache); await this.processDays(cache);
this.loading--; this.loading--;
} }
@ -723,6 +730,11 @@ export default defineComponent({
// Put back into cache // Put back into cache
utils.cacheData(cacheUrl, data); utils.cacheData(cacheUrl, data);
// Extend with native days
if (this.routeHasNative) {
await nativex.extendDaysWithLocal(data);
}
// Make sure we're still on the same page // Make sure we're still on the same page
if (this.state !== startState) return; if (this.state !== startState) return;
await this.processDays(data); await this.processDays(data);
@ -862,7 +874,15 @@ export default defineComponent({
const cacheUrl = this.getDayUrl(dayId); const cacheUrl = this.getDayUrl(dayId);
try { try {
const cache = await utils.getCachedData<IPhoto[]>(cacheUrl); const cache = await utils.getCachedData<IPhoto[]>(cacheUrl);
if (cache) this.processDay(dayId, cache); if (cache) {
// Cache only contains remote images; update from local too
if (this.routeHasNative) {
await nativex.extendDayWithLocal(dayId, cache);
}
// Process the cache
this.processDay(dayId, cache);
}
} catch { } catch {
console.warn(`Failed to process day cache: ${cacheUrl}`); console.warn(`Failed to process day cache: ${cacheUrl}`);
} }
@ -887,8 +907,13 @@ export default defineComponent({
async fetchDayExpire() { async fetchDayExpire() {
if (this.fetchDayQueue.length === 0) return; if (this.fetchDayQueue.length === 0) return;
// Map of dayId to photos
const dayIds = this.fetchDayQueue;
const dayMap = new Map<number, IPhoto[]>();
for (const dayId of dayIds) dayMap.set(dayId, []);
// Construct URL // Construct URL
const dayStr = this.fetchDayQueue.join(','); const dayStr = dayIds.join(',');
const url = this.getDayUrl(dayStr); const url = this.getDayUrl(dayStr);
this.fetchDayQueue = []; this.fetchDayQueue = [];
@ -905,20 +930,8 @@ export default defineComponent({
// Bin the data into separate days // Bin the data into separate days
// It is already sorted in dayid DESC // It is already sorted in dayid DESC
const dayMap = new Map<number, IPhoto[]>();
for (const photo of data) { for (const photo of data) {
if (!dayMap.has(photo.dayid)) dayMap.set(photo.dayid, []); dayMap.get(photo.dayid)?.push(photo);
dayMap.get(photo.dayid)!.push(photo);
}
// Get local images if we are running in native environment.
// Get them all together for each day here.
if (nativex.has()) {
const promises: Promise<void>[] = [];
for (const [dayId, photos] of dayMap) {
promises.push(nativex.extendDayWithLocal(dayId, photos));
}
await Promise.all(promises);
} }
// Store cache asynchronously // Store cache asynchronously
@ -928,9 +941,20 @@ export default defineComponent({
// These loops cannot be combined because processDay // These loops cannot be combined because processDay
// creates circular references which cannot be stringified // creates circular references which cannot be stringified
for (const [dayId, photos] of dayMap) { for (const [dayId, photos] of dayMap) {
if (photos.length === 0) continue;
utils.cacheData(this.getDayUrl(dayId), photos); utils.cacheData(this.getDayUrl(dayId), photos);
} }
// Get local images if we are running in native environment.
// Get them all together for each day here.
if (this.routeHasNative) {
await Promise.all(
Array.from(dayMap.entries()).map(([dayId, photos]) => {
return nativex.extendDayWithLocal(dayId, photos);
})
);
}
// Process each day as needed // Process each day as needed
for (const [dayId, photos] of dayMap) { for (const [dayId, photos] of dayMap) {
// Check if the response has any delta // Check if the response has any delta

View File

@ -1,4 +1,4 @@
import type { IPhoto } from './types'; import type { IDay, IPhoto } from './types';
/** /**
* Type of a native promise (this will be the exact type in Java). * Type of a native promise (this will be the exact type in Java).
@ -10,6 +10,7 @@ type NativePromise<T> = (call: string, arg: T) => void;
*/ */
export type NativeX = { export type NativeX = {
isNative: () => boolean; isNative: () => boolean;
getLocalDays: NativePromise<string>;
getLocalByDayId: NativePromise<string>; getLocalByDayId: NativePromise<string>;
getJpeg: NativePromise<string>; getJpeg: NativePromise<string>;
}; };
@ -79,6 +80,13 @@ globalThis.nativexr = (call: string, resolve?: string, reject?: string) => {
*/ */
export const has = () => !!nativex; export const has = () => !!nativex;
/**
* Gets the local days array.
*
* @returns List of local days (JSON string)
*/
const getLocalDays = nativePromisify<number, string>(nativex?.getLocalDays.bind(nativex));
/** /**
* Gets the local photos for a day with a dayId. * Gets the local photos for a day with a dayId.
* *
@ -95,6 +103,32 @@ const getLocalByDayId = nativePromisify<number, string>(nativex?.getLocalByDayId
*/ */
const getJpeg = nativePromisify<string, string>(nativex?.getJpeg.bind(nativex), true); const getJpeg = nativePromisify<string, string>(nativex?.getJpeg.bind(nativex), true);
/**
* Extend a list of days with local days.
* Fetches the local days from the native interface.
*/
export async function extendDaysWithLocal(days: IDay[]) {
if (!has()) return;
// Query native part
const local: IDay[] = JSON.parse(await getLocalDays(0));
const remoteMap = new Map(days.map((d) => [d.dayid, d]));
// Merge local days into remote days
for (const day of local) {
const remote = remoteMap.get(day.dayid);
if (remote) {
remote.count = Math.max(remote.count, day.count);
} else {
days.push(day);
}
}
// TODO: sort depends on view
// (but we show it for only timeline anyway for now)
days.sort((a, b) => b.dayid - a.dayid);
}
/** /**
* Extend a list of photos with local photos. * Extend a list of photos with local photos.
* Fetches the local photos from the native interface and filters out duplicates. * Fetches the local photos from the native interface and filters out duplicates.