Add excel import
parent
464a45db98
commit
18475ae76f
|
@ -447,20 +447,14 @@
|
|||
}
|
||||
|
||||
if (rarity === 5) {
|
||||
if (combined[i].pity === 0) {
|
||||
combined[i].pity = legendary;
|
||||
}
|
||||
combined[i].pity = legendary;
|
||||
legendary = 0;
|
||||
// rare = 0;
|
||||
} else if (rarity === 4) {
|
||||
if (combined[i].pity === 0) {
|
||||
combined[i].pity = rare;
|
||||
}
|
||||
combined[i].pity = rare;
|
||||
rare = 0;
|
||||
} else {
|
||||
if (combined[i].pity === 0) {
|
||||
combined[i].pity = 1;
|
||||
}
|
||||
combined[i].pity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,7 +737,7 @@
|
|||
{/if}
|
||||
|
||||
<div class="flex flex-col md:flex-row mt-4 md:justify-end items-center">
|
||||
{#if !showFaq}
|
||||
<!-- {#if !showFaq}
|
||||
<div class="flex-1 flex mb-4 md:mb-0 md:ml-4">
|
||||
<Checkbox disabled={false} bind:checked={newOnly}>
|
||||
<span class="text-white select-none">{$t('wish.import.importNewWishOnly')}</span>
|
||||
|
@ -753,7 +747,7 @@
|
|||
<span class="tooltip-content">{$t('wish.import.importNewWishUncheck')}</span>
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
{/if} -->
|
||||
<div>
|
||||
{#if !showFaq}
|
||||
<Button on:click={startImport} color="green" className="mr-4">{$t('wish.import.import')}</Button>
|
||||
|
@ -791,7 +785,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
/* .tooltip {
|
||||
@apply relative;
|
||||
|
||||
.tooltip-content {
|
||||
|
@ -815,6 +809,6 @@
|
|||
&:hover .tooltip-content {
|
||||
@apply block;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
</style>
|
||||
|
|
|
@ -104,6 +104,8 @@
|
|||
"title": "Wish Counter",
|
||||
"autoImport": "Auto Import",
|
||||
"helpAndSetting": "Help & Settings",
|
||||
"helps": "Help",
|
||||
"settings": "Settings",
|
||||
"wishesWorth": "Wishes Worth",
|
||||
"lifetimePulls": "Lifetime Pulls",
|
||||
"guarantee": "Guaranteed at {pity}",
|
||||
|
@ -237,13 +239,41 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"excel": {
|
||||
"title": "Excel Importer",
|
||||
"subtitle": "Select where your excel come from:",
|
||||
"default": "Paimon.moe Export",
|
||||
"takagg": "TakaGG Gacha Export",
|
||||
"notice": [
|
||||
"This feature still in BETA please backup first by going to Setting then Export to Excel!",
|
||||
"Wish with the same timestamp and reward name will NOT be touched (so existing wish will not be rewritten)",
|
||||
"Will only append and prepend wishes, this mean nothing will be inserted on the middle of the list",
|
||||
"Currently only support excel with ENGLISH reward name"
|
||||
],
|
||||
"selectFile": {
|
||||
"default": "Drag & drop Paimon.moe excel file here, or click here to select",
|
||||
"takagg": "Drag & drop TakaGG gacha export excel file here, or click here to select"
|
||||
},
|
||||
"processing": "Processing...",
|
||||
"addedOn": "Inserted on the:",
|
||||
"beginning": "Beginning",
|
||||
"end": "End",
|
||||
"total": "Total",
|
||||
"saveNotice": "Save the imported wishes?",
|
||||
"save": "Save",
|
||||
"success": "Excel import success 😀!",
|
||||
"errorInvalidFile": "Invalid excel file",
|
||||
"errorReadExcel": "Error reading the excel file!",
|
||||
"errorExcelPaimon": "This is not excel from paimon.moe export",
|
||||
"errorUnknownItem": "Got an unknown reward name"
|
||||
},
|
||||
"help": {
|
||||
"title": "Wish Counter Help & Settings",
|
||||
"exportTitle": "Export Wish History",
|
||||
"exportMessage": "You can export your wish history to an excel file here",
|
||||
"exportTitle": "Export & Import Wish History",
|
||||
"exportMessage": "You can export your wish history to an excel file here. You can also import the exported excel from paimon.moe or TakaGG Gacha Export.",
|
||||
"export": "Export to Excel",
|
||||
"exporting": "Exporting...",
|
||||
"import": "Import",
|
||||
"import": "Import From Excel",
|
||||
"exportFinish": "Export success, please wait until the browser download the file!",
|
||||
"wishTallyTitle": "Submit Wish Tally",
|
||||
"wishTally": "We are doing a global wish tally! You can submit your wish tally to participate. All pity data will be aggregated to know what is the average pity of paimon.moe users.",
|
||||
|
|
|
@ -0,0 +1,434 @@
|
|||
<script>
|
||||
import { t } from 'svelte-i18n';
|
||||
import { Workbook } from 'exceljs';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import Button from '../../components/Button.svelte';
|
||||
import { pushToast } from '../../stores/toast';
|
||||
import { weaponList } from '../../data/weaponList';
|
||||
import { characters } from '../../data/characters';
|
||||
import { getAccountPrefix } from '../../stores/account';
|
||||
import { readSave, updateSave } from '../../stores/saveManager';
|
||||
|
||||
export let closeModal;
|
||||
|
||||
const bannerCategories = {
|
||||
'character-event': 'Character Event',
|
||||
'weapon-event': 'Weapon Event',
|
||||
standard: 'Standard',
|
||||
beginners: "Beginners' Wish",
|
||||
};
|
||||
|
||||
let selectedType = 'default';
|
||||
let fileInput;
|
||||
let step = 0;
|
||||
let loading = false;
|
||||
|
||||
let added = {};
|
||||
|
||||
function changeType(type) {
|
||||
selectedType = type;
|
||||
}
|
||||
|
||||
function selectFile() {
|
||||
fileInput.click();
|
||||
}
|
||||
|
||||
async function readLocalData(id) {
|
||||
const prefix = getAccountPrefix();
|
||||
const path = `wish-counter-${id}`;
|
||||
const data = await readSave(`${prefix}${path}`);
|
||||
let pulls = [];
|
||||
|
||||
let newest = dayjs().year(2000);
|
||||
let oldest = dayjs().year(2200);
|
||||
|
||||
if (data !== null) {
|
||||
newest = dayjs(data.pulls[data.pulls.length - 1].time);
|
||||
oldest = dayjs(data.pulls[0].time);
|
||||
pulls = data.pulls;
|
||||
}
|
||||
|
||||
return {
|
||||
path: `${prefix}${path}`,
|
||||
data: pulls,
|
||||
newest,
|
||||
oldest,
|
||||
};
|
||||
}
|
||||
|
||||
async function processWishes(path, combined) {
|
||||
let rare = 0;
|
||||
let legendary = 0;
|
||||
for (let i = 0; i < combined.length; i++) {
|
||||
rare++;
|
||||
legendary++;
|
||||
|
||||
let rarity;
|
||||
if (combined[i].type === 'character') {
|
||||
rarity = characters[combined[i].id].rarity;
|
||||
} else if (combined[i].type === 'weapon') {
|
||||
rarity = weaponList[combined[i].id].rarity;
|
||||
}
|
||||
|
||||
if (rarity === 5) {
|
||||
combined[i].pity = legendary;
|
||||
legendary = 0;
|
||||
// rare = 0;
|
||||
} else if (rarity === 4) {
|
||||
combined[i].pity = rare;
|
||||
rare = 0;
|
||||
} else {
|
||||
combined[i].pity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
const data = {
|
||||
total: combined.length,
|
||||
legendary,
|
||||
rare,
|
||||
pulls: combined,
|
||||
};
|
||||
|
||||
await updateSave(path, data);
|
||||
}
|
||||
|
||||
async function save() {
|
||||
loading = true;
|
||||
|
||||
for (const id of Object.keys(bannerCategories)) {
|
||||
const { path, data } = await readLocalData(id);
|
||||
const { append, prepend } = added[id];
|
||||
|
||||
const beginning = prepend.map((e) => ({
|
||||
id: e[2],
|
||||
time: e[1],
|
||||
type: e[0],
|
||||
pity: 0,
|
||||
}));
|
||||
const end = append.map((e) => ({
|
||||
id: e[2],
|
||||
time: e[1],
|
||||
type: e[0],
|
||||
pity: 0,
|
||||
}));
|
||||
|
||||
const combined = [...beginning, ...data, ...end];
|
||||
|
||||
await processWishes(path, combined);
|
||||
}
|
||||
|
||||
const prefix = getAccountPrefix();
|
||||
await updateSave(`${prefix}collectables-updated`, true);
|
||||
|
||||
pushToast($t('wish.excel.success'));
|
||||
loading = false;
|
||||
closeModal();
|
||||
}
|
||||
|
||||
async function parseData(id, imported) {
|
||||
const { newest, oldest } = await readLocalData(id);
|
||||
const append = [];
|
||||
const prepend = [];
|
||||
|
||||
console.log(newest, oldest);
|
||||
|
||||
// new wishes
|
||||
imported.reverse();
|
||||
let index = 0;
|
||||
for (const row of imported) {
|
||||
if (dayjs(row[1]).isAfter(newest)) {
|
||||
append.push(row);
|
||||
index++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
imported = imported.slice(index, imported.length);
|
||||
|
||||
// old wishes
|
||||
imported.reverse();
|
||||
for (const row of imported) {
|
||||
if (dayjs(row[1]).isBefore(oldest)) {
|
||||
prepend.push(row);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
append.reverse();
|
||||
|
||||
console.log(prepend);
|
||||
console.log(append);
|
||||
|
||||
added[id] = {
|
||||
append,
|
||||
prepend,
|
||||
};
|
||||
}
|
||||
|
||||
async function readPaimonExcel(workbook) {
|
||||
const informationSheet = workbook.getWorksheet('Information');
|
||||
if (!informationSheet) {
|
||||
pushToast($t('wish.excel.errorExcelPaimon'), 'error');
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const row = informationSheet.getCell('A1').value;
|
||||
|
||||
if (row !== 'Paimon.moe Wish History Export') {
|
||||
pushToast($t('wish.excel.errorExcelPaimon'), 'error');
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const bannerCategories = {
|
||||
'character-event': 'Character Event',
|
||||
'weapon-event': 'Weapon Event',
|
||||
standard: 'Standard',
|
||||
beginners: "Beginners' Wish",
|
||||
};
|
||||
|
||||
const weapons = Object.values(weaponList);
|
||||
const chars = Object.values(characters);
|
||||
|
||||
for (const [id, name] of Object.entries(bannerCategories)) {
|
||||
const sheet = workbook.getWorksheet(name);
|
||||
const wishes = [];
|
||||
sheet.eachRow((row, index) => {
|
||||
if (index === 1) return;
|
||||
const type = row.getCell(1).text.toLowerCase();
|
||||
const time = row.getCell(3).text;
|
||||
const fullName = row.getCell(2).text;
|
||||
let name = '';
|
||||
if (type === 'weapon') {
|
||||
name = weapons.find((e) => e.name === fullName).id;
|
||||
} else if (type === 'character') {
|
||||
name = chars.find((e) => e.name === fullName).id;
|
||||
}
|
||||
|
||||
if (name === '') {
|
||||
pushToast($t('wish.excel.errorUnknownItem'), 'error');
|
||||
loading = false;
|
||||
throw 'unknown reward name';
|
||||
}
|
||||
|
||||
wishes.push([type, time, name]);
|
||||
});
|
||||
|
||||
console.log('from excel', name, wishes.length);
|
||||
await parseData(id, wishes);
|
||||
}
|
||||
|
||||
step = 1;
|
||||
loading = false;
|
||||
}
|
||||
|
||||
async function readGachaExportExcel(workbook) {
|
||||
const bannerCategories = {
|
||||
'character-event': 'Character Event Wish',
|
||||
'weapon-event': 'Weapon Event Wish',
|
||||
standard: 'Permanent Wish',
|
||||
beginners: "Novice Wishes",
|
||||
};
|
||||
|
||||
const weapons = Object.values(weaponList);
|
||||
const chars = Object.values(characters);
|
||||
|
||||
for (const [id, name] of Object.entries(bannerCategories)) {
|
||||
const sheet = workbook.getWorksheet(name);
|
||||
const wishes = [];
|
||||
sheet.eachRow((row, index) => {
|
||||
if (index === 1) return;
|
||||
const type = row.getCell(3).text.toLowerCase();
|
||||
const time = row.getCell(1).text;
|
||||
const fullName = row.getCell(2).text;
|
||||
let name = '';
|
||||
if (type === 'weapon') {
|
||||
name = weapons.find((e) => e.name === fullName).id;
|
||||
} else if (type === 'character') {
|
||||
name = chars.find((e) => e.name === fullName).id;
|
||||
}
|
||||
|
||||
if (name === '') {
|
||||
pushToast($t('wish.excel.errorUnknownItem'), 'error');
|
||||
loading = false;
|
||||
throw 'unknown reward name';
|
||||
}
|
||||
|
||||
wishes.push([type, time, name]);
|
||||
});
|
||||
|
||||
console.log('from excel', name, wishes.length);
|
||||
await parseData(id, wishes);
|
||||
}
|
||||
|
||||
step = 1;
|
||||
loading = false;
|
||||
}
|
||||
|
||||
async function readExcel(file) {
|
||||
loading = true;
|
||||
|
||||
const workbook = new Workbook();
|
||||
|
||||
try {
|
||||
const buffer = await fileToBuffer(file);
|
||||
await workbook.xlsx.load(buffer);
|
||||
} catch (err) {
|
||||
pushToast($t('wish.excel.errorReadExcel'), 'error');
|
||||
loading = false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (selectedType === 'default') {
|
||||
readPaimonExcel(workbook);
|
||||
} else {
|
||||
readGachaExportExcel(workbook);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
pushToast($t('wish.excel.errorReadExcel'), 'error');
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function checkFile(file) {
|
||||
console.log(file.type);
|
||||
if (file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
|
||||
readExcel(file);
|
||||
} else {
|
||||
pushToast($t('wish.excel.errorInvalidFile'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function onFileChange(event) {
|
||||
const target = event.target;
|
||||
const { files } = target;
|
||||
|
||||
if (files === null || files.length === 0) return;
|
||||
const file = files[0];
|
||||
|
||||
checkFile(file);
|
||||
fileInput.value = null;
|
||||
}
|
||||
|
||||
function dropHandler(ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
if (ev.dataTransfer.items) {
|
||||
if (ev.dataTransfer.items[0].kind === 'file') {
|
||||
const file = ev.dataTransfer.items[0].getAsFile();
|
||||
checkFile(file);
|
||||
}
|
||||
} else {
|
||||
checkFile(ev.dataTransfer.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function dragOverHandler(ev) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
const fileToBuffer = (file) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (event) => {
|
||||
if (event.target === null) {
|
||||
reject(new Error('Failed to read file'));
|
||||
} else {
|
||||
const buffer = event.target.result;
|
||||
resolve(buffer);
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h1 class="font-display text-white text-xl mb-2">{$t('wish.excel.title')}</h1>
|
||||
{#if step === 0}
|
||||
<div class="mb-4 bg-background rounded-xl p-4">
|
||||
<ol class="list-decimal ml-4">
|
||||
<li class="text-red-300">{$t('wish.excel.notice.0')}</li>
|
||||
<li class="text-white">{$t('wish.excel.notice.1')}</li>
|
||||
<li class="text-white">{$t('wish.excel.notice.2')}</li>
|
||||
<li class="text-white">{$t('wish.excel.notice.3')}</li>
|
||||
</ol>
|
||||
</div>
|
||||
<p class="text-gray-200 mb-2">{$t('wish.excel.subtitle')}</p>
|
||||
<div class="flex flex-row">
|
||||
<button on:click={() => changeType('default')} class={`pill ${selectedType === 'default' ? 'active' : ''}`}>
|
||||
{$t('wish.excel.default')}
|
||||
</button>
|
||||
<button on:click={() => changeType('takagg')} class={`pill ${selectedType === 'takagg' ? 'active' : ''}`}>
|
||||
{$t('wish.excel.takagg')}
|
||||
</button>
|
||||
</div>
|
||||
<input on:change={onFileChange} type="file" style="display: none;" bind:this={fileInput} />
|
||||
<!-- <Button disabled={loading} on:click={selectFile}>
|
||||
{loading ? $t('wish.excel.processing') : $t(`wish.excel.selectFile.${selectedType}`)}
|
||||
</Button> -->
|
||||
<div
|
||||
on:click={selectFile}
|
||||
on:drop={dropHandler}
|
||||
on:dragover={dragOverHandler}
|
||||
class="w-full h-32 rounded-xl border-dashed border-2 border-gray-400 flex items-center justify-center cursor-pointer p-8"
|
||||
>
|
||||
<p class="text-white">{loading ? $t('wish.excel.processing') : $t(`wish.excel.selectFile.${selectedType}`)}</p>
|
||||
</div>
|
||||
{/if}
|
||||
{#if step === 1}
|
||||
<table>
|
||||
<tr>
|
||||
<td class="px-2 text-white border-r border-gray-700">{$t('wish.excel.addedOn')}</td>
|
||||
<td class="px-2 text-white border-r border-gray-700 text-center">{$t('wish.excel.beginning')}</td>
|
||||
<td class="px-2 text-white border-r border-gray-700 text-center">{$t('wish.excel.end')}</td>
|
||||
<td class="px-2 text-white border-gray-700 text-center">{$t('wish.excel.total')}</td>
|
||||
</tr>
|
||||
{#each Object.entries(added) as [id, data]}
|
||||
<tr>
|
||||
<td class="px-2 text-white border-r border-t border-gray-700">{bannerCategories[id]}</td>
|
||||
<td class="px-2 text-white border-r border-t border-gray-700 text-center">{data.prepend.length}</td>
|
||||
<td class="px-2 text-white border-r border-t border-gray-700 text-center">{data.append.length}</td>
|
||||
<td class="px-2 text-white border-t border-gray-700 text-center">
|
||||
{data.prepend.length + data.append.length}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</table>
|
||||
<p class="text-white py-2">{$t('wish.excel.saveNotice')}</p>
|
||||
<Button disabled={loading} on:click={save}>{$t('wish.excel.save')}</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.pill {
|
||||
@apply rounded-2xl;
|
||||
@apply border-2;
|
||||
@apply border-white;
|
||||
@apply border-opacity-25;
|
||||
@apply text-white;
|
||||
@apply px-4;
|
||||
@apply py-1;
|
||||
@apply mr-2;
|
||||
@apply mb-2;
|
||||
@apply outline-none;
|
||||
@apply transition;
|
||||
@apply duration-100;
|
||||
|
||||
&:hover {
|
||||
@apply border-primary;
|
||||
}
|
||||
|
||||
&.active {
|
||||
@apply bg-primary;
|
||||
@apply border-primary;
|
||||
@apply text-background;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,61 +1,12 @@
|
|||
<script>
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import { mdiCheckCircleOutline, mdiLoading, mdiPencil, mdiStar } from '@mdi/js';
|
||||
import Icon from './Icon.svelte';
|
||||
import Button from './Button.svelte';
|
||||
import Checkbox from '../components/Checkbox.svelte';
|
||||
|
||||
import { exportToExcel } from '../functions/export';
|
||||
import { submitWishTally } from '../functions/wishTally';
|
||||
import { pushToast } from '../stores/toast';
|
||||
|
||||
export let setManualInput;
|
||||
export let settings;
|
||||
|
||||
let loadingExport = false;
|
||||
let wishTallySubmitted = false;
|
||||
|
||||
let enableManual = settings.manualInput;
|
||||
|
||||
function toggleManual() {
|
||||
setManualInput(enableManual);
|
||||
}
|
||||
|
||||
async function exportFile() {
|
||||
loadingExport = true;
|
||||
await exportToExcel();
|
||||
loadingExport = false;
|
||||
pushToast($t('wish.help.exportFinish'));
|
||||
}
|
||||
|
||||
$: enableManual, toggleManual();
|
||||
import { mdiPencil, mdiStar } from '@mdi/js';
|
||||
import Icon from '../../components/Icon.svelte';
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<!-- <h1 class="font-display text-white text-xl mb-4">{$t('wish.help.title')}</h1> -->
|
||||
<h1 class="font-display text-white text-xl mb-2">{$t('wish.help.exportTitle')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<p class="mb-2">{$t('wish.help.exportMessage')}</p>
|
||||
<Button className="mr-2" disabled={loadingExport} on:click={exportFile}>
|
||||
{#if loadingExport}
|
||||
<Icon path={mdiLoading} spin size={0.8} className="mr-2" />
|
||||
{/if}
|
||||
{$t(loadingExport ? 'wish.help.exporting' : 'wish.help.export')}
|
||||
</Button>
|
||||
<!-- <Button disabled={loadingExport}>{$t('wish.help.import')}</Button> -->
|
||||
</div>
|
||||
<h1 class="font-display text-white text-xl mt-8 mb-2">{$t('wish.help.manualTitle')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<div class="py-2 pl-4">
|
||||
<Checkbox disabled={false} bind:checked={enableManual}
|
||||
><span class="select-none cursor-pointer">{$t('wish.help.enableManual')}</span></Checkbox
|
||||
>
|
||||
</div>
|
||||
<p class="text-red-300">{$t('wish.help.notice')}</p>
|
||||
<p>{$t('wish.help.consider')}</p>
|
||||
</div>
|
||||
<h1 class="font-display text-white text-xl mt-8 mb-2">{$t('wish.help.howto.title')}</h1>
|
||||
<h1 class="font-display text-white text-xl mb-2">{$t('wish.help.howto.title')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<p class="mb-2">{$t('wish.help.howto.subtitle')}</p>
|
||||
<p class="mb-2">
|
|
@ -0,0 +1,74 @@
|
|||
<script>
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import { mdiLoading } from '@mdi/js';
|
||||
import Icon from '../../components/Icon.svelte';
|
||||
import Button from '../../components/Button.svelte';
|
||||
import Checkbox from '../../components/Checkbox.svelte';
|
||||
|
||||
import { exportToExcel } from '../../functions/export';
|
||||
import { pushToast } from '../../stores/toast';
|
||||
import ExcelImportModal from './_excelImport.svelte';
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
const { open: openModal, close: closeModal } = getContext('simple-modal');
|
||||
|
||||
export let setManualInput;
|
||||
export let settings;
|
||||
export let closeImportModal;
|
||||
|
||||
let loadingExport = false;
|
||||
|
||||
let enableManual = settings.manualInput;
|
||||
|
||||
function toggleManual() {
|
||||
setManualInput(enableManual);
|
||||
}
|
||||
|
||||
async function exportFile() {
|
||||
loadingExport = true;
|
||||
await exportToExcel();
|
||||
loadingExport = false;
|
||||
pushToast($t('wish.help.exportFinish'));
|
||||
}
|
||||
|
||||
function openImporter() {
|
||||
openModal(
|
||||
ExcelImportModal,
|
||||
{
|
||||
closeModal: closeImportModal
|
||||
},
|
||||
{
|
||||
closeButton: false,
|
||||
styleWindow: { background: '#25294A', width: '800px' },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
$: enableManual, toggleManual();
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h1 class="font-display text-white text-xl mb-2">{$t('wish.help.exportTitle')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<p class="mb-2">{$t('wish.help.exportMessage')}</p>
|
||||
<Button className="mr-2" disabled={loadingExport} on:click={exportFile}>
|
||||
{#if loadingExport}
|
||||
<Icon path={mdiLoading} spin size={0.8} className="mr-2" />
|
||||
{/if}
|
||||
{$t(loadingExport ? 'wish.help.exporting' : 'wish.help.export')}
|
||||
</Button>
|
||||
<Button disabled={loadingExport} on:click={openImporter}>{$t('wish.help.import')}</Button>
|
||||
</div>
|
||||
<h1 class="font-display text-white text-xl mt-8 mb-2">{$t('wish.help.manualTitle')}</h1>
|
||||
<div class="text-white p-2 bg-background rounded-xl">
|
||||
<div class="py-2 pl-4">
|
||||
<Checkbox disabled={false} bind:checked={enableManual}
|
||||
><span class="select-none cursor-pointer">{$t('wish.help.enableManual')}</span></Checkbox
|
||||
>
|
||||
</div>
|
||||
<p class="text-red-300">{$t('wish.help.notice')}</p>
|
||||
<p>{$t('wish.help.consider')}</p>
|
||||
</div>
|
||||
</div>
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import { onMount } from 'svelte';
|
||||
import dayjs from 'dayjs';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
import { characters } from '../../data/characters';
|
||||
import { weaponList } from '../../data/weaponList';
|
||||
|
@ -24,14 +25,16 @@
|
|||
let wishCount = 0;
|
||||
const avg = {};
|
||||
|
||||
$: if ($fromRemote) {
|
||||
const readDebounced = debounce(() => {
|
||||
readLocalData();
|
||||
}, 1000);
|
||||
|
||||
$: if ($fromRemote) {
|
||||
readDebounced();
|
||||
}
|
||||
|
||||
$: if ($updateTime) {
|
||||
setTimeout(() => {
|
||||
readLocalData();
|
||||
}, 1000);
|
||||
readDebounced();
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
|
@ -76,6 +79,8 @@
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
export async function readLocalData() {
|
||||
let totalWish = 0;
|
||||
console.log('wish summary read local');
|
||||
|
@ -94,7 +99,7 @@
|
|||
}
|
||||
updateCollectedCharacters = true;
|
||||
} else {
|
||||
collectedCharacters = {...defaultChars};
|
||||
collectedCharacters = JSON.parse(JSON.stringify(defaultChars));
|
||||
}
|
||||
const collectablesNeedUpdateData = await readSave(`${prefix}collectables-updated`);
|
||||
if (collectablesNeedUpdateData === null || collectablesNeedUpdateData === true) {
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
</tr>
|
||||
</table>
|
||||
{#if avg.legendary.pulls.length > 0}
|
||||
<div class="flex flex-wrap mt-2 overflow-y-auto" style="max-height: 300px;">
|
||||
<div class="flex flex-wrap mt-2 overflow-y-auto" style="max-height: 500px;">
|
||||
{#each avg.legendary.pulls as pull}
|
||||
<span class="pity">{pull.name} <span style={calculateColor((90 - pull.pity) / 90)}>{pull.pity}</span></span>
|
||||
{/each}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<script>
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
import { mdiDatabaseImport, mdiHelpCircle } from '@mdi/js';
|
||||
import { mdiCog, mdiDatabaseImport, mdiHelpCircle } from '@mdi/js';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
|
||||
import Button from '../../components/Button.svelte';
|
||||
import Icon from '../../components/Icon.svelte';
|
||||
import HowToModal from '../../components/WishCounterHowToModal.svelte';
|
||||
import ImportModal from '../../components/WishImportModal.svelte';
|
||||
import { fromRemote, readSave, updateSave } from '../../stores/saveManager';
|
||||
|
||||
|
@ -14,6 +13,8 @@
|
|||
import Counter from './_counter.svelte';
|
||||
import FirstTimePopup from './_firstTime.svelte';
|
||||
import MonthlyGraph from './_monthlyGraph.svelte';
|
||||
import HowToModal from './_helpModal.svelte';
|
||||
import SettingModal from './_settingModal.svelte';
|
||||
|
||||
const { open: openModal, close: closeModal } = getContext('simple-modal');
|
||||
|
||||
|
@ -78,9 +79,21 @@
|
|||
function openHowTo() {
|
||||
openModal(
|
||||
HowToModal,
|
||||
{},
|
||||
{
|
||||
closeButton: false,
|
||||
styleWindow: { background: '#25294A', width: '800px' },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function openSetting() {
|
||||
openModal(
|
||||
SettingModal,
|
||||
{
|
||||
setManualInput,
|
||||
settings,
|
||||
closeImportModal,
|
||||
},
|
||||
{
|
||||
closeButton: false,
|
||||
|
@ -111,6 +124,7 @@
|
|||
counter3.readLocalData();
|
||||
counter4.readLocalData();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@ -131,18 +145,30 @@
|
|||
<Icon size={0.8} path={mdiDatabaseImport} />
|
||||
{$t('wish.autoImport')}
|
||||
</Button>
|
||||
<Button on:click={openHowTo} className="hidden md:block">
|
||||
<Icon size={0.8} path={mdiHelpCircle} />
|
||||
{$t('wish.helpAndSetting')}
|
||||
{#if settings.manualInput}
|
||||
<Button on:click={openHowTo} className="mr-2 hidden md:block">
|
||||
<Icon size={0.8} path={mdiHelpCircle} />
|
||||
{$t('wish.helps')}
|
||||
</Button>
|
||||
{/if}
|
||||
<Button on:click={openSetting} className="hidden md:block">
|
||||
<Icon size={0.8} path={mdiCog} />
|
||||
{$t('wish.settings')}
|
||||
</Button>
|
||||
<div class="md:hidden flex flex-wrap justify-center">
|
||||
<Button className="m-1" on:click={openImport}>
|
||||
<Icon size={0.8} path={mdiDatabaseImport} />
|
||||
{$t('wish.autoImport')}
|
||||
</Button>
|
||||
<Button className="m-1" on:click={openHowTo}>
|
||||
<Icon size={0.8} path={mdiHelpCircle} />
|
||||
{$t('wish.helpAndSetting')}
|
||||
{#if settings.manualInput}
|
||||
<Button className="m-1" on:click={openHowTo}>
|
||||
<Icon size={0.8} path={mdiHelpCircle} />
|
||||
{$t('wish.helps')}
|
||||
</Button>
|
||||
{/if}
|
||||
<Button className="m-1" on:click={openSetting}>
|
||||
<Icon size={0.8} path={mdiCog} />
|
||||
{$t('wish.settings')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue