mirror of https://github.com/hykilpikonna/AquaDX
[+] Import player data, tested with maimai
parent
7c4f887ef4
commit
a71c2bd8ec
|
@ -82,6 +82,8 @@ export const EN_REF_HOME = {
|
|||
'home.join-discord-description': 'Join our Discord server to chat with other players and get help.',
|
||||
'home.setup': 'Setup Connection',
|
||||
'home.setup-description': 'If you own a cab or arcade setup, begin setting up the connection.',
|
||||
'home.import': 'Import Player Data',
|
||||
'home.import-description': 'If you are from another server, you can import your data here.',
|
||||
'home.linkcard.cards': 'Your Cards',
|
||||
'home.linkcard.description': 'Here are the cards you have linked to your account',
|
||||
'home.linkcard.account-card': 'Account Card',
|
||||
|
@ -109,6 +111,9 @@ export const EN_REF_HOME = {
|
|||
'home.setup.ask': 'If you have any questions, please ask in our',
|
||||
'home.setup.support': 'server',
|
||||
'home.setup.keychip-tips': 'This is your unique keychip, do not share it with anyone',
|
||||
'home.import.unknown-game': 'Unknown game type',
|
||||
'home.import.new-data': 'Data to import',
|
||||
'home.import.data-conflict': 'Proceed will override your current data',
|
||||
}
|
||||
|
||||
export const EN_REF_SETTINGS = {
|
||||
|
|
|
@ -91,6 +91,8 @@ const zhHome: typeof EN_REF_HOME = {
|
|||
'home.join-discord-description': '加入我们的 Discord 群,与其他玩家聊天、获取帮助',
|
||||
'home.setup': '连接到 AquaDX',
|
||||
'home.setup-description': '如果您有街机框体或者手台,点击这里设置服务器的连接',
|
||||
'home.import': '导入玩家数据',
|
||||
'home.import-description': '如果你来自其他在线服,可以点击这里导入从其他服务器导出的数据',
|
||||
'home.linkcard.cards': "已绑卡片",
|
||||
'home.linkcard.description': "这些是您绑定到帐户的卡",
|
||||
'home.linkcard.account-card': "账户卡",
|
||||
|
@ -118,6 +120,9 @@ const zhHome: typeof EN_REF_HOME = {
|
|||
'home.setup.ask': "如果您有任何问题, 请加入我们的",
|
||||
'home.setup.support': "以获取支持",
|
||||
'home.setup.keychip-tips': "这是你的狗号, 不要与任何人分享",
|
||||
'home.import.unknown-game': '未知游戏类型',
|
||||
'home.import.new-data': '要导入的数据',
|
||||
'home.import.data-conflict': '继续导入将覆盖现有数据',
|
||||
}
|
||||
|
||||
const zhSettings: typeof EN_REF_SETTINGS = {
|
||||
|
|
|
@ -303,6 +303,8 @@ export const GAME = {
|
|||
post(`/api/v2/game/${game}/change-name`, { newName }),
|
||||
export: (game: GameName): Promise<Record<string, any>> =>
|
||||
post(`/api/v2/game/${game}/export`),
|
||||
import: (game: GameName, data: any): Promise<Record<string, any>> =>
|
||||
post(`/api/v2/game/${game}/import`, {}, { body: JSON.stringify(data) }),
|
||||
}
|
||||
|
||||
export const DATA = {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import StatusOverlays from "../components/StatusOverlays.svelte";
|
||||
import ActionCard from "../components/ActionCard.svelte";
|
||||
import { t } from "../libs/i18n";
|
||||
import ImportDataAction from "./Home/ImportDataAction.svelte";
|
||||
|
||||
USER.ensureLoggedIn();
|
||||
|
||||
|
@ -54,6 +55,8 @@
|
|||
<h3>{t('home.setup')}</h3>
|
||||
<span>{t('home.setup-description')}</span>
|
||||
</ActionCard>
|
||||
|
||||
<ImportDataAction/>
|
||||
</div>
|
||||
{:else if tab === 1}
|
||||
<div out:fade={FADE_OUT} in:fade={FADE_IN}>
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
<script lang="ts">
|
||||
import { fade } from "svelte/transition"
|
||||
import { t } from "../../libs/i18n";
|
||||
import ActionCard from "../../components/ActionCard.svelte";
|
||||
import StatusOverlays from "../../components/StatusOverlays.svelte";
|
||||
import { CARD, GAME, USER } from "../../libs/sdk";
|
||||
import Icon from "@iconify/svelte";
|
||||
|
||||
let load = false;
|
||||
let error = "";
|
||||
let conflict: {
|
||||
oldName: string,
|
||||
oldRating: number,
|
||||
newName: string,
|
||||
newRating: number
|
||||
} | null;
|
||||
let confirmAction: (override: boolean) => void;
|
||||
|
||||
const startImport = async () => {
|
||||
const [fileHandle] = await window.showOpenFilePicker({
|
||||
id: 'aquadx_import',
|
||||
startIn: 'downloads',
|
||||
types: [
|
||||
{
|
||||
description: "Aqua Player Data",
|
||||
accept: {
|
||||
"application/json": [".json"],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (!fileHandle) return;
|
||||
load = true;
|
||||
|
||||
try {
|
||||
const file = await fileHandle.getFile();
|
||||
const data = JSON.parse(await file.text()) as any;
|
||||
const game = getGameByCode(data.gameId);
|
||||
|
||||
const me = await USER.me();
|
||||
const userGames = await CARD.userGames(me.username);
|
||||
|
||||
const existed = userGames[game];
|
||||
if (existed) {
|
||||
conflict = {
|
||||
oldName: existed.name,
|
||||
oldRating: existed.rating,
|
||||
newName: data.userData.userName,
|
||||
newRating: data.userData.playerRating
|
||||
};
|
||||
if (!await new Promise(resolve => confirmAction = resolve)) {
|
||||
return;
|
||||
}
|
||||
conflict = null;
|
||||
}
|
||||
|
||||
await GAME.import(game, data);
|
||||
location.href = `/u/${me.username}/${game}`;
|
||||
} catch (e: any) {
|
||||
error = e.message;
|
||||
} finally {
|
||||
conflict = null;
|
||||
load = false;
|
||||
}
|
||||
}
|
||||
|
||||
const getGameByCode = (code: string) => {
|
||||
switch (code.toUpperCase()) {
|
||||
case 'SDEZ':
|
||||
return 'mai2';
|
||||
case 'SDHD':
|
||||
return 'chu3';
|
||||
default:
|
||||
throw new Error(t('home.import.unknown-game'));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ActionCard color="209, 124, 102" icon="bxs:file-import" on:click={startImport}>
|
||||
<h3>{t('home.import')}</h3>
|
||||
<span>{t('home.import-description')}</span>
|
||||
</ActionCard>
|
||||
|
||||
<StatusOverlays {error} loading={load}/>
|
||||
|
||||
{#if conflict}
|
||||
<div class="overlay" transition:fade>
|
||||
<div>
|
||||
<h2>{t('home.import.data-conflict')}</h2>
|
||||
<p></p>
|
||||
<div class="conflict-cards">
|
||||
<div class="old card">
|
||||
<span class="type">{t('home.linkcard.account-card')}</span>
|
||||
<span>{t('home.linkcard.name')}: {conflict.oldName}</span>
|
||||
<span>{t('home.linkcard.rating')}: {conflict.oldRating}</span>
|
||||
<div class="trash">
|
||||
<Icon icon="ph:trash-duotone"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<Icon icon="icon-park-outline:down"/>
|
||||
</div>
|
||||
<div class="new card">
|
||||
<span class="type">{t('home.import.new-data')}</span>
|
||||
<span>{t('home.linkcard.name')}: {conflict.newName}</span>
|
||||
<span>{t('home.linkcard.rating')}: {conflict.newRating}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p></p>
|
||||
<div class="buttons">
|
||||
<button on:click={() => confirmAction(false)}>{t('action.cancel')}</button>
|
||||
<button class="error" on:click={() => confirmAction(true)}>{t('action.confirm')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="sass">
|
||||
@import "../../vars"
|
||||
h3
|
||||
font-size: 1.3rem
|
||||
margin: 0
|
||||
|
||||
.conflict-cards
|
||||
display: grid
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))
|
||||
gap: 0.5rem
|
||||
align-items: center
|
||||
|
||||
span:not(.type)
|
||||
font-size: 0.8rem
|
||||
|
||||
.old
|
||||
background: #ff6b6b20
|
||||
border: 1px solid $c-error
|
||||
color: #ffffff99
|
||||
position: relative
|
||||
|
||||
.trash
|
||||
display: flex
|
||||
position: absolute
|
||||
bottom: 0.5rem
|
||||
right: 0.5rem
|
||||
color: $c-error
|
||||
opacity: 0.6
|
||||
font-size: 2rem
|
||||
|
||||
.new
|
||||
background: #646cff20
|
||||
border: 1px solid $c-darker
|
||||
|
||||
.buttons
|
||||
display: grid
|
||||
grid-template-columns: 1fr 1fr
|
||||
gap: 1rem
|
||||
|
||||
.icon
|
||||
display: flex
|
||||
justify-content: center
|
||||
font-size: 2rem
|
||||
</style>
|
Loading…
Reference in New Issue