add platform method to offer saving a buffer handle
This commit is contained in:
parent
fd950feb94
commit
4477073d6d
6 changed files with 80 additions and 0 deletions
23
assets/download-sandbox.html
Normal file
23
assets/download-sandbox.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a id="link" href="#">Download!</a>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var link = document.getElementById("link");
|
||||||
|
function download(blob, filename) {
|
||||||
|
var url = URL.createObjectURL(blob);
|
||||||
|
link.href = url;
|
||||||
|
link.download = filename;
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
window.addEventListener("message", function(event) {
|
||||||
|
if (event.data.type === "download") {
|
||||||
|
download(event.data.blob, event.data.filename);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -23,6 +23,7 @@
|
||||||
import {Platform} from "./src/platform/web/Platform.js";
|
import {Platform} from "./src/platform/web/Platform.js";
|
||||||
main(new Platform(document.body, {
|
main(new Platform(document.body, {
|
||||||
worker: "src/worker.js",
|
worker: "src/worker.js",
|
||||||
|
downloadSandbox: "assets/download-sandbox.html",
|
||||||
olm: {
|
olm: {
|
||||||
wasm: "lib/olm/olm.wasm",
|
wasm: "lib/olm/olm.wasm",
|
||||||
legacyBundle: "lib/olm/olm_legacy.js",
|
legacyBundle: "lib/olm/olm_legacy.js",
|
||||||
|
|
|
@ -78,6 +78,10 @@ async function build({modernOnly}) {
|
||||||
]));
|
]));
|
||||||
await assets.write(`worker.js`, await buildJsLegacy("src/platform/web/worker/main.js", ['src/platform/web/worker/polyfill.js']));
|
await assets.write(`worker.js`, await buildJsLegacy("src/platform/web/worker/main.js", ['src/platform/web/worker/polyfill.js']));
|
||||||
}
|
}
|
||||||
|
// copy over non-theme assets
|
||||||
|
const downloadSandbox = "download-sandbox.html";
|
||||||
|
let downloadSandboxHtml = await fs.readFile(path.join(projectDir, `assets/${downloadSandbox}`));
|
||||||
|
await assets.write(downloadSandbox, downloadSandboxHtml);
|
||||||
// creates the directories where the theme css bundles are placed in,
|
// creates the directories where the theme css bundles are placed in,
|
||||||
// and writes to assets, so the build bundles can translate them, so do it first
|
// and writes to assets, so the build bundles can translate them, so do it first
|
||||||
await copyThemeAssets(themes, assets);
|
await copyThemeAssets(themes, assets);
|
||||||
|
@ -143,6 +147,7 @@ async function buildHtml(doc, version, globalHash, modernOnly, assets) {
|
||||||
});
|
});
|
||||||
const pathsJSON = JSON.stringify({
|
const pathsJSON = JSON.stringify({
|
||||||
worker: assets.has("worker.js") ? assets.resolve(`worker.js`) : null,
|
worker: assets.has("worker.js") ? assets.resolve(`worker.js`) : null,
|
||||||
|
downloadSandbox: assets.resolve("download-sandbox.html"),
|
||||||
serviceWorker: "sw.js",
|
serviceWorker: "sw.js",
|
||||||
olm: {
|
olm: {
|
||||||
wasm: assets.resolve("olm.wasm"),
|
wasm: assets.resolve("olm.wasm"),
|
||||||
|
@ -234,6 +239,7 @@ function isPreCached(asset) {
|
||||||
asset.endsWith(".png") ||
|
asset.endsWith(".png") ||
|
||||||
asset.endsWith(".css") ||
|
asset.endsWith(".css") ||
|
||||||
asset.endsWith(".wasm") ||
|
asset.endsWith(".wasm") ||
|
||||||
|
asset.endsWith(".html") ||
|
||||||
// most environments don't need the worker
|
// most environments don't need the worker
|
||||||
asset.endsWith(".js") && !NON_PRECACHED_JS.includes(asset);
|
asset.endsWith(".js") && !NON_PRECACHED_JS.includes(asset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {Crypto} from "./dom/Crypto.js";
|
||||||
import {estimateStorageUsage} from "./dom/StorageEstimate.js";
|
import {estimateStorageUsage} from "./dom/StorageEstimate.js";
|
||||||
import {WorkerPool} from "./dom/WorkerPool.js";
|
import {WorkerPool} from "./dom/WorkerPool.js";
|
||||||
import {BufferHandle} from "./dom/BufferHandle.js";
|
import {BufferHandle} from "./dom/BufferHandle.js";
|
||||||
|
import {downloadInIframe} from "./dom/download.js";
|
||||||
|
|
||||||
function addScript(src) {
|
function addScript(src) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
@ -133,4 +134,12 @@ export class Platform {
|
||||||
createBufferHandle(buffer, mimetype) {
|
createBufferHandle(buffer, mimetype) {
|
||||||
return new BufferHandle(buffer, mimetype);
|
return new BufferHandle(buffer, mimetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offerSaveBufferHandle(bufferHandle, filename) {
|
||||||
|
if (navigator.msSaveBlob) {
|
||||||
|
navigator.msSaveBlob(bufferHandle.blob, filename);
|
||||||
|
} else {
|
||||||
|
downloadInIframe(this._container, this._paths.downloadSandbox, bufferHandle.blob, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
37
src/platform/web/dom/download.js
Normal file
37
src/platform/web/dom/download.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function downloadInIframe(container, iframeSrc, blob, filename) {
|
||||||
|
let iframe = container.querySelector("iframe.downloadSandbox");
|
||||||
|
if (!iframe) {
|
||||||
|
iframe = document.createElement("iframe");
|
||||||
|
iframe.setAttribute("sandbox", "allow-scripts allow-downloads allow-downloads-without-user-activation");
|
||||||
|
iframe.setAttribute("src", iframeSrc);
|
||||||
|
iframe.className = "downloadSandbox";
|
||||||
|
container.appendChild(iframe);
|
||||||
|
let detach;
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
detach = () => {
|
||||||
|
iframe.removeEventListener("load", resolve);
|
||||||
|
iframe.removeEventListener("error", reject);
|
||||||
|
}
|
||||||
|
iframe.addEventListener("load", resolve);
|
||||||
|
iframe.addEventListener("error", reject);
|
||||||
|
});
|
||||||
|
detach();
|
||||||
|
}
|
||||||
|
iframe.contentWindow.postMessage({type: "download", blob: blob, filename: filename}, "*");
|
||||||
|
}
|
|
@ -49,3 +49,7 @@ body.hydrogen {
|
||||||
input::-ms-clear {
|
input::-ms-clear {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hydrogen > iframe.downloadSandbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
Reference in a new issue