cleanup ios

This commit is contained in:
spaced4ndy
2025-10-10 22:04:41 +04:00
parent a76e09f633
commit 748ddb7e28
9 changed files with 33 additions and 131 deletions
-14
View File
@@ -158,7 +158,6 @@ enum ChatCommand: ChatCmdProtocol {
case apiGetCallInvitations
case apiCallStatus(contact: Contact, callStatus: WebRTCCallStatus)
// WebRTC calls /
case apiGetNetworkStatuses
case apiChatRead(type: ChatType, id: Int64, scope: GroupChatScope?)
case apiChatItemsRead(type: ChatType, id: Int64, scope: GroupChatScope?, itemIds: [Int64])
case apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool)
@@ -359,7 +358,6 @@ enum ChatCommand: ChatCmdProtocol {
case let .apiEndCall(contact): return "/_call end @\(contact.apiId)"
case .apiGetCallInvitations: return "/_call get"
case let .apiCallStatus(contact, callStatus): return "/_call status @\(contact.apiId) \(callStatus.rawValue)"
case .apiGetNetworkStatuses: return "/_network_statuses"
case let .apiChatRead(type, id, scope): return "/_read chat \(ref(type, id, scope: scope))"
case let .apiChatItemsRead(type, id, scope, itemIds): return "/_read chat items \(ref(type, id, scope: scope)) \(joinedIds(itemIds))"
case let .apiChatUnread(type, id, unreadChat): return "/_unread chat \(ref(type, id, scope: nil)) \(onOff(unreadChat))"
@@ -534,7 +532,6 @@ enum ChatCommand: ChatCmdProtocol {
case .apiEndCall: return "apiEndCall"
case .apiGetCallInvitations: return "apiGetCallInvitations"
case .apiCallStatus: return "apiCallStatus"
case .apiGetNetworkStatuses: return "apiGetNetworkStatuses"
case .apiChatRead: return "apiChatRead"
case .apiChatItemsRead: return "apiChatItemsRead"
case .apiChatUnread: return "apiChatUnread"
@@ -793,7 +790,6 @@ enum ChatResponse1: Decodable, ChatAPIResult {
case userContactLinkDeleted(user: User)
case acceptingContactRequest(user: UserRef, contact: Contact)
case contactRequestRejected(user: UserRef, contactRequest: UserContactRequest, contact_: Contact?)
case networkStatuses(user_: UserRef?, networkStatuses: [ConnNetworkStatus])
case newChatItems(user: UserRef, chatItems: [AChatItem])
case groupChatItemsDeleted(user: UserRef, groupInfo: GroupInfo, chatItemIDs: Set<Int64>, byUser: Bool, member_: GroupMember?)
case forwardPlan(user: UserRef, chatItemIds: [Int64], forwardConfirmation: ForwardConfirmation?)
@@ -837,7 +833,6 @@ enum ChatResponse1: Decodable, ChatAPIResult {
case .userContactLinkDeleted: "userContactLinkDeleted"
case .acceptingContactRequest: "acceptingContactRequest"
case .contactRequestRejected: "contactRequestRejected"
case .networkStatuses: "networkStatuses"
case .newChatItems: "newChatItems"
case .groupChatItemsDeleted: "groupChatItemsDeleted"
case .forwardPlan: "forwardPlan"
@@ -870,7 +865,6 @@ enum ChatResponse1: Decodable, ChatAPIResult {
case .userContactLinkDeleted: return noDetails
case let .acceptingContactRequest(u, contact): return withUser(u, String(describing: contact))
case let .contactRequestRejected(u, contactRequest, contact_): return withUser(u, "contactRequest: \(String(describing: contactRequest))\ncontact_: \(String(describing: contact_))")
case let .networkStatuses(u, statuses): return withUser(u, String(describing: statuses))
case let .newChatItems(u, chatItems):
let itemsString = chatItems.map { chatItem in String(describing: chatItem) }.joined(separator: "\n")
return withUser(u, itemsString)
@@ -1060,7 +1054,6 @@ enum ChatEvent: Decodable, ChatAPIResult {
case contactUpdated(user: UserRef, toContact: Contact)
case groupMemberUpdated(user: UserRef, groupInfo: GroupInfo, fromMember: GroupMember, toMember: GroupMember)
case networkStatus(networkStatus: NetworkStatus, connections: [String])
case networkStatuses(user_: UserRef?, networkStatuses: [ConnNetworkStatus])
case chatInfoUpdated(user: UserRef, chatInfo: ChatInfo)
case newChatItems(user: UserRef, chatItems: [AChatItem])
case chatItemsStatusesUpdated(user: UserRef, chatItems: [AChatItem])
@@ -1138,7 +1131,6 @@ enum ChatEvent: Decodable, ChatAPIResult {
case .contactUpdated: "contactUpdated"
case .groupMemberUpdated: "groupMemberUpdated"
case .networkStatus: "networkStatus"
case .networkStatuses: "networkStatuses"
case .chatInfoUpdated: "chatInfoUpdated"
case .newChatItems: "newChatItems"
case .chatItemsStatusesUpdated: "chatItemsStatusesUpdated"
@@ -1211,7 +1203,6 @@ enum ChatEvent: Decodable, ChatAPIResult {
case let .contactUpdated(u, toContact): return withUser(u, String(describing: toContact))
case let .groupMemberUpdated(u, groupInfo, fromMember, toMember): return withUser(u, "groupInfo: \(groupInfo)\nfromMember: \(fromMember)\ntoMember: \(toMember)")
case let .networkStatus(status, conns): return "networkStatus: \(String(describing: status))\nconnections: \(String(describing: conns))"
case let .networkStatuses(u, statuses): return withUser(u, String(describing: statuses))
case let .chatInfoUpdated(u, chatInfo): return withUser(u, String(describing: chatInfo))
case let .newChatItems(u, chatItems):
let itemsString = chatItems.map { chatItem in String(describing: chatItem) }.joined(separator: "\n")
@@ -1410,11 +1401,6 @@ enum ForwardConfirmation: Decodable, Hashable {
case filesFailed(filesCount: Int)
}
struct ConnNetworkStatus: Decodable {
var agentConnId: String
var networkStatus: NetworkStatus
}
struct UserMsgReceiptSettings: Codable {
var enable: Bool
var clearOverrides: Bool
-23
View File
@@ -283,29 +283,6 @@ class ChatTagsModel: ObservableObject {
}
}
class NetworkModel: ObservableObject {
// map of connections network statuses, key is agent connection id
@Published var networkStatuses: Dictionary<String, NetworkStatus> = [:]
static let shared = NetworkModel()
private init() { }
func setContactNetworkStatus(_ contact: Contact, _ status: NetworkStatus) {
if let conn = contact.activeConn {
networkStatuses[conn.agentConnId] = status
}
}
func contactNetworkStatus(_ contact: Contact) -> NetworkStatus {
if let conn = contact.activeConn {
networkStatuses[conn.agentConnId] ?? .unknown
} else {
.unknown
}
}
}
/// ChatItemWithMenu can depend on previous or next item for it's appearance
/// This dummy model is used to force an update of all chat items,
/// when they might have changed appearance.
+20 -50
View File
@@ -15,8 +15,6 @@ import SwiftUI
private var chatController: chat_ctrl?
private let networkStatusesLock = DispatchQueue(label: "chat.simplex.app.network-statuses.lock")
enum TerminalItem: Identifiable {
case cmd(Date, ChatCommand)
case res(Date, ChatAPIResult)
@@ -1640,7 +1638,8 @@ func acceptContactRequest(incognito: Bool, contactRequestId: Int64, inProgress:
} else {
ChatModel.shared.replaceChat(contactRequestChatId(contactRequestId), chat)
}
NetworkModel.shared.setContactNetworkStatus(contact, .connected)
// TODO [sub status] review
// NetworkModel.shared.setContactNetworkStatus(contact, .connected)
inProgress?.wrappedValue = false
}
if contact.sndReady {
@@ -1728,12 +1727,6 @@ func apiCallStatus(_ contact: Contact, _ status: String) async throws {
}
}
func apiGetNetworkStatuses() throws -> [ConnNetworkStatus] {
let r: ChatResponse1 = try chatSendCmdSync(.apiGetNetworkStatuses)
if case let .networkStatuses(_, statuses) = r { return statuses }
throw r.unexpected
}
func markChatRead(_ im: ItemsModel, _ chat: Chat) async {
do {
if chat.chatStats.unreadCount > 0 {
@@ -1955,7 +1948,8 @@ func acceptMemberContact(contactId: Int64, inProgress: Binding<Bool>? = nil) asy
if let contact = await apiAcceptMemberContact(contactId: contactId) {
await MainActor.run {
ChatModel.shared.updateContact(contact)
NetworkModel.shared.setContactNetworkStatus(contact, .connected)
// TODO [sub status] review
// NetworkModel.shared.setContactNetworkStatus(contact, .connected)
inProgress?.wrappedValue = false
}
if contact.sndReady {
@@ -2241,7 +2235,6 @@ class ChatReceiver {
func processReceivedMsg(_ res: ChatEvent) async {
let m = ChatModel.shared
let n = NetworkModel.shared
logger.debug("processReceivedMsg: \(res.responseType)")
switch res {
case let .contactDeletedByContact(user, contact):
@@ -2263,9 +2256,10 @@ func processReceivedMsg(_ res: ChatEvent) async {
if contact.directOrUsed {
NtfManager.shared.notifyContactConnected(user, contact)
}
await MainActor.run {
n.setContactNetworkStatus(contact, .connected)
}
// TODO [sub status] review
// await MainActor.run {
// n.setContactNetworkStatus(contact, .connected)
// }
case let .contactConnecting(user, contact):
if active(user) && contact.directOrUsed {
await MainActor.run {
@@ -2286,9 +2280,10 @@ func processReceivedMsg(_ res: ChatEvent) async {
}
}
}
await MainActor.run {
n.setContactNetworkStatus(contact, .connected)
}
// TODO [sub status] review
// await MainActor.run {
// n.setContactNetworkStatus(contact, .connected)
// }
case let .receivedContactRequest(user, contactRequest, chat_):
if active(user) {
await MainActor.run {
@@ -2328,31 +2323,8 @@ func processReceivedMsg(_ res: ChatEvent) async {
}
}
case let .networkStatus(status, connections):
// dispatch queue to synchronize access
networkStatusesLock.sync {
var ns = n.networkStatuses
// slow loop is on the background thread
for cId in connections {
ns[cId] = status
}
// fast model update is on the main thread
DispatchQueue.main.sync {
n.networkStatuses = ns
}
}
case let .networkStatuses(_, statuses): ()
// dispatch queue to synchronize access
networkStatusesLock.sync {
var ns = n.networkStatuses
// slow loop is on the background thread
for s in statuses {
ns[s.agentConnId] = s.networkStatus
}
// fast model update is on the main thread
DispatchQueue.main.sync {
n.networkStatuses = ns
}
}
// TODO [sub status] update status for current chat in model if id matches
return
case let .chatInfoUpdated(user, chatInfo):
if active(user) {
await MainActor.run {
@@ -2554,11 +2526,12 @@ func processReceivedMsg(_ res: ChatEvent) async {
_ = m.upsertGroupMember(groupInfo, member)
}
}
if let contact = memberContact {
await MainActor.run {
n.setContactNetworkStatus(contact, .connected)
}
}
// TODO [sub status] review
// if let contact = memberContact {
// await MainActor.run {
// n.setContactNetworkStatus(contact, .connected)
// }
// }
case let .groupUpdated(user, toGroup):
if active(user) {
await MainActor.run {
@@ -2784,13 +2757,10 @@ func processReceivedMsg(_ res: ChatEvent) async {
func switchToLocalSession() {
let m = ChatModel.shared
let n = NetworkModel.shared
m.remoteCtrlSession = nil
do {
m.users = try listUsers()
try getUserChatData()
let statuses = (try apiGetNetworkStatuses()).map { s in (s.agentConnId, s.networkStatus) }
n.networkStatuses = Dictionary(uniqueKeysWithValues: statuses)
} catch let error {
logger.debug("error updating chat data: \(responseError(error))")
}
@@ -92,7 +92,6 @@ struct ChatInfoView: View {
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var theme: AppTheme
@Environment(\.dismiss) var dismiss: DismissAction
@ObservedObject var networkModel = NetworkModel.shared
@ObservedObject var chat: Chat
@State var contact: Contact
@State var localAlias: String
@@ -553,14 +552,17 @@ struct ChatInfoView: View {
.foregroundColor(theme.colors.primary)
.font(.system(size: 14))
Spacer()
Text(networkModel.contactNetworkStatus(contact).statusString)
// TODO [sub status] use status from model
// Text(networkModel.contactNetworkStatus(contact).statusString)
Text(NetworkStatus.connected.statusString)
.foregroundColor(theme.colors.secondary)
serverImage()
}
}
private func serverImage() -> some View {
let status = networkModel.contactNetworkStatus(contact)
// TODO [sub status] use status from model
let status = NetworkStatus.connected // networkModel.contactNetworkStatus(contact)
return Image(systemName: status.imageName)
.foregroundColor(status == .connected ? .green : theme.colors.secondary)
.font(.system(size: 12))
@@ -608,7 +610,8 @@ struct ChatInfoView: View {
private func networkStatusAlert() -> Alert {
Alert(
title: Text("Network status"),
message: Text(networkModel.contactNetworkStatus(contact).statusExplanation)
// TODO [sub status] use status from model
message: Text("") // Text(networkModel.contactNetworkStatus(contact).statusExplanation)
)
}
@@ -788,7 +788,8 @@ struct ComposeView: View {
await MainActor.run {
self.chatModel.updateContact(contact)
clearState()
NetworkModel.shared.setContactNetworkStatus(contact, .connected)
// TODO [sub status] review
// NetworkModel.shared.setContactNetworkStatus(contact, .connected)
}
} else {
AlertManager.shared.showAlertMsg(title: "Empty message!")
@@ -827,7 +828,8 @@ struct ComposeView: View {
if let contact = await apiConnectPreparedContact(contactId: chat.chatInfo.apiId, incognito: incognito, msg: mc) {
await MainActor.run {
self.chatModel.updateContact(contact)
NetworkModel.shared.setContactNetworkStatus(contact, .connected)
// TODO [sub status] review
// NetworkModel.shared.setContactNetworkStatus(contact, .connected)
clearState()
}
} else {
@@ -396,7 +396,8 @@ struct GroupMemberInfoView: View {
ItemsModel.shared.loadOpenChat(memberContact.id) {
dismissAllSheets(animated: true)
}
NetworkModel.shared.setContactNetworkStatus(memberContact, .connected)
// TODO [sub status] review
// NetworkModel.shared.setContactNetworkStatus(memberContact, .connected)
}
} catch let error {
logger.error("createMemberContactButton apiCreateMemberContact error: \(responseError(error))")
@@ -460,12 +460,6 @@ struct ChatPreviewView: View {
@ViewBuilder private func chatStatusImage() -> some View {
let size = dynamicSize(userFont).incognitoSize
switch chat.chatInfo {
case let .direct(contact):
if contact.active, let status = contact.activeConn?.connStatus, status == .ready || status == .sndReady {
NetworkStatusView(contact: contact, size: size)
} else {
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary, size: size)
}
case .group:
if progressByTimeout {
ProgressView()
@@ -482,30 +476,6 @@ struct ChatPreviewView: View {
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary, size: size)
}
}
struct NetworkStatusView: View {
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
@EnvironmentObject var theme: AppTheme
@ObservedObject var networkModel = NetworkModel.shared
let contact: Contact
let size: CGFloat
var body: some View {
let dynamicChatInfoSize = dynamicSize(userFont).chatInfoSize
switch (networkModel.contactNetworkStatus(contact)) {
case .connected: incognitoIcon(contact.contactConnIncognito, theme.colors.secondary, size: size)
case .error:
Image(systemName: "exclamationmark.circle")
.resizable()
.scaledToFit()
.frame(width: dynamicChatInfoSize, height: dynamicChatInfoSize)
.foregroundColor(theme.colors.secondary)
default:
ProgressView()
}
}
}
}
@ViewBuilder func incognitoIcon(_ incognito: Bool, _ secondaryColor: Color, size: CGFloat) -> some View {
-6
View File
@@ -28,12 +28,6 @@ chatStartedSwift = "{\"result\":{\"_owsf\":true,\"chatStarted\":{}}}"
chatStartedTagged :: LB.ByteString
chatStartedTagged = "{\"result\":{\"type\":\"chatStarted\"}}"
networkStatusesSwift :: LB.ByteString
networkStatusesSwift = "{\"result\":{\"_owsf\":true,\"networkStatuses\":{\"user_\":" <> userJSON <> ",\"networkStatuses\":[]}}}"
networkStatusesTagged :: LB.ByteString
networkStatusesTagged = "{\"result\":{\"type\":\"networkStatuses\",\"user_\":" <> userJSON <> ",\"networkStatuses\":[]}}"
userJSON :: LB.ByteString
userJSON = "{\"userId\":1,\"agentUserId\":\"1\",\"userContactId\":1,\"localDisplayName\":\"alice\",\"profile\":{\"profileId\":1,\"displayName\":\"alice\",\"fullName\":\"\",\"shortDescr\":\"Alice\",\"localAlias\":\"\"},\"fullPreferences\":{\"timedMessages\":{\"allow\":\"yes\"},\"fullDelete\":{\"allow\":\"no\"},\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"},\"files\":{\"allow\":\"always\"},\"calls\":{\"allow\":\"yes\"},\"sessions\":{\"allow\":\"no\"},\"commands\":[]},\"activeUser\":true,\"activeOrder\":1,\"showNtfs\":true,\"sendRcptsContacts\":true,\"sendRcptsSmallGroups\":true,\"autoAcceptMemberContacts\":false}"
-1
View File
@@ -25,7 +25,6 @@ owsf2TaggedJSONTest = do
activeUserExistsSwift `to` activeUserExistsTagged
activeUserSwift `to` activeUserTagged
chatStartedSwift `to` chatStartedTagged
networkStatusesSwift `to` networkStatusesTagged
parsedMarkdownSwift `to` parsedMarkdownTagged
where
to :: LB.ByteString -> LB.ByteString -> IO ()