s4s-packager / static /example.html
soiz1's picture
Upload 225 files
7aec436 verified
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; connect-src * data: blob:">
<meta name="robots" content="noindex">
<title>Scaffolding Demo</title>
<style>
body {
background-color: black;
color: white;
font-family: sans-serif;
overflow: hidden;
}
[hidden] {
display: none !important;
}
h1 {
font-weight: normal;
}
a {
color: inherit;
text-decoration: underline;
cursor: pointer;
}
#app, #loading, #error, #launch {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.screen {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
cursor: default;
user-select: none;
-webkit-user-select: none;
background-color: black;
}
#launch {
background-color: rgba(0, 0, 0, 0.7);
cursor: pointer;
}
.green-flag {
width: 80px;
height: 80px;
padding: 16px;
border-radius: 100%;
background: rgba(255, 255, 255, 0.75);
border: 3px solid hsla(0, 100%, 100%, 1);
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.progress-bar-outer {
border: 1px solid currentColor;
height: 10px;
width: 200px;
max-width: 200px;
}
.progress-bar-inner {
height: 100%;
width: 0;
background-color: currentColor;
}
.control-button {
width: 2rem;
height: 2rem;
padding: 0.375rem;
border-radius: 0.25rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
user-select: none;
-webkit-user-select: none;
cursor: pointer;
border: 0;
border-radius: 4px;
}
.control-button:hover {
background: hsla(0, 100%, 65%, 0.15);
}
.control-button.active {
background: hsla(0, 100%, 65%, 0.35);
}
.fullscreen-button {
background: white !important;
}
#error-information {
font-family: monospace;
}
</style>
</head>
<body>
<noscript>Enable JavaScript</noscript>
<div id="app"></div>
<div id="launch" class="screen" hidden title="Click to start">
<div class="green-flag">
<svg viewBox="0 0 16.63 17.5" width="42" height="44">
<defs><style>.cls-1,.cls-2{fill:#4cbf56;stroke:#45993d;stroke-linecap:round;stroke-linejoin:round;}.cls-2{stroke-width:1.5px;}</style></defs>
<path class="cls-1" d="M.75,2A6.44,6.44,0,0,1,8.44,2h0a6.44,6.44,0,0,0,7.69,0V12.4a6.44,6.44,0,0,1-7.69,0h0a6.44,6.44,0,0,0-7.69,0"/>
<line class="cls-2" x1="0.75" y1="16.75" x2="0.75" y2="0.75"/>
</svg>
</div>
</div>
<div id="loading" class="screen">
<div class="progress-bar-outer"><div class="progress-bar-inner" id="loading-inner"></div></div>
</div>
<div id="error" class="screen" hidden>
<h1>Error</h1>
<p id="error-information"></p>
</div>
<!-- If using Scaffolding as a library, update this path to where your scaffolding-[full|min].js is located. -->
<!-- This could also be a jsdelivr URL. -->
<script src="scaffolding/scaffolding-full.js"></script>
<script>
const PROJECT_ID = location.hash.substr(1) || '1';
const appElement = document.getElementById('app');
const launchScreen = document.getElementById('launch');
const loadingScreen = document.getElementById('loading');
const loadingInner = document.getElementById('loading-inner');
const errorScreen = document.getElementById('error');
const errorInformation = document.getElementById('error-information');
const scaffolding = new Scaffolding.Scaffolding();
scaffolding.setup();
scaffolding.appendTo(appElement);
const {storage, vm} = scaffolding;
storage.addWebStore(
[storage.AssetType.Project],
(asset) => `https://projects.penguinmod.com/api/projects/getPublished?type=file&id=${asset.assetId}`
);
storage.addWebStore(
[storage.AssetType.ImageVector, storage.AssetType.ImageBitmap, storage.AssetType.Sound],
(asset) => `https://assets.scratch.mit.edu/internalapi/asset/${asset.assetId}.${asset.dataFormat}/get/`
);
const setProgress = (progress) => {
loadingInner.style.width = `${progress * 100}%`;
}
storage.onprogress = (total, loaded) => {
setProgress(0.2 + (loaded / total) * 0.8)
};
setProgress(0.1);
const greenFlagButton = document.createElement('img');
greenFlagButton.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16.63 17.5"><path d="M.75 2a6.44 6.44 0 017.69 0h0a6.44 6.44 0 007.69 0v10.4a6.44 6.44 0 01-7.69 0h0a6.44 6.44 0 00-7.69 0" fill="#007AF4" stroke="#003080" stroke-linecap="round" stroke-linejoin="round"/><path stroke-width="1.5" fill="#007AF4" stroke="#003080" stroke-linecap="round" stroke-linejoin="round" d="M.75 16.75v-16"/></svg>');
greenFlagButton.className = 'control-button';
greenFlagButton.addEventListener('click', () => {
scaffolding.greenFlag();
});
scaffolding.addEventListener('PROJECT_RUN_START', () => {
greenFlagButton.classList.add('active');
});
scaffolding.addEventListener('PROJECT_RUN_STOP', () => {
greenFlagButton.classList.remove('active');
});
scaffolding.addControlButton({
element: greenFlagButton,
where: 'top-left'
});
const stopAllButton = document.createElement('img');
stopAllButton.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path fill="#ec5959" stroke="#b84848" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M4.3.5h5.4l3.8 3.8v5.4l-3.8 3.8H4.3L.5 9.7V4.3z"/></svg>');
stopAllButton.className = 'control-button';
stopAllButton.addEventListener('click', () => {
scaffolding.stopAll();
});
scaffolding.addControlButton({
element: stopAllButton,
where: 'top-left'
});
if (document.fullscreenEnabled || document.webkitFullscreenEnabled) {
let isFullScreen = !!(document.fullscreenElement || document.webkitFullscreenElement);
const fullscreenButton = document.createElement('img');
fullscreenButton.className = 'control-button fullscreen-button';
fullscreenButton.addEventListener('click', () => {
if (isFullScreen) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
} else {
if (document.body.requestFullscreen) {
document.body.requestFullscreen()
} else if (document.body.webkitRequestFullscreen) {
document.body.webkitRequestFullscreen();
}
}
});
const updateFullScreen = () => {
isFullScreen = !!(document.fullscreenElement || document.webkitFullscreenElement);
if (isFullScreen) {
fullscreenButton.src = 'data:image/svg+xml,' + encodeURIComponent('<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg"><g fill="#575E75" fill-rule="evenodd"><path d="M12.662 3.65l.89.891 3.133-2.374a.815.815 0 011.15.165.819.819 0 010 .986L15.467 6.46l.867.871c.25.25.072.664-.269.664L12.388 8A.397.397 0 0112 7.611V3.92c0-.341.418-.514.662-.27M7.338 16.35l-.89-.89-3.133 2.374a.817.817 0 01-1.15-.166.819.819 0 010-.985l2.37-3.143-.87-.871a.387.387 0 01.27-.664L7.612 12a.397.397 0 01.388.389v3.692a.387.387 0 01-.662.27M7.338 3.65l-.89.891-3.133-2.374a.815.815 0 00-1.15.165.819.819 0 000 .986l2.37 3.142-.87.871a.387.387 0 00.27.664L7.612 8A.397.397 0 008 7.611V3.92a.387.387 0 00-.662-.27M12.662 16.35l.89-.89 3.133 2.374a.817.817 0 001.15-.166.819.819 0 000-.985l-2.368-3.143.867-.871a.387.387 0 00-.269-.664L12.388 12a.397.397 0 00-.388.389v3.692c0 .342.418.514.662.27"/></g></svg>');
} else {
fullscreenButton.src = 'data:image/svg+xml,' + encodeURIComponent('<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg"><g fill="#575E75" fill-rule="evenodd"><path d="M16.338 7.35l-.89-.891-3.133 2.374a.815.815 0 01-1.15-.165.819.819 0 010-.986l2.368-3.142-.867-.871a.387.387 0 01.269-.664L16.612 3a.397.397 0 01.388.389V7.08a.387.387 0 01-.662.27M3.662 12.65l.89.89 3.133-2.374a.817.817 0 011.15.166.819.819 0 010 .985l-2.37 3.143.87.871c.248.25.071.664-.27.664L3.388 17A.397.397 0 013 16.611V12.92c0-.342.418-.514.662-.27M3.662 7.35l.89-.891 3.133 2.374a.815.815 0 001.15-.165.819.819 0 000-.986L6.465 4.54l.87-.871a.387.387 0 00-.27-.664L3.388 3A.397.397 0 003 3.389V7.08c0 .341.418.514.662.27M16.338 12.65l-.89.89-3.133-2.374a.817.817 0 00-1.15.166.819.819 0 000 .985l2.368 3.143-.867.871a.387.387 0 00.269.664l3.677.005a.397.397 0 00.388-.389V12.92a.387.387 0 00-.662-.27"/></g></svg>');
}
};
updateFullScreen();
document.addEventListener('fullscreenchange', updateFullScreen);
document.addEventListener('webkitfullscreenchange', updateFullScreen);
scaffolding.addControlButton({
element: fullscreenButton,
where: 'top-right'
});
}
scaffolding.addCloudProvider(new Scaffolding.Cloud.WebSocketProvider('wss://clouddata.turbowarp.org', PROJECT_ID));
const getProjectData = async () => {
const metadataResponse = await fetch(`https://trampoline.turbowarp.org/api/projects/${PROJECT_ID}`);
if (!metadataResponse.ok) {
throw new Error('Failed to load project metadata. It is probably unshared.');
}
const projectMetadata = await metadataResponse.json();
const token = projectMetadata.project_token;
const dataResponse = await fetch(`https://projects.scratch.mit.edu/${PROJECT_ID}?token=${token}`);
if (!dataResponse.ok) {
throw new Error('Failed to load project data.');
}
return dataResponse.arrayBuffer();
};
const run = async () => {
const projectData = await getProjectData();
setProgress(0.1);
await scaffolding.loadProject(projectData);
scaffolding.setUsername('123');
setProgress(1);
loadingScreen.hidden = true;
launchScreen.hidden = false;
launchScreen.addEventListener('click', () => {
launchScreen.hidden = true;
scaffolding.start();
});
launchScreen.focus();
};
const handleError = (error) => {
console.error(error);
errorScreen.hidden = false;
errorInformation.textContent = `${error}`;
};
run().catch(handleError);
</script>
</body>
</html>