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 {
return this.$route.name === 'folders';
},
routeHasNative(): boolean {
return this.routeIsBase && nativex.has();
},
isMonthView(): boolean {
if (this.$route.query.sort === 'timeline') return false;
@ -705,6 +708,10 @@ export default defineComponent({
if (!noCache) {
try {
if ((cache = await utils.getCachedData(cacheUrl))) {
if (this.routeHasNative) {
await nativex.extendDaysWithLocal(cache);
}
await this.processDays(cache);
this.loading--;
}
@ -723,6 +730,11 @@ export default defineComponent({
// Put back into cache
utils.cacheData(cacheUrl, data);
// Extend with native days
if (this.routeHasNative) {
await nativex.extendDaysWithLocal(data);
}
// Make sure we're still on the same page
if (this.state !== startState) return;
await this.processDays(data);
@ -862,7 +874,15 @@ export default defineComponent({
const cacheUrl = this.getDayUrl(dayId);
try {
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 {
console.warn(`Failed to process day cache: ${cacheUrl}`);
}
@ -887,8 +907,13 @@ export default defineComponent({
async fetchDayExpire() {
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
const dayStr = this.fetchDayQueue.join(',');
const dayStr = dayIds.join(',');
const url = this.getDayUrl(dayStr);
this.fetchDayQueue = [];
@ -905,20 +930,8 @@ export default defineComponent({
// Bin the data into separate days
// It is already sorted in dayid DESC
const dayMap = new Map<number, IPhoto[]>();
for (const photo of data) {
if (!dayMap.has(photo.dayid)) dayMap.set(photo.dayid, []);
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);
dayMap.get(photo.dayid)?.push(photo);
}
// Store cache asynchronously
@ -928,9 +941,20 @@ export default defineComponent({
// These loops cannot be combined because processDay
// creates circular references which cannot be stringified
for (const [dayId, photos] of dayMap) {
if (photos.length === 0) continue;
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
for (const [dayId, photos] of dayMap) {
// 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).
@ -10,6 +10,7 @@ type NativePromise<T> = (call: string, arg: T) => void;
*/
export type NativeX = {
isNative: () => boolean;
getLocalDays: NativePromise<string>;
getLocalByDayId: NativePromise<string>;
getJpeg: NativePromise<string>;
};
@ -79,6 +80,13 @@ globalThis.nativexr = (call: string, resolve?: string, reject?: string) => {
*/
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.
*
@ -95,6 +103,32 @@ const getLocalByDayId = nativePromisify<number, string>(nativex?.getLocalByDayId
*/
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.
* Fetches the local photos from the native interface and filters out duplicates.