|
1 | 1 | <script> |
2 | | - import {onMount} from 'svelte'; |
| 2 | + import {onMount, tick} from 'svelte'; |
3 | 3 | import {writable} from 'svelte/store'; |
4 | 4 | import {_} from '../locales'; |
5 | 5 | import Section from './Section.svelte'; |
|
33 | 33 | let files = null; |
34 | 34 | let fileInputElement; |
35 | 35 |
|
| 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 | +
|
36 | 50 | export let projectData = null; |
37 | 51 | const reset = () => { |
38 | 52 | projectData = null; |
|
131 | 145 | const handleFocus = (e) => { |
132 | 146 | e.target.select(); |
133 | 147 | }; |
| 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 | + }; |
134 | 162 | const handleDrop = ({detail: dataTransfer}) => { |
135 | 163 | const name = dataTransfer.files[0].name; |
136 | 164 | if (name.endsWith('.sb') || name.endsWith('.sb2') || name.endsWith('.sb3')) { |
137 | 165 | $type = 'file'; |
138 | | - files = dataTransfer.files; |
139 | | - fileInputElement.files = files; |
| 166 | + setFiles(dataTransfer.files, true); |
140 | 167 | } |
141 | 168 | }; |
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 | + }; |
147 | 172 | </script> |
148 | 173 |
|
149 | 174 | <style> |
|
184 | 209 | <input type="radio" name="project-type" bind:group={$type} value="file"> |
185 | 210 | {$_('select.file')} |
186 | 211 | </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"> |
188 | 213 | </div> |
189 | 214 | <div class="option"> |
190 | 215 | <label> |
|
0 commit comments