feat: implement chat history, theme customization, and password management
- Added chat history persistence for active rooms with auto-cleanup on stream end. - Overhauled Settings page with user profile, theme color picker, and password change. - Added backend API for user password updates. - Integrated flutter_launcher_icons and updated app icon to 'H' logo. - Fixed 'Duplicate keys' bug in danmaku by using UniqueKey and filtering historical messages. - Updated version to 1.0.0-beta3.5 and author info.
This commit is contained in:
@@ -16,10 +16,11 @@ const (
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
Type string `json:"type"` // "chat", "system", "danmaku"
|
||||
Username string `json:"username"`
|
||||
Content string `json:"content"`
|
||||
RoomID string `json:"room_id"`
|
||||
Type string `json:"type"` // "chat", "system", "danmaku"
|
||||
Username string `json:"username"`
|
||||
Content string `json:"content"`
|
||||
RoomID string `json:"room_id"`
|
||||
IsHistory bool `json:"is_history"`
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
@@ -31,19 +32,21 @@ type Client struct {
|
||||
}
|
||||
|
||||
type Hub struct {
|
||||
rooms map[string]map[*Client]bool
|
||||
broadcast chan Message
|
||||
register chan *Client
|
||||
unregister chan *Client
|
||||
mutex sync.RWMutex
|
||||
rooms map[string]map[*Client]bool
|
||||
roomsHistory map[string][]Message
|
||||
broadcast chan Message
|
||||
register chan *Client
|
||||
unregister chan *Client
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func NewHub() *Hub {
|
||||
return &Hub{
|
||||
broadcast: make(chan Message),
|
||||
register: make(chan *Client),
|
||||
unregister: make(chan *Client),
|
||||
rooms: make(map[string]map[*Client]bool),
|
||||
broadcast: make(chan Message),
|
||||
register: make(chan *Client),
|
||||
unregister: make(chan *Client),
|
||||
rooms: make(map[string]map[*Client]bool),
|
||||
roomsHistory: make(map[string][]Message),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +59,20 @@ func (h *Hub) Run() {
|
||||
h.rooms[client.RoomID] = make(map[*Client]bool)
|
||||
}
|
||||
h.rooms[client.RoomID][client] = true
|
||||
|
||||
// Send existing history to the newly joined client
|
||||
if history, ok := h.roomsHistory[client.RoomID]; ok {
|
||||
for _, msg := range history {
|
||||
msg.IsHistory = true
|
||||
msgBytes, _ := json.Marshal(msg)
|
||||
// Use select to avoid blocking if client's send channel is full
|
||||
select {
|
||||
case client.Send <- msgBytes:
|
||||
default:
|
||||
// If send fails, we could potentially log or ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
h.mutex.Unlock()
|
||||
|
||||
case client := <-h.unregister:
|
||||
@@ -64,6 +81,10 @@ func (h *Hub) Run() {
|
||||
if _, ok := rooms[client]; ok {
|
||||
delete(rooms, client)
|
||||
close(client.Send)
|
||||
// We no longer delete the room from h.rooms here if we want history to persist
|
||||
// even if everyone leaves (as long as it's active in DB).
|
||||
// But we should clean up if the room is empty and we want to save memory.
|
||||
// However, the history is what matters.
|
||||
if len(rooms) == 0 {
|
||||
delete(h.rooms, client.RoomID)
|
||||
}
|
||||
@@ -72,7 +93,16 @@ func (h *Hub) Run() {
|
||||
h.mutex.Unlock()
|
||||
|
||||
case message := <-h.broadcast:
|
||||
h.mutex.RLock()
|
||||
h.mutex.Lock()
|
||||
// Only store "chat" and "danmaku" messages in history
|
||||
if message.Type == "chat" || message.Type == "danmaku" {
|
||||
h.roomsHistory[message.RoomID] = append(h.roomsHistory[message.RoomID], message)
|
||||
// Limit history size to avoid memory leak (e.g., last 100 messages)
|
||||
if len(h.roomsHistory[message.RoomID]) > 100 {
|
||||
h.roomsHistory[message.RoomID] = h.roomsHistory[message.RoomID][1:]
|
||||
}
|
||||
}
|
||||
|
||||
clients := h.rooms[message.RoomID]
|
||||
if clients != nil {
|
||||
msgBytes, _ := json.Marshal(message)
|
||||
@@ -85,11 +115,18 @@ func (h *Hub) Run() {
|
||||
}
|
||||
}
|
||||
}
|
||||
h.mutex.RUnlock()
|
||||
h.mutex.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ClearRoomHistory removes history for a room, should be called when stream ends
|
||||
func (h *Hub) ClearRoomHistory(roomID string) {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
delete(h.roomsHistory, roomID)
|
||||
}
|
||||
|
||||
func (h *Hub) RegisterClient(c *Client) {
|
||||
h.register <- c
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user