284 lines
6.7 KiB
TypeScript
284 lines
6.7 KiB
TypeScript
// Created by: Claude
|
|
// Date: 2026-01-03
|
|
// Purpose: Store Zustand pour la gestion des rooms et messages
|
|
// Refs: client/CLAUDE.md
|
|
|
|
import { create } from 'zustand'
|
|
|
|
/**
|
|
* Message dans une room.
|
|
*/
|
|
export interface Message {
|
|
message_id: string
|
|
room_id: string
|
|
user_id: string
|
|
from_username: string
|
|
content: string
|
|
created_at: string
|
|
}
|
|
|
|
/**
|
|
* Membre d'une room.
|
|
*/
|
|
export interface RoomMember {
|
|
user_id: string
|
|
username: string
|
|
peer_id?: string
|
|
role: 'owner' | 'member' | 'guest'
|
|
presence: 'online' | 'busy' | 'offline'
|
|
}
|
|
|
|
/**
|
|
* Informations sur une room.
|
|
*/
|
|
export interface RoomInfo {
|
|
room_id: string
|
|
name: string
|
|
owner_user_id: string
|
|
created_at: string
|
|
members: RoomMember[]
|
|
messages: Message[]
|
|
}
|
|
|
|
/**
|
|
* État de la room courante.
|
|
*/
|
|
interface RoomState {
|
|
// Room courante
|
|
currentRoomId: string | null
|
|
currentRoom: RoomInfo | null
|
|
|
|
// Cache des rooms
|
|
rooms: Map<string, RoomInfo>
|
|
|
|
// Actions - Room courante
|
|
setCurrentRoom: (roomId: string, roomInfo: Partial<RoomInfo>) => void
|
|
clearCurrentRoom: () => void
|
|
|
|
// Actions - Messages
|
|
addMessage: (roomId: string, message: Message) => void
|
|
setMessages: (roomId: string, messages: Message[]) => void
|
|
|
|
// Actions - Membres
|
|
addMember: (roomId: string, member: RoomMember) => void
|
|
removeMember: (roomId: string, userId: string) => void
|
|
updateMemberPresence: (roomId: string, userId: string, presence: 'online' | 'busy' | 'offline') => void
|
|
setMembers: (roomId: string, members: RoomMember[]) => void
|
|
|
|
// Actions - Cache
|
|
updateRoomCache: (roomId: string, updates: Partial<RoomInfo>) => void
|
|
clearCache: () => void
|
|
}
|
|
|
|
/**
|
|
* Store pour la gestion des rooms et messages.
|
|
*/
|
|
export const useRoomStore = create<RoomState>((set, get) => ({
|
|
// État initial
|
|
currentRoomId: null,
|
|
currentRoom: null,
|
|
rooms: new Map(),
|
|
|
|
// Définir la room courante
|
|
setCurrentRoom: (roomId, roomInfo) => {
|
|
const existingRoom = get().rooms.get(roomId)
|
|
|
|
const room: RoomInfo = {
|
|
room_id: roomId,
|
|
name: roomInfo.name || existingRoom?.name || 'Unknown Room',
|
|
owner_user_id: roomInfo.owner_user_id || existingRoom?.owner_user_id || '',
|
|
created_at: roomInfo.created_at || existingRoom?.created_at || new Date().toISOString(),
|
|
members: roomInfo.members || existingRoom?.members || [],
|
|
messages: roomInfo.messages || existingRoom?.messages || [],
|
|
}
|
|
|
|
set((state) => {
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, room)
|
|
|
|
return {
|
|
currentRoomId: roomId,
|
|
currentRoom: room,
|
|
rooms: newRooms,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Effacer la room courante
|
|
clearCurrentRoom: () => set({
|
|
currentRoomId: null,
|
|
currentRoom: null,
|
|
}),
|
|
|
|
// Ajouter un message
|
|
addMessage: (roomId, message) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
messages: [...room.messages, message],
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Définir tous les messages d'une room
|
|
setMessages: (roomId, messages) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
messages,
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Ajouter un membre
|
|
addMember: (roomId, member) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
// Vérifier si le membre existe déjà
|
|
const existingIndex = room.members.findIndex((m) => m.user_id === member.user_id)
|
|
|
|
let updatedMembers
|
|
if (existingIndex >= 0) {
|
|
// Mettre à jour le membre existant
|
|
updatedMembers = [...room.members]
|
|
updatedMembers[existingIndex] = { ...updatedMembers[existingIndex], ...member }
|
|
} else {
|
|
// Ajouter un nouveau membre
|
|
updatedMembers = [...room.members, member]
|
|
}
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
members: updatedMembers,
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Retirer un membre
|
|
removeMember: (roomId, userId) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
members: room.members.filter((m) => m.user_id !== userId),
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Mettre à jour la présence d'un membre
|
|
updateMemberPresence: (roomId, userId, presence) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
const updatedMembers = room.members.map((m) =>
|
|
m.user_id === userId ? { ...m, presence } : m
|
|
)
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
members: updatedMembers,
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Définir tous les membres
|
|
setMembers: (roomId, members) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
members,
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Mettre à jour le cache d'une room
|
|
updateRoomCache: (roomId, updates) => {
|
|
set((state) => {
|
|
const room = state.rooms.get(roomId)
|
|
if (!room) return state
|
|
|
|
const updatedRoom = {
|
|
...room,
|
|
...updates,
|
|
}
|
|
|
|
const newRooms = new Map(state.rooms)
|
|
newRooms.set(roomId, updatedRoom)
|
|
|
|
return {
|
|
rooms: newRooms,
|
|
currentRoom: state.currentRoomId === roomId ? updatedRoom : state.currentRoom,
|
|
}
|
|
})
|
|
},
|
|
|
|
// Vider le cache
|
|
clearCache: () => set({
|
|
currentRoomId: null,
|
|
currentRoom: null,
|
|
rooms: new Map(),
|
|
}),
|
|
}))
|