Skip to content
Snippets Groups Projects
Commit 2f9b38e8 authored by Bruno Muniz's avatar Bruno Muniz :apple:
Browse files

Removed database target

parent 2d8770ee
No related branches found
No related tags found
2 merge requests!40v1.1.2b166,!38Using new database structure
Showing
with 872 additions and 934 deletions
import Retry
import Models
import Shared
import Database
import Foundation
extension Session {
......
......@@ -3,7 +3,7 @@ import Models
import Shared
import Combine
import Defaults
import Database
import XXModels
import Foundation
import BackupFeature
import NetworkMonitor
......@@ -52,7 +52,7 @@ public final class Session: SessionType {
@Dependency var networkMonitor: NetworkMonitoring
public let client: Client
public let dbManager: DatabaseManager
public let dbManager: Database
private var cancellables = Set<AnyCancellable>()
public var myId: Data { client.bindings.myId }
......@@ -76,61 +76,6 @@ public final class Session: SessionType {
networkMonitor.statusPublisher.map { $0 == .available }.eraseToAnyPublisher()
}
public func groups(_ request: Group.Request) -> AnyPublisher<[Group], Never> {
self.dbManager
.publisher(fetch: Group.self, request)
.catch { _ in Just([]) }
.eraseToAnyPublisher()
}
public func groupMembers(_ request: GroupMember.Request) -> AnyPublisher<[GroupMember], Never> {
self.dbManager
.publisher(fetch: GroupMember.self, request)
.catch { _ in Just([]) }
.eraseToAnyPublisher()
}
lazy public var contacts: (Contact.Request) -> AnyPublisher<[Contact], Never> = {
self.dbManager.publisher(fetch: Contact.self, $0).catch { _ in Just([]) }.eraseToAnyPublisher()
}
lazy public var singleMessages: (Contact) -> AnyPublisher<[Message], Never> = {
self.dbManager.publisher(fetch: Message.self, .withContact($0.userId)).catch { _ in Just([]) }.eraseToAnyPublisher()
}
lazy public var groupMessages: (Group) -> AnyPublisher<[GroupMessage], Never> = {
self.dbManager.publisher(fetch: GroupMessage.self, .fromGroup($0.groupId)).catch { _ in Just([]) }.eraseToAnyPublisher()
}
lazy public var groupChats: (GroupChatInfo.Request) -> AnyPublisher<[GroupChatInfo], Never> = {
self.dbManager.publisher(fetch: GroupChatInfo.self, $0).catch { _ in Just([]) }.eraseToAnyPublisher()
}
lazy public var singleChats: (SingleChatInfo.Request) -> AnyPublisher<[SingleChatInfo], Never> = { _ in
self.dbManager.publisher(fetch: Contact.self, .friends)
.flatMap { [unowned self] contactList -> AnyPublisher<[SingleChatInfo], Error> in
let contactIds = contactList.map { $0.userId }
let messagesPublisher: AnyPublisher<[Message], Error> = dbManager
.publisher(fetch: .latestOnesFromContactIds(contactIds))
.map { $0.sorted(by: { $0.timestamp > $1.timestamp }) }
.eraseToAnyPublisher()
return messagesPublisher.map { messages -> [SingleChatInfo] in
contactList.map { contact -> SingleChatInfo in
SingleChatInfo(contact: contact, lastMessage: messages.first {
$0.sender == contact.userId || $0.receiver == contact.userId
})
}
}
.eraseToAnyPublisher()
}
.catch { _ in Just([]) }
.map { $0.filter { $0.lastMessage != nil }}
.map { $0.sorted(by: { $0.lastMessage!.timestamp > $1.lastMessage!.timestamp })}
.eraseToAnyPublisher()
}
public init(
passphrase: String,
backupFile: Data,
......
import Models
import Combine
import Database
import Foundation
public protocol SessionType {
......@@ -10,16 +9,6 @@ public protocol SessionType {
var hasRunningTasks: Bool { get }
var isOnline: AnyPublisher<Bool, Never> { get }
var contacts: (Contact.Request) -> AnyPublisher<[Contact], Never> { get }
var singleMessages: (Contact) -> AnyPublisher<[Message], Never> { get }
var singleChats: (SingleChatInfo.Request) -> AnyPublisher<[SingleChatInfo], Never> { get }
func groupMembers(_: GroupMember.Request) -> AnyPublisher<[GroupMember], Never>
func groups(_: Group.Request) -> AnyPublisher<[Group], Never>
var groupMessages: (Group) -> AnyPublisher<[GroupMessage], Never> { get }
var groupChats: (GroupChatInfo.Request) -> AnyPublisher<[GroupChatInfo], Never> { get }
func deleteMyself() throws
func getId(from: Data) -> Data?
......
//import Foundation
//
//public struct Attachment: Codable, Equatable, Hashable {
//
// public enum Extension: Int64, Codable, CaseIterable {
// case image
// case audio
//
// public static func from(_ string: String) -> Extension? {
// self.allCases.first{ $0.written == string }
// }
//
// public var written: String {
// switch self {
// case .image:
// return "jpeg"
// case .audio:
// return "m4a"
// }
// }
//
// public var writtenExtended: String {
// switch self {
// case .image:
// return "image"
// case .audio:
// return "voice message"
// }
// }
// }
//
// public let data: Data?
// public let name: String
// public var transferId: Data?
// public let _extension: Extension
// public var progress: Float = 0.0
//
// public init(
// name: String,
// data: Data? = nil,
// transferId: Data? = nil,
// _extension: Extension
// ) {
// self.data = data
// self.name = name
// self._extension = _extension
// self.transferId = transferId
// }
//}
import Foundation
public struct Attachment: Codable, Equatable, Hashable {
public enum Extension: Int64, Codable, CaseIterable {
case image
case audio
public static func from(_ string: String) -> Extension? {
self.allCases.first{ $0.written == string }
}
public var written: String {
switch self {
case .image:
return "jpeg"
case .audio:
return "m4a"
}
}
public var writtenExtended: String {
switch self {
case .image:
return "image"
case .audio:
return "voice message"
}
}
}
public let data: Data?
public let name: String
public var transferId: Data?
public let _extension: Extension
public var progress: Float = 0.0
public init(
name: String,
data: Data? = nil,
transferId: Data? = nil,
_extension: Extension
) {
self.data = data
self.name = name
self._extension = _extension
self.transferId = transferId
}
}
//import UIKit
//import DifferenceKit
//
//public protocol IndexableItem {
// var indexedOn: NSString { get }
//}
//
//public class IndexedListCollator<Item: IndexableItem> {
// private final class CollationWrapper: NSObject {
// let value: Any
// @objc let indexedOn: NSString
//
// init(value: Any, indexedOn: NSString) {
// self.value = value
// self.indexedOn = indexedOn
// }
//
// func unwrappedValue<UnwrappedType>() -> UnwrappedType {
// return value as! UnwrappedType
// }
// }
//
// public init() {}
//
// public func sectioned(items: [Item]) -> (sections: [[Item]], collation: UILocalizedIndexedCollation) {
// let collation = UILocalizedIndexedCollation.current()
// let selector = #selector(getter: CollationWrapper.indexedOn)
//
// let wrappedItems = items.map { item in
// CollationWrapper(value: item, indexedOn: item.indexedOn)
// }
//
// let sortedObjects = collation.sortedArray(from: wrappedItems, collationStringSelector: selector) as! [CollationWrapper]
//
// var sections = collation.sectionIndexTitles.map { _ in [Item]() }
// sortedObjects.forEach { item in
// let sectionNumber = collation.section(for: item, collationStringSelector: selector)
// sections[sectionNumber].append(item.unwrappedValue())
// }
//
// return (sections: sections.filter { !$0.isEmpty }, collation: collation)
// }
//}
//
//public struct Contact: Codable, Hashable, Equatable {
// public enum Request {
// case all
// case failed
// case friends
// case received
// case requested
// case isRecent
// case verificationInProgress
// case withUserId(Data)
// case withUserIds([Data])
// case withUsername(String)
// }
//
// public enum Status: Int64, Codable {
// case friend
// case stranger
// case verified
// case verificationFailed
// case verificationInProgress
// case requested
// case requesting
// case requestFailed
// case confirming
// case confirmationFailed
// case hidden
// }
//
// public var id: Int64?
// public var photo: Data?
// public let userId: Data
// public var email: String?
// public var phone: String?
// public var status: Status
// public var marshaled: Data
// public var createdAt: Date
// public let username: String
// public var nickname: String?
// public var isRecent: Bool
//
// public init(
// photo: Data?,
// userId: Data,
// email: String?,
// phone: String?,
// status: Status,
// marshaled: Data,
// username: String,
// nickname: String?,
// createdAt: Date,
// isRecent: Bool
// ) {
// self.email = email
// self.phone = phone
// self.photo = photo
// self.status = status
// self.userId = userId
// self.username = username
// self.nickname = nickname
// self.marshaled = marshaled
// self.createdAt = createdAt
// self.isRecent = isRecent
// }
//
// public var differenceIdentifier: Data { userId }
//
// public static var databaseTableName: String { "contacts" }
//}
//
//extension Contact: Differentiable {}
//extension Contact: IndexableItem {
// public var indexedOn: NSString {
// guard let nickname = nickname else {
// return "\(username.first!)" as NSString
// }
//
// return "\(nickname.first!)" as NSString
// }
//}
import UIKit
import DifferenceKit
public protocol IndexableItem {
var indexedOn: NSString { get }
}
public class IndexedListCollator<Item: IndexableItem> {
private final class CollationWrapper: NSObject {
let value: Any
@objc let indexedOn: NSString
init(value: Any, indexedOn: NSString) {
self.value = value
self.indexedOn = indexedOn
}
func unwrappedValue<UnwrappedType>() -> UnwrappedType {
return value as! UnwrappedType
}
}
public init() {}
public func sectioned(items: [Item]) -> (sections: [[Item]], collation: UILocalizedIndexedCollation) {
let collation = UILocalizedIndexedCollation.current()
let selector = #selector(getter: CollationWrapper.indexedOn)
let wrappedItems = items.map { item in
CollationWrapper(value: item, indexedOn: item.indexedOn)
}
let sortedObjects = collation.sortedArray(from: wrappedItems, collationStringSelector: selector) as! [CollationWrapper]
var sections = collation.sectionIndexTitles.map { _ in [Item]() }
sortedObjects.forEach { item in
let sectionNumber = collation.section(for: item, collationStringSelector: selector)
sections[sectionNumber].append(item.unwrappedValue())
}
return (sections: sections.filter { !$0.isEmpty }, collation: collation)
}
}
public struct Contact: Codable, Hashable, Equatable {
public enum Request {
case all
case failed
case friends
case received
case requested
case isRecent
case verificationInProgress
case withUserId(Data)
case withUserIds([Data])
case withUsername(String)
}
public enum Status: Int64, Codable {
case friend
case stranger
case verified
case verificationFailed
case verificationInProgress
case requested
case requesting
case requestFailed
case confirming
case confirmationFailed
case hidden
}
public var id: Int64?
public var photo: Data?
public let userId: Data
public var email: String?
public var phone: String?
public var status: Status
public var marshaled: Data
public var createdAt: Date
public let username: String
public var nickname: String?
public var isRecent: Bool
public init(
photo: Data?,
userId: Data,
email: String?,
phone: String?,
status: Status,
marshaled: Data,
username: String,
nickname: String?,
createdAt: Date,
isRecent: Bool
) {
self.email = email
self.phone = phone
self.photo = photo
self.status = status
self.userId = userId
self.username = username
self.nickname = nickname
self.marshaled = marshaled
self.createdAt = createdAt
self.isRecent = isRecent
}
public var differenceIdentifier: Data { userId }
public static var databaseTableName: String { "contacts" }
}
extension Contact: Differentiable {}
extension Contact: IndexableItem {
public var indexedOn: NSString {
guard let nickname = nickname else {
return "\(username.first!)" as NSString
}
return "\(nickname.first!)" as NSString
}
}
//import Foundation
//
//public struct FileTransfer {
// public enum Request {
// case withTID(Data)
// case withContactId(Data)
// }
//
// public var tid: Data
// public var id: Int64?
// public var contact: Data
// public var fileName: String
// public var fileType: String
// public var isIncoming: Bool
//
// public static var databaseTableName: String { "transfers" }
//
// public init(
// id: Int64? = nil,
// tid: Data,
// contact: Data,
// fileName: String,
// fileType: String,
// isIncoming: Bool
// ) {
// self.id = id
// self.tid = tid
// self.contact = contact
// self.fileName = fileName
// self.fileType = fileType
// self.isIncoming = isIncoming
// }
//}
//
//extension FileTransfer: Codable {}
//extension FileTransfer: Hashable {}
//extension FileTransfer: Equatable {}
import Foundation
public struct FileTransfer {
public enum Request {
case withTID(Data)
case withContactId(Data)
}
public var tid: Data
public var id: Int64?
public var contact: Data
public var fileName: String
public var fileType: String
public var isIncoming: Bool
public static var databaseTableName: String { "transfers" }
public init(
id: Int64? = nil,
tid: Data,
contact: Data,
fileName: String,
fileType: String,
isIncoming: Bool
) {
self.id = id
self.tid = tid
self.contact = contact
self.fileName = fileName
self.fileType = fileType
self.isIncoming = isIncoming
}
}
extension FileTransfer: Codable {}
extension FileTransfer: Hashable {}
extension FileTransfer: Equatable {}
//import Foundation
//import KeychainAccess
//
//public struct Group: Codable, Equatable, Hashable {
// public enum Status: Int64, Codable {
// case hidden
// case pending
// case deleting
// case participating
// }
//
// public enum Request {
// case pending
// case accepted
// case withGroupId(Data)
// }
//
// public var id: Int64?
// public var name: String
// public var leader: Data
// public var groupId: Data
// public var status: Status
// public var serialize: Data
// public var createdAt: Date
// public static var databaseTableName: String { "groups" }
//
// public init(
// leader: Data,
// name: String,
// groupId: Data,
// status: Status,
// createdAt: Date,
// serialize: Data
// ) {
// self.name = name
// self.leader = leader
// self.status = status
// self.groupId = groupId
// self.createdAt = createdAt
// self.serialize = serialize
// }
//}
import Foundation
import KeychainAccess
public struct Group: Codable, Equatable, Hashable {
public enum Status: Int64, Codable {
case hidden
case pending
case deleting
case participating
}
public enum Request {
case pending
case accepted
case withGroupId(Data)
}
public var id: Int64?
public var name: String
public var leader: Data
public var groupId: Data
public var status: Status
public var serialize: Data
public var createdAt: Date
public static var databaseTableName: String { "groups" }
public init(
leader: Data,
name: String,
groupId: Data,
status: Status,
createdAt: Date,
serialize: Data
) {
self.name = name
self.leader = leader
self.status = status
self.groupId = groupId
self.createdAt = createdAt
self.serialize = serialize
}
}
//import Foundation
//
//public struct GroupChatInfo: Codable, Equatable, Hashable {
// public enum Request {
// case accepted
// case fromGroup(Data)
// }
//
// public var group: Group
// public var members: [GroupMember]
// public var lastMessage: GroupMessage?
//
// public init(
// group: Group,
// members: [GroupMember],
// lastMessage: GroupMessage? = nil
// ) {
// self.group = group
// self.members = members
// self.lastMessage = lastMessage
// }
//}
import Foundation
public struct GroupChatInfo: Codable, Equatable, Hashable {
public enum Request {
case accepted
case fromGroup(Data)
}
public var group: Group
public var members: [GroupMember]
public var lastMessage: GroupMessage?
public init(
group: Group,
members: [GroupMember],
lastMessage: GroupMessage? = nil
) {
self.group = group
self.members = members
self.lastMessage = lastMessage
}
}
//import Foundation
//
//public struct GroupMember {
// public enum Request {
// case all
// case strangers
// case fromGroup(Data)
// case withUserId(Data)
// }
//
// public enum Status: Int64, Codable {
// case usernameSet
// case pendingUsername
// }
//
// public var id: Int64?
// public var userId: Data
// public var groupId: Data
// public var status: Status
// public var username: String
// public var photo: Data?
//
// public init(
// id: Int64? = nil,
// userId: Data,
// groupId: Data,
// status: Status,
// username: String,
// photo: Data? = nil
// ) {
// self.id = id
// self.userId = userId
// self.groupId = groupId
// self.username = username
// self.status = status
// self.photo = photo
// }
//}
//
//extension GroupMember: Codable {}
//extension GroupMember: Hashable {}
//extension GroupMember: Equatable {}
import Foundation
public struct GroupMember {
public enum Request {
case all
case strangers
case fromGroup(Data)
case withUserId(Data)
}
public enum Status: Int64, Codable {
case usernameSet
case pendingUsername
}
public var id: Int64?
public var userId: Data
public var groupId: Data
public var status: Status
public var username: String
public var photo: Data?
public init(
id: Int64? = nil,
userId: Data,
groupId: Data,
status: Status,
username: String,
photo: Data? = nil
) {
self.id = id
self.userId = userId
self.groupId = groupId
self.username = username
self.status = status
self.photo = photo
}
}
extension GroupMember: Codable {}
extension GroupMember: Hashable {}
extension GroupMember: Equatable {}
//import Foundation
//
//public struct GroupMessage: Codable, Equatable, Hashable {
// public enum Request {
// case withUniqueId(Data)
// case id(Int64)
// case sending
// case fromGroup(Data)
// case unreadsFromGroup(Data)
// }
//
// public static var databaseTableName: String { "groupMessages" }
//
// public enum Status: Int64, Codable {
// case sent
// case read
// case failed
// case sending
// case received
// }
//
// public var id: Int64?
// public var uniqueId: Data?
// public var groupId: Data
// public var sender: Data
// public var roundId: Int64?
// public var payload: Payload
// public var status: Status
// public var roundURL: String?
// public var unread: Bool
// public var timestamp: Int
//
// public init(
// id: Int64? = nil,
// sender: Data,
// groupId: Data,
// payload: Payload,
// unread: Bool,
// timestamp: Int = 0,
// uniqueId: Data?,
// status: Status,
// roundId: Int64? = nil,
// roundURL: String? = nil
// ) {
// self.id = id
// self.sender = sender
// self.groupId = groupId
// self.payload = payload
// self.unread = unread
// self.timestamp = timestamp
// self.uniqueId = uniqueId
// self.status = status
// self.roundId = roundId
// self.roundURL = roundURL
// }
//}
import Foundation
public struct GroupMessage: Codable, Equatable, Hashable {
public enum Request {
case withUniqueId(Data)
case id(Int64)
case sending
case fromGroup(Data)
case unreadsFromGroup(Data)
}
public static var databaseTableName: String { "groupMessages" }
public enum Status: Int64, Codable {
case sent
case read
case failed
case sending
case received
}
public var id: Int64?
public var uniqueId: Data?
public var groupId: Data
public var sender: Data
public var roundId: Int64?
public var payload: Payload
public var status: Status
public var roundURL: String?
public var unread: Bool
public var timestamp: Int
public init(
id: Int64? = nil,
sender: Data,
groupId: Data,
payload: Payload,
unread: Bool,
timestamp: Int = 0,
uniqueId: Data?,
status: Status,
roundId: Int64? = nil,
roundURL: String? = nil
) {
self.id = id
self.sender = sender
self.groupId = groupId
self.payload = payload
self.unread = unread
self.timestamp = timestamp
self.uniqueId = uniqueId
self.status = status
self.roundId = roundId
self.roundURL = roundURL
}
}
//import Foundation
//import DifferenceKit
//
//public struct Message: Codable, Equatable, Hashable {
// public enum Request {
// case sending
// case withUniqueId(Data)
// case withId(Int64)
// case sendingAttachment
// case withContact(Data)
// case unreadsFromContactId(Data)
// case latestOnesFromContactIds([Data])
// }
//
// public enum Status: Int64, Codable {
// case read
// case sent
// case sending
// case sendingAttachment
// case receivingAttachment
// case received
// case failedToSend
// case timedOut
// }
//
// public var id: Int64?
// public var unread: Bool
// public let sender: Data
// public var roundURL: String?
// public var report: Data?
// public var status: Status
// public let receiver: Data
// public var timestamp: Int
// public var uniqueId: Data?
// public var payload: Payload
// public static var databaseTableName: String { "messages" }
//
// public init (
// sender: Data,
// receiver: Data,
// payload: Payload,
// unread: Bool,
// timestamp: Int,
// uniqueId: Data?,
// status: Status,
// roundURL: String? = nil
// ) {
// self.sender = sender
// self.unread = unread
// self.status = status
// self.payload = payload
// self.receiver = receiver
// self.uniqueId = uniqueId
// self.timestamp = timestamp
// self.roundURL = roundURL
// }
//}
//
//public extension Message.Status {
// var canReply: Bool {
// switch self {
// case .sent, .received, .read:
// return true
// default:
// return false
// }
// }
//}
//
//extension Message: Differentiable {}
import Foundation
import DifferenceKit
public struct Message: Codable, Equatable, Hashable {
public enum Request {
case sending
case withUniqueId(Data)
case withId(Int64)
case sendingAttachment
case withContact(Data)
case unreadsFromContactId(Data)
case latestOnesFromContactIds([Data])
}
public enum Status: Int64, Codable {
case read
case sent
case sending
case sendingAttachment
case receivingAttachment
case received
case failedToSend
case timedOut
}
public var id: Int64?
public var unread: Bool
public let sender: Data
public var roundURL: String?
public var report: Data?
public var status: Status
public let receiver: Data
public var timestamp: Int
public var uniqueId: Data?
public var payload: Payload
public static var databaseTableName: String { "messages" }
public init (
sender: Data,
receiver: Data,
payload: Payload,
unread: Bool,
timestamp: Int,
uniqueId: Data?,
status: Status,
roundURL: String? = nil
) {
self.sender = sender
self.unread = unread
self.status = status
self.payload = payload
self.receiver = receiver
self.uniqueId = uniqueId
self.timestamp = timestamp
self.roundURL = roundURL
}
}
public extension Message.Status {
var canReply: Bool {
switch self {
case .sent, .received, .read:
return true
default:
return false
}
}
}
extension Message: Differentiable {}
//import Foundation
//
//public struct Payload: Codable, Equatable, Hashable {
// public var text: String
// public var reply: Reply?
// public var attachment: Attachment?
//
// public init(text: String, reply: Reply?, attachment: Attachment?) {
// self.text = text
// self.reply = reply
// self.attachment = attachment
// }
//
// public init(with marshaled: Data) throws {
// let proto = try CMIXText(serializedData: marshaled)
//
// var reply: Reply?
//
// if proto.hasReply {
// reply = Reply(
// messageId: proto.reply.messageID,
// senderId: proto.reply.senderID
// )
// }
//
// self.init(text: proto.text, reply: reply, attachment: nil)
// }
//
// public func asData() -> Data {
// var protoModel = CMIXText()
// protoModel.text = text
//
// if let reply = reply {
// protoModel.reply = reply.asTextReply()
// }
//
// return try! protoModel.serializedData()
// }
//}
import Foundation
public struct Payload: Codable, Equatable, Hashable {
public var text: String
public var reply: Reply?
public var attachment: Attachment?
public init(text: String, reply: Reply?, attachment: Attachment?) {
self.text = text
self.reply = reply
self.attachment = attachment
}
public init(with marshaled: Data) throws {
let proto = try CMIXText(serializedData: marshaled)
var reply: Reply?
if proto.hasReply {
reply = Reply(
messageId: proto.reply.messageID,
senderId: proto.reply.senderID
)
}
self.init(text: proto.text, reply: reply, attachment: nil)
}
public func asData() -> Data {
var protoModel = CMIXText()
protoModel.text = text
if let reply = reply {
protoModel.reply = reply.asTextReply()
}
return try! protoModel.serializedData()
}
}
//import Foundation
//
//public struct Reply: Codable, Equatable, Hashable {
// public let messageId: Data
// public let senderId: Data
//
// public init(messageId: Data, senderId: Data) {
// self.messageId = messageId
// self.senderId = senderId
// }
//
// func asTextReply() -> TextReply {
// var reply = TextReply()
// reply.messageID = messageId
// reply.senderID = senderId
//
// return reply
// }
//}
import Foundation
public struct Reply: Codable, Equatable, Hashable {
public let messageId: Data
public let senderId: Data
public init(messageId: Data, senderId: Data) {
self.messageId = messageId
self.senderId = senderId
}
func asTextReply() -> TextReply {
var reply = TextReply()
reply.messageID = messageId
reply.senderID = senderId
return reply
}
}
//import Foundation
//
//public struct SingleChatInfo: Codable, Equatable, Hashable {
// public enum Request {
// case all
// }
//
// public var contact: Contact
// public var lastMessage: Message?
//
// public init(
// contact: Contact,
// lastMessage: Message?
// ) {
// self.contact = contact
// self.lastMessage = lastMessage
// }
//}
import Foundation
public struct SingleChatInfo: Codable, Equatable, Hashable {
public enum Request {
case all
}
public var contact: Contact
public var lastMessage: Message?
public init(
contact: Contact,
lastMessage: Message?
) {
self.contact = contact
self.lastMessage = lastMessage
}
}
import UIKit
import Models
import Defaults
import Database
import Integration
import DependencyInjection
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment