diff --git a/tgui/global.d.ts b/tgui/global.d.ts index 172bbc8aca7..1f2880a2d36 100644 --- a/tgui/global.d.ts +++ b/tgui/global.d.ts @@ -178,6 +178,11 @@ type ByondType = { * Maps icons to their ref */ iconRefMap: Record; + + /** + * Downloads a blob, platform-agnostic + */ + saveBlob(blob: Blob, filename: string, ext: string): void; }; /** diff --git a/tgui/packages/tgui-panel/chat/renderer.jsx b/tgui/packages/tgui-panel/chat/renderer.jsx index 51b5c355a3b..a80643b571f 100644 --- a/tgui/packages/tgui-panel/chat/renderer.jsx +++ b/tgui/packages/tgui-panel/chat/renderer.jsx @@ -624,13 +624,13 @@ class ChatRenderer { '\n' + '\n'; // Create and send a nice blob - const blob = new Blob([pageHtml]); + const blob = new Blob([pageHtml], { type: 'text/plain' }); const timestamp = new Date() .toISOString() .substring(0, 19) .replace(/[-:]/g, '') .replace('T', '-'); - window.navigator.msSaveBlob(blob, `ss13-chatlog-${timestamp}.html`); + Byond.saveBlob(blob, `ss13-chatlog-${timestamp}.html`, '.html'); } } diff --git a/tgui/public/tgui.html b/tgui/public/tgui.html index 15b90c70387..96841057e72 100644 --- a/tgui/public/tgui.html +++ b/tgui/public/tgui.html @@ -345,6 +345,37 @@ loadAsset({ url: url, sync: sync, type: 'css' }); }; + Byond.saveBlob = function (blob, filename, ext) { + if (window.navigator.msSaveBlob) { + window.navigator.msSaveBlob(blob, filename); + } else if (window.showSaveFilePicker) { + var accept = {}; + accept[blob.type] = [ext]; + + var opts = { + suggestedName: filename, + types: [ + { + description: 'SS13 file', + accept: accept, + }, + ], + }; + + window + .showSaveFilePicker(opts) + .then(function (file) { + return file.createWritable(); + }) + .then(function (file) { + return file.write(blob).then(function () { + return file.close(); + }); + }) + .catch(function () {}); + } + }; + // Icon cache Byond.iconRefMap = {}; })();