web/TransferSettings: show a safety warning before importing

This commit is contained in:
wukko 2024-07-28 13:20:22 +06:00
parent 5bb5c6dc3c
commit 4210b17d89
No known key found for this signature in database
GPG key ID: 3E30B3F26C7B4AA2
2 changed files with 60 additions and 30 deletions

View file

@ -7,6 +7,7 @@
"button.download": "download", "button.download": "download",
"button.share": "share", "button.share": "share",
"button.copy": "copy", "button.copy": "copy",
"button.import": "import",
"reset.title": "reset all settings?", "reset.title": "reset all settings?",
"reset.body": "are you sure you want to reset all settings? this action is immediate and irreversible.", "reset.body": "are you sure you want to reset all settings? this action is immediate and irreversible.",
@ -16,5 +17,9 @@
"picker.description.phone": "press an item to save it. images can also be saved with a long press.", "picker.description.phone": "press an item to save it. images can also be saved with a long press.",
"picker.description.ios": "press an item to save it with a shortcut. images can also be saved with a long press.", "picker.description.ios": "press an item to save it with a shortcut. images can also be saved with a long press.",
"saving.title": "choose how to save" "saving.title": "choose how to save",
"safety.title": "important safety notice",
"import.body": "importing unknown or corrupted files may unexpectedly alter or break cobalt functionality. only import files that you've personally exported and haven't modified.\n\nwe are not responsible for any harm caused by importing unknown setting files."
} }

View file

@ -1,54 +1,79 @@
<script lang="ts"> <script lang="ts">
import { t } from "$lib/i18n/translations";
import { createDialog } from "$lib/dialogs";
import settings, { updateSetting, loadFromString, } from "$lib/state/settings";
import ActionButton from "$components/buttons/ActionButton.svelte"; import ActionButton from "$components/buttons/ActionButton.svelte";
import IconFileExport from "@tabler/icons-svelte/IconFileExport.svelte"; import IconFileExport from "@tabler/icons-svelte/IconFileExport.svelte";
import IconFileImport from "@tabler/icons-svelte/IconFileImport.svelte"; import IconFileImport from "@tabler/icons-svelte/IconFileImport.svelte";
import settings, { updateSetting, loadFromString } from "$lib/state/settings";
const updateSettings = (reader: FileReader) => {
try {
const data = reader.result?.toString();
if (!data) {
throw "data is missing";
}
// TODO: input is not validated at all here, which means
// someone can potentially import a broken config.
// i don't know if we should do something about it
// or just thug it out.
updateSetting(loadFromString(data));
} catch (e) {
alert(e);
}
};
const importSettings = () => { const importSettings = () => {
const pseudoinput = document.createElement('input'); const pseudoinput = document.createElement("input");
pseudoinput.type = 'file'; pseudoinput.type = "file";
pseudoinput.accept = '.json'; pseudoinput.accept = ".json";
pseudoinput.onchange = (e: Event) => { pseudoinput.onchange = (e: Event) => {
const target = e.target as HTMLInputElement; const target = e.target as HTMLInputElement;
const reader = new FileReader(); const reader = new FileReader();
reader.onload = function() { reader.onload = function () {
try { createDialog({
const data = reader.result?.toString(); id: "import-confirm",
if (!data) { type: "small",
throw "data is missing"; icon: "warn-red",
} title: $t("dialog.safety.title"),
bodyText: $t("dialog.import.body"),
// TODO: input is not validated at all here, which means buttons: [
// someone can potentially import a broken config. {
// i don't know if we should do something about it text: $t("dialog.button.cancel"),
// or just thug it out. main: false,
updateSetting( action: () => {},
loadFromString(data) },
); {
} catch(e) { text: $t("dialog.button.import"),
alert(e); color: "red",
} main: true,
} action: () => updateSettings(reader),
},
],
});
};
if (target.files?.length === 1) { if (target.files?.length === 1) {
reader.readAsText(target.files[0]); reader.readAsText(target.files[0]);
} else alert('file missing'); } else alert("file missing");
}; };
pseudoinput.click(); pseudoinput.click();
} };
const exportSettings = () => { const exportSettings = () => {
const blob = new Blob( const blob = new Blob(
[ JSON.stringify($settings, null, 2) ], [ JSON.stringify($settings, null, 2) ],
{ type: 'application/json' } { type: "application/json" }
); );
const pseudolink = document.createElement('a'); const pseudolink = document.createElement("a");
pseudolink.href = URL.createObjectURL(blob); pseudolink.href = URL.createObjectURL(blob);
pseudolink.download = 'settings.json'; pseudolink.download = "settings.json";
pseudolink.click(); pseudolink.click();
} };
</script> </script>
<div class="button-row" id="settings-data-transfer"> <div class="button-row" id="settings-data-transfer">
@ -65,4 +90,4 @@
display: flex; display: flex;
gap: var(--padding); gap: var(--padding);
} }
</style> </style>