This commit is contained in:
fmodf 2024-07-22 14:02:33 +02:00
parent 7bb48e8719
commit 6ce16b1f3b
10 changed files with 6699 additions and 7842 deletions

View file

@ -7,4 +7,6 @@ enum AccountsAction: Codable {
case addAccountError(jid: String, reason: String?) case addAccountError(jid: String, reason: String?)
case makeAccountPermanent(account: Account) case makeAccountPermanent(account: Account)
case clientServerFeaturesUpdated(jid: String, features: [ServerFeature])
} }

View file

@ -9,4 +9,5 @@ enum XMPPAction: Codable {
case xmppSharingTryUpload(Message) case xmppSharingTryUpload(Message)
case xmppSharingUploadFailed(msgId: String, reason: String) case xmppSharingUploadFailed(msgId: String, reason: String)
case xmppSharingUploadSuccess(msgId: String, attachmentRemotePath: String) case xmppSharingUploadSuccess(msgId: String, attachmentRemotePath: String)
case serverFeaturesLoaded(jid: String, features: [String])
} }

View file

@ -1,8 +1,20 @@
import Combine import Combine
import Foundation
final class AccountsMiddleware { final class AccountsMiddleware {
static let shared = AccountsMiddleware() static let shared = AccountsMiddleware()
private lazy var allFeatures: [ServerFeature] = {
guard
let url = Bundle.main.url(forResource: "server_features", withExtension: "plist"),
let data = try? Data(contentsOf: url),
let loaded = try? PropertyListDecoder().decode([ServerFeature].self, from: data)
else {
return []
}
return loaded
}()
func middleware(state: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> { func middleware(state: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {
switch action { switch action {
case .databaseAction(.storedAccountsLoaded(let accounts)): case .databaseAction(.storedAccountsLoaded(let accounts)):
@ -36,6 +48,16 @@ final class AccountsMiddleware {
} }
.eraseToAnyPublisher() .eraseToAnyPublisher()
case .xmppAction(.serverFeaturesLoaded(let jid, let features)):
return Future<AppAction, Never> { [weak self] promise in
let serverFeatures = features
.compactMap { featureId in
self?.allFeatures.first(where: { $0.xep == featureId })
}
promise(.success(.accountsAction(.clientServerFeaturesUpdated(jid: jid, features: serverFeatures))))
}
.eraseToAnyPublisher()
default: default:
return Empty().eraseToAnyPublisher() return Empty().eraseToAnyPublisher()
} }

View file

@ -26,6 +26,14 @@ final class XMPPMiddleware {
} }
} }
.store(in: &cancellables) .store(in: &cancellables)
service.clientFeatures.sink { client, features in
let jid = client.userBareJid.stringValue
DispatchQueue.main.async {
store.dispatch(.xmppAction(.serverFeaturesLoaded(jid: jid, features: features)))
}
}
.store(in: &cancellables)
} }
func middleware(state: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> { func middleware(state: AppState, action: AppAction) -> AnyPublisher<AppAction, Never> {

View file

@ -0,0 +1,43 @@
import Foundation
struct ServerFeature: Stateable, Identifiable {
let xep: String
let name: String
let xmppId: String?
let description: String?
var id: String { xep }
}
// <feature id="">
// <xep>XEP-0001</xep>
// <name>XMPP Extension Protocols</name>
// <type>Procedural</type>
// <status>Active</status>
// <date>2016-11-16</date>
// <description/>
// </feature>
// <feature id="">
// <xep>XEP-0002</xep>
// <name>Special Interest Groups (SIGs)</name>
// <type>Procedural</type>
// <status>Active</status>
// <date>2002-01-11</date>
// <description/>
// </feature>
// <feature id="jabber:iq:pass">
// <xep>XEP-0003</xep>
// <name>Proxy Accept Socket Service (PASS)</name>
// <type>Historical</type>
// <status>Obsolete</status>
// <date>2009-06-03</date>
// <description/>
// </feature>
// <feature id="">
// <xep>XEP-0004</xep>
// <name>Data Forms</name>
// <type>Standards Track</type>
// <status>Final</status>
// <date>2007-08-13</date>
// <description/>
// </feature>

View file

@ -15,6 +15,10 @@ extension AccountsState {
state.accounts = state.accounts.filter { $0.bareJid != jid } state.accounts = state.accounts.filter { $0.bareJid != jid }
state.addAccountError = reason state.addAccountError = reason
case .clientServerFeaturesUpdated(let jid, let features):
state.discoFeatures[jid] = features
print(features)
default: default:
break break
} }

View file

@ -5,6 +5,7 @@ enum AccountNavigationState: Stateable {
struct AccountsState: Stateable { struct AccountsState: Stateable {
var navigation: AccountNavigationState var navigation: AccountNavigationState
var accounts: [Account] var accounts: [Account]
var discoFeatures: [String: [ServerFeature]]
var addAccountError: String? var addAccountError: String?
} }
@ -14,5 +15,6 @@ extension AccountsState {
init() { init() {
navigation = .addAccount navigation = .addAccount
accounts = [] accounts = []
discoFeatures = [:]
} }
} }

View file

@ -9,8 +9,10 @@ final class XMPPService: ObservableObject {
private let manager: MartinsManager private let manager: MartinsManager
private let clientStatePublisher = PassthroughSubject<(XMPPClient, XMPPClient.State), Never>() private let clientStatePublisher = PassthroughSubject<(XMPPClient, XMPPClient.State), Never>()
private let clientMessagesPublisher = PassthroughSubject<(XMPPClient, Martin.Message), Never>() private let clientMessagesPublisher = PassthroughSubject<(XMPPClient, Martin.Message), Never>()
private let clientFeaturesPublisher = PassthroughSubject<(XMPPClient, [String]), Never>()
private var clientStateCancellables: Set<AnyCancellable> = [] private var clientStateCancellables: Set<AnyCancellable> = []
private var clientMessagesCancellables: Set<AnyCancellable> = [] private var clientMessagesCancellables: Set<AnyCancellable> = []
private var clientFeaturesCancellables: Set<AnyCancellable> = []
@Published private(set) var clients: [XMPPClient] = [] @Published private(set) var clients: [XMPPClient] = []
var clientState: AnyPublisher<(XMPPClient, XMPPClient.State), Never> { var clientState: AnyPublisher<(XMPPClient, XMPPClient.State), Never> {
@ -21,6 +23,10 @@ final class XMPPService: ObservableObject {
clientMessagesPublisher.eraseToAnyPublisher() clientMessagesPublisher.eraseToAnyPublisher()
} }
var clientFeatures: AnyPublisher<(XMPPClient, [String]), Never> {
clientFeaturesPublisher.eraseToAnyPublisher()
}
init(manager: MartinsManager) { init(manager: MartinsManager) {
self.manager = manager self.manager = manager
} }
@ -46,6 +52,13 @@ final class XMPPService: ObservableObject {
} }
.store(in: &clientStateCancellables) .store(in: &clientStateCancellables)
// subscribe to client server features
client.module(DiscoveryModule.self).$serverDiscoResult
.sink { [weak self] disco in
self?.clientFeaturesPublisher.send((client, disco.features))
}
.store(in: &clientFeaturesCancellables)
// subscribe to client messages // subscribe to client messages
client.module(MessageModule.self).messagesPublisher client.module(MessageModule.self).messagesPublisher
.sink { [weak self] message in .sink { [weak self] message in
@ -80,9 +93,11 @@ final class XMPPService: ObservableObject {
client.modulesManager.register(PubSubModule()) client.modulesManager.register(PubSubModule())
client.modulesManager.register(MessageModule(chatManager: manager)) client.modulesManager.register(MessageModule(chatManager: manager))
client.modulesManager.register(MessageCarbonsModule())
client.modulesManager.register(MessageArchiveManagementModule()) client.modulesManager.register(MessageArchiveManagementModule())
client.modulesManager.register(MessageCarbonsModule())
client.module(.messageCarbons).enable()
// file transfer modules // file transfer modules
client.modulesManager.register(HttpFileUploadModule()) client.modulesManager.register(HttpFileUploadModule())
@ -160,8 +175,8 @@ final class XMPPService: ObservableObject {
switch res { switch res {
case .success(let slot): case .success(let slot):
var request = URLRequest(url: slot.putUri) var request = URLRequest(url: slot.putUri)
for (k, v) in slot.putHeaders { for (key, value) in slot.putHeaders {
request.addValue(v, forHTTPHeaderField: k) request.addValue(value, forHTTPHeaderField: key)
} }
request.httpMethod = "PUT" request.httpMethod = "PUT"
request.httpBody = data request.httpBody = data

File diff suppressed because it is too large Load diff

View file

@ -16,8 +16,10 @@ struct AddAccountScreen: View {
@State private var isShowingLoader = false @State private var isShowingLoader = false
#if DEBUG #if DEBUG
@State private var jidStr: String = "test1@test.anal.company" @State private var jidStr: String = "nartest1@conversations.im"
@State private var pass: String = "12345" @State private var pass: String = "nartest12345"
// @State private var jidStr: String = "test1@test.anal.company"
// @State private var pass: String = "12345"
#else #else
@State private var jidStr: String = "" @State private var jidStr: String = ""
@State private var pass: String = "" @State private var pass: String = ""