mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 22:25:20 +00:00
Fix room message routing and improve room UI
- Fix room field not being properly set in BluetoothMeshService sendMessage - Make room name header tappable to open sidebar - Show member count in parentheses next to room name - Display room members including self with "(you)" indicator - Show self in room member list with dot indicator - Disable favorite/chat actions for self in member list - Fix empty room detection logic
This commit is contained in:
@@ -520,6 +520,9 @@ class BluetoothMeshService: NSObject {
|
|||||||
timestamp: Date(),
|
timestamp: Date(),
|
||||||
isRelay: false,
|
isRelay: false,
|
||||||
originalSender: nil,
|
originalSender: nil,
|
||||||
|
isPrivate: false,
|
||||||
|
recipientNickname: nil,
|
||||||
|
senderPeerID: self.myPeerID,
|
||||||
mentions: mentions.isEmpty ? nil : mentions,
|
mentions: mentions.isEmpty ? nil : mentions,
|
||||||
room: room
|
room: room
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -206,9 +206,18 @@ struct ContentView: View {
|
|||||||
} else if let currentRoom = viewModel.currentRoom {
|
} else if let currentRoom = viewModel.currentRoom {
|
||||||
// Room header
|
// Room header
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Text(currentRoom)
|
let memberCount = (viewModel.roomMembers[currentRoom]?.count ?? 0) + 1 // +1 for self
|
||||||
|
Button(action: {
|
||||||
|
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) {
|
||||||
|
showSidebar.toggle()
|
||||||
|
sidebarDragOffset = 0
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("\(currentRoom) (\(memberCount))")
|
||||||
.font(.system(size: 18, weight: .medium, design: .monospaced))
|
.font(.system(size: 18, weight: .medium, design: .monospaced))
|
||||||
.foregroundColor(Color.orange)
|
.foregroundColor(Color.orange)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
@@ -568,7 +577,8 @@ struct ContentView: View {
|
|||||||
.foregroundColor(secondaryTextColor)
|
.foregroundColor(secondaryTextColor)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
} else if let currentRoom = viewModel.currentRoom,
|
} else if let currentRoom = viewModel.currentRoom,
|
||||||
(viewModel.roomMembers[currentRoom]?.isEmpty ?? true) {
|
viewModel.roomMembers[currentRoom]?.isEmpty ?? true,
|
||||||
|
!viewModel.connectedPeers.contains(viewModel.meshService.myPeerID) {
|
||||||
Text("No one in this room yet")
|
Text("No one in this room yet")
|
||||||
.font(.system(size: 14, design: .monospaced))
|
.font(.system(size: 14, design: .monospaced))
|
||||||
.foregroundColor(secondaryTextColor)
|
.foregroundColor(secondaryTextColor)
|
||||||
@@ -579,14 +589,21 @@ struct ContentView: View {
|
|||||||
let myPeerID = viewModel.meshService.myPeerID
|
let myPeerID = viewModel.meshService.myPeerID
|
||||||
|
|
||||||
// Filter peers based on current room
|
// Filter peers based on current room
|
||||||
let peersToShow = if let currentRoom = viewModel.currentRoom,
|
let peersToShow: [String] = {
|
||||||
|
if let currentRoom = viewModel.currentRoom,
|
||||||
let roomMemberIDs = viewModel.roomMembers[currentRoom] {
|
let roomMemberIDs = viewModel.roomMembers[currentRoom] {
|
||||||
// Show only peers who have sent messages to this room
|
// Show only peers who have sent messages to this room (including self)
|
||||||
viewModel.connectedPeers.filter { roomMemberIDs.contains($0) && $0 != myPeerID }
|
var memberPeers = viewModel.connectedPeers.filter { roomMemberIDs.contains($0) }
|
||||||
|
// Always include ourselves if we're connected
|
||||||
|
if viewModel.connectedPeers.contains(myPeerID) {
|
||||||
|
memberPeers.append(myPeerID)
|
||||||
|
}
|
||||||
|
return Array(Set(memberPeers)) // Remove duplicates
|
||||||
} else {
|
} else {
|
||||||
// Show all connected peers in main chat
|
// Show all connected peers in main chat
|
||||||
viewModel.connectedPeers.filter { $0 != myPeerID }
|
return viewModel.connectedPeers
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Sort peers: favorites first, then alphabetically by nickname
|
// Sort peers: favorites first, then alphabetically by nickname
|
||||||
let sortedPeers = peersToShow.sorted { peer1, peer2 in
|
let sortedPeers = peersToShow.sorted { peer1, peer2 in
|
||||||
@@ -603,13 +620,18 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ForEach(sortedPeers, id: \.self) { peerID in
|
ForEach(sortedPeers, id: \.self) { peerID in
|
||||||
let displayName = peerNicknames[peerID] ?? "person-\(peerID.prefix(4))"
|
let displayName = peerID == myPeerID ? viewModel.nickname : (peerNicknames[peerID] ?? "person-\(peerID.prefix(4))")
|
||||||
let rssi = peerRSSI[peerID]?.intValue ?? -100
|
let rssi = peerRSSI[peerID]?.intValue ?? -100
|
||||||
let isFavorite = viewModel.isFavorite(peerID: peerID)
|
let isFavorite = viewModel.isFavorite(peerID: peerID)
|
||||||
|
let isMe = peerID == myPeerID
|
||||||
|
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
// Signal strength indicator or unread message icon
|
// Signal strength indicator or unread message icon
|
||||||
if viewModel.unreadPrivateMessages.contains(peerID) {
|
if isMe {
|
||||||
|
Text("•")
|
||||||
|
.font(.system(size: 12))
|
||||||
|
.foregroundColor(textColor)
|
||||||
|
} else if viewModel.unreadPrivateMessages.contains(peerID) {
|
||||||
Image(systemName: "envelope.fill")
|
Image(systemName: "envelope.fill")
|
||||||
.font(.system(size: 12))
|
.font(.system(size: 12))
|
||||||
.foregroundColor(Color.orange)
|
.foregroundColor(Color.orange)
|
||||||
@@ -619,7 +641,8 @@ struct ContentView: View {
|
|||||||
.frame(width: 8, height: 8)
|
.frame(width: 8, height: 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Favorite star
|
// Favorite star (not for self)
|
||||||
|
if !isMe {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
viewModel.toggleFavorite(peerID: peerID)
|
viewModel.toggleFavorite(peerID: peerID)
|
||||||
}) {
|
}) {
|
||||||
@@ -628,8 +651,18 @@ struct ContentView: View {
|
|||||||
.foregroundColor(isFavorite ? Color.yellow : secondaryTextColor)
|
.foregroundColor(isFavorite ? Color.yellow : secondaryTextColor)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
|
}
|
||||||
|
|
||||||
// Peer name button
|
// Peer name
|
||||||
|
if isMe {
|
||||||
|
HStack {
|
||||||
|
Text(displayName + " (you)")
|
||||||
|
.font(.system(size: 14, design: .monospaced))
|
||||||
|
.foregroundColor(textColor)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
if peerNicknames[peerID] != nil {
|
if peerNicknames[peerID] != nil {
|
||||||
viewModel.startPrivateChat(with: peerID)
|
viewModel.startPrivateChat(with: peerID)
|
||||||
@@ -650,6 +683,7 @@ struct ContentView: View {
|
|||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.disabled(peerNicknames[peerID] == nil)
|
.disabled(peerNicknames[peerID] == nil)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user