This commit is contained in:
fmodf 2024-08-12 01:52:45 +02:00
parent 6df18d361f
commit 77ade86bb1
4 changed files with 106 additions and 3 deletions

View file

@ -0,0 +1,75 @@
import Foundation
import GRDB
import Martin
final class ClientMartinChatsManager: Martin.ChatManager {
func chats(for context: Martin.Context) -> [any Martin.ChatProtocol] {
do {
let chats: [Chat] = try Database.shared.dbQueue.read { db in
try Chat.filter(Column("account") == context.userBareJid.stringValue).fetchAll(db)
}
return chats.map { chat in
Martin.ChatBase(context: context, jid: BareJID(chat.participant))
}
} catch {
logIt(.error, "Error fetching chats: \(error.localizedDescription)")
return []
}
}
func chat(for context: Martin.Context, with: Martin.BareJID) -> (any Martin.ChatProtocol)? {
do {
let chat: Chat? = try Database.shared.dbQueue.read { db in
try Chat
.filter(Column("account") == context.userBareJid.stringValue)
.filter(Column("participant") == with.stringValue)
.fetchOne(db)
}
if chat != nil {
return Martin.ChatBase(context: context, jid: with)
} else {
return nil
}
} catch {
logIt(.error, "Error fetching chat: \(error.localizedDescription)")
return nil
}
}
func createChat(for context: Martin.Context, with: Martin.BareJID) -> (any Martin.ChatProtocol)? {
do {
let chat: Chat? = try Database.shared.dbQueue.read { db in
try Chat
.filter(Column("account") == context.userBareJid.stringValue)
.filter(Column("participant") == with.stringValue)
.fetchOne(db)
}
if chat != nil {
return Martin.ChatBase(context: context, jid: with)
} else {
let chat = Chat(
id: UUID().uuidString,
account: context.userBareJid.stringValue,
participant: with.stringValue,
type: .chat
)
try Database.shared.dbQueue.write { db in
try chat.save(db)
}
return Martin.ChatBase(context: context, jid: with)
}
} catch {
logIt(.error, "Error fetching chat: \(error.localizedDescription)")
return nil
}
}
func close(chat: any Martin.ChatProtocol) -> Bool {
// not used in Martin library for now
print("Closing chat: \(chat)")
return false
}
func initialize(context _: Martin.Context) {}
func deinitialize(context _: Martin.Context) {}
}

View file

@ -23,11 +23,12 @@ final class Client: ObservableObject {
private var rostersCancellable: AnyCancellable?
private var rosterManager = ClientMartinRosterManager()
private var chatsManager = ClientMartinChatsManager()
init(credentials: Credentials) {
self.credentials = credentials
state = credentials.isActive ? .enabled(.disconnected) : .disabled
connection = Self.prepareConnection(credentials, rosterManager)
connection = Self.prepareConnection(credentials, rosterManager, chatsManager)
connectionCancellable = connection.$state
.sink { [weak self] state in
guard let self = self else { return }
@ -92,7 +93,7 @@ extension Client {
}
private extension Client {
static func prepareConnection(_ credentials: Credentials, _ roster: RosterManager) -> XMPPClient {
static func prepareConnection(_ credentials: Credentials, _ roster: RosterManager, _ chat: ChatManager) -> XMPPClient {
let client = XMPPClient()
// register modules
@ -109,7 +110,7 @@ private extension Client {
client.modulesManager.register(PresenceModule())
// client.modulesManager.register(PubSubModule())
// client.modulesManager.register(MessageModule(chatManager: manager))
client.modulesManager.register(MessageModule(chatManager: chat))
// client.modulesManager.register(MessageArchiveManagementModule())
// client.modulesManager.register(MessageCarbonsModule())

View file

@ -0,0 +1,19 @@
import Foundation
import GRDB
enum ConversationType: Int, Codable, DatabaseValueConvertible {
case chat = 0
case room = 1
case channel = 2
}
struct Chat: DBStorable {
static let databaseTableName = "chats"
var id: String
var account: String
var participant: String
var type: ConversationType
}
extension Chat: Equatable {}

View file

@ -34,6 +34,14 @@ extension Database {
table.primaryKey(["bareJid", "contactBareJid"], onConflict: .replace)
table.column("locallyDeleted", .boolean).notNull().defaults(to: false)
}
// chats
try db.create(table: "chats", options: [.ifNotExists]) { table in
table.column("id", .text).notNull().primaryKey().unique(onConflict: .replace)
table.column("account", .text).notNull()
table.column("participant", .text).notNull()
table.column("type", .integer).notNull()
}
}
// return migrator