refactor: stricter domain: chat
This commit is contained in:
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
@@ -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]',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = [
|
||||
'👍',
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user