Add bad coders webring, update kumaos.
This commit is contained in:
parent
770369c84b
commit
dc0b9b14cb
17 changed files with 401 additions and 155 deletions
|
|
@ -15,11 +15,6 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="{{ '/static/main.css?fixcache=1' | url }}">
|
<link rel="stylesheet" href="{{ '/static/main.css?fixcache=1' | url }}">
|
||||||
<link href="{{ '/static/prism.css' | url }}" rel="stylesheet"/>
|
<link href="{{ '/static/prism.css' | url }}" rel="stylesheet"/>
|
||||||
<script type="module" src="{{ '/static/scripts/ccd.js' | url }}"></script>
|
|
||||||
<script type="module" src="{{ '/static/scripts/music.js' | url }}" defer></script>
|
|
||||||
<script type="module" src="{{ '/static/scripts/88x31.js' | url }}" defer></script>
|
|
||||||
<script type="module" src="{{ '/static/scripts/tips.js' | url }}" defer></script>
|
|
||||||
<script type="module" src="{{ '/static/scripts/click.js' | url }}" defer></script>
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/static/apple-touch-icon.png' | url }}">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/static/apple-touch-icon.png' | url }}">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/static/favicon-32x32.png' | url }}">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/static/favicon-32x32.png' | url }}">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ '/static/favicon-16x16.png' | url }}">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ '/static/favicon-16x16.png' | url }}">
|
||||||
|
|
@ -31,21 +26,10 @@
|
||||||
<meta property="og:image" content="{{ ('/static/images/' ~ (background or 'bear.jpg')) | url | absoluteUrl }}">
|
<meta property="og:image" content="{{ ('/static/images/' ~ (background or 'bear.jpg')) | url | absoluteUrl }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="iframe">
|
<body class="iframe">
|
||||||
{% poison %}
|
|
||||||
<script>
|
<script>
|
||||||
const rootPrefix = "{{ '/' | url }}";
|
const rootPrefix = "{{ '/' | url }}";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<noscript>
|
|
||||||
<style>
|
|
||||||
.i88x31:hover {
|
|
||||||
transform: scale(2);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</noscript>
|
|
||||||
|
|
||||||
<div id="everythingHelper">
|
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -241,6 +241,12 @@ headerLink: home
|
||||||
image: "/static/images/metro-flowers.jpg"
|
image: "/static/images/metro-flowers.jpg"
|
||||||
}) }}
|
}) }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://axelotl3001.neocities.org/webring/onionring.css">
|
||||||
|
<div id='Bad-coders'>
|
||||||
|
<script type="text/javascript" src="https://axelotl3001.neocities.org/webring/onionring-variables.js"></script>
|
||||||
|
<script type="text/javascript" src="https://axelotl3001.neocities.org/webring/onionring-widget.js"></script>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% include 'widgets/droidring.html' %}
|
{% include 'widgets/droidring.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
---
|
---
|
||||||
layout: text.njk
|
pageTitle: kumaOS
|
||||||
pagination:
|
pagination:
|
||||||
data: languages
|
data: languages
|
||||||
size: 1
|
size: 1
|
||||||
alias: langKey
|
alias: langKey
|
||||||
pageTitle: KumaOS
|
|
||||||
background: bliss-dark.jpg
|
|
||||||
---
|
---
|
||||||
{% from "macros.njk" import i88x31 with context %}
|
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Document</title>
|
||||||
|
<link rel="stylesheet" href="{{ '/static/kumos/kumos.css' | url }}">
|
||||||
<script type="module" src="{{ '/static/kumos/kernel.mjs' | url }}" defer></script>
|
<script type="module" src="{{ '/static/kumos/kernel.mjs' | url }}" defer></script>
|
||||||
<script type="module" src="{{ '/static/kumos/shell.mjs' | url }}" defer></script>
|
<script type="module" src="{{ '/static/kumos/system/init.mjs' | url }}" defer></script>
|
||||||
<script type="module" src="{{ '/static/kumos/guestbook.mjs' | url }}" defer></script>
|
</head>
|
||||||
<script type="module" src="{{ '/static/kumos/browser.mjs' | url }}" defer></script>
|
<body>
|
||||||
<script type="module" src="{{ '/static/kumos/apps.mjs' | url }}" defer></script>
|
<div style="user-select: none; pointer-events: none; display: flex; gap: 1em;">
|
||||||
<script type="module" src="{{ '/static/kumos/taskmanager.mjs' | url }}" defer></script>
|
<h1>kumaOS</h1>
|
||||||
<main>
|
<p>demo - not for production</p>
|
||||||
<h1>Welcome to KumOS</h1>
|
|
||||||
<p>There's not much to do right now as the system is being developed... Try running <code>apps</code> to see what's available.</p>
|
|
||||||
</main>
|
|
||||||
<aside>
|
|
||||||
<div id="aboutChangelog">
|
|
||||||
<div>
|
|
||||||
<h1 class="nomargin negativeMargin">{{ i18n[langKey].changes | smartTitle }}</h1>
|
|
||||||
<hr style="margin-bottom: .4em;">
|
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<style>
|
||||||
{%- for commit in collections.recentChanges %}
|
body {
|
||||||
<li class="doubleLine"><a class="textColored" href="https://github.com/adrianvic/adrianvic.github.io/commit/{{ commit.hash }}"><b>{{ commit.abbrevHash }}</b> {{ commit.subject }}</a></li>
|
background-image: url("{{ '/static/images/bliss-dark.jpg' | url }}");
|
||||||
{%- endfor %}
|
background-size: cover;
|
||||||
</ul>
|
width: 100vw;
|
||||||
</div>
|
height: 100vh;
|
||||||
</aside>
|
overflow: hidden;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getApplications } from "./kernel.mjs";
|
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getApplications } from "../kernel.mjs";
|
||||||
|
|
||||||
const app = new Application('apps', (p) => {
|
const app = new Application('apps', (p) => {
|
||||||
const w = new Window();
|
const w = new Window(p);
|
||||||
w.setTitle("App list");
|
w.setTitle("App list");
|
||||||
w.content.style.padding = "1rem";
|
w.content.style.padding = "1rem";
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ const app = new Application('apps', (p) => {
|
||||||
const item = document.createElement("li");
|
const item = document.createElement("li");
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.innerText = app.name;
|
link.innerText = app.name;
|
||||||
link.addEventListener('click', () => app.fn());
|
link.addEventListener('click', () => app.bootstrap());
|
||||||
item.appendChild(link);
|
item.appendChild(link);
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
})
|
})
|
||||||
|
|
@ -26,4 +26,4 @@ const app = new Application('apps', (p) => {
|
||||||
promoteWindow(w);
|
promoteWindow(w);
|
||||||
})
|
})
|
||||||
|
|
||||||
registerApplication(app);
|
export default app;
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Application, Window, promoteWindow, registerApplication, getScreenRoot } from "./kernel.mjs";
|
import { Application, Window, promoteWindow, registerApplication, getScreenRoot } from "../kernel.mjs";
|
||||||
|
|
||||||
const app = new Application('browser', (p) => {
|
const app = new Application('browser', (p) => {
|
||||||
const w = new Window();
|
const w = new Window(p);
|
||||||
w.setTitle("Web browser");
|
w.setTitle("Web browser");
|
||||||
const iframe = document.createElement("iframe");
|
const iframe = document.createElement("iframe");
|
||||||
iframe.src = "https://adrianvic.github.io";
|
iframe.src = "https://adrianvic.github.io";
|
||||||
|
|
@ -29,4 +29,4 @@ const app = new Application('browser', (p) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
registerApplication(app);
|
export default app;
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getProcList } from "./kernel.mjs";
|
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getProcList } from "../kernel.mjs";
|
||||||
import { notify } from "./shell.mjs";
|
import { notify } from "../system/shell.mjs";
|
||||||
|
|
||||||
function draw(p) {
|
function draw(p) {
|
||||||
const w = new Window();
|
const w = new Window(p);
|
||||||
w.setTitle("Guestbook");
|
w.setTitle("Guestbook");
|
||||||
w.content.innerHTML = `
|
w.content.innerHTML = `
|
||||||
<script src="https://iframe.chat/scripts/main.min.js"></script>
|
<script src="https://iframe.chat/scripts/main.min.js"></script>
|
||||||
|
|
@ -35,4 +35,4 @@ function main(p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = new Application('guestbook', main);
|
const app = new Application('guestbook', main);
|
||||||
registerApplication(app);
|
export default app;
|
||||||
5
static/kumos/apps/pkg.mjs
Normal file
5
static/kumos/apps/pkg.mjs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import "./apps.mjs";
|
||||||
|
import "./browser.mjs";
|
||||||
|
import "./guestbook.mjs";
|
||||||
|
import "./taskmanager.mjs";
|
||||||
|
import "./shell.mjs";
|
||||||
61
static/kumos/apps/shell.mjs
Normal file
61
static/kumos/apps/shell.mjs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { Application, Window, getScreenRoot, bus, promoteWindow } from "../kernel.mjs";
|
||||||
|
|
||||||
|
function draw(p) {
|
||||||
|
const w = new Window(p);
|
||||||
|
w.setTitle("Shell");
|
||||||
|
w.content.style.display = "flex";
|
||||||
|
w.content.style.flexDirection = "column";
|
||||||
|
|
||||||
|
const textarea = document.createElement("textarea");
|
||||||
|
textarea.style.width = "100%";
|
||||||
|
textarea.style.height = "100%";
|
||||||
|
bus.addEventListener("system-console", (e) => {
|
||||||
|
textarea.value += e.detail
|
||||||
|
.map(arg => typeof arg === "object" ? JSON.stringify(arg) : String(arg))
|
||||||
|
.join(" ")
|
||||||
|
+ "\n";
|
||||||
|
})
|
||||||
|
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.style.width = "100%";
|
||||||
|
div.style.display = "flex";
|
||||||
|
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.style.width = "100%";
|
||||||
|
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.textContent = "go";
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
eval(input.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
div.appendChild(input);
|
||||||
|
div.appendChild(button);
|
||||||
|
|
||||||
|
w.content.appendChild(textarea);
|
||||||
|
w.content.appendChild(div);
|
||||||
|
getScreenRoot().appendChild(w.window);
|
||||||
|
w.maximize();
|
||||||
|
|
||||||
|
function title(title) {
|
||||||
|
w.setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exit() {
|
||||||
|
p.detach();
|
||||||
|
w.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
w.close.addEventListener('click', () => {
|
||||||
|
exit();
|
||||||
|
})
|
||||||
|
|
||||||
|
promoteWindow(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(p) {
|
||||||
|
draw(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = new Application('shell', main);
|
||||||
|
export default app;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getProcList } from "./kernel.mjs";
|
import { Application, Window, promoteWindow, getScreenRoot, getProcList } from "../kernel.mjs";
|
||||||
|
|
||||||
const app = new Application('task', (p) => {
|
const app = new Application('task', (p) => {
|
||||||
function update() {
|
function update() {
|
||||||
|
|
@ -7,7 +7,7 @@ const app = new Application('task', (p) => {
|
||||||
getProcList().forEach(proc => {
|
getProcList().forEach(proc => {
|
||||||
const item = document.createElement("li");
|
const item = document.createElement("li");
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.innerText = `${proc.pid} -> ${proc.name}`;
|
link.innerText = `${proc.pid} -> ${proc.parent.length === 0 ? `` : proc.parent} ${proc.name}`;
|
||||||
item.appendChild(link);
|
item.appendChild(link);
|
||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
})
|
})
|
||||||
|
|
@ -31,4 +31,4 @@ const app = new Application('task', (p) => {
|
||||||
promoteWindow(w);
|
promoteWindow(w);
|
||||||
})
|
})
|
||||||
|
|
||||||
registerApplication(app);
|
export default app;
|
||||||
|
|
@ -1,28 +1,56 @@
|
||||||
const language = "en";
|
const language = "en";
|
||||||
const procList = [];
|
const procList = [];
|
||||||
|
const applications = [];
|
||||||
|
const screenRoot = document.querySelector('body');
|
||||||
|
screenRoot.classList.add("kumosroot");
|
||||||
|
|
||||||
|
export const bus = new EventTarget();
|
||||||
|
|
||||||
|
class SecurityError extends Error {
|
||||||
|
constructor(message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "SercurityError"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export class Process {
|
export class Process {
|
||||||
constructor(app) {
|
constructor(name, fn, parent = []) {
|
||||||
this.pid = procList.length == 0 ? 0 : procList[procList.length - 1].pid + 1;
|
this.pid = procList.length == 0 ? 0 : procList[procList.length - 1].pid + 1;
|
||||||
this.name = app.name;
|
this.name = name;
|
||||||
|
this.parent = parent;
|
||||||
procList.push(this);
|
procList.push(this);
|
||||||
app.fn(this);
|
fn(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
detach() {
|
detach() {
|
||||||
procList.splice(procList.indexOf(this), 1);
|
procList.splice(procList.indexOf(this), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
child(name, fn) {
|
||||||
|
return new Process(name, fn, [...this.parent, this.pid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
isPrivileged() {
|
||||||
|
return this.parent.indexOf(0) !== -1 || this.pid == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Application {
|
export class Application {
|
||||||
constructor(name, fn) {
|
constructor(name, fn) {
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
registerApplication(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap() {
|
||||||
|
new Process(this.name, this.fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Window {
|
export class Window {
|
||||||
constructor() {
|
constructor(p) {
|
||||||
|
this.process = p;
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
const w = document.createElement("div");
|
const w = document.createElement("div");
|
||||||
w.classList.add("window");
|
w.classList.add("window");
|
||||||
|
|
@ -38,23 +66,37 @@ export class Window {
|
||||||
title.classList.add("windowHeaderTitle");
|
title.classList.add("windowHeaderTitle");
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
|
||||||
|
// Buttons container
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.classList.add("buttonContainer");
|
||||||
|
|
||||||
// Close button
|
// Close button
|
||||||
const close = document.createElement("button");
|
const close = document.createElement("button");
|
||||||
close.innerText = "close";
|
|
||||||
close.classList.add("windowHeaderButton");
|
close.classList.add("windowHeaderButton");
|
||||||
close.classList.add("windowHeaderButtonClose");
|
close.classList.add("close");
|
||||||
this.close = close;
|
this.close = close;
|
||||||
|
|
||||||
|
// Maximize button
|
||||||
|
const maximize = document.createElement("button");
|
||||||
|
maximize.classList.add("windowHeaderButton");
|
||||||
|
maximize.classList.add("maximize");
|
||||||
|
this.maximizeButton = maximize;
|
||||||
|
maximize.addEventListener("click", () => { this.maximize() });
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
const c = document.createElement("div");
|
const c = document.createElement("div");
|
||||||
c.classList.add("windowContent");
|
c.classList.add("windowContent");
|
||||||
this.content = c;
|
this.content = c;
|
||||||
|
|
||||||
// Building
|
// Building
|
||||||
|
container.appendChild(maximize);
|
||||||
|
container.appendChild(close);
|
||||||
h.appendChild(title);
|
h.appendChild(title);
|
||||||
h.appendChild(close);
|
h.appendChild(container);
|
||||||
w.appendChild(h);
|
w.appendChild(h);
|
||||||
w.appendChild(c);
|
w.appendChild(c);
|
||||||
|
|
||||||
|
this.state = "floating";
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle(title) {
|
setTitle(title) {
|
||||||
|
|
@ -64,6 +106,10 @@ export class Window {
|
||||||
destroy() {
|
destroy() {
|
||||||
this.window.remove();
|
this.window.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maximize() {
|
||||||
|
this.window.classList.toggle("maximized");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function promoteWindow(window) {
|
export function promoteWindow(window) {
|
||||||
|
|
@ -103,11 +149,9 @@ export function promoteWindow(window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getScreenRoot() {
|
export function getScreenRoot() {
|
||||||
return document.querySelector('body');
|
return screenRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
const applications = [];
|
|
||||||
|
|
||||||
export function getApplications() {
|
export function getApplications() {
|
||||||
return applications;
|
return applications;
|
||||||
}
|
}
|
||||||
|
|
@ -123,3 +167,14 @@ export function getLanguage() {
|
||||||
export function getProcList() {
|
export function getProcList() {
|
||||||
return procList;
|
return procList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
["log","warn", "error", "info"].forEach(method => {
|
||||||
|
const original = console[method];
|
||||||
|
|
||||||
|
console[method] = (...args) => {
|
||||||
|
original(...args);
|
||||||
|
bus.dispatchEvent(new CustomEvent("system-console", {
|
||||||
|
detail: args
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
})
|
||||||
138
static/kumos/kumos.css
Normal file
138
static/kumos/kumos.css
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
.kumosroot {
|
||||||
|
--theme-color: #4c6d6e;
|
||||||
|
--theme-color-lighter: #84b9bb;
|
||||||
|
--theme-color-variation: #568b8d;
|
||||||
|
position: relative;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 9;
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
resize: both;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window.maximized {
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeader {
|
||||||
|
padding: 10px;
|
||||||
|
cursor: move;
|
||||||
|
z-index: 10;
|
||||||
|
background-color: rgba(255, 255, 255, 0.6);
|
||||||
|
color: #000000;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeader .buttonContainer {
|
||||||
|
display: flex;
|
||||||
|
gap: .4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowContent {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowContent {
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeader {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeaderTitle {
|
||||||
|
margin: 0px;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kumosBar {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--theme-color);
|
||||||
|
padding: .4em;
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kumosBar * {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeaderButton {
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeaderButton.close::before {
|
||||||
|
content: "×";
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeaderButton.close {
|
||||||
|
background-color: rgba(255, 0, 0, 0.6);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeaderButton.maximize::before {
|
||||||
|
content: "□";
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowHeaderButton.maximize {
|
||||||
|
background-color: rgba(255, 255, 0, 0.6);
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
button, input, textarea {
|
||||||
|
padding: .2em;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-inline-start: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
static/kumos/system/init.mjs
Normal file
10
static/kumos/system/init.mjs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import "../apps/pkg.mjs";
|
||||||
|
import { Process } from "../kernel.mjs";
|
||||||
|
import interactiveLogin from "./targets/interactive-login.mjs";
|
||||||
|
|
||||||
|
function init(p) {
|
||||||
|
console.log("Welcome to KumOS!");
|
||||||
|
interactiveLogin(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
new Process("init", init);
|
||||||
43
static/kumos/system/login.mjs
Normal file
43
static/kumos/system/login.mjs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { Process, Window, getScreenRoot, promoteWindow } from "../kernel.mjs";
|
||||||
|
import createShell from "./shell.mjs";
|
||||||
|
|
||||||
|
export default function init(p) {
|
||||||
|
function login(password) {
|
||||||
|
if (password == "demo") {
|
||||||
|
p.detach();
|
||||||
|
new Process("shell", createShell);
|
||||||
|
w.destroy();
|
||||||
|
} else {
|
||||||
|
console.log("Invalid password.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Please log in with login(password)!");
|
||||||
|
window.login = login;
|
||||||
|
const w = new Window(p);
|
||||||
|
w.setTitle("Login");
|
||||||
|
w.window.style.height = "fit-content";
|
||||||
|
w.window.style.width = "fit-content";
|
||||||
|
w.window.style.resize = "none";
|
||||||
|
|
||||||
|
const loginForm = document.createElement("div");
|
||||||
|
loginForm.style.display = "flex";
|
||||||
|
|
||||||
|
const passwordInput = document.createElement("input");
|
||||||
|
passwordInput.type = "password";
|
||||||
|
passwordInput.placeholder = "Password is 'demo'";
|
||||||
|
|
||||||
|
const loginButton = document.createElement("button");
|
||||||
|
loginButton.innerText = "login";
|
||||||
|
loginButton.addEventListener('click', () => {
|
||||||
|
login(passwordInput.value);
|
||||||
|
})
|
||||||
|
|
||||||
|
loginForm.appendChild(passwordInput);
|
||||||
|
loginForm.appendChild(loginButton);
|
||||||
|
w.content.appendChild(loginForm);
|
||||||
|
|
||||||
|
w.close.remove();
|
||||||
|
getScreenRoot().appendChild(w.window);
|
||||||
|
promoteWindow(w);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { getScreenRoot, getApplications, Process } from "./kernel.mjs";
|
import { getScreenRoot, getApplications, Process } from "../kernel.mjs";
|
||||||
import { showNotification } from "../scripts/notification.js";
|
import { showNotification } from "../../scripts/notification.js";
|
||||||
|
|
||||||
export function notify(title, text, time) {
|
export function notify(title, text, time) {
|
||||||
showNotification(title, text, time);
|
showNotification(title, text, time);
|
||||||
|
|
@ -9,14 +9,14 @@ function runApp(name) {
|
||||||
let launched = false;
|
let launched = false;
|
||||||
getApplications().forEach(app => {
|
getApplications().forEach(app => {
|
||||||
if (app.name == name) {
|
if (app.name == name) {
|
||||||
new Process(app);
|
app.bootstrap();
|
||||||
launched = true;
|
launched = true;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (!launched) alert("Not found.");
|
if (!launched) alert("Not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function createShell() {
|
export default function createShell(p) {
|
||||||
const bar = document.createElement('div');
|
const bar = document.createElement('div');
|
||||||
bar.classList.add("kumosBar");
|
bar.classList.add("kumosBar");
|
||||||
|
|
||||||
|
|
@ -31,6 +31,3 @@ function createShell() {
|
||||||
|
|
||||||
getScreenRoot().appendChild(bar);
|
getScreenRoot().appendChild(bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
createShell();
|
|
||||||
showNotification("KumOS Shell", "Welcome to KumOS, everything is work-in-progress! Try running apps to see available packages.", 10000);
|
|
||||||
5
static/kumos/system/targets/interactive-login.mjs
Normal file
5
static/kumos/system/targets/interactive-login.mjs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import login from "../login.mjs";
|
||||||
|
|
||||||
|
export default (p) => {
|
||||||
|
p.child("login", login);
|
||||||
|
}
|
||||||
|
|
@ -1172,67 +1172,6 @@ header div:first-child {
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* KumOS */
|
|
||||||
|
|
||||||
.window {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 9;
|
|
||||||
/* background-color: #f1f1f1; */
|
|
||||||
width: 300px;
|
|
||||||
height: 300px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
resize: both;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.windowHeader {
|
|
||||||
padding: 10px;
|
|
||||||
cursor: move;
|
|
||||||
z-index: 10;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
color: #fff;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.windowContent {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.windowContent {
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.windowHeader {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.windowHeaderTitle {
|
|
||||||
margin: 0px;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kumosBar {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
background-color: var(--theme-color);
|
|
||||||
padding: .4em;
|
|
||||||
display: flex;
|
|
||||||
gap: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kumosBar * {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Animations */
|
/* Animations */
|
||||||
|
|
||||||
@keyframes ellipsis-loader {
|
@keyframes ellipsis-loader {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
const body = document.querySelector('body');
|
const body = document.querySelector('body');
|
||||||
const elements = document.querySelectorAll('[data-tip]');
|
|
||||||
const hint = document.querySelector("#headerSubtitle");
|
const hint = document.querySelector("#headerSubtitle");
|
||||||
const hintPanelDefaultText = hint.innerHTML;
|
const hintPanelDefaultText = hint ? hint.innerHTML : null;
|
||||||
let fixedHint;
|
let fixedHint;
|
||||||
let currentObserver;
|
let currentObserver;
|
||||||
|
|
||||||
|
if (hint) {
|
||||||
|
const elements = document.querySelectorAll('[data-tip]');
|
||||||
elements.forEach(el => {
|
elements.forEach(el => {
|
||||||
registerElementHint(el);
|
registerElementHint(el);
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
|
if (!hint) return;
|
||||||
hint.innerHTML = hintPanelDefaultText;
|
hint.innerHTML = hintPanelDefaultText;
|
||||||
hint.classList.remove('fixed');
|
hint.classList.remove('fixed');
|
||||||
if (fixedHint) {
|
if (fixedHint) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue