getting some structure

Things like reflowing works, as well as switching between
"applications". Things seem to be coming along nicely.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
2023-12-01 23:49:39 +08:00
parent 02e1556a65
commit 32c1b7d54b
28 changed files with 14376 additions and 74 deletions

127
src/index.ts Normal file
View File

@ -0,0 +1,127 @@
import { FarpatchWidget } from './interfaces';
import { UartWidget } from './interface/uart';
import { DashboardWidget } from './interface/dashboard';
var FarpatchWidgets: { [key: string]: FarpatchWidget } = {
"dashboard": new DashboardWidget(),
"uart": new UartWidget(),
};
// TODO: Get the current widget from the address bar, if one exists
var currentWidgetName: string = "dashboard";
var currentWidget: FarpatchWidget = FarpatchWidgets[currentWidgetName];
var currentWidgetView: HTMLElement = document.getElementById(currentWidgetName + "-view") as HTMLElement;
function addToggleSidebarListener(element: HTMLElement) {
// Hide or show the sidebar. MaterialUI calls this toggling between
// a "rail" and a "sidebar".
element.addEventListener('click', function () {
// Hide or show the main content area
var main = document.getElementsByTagName("main")[0];
// Adjust the width of the sidebar as well
var sideNav = document.querySelectorAll(".sidenav")[0];
if (main.classList.contains("main-sidebar-rail")) {
main.classList.remove("main-sidebar-rail");
sideNav.classList.remove("sidenav-rail");
} else {
main.classList.add("main-sidebar-rail");
sideNav.classList.add("sidenav-rail");
}
}, false);
}
// On load, add a listener for mouse clicks on the navigation bar.
function setupNavItem(element: HTMLElement) {
// Get the base name of the element in order to set up the callback.
var elementBase = element.id.replace("-button", "");
if (typeof (FarpatchWidgets[elementBase]) === 'undefined') {
console.log("No widget found for " + elementBase);
// return;
} else {
console.log("Setting up widget for " + elementBase);
var elementContent = document.getElementById(elementBase + "-view");
if (typeof (elementContent) === 'undefined' || elementContent === null) {
console.log("No element found for " + elementBase + "-view");
return;
}
FarpatchWidgets[elementBase].onInit();
if (FarpatchWidgets[elementBase] === currentWidget) {
element.classList.add("sidenav-item-active");
FarpatchWidgets[elementBase].onFocus(elementContent);
currentWidgetView = elementContent;
elementContent.classList.add("main-content-active");
} else {
console.log("Not initializing widget " + elementBase);
}
}
// Hook "click" for each navigation item. The listener will:
// 1. Loop through each nav item and remove the "active" class for
// each inactive item and add it to the newly-clicked item.
// 2. Unhide the correct view to activate it
element.addEventListener('click', function () {
var main = document.getElementsByTagName("main")[0];
var navItems = document.querySelectorAll(".sidenav-item");
var elementBase = element.id.replace("-button", "");
if (typeof (FarpatchWidgets[elementBase]) !== 'undefined') {
if (FarpatchWidgets[elementBase] !== currentWidget) {
var newElementContent = document.getElementById(elementBase + "-view");
if (typeof (newElementContent) === 'undefined' || newElementContent === null) {
console.log("No element found for " + elementBase + "-view");
return;
}
currentWidget.onBlur(currentWidgetView);
FarpatchWidgets[elementBase].onFocus(newElementContent);
currentWidget = FarpatchWidgets[elementBase];
currentWidgetName = elementBase;
currentWidgetView = newElementContent;
}
}
for (var i = 0; i < navItems.length; i++) {
var navItem = navItems[i];
if (navItem === element) {
if (!navItem.classList.contains("sidenav-item-active")) {
navItem.classList.add("sidenav-item-active");
}
} else {
navItem.classList.remove("sidenav-item-active");
}
}
var mainViews = document.querySelectorAll(".main-content-active");
for (var i = 0; i < mainViews.length; i++) {
var mainView = mainViews[i];
mainView.classList.remove("main-content-active");
}
var elementBase = element.id.replace("-button", "");
var elementContent = document.getElementById(elementBase + "-view");
if (typeof (elementContent) === 'undefined' || elementContent === null) {
console.log("No element found for " + elementBase + "-view");
return;
}
elementContent.classList.add("main-content-active");
}, false);
}
document.addEventListener('DOMContentLoaded', function () {
var navItems = document.querySelectorAll(".sidenav-item");
for (var i = 0; i < navItems.length; i++) {
// For the "toggle" button, don't add a listener. Instead, have it
// toggle the visibility of the sidebar.
if (navItems[i].classList.contains("sidenav-item-toggle")) {
addToggleSidebarListener(navItems[i] as HTMLElement);
} else {
setupNavItem(navItems[i] as HTMLElement);
}
}
// var navItems = document.querySelectorAll(".main-viewport");
// for (var i = 0; i < navItems.length; i++) {
// addNavListener(navItems[i]);
// }
}, false);

View File

@ -0,0 +1,43 @@
import { FarpatchWidget } from "../interfaces";
export class DashboardWidget implements FarpatchWidget {
view: Element = document.createElement("div");
onInit(): void {
this.view.innerHTML = `
<div class="fieldset-item">
<picture aria-hidden="true">
<svg viewBox="0 0 24 24">
<title>A note icon</title>
<path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>
</picture>
<div class="input-stack">
<label
for="media-volume"
id="media-volume"
aria-hidden="true">
Media volume
</label>
<input
name="media-volume"
aria-labelledby="media-volume"
type="range"
value="3"
max="10"
style="--track-fill: 30%"
>
</div>
</div>
`;
console.log("Initialized Dashboard Widget");
}
onFocus(element: HTMLElement): void {
console.log("Displaying Dashboard Widget");
element.appendChild(this.view);
}
onBlur(element: HTMLElement): void {
console.log("Archiving Dashboard Widget");
element.removeChild(this.view);
}
}

60
src/interface/uart.ts Normal file
View File

@ -0,0 +1,60 @@
import { FarpatchWidget } from "../interfaces";
import { Terminal } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import { SerializeAddon } from '@xterm/addon-serialize';
export class UartWidget implements FarpatchWidget {
view: HTMLElement;
terminal: Terminal;
fitAddon: FitAddon;
serializeAddon: SerializeAddon;
resizeFunction: () => void;
initialized: boolean = false;
constructor() {
this.view = document.createElement("div");
this.terminal = new Terminal({ theme: { background: "#000000" } });
this.fitAddon = new FitAddon();
this.serializeAddon = new SerializeAddon();
this.resizeFunction = this.resizeTerminal.bind(this);
}
onInit(): void {
console.log("Initialized UART Widget");
}
onFocus(element: HTMLElement): void {
console.log("Displaying UART Widget");
if (!this.initialized) {
console.log("Initializing xterm.js");
var terminalContainer = document.createElement("div");
this.view.appendChild(terminalContainer);
this.terminal.loadAddon(this.fitAddon);
this.terminal.loadAddon(this.serializeAddon);
this.terminal.onKey((e) => {
console.log("Key pressed: " + e.key);
this.terminal.write(e.key);
if (e.key === '\r') {
this.terminal.write('\n');
}
});
this.terminal.open(terminalContainer);
this.terminal.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
this.initialized = true;
}
element.appendChild(this.view);
this.resizeFunction();
window.addEventListener('resize', this.resizeFunction);
window.setTimeout(() => {
this.terminal.focus();
}, 10);
}
onBlur(element: HTMLElement): void {
console.log("Archiving UART Widget");
element.removeChild(this.view);
window.removeEventListener('resize', this.resizeFunction);
}
// Whenever the window is resized, update the size of the terminal
resizeTerminal() {
this.fitAddon.fit();
}
}

5
src/interfaces.ts Normal file
View File

@ -0,0 +1,5 @@
export interface FarpatchWidget {
onInit(): void,
onFocus(element: HTMLElement): void,
onBlur(element: HTMLElement): void,
}