mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-29 04:39:53 +00:00
ios: programmatic navigation between list/chat (#980)
* ios: programmatic navigation between list/chat * prevent chat info sheet from showing when switching conversation * add direct chat with member to model * set status to connected Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com>
This commit is contained in:
parent
7343e4a51a
commit
51a2fa8c28
9 changed files with 66 additions and 27 deletions
|
@ -59,6 +59,16 @@ final class ChatModel: ObservableObject {
|
|||
chats.first(where: { $0.id == id })
|
||||
}
|
||||
|
||||
func getContactChat(_ contactId: Int64) -> Chat? {
|
||||
chats.first { chat in
|
||||
if case let .direct(contact) = chat.chatInfo {
|
||||
return contact.contactId == contactId
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func getChatIndex(_ id: String) -> Int? {
|
||||
chats.firstIndex(where: { $0.id == id })
|
||||
}
|
||||
|
|
|
@ -206,8 +206,9 @@ func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, sear
|
|||
func loadChat(chat: Chat, search: String = "") {
|
||||
do {
|
||||
let cInfo = chat.chatInfo
|
||||
let chat = try apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search)
|
||||
let m = ChatModel.shared
|
||||
m.reversedChatItems = []
|
||||
let chat = try apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search)
|
||||
m.updateChatInfo(chat.chatInfo)
|
||||
m.reversedChatItems = chat.chatItems.reversed()
|
||||
} catch let error {
|
||||
|
|
|
@ -216,6 +216,7 @@ struct ChatInfoView: View {
|
|||
try await apiDeleteChat(type: chat.chatInfo.chatType, id: chat.chatInfo.apiId)
|
||||
await MainActor.run {
|
||||
chatModel.removeChat(chat.chatInfo.id)
|
||||
chatModel.chatId = nil
|
||||
dismiss()
|
||||
}
|
||||
} catch let error {
|
||||
|
|
|
@ -72,7 +72,10 @@ struct ChatView: View {
|
|||
}
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "chevron.backward")
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: "chevron.backward")
|
||||
Text("Chats")
|
||||
}
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .principal) {
|
||||
|
@ -235,6 +238,15 @@ struct ChatView: View {
|
|||
.onChange(of: searchText) { _ in
|
||||
loadChat(chat: chat, search: searchText)
|
||||
}
|
||||
.onChange(of: chatModel.chatId) { _ in
|
||||
if let chatId = chatModel.chatId, let chat = chatModel.getChat(chatId) {
|
||||
showChatInfoSheet = false
|
||||
loadChat(chat: chat)
|
||||
DispatchQueue.main.async {
|
||||
scrollToBottom(proxy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.scaleEffect(x: 1, y: -1, anchor: .center)
|
||||
|
|
|
@ -221,6 +221,7 @@ struct GroupChatInfoView: View {
|
|||
try await apiDeleteChat(type: chat.chatInfo.chatType, id: chat.chatInfo.apiId)
|
||||
await MainActor.run {
|
||||
chatModel.removeChat(chat.chatInfo.id)
|
||||
chatModel.chatId = nil
|
||||
dismiss()
|
||||
}
|
||||
} catch let error {
|
||||
|
|
|
@ -30,11 +30,11 @@ struct GroupMemberInfoView: View {
|
|||
groupMemberInfoHeader()
|
||||
.listRowBackground(Color.clear)
|
||||
|
||||
// if let contactId = member.memberContactId {
|
||||
// Section {
|
||||
// openDirectChatButton(contactId)
|
||||
// }
|
||||
// }
|
||||
if let contactId = member.memberContactId {
|
||||
Section {
|
||||
openDirectChatButton(contactId)
|
||||
}
|
||||
}
|
||||
|
||||
Section("Member") {
|
||||
infoRow("Group", groupInfo.displayName)
|
||||
|
@ -80,18 +80,25 @@ struct GroupMemberInfoView: View {
|
|||
|
||||
func openDirectChatButton(_ contactId: Int64) -> some View {
|
||||
Button {
|
||||
if let i = chatModel.chats.firstIndex(where: { chat in
|
||||
switch chat.chatInfo {
|
||||
case let .direct(contact): return contact.contactId == contactId
|
||||
default: return false
|
||||
var chat = chatModel.getContactChat(contactId)
|
||||
if chat == nil {
|
||||
do {
|
||||
chat = try apiGetChat(type: .direct, id: contactId)
|
||||
if let chat = chat {
|
||||
// TODO it's not correct to blindly set network status to connected - we should manage network status in model / backend
|
||||
chat.serverInfo = Chat.ServerInfo(networkStatus: .connected)
|
||||
chatModel.addChat(chat)
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("openDirectChatButton apiGetChat error: \(responseError(error))")
|
||||
}
|
||||
}) {
|
||||
}
|
||||
if let chat = chat {
|
||||
dismissAllSheets(animated: true)
|
||||
chatModel.chatId = chatModel.chats[i].chatInfo.id
|
||||
chatModel.chatId = chat.id
|
||||
}
|
||||
} label: {
|
||||
Label("Send direct message", systemImage: "message")
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,16 +28,10 @@ struct ChatListNavLink: View {
|
|||
}
|
||||
}
|
||||
|
||||
private func chatView() -> some View {
|
||||
ChatView(chat: chat)
|
||||
.onAppear { loadChat(chat: chat) }
|
||||
}
|
||||
|
||||
@ViewBuilder private func contactNavLink(_ contact: Contact) -> some View {
|
||||
let v = NavLinkPlain(
|
||||
tag: chat.chatInfo.id,
|
||||
selection: $chatModel.chatId,
|
||||
destination: { chatView() },
|
||||
label: { ChatPreviewView(chat: chat) },
|
||||
disabled: !contact.ready
|
||||
)
|
||||
|
@ -97,7 +91,6 @@ struct ChatListNavLink: View {
|
|||
NavLinkPlain(
|
||||
tag: chat.chatInfo.id,
|
||||
selection: $chatModel.chatId,
|
||||
destination: { chatView() },
|
||||
label: { ChatPreviewView(chat: chat) },
|
||||
disabled: !groupInfo.ready
|
||||
)
|
||||
|
|
|
@ -14,6 +14,7 @@ struct ChatListView: View {
|
|||
// not really used in this view
|
||||
@State private var showSettings = false
|
||||
@State private var searchText = ""
|
||||
@State private var selectedChat: ChatId?
|
||||
|
||||
var body: some View {
|
||||
let v = NavigationView {
|
||||
|
@ -25,6 +26,7 @@ struct ChatListView: View {
|
|||
}
|
||||
}
|
||||
.onChange(of: chatModel.chatId) { _ in
|
||||
selectedChat = chatModel.chatId
|
||||
if chatModel.chatId == nil, let chatId = chatModel.chatToTop {
|
||||
chatModel.chatToTop = nil
|
||||
chatModel.popChat(chatId)
|
||||
|
@ -63,6 +65,15 @@ struct ChatListView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.background(
|
||||
NavigationLink(
|
||||
destination: chatView(selectedChat),
|
||||
isActive: Binding(
|
||||
get: { selectedChat != nil },
|
||||
set: { _, _ in selectedChat = nil }
|
||||
)
|
||||
) { EmptyView() }
|
||||
)
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
|
||||
|
@ -73,6 +84,14 @@ struct ChatListView: View {
|
|||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func chatView(_ chatId: ChatId?) -> some View {
|
||||
if let chatId = chatId, let chat = chatModel.getChat(chatId) {
|
||||
ChatView(chat: chat).onAppear {
|
||||
loadChat(chat: chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func filteredChats() -> [Chat] {
|
||||
let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase
|
||||
return s == ""
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
struct NavLinkPlain<V: Hashable, Destination: View, Label: View>: View {
|
||||
struct NavLinkPlain<V: Hashable, Label: View>: View {
|
||||
@State var tag: V
|
||||
@Binding var selection: V?
|
||||
@ViewBuilder var destination: () -> Destination
|
||||
@ViewBuilder var label: () -> Label
|
||||
var disabled = false
|
||||
|
||||
|
@ -21,10 +20,6 @@ struct NavLinkPlain<V: Hashable, Destination: View, Label: View>: View {
|
|||
.disabled(disabled)
|
||||
label()
|
||||
}
|
||||
.background {
|
||||
NavigationLink("", tag: tag, selection: $selection, destination: destination)
|
||||
.hidden()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue