From 1b91eacb5ba2805d26004af1c4abca9d682b4a2d Mon Sep 17 00:00:00 2001 From: Myx Date: Mon, 27 Apr 2026 03:02:13 +0200 Subject: [PATCH] feat: Theme studio v2 --- package-lock.json | 26 + package.json | 2 + .../chat-messages.component.html | 11 +- .../chat-messages/chat-messages.component.ts | 34 +- .../chat-message-composer.component.html | 13 +- .../chat-message-composer.component.ts | 10 +- .../chat-message-item.component.html | 34 +- .../chat-message-item.component.ts | 65 +-- .../chat-message-list.component.html | 11 +- .../chat-message-list.component.ts | 23 +- .../feature/dm-chat/dm-chat.component.html | 21 +- .../feature/dm-chat/dm-chat.component.ts | 50 +- .../dm-workspace/dm-workspace.component.html | 16 +- .../dm-workspace/dm-workspace.component.ts | 2 +- .../services/element-picker.service.ts | 9 +- .../services/layout-sync.service.ts | 43 +- .../services/theme.service.spec.ts | 489 ++++++++++++++++ .../application/services/theme.service.ts | 238 ++++++-- .../constants/theme-llm-guide.constants.ts | 32 +- .../domain/logic/theme-defaults.logic.ts | 230 ++------ .../domain/logic/theme-registry.logic.ts | 526 +++++++++++++++++- .../theme/domain/logic/theme-schema.logic.ts | 36 +- .../domain/logic/theme-validation.logic.ts | 133 +++-- .../theme/domain/models/theme.model.ts | 3 +- .../theme-grid-editor.component.html | 11 +- .../theme-grid-editor.component.scss | 16 +- .../theme-grid-editor.component.ts | 77 ++- .../theme-json-code-editor.component.ts | 228 +++++--- .../theme-json-format.logic.spec.ts | 24 + .../theme-json-format.logic.ts | 13 + .../theme-settings.component.html | 163 ++++-- .../theme-settings.component.scss | 106 ++++ .../theme-settings.component.ts | 358 +++++++++++- .../theme/feature/theme-node.directive.ts | 4 +- .../theme-style-application.logic.spec.ts | 56 ++ .../feature/theme-style-application.logic.ts | 14 + .../voice-controls.component.html | 15 +- .../voice-controls.component.ts | 18 +- .../rooms-side-panel.component.html | 18 +- .../rooms-side-panel.component.ts | 14 +- .../servers-rail/servers-rail.component.html | 7 +- .../servers-rail/servers-rail.component.ts | 178 +++--- .../settings-modal.component.html | 16 +- .../settings-modal.component.ts | 123 ++-- .../confirm-dialog.component.html | 1 + .../confirm-dialog.component.ts | 2 + .../context-menu/context-menu.component.html | 1 + .../context-menu/context-menu.component.ts | 2 + .../profile-card/profile-card.component.html | 11 +- .../profile-card/profile-card.component.ts | 77 +-- .../screen-share-source-picker.component.html | 2 + .../screen-share-source-picker.component.ts | 24 +- 52 files changed, 2792 insertions(+), 844 deletions(-) create mode 100644 toju-app/src/app/domains/theme/application/services/theme.service.spec.ts create mode 100644 toju-app/src/app/domains/theme/feature/settings/theme-json-code-editor/theme-json-format.logic.spec.ts create mode 100644 toju-app/src/app/domains/theme/feature/settings/theme-json-code-editor/theme-json-format.logic.ts create mode 100644 toju-app/src/app/domains/theme/feature/theme-style-application.logic.spec.ts create mode 100644 toju-app/src/app/domains/theme/feature/theme-style-application.logic.ts diff --git a/package-lock.json b/package-lock.json index 6ef57c5..6047d28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,10 @@ "@angular/platform-browser": "^21.0.0", "@angular/router": "^21.0.0", "@codemirror/commands": "^6.10.3", + "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-json": "^6.0.2", "@codemirror/language": "^6.12.3", + "@codemirror/lint": "^6.9.5", "@codemirror/state": "^6.6.0", "@codemirror/theme-one-dark": "^6.1.3", "@codemirror/view": "^6.41.0", @@ -2731,6 +2733,19 @@ "@lezer/common": "^1.1.0" } }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, "node_modules/@codemirror/lang-json": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", @@ -5791,6 +5806,17 @@ "integrity": "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==", "license": "MIT" }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, "node_modules/@lezer/highlight": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", diff --git a/package.json b/package.json index 811786a..4809d11 100644 --- a/package.json +++ b/package.json @@ -65,8 +65,10 @@ "@angular/platform-browser": "^21.0.0", "@angular/router": "^21.0.0", "@codemirror/commands": "^6.10.3", + "@codemirror/lang-css": "^6.3.1", "@codemirror/lang-json": "^6.0.2", "@codemirror/language": "^6.12.3", + "@codemirror/lint": "^6.9.5", "@codemirror/state": "^6.6.0", "@codemirror/theme-one-dark": "^6.1.3", "@codemirror/view": "^6.41.0", diff --git a/toju-app/src/app/domains/chat/feature/chat-messages/chat-messages.component.html b/toju-app/src/app/domains/chat/feature/chat-messages/chat-messages.component.html index 7014f6d..eff42d5 100644 --- a/toju-app/src/app/domains/chat/feature/chat-messages/chat-messages.component.html +++ b/toju-app/src/app/domains/chat/feature/chat-messages/chat-messages.component.html @@ -1,4 +1,7 @@ -
+
-
+
- message.roomId === roomId && - (message.channelId || 'general') === channelId - ); + return this.allMessages().filter((message) => message.roomId === roomId && (message.channelId || 'general') === channelId); }); - readonly conversationKey = computed( - () => `${this.currentRoom()?.id ?? 'no-room'}:${this.activeChannelId() ?? 'general'}` - ); + readonly conversationKey = computed(() => `${this.currentRoom()?.id ?? 'no-room'}:${this.activeChannelId() ?? 'general'}`); readonly klipyEnabled = computed(() => this.klipy.isEnabled(this.currentRoom())); readonly composerBottomPadding = signal(140); readonly klipyGifPickerAnchorRight = signal(16); @@ -176,9 +172,7 @@ export class ChatMessagesComponent { if (!message || !currentUserId) return; - const hasReacted = message.reactions.some( - (reaction) => reaction.emoji === event.emoji && reaction.userId === currentUserId - ); + const hasReacted = message.reactions.some((reaction) => reaction.emoji === event.emoji && reaction.userId === currentUserId); if (hasReacted) { this.store.dispatch( @@ -243,9 +237,7 @@ export class ChatMessagesComponent { const minRight = 16; const maxRight = Math.max(minRight, viewportWidth - popupWidth - 16); - this.klipyGifPickerAnchorRight.set( - Math.min(Math.max(Math.round(preferredRight), minRight), maxRight) - ); + this.klipyGifPickerAnchorRight.set(Math.min(Math.max(Math.round(preferredRight), minRight), maxRight)); } private getKlipyGifPickerWidth(viewportWidth: number): number { @@ -290,10 +282,7 @@ export class ChatMessagesComponent { if (blob) { try { - const result = await electronApi.saveFileAs( - attachment.filename, - await this.blobToBase64(blob) - ); + const result = await electronApi.saveFileAs(attachment.filename, await this.blobToBase64(blob)); if (result.saved || result.cancelled) return; @@ -416,12 +405,7 @@ export class ChatMessagesComponent { const message = [...this.channelMessages()] .reverse() - .find( - (entry) => - entry.senderId === currentUserId && - entry.content === content && - !entry.isDeleted - ); + .find((entry) => entry.senderId === currentUserId && entry.content === content && !entry.isDeleted); if (!message) { setTimeout(() => this.attachFilesToLastOwnMessage(content, pendingFiles), 150); diff --git a/toju-app/src/app/domains/chat/feature/chat-messages/components/message-composer/chat-message-composer.component.html b/toju-app/src/app/domains/chat/feature/chat-messages/components/message-composer/chat-message-composer.component.html index 324d41a..81e0655 100644 --- a/toju-app/src/app/domains/chat/feature/chat-messages/components/message-composer/chat-message-composer.component.html +++ b/toju-app/src/app/domains/chat/feature/chat-messages/components/message-composer/chat-message-composer.component.html @@ -1,7 +1,13 @@ -
+
@if (replyTo()) { -
+
+ + + + + } + + +
+ + +
@@ -222,7 +272,7 @@ } -
+

Explorer

@@ -240,7 +290,7 @@ />
-
+
@for (entry of filteredEntries(); track entry.key) { + +
+
- + @if (activeEditorTab() === 'json') { + + } @else { + + }
} @@ -370,7 +467,7 @@
-

Schema Hints

+

Editable Attributes