A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: windows 98!

+267 -40
+20 -16
_config.ts
··· 30 30 31 31 // CSS 32 32 33 - site.use(postcss({ includes: false })); 33 + site.use(postcss()); 34 34 site.add([".css"]); 35 35 36 + site.remoteFile( 37 + "styles/vendor/98.css", 38 + import.meta.resolve("./node_modules/98.css/dist/98.css"), 39 + ); 40 + 36 41 // BINARY ASSETS 37 42 38 43 site.add("/favicons"); 39 44 site.add("/fonts"); 40 45 site.add("/images"); 41 46 47 + site.remoteFile( 48 + "fonts/ms_sans_serif.woff2", 49 + import.meta.resolve( 50 + "./node_modules/98.css/fonts/converted/ms_sans_serif.woff2", 51 + ), 52 + ); 53 + 54 + site.remoteFile( 55 + "fonts/ms_sans_serif_bold.woff2", 56 + import.meta.resolve( 57 + "./node_modules/98.css/fonts/converted/ms_sans_serif_bold.woff2", 58 + ), 59 + ); 60 + 42 61 // MISC 43 62 44 63 site.use(sourceMaps()); 45 - 46 - // SCRIPTS 47 64 48 65 site.script("copy-type-defs", () => { 49 66 for ( ··· 59 76 } 60 77 }); 61 78 62 - site.script("copy-win98-fonts", () => { 63 - Deno.copyFileSync( 64 - "./node_modules/98.css/fonts/converted/ms_sans_serif.woff2", 65 - "./_site/fonts/ms_sans_serif.woff2", 66 - ); 67 - 68 - Deno.copyFileSync( 69 - "./node_modules/98.css/fonts/converted/ms_sans_serif_bold.woff2", 70 - "./_site/fonts/ms_sans_serif_bold.woff2", 71 - ); 72 - }); 73 - 74 79 site.addEventListener("afterBuild", () => { 75 80 // site.run("copy-type-defs"); 76 - site.run("copy-win98-fonts"); 77 81 });
+4 -1
src/component/constituent/blur/browser-list/element.js
··· 58 58 // REGISTER 59 59 //////////////////////////////////////////// 60 60 61 - customElements.define("dcb-browser-list", BrowserList); 61 + export const CLASS = BrowserList; 62 + export const NAME = "dcb-browser-list"; 63 + 64 + customElements.define(NAME, BrowserList);
+1 -1
src/index.vto
··· 12 12 title: "Queue" 13 13 14 14 --- 15 - <link rel="stylesheet" href="./styles/page/index.css" /> 15 + <link rel="stylesheet" href="index.css" /> 16 16 17 17 <header> 18 18 <h1>
-1
src/styles/icons/iconoir.css
··· 1 - @import "iconoir/css/iconoir.css";
-1
src/styles/icons/phosphor.css
··· 1 - @import "@phosphor-icons/fill/style.css";
+2 -2
src/styles/page/index.css src/index.css
··· 1 - @import "../diffuse/colors.css"; 2 - @import "../diffuse/fonts.css"; 1 + @import "./styles/diffuse/colors.css"; 2 + @import "./styles/diffuse/fonts.css"; 3 3 4 4 body { 5 5 background-color: var(--bg-color);
+2 -2
src/styles/theme/blur/index.css src/theme/blur/index.css
··· 1 1 @import "./variables.css"; 2 - @import "../../diffuse/colors.css"; 3 - @import "../../diffuse/fonts.css"; 2 + @import "../../styles/diffuse/colors.css"; 3 + @import "../../styles/diffuse/fonts.css"; 4 4 5 5 /*********************************** 6 6 * Base
src/styles/theme/blur/variables.css src/theme/blur/variables.css
+10 -5
src/styles/theme/webamp/index.css src/theme/webamp/index.css
··· 1 + /*********************************** 2 + * Fonts 3 + ***********************************/ 4 + 1 5 @font-face { 2 6 font-family: "Pixelated MS Sans Serif"; 3 7 src: url("/fonts/ms_sans_serif.woff2") format("woff2"); ··· 11 15 font-weight: 700; 12 16 font-style: normal; 13 17 } 18 + 19 + /*********************************** 20 + * 🪟 21 + ***********************************/ 14 22 15 23 body { 16 24 background: #3a6ea5; ··· 20 28 margin: 12px; 21 29 } 22 30 23 - main { 24 - } 25 - 26 - iframe { 27 - display: none; 31 + #webamp { 32 + isolation: isolate; 28 33 } 29 34 30 35 /***********************************
+1 -1
src/theme/blur/index.vto
··· 1 1 <!doctype html> 2 2 <html> 3 3 <head> 4 - <link rel="stylesheet" href="../../styles/theme/blur/index.css" /> 4 + <link rel="stylesheet" href="index.css" /> 5 5 </head> 6 6 <body> 7 7 <!-- UI -->
+1
src/theme/webamp/README.md
··· 1 + Components must have [98.css](https://jdan.github.io/98.css/) loaded.
+1
src/theme/webamp/browser/element.js
··· 1 + import { DiffuseElement } from "@common/element.js";
+8 -2
src/theme/webamp/index.js
··· 1 1 import Webamp from "webamp/lazy"; 2 2 import deepDiff from "@fry69/deep-diff"; 3 3 4 - import "@component/orchestrator/process-tracks/element.js"; 4 + // import "@component/orchestrator/process-tracks/element.js"; 5 5 import "@component/orchestrator/queue-tracks/element.js"; 6 6 import "@component/output/indexed-db/element.js"; 7 7 import "@component/processor/metadata/element.js"; ··· 11 11 12 12 import { component } from "@common/element.js"; 13 13 import { effect, signal, untracked } from "@common/signal.js"; 14 + 15 + import "./window/element.js"; 16 + import "./window-manager/element.js"; 14 17 15 18 /** 16 19 * @import {URLTrack} from "webamp" ··· 48 51 }, 49 52 }); 50 53 51 - // Override 54 + // Override track loader 52 55 const loadFromUrl = amp.media.loadFromUrl.bind(amp.media); 53 56 54 57 /** ··· 62 65 } 63 66 64 67 amp.media.loadFromUrl = loadOverride.bind(amp.media); 68 + 69 + // TODO: Handle minimize 70 + amp.onMinimize(() => {}); 65 71 66 72 // Render 67 73 const ampNode = document.createElement("div");
+20 -8
src/theme/webamp/index.vto
··· 5 5 6 6 <title>Diffuse</title> 7 7 8 - <link href="/styles/theme/webamp/index.css" rel="stylesheet" /> 8 + <link href="index.css" rel="stylesheet" /> 9 9 </head> 10 10 <body> 11 11 <!-- ··· 14 14 15 15 --> 16 16 <main> 17 - <div class="desktop"> 17 + <section class="desktop"> 18 18 <!-- INPUT --> 19 - <!--<a href="/configurator/input/" target="_blank" class="button desktop__item"> 19 + <a href="/configurator/input/" target="_blank" class="button desktop__item"> 20 20 <img src="/images/icons/windows_98/cd_audio_cd_a-4.png" width="32" /> 21 21 <label>Manage audio inputs</label> 22 - </a>--> 22 + </a> 23 23 24 24 <!-- OUTPUT --> 25 - <!--<a href="/configurator/output/" target="_blank" class="button desktop__item"> 25 + <a href="/configurator/output/" target="_blank" class="button desktop__item"> 26 26 <img src="/images/icons/windows_98/directory_open_file_mydocs_2k-2.png" width="32" /> 27 27 <label>Manage user data</label> 28 - </a>--> 28 + </a> 29 29 30 30 <!-- BROWSE --> 31 31 <!-- TODO --> 32 - </div> 32 + </section> 33 + <section class="windows"> 34 + <dtw-window-manager> 35 + <dtw-window> 36 + <span slot="title">Window</span> 37 + <p>👀</p> 38 + </dtw-window> 39 + <dtw-window> 40 + <span slot="title">Window</span> 41 + <p>👀</p> 42 + </dtw-window> 43 + </dtw-window-manager> 44 + </section> 33 45 </main> 34 46 35 47 <!-- ··· 62 74 SCRIPTS 63 75 64 76 --> 65 - <script src="/theme/webamp/index.js" type="module"></script> 77 + <script src="index.js" type="module"></script> 66 78 </body> 67 79 </html>
+98
src/theme/webamp/window-manager/element.js
··· 1 + import { DiffuseElement } from "@common/element.js"; 2 + import { signal } from "@common/signal.js"; 3 + 4 + /** 5 + * @import {RenderArg} from "@common/element.d.ts" 6 + * @import WindowElement from "../window/element.js"; 7 + */ 8 + 9 + //////////////////////////////////////////// 10 + // ELEMENT 11 + //////////////////////////////////////////// 12 + 13 + class WindowManager extends DiffuseElement { 14 + constructor() { 15 + super(); 16 + this.attachShadow({ mode: "open" }); 17 + } 18 + 19 + // SIGNALS 20 + 21 + $activeWindow = signal(/** @type {string | null} */ (null)); 22 + 23 + // LIFECYCLE 24 + 25 + /** 26 + * @override 27 + */ 28 + connectedCallback() { 29 + super.connectedCallback(); 30 + 31 + this.addEventListener("click", this.setActiveWindow); 32 + 33 + this.effect(() => { 34 + const activeId = this.$activeWindow.value; 35 + this.setWindowStatuses(activeId); 36 + }); 37 + } 38 + 39 + /** 40 + * @override 41 + */ 42 + disconnectedCallback() { 43 + super.disconnectedCallback(); 44 + this.removeEventListener("click", this.setActiveWindow); 45 + } 46 + 47 + /** 48 + * @param {string | null} activeId 49 + */ 50 + async setWindowStatuses(activeId) { 51 + await customElements.whenDefined("dtw-window"); 52 + 53 + this.querySelectorAll("dtw-window").forEach( 54 + (window) => { 55 + const win = /** @type {WindowElement} */ (window); 56 + 57 + if (activeId && window.id === activeId) { 58 + win.activate(); 59 + } else { 60 + win.deactivate(); 61 + } 62 + }, 63 + ); 64 + } 65 + 66 + /** 67 + * @param {Event} event 68 + */ 69 + setActiveWindow(event) { 70 + if (event.target instanceof HTMLElement) { 71 + const window = event.target?.closest("dtw-window"); 72 + if (!window) return; 73 + if (window.id) this.$activeWindow.value = window.id; 74 + } 75 + } 76 + 77 + // RENDER 78 + 79 + /** 80 + * @param {RenderArg} _ 81 + */ 82 + render({ html }) { 83 + return html` 84 + <slot></slot> 85 + `; 86 + } 87 + } 88 + 89 + export default WindowManager; 90 + 91 + //////////////////////////////////////////// 92 + // REGISTER 93 + //////////////////////////////////////////// 94 + 95 + export const CLASS = WindowManager; 96 + export const NAME = "dtw-window-manager"; 97 + 98 + customElements.define(NAME, WindowManager);
+99
src/theme/webamp/window/element.js
··· 1 + import { DiffuseElement } from "@common/element.js"; 2 + 3 + /** 4 + * @import {RenderArg} from "@common/element.d.ts" 5 + */ 6 + 7 + //////////////////////////////////////////// 8 + // ELEMENT 9 + //////////////////////////////////////////// 10 + 11 + class WindowElement extends DiffuseElement { 12 + constructor() { 13 + super(); 14 + 15 + this.id = this.id?.length ? this.id : crypto.randomUUID(); 16 + this.attachShadow({ mode: "open" }); 17 + } 18 + 19 + // LIFECYCLE 20 + 21 + /** 22 + * @override 23 + */ 24 + connectedCallback() { 25 + super.connectedCallback(); 26 + 27 + const x = Math.floor( 28 + Math.random() * (document.body.clientWidth - 300), 29 + ); 30 + 31 + this.style.position = "relative"; 32 + this.style.left = `${x}px`; 33 + } 34 + 35 + /** 36 + * @override 37 + */ 38 + disconnectedCallback() { 39 + super.disconnectedCallback(); 40 + } 41 + 42 + // ACTIONS 43 + 44 + activate() { 45 + this.shadowRoot?.querySelector(".title-bar")?.classList.remove("inactive"); 46 + } 47 + 48 + deactivate() { 49 + this.shadowRoot?.querySelector(".title-bar")?.classList.add("inactive"); 50 + } 51 + 52 + // RENDER 53 + 54 + /** 55 + * @param {RenderArg} _ 56 + */ 57 + render({ html }) { 58 + return html` 59 + <link rel="stylesheet" href="/styles/vendor/98.css" /> 60 + 61 + <style> 62 + dialog { 63 + background: transparent; 64 + border: 0; 65 + padding: 0; 66 + } 67 + </style> 68 + 69 + <dialog open> 70 + <div class="window" style="width: 300px"> 71 + <div class="title-bar"> 72 + <div class="title-bar-text"> 73 + <slot name="title"></slot> 74 + </div> 75 + <div class="title-bar-controls"> 76 + <!--<button aria-label="Minimize"></button>--> 77 + <!--<button aria-label="Maximize"></button>--> 78 + <button aria-label="Close"></button> 79 + </div> 80 + </div> 81 + <div class="window-body"> 82 + <slot></slot> 83 + </div> 84 + </div> 85 + </dialog> 86 + `; 87 + } 88 + } 89 + 90 + export default WindowElement; 91 + 92 + //////////////////////////////////////////// 93 + // REGISTER 94 + //////////////////////////////////////////// 95 + 96 + export const CLASS = WindowElement; 97 + export const NAME = "dtw-window"; 98 + 99 + customElements.define(NAME, WindowElement);