mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
wip
This commit is contained in:
@@ -43,9 +43,23 @@ private func addTermItem(_ items: inout [TerminalItem], _ item: TerminalItem) {
|
||||
items.append(item)
|
||||
}
|
||||
|
||||
/// Represents a gap in a list of chat items, indicating where data is missing and should be loaded.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - itemId: The unique identifier of the last item in the loaded list before the gap.
|
||||
/// This ID corresponds to an item in the chat history, ordered from older to newer items.
|
||||
/// It is typically used when loading items via .around or .initial pagination when loading items
|
||||
/// - indexRange: The range of indexes within `reversedChatItems` array that
|
||||
/// represents the gap. The first index in this range is the position of the gap itself.
|
||||
/// For instance, if the array `[0, 1, 2, -100-, 101]` has a gap at index 3, `indexRange`
|
||||
/// would be `3..<5`, indicating the gap starts at index 3.
|
||||
/// - indexRangeInParentItems: The range of indexes in the `ReverseList` or parent UI component
|
||||
/// that considers revealed or hidden items, showing where the gap appears in the visible list.
|
||||
/// The first index in this range points to where the gap starts in the UI.
|
||||
struct ChatGap {
|
||||
let index: Int
|
||||
let size: Int
|
||||
let itemId: Int64
|
||||
let indexRange: Range<Int>
|
||||
let indexRangeInParentItems: Range<Int>
|
||||
}
|
||||
|
||||
class ItemsModel: ObservableObject {
|
||||
@@ -63,14 +77,12 @@ class ItemsModel: ObservableObject {
|
||||
var itemAdded = false {
|
||||
willSet { publisher.send() }
|
||||
}
|
||||
var gap: ChatGap? = nil {
|
||||
willSet { publisher.send() }
|
||||
}
|
||||
|
||||
// Publishes directly to `objectWillChange` publisher,
|
||||
// this will cause reversedChatItems to be rendered without throttling
|
||||
@Published var isLoading = false
|
||||
@Published var showLoadingProgress = false
|
||||
@State var gaps: [ChatItem.ID] = []
|
||||
|
||||
init() {
|
||||
publisher
|
||||
@@ -99,7 +111,9 @@ class ItemsModel: ObservableObject {
|
||||
if let chat = ChatModel.shared.getChat(chatId) {
|
||||
await MainActor.run { self.isLoading = true }
|
||||
// try? await Task.sleep(nanoseconds: 5000_000000)
|
||||
await loadChat(chat: chat)
|
||||
if let gap = await loadChat(chat: chat) {
|
||||
self.gaps = [gap]
|
||||
}
|
||||
navigationTimeout.cancel()
|
||||
progressTimeout.cancel()
|
||||
await MainActor.run {
|
||||
|
||||
@@ -322,15 +322,15 @@ let loadItemsPerPage = 100
|
||||
let preloadItem = 25
|
||||
let idealChatListSize = 300
|
||||
|
||||
func apiGetChat(type: ChatType, id: Int64, search: String = "") async throws -> Chat {
|
||||
func apiGetChat(type: ChatType, id: Int64, search: String = "") async throws -> (Chat, Int?) {
|
||||
let r = await chatSendCmd(.apiGetChat(type: type, id: id, pagination: .initial(count: loadItemsPerPage), search: search))
|
||||
if case let .apiChat(_, chat, _) = r { return Chat.init(chat) }
|
||||
if case let .apiChat(_, chat, gap) = r { return (Chat.init(chat), gap) }
|
||||
throw r
|
||||
}
|
||||
|
||||
func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, search: String = "") async throws -> [ChatItem] {
|
||||
func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, search: String = "") async throws -> ([ChatItem], Int?) {
|
||||
let r = await chatSendCmd(.apiGetChat(type: type, id: id, pagination: pagination, search: search))
|
||||
if case let .apiChat(_, chat, _) = r { return chat.chatItems }
|
||||
if case let .apiChat(_, chat, gap) = r { return (chat.chatItems, gap) }
|
||||
if case .chatCmdError(_, _) = r {
|
||||
if case .chatError(_, let chatError) = r {
|
||||
if case .errorStore(let storeError) = chatError {
|
||||
@@ -343,7 +343,7 @@ func apiGetChatItems(type: ChatType, id: Int64, pagination: ChatPagination, sear
|
||||
throw r
|
||||
}
|
||||
|
||||
func loadChat(chat: Chat, search: String = "", clearItems: Bool = true) async {
|
||||
func loadChat(chat: Chat, search: String = "", clearItems: Bool = true) async -> ChatItem.ID? {
|
||||
do {
|
||||
let cInfo = chat.chatInfo
|
||||
let m = ChatModel.shared
|
||||
@@ -352,17 +352,23 @@ func loadChat(chat: Chat, search: String = "", clearItems: Bool = true) async {
|
||||
if clearItems {
|
||||
await MainActor.run {
|
||||
im.reversedChatItems = []
|
||||
im.gap = nil
|
||||
}
|
||||
}
|
||||
let chat = try await apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search)
|
||||
let (chat, gap) = try await apiGetChat(type: cInfo.chatType, id: cInfo.apiId, search: search)
|
||||
await MainActor.run {
|
||||
im.reversedChatItems = chat.chatItems.reversed()
|
||||
m.updateChatInfo(chat.chatInfo)
|
||||
}
|
||||
|
||||
return if gap != nil {
|
||||
chat.chatItems[loadItemsPerPage].id
|
||||
} else {
|
||||
nil
|
||||
}
|
||||
} catch let error {
|
||||
logger.error("loadChat error: \(responseError(error))")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func apiGetChatItemInfo(type: ChatType, id: Int64, itemId: Int64) async throws -> ChatItemInfo {
|
||||
|
||||
Reference in New Issue
Block a user