[feat] local backup functionality
This commit is contained in:
@@ -20,8 +20,9 @@
|
|||||||
"@mlc-ai/web-tokenizers": "^0.1.2",
|
"@mlc-ai/web-tokenizers": "^0.1.2",
|
||||||
"@smithy/protocol-http": "^3.0.10",
|
"@smithy/protocol-http": "^3.0.10",
|
||||||
"@smithy/signature-v4": "^2.0.16",
|
"@smithy/signature-v4": "^2.0.16",
|
||||||
"@tauri-apps/api": "1.4.0",
|
"@tauri-apps/api": "1.5.1",
|
||||||
"@types/marked": "^5.0.2",
|
"@types/marked": "^5.0.2",
|
||||||
|
"@types/streamsaver": "^2.0.4",
|
||||||
"@xenova/transformers": "^2.9.0",
|
"@xenova/transformers": "^2.9.0",
|
||||||
"blueimp-md5": "^2.19.0",
|
"blueimp-md5": "^2.19.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
"rollup": "^3.29.4",
|
"rollup": "^3.29.4",
|
||||||
"showdown": "^2.1.0",
|
"showdown": "^2.1.0",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
|
"streamsaver": "^2.0.6",
|
||||||
"three": "^0.154.0",
|
"three": "^0.154.0",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
@@ -64,7 +66,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.5.3",
|
"@sveltejs/vite-plugin-svelte": "^2.5.3",
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"@tauri-apps/cli": "1.4.0",
|
"@tauri-apps/cli": "1.5.7",
|
||||||
"@tsconfig/svelte": "^3.0.0",
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
"@types/blueimp-md5": "^2.18.2",
|
"@types/blueimp-md5": "^2.18.2",
|
||||||
"@types/dompurify": "^3.0.5",
|
"@types/dompurify": "^3.0.5",
|
||||||
|
|||||||
90
pnpm-lock.yaml
generated
90
pnpm-lock.yaml
generated
@@ -24,11 +24,14 @@ dependencies:
|
|||||||
specifier: ^2.0.16
|
specifier: ^2.0.16
|
||||||
version: 2.0.16
|
version: 2.0.16
|
||||||
'@tauri-apps/api':
|
'@tauri-apps/api':
|
||||||
specifier: 1.4.0
|
specifier: 1.5.1
|
||||||
version: 1.4.0
|
version: 1.5.1
|
||||||
'@types/marked':
|
'@types/marked':
|
||||||
specifier: ^5.0.2
|
specifier: ^5.0.2
|
||||||
version: 5.0.2
|
version: 5.0.2
|
||||||
|
'@types/streamsaver':
|
||||||
|
specifier: ^2.0.4
|
||||||
|
version: 2.0.4
|
||||||
'@xenova/transformers':
|
'@xenova/transformers':
|
||||||
specifier: ^2.9.0
|
specifier: ^2.9.0
|
||||||
version: 2.9.0
|
version: 2.9.0
|
||||||
@@ -125,6 +128,9 @@ dependencies:
|
|||||||
sortablejs:
|
sortablejs:
|
||||||
specifier: ^1.15.0
|
specifier: ^1.15.0
|
||||||
version: 1.15.0
|
version: 1.15.0
|
||||||
|
streamsaver:
|
||||||
|
specifier: ^2.0.6
|
||||||
|
version: 2.0.6
|
||||||
three:
|
three:
|
||||||
specifier: ^0.154.0
|
specifier: ^0.154.0
|
||||||
version: 0.154.0
|
version: 0.154.0
|
||||||
@@ -152,8 +158,8 @@ devDependencies:
|
|||||||
specifier: ^0.5.10
|
specifier: ^0.5.10
|
||||||
version: 0.5.10(tailwindcss@3.3.5)
|
version: 0.5.10(tailwindcss@3.3.5)
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
specifier: 1.4.0
|
specifier: 1.5.7
|
||||||
version: 1.4.0
|
version: 1.5.7
|
||||||
'@tsconfig/svelte':
|
'@tsconfig/svelte':
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
@@ -954,13 +960,13 @@ packages:
|
|||||||
tailwindcss: 3.3.5
|
tailwindcss: 3.3.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@tauri-apps/api@1.4.0:
|
/@tauri-apps/api@1.5.1:
|
||||||
resolution: {integrity: sha512-Jd6HPoTM1PZSFIzq7FB8VmMu3qSSyo/3lSwLpoapW+lQ41CL5Dow2KryLg+gyazA/58DRWI9vu/XpEeHK4uMdw==}
|
resolution: {integrity: sha512-6unsZDOdlXTmauU3NhWhn+Cx0rODV+rvNvTdvolE5Kls5ybA6cqndQENDt1+FS0tF7ozCP66jwWoH6a5h90BrA==}
|
||||||
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tauri-apps/cli-darwin-arm64@1.4.0:
|
/@tauri-apps/cli-darwin-arm64@1.5.7:
|
||||||
resolution: {integrity: sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==}
|
resolution: {integrity: sha512-eUpOUhs2IOpKaLa6RyGupP2owDLfd0q2FR/AILzryjtBtKJJRDQQvuotf+LcbEce2Nc2AHeYJIqYAsB4sw9K+g==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
@@ -968,8 +974,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-darwin-x64@1.4.0:
|
/@tauri-apps/cli-darwin-x64@1.5.7:
|
||||||
resolution: {integrity: sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==}
|
resolution: {integrity: sha512-zfumTv1xUuR+RB1pzhRy+51tB6cm8I76g0xUBaXOfEdOJ9FqW5GW2jdnEUbpNuU65qJ1lB8LVWHKGrSWWKazew==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
@@ -977,8 +983,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-arm-gnueabihf@1.4.0:
|
/@tauri-apps/cli-linux-arm-gnueabihf@1.5.7:
|
||||||
resolution: {integrity: sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==}
|
resolution: {integrity: sha512-JngWNqS06bMND9PhiPWp0e+yknJJuSozsSbo+iMzHoJNRauBZCUx+HnUcygUR66Cy6qM4eJvLXtsRG7ApxvWmg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -986,8 +992,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-arm64-gnu@1.4.0:
|
/@tauri-apps/cli-linux-arm64-gnu@1.5.7:
|
||||||
resolution: {integrity: sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==}
|
resolution: {integrity: sha512-WyIYP9BskgBGq+kf4cLAyru8ArrxGH2eMYGBJvuNEuSaqBhbV0i1uUxvyWdazllZLAEz1WvSocUmSwLknr1+sQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -995,8 +1001,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-arm64-musl@1.4.0:
|
/@tauri-apps/cli-linux-arm64-musl@1.5.7:
|
||||||
resolution: {integrity: sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==}
|
resolution: {integrity: sha512-OrDpihQP2MB0JY1a/wP9wsl9dDjFDpVEZOQxt4hU+UVGRCZQok7ghPBg4+Xpd1CkNkcCCuIeY8VxRvwLXpnIzg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1004,8 +1010,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-x64-gnu@1.4.0:
|
/@tauri-apps/cli-linux-x64-gnu@1.5.7:
|
||||||
resolution: {integrity: sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==}
|
resolution: {integrity: sha512-4T7FAYVk76rZi8VkuLpiKUAqaSxlva86C1fHm/RtmoTKwZEV+MI3vIMoVg+AwhyWIy9PS55C75nF7+OwbnFnvQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1013,8 +1019,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-x64-musl@1.4.0:
|
/@tauri-apps/cli-linux-x64-musl@1.5.7:
|
||||||
resolution: {integrity: sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==}
|
resolution: {integrity: sha512-LL9aMK601BmQjAUDcKWtt5KvAM0xXi0iJpOjoUD3LPfr5dLvBMTflVHQDAEtuZexLQyqpU09+60781PrI/FCTw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@@ -1022,8 +1028,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-win32-arm64-msvc@1.4.0:
|
/@tauri-apps/cli-win32-arm64-msvc@1.5.7:
|
||||||
resolution: {integrity: sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==}
|
resolution: {integrity: sha512-TmAdM6GVkfir3AUFsDV2gyc25kIbJeAnwT72OnmJGAECHs/t/GLP9IkFLLVcFKsiosRf8BXhVyQ84NYkSWo14w==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -1031,8 +1037,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-win32-ia32-msvc@1.4.0:
|
/@tauri-apps/cli-win32-ia32-msvc@1.5.7:
|
||||||
resolution: {integrity: sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==}
|
resolution: {integrity: sha512-bqWfxwCfLmrfZy69sEU19KHm5TFEaMb8KIekd4aRq/kyOlrjKLdZxN1PyNRP8zpJA1lTiRHzfUDfhpmnZH/skg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -1040,8 +1046,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-win32-x64-msvc@1.4.0:
|
/@tauri-apps/cli-win32-x64-msvc@1.5.7:
|
||||||
resolution: {integrity: sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==}
|
resolution: {integrity: sha512-OxLHVBNdzyQ//xT3kwjQFnJTn/N5zta/9fofAkXfnL7vqmVn6s/RY1LDa3sxCHlRaKw0n3ShpygRbM9M8+sO9w==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -1049,21 +1055,21 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli@1.4.0:
|
/@tauri-apps/cli@1.5.7:
|
||||||
resolution: {integrity: sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==}
|
resolution: {integrity: sha512-z7nXLpDAYfQqR5pYhQlWOr88DgPq1AfQyxHhGiakiVgWlaG0ikEfQxop2txrd52H0TRADG0JHR9vFrVFPv4hVQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@tauri-apps/cli-darwin-arm64': 1.4.0
|
'@tauri-apps/cli-darwin-arm64': 1.5.7
|
||||||
'@tauri-apps/cli-darwin-x64': 1.4.0
|
'@tauri-apps/cli-darwin-x64': 1.5.7
|
||||||
'@tauri-apps/cli-linux-arm-gnueabihf': 1.4.0
|
'@tauri-apps/cli-linux-arm-gnueabihf': 1.5.7
|
||||||
'@tauri-apps/cli-linux-arm64-gnu': 1.4.0
|
'@tauri-apps/cli-linux-arm64-gnu': 1.5.7
|
||||||
'@tauri-apps/cli-linux-arm64-musl': 1.4.0
|
'@tauri-apps/cli-linux-arm64-musl': 1.5.7
|
||||||
'@tauri-apps/cli-linux-x64-gnu': 1.4.0
|
'@tauri-apps/cli-linux-x64-gnu': 1.5.7
|
||||||
'@tauri-apps/cli-linux-x64-musl': 1.4.0
|
'@tauri-apps/cli-linux-x64-musl': 1.5.7
|
||||||
'@tauri-apps/cli-win32-arm64-msvc': 1.4.0
|
'@tauri-apps/cli-win32-arm64-msvc': 1.5.7
|
||||||
'@tauri-apps/cli-win32-ia32-msvc': 1.4.0
|
'@tauri-apps/cli-win32-ia32-msvc': 1.5.7
|
||||||
'@tauri-apps/cli-win32-x64-msvc': 1.4.0
|
'@tauri-apps/cli-win32-x64-msvc': 1.5.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@tootallnate/once@2.0.0:
|
/@tootallnate/once@2.0.0:
|
||||||
@@ -1156,6 +1162,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==}
|
resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/streamsaver@2.0.4:
|
||||||
|
resolution: {integrity: sha512-XxpGYIaBP+2NgZ5+4YeG7hI3wYAyOX8QB92xlPpNvStIAvlniml1th+D0bes1lUZz52IWkPlXMf88wy8NzFkbA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/three@0.154.0:
|
/@types/three@0.154.0:
|
||||||
resolution: {integrity: sha512-IioqpGhch6FdLDh4zazRn3rXHj6Vn2nVOziJdXVbJFi9CaI65LtP9qqUtpzbsHK2Ezlox8NtsLNHSw3AQzucjA==}
|
resolution: {integrity: sha512-IioqpGhch6FdLDh4zazRn3rXHj6Vn2nVOziJdXVbJFi9CaI65LtP9qqUtpzbsHK2Ezlox8NtsLNHSw3AQzucjA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3362,6 +3372,10 @@ packages:
|
|||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/streamsaver@2.0.6:
|
||||||
|
resolution: {integrity: sha512-LK4e7TfCV8HzuM0PKXuVUfKyCB1FtT9L0EGxsFk5Up8njj0bXK8pJM9+Wq2Nya7/jslmCQwRK39LFm55h7NBTw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/streamx@2.15.5:
|
/streamx@2.15.5:
|
||||||
resolution: {integrity: sha512-9thPGMkKC2GctCzyCUjME3yR03x2xNo0GPKGkRw2UMYN+gqWa9uqpyNWhmsNCutU5zHmkUum0LsCRQTXUgUCAg==}
|
resolution: {integrity: sha512-9thPGMkKC2GctCzyCUjME3yR03x2xNo0GPKGkRw2UMYN+gqWa9uqpyNWhmsNCutU5zHmkUum0LsCRQTXUgUCAg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
import { forageStorage, isNodeServer, isTauri } from "src/ts/storage/globalApi";
|
import { forageStorage, isNodeServer, isTauri } from "src/ts/storage/globalApi";
|
||||||
import { unMigrationAccount } from "src/ts/storage/accountStorage";
|
import { unMigrationAccount } from "src/ts/storage/accountStorage";
|
||||||
import { checkDriver } from "src/ts/drive/drive";
|
import { checkDriver } from "src/ts/drive/drive";
|
||||||
|
import { LoadLocalBackup, SaveLocalBackup } from "src/ts/drive/backuplocal";
|
||||||
let openIframe = false
|
let openIframe = false
|
||||||
let openIframeURL = ''
|
let openIframeURL = ''
|
||||||
let popup:Window = null
|
let popup:Window = null
|
||||||
@@ -36,6 +37,25 @@
|
|||||||
}}></svelte:window>
|
}}></svelte:window>
|
||||||
|
|
||||||
<h2 class="mb-2 text-2xl font-bold mt-2">{language.account} & {language.files}</h2>
|
<h2 class="mb-2 text-2xl font-bold mt-2">{language.account} & {language.files}</h2>
|
||||||
|
<button
|
||||||
|
on:click={async () => {
|
||||||
|
if(await alertConfirm(language.backupConfirm)){
|
||||||
|
SaveLocalBackup()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
class="drop-shadow-lg p-3 border-borderc border-solid mt-2 flex justify-center items-center ml-2 mr-2 border-1 hover:bg-selected text-sm">
|
||||||
|
{language.savebackup} (Local)
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
on:click={async () => {
|
||||||
|
if((await alertConfirm(language.backupLoadConfirm)) && (await alertConfirm(language.backupLoadConfirm2))){
|
||||||
|
LoadLocalBackup()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
class="drop-shadow-lg p-3 border-borderc border-solid mt-2 flex justify-center items-center ml-2 mr-2 border-1 hover:bg-selected text-sm mb-4">
|
||||||
|
{language.loadbackup} (Local)
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
|
|||||||
187
src/ts/drive/backuplocal.ts
Normal file
187
src/ts/drive/backuplocal.ts
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
import { BaseDirectory, readBinaryFile, readDir, writeBinaryFile } from "@tauri-apps/api/fs";
|
||||||
|
import { alertError, alertNormal, alertStore, alertWait } from "../alert";
|
||||||
|
import { forageStorage, isTauri } from "../storage/globalApi";
|
||||||
|
import { decodeRisuSave, encodeRisuSave } from "../storage/risuSave";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
import { DataBase } from "../storage/database";
|
||||||
|
import { save } from "@tauri-apps/api/dialog";
|
||||||
|
import { relaunch } from "@tauri-apps/api/process";
|
||||||
|
import { sleep } from "../util";
|
||||||
|
|
||||||
|
class TauriWriter{
|
||||||
|
path: string
|
||||||
|
firstWrite: boolean = true
|
||||||
|
constructor(path: string){
|
||||||
|
this.path = path
|
||||||
|
}
|
||||||
|
|
||||||
|
async write(data:Uint8Array) {
|
||||||
|
await writeBinaryFile(this.path, data, {
|
||||||
|
append: !this.firstWrite
|
||||||
|
})
|
||||||
|
this.firstWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
async close(){
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBasename(data:string){
|
||||||
|
const baseNameRegex = /\\/g
|
||||||
|
const splited = data.replace(baseNameRegex, '/').split('/')
|
||||||
|
const lasts = splited[splited.length-1]
|
||||||
|
return lasts
|
||||||
|
}
|
||||||
|
|
||||||
|
class LocalWriter{
|
||||||
|
writableStream: WritableStream
|
||||||
|
writer: WritableStreamDefaultWriter|TauriWriter
|
||||||
|
async init() {
|
||||||
|
if(isTauri){
|
||||||
|
const filePath = await save({
|
||||||
|
filters: [{
|
||||||
|
name: 'Binary',
|
||||||
|
extensions: ['bin']
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
if(!filePath){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.writer = new TauriWriter(filePath)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const streamSaver = await import('streamsaver')
|
||||||
|
this.writableStream = streamSaver.createWriteStream('risu-backup.bin')
|
||||||
|
this.writer = this.writableStream.getWriter()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
async write(name:string,data: Uint8Array){
|
||||||
|
const encodedName = new TextEncoder().encode(getBasename(name))
|
||||||
|
const nameLength = new Uint32Array([encodedName.byteLength])
|
||||||
|
await this.writer.write(new Uint8Array(nameLength.buffer))
|
||||||
|
await this.writer.write(encodedName)
|
||||||
|
const dataLength = new Uint32Array([data.byteLength])
|
||||||
|
await this.writer.write(new Uint8Array(dataLength.buffer))
|
||||||
|
await this.writer.write(data)
|
||||||
|
}
|
||||||
|
async close(){
|
||||||
|
await this.writer.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function SaveLocalBackup(){
|
||||||
|
alertWait("Saving local backup...")
|
||||||
|
const writer = new LocalWriter()
|
||||||
|
const r = await writer.init()
|
||||||
|
if(!r){
|
||||||
|
alertError('Failed')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isTauri){
|
||||||
|
const assets = await readDir('assets', {dir: BaseDirectory.AppData})
|
||||||
|
let i = 0;
|
||||||
|
for(let asset of assets){
|
||||||
|
i += 1;
|
||||||
|
alertWait(`Saving local Backup... (${i} / ${assets.length})`)
|
||||||
|
const key = asset.name
|
||||||
|
if(!key || !key.endsWith('.png')){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
await writer.write(key, await readBinaryFile(asset.path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
const keys = await forageStorage.keys()
|
||||||
|
|
||||||
|
for(let i=0;i<keys.length;i++){
|
||||||
|
alertWait(`Saving local Backup... (${i} / ${keys.length})`)
|
||||||
|
|
||||||
|
const key = keys[i]
|
||||||
|
if(!key || !key.endsWith('.png')){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
await writer.write(key, await forageStorage.getItem(key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbData = encodeRisuSave(get(DataBase), 'compression')
|
||||||
|
|
||||||
|
alertWait(`Saving local Backup... (Saving database)`)
|
||||||
|
|
||||||
|
await writer.write('database.risudat', dbData)
|
||||||
|
|
||||||
|
alertNormal('Success')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function LoadLocalBackup(){
|
||||||
|
//select file
|
||||||
|
try {
|
||||||
|
const input = document.createElement('input')
|
||||||
|
input.type = 'file'
|
||||||
|
input.accept = '.bin'
|
||||||
|
input.onchange = async () => {
|
||||||
|
if(!input.files || input.files.length === 0){
|
||||||
|
input.remove()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const file = input.files[0]
|
||||||
|
const reader = new FileReader()
|
||||||
|
input.remove()
|
||||||
|
reader.onload = async () => {
|
||||||
|
const buffer = reader.result as ArrayBuffer
|
||||||
|
const bufferLength = buffer.byteLength
|
||||||
|
for(let i=0;i<bufferLength;){
|
||||||
|
const progress = (i / bufferLength * 100).toFixed(2)
|
||||||
|
alertWait(`Loading local Backup... (${progress}%)`)
|
||||||
|
|
||||||
|
const nameLength = new Uint32Array(buffer.slice(i, i+4))[0]
|
||||||
|
i += 4
|
||||||
|
const name = new TextDecoder().decode(new Uint8Array(buffer.slice(i, i+nameLength)))
|
||||||
|
i += nameLength
|
||||||
|
const dataLength = new Uint32Array(buffer.slice(i, i+4))[0]
|
||||||
|
i += 4
|
||||||
|
const data = new Uint8Array(buffer.slice(i, i+dataLength))
|
||||||
|
i += dataLength
|
||||||
|
if(name === 'database.risudat'){
|
||||||
|
const db = new Uint8Array(data)
|
||||||
|
const dbData = await decodeRisuSave(db)
|
||||||
|
DataBase.set(dbData)
|
||||||
|
if(isTauri){
|
||||||
|
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
||||||
|
relaunch()
|
||||||
|
alertStore.set({
|
||||||
|
type: "wait",
|
||||||
|
msg: "Success, Refreshing your app."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
await forageStorage.setItem('database/database.bin', dbData)
|
||||||
|
location.search = ''
|
||||||
|
alertStore.set({
|
||||||
|
type: "wait",
|
||||||
|
msg: "Success, Refreshing your app."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if(isTauri){
|
||||||
|
await writeBinaryFile(`assets/` + name, data ,{dir: BaseDirectory.AppData})
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
await forageStorage.setItem('assets/' + name, data)
|
||||||
|
}
|
||||||
|
await sleep(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.readAsArrayBuffer(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
input.click()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
alertError('Failed, Is file corrupted?')
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user