From 162ec5322f43a323ecf48363ec3ec8c8e2cddc94 Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Sat, 20 Jun 2026 01:06:46 +0200 Subject: [PATCH] csdfsdf --- docs/ANLEITUNG.md | 87 +++++++++++++ docs/CONTENT.md | 129 +++++++++++++++++++ docs/README.md | 31 ++++- docs/WEITERENTWICKLUNG.md | 71 +++++++++++ modules/README.md | 9 ++ partials/desktop/shell.php | 56 ++++++--- public/assets/desktop/desktop.css | 202 +++++++++++++++++++++++------- public/assets/desktop/desktop.js | 191 +++++++++++++++++----------- skins/README.md | 9 ++ 9 files changed, 643 insertions(+), 142 deletions(-) create mode 100644 docs/ANLEITUNG.md create mode 100644 docs/CONTENT.md create mode 100644 docs/WEITERENTWICKLUNG.md diff --git a/docs/ANLEITUNG.md b/docs/ANLEITUNG.md new file mode 100644 index 00000000..03ce8ec8 --- /dev/null +++ b/docs/ANLEITUNG.md @@ -0,0 +1,87 @@ +# Anleitung + +Nutzungs- und Hilfedatei fuer `desktop.kusche.berlin`. + +Diese Datei ist fuer spaetere Endnutzerhilfe, interne Einfuehrung und als Basis fuer einen Hilfebereich gedacht. + +## Einstieg + +Der Desktop besteht aus mehreren Hauptbereichen: + +- `Desktop` + Arbeitsflaeche mit Icons, Fenstern und Infobereich. + +- `Startmenue` + Zugang zu Benutzerfunktionen und installierten Programmen. + +- `Infobereich` + Rechter Seitenbereich fuer eingeblendete Informationskarten. + +- `Widget-Bereich` + Bereich bei Uhr und Systemleiste fuer kleine Mini-Funktionen. + +## Startmenue verwenden + +Das Startmenue ist in drei Bereiche gegliedert: + +1. `User Setting Bereich` + Hier befinden sich Benutzername, User-Icon, Einstellungen sowie Anmelden oder Abmelden. +2. `Funktion-Bereich` + Hier werden die Funktionsgruppen ausgewaehlt. Aktuell ist `Programme` die erste Gruppe. +3. `Auswahlbereich` + Hier erscheinen die Inhalte der aktuell gewaehlten Funktionsgruppe, zum Beispiel installierte Apps. + +## Programme oeffnen + +- Desktop-Icons koennen direkt geoeffnet werden. +- Im Startmenue lassen sich Programme ueber den `Auswahlbereich` starten. +- Fenster koennen verschoben, minimiert, maximiert und geschlossen werden. + +## Einstellungen oeffnen + +Die Einstellungen werden aktuell ueber die App `User Self Management` bereitgestellt. + +Dort koennen derzeit insbesondere verwaltet werden: + +- `Desktop Type` beziehungsweise Skin-Auswahl +- persoenliche Benutzerdaten +- sichtbare Apps +- Inhalte des `Infobereichs` + +## Benutzerdaten + +Aktuell gelten folgende Regeln: + +- Standardfelder wie Name, E-Mail, Telefon, Titel und Ort koennen fuer LDAP vorbereitet oder synchronisiert werden. +- `Geburtsdatum` bleibt derzeit lokal gespeichert. +- nicht jedes Profilfeld wird automatisch in LDAP geschrieben. + +## Desktop Type und Skins + +Das System unterstuetzt derzeit: + +- `Apple` +- `Windows` +- `Linux` + +Der ausgewaehlte Desktop Type beeinflusst Darstellung und Interaktionsdetails, waehrend die gemeinsame Shell-Logik erhalten bleibt. + +## Infobereich + +Der `Infobereich` ist der rechte Desktopbereich. + +- Inhalte koennen benutzerbezogen ein- oder ausgeblendet werden. +- Aenderungen sollen gespeichert bleiben. +- Der `Infobereich` ist nicht identisch mit dem `Widget-Bereich`. + +## Begriffsregel + +Fuer sprachliche Konsistenz gilt: + +- rechte Desktopseite: `Infobereich` +- Mini-Apps an Uhr/Systemleiste: `Widget-Bereich` +- linke Startmenuespalte: `User Setting Bereich` +- mittlere Startmenuespalte: `Funktion-Bereich` +- rechte Startmenuespalte: `Auswahlbereich` + +Die verbindliche zentrale Fassung der Begriffe steht in [CONTENT.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/CONTENT.md). diff --git a/docs/CONTENT.md b/docs/CONTENT.md new file mode 100644 index 00000000..63377151 --- /dev/null +++ b/docs/CONTENT.md @@ -0,0 +1,129 @@ +# Content + +Zentrale Inhaltsbasis fuer `desktop.kusche.berlin`. + +Diese Datei dient als gemeinsame Quelle fuer: + +- Begriffe und offizielle Benennungen im System +- Funktionsbeschreibung des aktuellen Systems +- spaetere Inhalte fuer einen Hilfe-Bereich +- zentrale Zusammenfassung der dezentralen `README.md`-Dateien + +## Zweck + +`CONTENT.md` beschreibt das System fachlich und sprachlich. + +Nicht hier hinein gehoeren: + +- technische Detailanweisungen fuer Entwickler +- Go- und NoGo-Regeln fuer Umsetzung +- nur ordnerspezifische Detailerklaerungen ohne Relevanz fuer das Gesamtsystem + +Diese Inhalte liegen in: + +- [ANLEITUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/ANLEITUNG.md) +- [WEITERENTWICKLUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/WEITERENTWICKLUNG.md) + +## Offizielle Begriffe + +Diese Benennungen gelten projektweit und sollen in UI, Doku und Weiterentwicklung konsistent verwendet werden. + +### Oberflaechenbereiche + +- `Desktop` + Die eigentliche Arbeitsflaeche mit Icons, Fenstern, Taskbar und Infobereich. + +- `Infobereich` + Der rechte Bereich auf dem Desktop mit eingeblendeten Informationskarten oder kleinen Bereichsmodulen. + +- `Widget-Bereich` + Der Bereich bei der Uhr bzw. Systemleiste fuer kleine Widgets oder Mini-Apps. + +- `Setup-Bereich` + Der zentrale Einstellungsbereich fuer Benutzer, Desktop-Typ, Apps und Bereichsauswahl. Aktuell umgesetzt ueber `User Self Management`. + +### Menue-Bereiche + +- `User Setting Bereich` + Linke Menuespalte mit User-Icon, Benutzername, Einstieg in Einstellungen und Session-Aktion. + +- `Funktion-Bereich` + Mittlere Menuespalte mit Funktionsgruppen wie `Programme`. + +- `Auswahlbereich` + Rechte Menuespalte mit den Inhalten der aktuell gewaehlten Funktionsgruppe. + +### Systemobjekte + +- `App` + Ein bereitgestelltes System-Tool oder Modul. Eine App kann als Desktop-App, Menue-App, Systembar-Eintrag oder Quelle fuer Widgets/Funktionen auftreten. + +- `Widget` + Eine kleine Funktion oder Mini-Anzeige. Widgets sind nicht automatisch identisch mit Apps. Eine App kann Widgets bereitstellen, muss es aber nicht. + +- `Desktop Type` + Benutzerseitige Auswahl des Desktop-/Skin-Typs. Aktuell vorgesehen: `Apple`, `Windows`, `Linux`. + +- `Skin` + Technische und visuelle Auspraegung eines Desktop-Typs, inklusive Layout, Interaktionsdetails und Asset-Zuordnung. + +## Aktueller Systemumfang + +Stand dieser Datei: + +- gemeinsame Desktop-Shell mit den Skins `Apple`, `Windows` und `Linux` +- frei verschiebbare Desktop-Icons +- Icon-Positionen lokal gespeichert, pro Benutzer und pro Skin +- automatische Schriftfarbanpassung fuer Desktop-Icons anhand des Hintergrunds +- Fensterverwaltung mit Oeffnen, Fokussieren, Minimieren, Maximieren und Verschieben +- konsistentes Standard-Design fuer Fensterinhalte, sofern eine App kein eigenes UI mitbringt +- Startmenue mit `User Setting Bereich`, `Funktion-Bereich` und `Auswahlbereich` +- rechter `Infobereich` mit benutzerbezogener Sichtbarkeit +- `User Self Management` als Setup-App +- lokale Benutzereinstellungen fuer Desktop-Skin, App-Auswahl, Infobereich und Profildaten +- LDAP-Synchronisierung fuer Standardfelder wie Name, E-Mail, Telefon, Titel und Ort +- `Geburtsdatum` aktuell bewusst nur lokal gespeichert +- Keycloak bleibt das Auth-System + +## Zentrale Inhaltszusammenfassung aus bestehenden README-Dateien + +### Globales Projekt + +Aus [README.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/README.md): + +- `public/` ist der Web-Root fuer die Desktop-Shell +- `src/Desktop/` enthaelt zentrale Desktop-Mechaniken +- `partials/desktop/` enthaelt Shell-Templates +- `modules/` bleibt Zielort fuer klassische Module +- `temp/nexus-module-import/` ist Rohbasis fuer importierte Nexus-Module +- Keycloak bleibt das Auth-System + +### Module + +Aus [modules/README.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/modules/README.md): + +- klassische Module bleiben unter `modules//` +- Businesslogik wird nicht in den Desktop-Core verschoben + +### Skins + +Aus [skins/README.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/skins/README.md): + +- `skins//profile.php` enthaelt Skin-Metadaten +- `skins//vendor/` enthaelt Rohquellen und Quellpacks +- `public/assets/desktop/skins//` enthaelt auslieferbare CSS/JS-Dateien +- `public/assets/desktop/skin-icons//` enthaelt verwendete Web-Icons + +## Hilfe-Bereich Vorbereitung + +Fuer einen spaeteren Hilfebereich sollen Inhalte aus dieser Datei in Themenblcke uebernommen werden: + +- `Begriffe` +- `Desktop bedienen` +- `Menue verstehen` +- `Fenster verwenden` +- `Infobereich konfigurieren` +- `Apps und Desktop Type verwalten` +- `Benutzerdaten und Synchronisierung` + +Die Inhalte sollen spaeter moeglichst nicht neu erfunden, sondern aus den zentral gepflegten Dateien abgeleitet werden. diff --git a/docs/README.md b/docs/README.md index 041aa02b..6477bdaf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,18 +1,39 @@ # desktop.kusche.berlin -V1-Scaffold fuer die neue Desktop-Oberflaeche von Kusche.Berlin. +Zentraler Dokumentationsindex fuer das Projekt. -## Struktur +## Zentrale Dateien + +- [CONTENT.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/CONTENT.md) + Zentrale Inhaltsbasis mit offiziellen Begriffen, Systemumfang und spaeterer Hilfe-Basis. + +- [ANLEITUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/ANLEITUNG.md) + Nutzungs- und Hilfedatei fuer Bedienung, Orientierung und spaetere Hilfebereiche. + +- [WEITERENTWICKLUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/WEITERENTWICKLUNG.md) + Regeln fuer Weiterentwicklung, Doku-Pflege, Go's und NoGo's. + +## Technische Projektstruktur - `public/` Web-Root mit Desktop-Shell auf `/` -- `api/desktop.php` JSON-Payload fuer die Shell - `src/Desktop/` zentrale Desktop-Mechaniken - `partials/desktop/` Shell-Template - `modules/` Zielort fuer klassische Module - `temp/nexus-module-import/` Rohbasis fuer importierte Nexus-Module -## Hinweise +## Fachliche Hinweise - `Old-Nexus/` wird nicht technisch eingebunden. - Skins `Windows`, `Apple`, `Linux` laufen auf einer gemeinsamen Shell. -- Keycloak bleibt das Auth-System; der Theme-Handoff ist in `docs/keycloak-theme-handoff.md` beschrieben. +- Keycloak bleibt das Auth-System. +- der Theme-Handoff ist in [keycloak-theme-handoff.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/keycloak-theme-handoff.md) beschrieben. + +## Dokumentationsregel + +Wichtige Informationen duerfen nicht nur in Unterordnern oder Einzeldateien stehen. + +Es gilt: + +- wichtige Inhalte aus Unterordner-`README.md`-Dateien werden zentral in `docs/CONTENT.md` gespiegelt +- Nutzungswissen wird in `docs/ANLEITUNG.md` gepflegt +- Entwicklungsregeln werden in `docs/WEITERENTWICKLUNG.md` gepflegt diff --git a/docs/WEITERENTWICKLUNG.md b/docs/WEITERENTWICKLUNG.md new file mode 100644 index 00000000..de342082 --- /dev/null +++ b/docs/WEITERENTWICKLUNG.md @@ -0,0 +1,71 @@ +# Weiterentwicklung + +Zentrale Arbeits- und Regeldatei fuer die Weiterentwicklung von `desktop.kusche.berlin`. + +Diese Datei enthaelt: + +- Go's und NoGo's +- Dokumentationsregeln +- Architektur- und Pflegehinweise + +## Dokumentationspflicht + +Die Projektdokumentation wird zentral und dezentral gleichzeitig gepflegt. + +Verbindlich ist: + +- zentrale Inhalte und Begriffe muessen in [CONTENT.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/CONTENT.md) gepflegt werden +- Nutzungs- und Hilfetexte muessen in [ANLEITUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/ANLEITUNG.md) gepflegt werden +- Entwicklungsregeln muessen in dieser Datei gepflegt werden +- vorhandene `README.md`-Dateien in Unterordnern muessen weiter gepflegt werden +- wichtige Informationen aus den einzelnen `README.md`-Dateien muessen auch zentral gehalten werden +- bei neuen wichtigen Unterordnern ist zu pruefen, ob eine eigene `README.md` noetig ist + +## Go's + +- Desktop-Mechaniken zentral halten, nicht pro App duplizieren +- Fensterverhalten konsistent halten +- gemeinsame Standards fuer Fensterinhalte nutzen, sofern eine App kein bewusst eigenes UI benoetigt +- Begriffe in UI und Doku konsistent nach `CONTENT.md` verwenden +- Apps als bereitgestellte Systemfunktionen denken, nicht nur als sichtbare Fenster +- Unterschiede zwischen `App`, `Infobereich` und `Widget-Bereich` sauber trennen +- lokale Persistenz und spaetere Backend-Synchronisierung getrennt vorbereiten +- `README.md`-Dateien in Teilbereichen aktuell halten +- zentrale Doku bei jeder relevanten Struktur- oder Begriffsanpassung mitpflegen + +## NoGo's + +- keine stillen Umbenennungen von Bereichen ohne Aktualisierung der zentralen Doku +- keine Rueckbauten bestehender Desktop-Mechaniken ohne ausdrueckliche Entscheidung +- keine Vermischung von Modul-Businesslogik mit globalem Desktop-Core +- keine Skin-Sonderlogik direkt in einzelnen Apps, wenn sie global loesbar ist +- keine nur lokalen README-Informationen ohne zentrale Uebernahme der wichtigen Punkte +- keine Hilfeinhalte nur in Chatverlaeufen oder Ad-hoc-Notizen belassen +- keine produktive Architekturabhaengigkeit zu `Old-Nexus/` oder vergleichbaren Altbestaenden + +## Architekturregeln + +- `modules//` bleibt Ort fuer klassische Module +- globale Desktop-Mechaniken liegen im gemeinsamen Kern +- Skins definieren Darstellung und Interaktionsdetails, nicht die Fachlogik +- Hilfe- und Inhaltsdateien sollen spaeter maschinenlesbar oder zumindest klar strukturierbar in einen Hilfebereich ueberfuehrt werden koennen + +## Pflegeprozess + +Bei jeder groesseren Aenderung ist zu pruefen: + +1. Wurden offizielle Begriffe geaendert oder erweitert +2. Wurde der Systemumfang sichtbar erweitert +3. Braucht ein Unterordner eine gepflegte `README.md` +4. Muessen zentrale Dateien angepasst werden +5. Ist der Inhalt spaeter fuer einen Hilfebereich relevant + +## Aktuell wichtige Projektregeln + +- `UMSETZUNGSSTATUS.md` nur dann als erledigt markieren, wenn es ausdruecklich freigegeben wurde +- Fokus liegt aktuell auf Desktop-UI und Apps +- Login und Keycloak sind vorerst akzeptiert und nicht der aktuelle Hauptschwerpunkt +- Desktop-Icons sind frei verschiebbar und werden pro Benutzer und Skin lokal gespeichert +- die Schriftfarbe von Desktop-Icons passt sich automatisch an den Hintergrund an +- Benutzerdaten sollen spaeter sauber in LDAP oder Keycloak geschrieben werden +- Standard-Fensterinhalte sollen ein gemeinsames Design nutzen diff --git a/modules/README.md b/modules/README.md index 0e42ae10..d51ed468 100644 --- a/modules/README.md +++ b/modules/README.md @@ -3,3 +3,12 @@ Klassische Module bleiben in diesem Projekt unter `modules//`. Die neue Desktop-Shell ist nur die UI-Schicht. Modul-Businesslogik wird nicht in den Desktop-Core verschoben. + +## Pflegehinweis + +Diese Datei muss gepflegt bleiben, wenn sich Modulstruktur oder Modulregeln aendern. + +Wichtige Inhalte aus dieser Datei muessen ebenfalls zentral gepflegt werden in: + +- [CONTENT.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/CONTENT.md) +- [WEITERENTWICKLUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/WEITERENTWICKLUNG.md) diff --git a/partials/desktop/shell.php b/partials/desktop/shell.php index 40fd9b1c..0cc5a929 100644 --- a/partials/desktop/shell.php +++ b/partials/desktop/shell.php @@ -100,27 +100,45 @@ $renderStartIcon = static function (array $profile): string {
diff --git a/public/assets/desktop/desktop.css b/public/assets/desktop/desktop.css index 8a069c66..52bf8b22 100644 --- a/public/assets/desktop/desktop.css +++ b/public/assets/desktop/desktop.css @@ -953,16 +953,18 @@ h1 { bottom: calc(var(--taskbar-height) + 28px); z-index: 130; display: grid; - align-content: start; - grid-template-columns: minmax(240px, 280px) minmax(280px, 360px); - gap: 16px; - width: min(720px, calc(100% - 48px)); - padding: 18px; - border-radius: 24px; - background: rgba(15, 23, 42, 0.82); - border: 1px solid var(--shell-border); - box-shadow: var(--shadow); - backdrop-filter: blur(24px); + align-content: stretch; + grid-template-columns: minmax(220px, 250px) minmax(180px, 220px) minmax(320px, 1fr); + gap: 0; + width: min(920px, calc(100% - 48px)); + min-height: 560px; + padding: 0; + border-radius: 22px; + background: rgba(28, 28, 32, 0.96); + border: 1px solid rgba(255, 255, 255, 0.08); + box-shadow: 0 24px 60px rgba(15, 23, 42, 0.42); + overflow: hidden; + backdrop-filter: blur(18px); } .start-menu::before { @@ -977,59 +979,159 @@ h1 { display: none !important; } -.start-menu-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; - grid-column: 1 / -1; - padding-bottom: 10px; - border-bottom: 1px solid rgba(255, 255, 255, 0.08); -} - -.start-menu-header h2 { - margin-bottom: 0; -} - -.start-menu-column, -.start-menu-block { +.start-menu-user-settings, +.start-menu-function-area, +.start-menu-selection-area { display: grid; - gap: 12px; -} - -.start-menu-column { align-content: start; } +.start-menu-user-settings { + grid-template-rows: auto auto 1fr auto; + gap: 16px; + padding: 20px 16px 16px; + background: linear-gradient(180deg, rgba(45, 45, 52, 0.98), rgba(32, 32, 38, 0.98)); + border-right: 1px solid rgba(255, 255, 255, 0.06); +} + +.start-menu-function-area { + gap: 14px; + padding: 20px 14px; + background: rgba(36, 36, 42, 0.98); + border-right: 1px solid rgba(255, 255, 255, 0.06); +} + +.start-menu-selection-area { + gap: 14px; + padding: 20px 16px; + background: linear-gradient(180deg, rgba(40, 40, 46, 0.98), rgba(33, 33, 38, 0.98)); +} + +.start-menu-section-title { + font-size: 12px; + font-weight: 700; + letter-spacing: 0.12em; + text-transform: uppercase; + color: rgba(248, 250, 252, 0.66); +} + +.start-menu-settings-button, +.start-menu-user-card, +.start-menu-session-action, +.start-menu-function, .start-menu-entry { display: grid; - grid-template-columns: 44px minmax(0, 1fr) auto; + grid-template-columns: 44px minmax(0, 1fr); align-items: center; gap: 12px; width: 100%; padding: 12px 14px; - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 18px; - background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 16px; + background: rgba(255, 255, 255, 0.04); color: inherit; text-align: left; cursor: pointer; + font: inherit; + text-decoration: none; + transition: background-color 140ms ease, border-color 140ms ease, transform 140ms ease; } -.start-menu-entry:hover { - background: rgba(255, 255, 255, 0.18); +.start-menu-settings-button:hover, +.start-menu-user-card:hover, +.start-menu-session-action:hover, +.start-menu-function:hover, +.start-menu-entry:hover, +.start-menu-function.is-active { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.12); } +.start-menu-function.is-active { + transform: translateX(2px); +} + +.start-menu-settings-icon, +.start-menu-function-icon, +.start-menu-session-icon, +.start-menu-entry-badge, +.start-menu-user-avatar { + display: inline-grid; + place-items: center; + width: 36px; + height: 36px; + border-radius: 12px; + background: rgba(255, 255, 255, 0.08); + font-size: 16px; + font-weight: 700; +} + +.start-menu-user-card { + grid-template-columns: 56px minmax(0, 1fr); + align-items: center; + padding: 16px; +} + +.start-menu-user-avatar { + width: 48px; + height: 48px; + border-radius: 16px; + background: linear-gradient(135deg, #60a5fa, #2563eb); + color: #eff6ff; + font-size: 15px; + letter-spacing: 0.04em; +} + +.start-menu-user-copy, +.start-menu-function-copy { + display: grid; + gap: 4px; + min-width: 0; +} + +.start-menu-user-copy strong, +.start-menu-function-copy strong, .start-menu-entry strong, -.start-menu-entry span { +.start-menu-entry span, +.start-menu-session-action span { display: block; } +.start-menu-user-copy small, +.start-menu-function-copy small, .start-menu-entry small { - opacity: 0.7; + color: rgba(248, 250, 252, 0.66); +} + +.start-menu-function-list, +.start-menu-selection-list { + display: grid; + gap: 10px; + align-content: start; +} + +.start-menu-selection-list { + max-height: 520px; + padding-right: 4px; + overflow: auto; + scrollbar-width: thin; + scrollbar-color: rgba(255, 255, 255, 0.18) transparent; +} + +.start-menu-selection-list::-webkit-scrollbar { + width: 8px; +} + +.start-menu-selection-list::-webkit-scrollbar-thumb { + border-radius: 999px; + background: rgba(255, 255, 255, 0.16); +} + +.start-menu-entry { + grid-template-columns: 44px minmax(0, 1fr) auto; + background: rgba(255, 255, 255, 0.05); } -.start-menu-entry-badge, .start-menu-entry-toggle { display: inline-grid; place-items: center; @@ -1041,9 +1143,18 @@ h1 { font-weight: 700; } -.start-menu-entry-toggle.is-active { - background: var(--accent); - color: #0f172a; +.start-menu-session-action { + margin-top: auto; +} + +.start-menu-session-action.is-logout .start-menu-session-icon { + background: rgba(220, 38, 38, 0.2); + color: #fca5a5; +} + +.start-menu-session-action.is-logout:hover { + background: rgba(220, 38, 38, 0.12); + border-color: rgba(220, 38, 38, 0.22); } .taskbar-apps { @@ -1204,9 +1315,16 @@ h1 { bottom: 88px; transform: none; width: auto; + min-height: 0; grid-template-columns: 1fr; } + .start-menu-user-settings, + .start-menu-function-area { + border-right: 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + } + .window-layer { position: static; inset: auto; diff --git a/public/assets/desktop/desktop.js b/public/assets/desktop/desktop.js index d43633cd..e354884a 100644 --- a/public/assets/desktop/desktop.js +++ b/public/assets/desktop/desktop.js @@ -10,8 +10,12 @@ if (payloadNode) { const startButton = document.getElementById('start-button'); const startMenu = document.getElementById('start-menu'); const startMenuApps = document.getElementById('start-menu-apps'); - const startMenuWidgets = document.getElementById('start-menu-widgets'); - const startMenuActions = document.getElementById('start-menu-actions'); + const startMenuFunctions = document.getElementById('start-menu-functions'); + const startMenuSettingsButton = document.getElementById('start-menu-settings-button'); + const startMenuUserCard = document.getElementById('start-menu-user-card'); + const startMenuUserName = document.getElementById('start-menu-user-name'); + const startMenuUserAvatar = document.getElementById('start-menu-user-avatar'); + const startMenuSessionAction = document.getElementById('start-menu-session-action'); const accountMenu = document.getElementById('tray-account-menu'); const clockNode = document.getElementById('clock'); const clockTopNode = document.getElementById('clock-top'); @@ -30,6 +34,7 @@ if (payloadNode) { let sideDesktopInset = 0; let bottomDesktopInset = 120; let iconContextMenu = null; + let activeFunctionArea = 'programs'; const windowControlsMode = document.body.dataset.windowControls || 'windows'; let wallpaperImagePromise = null; @@ -169,15 +174,35 @@ if (payloadNode) { const updateSessionDisplay = () => { const accountNode = document.querySelector('.tray-pill[data-tray-id="account"]'); - if (!accountNode) { - return; - } - const displayName = currentUserPreferences?.profile?.name || payload.session?.display_name; - if (typeof displayName === 'string' && displayName.trim() !== '') { + if (accountNode && typeof displayName === 'string' && displayName.trim() !== '') { accountNode.textContent = displayName; } + + if (startMenuUserName && typeof displayName === 'string' && displayName.trim() !== '') { + startMenuUserName.textContent = displayName; + } + + if (startMenuUserAvatar) { + startMenuUserAvatar.textContent = buildInitials(displayName); + } + }; + + const buildInitials = (value) => { + const normalized = typeof value === 'string' ? value.trim() : ''; + + if (normalized === '') { + return 'GU'; + } + + const parts = normalized.split(/\s+/).filter(Boolean); + + if (parts.length === 1) { + return parts[0].slice(0, 2).toUpperCase(); + } + + return `${parts[0][0] || ''}${parts[1][0] || ''}`.toUpperCase(); }; const setAccountMenuOpen = (isOpen) => { @@ -1137,45 +1162,45 @@ if (payloadNode) { }); }; - const renderMenuWidgets = () => { - if (!startMenuWidgets) { + const renderFunctionArea = () => { + if (!startMenuFunctions) { return; } - startMenuWidgets.innerHTML = ''; + startMenuFunctions.querySelectorAll('[data-function-id]').forEach((button) => { + const isActive = button instanceof HTMLElement && button.dataset.functionId === activeFunctionArea; + button.classList.toggle('is-active', isActive); + }); + }; - payload.widgets.registry.forEach((widget) => { + const renderSelectionArea = () => { + if (!startMenuApps) { + return; + } + + startMenuApps.innerHTML = ''; + + if (activeFunctionArea !== 'programs') { + return; + } + + payload.apps.forEach((app) => { const button = document.createElement('button'); button.type = 'button'; - button.className = 'start-menu-entry'; + button.className = 'start-menu-entry start-menu-entry--app'; button.innerHTML = ` - ${widget.icon || 'WG'} + ${buildAppIconMarkup(app, 'start-menu-app-icon')} - ${widget.title} - ${widget.summary || ''} - - - ${activeWidgets.has(widget.widget_id) ? 'On' : 'Off'} + ${app.title} + ${app.summary || ''} + Open `; button.addEventListener('click', () => { - if (activeWidgets.has(widget.widget_id)) { - activeWidgets.delete(widget.widget_id); - } else { - activeWidgets.add(widget.widget_id); - } - - renderWidgets(); - renderMenuWidgets(); - persistSettingsPatch({ - widgets: { - active_ids: Array.from(activeWidgets), - }, - }).catch(() => { - // Keep current desktop state even if persistence fails. - }); + openApp(app); + closeStartMenu(); }); - startMenuWidgets.appendChild(button); + startMenuApps.appendChild(button); }); }; @@ -1193,6 +1218,7 @@ if (payloadNode) { const publicDashboard = findAppById('public-dashboard'); if (publicDashboard) { openApp(publicDashboard); + closeStartMenu(); } return; } @@ -1206,7 +1232,7 @@ if (payloadNode) { } renderWidgets(); - renderMenuWidgets(); + renderStartMenu(); persistSettingsPatch({ widgets: { active_ids: Array.from(activeWidgets), @@ -1218,49 +1244,12 @@ if (payloadNode) { }; const renderStartMenu = () => { - if (!startMenuApps || !startMenuActions) { + if (!startMenuApps) { return; } - startMenuApps.innerHTML = ''; - startMenuActions.innerHTML = ''; - - payload.apps.forEach((app) => { - const button = document.createElement('button'); - button.type = 'button'; - button.className = 'start-menu-entry'; - button.innerHTML = ` - ${buildAppIconMarkup(app, 'start-menu-app-icon')} - - ${app.title} - ${app.summary || ''} - - Open - `; - button.addEventListener('click', () => { - openApp(app); - closeStartMenu(); - }); - startMenuApps.appendChild(button); - }); - - payload.menu.quick_actions.forEach((action) => { - const button = document.createElement('button'); - button.type = 'button'; - button.className = 'start-menu-entry'; - button.innerHTML = ` - QA - - ${action.label} - ${action.description} - - Run - `; - button.addEventListener('click', () => runQuickAction(action.action_id)); - startMenuActions.appendChild(button); - }); - - renderMenuWidgets(); + renderFunctionArea(); + renderSelectionArea(); }; payload.apps.forEach((app) => { @@ -1357,6 +1346,56 @@ if (payloadNode) { } }); + startMenuSettingsButton?.addEventListener('click', () => { + openAccountSettings(); + }); + + startMenuUserCard?.addEventListener('click', () => { + openAccountSettings(); + }); + + startMenuSessionAction?.addEventListener('click', (event) => { + const target = event.currentTarget; + + if (!(target instanceof HTMLElement) || target.dataset.sessionAction !== 'login') { + return; + } + + event.preventDefault(); + const loginApp = findAppById('desktop-login'); + if (loginApp) { + openApp(loginApp); + } + closeStartMenu(); + }); + + startMenuFunctions?.addEventListener('click', (event) => { + const target = event.target instanceof Element ? event.target.closest('[data-function-id]') : null; + + if (!(target instanceof HTMLElement)) { + return; + } + + activeFunctionArea = target.dataset.functionId || 'programs'; + renderStartMenu(); + }); + + startMenuFunctions?.addEventListener('mouseover', (event) => { + const target = event.target instanceof Element ? event.target.closest('[data-function-id]') : null; + + if (!(target instanceof HTMLElement)) { + return; + } + + const nextFunctionArea = target.dataset.functionId || 'programs'; + if (nextFunctionArea === activeFunctionArea) { + return; + } + + activeFunctionArea = nextFunctionArea; + renderStartMenu(); + }); + window.addEventListener('desktop:user-settings-updated', (event) => { const preferences = event.detail?.preferences; const requiresReload = Boolean(event.detail?.requiresReload); @@ -1371,8 +1410,8 @@ if (payloadNode) { activeWidgets.clear(); nextWidgetIds.forEach((widgetId) => activeWidgets.add(widgetId)); renderWidgets(); - renderMenuWidgets(); updateSessionDisplay(); + renderStartMenu(); } if (requiresReload) { diff --git a/skins/README.md b/skins/README.md index ca46f6ac..c6837960 100644 --- a/skins/README.md +++ b/skins/README.md @@ -10,3 +10,12 @@ Grundsatz: - `public/assets/desktop/skin-icons//` enthaelt nur die aktuell im Frontend verwendeten Web-Icons. Damit bleiben Skin-Quellen ausserhalb des Webroots, waehrend die benoetigten Laufzeit-Assets weiter direkt vom Browser geladen werden koennen. + +## Pflegehinweis + +Diese Datei muss gepflegt bleiben, wenn sich Skin-Struktur, Asset-Fluss oder Ablageregeln aendern. + +Wichtige Inhalte aus dieser Datei muessen ebenfalls zentral gepflegt werden in: + +- [CONTENT.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/CONTENT.md) +- [WEITERENTWICKLUNG.md](/home/lars/Schreibtisch/Projekte/desktop.kusche.berlin/docs/WEITERENTWICKLUNG.md)