Add iOS chat list status indicators
This commit is contained in:
@@ -17,13 +17,19 @@ public struct RootView: View {
|
||||
Group {
|
||||
switch store.authState {
|
||||
case .ready:
|
||||
ChatListView(viewModel: chatListViewModel, bridge: store.bridge)
|
||||
ChatListView(
|
||||
viewModel: chatListViewModel,
|
||||
bridge: store.bridge,
|
||||
networkState: store.networkState,
|
||||
typingState: store.typingState
|
||||
)
|
||||
default:
|
||||
AuthView(state: store.authState, viewModel: authViewModel)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
await store.refreshAuthState()
|
||||
await store.refreshNetworkState()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,22 +124,34 @@ public struct AuthView: View {
|
||||
public struct ChatListView: View {
|
||||
@ObservedObject public var viewModel: ChatListViewModel
|
||||
public let bridge: SessionBridge
|
||||
public var networkState: NetworkState
|
||||
public var typingState: TypingState
|
||||
@State private var selectedChat: ChatSummary?
|
||||
@State private var showsAccountSwitcher = false
|
||||
|
||||
public init(viewModel: ChatListViewModel, bridge: SessionBridge) {
|
||||
public init(
|
||||
viewModel: ChatListViewModel,
|
||||
bridge: SessionBridge,
|
||||
networkState: NetworkState = .ready,
|
||||
typingState: TypingState = .idle
|
||||
) {
|
||||
self.viewModel = viewModel
|
||||
self.bridge = bridge
|
||||
self.networkState = networkState
|
||||
self.typingState = typingState
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
NavigationSplitView {
|
||||
List(selection: $selectedChat) {
|
||||
ForEach(viewModel.filteredChats) { chat in
|
||||
NavigationLink(value: chat) {
|
||||
ChatRow(chat: chat)
|
||||
VStack(spacing: 0) {
|
||||
List(selection: $selectedChat) {
|
||||
ForEach(viewModel.filteredChats) { chat in
|
||||
NavigationLink(value: chat) {
|
||||
ChatRow(chat: chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
ChatListStatusBar(networkState: networkState, typingState: typingState)
|
||||
}
|
||||
.navigationTitle("Chats")
|
||||
.searchable(text: $viewModel.searchText)
|
||||
@@ -178,6 +196,71 @@ public struct ChatListView: View {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ChatListStatusBar: View {
|
||||
public var networkState: NetworkState
|
||||
public var typingState: TypingState
|
||||
|
||||
public init(networkState: NetworkState, typingState: TypingState) {
|
||||
self.networkState = networkState
|
||||
self.typingState = typingState
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: networkIconName)
|
||||
.foregroundStyle(networkState == .ready ? .green : .orange)
|
||||
Text(statusText)
|
||||
.font(.footnote)
|
||||
.lineLimit(1)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(.bar)
|
||||
}
|
||||
|
||||
private var networkIconName: String {
|
||||
switch networkState {
|
||||
case .ready:
|
||||
"checkmark.circle.fill"
|
||||
case .waitingForNetwork:
|
||||
"wifi.slash"
|
||||
case .connectingToProxy:
|
||||
"shield.lefthalf.filled"
|
||||
case .connecting:
|
||||
"antenna.radiowaves.left.and.right"
|
||||
case .updating:
|
||||
"arrow.triangle.2.circlepath"
|
||||
}
|
||||
}
|
||||
|
||||
private var statusText: String {
|
||||
switch typingState {
|
||||
case let .typing(_, _, text) where !text.isEmpty:
|
||||
text
|
||||
case .typing:
|
||||
"Typing"
|
||||
case .idle:
|
||||
networkText
|
||||
}
|
||||
}
|
||||
|
||||
private var networkText: String {
|
||||
switch networkState {
|
||||
case .ready:
|
||||
"Online"
|
||||
case .waitingForNetwork:
|
||||
"Waiting for network"
|
||||
case .connectingToProxy:
|
||||
"Connecting to proxy"
|
||||
case .connecting:
|
||||
"Connecting"
|
||||
case .updating:
|
||||
"Updating"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct ChatRow: View {
|
||||
public var chat: ChatSummary
|
||||
|
||||
@@ -195,7 +278,20 @@ public struct ChatRow: View {
|
||||
Image(systemName: "pin.fill")
|
||||
.font(.caption)
|
||||
}
|
||||
if chat.isMuted {
|
||||
Image(systemName: "bell.slash")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
if chat.unreadMentionCount > 0 {
|
||||
Text("@\(chat.unreadMentionCount)")
|
||||
.font(.caption)
|
||||
.padding(.horizontal, 7)
|
||||
.padding(.vertical, 3)
|
||||
.background(.orange, in: Capsule())
|
||||
.foregroundStyle(.white)
|
||||
}
|
||||
if chat.unreadCount > 0 {
|
||||
Text("\(chat.unreadCount)")
|
||||
.font(.caption)
|
||||
@@ -205,7 +301,13 @@ public struct ChatRow: View {
|
||||
.foregroundStyle(.white)
|
||||
}
|
||||
}
|
||||
Text(chat.draft?.text ?? chat.lastMessage)
|
||||
HStack(spacing: 4) {
|
||||
if chat.draft != nil {
|
||||
Text("Draft")
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
Text(chat.draft?.text ?? chat.lastMessage)
|
||||
}
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(chat.draft == nil ? Color.secondary : Color.red)
|
||||
.lineLimit(2)
|
||||
|
||||
Reference in New Issue
Block a user