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,156 @@
|
||||
import Foundation
|
||||
|
||||
/// Snapshot of everything the "server details" screen shows, modelled after
|
||||
/// Monal's `ServerDetails`: server software (XEP-0092), disco#info identities
|
||||
/// and features (XEP-0030), conference (MUC) services, STUN/TURN services
|
||||
/// (XEP-0215) and a few connection-level capability flags.
|
||||
struct ServerInformation: Equatable, Sendable {
|
||||
enum CapabilityStatus: Equatable, Sendable {
|
||||
case success, normal, warning, error
|
||||
}
|
||||
|
||||
struct Software: Equatable, Sendable {
|
||||
let name: String?
|
||||
let version: String?
|
||||
let os: String?
|
||||
}
|
||||
|
||||
struct Identity: Equatable, Sendable, Identifiable {
|
||||
let category: String
|
||||
let type: String
|
||||
let name: String?
|
||||
|
||||
var id: String { "\(category)/\(type)" }
|
||||
|
||||
var title: String { "\(category) / \(type)" }
|
||||
}
|
||||
|
||||
struct ConferenceServer: Equatable, Sendable, Identifiable {
|
||||
let jid: String
|
||||
let name: String?
|
||||
let type: String
|
||||
let category: String
|
||||
|
||||
var id: String { jid }
|
||||
}
|
||||
|
||||
struct ExternalService: Equatable, Sendable, Identifiable {
|
||||
let type: String
|
||||
let host: String
|
||||
let port: UInt16?
|
||||
let transport: String?
|
||||
|
||||
var id: String { "\(type)|\(host)|\(port.map(String.init) ?? "")" }
|
||||
}
|
||||
|
||||
struct ConnectionStats: Equatable, Sendable {
|
||||
let lastLogin: Date?
|
||||
let smacksSessionEstablished: Date?
|
||||
let sent: UInt32
|
||||
let acknowledged: UInt32
|
||||
let received: UInt32
|
||||
|
||||
var unacknowledged: UInt32 {
|
||||
sent > acknowledged ? sent - acknowledged : 0
|
||||
}
|
||||
}
|
||||
|
||||
struct Capability: Equatable, Sendable, Identifiable {
|
||||
let title: String
|
||||
let detail: String
|
||||
let status: CapabilityStatus
|
||||
|
||||
var id: String { title }
|
||||
}
|
||||
|
||||
let serverDomain: String
|
||||
let software: Software
|
||||
let identities: [Identity]
|
||||
let serverFeatures: [String]
|
||||
let accountFeatures: [String]
|
||||
let conferenceServers: [ConferenceServer]
|
||||
let externalServices: [ExternalService]
|
||||
let connectionStats: ConnectionStats
|
||||
let saslMethods: [String]
|
||||
let supportsStreamManagement: Bool
|
||||
let supportsCarbons: Bool
|
||||
let supportsClientState: Bool
|
||||
let supportsHTTPUpload: Bool
|
||||
let supportsRosterVersioning: Bool
|
||||
let supportsRosterPreApproval: Bool
|
||||
|
||||
/// The curated XEP list Monal shows, with a status derived from the server
|
||||
/// and account disco features plus the connection-level flags.
|
||||
var capabilities: [Capability] {
|
||||
let server = Set(serverFeatures)
|
||||
let account = Set(accountFeatures)
|
||||
let supportsPubSub = account.contains { $0.hasPrefix("http://jabber.org/protocol/pubsub") }
|
||||
return [
|
||||
Capability(
|
||||
title: "XEP-0163 Personal Eventing Protocol",
|
||||
detail: "Публикация событий состояния аккаунта (аватары, статусы) через publish-subscribe.",
|
||||
status: supportsPubSub ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0191 Blocking Command",
|
||||
detail: "Расширение XMPP для блокировки контактов.",
|
||||
status: server.contains("urn:xmpp:blocking") ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0198 Stream Management",
|
||||
detail: "Возобновление потока при обрыве соединения — быстрее переподключение и экономия заряда.",
|
||||
status: supportsStreamManagement ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0199 XMPP Ping",
|
||||
detail: "Пинг уровня приложения поверх XML-потока.",
|
||||
status: server.contains("urn:xmpp:ping") ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0215 External Service Discovery",
|
||||
detail: "Обнаружение внешних сервисов (STUN/TURN) для аудио- и видеозвонков.",
|
||||
status: server.contains("urn:xmpp:extdisco:2") ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0237 Roster Versioning",
|
||||
detail: "Версионирование ростера, чтобы сервер не отправлял его повторно, если он не менялся.",
|
||||
status: supportsRosterVersioning ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0280 Message Carbons",
|
||||
detail: "Синхронизация сообщений между всеми вашими устройствами.",
|
||||
status: supportsCarbons ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0313 Message Archive Management",
|
||||
detail: "Доступ к архиву сообщений на сервере.",
|
||||
status: account.contains("urn:xmpp:mam:2") ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0352 Client State Indication",
|
||||
detail: "Указывает, активно ли устройство. Экономит заряд.",
|
||||
status: supportsClientState ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0357 Push Notifications",
|
||||
detail: "Push-уведомления через Apple даже когда приложение выгружено.",
|
||||
status: account.contains("urn:xmpp:push:0") ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0363 HTTP File Upload",
|
||||
detail: "Загрузка файлов на сервер для обмена с собеседниками.",
|
||||
status: supportsHTTPUpload ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0379 Pre-Authenticated Roster Subscription",
|
||||
detail: "Ссылки для предварительно аутентифицированной подписки на присутствие.",
|
||||
status: supportsRosterPreApproval ? .success : .error
|
||||
),
|
||||
Capability(
|
||||
title: "XEP-0474 SASL SCRAM Downgrade Protection",
|
||||
detail: "Защита SASL/SASL2-рукопожатия от понижения метода и channel-binding. Определяется во время SCRAM-аутентификации, а не рекламируется статически.",
|
||||
status: .normal
|
||||
),
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user