2022-01-24 16:07:17 +00:00
|
|
|
//
|
|
|
|
// ChatModel.swift
|
|
|
|
// SimpleX
|
|
|
|
//
|
|
|
|
// Created by Evgeny Poberezkin on 22/01/2022.
|
|
|
|
// Copyright © 2022 SimpleX Chat. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import Combine
|
|
|
|
|
|
|
|
final class ChatModel: ObservableObject {
|
|
|
|
@Published var currentUser: User?
|
2022-01-29 11:10:04 +00:00
|
|
|
@Published var chats: Dictionary<String, Chat> = [:]
|
|
|
|
@Published var chatPreviews: [ChatPreview] = []
|
|
|
|
@Published var chatItems: [ChatItem] = []
|
|
|
|
@Published var apiResponses: [APIResponse] = []
|
2022-01-24 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct User: Codable {
|
|
|
|
var userId: Int64
|
|
|
|
var userContactId: Int64
|
|
|
|
var localDisplayName: ContactName
|
|
|
|
var profile: Profile
|
|
|
|
var activeUser: Bool
|
|
|
|
}
|
|
|
|
|
|
|
|
typealias ContactName = String
|
|
|
|
|
|
|
|
typealias GroupName = String
|
|
|
|
|
|
|
|
struct Profile: Codable {
|
|
|
|
var displayName: String
|
|
|
|
var fullName: String
|
|
|
|
}
|
|
|
|
|
2022-01-29 11:10:04 +00:00
|
|
|
struct ChatPreview: Identifiable, Codable {
|
|
|
|
var chatInfo: ChatInfo
|
|
|
|
var lastChatItem: ChatItem?
|
|
|
|
|
|
|
|
var id: String {
|
|
|
|
get { chatInfo.id }
|
|
|
|
}
|
2022-01-24 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
2022-01-29 11:10:04 +00:00
|
|
|
enum ChatInfo: Identifiable, Codable {
|
|
|
|
case direct(contact: Contact)
|
2022-01-30 00:35:20 +04:00
|
|
|
case group(groupInfo: GroupInfo)
|
2022-01-29 11:10:04 +00:00
|
|
|
|
|
|
|
var displayName: String {
|
|
|
|
get {
|
|
|
|
switch self {
|
|
|
|
case let .direct(contact): return "@\(contact.localDisplayName)"
|
2022-01-30 00:35:20 +04:00
|
|
|
case let .group(groupInfo): return "#\(groupInfo.localDisplayName)"
|
2022-01-29 11:10:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var id: String {
|
|
|
|
get {
|
|
|
|
switch self {
|
|
|
|
case let .direct(contact): return "@\(contact.contactId)"
|
2022-01-30 00:35:20 +04:00
|
|
|
case let .group(groupInfo): return "#\(groupInfo.groupId)"
|
2022-01-29 11:10:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var apiType: String {
|
|
|
|
get {
|
|
|
|
switch self {
|
|
|
|
case .direct(_): return "direct"
|
2022-01-30 00:35:20 +04:00
|
|
|
case .group(_): return "group"
|
2022-01-29 11:10:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var apiId: Int64 {
|
|
|
|
get {
|
|
|
|
switch self {
|
|
|
|
case let .direct(contact): return contact.contactId
|
2022-01-30 00:35:20 +04:00
|
|
|
case let .group(groupInfo): return groupInfo.groupId
|
2022-01-29 11:10:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class Chat: Codable {
|
|
|
|
var chatInfo: ChatInfo
|
|
|
|
var chatItems: [ChatItem]
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Contact: Identifiable, Codable {
|
2022-01-24 16:07:17 +00:00
|
|
|
var contactId: Int64
|
|
|
|
var localDisplayName: ContactName
|
|
|
|
var profile: Profile
|
|
|
|
var viaGroup: Int64?
|
2022-01-29 11:10:04 +00:00
|
|
|
|
|
|
|
var id: String { get { "@\(contactId)" } }
|
2022-01-24 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
2022-01-29 11:10:04 +00:00
|
|
|
struct GroupInfo: Identifiable, Codable {
|
2022-01-24 16:07:17 +00:00
|
|
|
var groupId: Int64
|
|
|
|
var localDisplayName: GroupName
|
|
|
|
var groupProfile: GroupProfile
|
2022-01-29 11:10:04 +00:00
|
|
|
|
|
|
|
var id: String { get { "#\(groupId)" } }
|
2022-01-24 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct GroupProfile: Codable {
|
|
|
|
var displayName: String
|
|
|
|
var fullName: String
|
|
|
|
}
|
|
|
|
|
2022-01-29 11:10:04 +00:00
|
|
|
struct GroupMember: Codable {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ChatItem: Identifiable, Codable {
|
|
|
|
var chatDir: CIDirection
|
|
|
|
var meta: CIMeta
|
|
|
|
var content: CIContent
|
|
|
|
|
|
|
|
var id: Int64 { get { meta.itemId } }
|
2022-01-24 16:07:17 +00:00
|
|
|
}
|
|
|
|
|
2022-01-29 11:10:04 +00:00
|
|
|
enum CIDirection: Codable {
|
|
|
|
case directSnd
|
|
|
|
case directRcv
|
|
|
|
case groupSnd
|
|
|
|
case groupRcv(GroupMember)
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CIMeta: Codable {
|
|
|
|
var itemId: Int64
|
|
|
|
var itemTs: Date
|
|
|
|
var itemText: String
|
|
|
|
var createdAt: Date
|
|
|
|
}
|
|
|
|
|
|
|
|
enum CIContent: Codable {
|
|
|
|
case sndMsgContent(msgContent: MsgContent)
|
|
|
|
case rcvMsgContent(msgContent: MsgContent)
|
|
|
|
// files etc.
|
|
|
|
|
|
|
|
var text: String {
|
|
|
|
get {
|
|
|
|
switch self {
|
|
|
|
case let .sndMsgContent(mc): return mc.string
|
|
|
|
case let .rcvMsgContent(mc): return mc.string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum MsgContent: Codable {
|
2022-01-24 16:07:17 +00:00
|
|
|
case text(String)
|
2022-01-29 11:10:04 +00:00
|
|
|
case unknown(type: String, text: String, json: String)
|
|
|
|
case invalid(json: String)
|
|
|
|
|
|
|
|
init(from: Decoder) throws {
|
|
|
|
self = .invalid(json: "")
|
|
|
|
}
|
|
|
|
|
|
|
|
var string: String {
|
|
|
|
get {
|
|
|
|
switch self {
|
|
|
|
case let .text(str): return str
|
|
|
|
case .unknown: return "unknown"
|
|
|
|
case .invalid: return "invalid"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-24 16:07:17 +00:00
|
|
|
}
|
2022-01-29 11:10:04 +00:00
|
|
|
|
|
|
|
//func parseMsgContent(_ mc: SomeMsgContent) -> MsgContent {
|
|
|
|
// if let type = mc["type"] as? String {
|
|
|
|
// let text_ = mc["text"] as? String
|
|
|
|
// switch type {
|
|
|
|
// case "text":
|
|
|
|
// if let text = text_ { return .text(text) }
|
|
|
|
// case let t:
|
|
|
|
// return .unknown(type: t, text: text_ ?? "unknown item", json: prettyJSON(mc) ?? "error")
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// return .invalid(json: prettyJSON(mc) ?? "error")
|
|
|
|
//}
|