|
30 | 30 | } |
31 | 31 | const projectUrl = writablePersistentStore('SelectProject.url', ''); |
32 | 32 |
|
33 | | - let files = null; |
| 33 | + export let projectData = null; |
| 34 | + const resetProjectAndCancelTask = () => { |
| 35 | + projectData = null; |
| 36 | + currentTask.abort(); |
| 37 | + }; |
| 38 | +
|
| 39 | + // Reset project when input changes |
| 40 | + $: $projectId, $type, resetProjectAndCancelTask(); |
| 41 | +
|
| 42 | + // just incase some non-number string was stored from older versions |
| 43 | + $projectId = extractProjectId($projectId); |
| 44 | +
|
| 45 | + const getDisplayedProjectURL = () => `https://scratch.mit.edu/projects/${$projectId}`; |
| 46 | +
|
| 47 | + const submitOnEnter = (e) => { |
| 48 | + if (e.key === 'Enter') { |
| 49 | + load(); |
| 50 | + } |
| 51 | + }; |
| 52 | + const handleInput = (e) => { |
| 53 | + $projectId = extractProjectId(e.target.value); |
| 54 | + e.target.value = getDisplayedProjectURL(); |
| 55 | + }; |
| 56 | + const handleFocus = (e) => { |
| 57 | + e.target.select(); |
| 58 | + }; |
| 59 | +
|
34 | 60 | let fileInputElement; |
35 | 61 |
|
| 62 | + const copyFileList = (files) => { |
| 63 | + const transfer = new DataTransfer(); |
| 64 | + for (const file of files) { |
| 65 | + transfer.items.add(file); |
| 66 | + } |
| 67 | + return transfer.files; |
| 68 | + }; |
| 69 | +
|
36 | 70 | // This is used to remember files between reloads in some browsers (currently only Firefox) |
37 | 71 | // This element is defined in the HTML of template.ejs because some browsers won't |
38 | 72 | // autocomplete file inputs generated by JS. |
39 | 73 | const inputForRememberingProjectFile = document.querySelector('.input-for-remembering-project-file'); |
40 | 74 | if (inputForRememberingProjectFile) { |
41 | | - // We'll check for autocompleted files after mount so that fileInputElement is defined. |
| 75 | + // Check for autocompleted files after mount so that fileInputElement is defined. |
42 | 76 | onMount(() => { |
43 | 77 | const storedFiles = inputForRememberingProjectFile.files; |
44 | 78 | if (storedFiles.length) { |
45 | | - setFiles(inputForRememberingProjectFile.files, false); |
| 79 | + fileInputElement.files = copyFileList(storedFiles); |
46 | 80 | } |
47 | 81 | }); |
48 | 82 | } |
49 | 83 |
|
50 | | - export let projectData = null; |
51 | | - const reset = () => { |
52 | | - projectData = null; |
| 84 | + const setFiles = (files) => { |
| 85 | + resetProjectAndCancelTask(); |
| 86 | + if (fileInputElement.files !== files) { |
| 87 | + fileInputElement.files = files; |
| 88 | + } |
| 89 | + if (inputForRememberingProjectFile) { |
| 90 | + inputForRememberingProjectFile.files = copyFileList(files); |
| 91 | + } |
| 92 | + if (files.length && $type === 'file') { |
| 93 | + load(); |
| 94 | + } |
| 95 | + }; |
| 96 | + const handleDrop = ({detail: dataTransfer}) => { |
| 97 | + const name = dataTransfer.files[0].name; |
| 98 | + if (name.endsWith('.sb') || name.endsWith('.sb2') || name.endsWith('.sb3')) { |
| 99 | + $type = 'file'; |
| 100 | + setFiles(dataTransfer.files); |
| 101 | + } |
| 102 | + }; |
| 103 | + const handleFileInputChange = (e) => { |
| 104 | + setFiles(e.target.files); |
53 | 105 | }; |
54 | | -
|
55 | | - // Reset project whenever an input changes |
56 | | - $: files, $projectId, $type, reset(), currentTask.abort(); |
57 | 106 |
|
58 | 107 | const internalLoad = async (task) => { |
59 | 108 | let uniqueId = ''; |
|
91 | 140 | loadProjectPromise |
92 | 141 | ]); |
93 | 142 | } else if ($type === 'file') { |
94 | | - if (!files) { |
| 143 | + const files = fileInputElement.files; |
| 144 | + const file = files && files[0]; |
| 145 | + if (!file) { |
95 | 146 | throw new UserError($_('select.noFileSelected')); |
96 | 147 | } |
97 | | - const file = files[0]; |
98 | 148 | uniqueId = `@${file.name}`; |
99 | 149 | projectTitle = file.name; |
100 | 150 | task.setProgressText($_('progress.compressingProject')); |
|
119 | 169 | project, |
120 | 170 | }; |
121 | 171 | }; |
122 | | -
|
123 | 172 | const load = async () => { |
124 | | - reset(); |
| 173 | + resetProjectAndCancelTask(); |
125 | 174 | const task = new Task(); |
126 | 175 | projectData = await task.do(internalLoad(task)); |
127 | 176 | task.done(); |
128 | 177 | }; |
129 | | -
|
130 | | - // just incase some non-number string was stored from older versions |
131 | | - $projectId = extractProjectId($projectId); |
132 | | -
|
133 | | - const getDisplayedProjectURL = () => `https://scratch.mit.edu/projects/${$projectId}`; |
134 | | -
|
135 | | - const submitOnEnter = (e) => { |
136 | | - if (e.key === 'Enter') { |
137 | | - e.target.blur(); |
138 | | - load(); |
139 | | - } |
140 | | - }; |
141 | | - const handleInput = (e) => { |
142 | | - $projectId = extractProjectId(e.target.value); |
143 | | - e.target.value = getDisplayedProjectURL(); |
144 | | - }; |
145 | | - const handleFocus = (e) => { |
146 | | - e.target.select(); |
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 | | - }; |
162 | | - const handleDrop = ({detail: dataTransfer}) => { |
163 | | - const name = dataTransfer.files[0].name; |
164 | | - if (name.endsWith('.sb') || name.endsWith('.sb2') || name.endsWith('.sb3')) { |
165 | | - $type = 'file'; |
166 | | - setFiles(dataTransfer.files, true); |
167 | | - } |
168 | | - }; |
169 | | - const handleFileInputChange = (e) => { |
170 | | - setFiles(e.target.files, true); |
171 | | - }; |
172 | 178 | </script> |
173 | 179 |
|
174 | 180 | <style> |
|
0 commit comments