This commit is contained in:
fmodf 2024-12-17 17:07:13 +01:00
parent 7a722e200c
commit e30ec562cb
4 changed files with 64 additions and 22 deletions

View file

@ -30,9 +30,16 @@ struct TestScreen: View {
.background { Color.blue.opacity(0.4) } .background { Color.blue.opacity(0.4) }
} }
Button { Button {
// cls.requestRoster() cls.addContact(jidStr: "asdadad@asdfsdf.df")
} label: { } label: {
Text("Request roster") Text("Add contact")
.padding()
.background { Color.blue.opacity(0.4) }
}
Button {
cls.deleteContact(jidStr: "asdadad@asdfsdf.df")
} label: {
Text("Remove contact")
.padding() .padding()
.background { Color.blue.opacity(0.4) } .background { Color.blue.opacity(0.4) }
} }
@ -51,9 +58,8 @@ struct TestScreen: View {
final class TestStorage: XMPPStorage { final class TestStorage: XMPPStorage {
private var roster: [String: Data] = [:] private var roster: [String: Data] = [:]
func getCredentialsByUUID(_ uuid: UUID) async -> Credentials? { func getCredentialsByUUID(_: UUID) async -> Credentials? {
print(uuid) ["password": pass]
return ["password": pass]
} }
func deleteRoster(jid: JID) async { func deleteRoster(jid: JID) async {
@ -66,7 +72,10 @@ final class TestStorage: XMPPStorage {
func setRoster(jid: JID, roster: Data) async { func setRoster(jid: JID, roster: Data) async {
self.roster[jid.bare] = roster self.roster[jid.bare] = roster
print("updated")
if let arr = try? JSONDecoder().decode([XMLElement].self, from: roster) {
print("ROSTER: \(arr)\n\n")
}
} }
} }

View file

@ -127,7 +127,7 @@ extension XMPPClient {
} }
} }
func deleteRosterItem(jidStr: String) { func deleteContact(jidStr: String) {
Task { Task {
await fire(.deleteRosterItem(jidStr: jidStr)) await fire(.deleteRosterItem(jidStr: jidStr))
} }

View file

@ -30,6 +30,7 @@ enum RosterSubsriptionType: String {
// Roster is a "transparent" structure // Roster is a "transparent" structure
// which is just wrap xml item around // which is just wrap xml item around
// TODO: Add groups and annotattions!
struct RosterItem: Identifiable, Equatable { struct RosterItem: Identifiable, Equatable {
let owner: String let owner: String
let wrapped: XMLElement let wrapped: XMLElement
@ -66,5 +67,3 @@ struct RosterItem: Identifiable, Equatable {
rhs.id == lhs.id && rhs.wrapped == lhs.wrapped rhs.id == lhs.id && rhs.wrapped == lhs.wrapped
} }
} }
// TODO: Add groups and annotattions!

View file

@ -6,6 +6,7 @@ final class RosterModule: XmppModule {
let id = "Roseter module" let id = "Roseter module"
private weak var storage: (any XMPPStorage)? private weak var storage: (any XMPPStorage)?
private var fullReqId = ""
init(_ storage: any XMPPStorage) { init(_ storage: any XMPPStorage) {
self.storage = storage self.storage = storage
@ -26,6 +27,7 @@ final class RosterModule: XmppModule {
payload: XMLElement(name: "query", xmlns: "jabber:iq:roster", attributes: [:], content: nil, nodes: []) payload: XMLElement(name: "query", xmlns: "jabber:iq:roster", attributes: [:], content: nil, nodes: [])
) )
if let req { if let req {
fullReqId = req.id ?? "???"
return .stanzaOutbound(req) return .stanzaOutbound(req)
} else { } else {
return nil return nil
@ -38,6 +40,12 @@ final class RosterModule: XmppModule {
return nil return nil
} }
case .addRosterItem(let jidStr):
return updRoster(state: state, target: jidStr, remove: false)
case .deleteRosterItem(let jidStr):
return updRoster(state: state, target: jidStr, remove: true)
default: default:
return nil return nil
} }
@ -45,7 +53,7 @@ final class RosterModule: XmppModule {
} }
private extension RosterModule { private extension RosterModule {
func processRoster(state: ClientState, stanza: Stanza) async -> Event? { private func processRoster(state: ClientState, stanza: Stanza) async -> Event? {
// get inner query // get inner query
guard let query = stanza.wrapped.nodes.first(where: { $0.name == "query" }) guard let query = stanza.wrapped.nodes.first(where: { $0.name == "query" })
else { return nil } else { return nil }
@ -68,21 +76,47 @@ private extension RosterModule {
await storage?.setRoster(jid: state.jid, roster: data) await storage?.setRoster(jid: state.jid, roster: data)
return .rosterUpdated return .rosterUpdated
// process get response (.result from server) // process .result from server
} else if stanza.type == .iq(.get) { } else if stanza.type == .iq(.result) {
// process full list
if stanza.id == fullReqId {
let items = query.nodes.filter { $0.name == "item" } let items = query.nodes.filter { $0.name == "item" }
guard let data = try? JSONEncoder().encode(items) else { return nil } guard let data = try? JSONEncoder().encode(items) else { return nil }
await storage?.setRoster(jid: state.jid, roster: data) await storage?.setRoster(jid: state.jid, roster: data)
// process changed item
} else {
// TODO: Fix removing item!
// guard
// let item = query.nodes.first(where: { $0.name == "item" }),
// let new = RosterItem(wrap: item, owner: state.jid)
// else { return nil }
// existItems = existItems.filter { $0.jid != new.jid }
// if new.subsription != .remove {
// existItems.append(new)
// } else {
// print("REMOVED!!!")
// }
// guard let data = try? JSONEncoder().encode(existItems.map { $0.wrapped }) else { return nil }
// await storage?.setRoster(jid: state.jid, roster: data)
}
return .rosterUpdated return .rosterUpdated
} else { } else {
return nil return nil
} }
} }
}
// <iq to='testmon3@test.anal.company/TwtWkVOZ3liz' type='result' id='7l899q9r'> private func updRoster(state: ClientState, target: String, remove: Bool) -> Event? {
// <query ver='27' xmlns='jabber:iq:roster'> var attributes = ["jid": target]
// <item jid='fmodf@conversations.im' subscription='both' xmlns='jabber:iq:roster'/> if remove {
// <item subscription='to' jid='testmon4@test.anal.company' xmlns='jabber:iq:roster'/> attributes["subcription"] = "remove"
// </query> }
// </iq> let item = XMLElement(name: "item", xmlns: "jabber:iq:roster", attributes: attributes, content: nil, nodes: [])
let query = XMLElement(name: "query", xmlns: "jabber:iq:roster", attributes: [:], content: nil, nodes: [item])
if let req = Stanza.iqSet(from: state.jid.full, payload: query) {
return .stanzaOutbound(req)
} else {
return nil
}
}
}