Add bad coders webring, update kumaos.

This commit is contained in:
天クマ 2026-07-07 16:42:07 -03:00
commit dc0b9b14cb
17 changed files with 401 additions and 155 deletions

View file

@ -15,11 +15,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{{ '/static/main.css?fixcache=1' | url }}">
<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="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 }}">
@ -31,21 +26,10 @@
<meta property="og:image" content="{{ ('/static/images/' ~ (background or 'bear.jpg')) | url | absoluteUrl }}">
</head>
<body class="iframe">
{% poison %}
<script>
const rootPrefix = "{{ '/' | url }}";
</script>
<noscript>
<style>
.i88x31:hover {
transform: scale(2);
}
</style>
</noscript>
<div id="everythingHelper">
{{ content | safe }}
</div>
{{ content | safe }}
</body>
</html>

View file

@ -241,6 +241,12 @@ headerLink: home
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' %}
</div>

View file

@ -1,34 +1,34 @@
---
layout: text.njk
pageTitle: kumaOS
pagination:
data: languages
size: 1
alias: langKey
pageTitle: KumaOS
background: bliss-dark.jpg
---
{% from "macros.njk" import i88x31 with context %}
<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/guestbook.mjs' | url }}" defer></script>
<script type="module" src="{{ '/static/kumos/browser.mjs' | url }}" defer></script>
<script type="module" src="{{ '/static/kumos/apps.mjs' | url }}" defer></script>
<script type="module" src="{{ '/static/kumos/taskmanager.mjs' | url }}" defer></script>
<main>
<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>
<ul>
{%- for commit in collections.recentChanges %}
<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>
{%- endfor %}
</ul>
</div>
</aside>
<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/system/init.mjs' | url }}" defer></script>
</head>
<body>
<div style="user-select: none; pointer-events: none; display: flex; gap: 1em;">
<h1>kumaOS</h1>
<p>demo - not for production</p>
</div>
<style>
body {
background-image: url("{{ '/static/images/bliss-dark.jpg' | url }}");
background-size: cover;
width: 100vw;
height: 100vh;
overflow: hidden;
margin: 0;
}
</style>
</body>
</html>

View file

@ -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 w = new Window();
const w = new Window(p);
w.setTitle("App list");
w.content.style.padding = "1rem";
@ -10,7 +10,7 @@ const app = new Application('apps', (p) => {
const item = document.createElement("li");
const link = document.createElement("a");
link.innerText = app.name;
link.addEventListener('click', () => app.fn());
link.addEventListener('click', () => app.bootstrap());
item.appendChild(link);
list.appendChild(item);
})
@ -26,4 +26,4 @@ const app = new Application('apps', (p) => {
promoteWindow(w);
})
registerApplication(app);
export default app;

View file

@ -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 w = new Window();
const w = new Window(p);
w.setTitle("Web browser");
const iframe = document.createElement("iframe");
iframe.src = "https://adrianvic.github.io";
@ -29,4 +29,4 @@ const app = new Application('browser', (p) => {
})
})
registerApplication(app);
export default app;

View file

@ -1,8 +1,8 @@
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getProcList } from "./kernel.mjs";
import { notify } from "./shell.mjs";
import { Application, Window, promoteWindow, registerApplication, getScreenRoot, getProcList } from "../kernel.mjs";
import { notify } from "../system/shell.mjs";
function draw(p) {
const w = new Window();
const w = new Window(p);
w.setTitle("Guestbook");
w.content.innerHTML = `
<script src="https://iframe.chat/scripts/main.min.js"></script>
@ -35,4 +35,4 @@ function main(p) {
}
const app = new Application('guestbook', main);
registerApplication(app);
export default app;

View file

@ -0,0 +1,5 @@
import "./apps.mjs";
import "./browser.mjs";
import "./guestbook.mjs";
import "./taskmanager.mjs";
import "./shell.mjs";

View 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;

View file

@ -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) => {
function update() {
@ -7,7 +7,7 @@ const app = new Application('task', (p) => {
getProcList().forEach(proc => {
const item = document.createElement("li");
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);
list.appendChild(item);
})
@ -31,4 +31,4 @@ const app = new Application('task', (p) => {
promoteWindow(w);
})
registerApplication(app);
export default app;

View file

@ -1,33 +1,61 @@
const language = "en";
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 {
constructor(app) {
constructor(name, fn, parent = []) {
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);
app.fn(this);
fn(this);
}
detach() {
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 {
constructor(name, fn) {
this.fn = fn;
this.name = name;
registerApplication(this);
}
bootstrap() {
new Process(this.name, this.fn);
}
}
export class Window {
constructor() {
constructor(p) {
this.process = p;
// Window
const w = document.createElement("div");
w.classList.add("window");
this.window = w;
// Header
const h = document.createElement("div");
h.classList.add("windowHeader");
@ -37,13 +65,23 @@ export class Window {
const title = document.createElement("p");
title.classList.add("windowHeaderTitle");
this.title = title;
// Buttons container
const container = document.createElement("div");
container.classList.add("buttonContainer");
// Close button
const close = document.createElement("button");
close.innerText = "close";
close.classList.add("windowHeaderButton");
close.classList.add("windowHeaderButtonClose");
close.classList.add("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
const c = document.createElement("div");
@ -51,50 +89,58 @@ export class Window {
this.content = c;
// Building
container.appendChild(maximize);
container.appendChild(close);
h.appendChild(title);
h.appendChild(close);
h.appendChild(container);
w.appendChild(h);
w.appendChild(c);
}
this.state = "floating";
}
setTitle(title) {
this.title.innerText = title;
}
destroy() {
this.window.remove();
}
maximize() {
this.window.classList.toggle("maximized");
}
}
export function promoteWindow(window) {
const header = window.header;
const elmnt = window.window;
header.style.cursor = 'move';
header.onmousedown = (e) => {
e.preventDefault();
let pos3 = e.clientX;
let pos4 = e.clientY;
const startTop = elmnt.offsetTop;
const startLeft = elmnt.offsetLeft;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
function elementDrag(e) {
e.preventDefault();
const pos1 = pos3 - e.clientX;
const pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
@ -103,11 +149,9 @@ export function promoteWindow(window) {
}
export function getScreenRoot() {
return document.querySelector('body');
return screenRoot;
}
const applications = [];
export function getApplications() {
return applications;
}
@ -122,4 +166,15 @@ export function getLanguage() {
export function getProcList() {
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
View 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;
}
}

View 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);

View 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);
}

View file

@ -1,5 +1,5 @@
import { getScreenRoot, getApplications, Process } from "./kernel.mjs";
import { showNotification } from "../scripts/notification.js";
import { getScreenRoot, getApplications, Process } from "../kernel.mjs";
import { showNotification } from "../../scripts/notification.js";
export function notify(title, text, time) {
showNotification(title, text, time);
@ -9,14 +9,14 @@ function runApp(name) {
let launched = false;
getApplications().forEach(app => {
if (app.name == name) {
new Process(app);
app.bootstrap();
launched = true;
}
})
if (!launched) alert("Not found.");
}
function createShell() {
export default function createShell(p) {
const bar = document.createElement('div');
bar.classList.add("kumosBar");
@ -30,7 +30,4 @@ function createShell() {
bar.appendChild(runButton);
getScreenRoot().appendChild(bar);
}
createShell();
showNotification("KumOS Shell", "Welcome to KumOS, everything is work-in-progress! Try running apps to see available packages.", 10000);
}

View file

@ -0,0 +1,5 @@
import login from "../login.mjs";
export default (p) => {
p.child("login", login);
}

View file

@ -1172,67 +1172,6 @@ header div:first-child {
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 */
@keyframes ellipsis-loader {

View file

@ -1,16 +1,19 @@
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
const body = document.querySelector('body');
const elements = document.querySelectorAll('[data-tip]');
const hint = document.querySelector("#headerSubtitle");
const hintPanelDefaultText = hint.innerHTML;
const hintPanelDefaultText = hint ? hint.innerHTML : null;
let fixedHint;
let currentObserver;
elements.forEach(el => {
registerElementHint(el);
})
if (hint) {
const elements = document.querySelectorAll('[data-tip]');
elements.forEach(el => {
registerElementHint(el);
});
}
function cleanup() {
if (!hint) return;
hint.innerHTML = hintPanelDefaultText;
hint.classList.remove('fixed');
if (fixedHint) {