add server info screen, connection stats, and emoji picker
Server information (Monal-style): - Add ServerInformation model and ServerInfoView reachable from Settings, showing server software (XEP-0092), disco#info identities and features, conference (MUC) services via disco#items, and STUN/TURN via XEP-0215. - Add a curated XEP capability list with per-XEP success/error status derived from server/account disco features and connection flags. - Detect PEP (0163) from account disco pubsub#* features, HTTP Upload (0363) from the main domain plus its components, and add Roster Versioning (0237), Pre-Authenticated Roster Subscription (0379), and SASL SCRAM Downgrade Protection (0474, neutral because Martin does not expose SSDP). Connection statistics: - Add LumaConnectionStatsModule, an XmppStanzaFilter registered before stream management, to count sent / acknowledged / received stanzas. - Track last login and SMACKS session timestamps, and read SASL mechanisms and Client State Indication from the raw stream features. MAM / OMEMO handling: - Prefer a plaintext <body> fallback when OMEMO decryption fails instead of showing "failed to decrypt". - Keep the optimistic text of our own outgoing message when its echo cannot be decrypted back, instead of replacing it with a placeholder. Emoji picker: - Add EmojiCatalog and a cross-platform EmojiPickerView. - Open the picker for reactions (replacing the static quick list) and from the composer's smiley button, inserting the chosen emoji into the draft.
This commit is contained in:
1 parent
a886917dc8
commit
0317277d46
12 files changed
+1081
-24
No files matched your search
@@ -0,0 +1,68 @@
|
||||
import Foundation
|
||||
import Martin
|
||||
|
||||
/// Counts XEP-0198 stanza statistics (sent / acknowledged / received) at the
|
||||
/// stream level so the server-details screen can mirror Monal's connection
|
||||
/// statistics. Registered as an `XmppStanzaFilter` *before* stream management
|
||||
/// so it can also observe the server's `<a h='N'>` acknowledgements.
|
||||
final class LumaConnectionStatsModule: XmppModuleBase, XmppModule, XmppStanzaFilter {
|
||||
static let ID = "lumaConnectionStats"
|
||||
static let smNamespace = "urn:xmpp:sm:3"
|
||||
|
||||
let criteria = Criteria.empty()
|
||||
let features: [String] = []
|
||||
|
||||
private let lock = NSLock()
|
||||
private var sent: UInt32 = 0
|
||||
private var received: UInt32 = 0
|
||||
private var acknowledged: UInt32 = 0
|
||||
|
||||
struct Snapshot: Equatable, Sendable {
|
||||
let sent: UInt32
|
||||
let acknowledged: UInt32
|
||||
let received: UInt32
|
||||
|
||||
var unacknowledged: UInt32 {
|
||||
sent > acknowledged ? sent - acknowledged : 0
|
||||
}
|
||||
}
|
||||
|
||||
var snapshot: Snapshot {
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
return Snapshot(sent: sent, acknowledged: acknowledged, received: received)
|
||||
}
|
||||
|
||||
func processIncoming(stanza: Stanza) -> Bool {
|
||||
if stanza.xmlns == Self.smNamespace, stanza.name == "a" {
|
||||
if let raw = stanza.getAttribute("h"), let value = UInt32(raw) {
|
||||
lock.lock()
|
||||
acknowledged = value
|
||||
lock.unlock()
|
||||
}
|
||||
// Let StreamManagementModule consume the acknowledgement too.
|
||||
return false
|
||||
}
|
||||
if Self.isCountable(stanza) {
|
||||
lock.lock()
|
||||
received += 1
|
||||
lock.unlock()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func processOutgoing(stanza: Stanza) {
|
||||
guard Self.isCountable(stanza) else { return }
|
||||
lock.lock()
|
||||
sent += 1
|
||||
lock.unlock()
|
||||
}
|
||||
|
||||
func process(stanza: Stanza) throws {
|
||||
// Criteria is empty, so this module is never selected by the dispatcher.
|
||||
}
|
||||
|
||||
private static func isCountable(_ stanza: Stanza) -> Bool {
|
||||
stanza.name == "iq" || stanza.name == "message" || stanza.name == "presence"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user