Change storage to localforage

Use IndexedDB for primary storage
This commit is contained in:
Made Baruna 2021-05-18 14:25:49 +08:00
parent d74a11eb4f
commit 90d087d64d
No known key found for this signature in database
GPG key ID: 5AA5DA16AA5DCEAD
24 changed files with 296 additions and 202 deletions

View file

@ -11,6 +11,7 @@
"dependencies": {
"compression": "^1.7.1",
"exceljs": "^4.2.1",
"localforage": "^1.9.0",
"polka": "next",
"prettier": "^2.2.1",
"sirv": "^1.0.0"

View file

@ -1,9 +1,18 @@
import * as sapper from '@sapper/app';
import localforage from 'localforage';
import { startClient } from './i18n.js';
console.log('localforage config');
localforage.config({
driver: [localforage.INDEXEDDB, localforage.LOCALSTORAGE],
name: 'paimonmoe',
version: 1.0,
description: 'paimonmoe local storage',
});
startClient();
sapper.start({
target: document.querySelector('#sapper')
});
target: document.querySelector('#sapper'),
});

View file

@ -81,7 +81,7 @@
try {
const remoteSaveData = await getData();
for (const k in remoteSaveData) {
updateSave(k, remoteSaveData[k], true);
await updateSave(k, remoteSaveData[k], true);
}
} catch (err) {
console.error(err);
@ -91,7 +91,7 @@
async function useRemoteData() {
for (const k in remoteSave) {
updateSave(k, remoteSave[k], true);
await updateSave(k, remoteSave[k], true);
}
synced.set(true);
@ -99,7 +99,7 @@
}
async function useLocalData() {
await saveData(getLocalSaveJson());
await saveData(await getLocalSaveJson());
synced.set(true);
closeModal();
@ -184,7 +184,7 @@
saveId.set(result.id);
if (localSaveExists) {
await saveData(getLocalSaveJson());
await saveData(await getLocalSaveJson());
}
synced.set(true);
@ -253,8 +253,8 @@
);
}
function exportData() {
downloadData(getLocalSaveJson(), 'paimon-moe-local-data');
async function exportData() {
downloadData(await getLocalSaveJson(), 'paimon-moe-local-data');
downloadData(JSON.stringify(remoteSave), 'paimon-moe-drive-data');
}

View file

@ -13,11 +13,11 @@
readLocalData();
}
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
});
function readLocalData() {
async function readLocalData() {
loading.set(true);
const prefix = getAccountPrefix();
@ -29,10 +29,10 @@
if (unsubscribeWl) unsubscribeWl();
console.log('setting read local');
const accountsSave = readSave('accounts');
const serverSave = readSave(`${prefix}server`);
const arSave = readSave(`${prefix}ar`);
const wlSave = readSave(`${prefix}wl`);
const accountsSave = await readSave('accounts');
const serverSave = await readSave(`${prefix}server`);
const arSave = await readSave(`${prefix}ar`);
const wlSave = await readSave(`${prefix}wl`);
if (accountsSave !== null) {
const accountList = accountsSave.split(',').map((e) => ({
label: `Account ${e.substring(7)}`,
@ -51,26 +51,26 @@
wl.set(Number(wlSave));
}
unsubscribeServer = server.subscribe((val) => {
unsubscribeServer = server.subscribe(async (val) => {
if (firstLoad) return;
const prefix = getAccountPrefix();
console.log('server changed', val);
updateSave(`${prefix}server`, val);
await updateSave(`${prefix}server`, val);
});
unsubscribeWl = wl.subscribe((val) => {
unsubscribeWl = wl.subscribe(async (val) => {
if (firstLoad) return;
const prefix = getAccountPrefix();
console.log('wl changed', val);
updateSave(`${prefix}wl`, val);
await updateSave(`${prefix}wl`, val);
});
unsubscribeAr = ar.subscribe((val) => {
unsubscribeAr = ar.subscribe(async (val) => {
if (firstLoad) return;
const prefix = getAccountPrefix();
console.log('ar changed', val);
updateSave(`${prefix}ar`, val);
await updateSave(`${prefix}ar`, val);
});
firstLoad = false;

View file

@ -11,8 +11,8 @@
readLocalData();
}
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
const unsub = selectedAccount.subscribe(() => {
console.log('account changed, reading todo for the account');
@ -22,7 +22,7 @@
return () => unsub();
});
function readLocalData() {
async function readLocalData() {
loading.set(true);
firstLoad = true;
@ -31,18 +31,19 @@
const prefix = getAccountPrefix();
console.log('todo read local');
const data = readSave(`${prefix}todos`);
const data = await readSave(`${prefix}todos`);
console.log(data);
if (data !== null) {
const todoList = JSON.parse(data);
const todoList = data;
todos.set(todoList);
} else {
todos.set([]);
}
unsubscribe = todos.subscribe((val) => {
unsubscribe = todos.subscribe(async (val) => {
if (firstLoad) return;
updateSave(`${prefix}todos`, JSON.stringify(val));
await updateSave(`${prefix}todos`, val);
});
firstLoad = false;

View file

@ -41,14 +41,14 @@
name = weaponList[editName];
}
time = dayjs.unix(editTime).format('YYYY-MM-DDTHH:mm:ss');
time = dayjs(editTime).format('YYYY-MM-DDTHH:mm:ss');
});
function add() {
const pull = {
type: type.value,
id: name.id,
time: dayjs(time).unix(),
time: dayjs(time).format('YYYY-MM-DD HH:mm:ss'),
pity,
manualInput: true,
};
@ -60,7 +60,7 @@
const pull = {
type: type.value,
id: name.id,
time: dayjs(time).unix(),
time: dayjs(time).format('YYYY-MM-DD HH:mm:ss'),
pity,
manualInput: true,
};

View file

@ -5,6 +5,8 @@
import { onMount } from 'svelte';
import { slide } from 'svelte/transition';
import dayjs from 'dayjs';
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
dayjs.extend(isSameOrBefore);
import { pushToast } from '../stores/toast';
import Button from './Button.svelte';
@ -96,9 +98,9 @@
async function startImport() {
if (selectedType === 'pclocal') {
importFromGeneratedText();
await importFromGeneratedText();
} else {
processLogs();
await processLogs();
}
}
@ -160,7 +162,8 @@
const weapons = Object.values(weaponList);
const chars = Object.values(characters);
const newestPullTime = getNewestPullTime(type);
const newestPullTime = await getNewestPullTime(type);
// console.log(newestPullTime);
let page = 1;
let result = [];
let lastTime = 0;
@ -220,15 +223,15 @@
try {
for (let row of result) {
const code = row.gacha_type;
const time = dayjs(row.time);
const time = row.time;
const name = row.name;
const type = row.item_type.replace(/ /g, '');
if (time.unix() <= newestPullTime) {
if (dayjs(time).isSameOrBefore(newestPullTime)) {
return;
}
lastTime = time;
lastTime = dayjs(time);
let id;
if (type === 'Weapon') {
@ -246,7 +249,7 @@
{
type: type.toLowerCase(),
id,
time: time.unix(),
time,
pity: 0,
},
];
@ -255,38 +258,38 @@
page = page + 1;
lastId = result.length > 0 ? result[result.length - 1].id : 0;
await sleep(1000);
console.log(wishes);
// console.log(wishes);
} catch (err) {
processingLog = false;
pushToast($t('wish.import.invalidData'), 'error');
console.error(err);
throw 'invalid data';
}
} while (result.length > 0 && lastTime > newestPullTime);
} while (result.length > 0 && lastTime.isAfter(newestPullTime));
}
function getNewestPullTime(type) {
async function getNewestPullTime(type) {
if (!newOnly) {
// return very long time so it equally all wishes
return new dayjs().year(2000).unix();
return dayjs().year(2000);
}
const prefix = getAccountPrefix();
const path = `wish-counter-${type.id}`;
const localData = readSave(`${prefix}${path}`);
const localData = await readSave(`${prefix}${path}`);
let localWishes = [];
if (localData !== null) {
const counterData = JSON.parse(localData);
const counterData = localData;
localWishes = counterData.pulls || [];
if (localWishes.length > 0) {
const lastPull = localWishes[localWishes.length - 1];
return lastPull.time;
return dayjs(lastPull.time);
}
}
return new dayjs().year(2000).unix();
return dayjs().year(2000);
}
async function fetchRetry(url, options, n) {
@ -330,7 +333,7 @@
}
}
function importFromGeneratedText() {
async function importFromGeneratedText() {
if (!generatedTextInput.startsWith('paimonmoe,importer,version,1,0')) {
pushToast('Invalid data, please use the latest importer app', 'error');
return;
@ -342,19 +345,19 @@
const weapons = Object.values(weaponList);
const chars = Object.values(characters);
try {
for (let row of rows) {
if (row === '') continue;
const cell = row.split(',');
const code = Number(cell[0]);
const time = dayjs(cell[1]);
const time = cell[1];
const name = cell[2];
const type = cell[3].replace(/ /g, '');
const newestPullTime = getNewestPullTime(types[code]);
if (time.unix() <= newestPullTime) {
const newestPullTime = await getNewestPullTime(types[code]);
if (dayjs(time).isSameOrBefore(newestPullTime)) {
continue;
}
@ -374,7 +377,7 @@
{
type: type.toLowerCase(),
id,
time: time.unix(),
time,
pity: 0,
},
];
@ -389,10 +392,10 @@
console.log(wishes);
}
function saveData() {
async function saveData() {
calculatingPity = true;
for (let [code, type] of Object.entries(types)) {
processWishes(code, type);
await processWishes(code, type);
}
calculatingPity = false;
@ -403,11 +406,11 @@
}
const prefix = getAccountPrefix();
updateSave(`${prefix}collectables-updated`, 'true');
await updateSave(`${prefix}collectables-updated`, true);
closeModal();
}
function processWishes(code, type) {
async function processWishes(code, type) {
processFirstTimePopup(false, false);
if (wishes[code] === undefined) return;
@ -415,18 +418,18 @@
const prefix = getAccountPrefix();
const path = `wish-counter-${type.id}`;
const localData = readSave(`${prefix}${path}`);
const localData = await readSave(`${prefix}${path}`);
let localWishes = [];
if (localData !== null) {
const counterData = JSON.parse(localData);
const counterData = localData;
localWishes = counterData.pulls || [];
}
const importedWishes = wishes[code].slice().reverse();
const oldestWish = importedWishes[0];
localWishes = localWishes.slice().filter((e) => e.time < oldestWish.time);
localWishes = localWishes.slice().filter((e) => dayjs(e.time).isBefore(dayjs(oldestWish.time)));
const combined = [...localWishes, ...importedWishes];
@ -461,14 +464,14 @@
}
}
const data = JSON.stringify({
const data = {
total: combined.length,
legendary,
rare,
pulls: combined,
});
};
updateSave(`${prefix}${path}`, data);
await updateSave(`${prefix}${path}`, data);
}
const servers = [
@ -489,6 +492,7 @@
detectPlatform();
selectedServer = servers.find((e) => e.value === $server);
});
</script>
{#if processingLog}
@ -812,4 +816,5 @@
@apply block;
}
}
</style>

View file

@ -115,7 +115,7 @@ async function addInformation(workbook) {
};
sheet.addRow(['Paimon.moe Wish History Export']);
sheet.addRow(['Version', 1]);
sheet.addRow(['Version', 2]);
sheet.addRow(['Export Date', dayjs().format('YYYY-MM-DD HH:mm:ss')]);
sheet.mergeCells('A1:B1');
@ -146,7 +146,7 @@ async function addWishHistory(workbook, icons) {
bold: true,
};
const data = process(id);
const data = await process(id);
if (data === null) continue;
let groupCount = 0;
@ -166,7 +166,7 @@ async function addWishHistory(workbook, icons) {
const row = sheet.addRow([
pull.type[0].toUpperCase() + pull.type.slice(1),
pull.name,
dayjs.unix(pull.time).toDate(),
pull.time,
pull.rarity,
pull.pity,
pull.at,

View file

@ -19,11 +19,11 @@ const bannerTypes = {
beginners: 'beginners',
};
function readLocalData(path) {
async function readLocalData(path) {
const prefix = getAccountPrefix();
const data = readSave(`${prefix}${path}`);
const data = await readSave(`${prefix}${path}`);
if (data !== null) {
const counterData = JSON.parse(data);
const counterData = data;
const total = counterData.total;
const legendary = counterData.legendary;
const rare = counterData.rare;
@ -49,10 +49,10 @@ function getNextBanner(time, currentBannerIndex, selectedBanners) {
}
function formatTime(time) {
return dayjs.unix(time).format('ddd YYYY-MM-DD HH:mm:ss');
return dayjs(time).format('ddd YYYY-MM-DD HH:mm:ss');
}
export function process(id) {
export async function process(id) {
const path = `wish-counter-${id}`;
const bannerType = bannerTypes[id];
@ -81,7 +81,7 @@ export function process(id) {
};
});
const data = readLocalData(path);
const data = await readLocalData(path);
if (data === null) return null;
@ -102,9 +102,10 @@ export function process(id) {
for (let i = 0; i < pullData.length; i++) {
const pull = pullData[i];
const next = pullData[i + 1] || { time: dayjs().year(2000).unix() };
const currentPullTime = dayjs(pull.time).unix();
if (currentBanner === null || currentBanner.end < pull.time) {
const nextBanner = getNextBanner(pull.time, currentBannerIndex, selectedBanners);
if (currentBanner === null || currentBanner.end < currentPullTime) {
const nextBanner = getNextBanner(currentPullTime, currentBannerIndex, selectedBanners);
if (nextBanner === undefined) {
console.log('error banner here', JSON.stringify(pull));

View file

@ -1,9 +1,11 @@
import dayjs from 'dayjs';
import { process } from './wish';
const bannerCategories = ['beginners', 'standard', 'character-event', 'weapon-event'];
const rareInclude = {
300011: ['rosaria'],
300012: ['yanfei', 'noelle', 'diona'],
300013: ['xingqiu', 'beidou', 'xinyan'],
};
async function sendWish(data) {
@ -23,7 +25,7 @@ export async function submitWishTally() {
for (const id of bannerCategories) {
prefixId += 100000;
const data = process(id);
const data = await process(id);
if (data === null) continue;
if (data.hasManualInput) continue;
@ -31,7 +33,9 @@ export async function submitWishTally() {
const { pulls, banner } = data;
const firstFivePulls = pulls.slice(0, 5).map((e) => [e.time.toString(), e.id, e.type, e.pity, e.group === 'group']);
const firstFivePulls = pulls
.slice(0, 5)
.map((e) => [dayjs(e.time).unix().toString(), e.id, e.type, e.pity, e.group === 'group']);
for (let i = banner.length - 1; i >= Math.max(banner.length - 3, 0); i--) {
const total = banner[i].total;
@ -44,7 +48,7 @@ export async function submitWishTally() {
const legendaryCount = banner[i].legendary.length;
const rareCount = banner[i].rare.character.length + banner[i].rare.weapon.length;
const legendaryPulls = banner[i].legendary.map((e) => [
e.time.toString(),
dayjs(e.time).unix().toString(),
e.id,
e.type,
e.pity,
@ -57,7 +61,7 @@ export async function submitWishTally() {
if (rareInclude[prefixId + i + 1]) {
const includedRarePulls = banner[i].rare.character
.filter((e) => rareInclude[prefixId + i + 1].includes(e.id))
.map((e) => [e.time.toString(), e.id, e.type, e.pity, e.group === 'group', true, 4]);
.map((e) => [dayjs(e.time).unix().toString(), e.id, e.type, e.pity, e.group === 'group', true, 4]);
legendaryPulls.push(...includedRarePulls);
}

View file

@ -17,22 +17,22 @@
let latestPull = null;
let latestBanner = null;
function getLatestWish() {
async function getLatestWish() {
const prefix = getAccountPrefix();
let latestTime = 0;
let latestTime = dayjs().year(2000);
let latest = null;
let banner = null;
for (let type of bannerTypes) {
const path = `wish-counter-${type.id}`;
const data = readSave(`${prefix}${path}`);
const data = await readSave(`${prefix}${path}`);
if (data !== null) {
const counterData = JSON.parse(data);
const counterData = data;
const pulls = counterData.pulls || [];
if (pulls.length > 0) {
const currentLatest = pulls[pulls.length - 1];
if (currentLatest.time > latestTime) {
if (dayjs(currentLatest.time).isAfter(latestTime)) {
latestTime = currentLatest.time;
latest = currentLatest;
banner = type;
@ -46,7 +46,7 @@
}
onMount(async () => {
getLatestWish();
await getLatestWish();
await tick();
dispatch('done');
});
@ -76,7 +76,7 @@
</tr>
<tr>
<td class="text-gray-400 pr-1">{$t('home.wish.time')}</td>
<td>{dayjs.unix(latestPull.time).format('ddd YYYY-MM-DD HH:mm:ss')}</td>
<td>{latestPull.time}</td>
</tr>
<tr>
<td class="text-gray-400 pr-1 align-top">{$t('home.wish.name')}</td>

View file

@ -28,8 +28,8 @@
});
// check local storage save on load
onMount(() => {
checkLocalSave();
onMount(async () => {
await checkLocalSave();
});
</script>

View file

@ -92,11 +92,11 @@
orderAchievement();
}
const saveData = debounce(() => {
const data = JSON.stringify(checkList);
const saveData = debounce(async () => {
const data = checkList;
const prefix = getAccountPrefix();
updateSave(`${prefix}achievement`, data);
await updateSave(`${prefix}achievement`, data);
}, 2000);
async function changeCategory(id, index, firstLoad) {
@ -166,11 +166,11 @@
changeCategory(active, activeIndex, true);
}
function readLocalData() {
async function readLocalData() {
const prefix = getAccountPrefix();
const achievementData = readSave(`${prefix}achievement`);
const achievementData = await readSave(`${prefix}achievement`);
if (achievementData !== null) {
checkList = JSON.parse(achievementData);
checkList = achievementData;
migrateNewVersion();
}
}
@ -199,8 +199,8 @@
}
}
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
parseCategories();
changeCategory('0', 0, true);

View file

@ -83,11 +83,11 @@
const level = [1, 20, 20, 40, 40, 50, 50, 60, 60, 70, 70, 80, 80, 90];
const ascen = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6];
function getConstellationCount() {
async function getConstellationCount() {
const prefix = getAccountPrefix();
const data = readSave(`${prefix}characters`);
const data = await readSave(`${prefix}characters`);
if (data !== null) {
const constellation = JSON.parse(data);
const constellation = data;
chars = constellation;
if (constellation[id]) {
constellationCount = constellation[id].default + constellation[id].wish - 1;
@ -102,7 +102,7 @@
manualCount = Math.max(0, manualCount + val);
}
function saveConstellationCount() {
async function saveConstellationCount() {
editConstallation = false;
if (chars[id]) {
chars[id].manual = manualCount;
@ -124,15 +124,15 @@
}
const prefix = getAccountPrefix();
updateSave(`${prefix}characters`, JSON.stringify(chars));
await updateSave(`${prefix}characters`, chars);
}
function scrollToView(view) {
view.scrollIntoView({ behavior: 'smooth' });
}
onMount(() => {
getConstellationCount();
onMount(async () => {
await getConstellationCount();
});
$: constellationCountTotal = constellationCount + manualCount;

View file

@ -71,7 +71,7 @@
}
}
function processWishes() {
async function processWishes() {
const chars = {
amber: {
default: 1,
@ -113,10 +113,10 @@
const bannerCategories = ['beginners', 'standard', 'character-event', 'weapon-event'];
const prefix = getAccountPrefix();
for (const id of bannerCategories) {
const data = readSave(`${prefix}wish-counter-${id}`);
const data = await readSave(`${prefix}wish-counter-${id}`);
if (data !== null) {
showConstellation = true;
const counterData = JSON.parse(data);
const counterData = data;
const pullData = counterData.pulls || [];
for (const pull of pullData) {
if (pull.type === 'character') {
@ -135,23 +135,23 @@
if (showConstellation) {
constellation = chars;
updateSave(`${prefix}characters`, JSON.stringify(chars));
await updateSave(`${prefix}characters`, chars);
}
}
function getConstellation() {
async function getConstellation() {
const prefix = getAccountPrefix();
const data = readSave(`${prefix}characters`);
const data = await readSave(`${prefix}characters`);
if (data !== null) {
constellation = JSON.parse(data);
constellation = data;
showConstellation = true;
} else {
processWishes();
await processWishes();
}
}
onMount(() => {
getConstellation();
onMount(async () => {
await getConstellation();
});
</script>

View file

@ -134,28 +134,28 @@
return `color: hsl(${hue}, 100%, 60%);`;
}
const saveData = debounce(() => {
const data = JSON.stringify(currentUsage);
const saveData = debounce(async () => {
const data = currentUsage;
const prefix = getAccountPrefix();
updateSave(`${prefix}furnishing`, data);
await updateSave(`${prefix}furnishing`, data);
}, 2000);
function readLocalData() {
async function readLocalData() {
const prefix = getAccountPrefix();
const furnishingData = readSave(`${prefix}furnishing`);
const furnishingData = await readSave(`${prefix}furnishing`);
if (furnishingData !== null) {
currentUsage = {
...currentUsage,
...JSON.parse(furnishingData),
...furnishingData,
};
}
}
onMount(() => {
onMount(async () => {
parseFurnishing();
max = items[0].ratio;
readLocalData();
await readLocalData();
locale.subscribe((val) => {
changeLocale(val);

View file

@ -1,5 +1,6 @@
<script>
import { t } from 'svelte-i18n';
import localforage from 'localforage';
import { mdiCheckCircleOutline, mdiChevronDown, mdiDiscord, mdiGithub, mdiGoogleDrive, mdiLoading } from '@mdi/js';
import { getContext, onMount } from 'svelte';
@ -79,7 +80,7 @@
}
}
function addAccount() {
async function addAccount() {
const accountList = $accounts;
const accountNumber =
accountList.length === 1 ? 2 : Number(accountList[accountList.length - 1].value.substring(7)) + 1;
@ -88,7 +89,7 @@
const updatedAccountList = [...accountList, newAccount];
accounts.set(updatedAccountList);
updateSave(
await updateSave(
'accounts',
updatedAccountList
.slice(1)
@ -99,7 +100,7 @@
pushToast(`Account ${accountNumber} added, select it on the account list!`);
}
function selectAccount() {
async function selectAccount() {
if (!mounted) return;
console.log('changed account to', currentAccount.label);
@ -107,22 +108,22 @@
selectedAccount.set(currentAccount);
const prefix = getAccountPrefix();
const serverSave = readSave(`${prefix}server`);
const serverSave = await readSave(`${prefix}server`);
if (serverSave === null) {
selectedServer = { label: 'Asia/TW/HK/MO', value: 'Asia' };
} else {
const serverSave = readSave(`${prefix}server`);
const serverSave = await readSave(`${prefix}server`);
selectedServer = servers.find((e) => e.value === serverSave);
}
const arSave = readSave(`${prefix}ar`);
const arSave = await readSave(`${prefix}ar`);
if (arSave === null) {
arInput = '45';
} else {
arInput = arSave;
}
const wlSave = readSave(`${prefix}wl`);
const wlSave = await readSave(`${prefix}wl`);
if (wlSave === null) {
wlInput = '6';
} else {
@ -130,7 +131,7 @@
}
}
function deleteAccount() {
async function deleteAccount() {
const prefix = getAccountPrefix();
const updatedList = $accounts.filter((e) => e.value !== currentAccount.value);
@ -156,11 +157,11 @@
];
for (let k of keyWillBeDeleted) {
localStorage.removeItem(`${prefix}${k}`);
await localforage.removeItem(`${prefix}${k}`);
}
if (updatedList.length > 1) {
updateSave(
await updateSave(
'accounts',
updatedList
.slice(1)
@ -168,14 +169,14 @@
.join(','),
);
} else {
updateSave('accounts', undefined);
await updateSave('accounts', undefined);
}
pushToast('Data deleted');
closeModal();
}
function resetAccount() {
async function resetAccount() {
const prefix = getAccountPrefix();
const keyWillBeDeleted = [
@ -191,11 +192,11 @@
];
for (let k of keyWillBeDeleted) {
localStorage.removeItem(`${prefix}${k}`);
await localforage.removeItem(`${prefix}${k}`);
}
updateSave(`${prefix}todos`, undefined, true);
updateSave(`${prefix}todos`, JSON.stringify([]));
await updateSave(`${prefix}todos`, undefined, true);
await updateSave(`${prefix}todos`, []);
pushToast('Data deleted');
closeModal();

View file

@ -102,12 +102,12 @@
);
}
function readLocalData() {
async function readLocalData() {
console.log('wish read local');
const prefix = getAccountPrefix();
const data = readSave(`${prefix}${path}`);
const data = await readSave(`${prefix}${path}`);
if (data !== null) {
const counterData = JSON.parse(data);
const counterData = data;
total = counterData.total;
legendary = counterData.legendary;
rare = counterData.rare;
@ -118,8 +118,9 @@
}
function getNextBanner(time) {
console.log(time);
for (let i = currentBannerIndex + 1; i < selectedBanners.length; i++) {
console.log('change banner', i, dayjs.unix(time).format(), dayjs.unix(selectedBanners[i].start).format());
console.log('change banner', i, time, dayjs.unix(selectedBanners[i].start).format());
if (time >= selectedBanners[i].start && time < selectedBanners[i].end) {
currentBannerIndex = i;
return selectedBanners[i];
@ -140,9 +141,10 @@
for (let i = 0; i < pullData.length; i++) {
const pull = pullData[i];
const next = pullData[i + 1] || { time: dayjs().year(2000).unix() };
const currentPullTime = dayjs(pull.time).unix();
if (currentBanner === null || currentBanner.end < pull.time) {
currentBanner = getNextBanner(pull.time);
if (currentBanner === null || currentBanner.end < currentPullTime) {
currentBanner = getNextBanner(currentPullTime);
if (currentBanner === undefined) {
console.log('error banner here', JSON.stringify(pull));
@ -370,8 +372,8 @@
}
}
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
isSafari =
navigator.vendor &&
@ -393,7 +395,7 @@
}
function formatTime(time) {
return dayjs.unix(time).format('ddd YYYY-MM-DD HH:mm:ss');
return dayjs(time).format('ddd YYYY-MM-DD HH:mm:ss');
}
function calculateLegendaryColor(percentage) {

View file

@ -47,8 +47,8 @@
}
$: showRarity, pulls, filterRarity();
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
filterRarity();
});
@ -175,12 +175,13 @@
isEdit = false;
}
export function readLocalData() {
export async function readLocalData() {
console.log('wish read local');
const prefix = getAccountPrefix();
const data = readSave(`${prefix}${path}`);
const data = await readSave(`${prefix}${path}`);
console.log(data);
if (data !== null) {
const counterData = JSON.parse(data);
const counterData = data;
total = counterData.total;
legendary = counterData.legendary;
rare = counterData.rare;
@ -188,16 +189,16 @@
}
}
const saveData = debounce(() => {
const data = JSON.stringify({
const saveData = debounce(async () => {
const data = {
total,
legendary,
rare,
pulls,
});
};
const prefix = getAccountPrefix();
updateSave(`${prefix}${path}`, data);
await updateSave(`${prefix}${path}`, data);
}, 2000);
function add(val) {
@ -231,7 +232,7 @@
...[...new Array(filler)].map((e) => ({
type: 'unknown_3_star',
id: 'unknown_3_star',
time: dayjs().unix(),
time: dayjs().format('YYYY-MM-DD HH:mm:ss'),
pity: 1,
manualInput: true,
})),
@ -264,6 +265,7 @@
rare = 0;
saveData();
}
</script>
<div class="bg-item rounded-xl p-4 inline-flex flex-col w-full" style="height: min-content;">
@ -394,7 +396,7 @@
<Icon path={mdiTableOfContents} color="white" />
</a>
</div>
<table class="w-full">
<table class="w-full text-sm">
<tr>
<th class="border-b border-gray-700 text-gray-400 font-display text-left pl-2">{$t('wish.name')}</th>
<th class="border-b border-gray-700 text-gray-400 font-display text-left pl-2">{$t('wish.time')}</th>
@ -429,9 +431,9 @@
{:else if pull.type === 'unknown_3_star'}
<td class="border-b border-gray-700 py-1 pl-2 font-semibold text-primary">Unknown</td>
{/if}
<td class="border-b border-gray-700 text-sm py-1 px-2 whitespace-no-wrap" style="font-family: monospace;"
>{dayjs.unix(pull.time).format('YYYY-MM-DD HH:mm:ss')}</td
>
<td class="border-b border-gray-700 text-xs py-1 px-2 whitespace-no-wrap" style="font-family: monospace;">
{pull.time}
</td>
<td class="text-right border-b border-gray-700 py-1">{pull.pity}</td>
</tr>
{/each}
@ -475,4 +477,5 @@
}
}
}
</style>

View file

@ -21,7 +21,7 @@
const types = bannerTypes;
let loading = true;
let totalWish = 0;
let wishCount = 0;
const avg = {};
$: if ($fromRemote) {
@ -32,8 +32,8 @@
readLocalData();
}
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
});
const defaultChars = {
@ -74,19 +74,19 @@
},
};
export function readLocalData() {
totalWish = 0;
export async function readLocalData() {
let totalWish = 0;
console.log('wish summary read local');
const prefix = getAccountPrefix();
monthlyData = {};
let currentMonthlyData = {};
// collected characters stuff
let updateCollectedCharacters = false;
let collectedCharacters = {};
const collectedCharactersData = readSave(`${prefix}characters`);
const collectedCharactersData = await readSave(`${prefix}characters`);
if (collectedCharactersData !== null) {
collectedCharacters = JSON.parse(collectedCharactersData);
collectedCharacters = collectedCharactersData;
for (const collectedId of Object.keys(collectedCharacters)) {
collectedCharacters[collectedId].wish = 0;
}
@ -94,18 +94,18 @@
} else {
collectedCharacters = defaultChars;
}
const collectablesNeedUpdateData = readSave(`${prefix}collectables-updated`);
if (collectablesNeedUpdateData === null || collectablesNeedUpdateData === 'true') {
const collectablesNeedUpdateData = await readSave(`${prefix}collectables-updated`);
if (collectablesNeedUpdateData === null || collectablesNeedUpdateData === true) {
updateCollectedCharacters = true;
} else if (collectablesNeedUpdateData === 'false') {
} else if (collectablesNeedUpdateData === false) {
updateCollectedCharacters = false;
}
for (let type of types) {
const path = `wish-counter-${type.id}`;
const data = readSave(`${prefix}${path}`);
const data = await readSave(`${prefix}${path}`);
if (data !== null) {
const counterData = JSON.parse(data);
const counterData = data;
const pulls = counterData.pulls || [];
const total = counterData.total;
@ -147,27 +147,27 @@
currentType = 'weapon';
}
const time = dayjs.unix(pull.time).format('YYYY-MM');
if (monthlyData[time] === undefined) {
monthlyData[time] = {
const time = dayjs(pull.time).format('YYYY-MM');
if (currentMonthlyData[time] === undefined) {
currentMonthlyData[time] = {
total: 0,
legendary: 0,
rare: 0,
};
}
monthlyData[time].total++;
currentMonthlyData[time].total++;
if (rarity === 5) {
legendary++;
legendaryPity += pull.pity;
monthlyData[time].legendary++;
currentMonthlyData[time].legendary++;
legendaryPulls.push({ name: itemName, pity: pull.pity });
} else if (rarity === 4) {
rare++;
rarePity += pull.pity;
monthlyData[time].rare++;
currentMonthlyData[time].rare++;
if (currentType === 'character') {
rareCharacter++;
@ -205,15 +205,19 @@
}
}
wishCount = totalWish;
monthlyData = currentMonthlyData;
if (updateCollectedCharacters && totalWish > 0) {
console.log('updating collectables');
updateSave(`${prefix}characters`, JSON.stringify(collectedCharacters));
updateSave(`${prefix}collectables-updated`, 'false');
await updateSave(`${prefix}characters`, collectedCharacters);
await updateSave(`${prefix}collectables-updated`, false);
}
console.log(avg);
// console.log(avg);
loading = false;
}
</script>
{#if !loading}
@ -234,7 +238,7 @@
{/if}
<div class="bg-item rounded-xl p-4 flex items-center w-full text-white" style="height: min-content;">
{$t('wish.wishesWorth')} <img class="w-4 h-4 mx-2" src="/images/primogem.png" alt="primogem" />
{numberFormat.format(totalWish * 160)}
{numberFormat.format(wishCount * 160)}
</div>
<a
href="/wish/tally"

View file

@ -36,15 +36,15 @@
readLocalData();
}
onMount(() => {
readLocalData();
onMount(async () => {
await readLocalData();
});
function readLocalData() {
async function readLocalData() {
console.log('wish read setting');
const data = readSave(path);
const data = await readSave(path);
if (data !== null) {
settings = JSON.parse(data);
settings = data;
} else {
settings = {
firstTime: true,
@ -53,7 +53,7 @@
}
}
function setManualInput(val) {
async function setManualInput(val) {
if (settings.manualInput === val) return;
settings = {
@ -61,17 +61,17 @@
manualInput: val,
};
updateSave(path, JSON.stringify(settings));
await updateSave(path, settings);
}
function processFirstTimePopup(val, manualVal) {
async function processFirstTimePopup(val, manualVal) {
settings = {
...settings,
firstTime: val,
manualInput: manualVal,
};
updateSave(path, JSON.stringify(settings));
await updateSave(path, settings);
}
function openHowTo() {

View file

@ -1,6 +1,7 @@
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';
@ -9,6 +10,7 @@ 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;
@ -21,8 +23,8 @@ driveSignedIn.subscribe((val) => {
signedIn = val;
});
const saveToRemote = debounce(() => {
saveData(getLocalSaveJson());
const saveToRemote = debounce(async () => {
saveData(await getLocalSaveJson());
}, 5000);
async function saveData(data) {
@ -57,33 +59,80 @@ synced.subscribe((value) => {
}
});
export const checkLocalSave = () => {
const localUpdateTime = localStorage.getItem(UPDATE_TIME_KEY);
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 converted = localStorage.getItem(CONVERTED_KEY);
if (converted !== null) return;
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 {
await localforage.setItem(key, JSON.parse(value));
}
}
localStorage.setItem(CONVERTED_KEY, dayjs().toISOString());
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 = () => {
return JSON.stringify(localStorage);
export const getLocalSaveJson = async () => {
const data = {};
await localforage.iterate((value, key) => {
data[key] = value;
});
return JSON.stringify(data);
};
export const updateSave = (key, data, isFromRemote) => {
export const updateSave = async (key, data, isFromRemote) => {
if (!isFromRemote) {
localModified.set(true);
}
if (data !== undefined) {
localStorage.setItem(key, data);
await localforage.setItem(key, data);
} else {
localStorage.removeItem(key);
await localforage.removeItem(key);
}
if (!isFromRemote) {
const currentTime = dayjs();
updateTime.set(currentTime);
localStorage.setItem(UPDATE_TIME_KEY, currentTime.toISOString());
await localforage.setItem(UPDATE_TIME_KEY, currentTime.toISOString());
if (signedIn) {
saveToRemote();
@ -93,7 +142,7 @@ export const updateSave = (key, data, isFromRemote) => {
}
};
export const readSave = (key) => {
const data = localStorage.getItem(key);
export const readSave = async (key) => {
const data = await localforage.getItem(key);
return data;
};

View file

Before

(image error) Size: 532 KiB

After

(image error) Size: 532 KiB

View file

@ -2037,6 +2037,13 @@ lazystream@^1.0.0:
dependencies:
readable-stream "^2.0.5"
lie@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=
dependencies:
immediate "~3.0.5"
lie@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
@ -2054,6 +2061,13 @@ listenercount@~1.0.1:
resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=
localforage@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.9.0.tgz#f3e4d32a8300b362b4634cc4e066d9d00d2f09d1"
integrity sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g==
dependencies:
lie "3.1.1"
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"