Files
Toju/src/app/core/models/index.ts
2026-03-09 23:02:52 +01:00

314 lines
6.1 KiB
TypeScript

export type UserStatus = 'online' | 'away' | 'busy' | 'offline';
export type UserRole = 'host' | 'admin' | 'moderator' | 'member';
export type ChannelType = 'text' | 'voice';
export const DELETED_MESSAGE_CONTENT = '[Message deleted]';
export interface User {
id: string;
oderId: string;
username: string;
displayName: string;
avatarUrl?: string;
status: UserStatus;
role: UserRole;
joinedAt: number;
peerId?: string;
isOnline?: boolean;
isAdmin?: boolean;
isRoomOwner?: boolean;
voiceState?: VoiceState;
screenShareState?: ScreenShareState;
}
export interface RoomMember {
id: string;
oderId?: string;
username: string;
displayName: string;
avatarUrl?: string;
role: UserRole;
joinedAt: number;
lastSeenAt: number;
}
export interface Channel {
id: string;
name: string;
type: ChannelType;
position: number;
}
export interface Message {
id: string;
roomId: string;
channelId?: string;
senderId: string;
senderName: string;
content: string;
timestamp: number;
editedAt?: number;
reactions: Reaction[];
isDeleted: boolean;
replyToId?: string;
}
export interface Reaction {
id: string;
messageId: string;
oderId: string;
userId: string;
emoji: string;
timestamp: number;
}
export interface Room {
id: string;
name: string;
description?: string;
topic?: string;
hostId: string;
password?: string;
isPrivate: boolean;
createdAt: number;
userCount: number;
maxUsers?: number;
icon?: string;
iconUpdatedAt?: number;
permissions?: RoomPermissions;
channels?: Channel[];
members?: RoomMember[];
}
export interface RoomSettings {
name: string;
description?: string;
topic?: string;
isPrivate: boolean;
password?: string;
maxUsers?: number;
rules?: string[];
}
export interface RoomPermissions {
adminsManageRooms?: boolean;
moderatorsManageRooms?: boolean;
adminsManageIcon?: boolean;
moderatorsManageIcon?: boolean;
allowVoice?: boolean;
allowScreenShare?: boolean;
allowFileUploads?: boolean;
slowModeInterval?: number;
}
export interface BanEntry {
oderId: string;
userId: string;
roomId: string;
bannedBy: string;
displayName?: string;
reason?: string;
expiresAt?: number;
timestamp: number;
}
export interface PeerConnection {
peerId: string;
userId: string;
status: 'connecting' | 'connected' | 'disconnected' | 'failed';
dataChannel?: RTCDataChannel;
connection?: RTCPeerConnection;
}
export interface VoiceState {
isConnected: boolean;
isMuted: boolean;
isDeafened: boolean;
isSpeaking: boolean;
isMutedByAdmin?: boolean;
volume?: number;
roomId?: string;
serverId?: string;
}
export interface ScreenShareState {
isSharing: boolean;
streamId?: string;
sourceId?: string;
sourceName?: string;
}
export type SignalingMessageType =
| 'offer'
| 'answer'
| 'ice-candidate'
| 'join'
| 'leave'
| 'chat'
| 'state-sync'
| 'kick'
| 'ban'
| 'host-change'
| 'room-update';
export interface SignalingMessage {
type: SignalingMessageType;
from: string;
to?: string;
payload: unknown;
timestamp: number;
}
export type ChatEventType =
| 'message'
| 'chat-message'
| 'edit'
| 'message-edited'
| 'delete'
| 'message-deleted'
| 'reaction'
| 'reaction-added'
| 'reaction-removed'
| 'kick'
| 'ban'
| 'room-deleted'
| 'host-change'
| 'room-settings-update'
| 'voice-state'
| 'chat-inventory-request'
| 'chat-inventory'
| 'chat-sync-request-ids'
| 'chat-sync-batch'
| 'chat-sync-summary'
| 'chat-sync-request'
| 'chat-sync-full'
| 'file-announce'
| 'file-chunk'
| 'file-request'
| 'file-cancel'
| 'file-not-found'
| 'member-roster-request'
| 'member-roster'
| 'member-leave'
| 'voice-state-request'
| 'state-request'
| 'screen-state'
| 'screen-share-request'
| 'screen-share-stop'
| 'role-change'
| 'room-permissions-update'
| 'server-icon-summary'
| 'server-icon-request'
| 'server-icon-full'
| 'server-icon-update'
| 'server-state-request'
| 'server-state-full'
| 'unban'
| 'channels-update';
export interface ChatInventoryItem {
id: string;
ts: number;
rc: number;
ac?: number;
}
export interface ChatAttachmentAnnouncement {
id: string;
filename: string;
size: number;
mime: string;
isImage: boolean;
uploaderPeerId?: string;
}
export interface ChatAttachmentMeta extends ChatAttachmentAnnouncement {
messageId: string;
filePath?: string;
savedPath?: string;
}
/** Optional fields depend on `type`. */
export interface ChatEvent {
type: ChatEventType;
fromPeerId?: string;
messageId?: string;
message?: Message;
reaction?: Reaction;
data?: string | Partial<Message>;
timestamp?: number;
targetUserId?: string;
roomId?: string;
items?: ChatInventoryItem[];
ids?: string[];
messages?: Message[];
attachments?: Record<string, ChatAttachmentMeta[]>;
total?: number;
index?: number;
count?: number;
lastUpdated?: number;
file?: ChatAttachmentAnnouncement;
fileId?: string;
hostId?: string;
hostOderId?: string;
previousHostId?: string;
previousHostOderId?: string;
kickedBy?: string;
bannedBy?: string;
content?: string;
editedAt?: number;
deletedAt?: number;
deletedBy?: string;
oderId?: string;
displayName?: string;
emoji?: string;
reason?: string;
settings?: RoomSettings;
permissions?: Partial<RoomPermissions>;
voiceState?: Partial<VoiceState>;
isScreenSharing?: boolean;
icon?: string;
iconUpdatedAt?: number;
role?: UserRole;
room?: Room;
channels?: Channel[];
members?: RoomMember[];
ban?: BanEntry;
bans?: BanEntry[];
banOderId?: string;
expiresAt?: number;
}
export interface ServerInfo {
id: string;
name: string;
description?: string;
topic?: string;
hostName: string;
ownerId?: string;
ownerName?: string;
ownerPublicKey?: string;
userCount: number;
maxUsers: number;
isPrivate: boolean;
tags?: string[];
createdAt: number;
sourceId?: string;
sourceName?: string;
}
export interface JoinRequest {
roomId: string;
userId: string;
username: string;
}
export interface AppState {
currentUser: User | null;
currentRoom: Room | null;
isConnecting: boolean;
error: string | null;
}