feat: Add profile images
This commit is contained in:
@@ -41,6 +41,7 @@ export interface ChatEventBase {
|
||||
lastUpdated?: number;
|
||||
file?: ChatAttachmentAnnouncement;
|
||||
fileId?: string;
|
||||
username?: string;
|
||||
hostId?: string;
|
||||
hostOderId?: string;
|
||||
previousHostId?: string;
|
||||
@@ -62,6 +63,10 @@ export interface ChatEventBase {
|
||||
isCameraEnabled?: boolean;
|
||||
icon?: string;
|
||||
iconUpdatedAt?: number;
|
||||
avatarUrl?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
role?: UserRole;
|
||||
room?: Partial<Room>;
|
||||
channels?: Channel[];
|
||||
@@ -263,6 +268,43 @@ export interface ServerIconUpdateEvent extends ChatEventBase {
|
||||
iconUpdatedAt: number;
|
||||
}
|
||||
|
||||
export interface UserAvatarSummaryEvent extends ChatEventBase {
|
||||
type: 'user-avatar-summary';
|
||||
oderId: string;
|
||||
username?: string;
|
||||
displayName?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt: number;
|
||||
}
|
||||
|
||||
export interface UserAvatarRequestEvent extends ChatEventBase {
|
||||
type: 'user-avatar-request';
|
||||
oderId: string;
|
||||
}
|
||||
|
||||
export interface UserAvatarFullEvent extends ChatEventBase {
|
||||
type: 'user-avatar-full';
|
||||
oderId: string;
|
||||
username?: string;
|
||||
displayName?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime: string;
|
||||
avatarUpdatedAt: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface UserAvatarChunkEvent extends ChatEventBase {
|
||||
type: 'user-avatar-chunk';
|
||||
oderId: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
index: number;
|
||||
total: number;
|
||||
data: string;
|
||||
}
|
||||
|
||||
export interface ServerStateRequestEvent extends ChatEventBase {
|
||||
type: 'server-state-request';
|
||||
roomId: string;
|
||||
@@ -343,6 +385,10 @@ export type ChatEvent =
|
||||
| StateRequestEvent
|
||||
| ScreenShareRequestEvent
|
||||
| ScreenShareStopEvent
|
||||
| UserAvatarSummaryEvent
|
||||
| UserAvatarRequestEvent
|
||||
| UserAvatarFullEvent
|
||||
| UserAvatarChunkEvent
|
||||
| ServerIconSummaryEvent
|
||||
| ServerIconRequestEvent
|
||||
| ServerIconFullEvent
|
||||
|
||||
@@ -8,3 +8,5 @@ export * from './chat-events';
|
||||
export * from './media-preferences';
|
||||
export * from './signaling-contracts';
|
||||
export * from './attachment-contracts';
|
||||
export * from './p2p-transfer.constants';
|
||||
export * from './p2p-transfer.utils';
|
||||
|
||||
2
toju-app/src/app/shared-kernel/p2p-transfer.constants.ts
Normal file
2
toju-app/src/app/shared-kernel/p2p-transfer.constants.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
/** Shared binary chunk size for payloads streamed over RTCDataChannel. */
|
||||
export const P2P_BASE64_CHUNK_SIZE_BYTES = 64 * 1024;
|
||||
48
toju-app/src/app/shared-kernel/p2p-transfer.utils.ts
Normal file
48
toju-app/src/app/shared-kernel/p2p-transfer.utils.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { P2P_BASE64_CHUNK_SIZE_BYTES } from './p2p-transfer.constants';
|
||||
|
||||
export function arrayBufferToBase64(buffer: ArrayBuffer): string {
|
||||
let binary = '';
|
||||
|
||||
const bytes = new Uint8Array(buffer);
|
||||
|
||||
for (let index = 0; index < bytes.byteLength; index++) {
|
||||
binary += String.fromCharCode(bytes[index]);
|
||||
}
|
||||
|
||||
return btoa(binary);
|
||||
}
|
||||
|
||||
export function decodeBase64(base64: string): Uint8Array {
|
||||
const binary = atob(base64);
|
||||
const bytes = new Uint8Array(binary.length);
|
||||
|
||||
for (let index = 0; index < binary.length; index++) {
|
||||
bytes[index] = binary.charCodeAt(index);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export async function* iterateBlobChunks(
|
||||
blob: Blob,
|
||||
chunkSize = P2P_BASE64_CHUNK_SIZE_BYTES
|
||||
): AsyncGenerator<{ base64: string; index: number; total: number }, void, undefined> {
|
||||
const totalChunks = Math.ceil(blob.size / chunkSize);
|
||||
|
||||
let offset = 0;
|
||||
let chunkIndex = 0;
|
||||
|
||||
while (offset < blob.size) {
|
||||
const slice = blob.slice(offset, offset + chunkSize);
|
||||
const arrayBuffer = await slice.arrayBuffer();
|
||||
|
||||
yield {
|
||||
base64: arrayBufferToBase64(arrayBuffer),
|
||||
index: chunkIndex,
|
||||
total: totalChunks
|
||||
};
|
||||
|
||||
offset += chunkSize;
|
||||
chunkIndex++;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,9 @@ export interface User {
|
||||
username: string;
|
||||
displayName: string;
|
||||
avatarUrl?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
status: UserStatus;
|
||||
role: UserRole;
|
||||
joinedAt: number;
|
||||
@@ -33,6 +36,9 @@ export interface RoomMember {
|
||||
username: string;
|
||||
displayName: string;
|
||||
avatarUrl?: string;
|
||||
avatarHash?: string;
|
||||
avatarMime?: string;
|
||||
avatarUpdatedAt?: number;
|
||||
role: UserRole;
|
||||
roleIds?: string[];
|
||||
joinedAt: number;
|
||||
|
||||
Reference in New Issue
Block a user