Skip to content

Commit 956a9d8

Browse files
committed
Persist project file between reloads in Firefox
1 parent 7b70cda commit 956a9d8

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

src/p4/SelectProject.svelte

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script>
2-
import {onMount} from 'svelte';
2+
import {onMount, tick} from 'svelte';
33
import {writable} from 'svelte/store';
44
import {_} from '../locales';
55
import Section from './Section.svelte';
@@ -33,6 +33,20 @@
3333
let files = null;
3434
let fileInputElement;
3535
36+
// This is used to remember files between reloads in some browsers (currently only Firefox)
37+
// This element is defined in the HTML of template.ejs because some browsers won't
38+
// autocomplete file inputs generated by JS.
39+
const inputForRememberingProjectFile = document.querySelector('.input-for-remembering-project-file');
40+
if (inputForRememberingProjectFile) {
41+
// We'll check for autocompleted files after mount so that fileInputElement is defined.
42+
onMount(() => {
43+
const storedFiles = inputForRememberingProjectFile.files;
44+
if (storedFiles.length) {
45+
setFiles(inputForRememberingProjectFile.files, false);
46+
}
47+
});
48+
}
49+
3650
export let projectData = null;
3751
const reset = () => {
3852
projectData = null;
@@ -131,19 +145,30 @@
131145
const handleFocus = (e) => {
132146
e.target.select();
133147
};
148+
const setFiles = (newFiles, canAutomaticallyLoadProject) => {
149+
files = newFiles;
150+
if (fileInputElement && fileInputElement.files !== files) {
151+
fileInputElement.files = files;
152+
}
153+
if (inputForRememberingProjectFile && inputForRememberingProjectFile.files !== files) {
154+
inputForRememberingProjectFile.files = files;
155+
}
156+
if (canAutomaticallyLoadProject && files.length) {
157+
// Setting files= above will trigger a tick that cancels the current task. We need to wait for that
158+
// tick to finish before starting a new task, otherwise it'll be cancelled immediately.
159+
tick().then(load);
160+
}
161+
};
134162
const handleDrop = ({detail: dataTransfer}) => {
135163
const name = dataTransfer.files[0].name;
136164
if (name.endsWith('.sb') || name.endsWith('.sb2') || name.endsWith('.sb3')) {
137165
$type = 'file';
138-
files = dataTransfer.files;
139-
fileInputElement.files = files;
166+
setFiles(dataTransfer.files, true);
140167
}
141168
};
142-
143-
// Automatically start loading when a file is selected
144-
$: if (files && files[0]) {
145-
load();
146-
}
169+
const handleFileInputChange = (e) => {
170+
setFiles(e.target.files, true);
171+
};
147172
</script>
148173

149174
<style>
@@ -184,7 +209,7 @@
184209
<input type="radio" name="project-type" bind:group={$type} value="file">
185210
{$_('select.file')}
186211
</label>
187-
<input hidden={$type !== "file"} bind:files={files} bind:this={fileInputElement} type="file" accept=".sb,.sb2,.sb3">
212+
<input hidden={$type !== "file"} on:change={handleFileInputChange} bind:this={fileInputElement} type="file" accept=".sb,.sb2,.sb3">
188213
</div>
189214
<div class="option">
190215
<label>

src/p4/template.ejs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@
2121
background-color: #111;
2222
color-scheme: dark;
2323
}
24+
.input-for-remembering-project-file {
25+
display: none;
26+
}
2427
</style>
2528
</head>
2629
<body>
2730
<noscript>This page requires JavaScript.</noscript>
31+
<!-- This element needs to exist in the HTML for some browsers to autocomplete it. -->
32+
<input type="file" class="input-for-remembering-project-file" autocomplete="on">
2833
<div id="app"></div>
2934
<script>
3035
(function() {

0 commit comments

Comments
 (0)