initial commit

This commit is contained in:
Filip
2026-03-11 16:06:00 +01:00
parent b3c69053f6
commit 5fd80e6dd6
127 changed files with 39684 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
import Foundation
struct Conversation: Identifiable, Equatable {
let id: String
var name: String?
var members: [ConversationMember]
var createdBy: String?
var avatarFile: String?
var unreadCount: Int
var isFavorite: Bool
var lastMessageTime: Date?
var isGroup: Bool {
name != nil || members.count > 2
}
/// Display name: group name, or DM partner username
func displayName(currentUserId: String) -> String {
if let name = name, !name.isEmpty {
return name
}
// DM: show the other person's name
if let other = members.first(where: { $0.userId != currentUserId }) {
return other.username
}
return "Unknown"
}
/// DM partner user ID (nil for groups)
func dmPartnerId(currentUserId: String) -> String? {
guard !isGroup else { return nil }
return members.first(where: { $0.userId != currentUserId })?.userId
}
static func == (lhs: Conversation, rhs: Conversation) -> Bool {
lhs.id == rhs.id
}
}
struct ConversationMember: Identifiable, Equatable, Codable {
let userId: String
var username: String
var email: String
var id: String { userId }
}

View File

@@ -0,0 +1,43 @@
import Foundation
/// Key bundle for one device, used in X3DH
struct DeviceBundle {
let deviceId: String
let identityKey: Data // Ed25519 public key (32 bytes)
let spk: Data // X25519 public key (32 bytes)
let spkSignature: Data // Ed25519 signature (64 bytes)
let spkId: String
let opk: Data? // X25519 public key (32 bytes), optional
let opkId: String?
/// Parse from server response dictionary
static func fromDict(_ dict: [String: Any]) throws -> DeviceBundle {
guard let deviceId = dict["device_id"] as? String,
let ikHex = dict["identity_key"] as? String,
let ik = Data(hexString: ikHex),
let spkHex = dict["spk"] as? String,
let spk = Data(hexString: spkHex),
let spkSigHex = dict["spk_signature"] as? String,
let spkSig = Data(hexString: spkSigHex),
let spkId = dict["spk_id"] as? String else {
throw ChatError.invalidData("Invalid device bundle")
}
var opk: Data?
var opkId: String?
if let opkHex = dict["opk"] as? String, let opkData = Data(hexString: opkHex) {
opk = opkData
opkId = dict["opk_id"] as? String
}
return DeviceBundle(
deviceId: deviceId,
identityKey: ik,
spk: spk,
spkSignature: spkSig,
spkId: spkId,
opk: opk,
opkId: opkId
)
}
}

View File

@@ -0,0 +1,9 @@
import Foundation
struct Invitation: Identifiable {
let id: String // invitation id (from server) or conversationId
let conversationId: String
let conversationName: String
let invitedBy: String
let invitedByUsername: String
}

View File

@@ -0,0 +1,33 @@
import Foundation
struct Message: Identifiable, Equatable {
let id: String
let conversationId: String
let senderId: String
var senderUsername: String
let createdAt: Date
var text: String?
var replyTo: String?
var imageFileId: String?
var file: FileInfo?
var isDeleted: Bool
var readBy: Set<String>
/// Whether this is a self-sent message
func isMine(currentUserId: String) -> Bool {
senderId == currentUserId
}
static func == (lhs: Message, rhs: Message) -> Bool {
lhs.id == rhs.id
}
}
struct FileInfo: Equatable, Codable {
let fileId: String
let aesKey: String // hex
let iv: String // hex
let filename: String
let size: Int
let mimeType: String
}

View File

@@ -0,0 +1,19 @@
import Foundation
struct User: Identifiable, Equatable {
let id: String
var username: String
var email: String
var identityKey: Data? // Ed25519 public key (32 bytes)
}
struct UserProfile: Equatable {
var userId: String
var username: String?
var email: String?
var phone: String?
var phoneVisible: Bool
var location: String?
var locationVisible: Bool
var avatarFile: String?
}