refactor: stricter domain: chat

This commit is contained in:
2026-04-11 14:01:19 +02:00
parent 39b85e2e3a
commit 98ed8eeb68
16 changed files with 34 additions and 29 deletions

View File

@@ -7,9 +7,12 @@ Text messaging, reactions, GIF search, typing indicators, and the user list. All
```
chat/
├── application/
│ └── klipy.service.ts GIF search via the KLIPY API (proxied through the server)
│ └── services/
│ ├── klipy.service.ts GIF search via the KLIPY API (proxied through the server)
│ └── link-metadata.service.ts Link preview metadata fetching
├── domain/
│ └── rules/
│ ├── message.rules.ts canEditMessage, normaliseDeletedMessage, getMessageTimestamp
│ └── message-sync.rules.ts Inventory-based sync: chunkArray, findMissingIds, limits
@@ -25,6 +28,7 @@ chat/
│ │ └── services/
│ │ └── chat-markdown.service.ts Markdown-to-HTML rendering
│ │
│ ├── chat-image-proxy-fallback.directive.ts Image proxy fallback for broken URLs
│ ├── klipy-gif-picker/ GIF search/browse picker panel
│ ├── typing-indicator/ "X is typing..." display (3 s TTL, max 4 names)
│ └── user-list/ Online user sidebar
@@ -129,7 +133,7 @@ graph LR
Klipy --> API
click Picker "feature/klipy-gif-picker/" "GIF search panel" _blank
click Klipy "application/klipy.service.ts" "GIF search via KLIPY API" _blank
click Klipy "application/services/klipy.service.ts" "GIF search via KLIPY API" _blank
click SD "../server-directory/application/server-directory.facade.ts" "Resolves API base URL" _blank
```

View File

@@ -13,7 +13,7 @@ import {
throwError
} from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { ServerDirectoryFacade } from '../../server-directory';
import { ServerDirectoryFacade } from '../../../server-directory';
export interface KlipyGif {
id: string;

View File

@@ -1,8 +1,8 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
import { ServerDirectoryFacade } from '../../server-directory';
import { LinkMetadata } from '../../../shared-kernel';
import { ServerDirectoryFacade } from '../../../server-directory';
import { LinkMetadata } from '../../../../shared-kernel';
const URL_PATTERN = /https?:\/\/[^\s<>)"']+/g;

View File

@@ -1,4 +1,4 @@
import { DELETED_MESSAGE_CONTENT, type Message } from '../../../shared-kernel';
import { DELETED_MESSAGE_CONTENT, type Message } from '../../../../shared-kernel';
/** Extracts the effective timestamp from a message (editedAt takes priority). */
export function getMessageTimestamp(msg: Message): number {

View File

@@ -7,7 +7,7 @@ import {
input,
signal
} from '@angular/core';
import { KlipyService } from '../application/klipy.service';
import { KlipyService } from '../application/services/klipy.service';
@Directive({
selector: 'img[appChatImageProxyFallback]',

View File

@@ -11,7 +11,7 @@ import { Store } from '@ngrx/store';
import { ElectronBridgeService } from '../../../../core/platform/electron/electron-bridge.service';
import { RealtimeSessionFacade } from '../../../../core/realtime';
import { Attachment, AttachmentFacade } from '../../../attachment';
import { KlipyGif } from '../../application/klipy.service';
import { KlipyGif } from '../../application/services/klipy.service';
import { MessagesActions } from '../../../../store/messages/messages.actions';
import {
selectAllMessages,
@@ -33,7 +33,7 @@ import {
ChatMessageImageContextMenuEvent,
ChatMessageReactionEvent,
ChatMessageReplyEvent
} from './models/chat-messages.models';
} from './models/chat-messages.model';
@Component({
selector: 'app-chat-messages',

View File

@@ -21,12 +21,12 @@ import {
} from '@ng-icons/lucide';
import type { ClipboardFilePayload } from '../../../../../../core/platform/electron/electron-api.models';
import { ElectronBridgeService } from '../../../../../../core/platform/electron/electron-bridge.service';
import { KlipyGif, KlipyService } from '../../../../application/klipy.service';
import { KlipyGif, KlipyService } from '../../../../application/services/klipy.service';
import { Message } from '../../../../../../shared-kernel';
import { ChatImageProxyFallbackDirective } from '../../../chat-image-proxy-fallback.directive';
import { TypingIndicatorComponent } from '../../../typing-indicator/typing-indicator.component';
import { ChatMarkdownService } from '../../services/chat-markdown.service';
import { ChatMessageComposerSubmitEvent } from '../../models/chat-messages.models';
import { ChatMessageComposerSubmitEvent } from '../../models/chat-messages.model';
type LocalFileWithPath = File & {
path?: string;

View File

@@ -29,7 +29,7 @@ import {
AttachmentFacade,
MAX_AUTO_SAVE_SIZE_BYTES
} from '../../../../../attachment';
import { KlipyService } from '../../../../application/klipy.service';
import { KlipyService } from '../../../../application/services/klipy.service';
import { DELETED_MESSAGE_CONTENT, Message } from '../../../../../../shared-kernel';
import {
ChatAudioPlayerComponent,
@@ -45,7 +45,7 @@ import {
ChatMessageImageContextMenuEvent,
ChatMessageReactionEvent,
ChatMessageReplyEvent
} from '../../models/chat-messages.models';
} from '../../models/chat-messages.model';
const COMMON_EMOJIS = [
'👍',

View File

@@ -13,7 +13,7 @@ import {
signal
} from '@angular/core';
import { Attachment } from '../../../../../attachment';
import { getMessageTimestamp } from '../../../../domain/message.rules';
import { getMessageTimestamp } from '../../../../domain/rules/message.rules';
import { Message } from '../../../../../../shared-kernel';
import {
ChatMessageDeleteEvent,
@@ -22,7 +22,7 @@ import {
ChatMessageImageContextMenuEvent,
ChatMessageReactionEvent,
ChatMessageReplyEvent
} from '../../models/chat-messages.models';
} from '../../models/chat-messages.model';
import { ChatMessageItemComponent } from '../message-item/chat-message-item.component';
interface PrismGlobal {

View File

@@ -12,7 +12,7 @@ import {
} from '@ng-icons/lucide';
import { Attachment } from '../../../../../attachment';
import { ContextMenuComponent } from '../../../../../../shared';
import { ChatMessageImageContextMenuEvent } from '../../models/chat-messages.models';
import { ChatMessageImageContextMenuEvent } from '../../models/chat-messages.model';
@Component({
selector: 'app-chat-message-overlays',

View File

@@ -20,7 +20,7 @@ import {
lucideSearch,
lucideX
} from '@ng-icons/lucide';
import { KlipyGif, KlipyService } from '../../application/klipy.service';
import { KlipyGif, KlipyService } from '../../application/services/klipy.service';
import { ChatImageProxyFallbackDirective } from '../chat-image-proxy-fallback.directive';
const KLIPY_CARD_MIN_WIDTH = 140;

View File

@@ -1,6 +1,7 @@
export * from './application/klipy.service';
export * from './domain/message.rules';
export * from './domain/message-sync.rules';
export * from './application/services/klipy.service';
export * from './application/services/link-metadata.service';
export * from './domain/rules/message.rules';
export * from './domain/rules/message-sync.rules';
export { ChatMessagesComponent } from './feature/chat-messages/chat-messages.component';
export { TypingIndicatorComponent } from './feature/typing-indicator/typing-indicator.component';
export { KlipyGifPickerComponent } from './feature/klipy-gif-picker/klipy-gif-picker.component';

View File

@@ -37,7 +37,7 @@ import { DatabaseService } from '../../infrastructure/persistence';
import { reportDebuggingError, trackDebuggingTaskFailure } from '../../core/helpers/debugging-helpers';
import { DebuggingService } from '../../core/services';
import { AttachmentFacade } from '../../domains/attachment';
import { LinkMetadataService } from '../../domains/chat/application/link-metadata.service';
import { LinkMetadataService } from '../../domains/chat/application/services/link-metadata.service';
import { TimeSyncService } from '../../core/services/time-sync.service';
import {
DELETED_MESSAGE_CONTENT,
@@ -45,7 +45,7 @@ import {
Reaction
} from '../../shared-kernel';
import { hydrateMessages } from './messages.helpers';
import { canEditMessage } from '../../domains/chat/domain/message.rules';
import { canEditMessage } from '../../domains/chat/domain/rules/message.rules';
import { resolveRoomPermission } from '../../domains/access-control';
import { dispatchIncomingMessage, IncomingMessageContext } from './messages-incoming.handlers';

View File

@@ -4,8 +4,8 @@
*/
import { Message } from '../../shared-kernel';
import { DatabaseService } from '../../infrastructure/persistence';
import { getMessageTimestamp, normaliseDeletedMessage } from '../../domains/chat/domain/message.rules';
import type { InventoryItem } from '../../domains/chat/domain/message-sync.rules';
import { getMessageTimestamp, normaliseDeletedMessage } from '../../domains/chat/domain/rules/message.rules';
import type { InventoryItem } from '../../domains/chat/domain/rules/message-sync.rules';
// Re-export domain logic so existing callers keep working
export {
@@ -13,7 +13,7 @@ export {
getLatestTimestamp,
normaliseDeletedMessage,
canEditMessage
} from '../../domains/chat/domain/message.rules';
} from '../../domains/chat/domain/rules/message.rules';
export {
INVENTORY_LIMIT,
CHUNK_SIZE,
@@ -23,8 +23,8 @@ export {
FULL_SYNC_LIMIT,
chunkArray,
findMissingIds
} from '../../domains/chat/domain/message-sync.rules';
export type { InventoryItem } from '../../domains/chat/domain/message-sync.rules';
} from '../../domains/chat/domain/rules/message-sync.rules';
export type { InventoryItem } from '../../domains/chat/domain/rules/message-sync.rules';
/** Hydrates a single message with its reactions from the database. */
export async function hydrateMessage(