mirror of
https://github.com/MadeBaruna/paimon-moe.git
synced 2025-01-03 17:52:11 +01:00
WIP: data conflict resolve
This commit is contained in:
parent
925355bc32
commit
8567c6b831
6 changed files with 99 additions and 14 deletions
|
@ -2,13 +2,13 @@
|
|||
// doc: /static/images.save_sync_flow.png
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import { onMount, getContext } from 'svelte';
|
||||
import { driveSignedIn, driveLoading, saveId } from '../stores/dataSync';
|
||||
import { onMount, getContext, setContext } from 'svelte';
|
||||
import { driveSignedIn, driveLoading, saveId, synced } from '../stores/dataSync';
|
||||
import { getLocalSaveJson, updateSave, updateTime, UPDATE_TIME_KEY } from '../stores/saveManager';
|
||||
|
||||
import SyncConflictModal from '../components/SyncConflictModal.svelte';
|
||||
|
||||
const { open: openModal } = getContext('simple-modal');
|
||||
const { open: openModal, close: closeModal } = getContext('simple-modal');
|
||||
|
||||
const CLIENT_ID = __paimon.env.GOOGLE_DRIVE_CLIENT_ID;
|
||||
const API_KEY = __paimon.env.GOOGLE_DRIVE_API_KEY;
|
||||
|
@ -19,12 +19,21 @@
|
|||
|
||||
$: localSaveExists = $updateTime !== null;
|
||||
|
||||
setContext('sync', {
|
||||
startSync,
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
startSync();
|
||||
});
|
||||
|
||||
function startSync() {
|
||||
synced.set(false);
|
||||
const script = document.createElement('script');
|
||||
script.onload = handleClientLoad;
|
||||
script.src = 'https://apis.google.com/js/api.js';
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function handleClientLoad() {
|
||||
gapi.load('client:auth2', initClient);
|
||||
|
@ -37,6 +46,8 @@
|
|||
|
||||
if (status) {
|
||||
getFiles();
|
||||
} else {
|
||||
synced.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +62,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function useRemoteData() {
|
||||
for (const k in remoteSave) {
|
||||
updateSave(k, remoteSave[k], true);
|
||||
}
|
||||
|
||||
synced.set(true);
|
||||
closeModal();
|
||||
}
|
||||
|
||||
async function useLocalData() {
|
||||
await saveData(getLocalSaveJson());
|
||||
|
||||
synced.set(true);
|
||||
closeModal();
|
||||
}
|
||||
|
||||
async function compareLocalSave() {
|
||||
try {
|
||||
const data = await getData();
|
||||
|
@ -65,6 +92,8 @@
|
|||
remoteTime: remoteTime,
|
||||
localTime: $updateTime,
|
||||
downloadBackup: exportData,
|
||||
useRemote: useRemoteData,
|
||||
useLocal: useLocalData,
|
||||
},
|
||||
{
|
||||
closeButton: false,
|
||||
|
@ -73,6 +102,8 @@
|
|||
styleWindow: { background: '#25294A' },
|
||||
},
|
||||
);
|
||||
} else {
|
||||
synced.set(true);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
@ -100,6 +131,7 @@
|
|||
await compareLocalSave();
|
||||
} else {
|
||||
await copyRemoteToLocal();
|
||||
synced.set(true);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
@ -125,6 +157,7 @@
|
|||
await saveData(getLocalSaveJson());
|
||||
}
|
||||
|
||||
synced.set(true);
|
||||
console.log(result);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
@ -140,6 +173,7 @@
|
|||
alt: 'media',
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
return result;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
@ -199,3 +233,5 @@
|
|||
fileLink.click();
|
||||
}
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { mdiCloudAlert, mdiContentSave, mdiDownload, mdiFile, mdiGoogleDrive, mdiUpload } from '@mdi/js';
|
||||
import { mdiCloudAlert, mdiContentSave, mdiDownload, mdiFile, mdiGoogleDrive, mdiLoading, mdiUpload } from '@mdi/js';
|
||||
import Button from './Button.svelte';
|
||||
|
||||
import Icon from './Icon.svelte';
|
||||
|
@ -7,6 +7,20 @@
|
|||
export let remoteTime;
|
||||
export let localTime;
|
||||
export let downloadBackup = () => {};
|
||||
export let useRemote = () => {};
|
||||
export let useLocal = () => {};
|
||||
|
||||
let loading = false;
|
||||
|
||||
function useLocalData() {
|
||||
loading = true;
|
||||
useLocal();
|
||||
}
|
||||
|
||||
function useRemoteData() {
|
||||
loading = true;
|
||||
useRemote();
|
||||
}
|
||||
|
||||
const remoteFormatted = remoteTime.format('dddd, MMMM D, YYYY h:mm A');
|
||||
const localFormatted = localTime.format('dddd, MMMM D, YYYY h:mm A');
|
||||
|
@ -26,8 +40,8 @@
|
|||
{remoteNewer ? 'NEWER' : 'OLDER'}
|
||||
</p>
|
||||
<p class="text-gray-400 mt-1">Last modified: {remoteFormatted}</p>
|
||||
<Button className="mt-2 w-full">
|
||||
<Icon path={mdiDownload} className="mr-1" />Replace Local Data
|
||||
<Button disabled={loading} className="mt-2 w-full" on:click={useRemoteData}>
|
||||
<Icon path={loading ? mdiLoading : mdiDownload} spin={loading} className="mr-1" />Replace Local Data
|
||||
</Button>
|
||||
</div>
|
||||
<p class="mt-2 text-white text-center">OR</p>
|
||||
|
@ -38,8 +52,8 @@
|
|||
{remoteNewer ? 'OLDER' : 'NEWER'}
|
||||
</p>
|
||||
<p class="text-gray-400 mt-1">Last modified: {localFormatted}</p>
|
||||
<Button className="mt-2 w-full">
|
||||
<Icon path={mdiUpload} className="mr-1" />Replace Google Drive Data
|
||||
<Button disabled={loading} className="mt-2 w-full" on:click={useLocalData}>
|
||||
<Icon path={loading ? mdiLoading : mdiUpload} spin={loading} className="mr-1" />Replace Google Drive Data
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex mt-6 justify-end">
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
<Sidebar {segment} mobile />
|
||||
{/if}
|
||||
<Modal>
|
||||
<DataSync>
|
||||
<main style="flex: 1 0 auto;">
|
||||
<slot />
|
||||
</main>
|
||||
<DataSync />
|
||||
</DataSync>
|
||||
</Modal>
|
||||
<p class="lg:ml-64 px-8 py-4 text-gray-600">
|
||||
Paimon.moe is not affiliated with miHoYo.<br />
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
});
|
||||
|
||||
function readLocalData() {
|
||||
console.log('wish read local');
|
||||
const data = readSave(path);
|
||||
if (data !== null) {
|
||||
const counterData = JSON.parse(data);
|
||||
|
|
|
@ -2,5 +2,6 @@ import { writable } from 'svelte/store';
|
|||
|
||||
export const driveSignedIn = writable(false);
|
||||
export const driveLoading = writable(true);
|
||||
export const synced = writable(true);
|
||||
export const lastSyncTime = writable(null);
|
||||
export const synced = writable(false);
|
||||
export const saveId = writable('');
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
import dayjs from 'dayjs';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
import { synced } from './dataSync';
|
||||
|
||||
export const updateTime = writable(null);
|
||||
export const fromRemote = writable(false);
|
||||
|
||||
export const UPDATE_TIME_KEY = 'update-time';
|
||||
|
||||
let pendingQueue = [];
|
||||
let queueSave = true;
|
||||
|
||||
const unsubscribe = synced.subscribe((value) => {
|
||||
console.log('synced:', value);
|
||||
queueSave = !value;
|
||||
|
||||
if (value) {
|
||||
flushPendingQueue();
|
||||
}
|
||||
});
|
||||
|
||||
export const checkLocalSave = () => {
|
||||
const localUpdateTime = localStorage.getItem(UPDATE_TIME_KEY);
|
||||
if (localUpdateTime !== null) {
|
||||
|
@ -19,6 +33,11 @@ export const getLocalSaveJson = () => {
|
|||
};
|
||||
|
||||
export const updateSave = (key, data, isFromRemote) => {
|
||||
if (queueSave && !isFromRemote) {
|
||||
pendingQueue.push({ key, data });
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.setItem(key, data);
|
||||
|
||||
if (!isFromRemote) {
|
||||
|
@ -34,3 +53,16 @@ export const readSave = (key) => {
|
|||
const data = localStorage.getItem(key);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const flushPendingQueue = () => {
|
||||
console.log('flushing save queue');
|
||||
console.log(pendingQueue);
|
||||
|
||||
for (const item of pendingQueue) {
|
||||
updateSave(item.key, item.data);
|
||||
}
|
||||
|
||||
pendingQueue = [];
|
||||
queueSave = false;
|
||||
unsubscribe();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue