diff options
| author | Fuwn <[email protected]> | 2026-02-18 12:45:11 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-18 12:45:19 -0800 |
| commit | 2aaf7665047f61e72495b99b6caaef54d19332fe (patch) | |
| tree | c82cbc7a8b99bdc2eb59e75748c2c18bb9d39713 /Sora/Views/Generic | |
| parent | perf: memoize post grid derived collections and remove columns cache (diff) | |
| download | sora-testing-2aaf7665047f61e72495b99b6caaef54d19332fe.tar.xz sora-testing-2aaf7665047f61e72495b99b6caaef54d19332fe.zip | |
chore: finalise performance optimisation batch and metrics
Diffstat (limited to 'Sora/Views/Generic')
| -rw-r--r-- | Sora/Views/Generic/GenericListView.swift | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/Sora/Views/Generic/GenericListView.swift b/Sora/Views/Generic/GenericListView.swift index a829856..096ac85 100644 --- a/Sora/Views/Generic/GenericListView.swift +++ b/Sora/Views/Generic/GenericListView.swift @@ -32,6 +32,9 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { let removeAllAction: () -> Void @State private var folderHierarchy = FolderHierarchy(folders: []) @State private var displayedItems: [T] = [] + @State private var shuffleOrderByIdentifier: [UUID: Int] = [:] + @State private var shuffleSourceIdentifiers: [UUID] = [] + @State private var shouldRefreshShuffleOrder = true private func refreshFolderHierarchy() { folderHierarchy = FolderHierarchy(folders: settings.folders) @@ -85,14 +88,44 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { return leftItem.visitedCount > rightItem.visitedCount case .shuffle: - return Bool.random() + return leftItem.date > rightItem.date + } + } + } + + private func refreshShuffleOrder(for itemsToShuffle: [T]) { + let currentIdentifiers = itemsToShuffle.map(\.id) + + if shouldRefreshShuffleOrder || shuffleSourceIdentifiers != currentIdentifiers { + var refreshedShuffleOrderByIdentifier: [UUID: Int] = [:] + let shuffledIdentifiers = currentIdentifiers.shuffled() + + for (identifierIndex, identifier) in shuffledIdentifiers.enumerated() { + refreshedShuffleOrderByIdentifier[identifier] = identifierIndex + } + + shuffleOrderByIdentifier = refreshedShuffleOrderByIdentifier + shuffleSourceIdentifiers = currentIdentifiers + shouldRefreshShuffleOrder = false + } + } + + private func shuffledItems(from itemsToShuffle: [T]) -> [T] { + itemsToShuffle.sorted { leftItem, rightItem in + let leftIndex = shuffleOrderByIdentifier[leftItem.id] ?? Int.max + let rightIndex = shuffleOrderByIdentifier[rightItem.id] ?? Int.max + + if leftIndex != rightIndex { + return leftIndex < rightIndex } + + return leftItem.id.uuidString < rightItem.id.uuidString } } private func refreshDisplayedItems() { let normalizedSearchText = searchText.lowercased() - let filteredItems = items.filter { item in + let matchingItems = items.filter { item in let matchesSearch = normalizedSearchText.isEmpty || item.tags @@ -106,7 +139,13 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { return matchesSelectedCollection(for: item) && matchesSearch && matchesProvider } - displayedItems = sortedItems(from: filteredItems) + if !allowBookmarking, sort == .shuffle { + refreshShuffleOrder(for: matchingItems) + displayedItems = shuffledItems(from: matchingItems) + return + } + + displayedItems = sortedItems(from: matchingItems) } @ViewBuilder private var listContent: some View { @@ -379,6 +418,10 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View { refreshDisplayedItems() } .onChange(of: sort) { + if sort == .shuffle { + shouldRefreshShuffleOrder = true + } + refreshDisplayedItems() } .onChange(of: settings.folders) { |