summaryrefslogtreecommitdiff
path: root/Sora/Views/Generic
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-18 12:45:11 -0800
committerFuwn <[email protected]>2026-02-18 12:45:19 -0800
commit2aaf7665047f61e72495b99b6caaef54d19332fe (patch)
treec82cbc7a8b99bdc2eb59e75748c2c18bb9d39713 /Sora/Views/Generic
parentperf: memoize post grid derived collections and remove columns cache (diff)
downloadsora-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.swift49
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) {