paimon-moe-fork/src/stores/saveManager.js

171 lines
4.1 KiB
JavaScript

import dayjs from 'dayjs';
import { writable } from 'svelte/store';
import debounce from 'lodash/debounce';
import localforage from 'localforage';
import { synced, saveId, localModified, lastSyncTime, driveSignedIn } from './dataSync';
import { pushToast } from './toast';
export const updateTime = writable(null);
export const fromRemote = writable(false);
export const UPDATE_TIME_KEY = 'update-time';
export const CONVERTED_KEY = 'converted';
let saveFileId = '';
let signedIn = false;
saveId.subscribe((val) => {
saveFileId = val;
});
driveSignedIn.subscribe((val) => {
signedIn = val;
});
const saveToRemote = debounce(async () => {
saveData(await getLocalSaveJson());
}, 5000);
async function saveData(data) {
console.log('saving to remote file');
synced.set(false);
try {
await gapi.client.request({
path: `/upload/drive/v3/files/${saveFileId}`,
method: 'PATCH',
params: {
uploadType: 'media',
},
body: data,
});
synced.set(true);
localModified.set(false);
pushToast('Data has been synced!');
} catch (err) {
console.error(err);
pushToast('Error when uploading your data!', 'error');
synced.set(true);
}
}
synced.subscribe((value) => {
console.log('synced:', value);
if (value) {
lastSyncTime.set(dayjs());
}
});
const convertTime = (data) => {
for (const pull of data.pulls) {
pull.time = dayjs.unix(pull.time).format('YYYY-MM-DD HH:mm:ss');
}
return data;
};
const convertSave = async () => {
const lfkeys = await localforage.keys();
for (const key of lfkeys) {
if (key.includes('backup')) {
await localforage.removeItem(key);
}
}
const converted = localStorage.getItem(CONVERTED_KEY);
if (converted !== null) return;
let convertedCount = 0;
for (const [key, value] of Object.entries(localStorage)) {
if (key.endsWith('ar') || key.endsWith('wl')) {
await localforage.setItem(key, Number(value));
} else if (key.endsWith('collectables-updated')) {
await localforage.setItem(key, value === 'true');
} else if (
key.endsWith('accounts') ||
key.endsWith('locale') ||
key.endsWith('server') ||
key.endsWith('update-time')
) {
await localforage.setItem(key, value);
} else if (
key.endsWith('wish-counter-character-event') ||
key.endsWith('wish-counter-weapon-event') ||
key.endsWith('wish-counter-standard') ||
key.endsWith('wish-counter-beginners')
) {
const converted = convertTime(JSON.parse(value));
await localforage.setItem(key, converted);
} else {
try {
await localforage.setItem(key, JSON.parse(value));
} catch (err) {
await localforage.setItem(key, value);
}
}
if (!key.endsWith('locale')) {
convertedCount++;
}
}
const convertedTime = dayjs().toISOString();
localStorage.setItem(CONVERTED_KEY, convertedTime);
await localforage.setItem(CONVERTED_KEY, convertedTime);
if (convertedCount > 0) {
window.location.reload();
}
};
export const checkLocalSave = async () => {
await convertSave();
const localUpdateTime = await localforage.getItem(UPDATE_TIME_KEY);
if (localUpdateTime !== null) {
updateTime.set(dayjs(localUpdateTime));
console.log('local save update time:', localUpdateTime);
}
};
export const getLocalSaveJson = async () => {
const data = {};
await localforage.iterate((value, key) => {
data[key] = value;
});
return JSON.stringify(data);
};
export const updateSave = async (key, data, isFromRemote) => {
console.log('updateSave', key, isFromRemote, data);
if (!isFromRemote) {
localModified.set(true);
}
if (data !== undefined) {
await localforage.setItem(key, data);
} else {
await localforage.removeItem(key);
}
if (!isFromRemote) {
const currentTime = dayjs();
updateTime.set(currentTime);
await localforage.setItem(UPDATE_TIME_KEY, currentTime.toISOString());
if (signedIn) {
saveToRemote();
}
} else {
fromRemote.set(true);
}
};
export const readSave = async (key) => {
const data = await localforage.getItem(key);
return data;
};