422 lines
12 KiB
TypeScript
422 lines
12 KiB
TypeScript
/**
|
|
* Core domain models for the MetoYou P2P chat application.
|
|
*
|
|
* These interfaces define the data structures shared across
|
|
* services, store, and components.
|
|
*/
|
|
|
|
/** Possible online-presence statuses for a user. */
|
|
export type UserStatus = 'online' | 'away' | 'busy' | 'offline';
|
|
|
|
/** Role hierarchy within a room/server. */
|
|
export type UserRole = 'host' | 'admin' | 'moderator' | 'member';
|
|
|
|
/** Channel type within a server. */
|
|
export type ChannelType = 'text' | 'voice';
|
|
|
|
/**
|
|
* Represents an authenticated user in the system.
|
|
* Users are identified by both a local `id` and a network-wide `oderId`.
|
|
*/
|
|
export interface User {
|
|
/** Local database identifier. */
|
|
id: string;
|
|
/** Network-wide unique identifier used for peer identification. */
|
|
oderId: string;
|
|
/** Login username (unique per auth server). */
|
|
username: string;
|
|
/** Human-readable display name shown in the UI. */
|
|
displayName: string;
|
|
/** Optional URL to the user's avatar image. */
|
|
avatarUrl?: string;
|
|
/** Current online-presence status. */
|
|
status: UserStatus;
|
|
/** Role within the current room/server. */
|
|
role: UserRole;
|
|
/** Epoch timestamp (ms) when the user first joined. */
|
|
joinedAt: number;
|
|
/** WebRTC peer identifier (transient, set when connected). */
|
|
peerId?: string;
|
|
/** Whether the user is currently connected. */
|
|
isOnline?: boolean;
|
|
/** Whether the user holds admin-level privileges. */
|
|
isAdmin?: boolean;
|
|
/** Whether the user is the owner of the current room. */
|
|
isRoomOwner?: boolean;
|
|
/** Real-time voice connection state. */
|
|
voiceState?: VoiceState;
|
|
/** Real-time screen-sharing state. */
|
|
screenShareState?: ScreenShareState;
|
|
}
|
|
|
|
/**
|
|
* A communication channel within a server (either text or voice).
|
|
*/
|
|
export interface Channel {
|
|
/** Unique channel identifier. */
|
|
id: string;
|
|
/** Display name of the channel. */
|
|
name: string;
|
|
/** Whether this is a text chat or voice channel. */
|
|
type: ChannelType;
|
|
/** Sort order within its type group (lower value = higher priority). */
|
|
position: number;
|
|
}
|
|
|
|
/**
|
|
* A single chat message in a room's text channel.
|
|
*/
|
|
export interface Message {
|
|
/** Unique message identifier. */
|
|
id: string;
|
|
/** The room this message belongs to. */
|
|
roomId: string;
|
|
/** The text channel within the room (defaults to 'general'). */
|
|
channelId?: string;
|
|
/** Identifier of the user who sent the message. */
|
|
senderId: string;
|
|
/** Display name of the sender at the time of sending. */
|
|
senderName: string;
|
|
/** Markdown-formatted message body. */
|
|
content: string;
|
|
/** Epoch timestamp (ms) when the message was created. */
|
|
timestamp: number;
|
|
/** Epoch timestamp (ms) of the last edit, if any. */
|
|
editedAt?: number;
|
|
/** Emoji reactions attached to this message. */
|
|
reactions: Reaction[];
|
|
/** Whether this message has been soft-deleted. */
|
|
isDeleted: boolean;
|
|
/** If this is a reply, the ID of the parent message. */
|
|
replyToId?: string;
|
|
}
|
|
|
|
/**
|
|
* An emoji reaction on a message.
|
|
*/
|
|
export interface Reaction {
|
|
/** Unique reaction identifier. */
|
|
id: string;
|
|
/** The message this reaction is attached to. */
|
|
messageId: string;
|
|
/** Network-wide user ID of the reactor. */
|
|
oderId: string;
|
|
/** Alias for `oderId` (kept for backward compatibility). */
|
|
userId: string;
|
|
/** The emoji character(s) used. */
|
|
emoji: string;
|
|
/** Epoch timestamp (ms) when the reaction was added. */
|
|
timestamp: number;
|
|
}
|
|
|
|
/**
|
|
* A chat room (server) that users can join to communicate.
|
|
*/
|
|
export interface Room {
|
|
/** Unique room identifier. */
|
|
id: string;
|
|
/** Display name of the room. */
|
|
name: string;
|
|
/** Optional long-form description. */
|
|
description?: string;
|
|
/** Short topic/status line shown in the header. */
|
|
topic?: string;
|
|
/** User ID of the room's creator/owner. */
|
|
hostId: string;
|
|
/** Password required to join (if private). */
|
|
password?: string;
|
|
/** Whether the room requires a password to join. */
|
|
isPrivate: boolean;
|
|
/** Epoch timestamp (ms) when the room was created. */
|
|
createdAt: number;
|
|
/** Current number of connected users. */
|
|
userCount: number;
|
|
/** Maximum allowed concurrent users. */
|
|
maxUsers?: number;
|
|
/** Server icon as a data-URL or remote URL. */
|
|
icon?: string;
|
|
/** Epoch timestamp (ms) of the last icon update (for conflict resolution). */
|
|
iconUpdatedAt?: number;
|
|
/** Role-based management permission overrides. */
|
|
permissions?: RoomPermissions;
|
|
/** Text and voice channels within the server. */
|
|
channels?: Channel[];
|
|
}
|
|
|
|
/**
|
|
* Editable subset of room properties exposed in the settings UI.
|
|
*/
|
|
export interface RoomSettings {
|
|
/** Room display name. */
|
|
name: string;
|
|
/** Optional long-form description. */
|
|
description?: string;
|
|
/** Short topic/status line. */
|
|
topic?: string;
|
|
/** Whether a password is required to join. */
|
|
isPrivate: boolean;
|
|
/** Password for private rooms. */
|
|
password?: string;
|
|
/** Maximum allowed concurrent users. */
|
|
maxUsers?: number;
|
|
/** Optional list of room rules. */
|
|
rules?: string[];
|
|
}
|
|
|
|
/**
|
|
* Fine-grained permission toggles for a room.
|
|
* Controls which roles can perform management actions.
|
|
*/
|
|
export interface RoomPermissions {
|
|
/** Whether admins can create/modify rooms. */
|
|
adminsManageRooms?: boolean;
|
|
/** Whether moderators can create/modify rooms. */
|
|
moderatorsManageRooms?: boolean;
|
|
/** Whether admins can change the server icon. */
|
|
adminsManageIcon?: boolean;
|
|
/** Whether moderators can change the server icon. */
|
|
moderatorsManageIcon?: boolean;
|
|
/** Whether voice channels are enabled. */
|
|
allowVoice?: boolean;
|
|
/** Whether screen sharing is enabled. */
|
|
allowScreenShare?: boolean;
|
|
/** Whether file uploads are enabled. */
|
|
allowFileUploads?: boolean;
|
|
/** Minimum delay (seconds) between messages (0 = disabled). */
|
|
slowModeInterval?: number;
|
|
}
|
|
|
|
/**
|
|
* A record of a user being banned from a room.
|
|
*/
|
|
export interface BanEntry {
|
|
/** Unique ban identifier (also used as the banned user's oderId). */
|
|
oderId: string;
|
|
/** The banned user's local ID. */
|
|
userId: string;
|
|
/** The room the ban applies to. */
|
|
roomId: string;
|
|
/** User ID of the admin who issued the ban. */
|
|
bannedBy: string;
|
|
/** Display name of the banned user at the time of banning. */
|
|
displayName?: string;
|
|
/** Human-readable reason for the ban. */
|
|
reason?: string;
|
|
/** Epoch timestamp (ms) when the ban expires (undefined = permanent). */
|
|
expiresAt?: number;
|
|
/** Epoch timestamp (ms) when the ban was issued. */
|
|
timestamp: number;
|
|
}
|
|
|
|
/**
|
|
* Tracks the state of a WebRTC peer connection.
|
|
*/
|
|
export interface PeerConnection {
|
|
/** Remote peer identifier. */
|
|
peerId: string;
|
|
/** Local user identifier. */
|
|
userId: string;
|
|
/** Current connection lifecycle state. */
|
|
status: 'connecting' | 'connected' | 'disconnected' | 'failed';
|
|
/** The RTCDataChannel used for P2P messaging. */
|
|
dataChannel?: RTCDataChannel;
|
|
/** The underlying RTCPeerConnection. */
|
|
connection?: RTCPeerConnection;
|
|
}
|
|
|
|
/**
|
|
* Real-time voice connection state for a user in a voice channel.
|
|
*/
|
|
export interface VoiceState {
|
|
/** Whether the user is connected to a voice channel. */
|
|
isConnected: boolean;
|
|
/** Whether the user's microphone is muted (self or by admin). */
|
|
isMuted: boolean;
|
|
/** Whether the user has deafened themselves. */
|
|
isDeafened: boolean;
|
|
/** Whether the user is currently speaking (voice activity detection). */
|
|
isSpeaking: boolean;
|
|
/** Whether the user was server-muted by an admin. */
|
|
isMutedByAdmin?: boolean;
|
|
/** User's output volume level (0-1). */
|
|
volume?: number;
|
|
/** The voice channel ID within the server (e.g. 'vc-general'). */
|
|
roomId?: string;
|
|
/** The server ID the user is connected to voice in. */
|
|
serverId?: string;
|
|
}
|
|
|
|
/**
|
|
* Real-time screen-sharing state for a user.
|
|
*/
|
|
export interface ScreenShareState {
|
|
/** Whether the user is actively sharing their screen. */
|
|
isSharing: boolean;
|
|
/** MediaStream ID of the screen capture. */
|
|
streamId?: string;
|
|
/** Desktop capturer source ID (Electron only). */
|
|
sourceId?: string;
|
|
/** Human-readable name of the captured source. */
|
|
sourceName?: string;
|
|
}
|
|
|
|
/** All signaling message types exchanged via the WebSocket relay. */
|
|
export type SignalingMessageType =
|
|
| 'offer'
|
|
| 'answer'
|
|
| 'ice-candidate'
|
|
| 'join'
|
|
| 'leave'
|
|
| 'chat'
|
|
| 'state-sync'
|
|
| 'kick'
|
|
| 'ban'
|
|
| 'host-change'
|
|
| 'room-update';
|
|
|
|
/**
|
|
* A message exchanged via the signaling WebSocket server.
|
|
*/
|
|
export interface SignalingMessage {
|
|
/** The type of signaling event. */
|
|
type: SignalingMessageType;
|
|
/** Sender's peer ID. */
|
|
from: string;
|
|
/** Optional target peer ID (for directed messages). */
|
|
to?: string;
|
|
/** Arbitrary payload specific to the message type. */
|
|
payload: unknown;
|
|
/** Epoch timestamp (ms) when the message was sent. */
|
|
timestamp: number;
|
|
}
|
|
|
|
/** All P2P chat event types exchanged via RTCDataChannel. */
|
|
export type ChatEventType =
|
|
| 'message'
|
|
| 'chat-message'
|
|
| 'edit'
|
|
| 'message-edited'
|
|
| 'delete'
|
|
| 'message-deleted'
|
|
| 'reaction'
|
|
| 'reaction-added'
|
|
| 'reaction-removed'
|
|
| 'kick'
|
|
| 'ban'
|
|
| 'room-deleted'
|
|
| 'room-settings-update'
|
|
| 'voice-state'
|
|
| 'chat-inventory-request'
|
|
| 'voice-state-request'
|
|
| 'state-request'
|
|
| 'screen-state'
|
|
| 'role-change'
|
|
| 'channels-update';
|
|
|
|
/**
|
|
* A P2P event exchanged between peers via RTCDataChannel.
|
|
* The `type` field determines which optional fields are populated.
|
|
*/
|
|
export interface ChatEvent {
|
|
/** The type of P2P event. */
|
|
type: ChatEventType;
|
|
/** Relevant message ID (for edits, deletes, reactions). */
|
|
messageId?: string;
|
|
/** Full message payload (for new messages). */
|
|
message?: Message;
|
|
/** Reaction payload (for reaction events). */
|
|
reaction?: Reaction;
|
|
/** Partial message updates (for edits). */
|
|
data?: Partial<Message>;
|
|
/** Event timestamp. */
|
|
timestamp?: number;
|
|
/** Target user ID (for kick/ban). */
|
|
targetUserId?: string;
|
|
/** Room ID the event pertains to. */
|
|
roomId?: string;
|
|
/** User who issued a kick. */
|
|
kickedBy?: string;
|
|
/** User who issued a ban. */
|
|
bannedBy?: string;
|
|
/** Text content (for messages/edits). */
|
|
content?: string;
|
|
/** Edit timestamp. */
|
|
editedAt?: number;
|
|
/** User who performed a delete. */
|
|
deletedBy?: string;
|
|
/** Network-wide user identifier. */
|
|
oderId?: string;
|
|
/** Display name of the event sender. */
|
|
displayName?: string;
|
|
/** Emoji character (for reactions). */
|
|
emoji?: string;
|
|
/** Ban/kick reason. */
|
|
reason?: string;
|
|
/** Updated room settings. */
|
|
settings?: RoomSettings;
|
|
/** Partial voice state update. */
|
|
voiceState?: Partial<VoiceState>;
|
|
/** Screen-sharing flag. */
|
|
isScreenSharing?: boolean;
|
|
/** New role assignment. */
|
|
role?: UserRole;
|
|
/** Updated channel list. */
|
|
channels?: Channel[];
|
|
}
|
|
|
|
/**
|
|
* Server listing as returned by the directory API.
|
|
*/
|
|
export interface ServerInfo {
|
|
/** Unique server identifier. */
|
|
id: string;
|
|
/** Display name. */
|
|
name: string;
|
|
/** Optional description. */
|
|
description?: string;
|
|
/** Optional topic. */
|
|
topic?: string;
|
|
/** Display name of the host. */
|
|
hostName: string;
|
|
/** Owner's user ID. */
|
|
ownerId?: string;
|
|
/** Owner's public key / oderId. */
|
|
ownerPublicKey?: string;
|
|
/** Current number of connected users. */
|
|
userCount: number;
|
|
/** Maximum allowed users. */
|
|
maxUsers: number;
|
|
/** Whether a password is required. */
|
|
isPrivate: boolean;
|
|
/** Searchable tags. */
|
|
tags?: string[];
|
|
/** Epoch timestamp (ms) when the server was created. */
|
|
createdAt: number;
|
|
}
|
|
|
|
/**
|
|
* Request payload for joining a server.
|
|
*/
|
|
export interface JoinRequest {
|
|
/** Target room/server ID. */
|
|
roomId: string;
|
|
/** Requesting user's ID. */
|
|
userId: string;
|
|
/** Requesting user's username. */
|
|
username: string;
|
|
}
|
|
|
|
/**
|
|
* Top-level application state snapshot (used for diagnostics).
|
|
*/
|
|
export interface AppState {
|
|
/** The currently authenticated user, or null if logged out. */
|
|
currentUser: User | null;
|
|
/** The room the user is currently viewing, or null. */
|
|
currentRoom: Room | null;
|
|
/** Whether a connection attempt is in progress. */
|
|
isConnecting: boolean;
|
|
/** Last error message, or null. */
|
|
error: string | null;
|
|
}
|