From 6f14c3646443af311307dba0a5b95dd73b1e34d8 Mon Sep 17 00:00:00 2001 From: Blockyheadman <80011716+Blockyheadman@users.noreply.github.com> Date: Fri, 14 Aug 2026 00:19:04 -0500 Subject: [PATCH 1/5] implement very tacky draggable tskbar icons --- .../shell/Shell/Taskbar/OpenedApps.svelte | 122 +++++++++++++++++- .../components/shell/taskbar/openedapps.css | 20 ++- 2 files changed, 133 insertions(+), 9 deletions(-) diff --git a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte index 88f21176..71be9e82 100755 --- a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte +++ b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte @@ -3,17 +3,131 @@ import { Daemon, Stack } from "$ts/env"; import { ProcessesHelper } from "$ts/helpers/processes"; import { isPopulatable } from "$ts/util/apps"; + import { draggable, type DragOptions } from "@neodrag/svelte"; import OpenedApp from "./OpenedApps/OpenedApp.svelte"; + import { Store } from "$ts/writable"; + import type { IProcess } from "$interfaces/IProcess"; + import { flip } from "svelte/animate"; const { process }: { process: IShellRuntime } = $props(); const { userPreferences } = process; const { store } = Stack; + + let positions = Store>(new Map()); + let tabs = Store>(new Map()); + store() + .entries() + .forEach((v, i) => { + tabs().set(v[0], v[1]); + }); + + store.subscribe((v) => { + if (tabs().size === v.size) return; + + // process has been killed + if (v.size < tabs().size) { + tabs.set( + new Map( + [...tabs().entries()].filter(([pid]) => { + return v.keys().toArray().includes(pid); + }) + ) + ); + + positions.set( + new Map( + [...positions().entries()].filter(([pid]) => { + return v.keys().toArray().includes(pid); + }) + ) + ); + } else { + v.entries().forEach(([pid, process]) => { + if (!tabs().keys().toArray().includes(pid)) { + tabs().set(pid, process); + tabs.set(new Map(tabs())); + + positions().set(pid, { x: 0, y: 0 }); + positions.set(new Map(positions())); + } + }); + } + + // console.log("proc list:", tabs()); + // console.log("pos list: ", positions()); + }); + + function getPos(pid: number) { + if (!positions().has(pid)) { + positions().set(pid, { x: 0, y: 0 }); + } + return positions().get(pid)!; + }
- {#each [...$store] as [pid, openedProcess] (pid)} - {#if ProcessesHelper.IsAnyGraphicalAppProcess(openedProcess) && !openedProcess._disposed && (isPopulatable(openedProcess.app.data) || openedProcess.overridePopulatable) && (!$userPreferences.shell.taskbar.openedAppsPerWorkspace || Daemon?.workspaces?.getDesktopIndexByUuid(openedProcess.app.desktop || "") === $userPreferences.workspaces.index)} - - {/if} + {#each [...$tabs] as [pid, openedProcess] (pid)} +
= 0 ? Math.floor(iconDragDist) : Math.ceil(iconDragDist); + const iconGridDragDist = + Math.abs(iconDragDist) - Math.abs(iconDragDistRounded) >= movementActuationDistance + ? iconDragDist < 0 + ? iconDragDistRounded - 1 + : iconDragDistRounded + 1 + : iconDragDistRounded; + + // console.log("data.offsetX: ", data.offsetX); + // console.log("button width: ", iconButton.offsetWidth); + // console.log("total movement: ", iconDragDist); + // console.log("total movement (rounded):", iconDragDistRounded); + // console.log("total icon space moves: ", iconGridDragDist); + + const currentEntryIdx = $tabs + .keys() + .toArray() + .findIndex((val) => { + return val === pid; + }); + + const currentEntry = $tabs.entries().toArray().at(currentEntryIdx); + + // console.log("currentEntryIdx:", currentEntryIdx); + // console.log("currentEntry: ", currentEntry); + + if (!currentEntry) return; + + // begin repositioning + + const entries = [...$tabs]; + entries.splice(currentEntryIdx, 1); + entries.splice(currentEntryIdx + iconGridDragDist, 0, currentEntry); + tabs.set(new Map(entries)); + + $positions.set(pid, { x: 0, y: 0 }); + + // console.log(tabs()); + }, + }} + > + {#if ProcessesHelper.IsAnyGraphicalAppProcess(openedProcess) && !openedProcess._disposed && (isPopulatable(openedProcess.app.data) || openedProcess.overridePopulatable) && (!$userPreferences.shell.taskbar.openedAppsPerWorkspace || Daemon?.workspaces?.getDesktopIndexByUuid(openedProcess.app.desktop || "") === $userPreferences.workspaces.index)} + + {/if} +
{/each}
diff --git a/src/css/apps/components/shell/taskbar/openedapps.css b/src/css/apps/components/shell/taskbar/openedapps.css index 9cc5f083..bb6cdf92 100755 --- a/src/css/apps/components/shell/taskbar/openedapps.css +++ b/src/css/apps/components/shell/taskbar/openedapps.css @@ -15,8 +15,16 @@ div.shell div.taskbar div.opened-apps::-webkit-scrollbar { width: 1px; } -#arcShell div.shell div.taskbar div.opened-apps button { +#arcShell div.shell div.taskbar div.opened-apps div.drag-container { display: inline-flex; + + &:not(:has(> button)) { + display: none; + } +} + +#arcShell div.shell div.taskbar div.opened-apps button { + display: flex; max-width: 180px; align-items: center; gap: 10px; @@ -52,7 +60,7 @@ div.shell div.taskbar div.opened-apps::-webkit-scrollbar { transform-origin: left; } -#arcShell div.shell div.taskbar div.opened-apps button.iconic.closing + button { +#arcShell div.shell div.taskbar div.opened-apps button.iconic.closing+button { margin-left: -40px; transition: margin-left 0.3s, @@ -71,7 +79,7 @@ div.shell div.taskbar div.opened-apps::-webkit-scrollbar { white-space: nowrap; } -#arcShell div.shell div.taskbar div.opened-apps button + button { +#arcShell div.shell div.taskbar div.opened-apps div:has(button)+div:has(button) { margin-left: 5px; } @@ -104,10 +112,12 @@ div.shell div.taskbar div.opened-apps button:hover img.backdrop { #arcShell div.shell div.taskbar button.start-button.active { background-color: var(--button-glass-active-bg); } + #arcShell div.shell div.taskbar div.opened-apps button { outline: var(--shell-component-outline) 1px solid !important; outline-offset: -1px; } + div.shell div.taskbar div.opened-apps button.active img.backdrop { opacity: 0.5; filter: brightness(1.3) blur(7px); @@ -122,7 +132,7 @@ div.shell div.taskbar div.opened-apps button.active img.backdrop { opacity: 0.7; } -#arcShell > div.body div.taskbar button.opened-app.blinking { +#arcShell>div.body div.taskbar button.opened-app.blinking { animation: blinking 0.7s infinite alternate; } @@ -130,4 +140,4 @@ div.shell div.taskbar div.opened-apps button.active img.backdrop { to { background-color: var(--clr-orange-fg); } -} +} \ No newline at end of file From 72b78bdd75459ee2baf6f8a6ce145f4488f1b7c9 Mon Sep 17 00:00:00 2001 From: Blockyheadman <80011716+Blockyheadman@users.noreply.github.com> Date: Fri, 14 Aug 2026 00:24:15 -0500 Subject: [PATCH 2/5] only process items that should show up --- .../shell/Shell/Taskbar/OpenedApps.svelte | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte index 71be9e82..051e4e6e 100755 --- a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte +++ b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte @@ -13,12 +13,24 @@ const { userPreferences } = process; const { store } = Stack; + function shouldShow(openedProcess: IProcess) { + return ( + ProcessesHelper.IsAnyGraphicalAppProcess(openedProcess) && + !openedProcess._disposed && + (isPopulatable(openedProcess.app.data) || openedProcess.overridePopulatable) && + (!$userPreferences.shell.taskbar.openedAppsPerWorkspace || + Daemon?.workspaces?.getDesktopIndexByUuid(openedProcess.app.desktop || "") === $userPreferences.workspaces.index) + ); + } + let positions = Store>(new Map()); let tabs = Store>(new Map()); store() .entries() - .forEach((v, i) => { - tabs().set(v[0], v[1]); + .forEach(([pid, process]) => { + if (shouldShow(process)) { + tabs().set(pid, process); + } }); store.subscribe((v) => { @@ -43,7 +55,7 @@ ); } else { v.entries().forEach(([pid, process]) => { - if (!tabs().keys().toArray().includes(pid)) { + if (!tabs().keys().toArray().includes(pid) && shouldShow(process)) { tabs().set(pid, process); tabs.set(new Map(tabs())); @@ -125,9 +137,7 @@ }, }} > - {#if ProcessesHelper.IsAnyGraphicalAppProcess(openedProcess) && !openedProcess._disposed && (isPopulatable(openedProcess.app.data) || openedProcess.overridePopulatable) && (!$userPreferences.shell.taskbar.openedAppsPerWorkspace || Daemon?.workspaces?.getDesktopIndexByUuid(openedProcess.app.desktop || "") === $userPreferences.workspaces.index)} - - {/if} + {/each} From 404fc4e46ab34f11d44dd61824af8c5e2bc1182d Mon Sep 17 00:00:00 2001 From: Blockyheadman <80011716+Blockyheadman@users.noreply.github.com> Date: Fri, 14 Aug 2026 00:37:37 -0500 Subject: [PATCH 3/5] fix kill all bug where buttons wouldn't disappear --- .../shell/Shell/Taskbar/OpenedApps.svelte | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte index 051e4e6e..23599a04 100755 --- a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte +++ b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte @@ -36,34 +36,35 @@ store.subscribe((v) => { if (tabs().size === v.size) return; - // process has been killed - if (v.size < tabs().size) { - tabs.set( - new Map( - [...tabs().entries()].filter(([pid]) => { - return v.keys().toArray().includes(pid); - }) - ) - ); - - positions.set( - new Map( - [...positions().entries()].filter(([pid]) => { - return v.keys().toArray().includes(pid); - }) - ) - ); - } else { - v.entries().forEach(([pid, process]) => { - if (!tabs().keys().toArray().includes(pid) && shouldShow(process)) { - tabs().set(pid, process); - tabs.set(new Map(tabs())); - - positions().set(pid, { x: 0, y: 0 }); - positions.set(new Map(positions())); - } - }); - } + // add new processes + + v.entries().forEach(([pid, process]) => { + if (!tabs().keys().toArray().includes(pid) && shouldShow(process)) { + tabs().set(pid, process); + tabs.set(new Map(tabs())); + + positions().set(pid, { x: 0, y: 0 }); + positions.set(new Map(positions())); + } + }); + + // remove old processes + + tabs.set( + new Map( + [...tabs().entries()].filter(([pid]) => { + return v.keys().toArray().includes(pid); + }) + ) + ); + + positions.set( + new Map( + [...positions().entries()].filter(([pid]) => { + return v.keys().toArray().includes(pid); + }) + ) + ); // console.log("proc list:", tabs()); // console.log("pos list: ", positions()); From 5f0e08283ae3ac88d447ba22860e13a3b8857849 Mon Sep 17 00:00:00 2001 From: Blockyheadman <80011716+Blockyheadman@users.noreply.github.com> Date: Fri, 14 Aug 2026 21:20:09 -0500 Subject: [PATCH 4/5] remove unnecessary css --- src/css/apps/components/shell/taskbar/openedapps.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/css/apps/components/shell/taskbar/openedapps.css b/src/css/apps/components/shell/taskbar/openedapps.css index bb6cdf92..eba4e594 100755 --- a/src/css/apps/components/shell/taskbar/openedapps.css +++ b/src/css/apps/components/shell/taskbar/openedapps.css @@ -17,10 +17,6 @@ div.shell div.taskbar div.opened-apps::-webkit-scrollbar { #arcShell div.shell div.taskbar div.opened-apps div.drag-container { display: inline-flex; - - &:not(:has(> button)) { - display: none; - } } #arcShell div.shell div.taskbar div.opened-apps button { From e3055a842d50bc66597e73d039a9a4e9d3d48fe0 Mon Sep 17 00:00:00 2001 From: Blockyheadman <80011716+Blockyheadman@users.noreply.github.com> Date: Fri, 14 Aug 2026 22:00:26 -0500 Subject: [PATCH 5/5] change to use `$state` instead of `Store` --- .../shell/Shell/Taskbar/OpenedApps.svelte | 80 +++++++------------ 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte index 23599a04..6ca94df0 100755 --- a/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte +++ b/src/apps/components/shell/Shell/Taskbar/OpenedApps.svelte @@ -3,9 +3,8 @@ import { Daemon, Stack } from "$ts/env"; import { ProcessesHelper } from "$ts/helpers/processes"; import { isPopulatable } from "$ts/util/apps"; - import { draggable, type DragOptions } from "@neodrag/svelte"; + import { draggable } from "@neodrag/svelte"; import OpenedApp from "./OpenedApps/OpenedApp.svelte"; - import { Store } from "$ts/writable"; import type { IProcess } from "$interfaces/IProcess"; import { flip } from "svelte/animate"; @@ -23,63 +22,56 @@ ); } - let positions = Store>(new Map()); - let tabs = Store>(new Map()); + let positions = $state>(new Map()); + let tabs = $state>(new Map()); + + // get any exisiting processes + // just in case store() .entries() .forEach(([pid, process]) => { if (shouldShow(process)) { - tabs().set(pid, process); + tabs.set(pid, process); } }); store.subscribe((v) => { - if (tabs().size === v.size) return; + if (tabs.size === v.size) return; // add new processes v.entries().forEach(([pid, process]) => { - if (!tabs().keys().toArray().includes(pid) && shouldShow(process)) { - tabs().set(pid, process); - tabs.set(new Map(tabs())); - - positions().set(pid, { x: 0, y: 0 }); - positions.set(new Map(positions())); + if (!tabs.keys().toArray().includes(pid) && shouldShow(process)) { + tabs.set(pid, process); + positions.set(pid, { x: 0, y: 0 }); } }); - // remove old processes + // remove dead processes - tabs.set( - new Map( - [...tabs().entries()].filter(([pid]) => { - return v.keys().toArray().includes(pid); - }) - ) + tabs = new Map( + [...tabs.entries()].filter(([pid]) => { + return v.keys().toArray().includes(pid); + }) ); - positions.set( - new Map( - [...positions().entries()].filter(([pid]) => { - return v.keys().toArray().includes(pid); - }) - ) + positions = new Map( + [...positions.entries()].filter(([pid]) => { + return v.keys().toArray().includes(pid); + }) ); - - // console.log("proc list:", tabs()); - // console.log("pos list: ", positions()); }); function getPos(pid: number) { - if (!positions().has(pid)) { - positions().set(pid, { x: 0, y: 0 }); + if (!positions.has(pid)) { + positions.set(pid, { x: 0, y: 0 }); } - return positions().get(pid)!; + return positions.get(pid)!; }
- {#each [...$tabs] as [pid, openedProcess] (pid)} + {#each [...tabs] as [pid, openedProcess] (pid)}
{ return val === pid; }); - const currentEntry = $tabs.entries().toArray().at(currentEntryIdx); - - // console.log("currentEntryIdx:", currentEntryIdx); - // console.log("currentEntry: ", currentEntry); - + const currentEntry = tabs.entries().toArray().at(currentEntryIdx); if (!currentEntry) return; // begin repositioning - const entries = [...$tabs]; + const entries = [...tabs]; entries.splice(currentEntryIdx, 1); entries.splice(currentEntryIdx + iconGridDragDist, 0, currentEntry); - tabs.set(new Map(entries)); - - $positions.set(pid, { x: 0, y: 0 }); + tabs = new Map(entries); - // console.log(tabs()); + // force reset position so it's not visually offset + positions.set(pid, { x: 0, y: 0 }); }, }} >