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 makeAccountPermanent(account: Account)
case clientServerFeaturesUpdated(jid: String, features: [ServerFeature])
}

View file

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

View file

@ -1,8 +1,20 @@
import Combine
import Foundation
final class 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> {
switch action {
case .databaseAction(.storedAccountsLoaded(let accounts)):
@ -36,6 +48,16 @@ final class AccountsMiddleware {
}
.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:
return Empty().eraseToAnyPublisher()
}

View file

@ -26,6 +26,14 @@ final class XMPPMiddleware {
}
}
.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> {

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.addAccountError = reason
case .clientServerFeaturesUpdated(let jid, let features):
state.discoFeatures[jid] = features
print(features)
default:
break
}

View file

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

View file

@ -9,8 +9,10 @@ final class XMPPService: ObservableObject {
private let manager: MartinsManager
private let clientStatePublisher = PassthroughSubject<(XMPPClient, XMPPClient.State), Never>()
private let clientMessagesPublisher = PassthroughSubject<(XMPPClient, Martin.Message), Never>()
private let clientFeaturesPublisher = PassthroughSubject<(XMPPClient, [String]), Never>()
private var clientStateCancellables: Set<AnyCancellable> = []
private var clientMessagesCancellables: Set<AnyCancellable> = []
private var clientFeaturesCancellables: Set<AnyCancellable> = []
@Published private(set) var clients: [XMPPClient] = []
var clientState: AnyPublisher<(XMPPClient, XMPPClient.State), Never> {
@ -21,6 +23,10 @@ final class XMPPService: ObservableObject {
clientMessagesPublisher.eraseToAnyPublisher()
}
var clientFeatures: AnyPublisher<(XMPPClient, [String]), Never> {
clientFeaturesPublisher.eraseToAnyPublisher()
}
init(manager: MartinsManager) {
self.manager = manager
}
@ -46,6 +52,13 @@ final class XMPPService: ObservableObject {
}
.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
client.module(MessageModule.self).messagesPublisher
.sink { [weak self] message in
@ -80,9 +93,11 @@ final class XMPPService: ObservableObject {
client.modulesManager.register(PubSubModule())
client.modulesManager.register(MessageModule(chatManager: manager))
client.modulesManager.register(MessageCarbonsModule())
client.modulesManager.register(MessageArchiveManagementModule())
client.modulesManager.register(MessageCarbonsModule())
client.module(.messageCarbons).enable()
// file transfer modules
client.modulesManager.register(HttpFileUploadModule())
@ -160,8 +175,8 @@ final class XMPPService: ObservableObject {
switch res {
case .success(let slot):
var request = URLRequest(url: slot.putUri)
for (k, v) in slot.putHeaders {
request.addValue(v, forHTTPHeaderField: k)
for (key, value) in slot.putHeaders {
request.addValue(value, forHTTPHeaderField: key)
}
request.httpMethod = "PUT"
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
#if DEBUG
@State private var jidStr: String = "test1@test.anal.company"
@State private var pass: String = "12345"
@State private var jidStr: String = "nartest1@conversations.im"
@State private var pass: String = "nartest12345"
// @State private var jidStr: String = "test1@test.anal.company"
// @State private var pass: String = "12345"
#else
@State private var jidStr: String = ""
@State private var pass: String = ""