7 files changed
+108
-34
No files matched your search
@@ -49,3 +49,13 @@ export class HTTPError extends Error {
|
||||
this.name = 'HTTPError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error indicating a project cannot be accessed, perhaps because it's unshared, doesn't exist, or has an invalid ID.
|
||||
*/
|
||||
export class CannotAccessProjectError extends Error {
|
||||
constructor (message) {
|
||||
super(message);
|
||||
this.name = 'CannotAccessProjectError';
|
||||
}
|
||||
}
|
||||
+21
-6
@@ -33,6 +33,14 @@
|
||||
"string": "This version of the packager appears to be outdated. Please refresh and try again.",
|
||||
"context": "Error displayed when the packager detects that you are using an old version and that you must refresh to continue."
|
||||
},
|
||||
"cannotAccessProject": {
|
||||
"string": "Can't access project metadata. This probably means the project is unshared, never existed, or the ID is invalid.",
|
||||
"context": "Part of the error modal when loading an unshared project."
|
||||
},
|
||||
"cannotAccessProjectCaching": {
|
||||
"string": "If the project was shared recently, it may take up to an hour for this message to go away.",
|
||||
"context": "Part of the error modal when loading an unshared project."
|
||||
},
|
||||
"close": {
|
||||
"string": "Close"
|
||||
},
|
||||
@@ -84,6 +92,9 @@
|
||||
"compressingProject": {
|
||||
"string": "Compressing project"
|
||||
},
|
||||
"loadingProjectMetadata": {
|
||||
"string": "Downloading project metadata"
|
||||
},
|
||||
"loadingProjectData": {
|
||||
"string": "Downloading project data"
|
||||
},
|
||||
@@ -137,13 +148,17 @@
|
||||
"string": "No file selected",
|
||||
"context": "Error message"
|
||||
},
|
||||
"uncertainty": {
|
||||
"string": "May 8, 2022 - The future of packaging unshared projects is unknown due to upcoming changes to the Scratch API. {moreInformation}.",
|
||||
"context": "The Scratch Team is probably going to prevent third-party sites from accessing unshared projects. This describes the situation. The date is when this notice was added so that people can understand that this is a new notice."
|
||||
"unsharedProjects": {
|
||||
"string": "Unshared projects are no longer accessible using their project ID due to Scratch API changes. Instead, you can either share the project or save the project to your computer (File > Save to your computer) and load the file in the packager.",
|
||||
"context": "Warning message about unshared projects no longer being accessible."
|
||||
},
|
||||
"uncertaintyMore": {
|
||||
"string": "More information",
|
||||
"context": "Link to more information about the Scratch Team probably going to prevent third-party sites from accessing unshared projects."
|
||||
"unsharedProjectsTemporary": {
|
||||
"string": "Unshared projects will no longer accessible using their project ID in the near future due to upcoming Scratch API changes. Instead, you can either share the project or save the project to your computer (File > Save to your computer) and load the file in the packager.",
|
||||
"context": "Temporary warning message about unshared projects not being accessible in the FUTURE. Will be replaced with similar message after the changes are implemented."
|
||||
},
|
||||
"unsharedProjectsMore": {
|
||||
"string": "For more information, visit: {link}",
|
||||
"context": "Link to learn more about the state of unshared projects."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
|
||||
+23
-1
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import Section from './Section.svelte';
|
||||
import Button from './Button.svelte';
|
||||
import {OutdatedPackagerError, UnknownNetworkError, UserError} from '../common/errors';
|
||||
import {CannotAccessProjectError, OutdatedPackagerError, UnknownNetworkError, UserError} from '../common/errors';
|
||||
import {error} from './stores';
|
||||
import {FEEDBACK_PRIMARY} from '../packager/brand';
|
||||
import {_} from '../locales/';
|
||||
@@ -113,6 +113,28 @@
|
||||
<Button on:click={refresh} text={$_('p4.refresh')} />
|
||||
<Button secondary on:click={closeModal} text={$_('p4.close')} />
|
||||
</p>
|
||||
{:else if $error instanceof CannotAccessProjectError}
|
||||
<p>
|
||||
{$_('p4.cannotAccessProject')}
|
||||
</p>
|
||||
<p>
|
||||
<ComplexMessage
|
||||
message={$_('select.unsharedProjects')}
|
||||
values={{
|
||||
moreInformation: {
|
||||
text: $_('select.unsharedProjectsMore'),
|
||||
href: 'https://docs.turbowarp.org/unshared-projects',
|
||||
newTab: true
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
{$_('p4.cannotAccessProjectCaching')}
|
||||
</p>
|
||||
<p>
|
||||
<Button on:click={closeModal} text={$_('p4.close')} />
|
||||
</p>
|
||||
{:else}
|
||||
<p>{$_('p4.errorMessage').replace('{error}', $error)}</p>
|
||||
<p>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import writablePersistentStore from './persistent-store';
|
||||
import {progress, currentTask} from './stores';
|
||||
import {UserError} from '../common/errors';
|
||||
import getProjectTitle from './get-project-meta';
|
||||
import getProjectMetadata from './get-project-metadata';
|
||||
import loadProject from '../packager/load-project';
|
||||
import {extractProjectId, isValidURL, getTitleFromURL} from './url-utils';
|
||||
import Task from './task';
|
||||
@@ -133,13 +133,24 @@
|
||||
throw new UserError($_('select.invalidId'));
|
||||
}
|
||||
uniqueId = `#${id}`;
|
||||
|
||||
task.setProgressText($_('progress.loadingProjectMetadata'));
|
||||
let metadata;
|
||||
try {
|
||||
metadata = await getProjectMetadata(id);
|
||||
} catch (e) {
|
||||
// For now, we'll treat this as non-critical.
|
||||
// In the future, this will probably be a critical error.
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
const token = metadata ? metadata.token : null;
|
||||
projectTitle = metadata ? metadata.title : '';
|
||||
|
||||
task.setProgressText($_('progress.loadingProjectData'));
|
||||
const {promise: loadProjectPromise, terminate} = await loadProject.fromID(id, progressCallback);
|
||||
const {promise: loadProjectPromise, terminate} = await loadProject.fromID(id, token, progressCallback);
|
||||
task.whenAbort(terminate);
|
||||
[projectTitle, project] = await Promise.all([
|
||||
getProjectTitle(id),
|
||||
loadProjectPromise
|
||||
]);
|
||||
project = await loadProjectPromise;
|
||||
} else if ($type === 'file') {
|
||||
const files = fileInputElement.files;
|
||||
const file = files && files[0];
|
||||
@@ -231,12 +242,15 @@
|
||||
</div>
|
||||
|
||||
{#if $type === "id"}
|
||||
<p>
|
||||
{$_('select.unsharedProjectsTemporary')}
|
||||
</p>
|
||||
<p>
|
||||
<ComplexMessage
|
||||
message={$_('select.uncertainty')}
|
||||
message={$_('select.unsharedProjectsMore')}
|
||||
values={{
|
||||
moreInformation: {
|
||||
text: $_('select.uncertaintyMore'),
|
||||
link: {
|
||||
text: 'https://docs.turbowarp.org/unshared-projects',
|
||||
href: 'https://docs.turbowarp.org/unshared-projects',
|
||||
newTab: true
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import request from '../common/request';
|
||||
|
||||
const getProjectTitle = async (id) => {
|
||||
try {
|
||||
const meta = await request({
|
||||
url: `https://trampoline.turbowarp.org/proxy/projects/${id}`,
|
||||
timeout: 10000,
|
||||
type: 'json'
|
||||
});
|
||||
return meta.title;
|
||||
} catch (e) {
|
||||
// Happens commonly when loading unshared projects, not something to worry about
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
export default getProjectTitle;
|
||||
@@ -0,0 +1,26 @@
|
||||
import {CannotAccessProjectError} from '../common/errors';
|
||||
import request from '../common/request';
|
||||
|
||||
const getProjectMetadata = async (id) => {
|
||||
try {
|
||||
const meta = await request({
|
||||
url: [
|
||||
// Hopefully one of these URLs won't be blocked.
|
||||
`https://trampoline.turbowarp.org/proxy/projects/${id}`,
|
||||
`https://trampoline.turbowarp.xyz/proxy/projects/${id}`
|
||||
],
|
||||
type: 'json'
|
||||
});
|
||||
return {
|
||||
title: meta.title,
|
||||
token: meta.project_token
|
||||
};
|
||||
} catch (e) {
|
||||
if (e && e.status === 404) {
|
||||
throw new CannotAccessProjectError(`Cannot access project ${id}`);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
export default getProjectMetadata;
|
||||
@@ -39,7 +39,11 @@ const fromURL = async (url, progressCallback) => {
|
||||
return downloadProject(buffer, progressCallback);
|
||||
};
|
||||
|
||||
const fromID = (id, progressCallback) => fromURL(`https://projects.scratch.mit.edu/${id}`, progressCallback);
|
||||
const fromID = (id, token, progressCallback) => {
|
||||
const tokenPart = token ? `?token=${token}` : '';
|
||||
let url = `https://projects.scratch.mit.edu/${id}${tokenPart}`;
|
||||
return fromURL(url, progressCallback);
|
||||
};
|
||||
|
||||
const fromFile = async (file, progressCallback) => {
|
||||
const buffer = await readAsArrayBuffer(file);
|
||||
|
||||
Reference in new issue
Block a user