mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 15:05:20 +00:00
Improve room functionality
- Fix header to show "x people / y rooms" count - Add proper leave room functionality that cleans up data - Track and display room members in sidebar - Show "IN #ROOM" header when viewing a room - Only show peers who have sent messages to current room - Add leave button in room header alongside main button - Ensure senderPeerID is set for room member tracking
This commit is contained in:
@@ -39,6 +39,7 @@ class ChatViewModel: ObservableObject {
|
||||
@Published var currentRoom: String? = nil // Currently selected room
|
||||
@Published var roomMessages: [String: [BitchatMessage]] = [:] // room -> messages
|
||||
@Published var unreadRoomMessages: [String: Int] = [:] // room -> unread count
|
||||
@Published var roomMembers: [String: Set<String>] = [:] // room -> set of peer IDs who have sent messages
|
||||
|
||||
let meshService = BluetoothMeshService()
|
||||
private let userDefaults = UserDefaults.standard
|
||||
@@ -132,8 +133,10 @@ class ChatViewModel: ObservableObject {
|
||||
currentRoom = nil
|
||||
}
|
||||
|
||||
// Keep messages for now (could clear if desired)
|
||||
// Clean up room data
|
||||
unreadRoomMessages.removeValue(forKey: room)
|
||||
roomMessages.removeValue(forKey: room)
|
||||
roomMembers.removeValue(forKey: room)
|
||||
}
|
||||
|
||||
func switchToRoom(_ room: String?) {
|
||||
@@ -229,6 +232,9 @@ class ChatViewModel: ObservableObject {
|
||||
timestamp: Date(),
|
||||
isRelay: false,
|
||||
originalSender: nil,
|
||||
isPrivate: false,
|
||||
recipientNickname: nil,
|
||||
senderPeerID: meshService.myPeerID,
|
||||
mentions: mentions.isEmpty ? nil : mentions,
|
||||
room: messageRoom
|
||||
)
|
||||
@@ -239,6 +245,12 @@ class ChatViewModel: ObservableObject {
|
||||
roomMessages[room] = []
|
||||
}
|
||||
roomMessages[room]?.append(message)
|
||||
|
||||
// Track ourselves as a room member
|
||||
if roomMembers[room] == nil {
|
||||
roomMembers[room] = []
|
||||
}
|
||||
roomMembers[room]?.insert(meshService.myPeerID)
|
||||
} else {
|
||||
// Add to main messages
|
||||
messages.append(message)
|
||||
@@ -658,6 +670,14 @@ extension ChatViewModel: BitchatDelegate {
|
||||
roomMessages[room]?.append(message)
|
||||
roomMessages[room]?.sort { $0.timestamp < $1.timestamp }
|
||||
|
||||
// Track room members
|
||||
if roomMembers[room] == nil {
|
||||
roomMembers[room] = []
|
||||
}
|
||||
if let senderPeerID = message.senderPeerID {
|
||||
roomMembers[room]?.insert(senderPeerID)
|
||||
}
|
||||
|
||||
// Update unread count if not currently viewing this room
|
||||
if currentRoom != room {
|
||||
unreadRoomMessages[room] = (unreadRoomMessages[room] ?? 0) + 1
|
||||
|
||||
@@ -212,6 +212,23 @@ struct ContentView: View {
|
||||
|
||||
Spacer()
|
||||
|
||||
// Leave room button
|
||||
Button(action: {
|
||||
viewModel.leaveRoom(currentRoom)
|
||||
}) {
|
||||
Text("leave")
|
||||
.font(.system(size: 12, design: .monospaced))
|
||||
.foregroundColor(Color.red)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 2)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 4)
|
||||
.stroke(Color.red.opacity(0.5), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
// Back to main button
|
||||
Button(action: {
|
||||
viewModel.switchToRoom(nil)
|
||||
}) {
|
||||
@@ -272,7 +289,15 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
let otherPeersCount = viewModel.connectedPeers.filter { $0 != viewModel.meshService.myPeerID }.count
|
||||
Text(viewModel.isConnected ? "\(otherPeersCount) \(otherPeersCount == 1 ? "person" : "people")" : "alone :/")
|
||||
let roomCount = viewModel.joinedRooms.count
|
||||
let statusText = if !viewModel.isConnected {
|
||||
"alone :/"
|
||||
} else if roomCount > 0 {
|
||||
"\(otherPeersCount) \(otherPeersCount == 1 ? "person" : "people") / \(roomCount) \(roomCount == 1 ? "room" : "rooms")"
|
||||
} else {
|
||||
"\(otherPeersCount) \(otherPeersCount == 1 ? "person" : "people")"
|
||||
}
|
||||
Text(statusText)
|
||||
.font(.system(size: 12, design: .monospaced))
|
||||
.foregroundColor(viewModel.isConnected ? textColor : Color.red)
|
||||
}
|
||||
@@ -524,7 +549,13 @@ struct ContentView: View {
|
||||
|
||||
// People section
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
if !viewModel.connectedPeers.isEmpty {
|
||||
// Show appropriate header based on context
|
||||
if let currentRoom = viewModel.currentRoom {
|
||||
Text("IN \(currentRoom.uppercased())")
|
||||
.font(.system(size: 11, weight: .semibold, design: .monospaced))
|
||||
.foregroundColor(secondaryTextColor)
|
||||
.padding(.horizontal, 12)
|
||||
} else if !viewModel.connectedPeers.isEmpty {
|
||||
Text("PEOPLE")
|
||||
.font(.system(size: 11, weight: .semibold, design: .monospaced))
|
||||
.foregroundColor(secondaryTextColor)
|
||||
@@ -536,13 +567,29 @@ struct ContentView: View {
|
||||
.font(.system(size: 14, design: .monospaced))
|
||||
.foregroundColor(secondaryTextColor)
|
||||
.padding(.horizontal)
|
||||
} else if let currentRoom = viewModel.currentRoom,
|
||||
(viewModel.roomMembers[currentRoom]?.isEmpty ?? true) {
|
||||
Text("No one in this room yet")
|
||||
.font(.system(size: 14, design: .monospaced))
|
||||
.foregroundColor(secondaryTextColor)
|
||||
.padding(.horizontal)
|
||||
} else {
|
||||
let peerNicknames = viewModel.meshService.getPeerNicknames()
|
||||
let peerRSSI = viewModel.meshService.getPeerRSSI()
|
||||
let myPeerID = viewModel.meshService.myPeerID
|
||||
|
||||
// Filter peers based on current room
|
||||
let peersToShow = if let currentRoom = viewModel.currentRoom,
|
||||
let roomMemberIDs = viewModel.roomMembers[currentRoom] {
|
||||
// Show only peers who have sent messages to this room
|
||||
viewModel.connectedPeers.filter { roomMemberIDs.contains($0) && $0 != myPeerID }
|
||||
} else {
|
||||
// Show all connected peers in main chat
|
||||
viewModel.connectedPeers.filter { $0 != myPeerID }
|
||||
}
|
||||
|
||||
// Sort peers: favorites first, then alphabetically by nickname
|
||||
let sortedPeers = viewModel.connectedPeers.filter { $0 != myPeerID }.sorted { peer1, peer2 in
|
||||
let sortedPeers = peersToShow.sorted { peer1, peer2 in
|
||||
let isFav1 = viewModel.isFavorite(peerID: peer1)
|
||||
let isFav2 = viewModel.isFavorite(peerID: peer2)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user