Saveing and opening files, quick links.
Signed-off-by: Rachel <508861+Ryex@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"> </div>
|
||||
<ul class="nav navbar-nav d-flex flex-row">
|
||||
|
||||
152
www/src/index.js
152
www/src/index.js
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user