129 lines
4.2 KiB
Swift
129 lines
4.2 KiB
Swift
import Foundation
|
|
|
|
public protocol SessionBridge: Sendable {
|
|
func authState() async throws -> AuthState
|
|
func pollEvents() async throws -> [SessionEvent]
|
|
func sendPhoneNumber(_ phone: String) async throws
|
|
func sendCode(_ code: String) async throws
|
|
func sendPassword(_ password: String) async throws
|
|
func loadFolders() async throws -> [Folder]
|
|
func loadChats(folderId: Int32?) async throws -> [ChatSummary]
|
|
func loadHistory(chatId: Int64) async throws -> [Message]
|
|
func openProfile(chatId: Int64) async throws -> Profile
|
|
func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message
|
|
}
|
|
|
|
public actor FakeSessionBridge: SessionBridge {
|
|
private var auth: AuthState
|
|
private var chats: [ChatSummary]
|
|
private var messages: [Int64: [Message]]
|
|
private var events: [SessionEvent]
|
|
private var nextMessageId: Int64
|
|
|
|
public init(auth: AuthState = .waitPhoneNumber) {
|
|
self.auth = auth
|
|
let saved = ChatSummary(
|
|
id: 1,
|
|
title: "Saved Messages",
|
|
username: "saved",
|
|
lastMessage: "Hello from fake TDLib",
|
|
unreadCount: 1,
|
|
isPinned: true
|
|
)
|
|
let team = ChatSummary(
|
|
id: 2,
|
|
title: "iOS Team",
|
|
lastMessage: "Bridge smoke is green",
|
|
unreadMentionCount: 1,
|
|
folderIds: [0, 2],
|
|
isMuted: true,
|
|
draft: Draft(chatId: 2, text: "Follow up")
|
|
)
|
|
self.chats = [saved, team]
|
|
self.messages = [
|
|
1: [
|
|
Message(id: 1, chatId: 1, senderName: "Alice", text: "Hello from fake TDLib", isOutgoing: false, isRead: false)
|
|
],
|
|
2: [
|
|
Message(id: 2, chatId: 2, senderName: "Mikhail", text: "Bridge smoke is green", isOutgoing: true)
|
|
],
|
|
]
|
|
self.events = [.chatListChanged([saved, team])]
|
|
self.nextMessageId = 3
|
|
}
|
|
|
|
public func authState() async throws -> AuthState {
|
|
auth
|
|
}
|
|
|
|
public func pollEvents() async throws -> [SessionEvent] {
|
|
let drained = events
|
|
events.removeAll()
|
|
return drained
|
|
}
|
|
|
|
public func sendPhoneNumber(_ phone: String) async throws {
|
|
auth = .waitCode
|
|
events.append(.authChanged(auth))
|
|
}
|
|
|
|
public func sendCode(_ code: String) async throws {
|
|
auth = .waitPassword
|
|
events.append(.authChanged(auth))
|
|
}
|
|
|
|
public func sendPassword(_ password: String) async throws {
|
|
auth = .ready
|
|
events.append(.authChanged(auth))
|
|
}
|
|
|
|
public func loadFolders() async throws -> [Folder] {
|
|
[Folder(id: 0, name: "All"), Folder(id: 2, name: "Work")]
|
|
}
|
|
|
|
public func loadChats(folderId: Int32?) async throws -> [ChatSummary] {
|
|
let result = folderId.map { folderId in
|
|
chats.filter { $0.folderIds.contains(folderId) }
|
|
} ?? chats
|
|
events.append(.chatListChanged(result))
|
|
return result
|
|
}
|
|
|
|
public func loadHistory(chatId: Int64) async throws -> [Message] {
|
|
messages[chatId] ?? []
|
|
}
|
|
|
|
public func openProfile(chatId: Int64) async throws -> Profile {
|
|
let chat = chats.first { $0.id == chatId }
|
|
let profile = Profile(
|
|
chatId: chatId,
|
|
title: chat?.title ?? "Unknown",
|
|
username: chat?.username,
|
|
bio: chatId == 1 ? "Fake profile for the iOS app shell" : "Team chat",
|
|
isGroup: chatId != 1,
|
|
memberCount: chatId == 1 ? nil : 4
|
|
)
|
|
events.append(.profileLoaded(profile))
|
|
return profile
|
|
}
|
|
|
|
public func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message {
|
|
let message = Message(
|
|
id: nextMessageId,
|
|
chatId: chatId,
|
|
senderName: "Me",
|
|
text: text,
|
|
isOutgoing: true,
|
|
replyText: replyToMessageId.map { "Reply to #\($0)" }
|
|
)
|
|
nextMessageId += 1
|
|
messages[chatId, default: []].append(message)
|
|
if let index = chats.firstIndex(where: { $0.id == chatId }) {
|
|
chats[index].lastMessage = text
|
|
chats[index].draft = nil
|
|
}
|
|
events.append(.messageAdded(chatId, message))
|
|
return message
|
|
}
|
|
}
|