72 lines
2.4 KiB
JavaScript
72 lines
2.4 KiB
JavaScript
// "Save & settings" dialog: export (file or text), import (file or pasted text), reset.
|
|
|
|
import { downloadText, ImportError, readFileText } from '../services/saveio.js';
|
|
import { t } from '../services/i18n.js';
|
|
import { $ } from './dom.js';
|
|
import { showToast } from './toast.js';
|
|
|
|
/**
|
|
* @param hooks.getExport () => { text, name } current save as text + file base name
|
|
* @param hooks.importText (text) => void throws ImportError on bad input
|
|
* @param hooks.reset () => void
|
|
*/
|
|
export function createSettings(hooks) {
|
|
const dialog = $('#settings');
|
|
const exportBox = $('#export-text');
|
|
const importBox = $('#import-text');
|
|
const fileInput = $('#import-file');
|
|
|
|
function open() {
|
|
exportBox.value = hooks.getExport().text;
|
|
importBox.value = '';
|
|
if (typeof dialog.showModal === 'function') dialog.showModal();
|
|
else dialog.setAttribute('open', '');
|
|
}
|
|
|
|
function download(extension, mime) {
|
|
const { text, name } = hooks.getExport();
|
|
downloadText(`${name}.${extension}`, text, mime);
|
|
}
|
|
|
|
async function copy() {
|
|
exportBox.value = hooks.getExport().text;
|
|
try {
|
|
await navigator.clipboard.writeText(exportBox.value);
|
|
} catch {
|
|
exportBox.select();
|
|
if (!document.execCommand?.('copy')) return showToast(t('toast.copyFailed'), { error: true });
|
|
}
|
|
showToast(t('toast.copied'));
|
|
}
|
|
|
|
async function runImport(text) {
|
|
try {
|
|
await hooks.importText(text);
|
|
dialog.close?.();
|
|
showToast(t('toast.imported'));
|
|
} catch (error) {
|
|
const code = error instanceof ImportError ? error.code : 'invalid';
|
|
showToast(t(`error.import.${code}`), { error: true });
|
|
}
|
|
}
|
|
|
|
$('#open-settings').addEventListener('click', open);
|
|
$('#export-json').addEventListener('click', () => download('json', 'application/json'));
|
|
$('#export-txt').addEventListener('click', () => download('txt', 'text/plain'));
|
|
$('#export-copy').addEventListener('click', copy);
|
|
$('#import-paste').addEventListener('click', () => runImport(importBox.value));
|
|
fileInput.addEventListener('change', async () => {
|
|
const file = fileInput.files?.[0];
|
|
fileInput.value = ''; // allow picking the same file again
|
|
if (file) await runImport(await readFileText(file));
|
|
});
|
|
$('#reset-game').addEventListener('click', () => {
|
|
if (!confirm(t('settings.resetConfirm'))) return;
|
|
hooks.reset();
|
|
dialog.close?.();
|
|
showToast(t('toast.reset'));
|
|
});
|
|
|
|
return { open };
|
|
}
|