mobile: use batched DOWN/UP events, core: include pending contacts (#573)

* mobile: use batched DOWN/UP events, core: include pending contacts

* query style
This commit is contained in:
Evgeny Poberezkin 2022-04-26 07:51:06 +01:00 committed by GitHub
parent 44de6297ee
commit fc5cdc5eb1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 43 deletions

View file

@ -67,8 +67,8 @@ class ChatModel(val controller: ChatController) {
} }
} }
fun updateNetworkStatus(contact: Contact, status: Chat.NetworkStatus) { fun updateNetworkStatus(id: ChatId, status: Chat.NetworkStatus) {
val i = getChatIndex(contact.id) val i = getChatIndex(id)
if (i >= 0) { if (i >= 0) {
val chat = chats[i] val chat = chats[i]
chats[i] = chat.copy(serverInfo = chat.serverInfo.copy(networkStatus = status)) chats[i] = chat.copy(serverInfo = chat.serverInfo.copy(networkStatus = status))
@ -389,6 +389,14 @@ class Contact(
} }
} }
@Serializable
class ContactRef(
val contactId: Long,
var localDisplayName: String
) {
val id: ChatId get() = "@$contactId"
}
@Serializable @Serializable
class ContactSubStatus( class ContactSubStatus(
val contact: Contact, val contact: Contact,

View file

@ -352,7 +352,7 @@ open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: Nt
is CR.ContactConnected -> { is CR.ContactConnected -> {
chatModel.updateContact(r.contact) chatModel.updateContact(r.contact)
chatModel.removeChat(r.contact.activeConn.id) chatModel.removeChat(r.contact.activeConn.id)
chatModel.updateNetworkStatus(r.contact, Chat.NetworkStatus.Connected()) chatModel.updateNetworkStatus(r.contact.id, Chat.NetworkStatus.Connected())
// NtfManager.shared.notifyContactConnected(contact) // NtfManager.shared.notifyContactConnected(contact)
} }
is CR.ContactConnecting -> { is CR.ContactConnecting -> {
@ -371,17 +371,18 @@ open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: Nt
chatModel.updateChatInfo(cInfo) chatModel.updateChatInfo(cInfo)
} }
} }
is CR.ContactSubscribed -> processContactSubscribed(r.contact) is CR.ContactsSubscribed -> updateContactsStatus(r.contactRefs, Chat.NetworkStatus.Connected())
is CR.ContactDisconnected -> { is CR.ContactsDisconnected -> updateContactsStatus(r.contactRefs, Chat.NetworkStatus.Disconnected())
chatModel.updateContact(r.contact)
chatModel.updateNetworkStatus(r.contact, Chat.NetworkStatus.Disconnected())
}
is CR.ContactSubError -> processContactSubError(r.contact, r.chatError) is CR.ContactSubError -> processContactSubError(r.contact, r.chatError)
is CR.ContactSubSummary -> { is CR.ContactSubSummary -> {
for (sub in r.contactSubscriptions) { for (sub in r.contactSubscriptions) {
val err = sub.contactError val err = sub.contactError
if (err == null) processContactSubscribed(sub.contact) if (err == null) {
else processContactSubError(sub.contact, sub.contactError) chatModel.updateContact(sub.contact)
chatModel.updateNetworkStatus(sub.contact.id, Chat.NetworkStatus.Connected())
} else {
processContactSubError(sub.contact, sub.contactError)
}
} }
} }
is CR.NewChatItem -> { is CR.NewChatItem -> {
@ -436,9 +437,10 @@ open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: Nt
} }
} }
fun processContactSubscribed(contact: Contact) { fun updateContactsStatus(contactRefs: List<ContactRef>, status: Chat.NetworkStatus) {
chatModel.updateContact(contact) for (c in contactRefs) {
chatModel.updateNetworkStatus(contact, Chat.NetworkStatus.Connected()) chatModel.updateNetworkStatus(c.id, status)
}
} }
fun processContactSubError(contact: Contact, chatError: ChatError) { fun processContactSubError(contact: Contact, chatError: ChatError) {
@ -454,7 +456,7 @@ open class ChatController(private val ctrl: ChatCtrl, private val ntfManager: Nt
} }
} }
else e.string else e.string
chatModel.updateNetworkStatus(contact, Chat.NetworkStatus.Error(err)) chatModel.updateNetworkStatus(contact.id, Chat.NetworkStatus.Error(err))
} }
fun showBackgroundServiceNotice() { fun showBackgroundServiceNotice() {
@ -667,8 +669,8 @@ sealed class CR {
@Serializable @SerialName("acceptingContactRequest") class AcceptingContactRequest(val contact: Contact): CR() @Serializable @SerialName("acceptingContactRequest") class AcceptingContactRequest(val contact: Contact): CR()
@Serializable @SerialName("contactRequestRejected") class ContactRequestRejected: CR() @Serializable @SerialName("contactRequestRejected") class ContactRequestRejected: CR()
@Serializable @SerialName("contactUpdated") class ContactUpdated(val toContact: Contact): CR() @Serializable @SerialName("contactUpdated") class ContactUpdated(val toContact: Contact): CR()
@Serializable @SerialName("contactSubscribed") class ContactSubscribed(val contact: Contact): CR() @Serializable @SerialName("contactsSubscribed") class ContactsSubscribed(val server: String, val contactRefs: List<ContactRef>): CR()
@Serializable @SerialName("contactDisconnected") class ContactDisconnected(val contact: Contact): CR() @Serializable @SerialName("contactsDisconnected") class ContactsDisconnected(val server: String, val contactRefs: List<ContactRef>): CR()
@Serializable @SerialName("contactSubError") class ContactSubError(val contact: Contact, val chatError: ChatError): CR() @Serializable @SerialName("contactSubError") class ContactSubError(val contact: Contact, val chatError: ChatError): CR()
@Serializable @SerialName("contactSubSummary") class ContactSubSummary(val contactSubscriptions: List<ContactSubStatus>): CR() @Serializable @SerialName("contactSubSummary") class ContactSubSummary(val contactSubscriptions: List<ContactSubStatus>): CR()
@Serializable @SerialName("groupSubscribed") class GroupSubscribed(val group: GroupInfo): CR() @Serializable @SerialName("groupSubscribed") class GroupSubscribed(val group: GroupInfo): CR()
@ -713,8 +715,8 @@ sealed class CR {
is AcceptingContactRequest -> "acceptingContactRequest" is AcceptingContactRequest -> "acceptingContactRequest"
is ContactRequestRejected -> "contactRequestRejected" is ContactRequestRejected -> "contactRequestRejected"
is ContactUpdated -> "contactUpdated" is ContactUpdated -> "contactUpdated"
is ContactSubscribed -> "contactSubscribed" is ContactsSubscribed -> "contactsSubscribed"
is ContactDisconnected -> "contactDisconnected" is ContactsDisconnected -> "contactsDisconnected"
is ContactSubError -> "contactSubError" is ContactSubError -> "contactSubError"
is ContactSubSummary -> "contactSubSummary" is ContactSubSummary -> "contactSubSummary"
is GroupSubscribed -> "groupSubscribed" is GroupSubscribed -> "groupSubscribed"
@ -760,8 +762,8 @@ sealed class CR {
is AcceptingContactRequest -> json.encodeToString(contact) is AcceptingContactRequest -> json.encodeToString(contact)
is ContactRequestRejected -> noDetails() is ContactRequestRejected -> noDetails()
is ContactUpdated -> json.encodeToString(toContact) is ContactUpdated -> json.encodeToString(toContact)
is ContactSubscribed -> json.encodeToString(contact) is ContactsSubscribed -> "server: $server\ncontacts:\n${json.encodeToString(contactRefs)}"
is ContactDisconnected -> json.encodeToString(contact) is ContactsDisconnected -> "server: $server\ncontacts:\n${json.encodeToString(contactRefs)}"
is ContactSubError -> "error:\n${chatError.string}\ncontact:\n${json.encodeToString(contact)}" is ContactSubError -> "error:\n${chatError.string}\ncontact:\n${json.encodeToString(contact)}"
is ContactSubSummary -> json.encodeToString(contactSubscriptions) is ContactSubSummary -> json.encodeToString(contactSubscriptions)
is GroupSubscribed -> json.encodeToString(group) is GroupSubscribed -> json.encodeToString(group)

View file

@ -70,9 +70,9 @@ final class ChatModel: ObservableObject {
} }
} }
func updateNetworkStatus(_ contact: Contact, _ status: Chat.NetworkStatus) { func updateNetworkStatus(_ id: ChatId, _ status: Chat.NetworkStatus) {
if let ix = getChatIndex(contact.id) { if let i = getChatIndex(id) {
chats[ix].serverInfo.networkStatus = status chats[i].serverInfo.networkStatus = status
} }
} }
@ -488,6 +488,13 @@ struct Contact: Identifiable, Decodable, NamedChat {
) )
} }
struct ContactRef: Decodable {
var contactId: Int64
var localDisplayName: ContactName
var id: ChatId { get { "@\(contactId)" } }
}
struct ContactSubStatus: Decodable { struct ContactSubStatus: Decodable {
var contact: Contact var contact: Contact
var contactError: ChatError? var contactError: ChatError?

View file

@ -159,8 +159,8 @@ enum ChatResponse: Decodable, Error {
case acceptingContactRequest(contact: Contact) case acceptingContactRequest(contact: Contact)
case contactRequestRejected case contactRequestRejected
case contactUpdated(toContact: Contact) case contactUpdated(toContact: Contact)
case contactSubscribed(contact: Contact) case contactsSubscribed(server: String, contactRefs: [ContactRef])
case contactDisconnected(contact: Contact) case contactsDisconnected(server: String, contactRefs: [ContactRef])
case contactSubError(contact: Contact, chatError: ChatError) case contactSubError(contact: Contact, chatError: ChatError)
case contactSubSummary(contactSubscriptions: [ContactSubStatus]) case contactSubSummary(contactSubscriptions: [ContactSubStatus])
case groupSubscribed(groupInfo: GroupInfo) case groupSubscribed(groupInfo: GroupInfo)
@ -207,8 +207,8 @@ enum ChatResponse: Decodable, Error {
case .acceptingContactRequest: return "acceptingContactRequest" case .acceptingContactRequest: return "acceptingContactRequest"
case .contactRequestRejected: return "contactRequestRejected" case .contactRequestRejected: return "contactRequestRejected"
case .contactUpdated: return "contactUpdated" case .contactUpdated: return "contactUpdated"
case .contactSubscribed: return "contactSubscribed" case .contactsSubscribed: return "contactsSubscribed"
case .contactDisconnected: return "contactDisconnected" case .contactsDisconnected: return "contactsDisconnected"
case .contactSubError: return "contactSubError" case .contactSubError: return "contactSubError"
case .contactSubSummary: return "contactSubSummary" case .contactSubSummary: return "contactSubSummary"
case .groupSubscribed: return "groupSubscribed" case .groupSubscribed: return "groupSubscribed"
@ -258,8 +258,8 @@ enum ChatResponse: Decodable, Error {
case let .acceptingContactRequest(contact): return String(describing: contact) case let .acceptingContactRequest(contact): return String(describing: contact)
case .contactRequestRejected: return noDetails case .contactRequestRejected: return noDetails
case let .contactUpdated(toContact): return String(describing: toContact) case let .contactUpdated(toContact): return String(describing: toContact)
case let .contactSubscribed(contact): return String(describing: contact) case let .contactsSubscribed(server, contactRefs): return "server: \(server)\ncontacts:\n\(String(describing: contactRefs))"
case let .contactDisconnected(contact): return String(describing: contact) case let .contactsDisconnected(server, contactRefs): return "server: \(server)\ncontacts:\n\(String(describing: contactRefs))"
case let .contactSubError(contact, chatError): return "contact:\n\(String(describing: contact))\nerror:\n\(String(describing: chatError))" case let .contactSubError(contact, chatError): return "contact:\n\(String(describing: contact))\nerror:\n\(String(describing: chatError))"
case let .contactSubSummary(contactSubscriptions): return String(describing: contactSubscriptions) case let .contactSubSummary(contactSubscriptions): return String(describing: contactSubscriptions)
case let .groupSubscribed(groupInfo): return String(describing: groupInfo) case let .groupSubscribed(groupInfo): return String(describing: groupInfo)
@ -720,7 +720,7 @@ func processReceivedMsg(_ res: ChatResponse) {
case let .contactConnected(contact): case let .contactConnected(contact):
m.updateContact(contact) m.updateContact(contact)
m.removeChat(contact.activeConn.id) m.removeChat(contact.activeConn.id)
m.updateNetworkStatus(contact, .connected) m.updateNetworkStatus(contact.id, .connected)
NtfManager.shared.notifyContactConnected(contact) NtfManager.shared.notifyContactConnected(contact)
case let .contactConnecting(contact): case let .contactConnecting(contact):
m.updateContact(contact) m.updateContact(contact)
@ -736,11 +736,10 @@ func processReceivedMsg(_ res: ChatResponse) {
if m.hasChat(toContact.id) { if m.hasChat(toContact.id) {
m.updateChatInfo(cInfo) m.updateChatInfo(cInfo)
} }
case let .contactSubscribed(contact): case let .contactsSubscribed(_, contactRefs):
processContactSubscribed(contact) updateContactsStatus(contactRefs, status: .connected)
case let .contactDisconnected(contact): case let .contactsDisconnected(_, contactRefs):
m.updateContact(contact) updateContactsStatus(contactRefs, status: .disconnected)
m.updateNetworkStatus(contact, .disconnected)
case let .contactSubError(contact, chatError): case let .contactSubError(contact, chatError):
processContactSubError(contact, chatError) processContactSubError(contact, chatError)
case let .contactSubSummary(contactSubscriptions): case let .contactSubSummary(contactSubscriptions):
@ -748,7 +747,8 @@ func processReceivedMsg(_ res: ChatResponse) {
if let err = sub.contactError { if let err = sub.contactError {
processContactSubError(sub.contact, err) processContactSubError(sub.contact, err)
} else { } else {
processContactSubscribed(sub.contact) m.updateContact(sub.contact)
m.updateNetworkStatus(sub.contact.id, .connected)
} }
} }
case let .newChatItem(aChatItem): case let .newChatItem(aChatItem):
@ -810,10 +810,11 @@ func processReceivedMsg(_ res: ChatResponse) {
} }
} }
func processContactSubscribed(_ contact: Contact) { func updateContactsStatus(_ contactRefs: [ContactRef], status: Chat.NetworkStatus) {
let m = ChatModel.shared let m = ChatModel.shared
m.updateContact(contact) for c in contactRefs {
m.updateNetworkStatus(contact, .connected) m.updateNetworkStatus(c.id, status)
}
} }
func processContactSubError(_ contact: Contact, _ chatError: ChatError) { func processContactSubError(_ contact: Contact, _ chatError: ChatError) {
@ -825,7 +826,7 @@ func processContactSubError(_ contact: Contact, _ chatError: ChatError) {
case .errorAgent(agentError: .SMP(smpErr: .AUTH)): err = "contact deleted" case .errorAgent(agentError: .SMP(smpErr: .AUTH)): err = "contact deleted"
default: err = String(describing: chatError) default: err = String(describing: chatError)
} }
m.updateNetworkStatus(contact, .error(err)) m.updateNetworkStatus(contact.id, .error(err))
} }
private struct UserResponse: Decodable { private struct UserResponse: Decodable {

View file

@ -1209,11 +1209,11 @@ getConnectionsContacts st userId agentConnIds =
SELECT ct.contact_id, ct.local_display_name SELECT ct.contact_id, ct.local_display_name
FROM contacts ct FROM contacts ct
JOIN connections c ON c.contact_id = ct.contact_id JOIN connections c ON c.contact_id = ct.contact_id
WHERE ct.user_id = ? AND c.agent_conn_id IN (SELECT conn_id FROM temp.conn_ids) WHERE ct.user_id = ?
AND c.agent_conn_id IN (SELECT conn_id FROM temp.conn_ids)
AND c.conn_type = ? AND c.conn_type = ?
AND (c.conn_status = ? OR c.conn_status = ?)
|] |]
(userId, ConnContact, ConnReady, ConnSndReady) (userId, ConnContact)
DB.execute_ db "DROP TABLE temp.conn_ids" DB.execute_ db "DROP TABLE temp.conn_ids"
pure conns pure conns