Saveing and opening files, quick links.

Signed-off-by: Rachel <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel
2024-03-18 22:12:01 -07:00
parent 13491aa7df
commit 812aa00881
3 changed files with 164 additions and 49 deletions

View File

@@ -48,6 +48,7 @@ code {
.navbar-default .navbar-brand {
color: #fff;
text-wrap: nowrap;
white-space: nowrap;
}
.navbar-brand a {
@@ -75,13 +76,13 @@ ol, ul {
.navbar-default .navbar-text {
color: #fff;
text-wrap: nowrap;
white-space: nowrap;
}
.navbar-text {
padding: 0;
position: relative;
}
.navbar-nav {
margin: 7.5px -15px;
display: block;
}
@media (min-width: 768px) {
@@ -127,3 +128,12 @@ ol, ul {
margin-bottom: 0;
display: inline-block;
}
.navbar-nav .dropdown-menu {
position: absolute;
}
.modal-title {
color: #fff;
}
.modal-body button {
color: #fff
}

View File

@@ -4,15 +4,21 @@
<head>
<meta charset="utf-8">
<title>Stationeers IC10 Emulator</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js"
integrity="sha512-ykZ1QQr0Jy/4ZkvKuqWn4iF3lqPZyij9iRv6sGqLRdTPkY69YX6+7wvVGmsdBbiIfN/8OdsI7HABjvEok6ZopQ=="
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.bundle.min.js"
integrity="sha512-7Pi/otdlbbCR+LnW+F7PwFcSDJOuUJB3OxtEHbg4vSMvzvJjde4Po1v4BR9Gdc9aXNUNFVUY+SK51wWT8WF0Gg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-reboot.min.css"
integrity="sha512-HJaQ4y3YcUGCWikWDn8bFeGTy3Z/3IbxFYQ9G3UAWx16PyTL6Nu5P/BDDV9s0WhK3Sq27Wtbk/6IcwGmGSMXYg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css"
integrity="sha512-jnSuA4Ss2PkkikSOLtYs8BlYIeeIK1h99ty4YfvRPAlzr377vr3CXDb7sb7eEEBYjDtcYj+AjBH3FLv5uSJuXg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-grid.min.css"
integrity="sha512-i1b/nzkVo97VN5WbEtaPebBG8REvjWeqNclJ6AItj7msdVcaveKrlIIByDpvjk5nwHjXkIqGZscVxOrTb9tsMA=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap-utilities.min.css"
integrity="sha512-4ocAKAxnrkSm7MvkkF1D435kko3/HWWvoi/U9+7+ln94B/U01Mggca05Pm3W59BIv3abl0U3MPdygAPLo5aeqg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/js/fontawesome.min.js"
integrity="sha512-C8qHv0HOaf4yoA7ISuuCTrsPX8qjolYTZyoFRKNA9dFKnxgzIHnYTOJhXQIt6zwpIFzCrRzUBuVgtC4e5K1nhA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
@@ -30,7 +36,7 @@
#editor {
position: relative;
width: 100%;
height: calc(100vh - 70px);
height: calc(100vh - 84px);
top: 0;
right: 0;
bottom: 0;
@@ -43,21 +49,42 @@
<noscript>This page contains webassembly and javascript content, please enable javascript in your browser.</noscript>
<script src="./bootstrap.js"></script>
<div class="App" data-bs-theme="dark">
<div id="modelShareLink" class="modal fade" tabindex="-1" aria-hidden="true" data-bs-theme="dark">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Share This Code!</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="input-group mb-3">
<input id="shareLinkText" type="text" class="form-control user-select-all"
aria-label="Recipient's username" aria-describedby="shareLinkCopyButton" readonly>
<button class="btn btn-outline-secondary" type="button" id="shareLinkCopyButton">Copy</button>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-default">
<div class="d-flex flex-row justify-content-start w-100">
<div class="nav navbar-nav dropdown">
<button class="btn btn-outline-secondary" type="button" id="mainMenu" data-toggle="dropdown"
<div class="nav navbar-nav navbar-header dropdown">
<button class="btn btn-outline-secondary" type="button" id="mainMenu" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fa-solid fa-bars"></i>
</button>
<div class="dropdown-menu" aria-labelledby="mainMenu">
<button class="dropdown-item" type="button">Share</button>
<button class="dropdown-item" type="button">Open File</button>
<button class="dropdown-item" type="button">Save As</button>
</div>
<ul class="dropdown-menu" aria-labelledby="mainMenu">
<li><button id="mainMenuShare" class="dropdown-item" type="button" data-bs-toggle="modal"
data-bs-target="#modelShareLink">Share</button></li>
<li><button id="mainMenuOpenFile" class="dropdown-item" type="button">Open File</button></li>
<li><button id="mainMenuSaveAs" class="dropdown-item" type="button">Save As</button></li>
</ul>
</div>
<div class="nav navbar-nav navbar-header">
<a class="navbar-brand active" aria-current="page" href="/">IC10Emu</a>
<a class="navbar-brand active" aria-current="page" href="/">Stationeers IC10 Emulator</a>
</div>
<div class="flex-grow w-100">&nbsp;</div>
<ul class="nav navbar-nav d-flex flex-row">

View File

@@ -1,8 +1,8 @@
import {init} from "ic10emu_wasm";
import { init } from "ic10emu_wasm";
import * as ace from "ace-code";
import {Mode as IC10Mode} from "./ic10_mode";
import { Mode as IC10Mode } from "./ic10_mode";
import * as theme from "ace-code/src/theme/one_dark";
import {AceLanguageClient} from "ace-linters/build/ace-language-client";
import { AceLanguageClient } from "ace-linters/build/ace-language-client";
import ace_ext_statusbar from "ace-code/src/ext/statusbar";
import ace_ext_keybinding_menu from "ace-code/src/ext/keybinding_menu";
import _ace_ext_langue_tools from "ace-code/src/ext/language_tools";
@@ -111,41 +111,20 @@ j ra
const loaded = w =>
new Promise(r => w.addEventListener("message", r, { once: true }));
async function setupLsp(editor, mode) {
// Create a web worker
let worker = new Worker(new URL('./lspWorker.js', import.meta.url));
await Promise.all([loaded(worker)]);
const serverData = {
module: () => import("ace-linters/build/language-client"),
modes: "ic10",
type: "webworker",
worker: worker,
}
// Create a language provider for web worker
let languageProvider = AceLanguageClient.for(serverData);
// Register the editor with the language provider
languageProvider.registerEditor(editor);
let options = mode.options ?? {};
languageProvider.setSessionOptions(editor.session, options);
}
function base64url_encode(buffer) {
return btoa(Array.from(new Uint8Array(buffer), b => String.fromCharCode(b)).join(''))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
return btoa(Array.from(new Uint8Array(buffer), b => String.fromCharCode(b)).join(''))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
function base64url_decode(value) {
const m = value.length % 4;
return Uint8Array.from(atob(
value.replace(/-/g, '+')
.replace(/_/g, '/')
.padEnd(value.length + (m === 0 ? 0 : 4 - m), '=')
), c => c.charCodeAt(0)).buffer
const m = value.length % 4;
return Uint8Array.from(atob(
value.replace(/-/g, '+')
.replace(/_/g, '/')
.padEnd(value.length + (m === 0 ? 0 : 4 - m), '=')
), c => c.charCodeAt(0)).buffer
}
async function concatUintArrays(arrays) {
@@ -161,7 +140,7 @@ async function* streamAsyncIterator(stream) {
try {
while (true) {
// Read from the stream
const {done, value} = await reader.read();
const { done, value } = await reader.read();
if (done) return;
yield value;
}
@@ -229,6 +208,27 @@ async function getContentFromFragment(editor, default_content) {
}
}
async function setupLsp(editor, mode) {
// Create a web worker
let worker = new Worker(new URL('./lspWorker.js', import.meta.url));
await Promise.all([loaded(worker)]);
const serverData = {
module: () => import("ace-linters/build/language-client"),
modes: "ic10",
type: "webworker",
worker: worker,
}
// Create a language provider for web worker
let languageProvider = AceLanguageClient.for(serverData);
// Register the editor with the language provider
languageProvider.registerEditor(editor);
let options = mode.options ?? {};
languageProvider.setSessionOptions(editor.session, options);
}
docReady(() => {
const mode = new IC10Mode()
var editor = ace.edit("editor", {
@@ -248,7 +248,7 @@ docReady(() => {
});
editor.setTheme("ace/theme/one_dark");
var statusBar = new ace_ext_statusbar.StatusBar(editor, document.getElementById("statusBar"));
var statusBar = new ace_ext_statusbar.StatusBar(editor, document.getElementById("statusBar"));
statusBar.updateStatus(editor);
ace_ext_keybinding_menu.init(editor);
// editor.setOption("keyboardHandler", "ace/keyboard/vim");
@@ -262,9 +262,87 @@ docReady(() => {
window.addEventListener('hashchange', (event) => {
getContentFromFragment(editor, "");
});
// Menu
document.getElementById("mainMenuShare").addEventListener('click', (event) => {
const link = document.getElementById("shareLinkText");
link.setAttribute('value', window.location);
link.setSelectionRange(0, 0);
}, { capture: true });
document.getElementById("shareLinkCopyButton").addEventListener('click', (event) => {
event.preventDefault();
const link = document.getElementById("shareLinkText");
link.select();
link.setSelectionRange(0, 99999);
navigator.clipboard.writeText(link.value);
}, { capture: true });
document.getElementById("mainMenuOpenFile").addEventListener('click', (event) => {
openFile(editor);
}, { capture: true });
document.getElementById("mainMenuSaveAs").addEventListener('click', (event) => {
saveFile(editor.getSession().getValue())
}, { capture: true });
});
async function saveFile(content) {
const blob = new Blob([content], { type: "text/plain" });
if (typeof window.showSaveFilePicker !== "undefined") {
console.log("Saving via FileSystem API")
const options = {
types: [
{
suggestedName: "code.ic10",
description: 'Text Files',
accept: {
'text/plain': ['.txt', '.ic10'],
},
},
],
};
const saveHandle = await window.showSaveFilePicker(options);
const ws = await saveHandle.createWritable();
await ws.write(blob);
await ws.close();
} else {
console.log("saving file via hidden link event");
var a = document.createElement('a');
a.download = "code.ic10";
a.href = window.URL.createObjectURL(blob);
a.click();
}
}
async function openFile(editor) {
if (typeof window.showOpenFilePicker !== "undefined") {
console.log("opening file via FileSystem Api");
const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
const session = editor.getSession();
session.setValue(contents);
} else {
console.log("opening file via hidden input event");
let input = document.createElement('input');
input.type = 'file';
input.accept = ".txt,.ic10,.mips,text/*";
input.onchange = _ => {
const files = Array.from(input.files);
console.log(files);
const file = files[0];
var reader = new FileReader();
reader.onload = (e) => {
const contents = e.target.result;
const session = editor.getSession();
// session.id = file.name;
session.setValue(contents);
};
reader.readAsText(file);
};
input.click();
}
}