Skip to content

Commit 5a547d5

Browse files
committed
Refactor and improve project selector
1 parent 0317d51 commit 5a547d5

File tree

1 file changed

+62
-56
lines changed

1 file changed

+62
-56
lines changed

src/p4/SelectProject.svelte

Lines changed: 62 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,79 @@
3030
}
3131
const projectUrl = writablePersistentStore('SelectProject.url', '');
3232
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+
3460
let fileInputElement;
3561
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+
3670
// This is used to remember files between reloads in some browsers (currently only Firefox)
3771
// This element is defined in the HTML of template.ejs because some browsers won't
3872
// autocomplete file inputs generated by JS.
3973
const inputForRememberingProjectFile = document.querySelector('.input-for-remembering-project-file');
4074
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.
4276
onMount(() => {
4377
const storedFiles = inputForRememberingProjectFile.files;
4478
if (storedFiles.length) {
45-
setFiles(inputForRememberingProjectFile.files, false);
79+
fileInputElement.files = copyFileList(storedFiles);
4680
}
4781
});
4882
}
4983
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);
53105
};
54-
55-
// Reset project whenever an input changes
56-
$: files, $projectId, $type, reset(), currentTask.abort();
57106
58107
const internalLoad = async (task) => {
59108
let uniqueId = '';
@@ -91,10 +140,11 @@
91140
loadProjectPromise
92141
]);
93142
} else if ($type === 'file') {
94-
if (!files) {
143+
const files = fileInputElement.files;
144+
const file = files && files[0];
145+
if (!file) {
95146
throw new UserError($_('select.noFileSelected'));
96147
}
97-
const file = files[0];
98148
uniqueId = `@${file.name}`;
99149
projectTitle = file.name;
100150
task.setProgressText($_('progress.compressingProject'));
@@ -119,56 +169,12 @@
119169
project,
120170
};
121171
};
122-
123172
const load = async () => {
124-
reset();
173+
resetProjectAndCancelTask();
125174
const task = new Task();
126175
projectData = await task.do(internalLoad(task));
127176
task.done();
128177
};
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-
};
172178
</script>
173179

174180
<style>

0 commit comments

Comments
 (0)