Fix a crash opening Search when a video is in history under several sources

watchEntriesMap() built its dictionary with uniqueKeysWithValues, but the
same video ID can be recorded under more than one source scope, which
trapped on the duplicate key (3 crash logs from build 270, all in
SearchView.loadWatchEntries). Keep the most recent entry instead.

The subscription metadata map in Manage Channels had the same shape (a
channel subscribed under several account scopes), as did the server
history hydration map; both now tolerate duplicates.
This commit is contained in:
Arkadiusz Fal
2026-10-14 09:24:56 +02:00
parent fd6a97ce5c
commit e5cea1b6c8
3 changed files with 9 additions and 4 deletions

View File

@@ -136,7 +136,9 @@ extension DataManager {
/// Returns a dictionary of video ID to WatchEntry for efficient bulk lookup.
func watchEntriesMap() -> [String: WatchEntry] {
let entries = watchHistory(limit: 10000)
return Dictionary(uniqueKeysWithValues: entries.map { ($0.videoID, $0) })
// The same video ID can be recorded under several source scopes; the
// history is most recent first, so the first entry is the one to keep.
return Dictionary(entries.map { ($0.videoID, $0) }, uniquingKeysWith: { first, _ in first })
}
/// Gets the total count of watch history entries.

View File

@@ -1990,9 +1990,10 @@ struct HomeView: View {
}
let known: [String: Video] = Dictionary(
uniqueKeysWithValues: ids.compactMap { id in
ids.compactMap { id in
dataManager?.watchEntry(for: id).map { (id, $0.toVideo()) }
}
},
uniquingKeysWith: { first, _ in first }
)
return await withTaskGroup(of: (Int, Video).self) { group in

View File

@@ -263,8 +263,10 @@ struct ManageChannelsView: View {
if let syncChannels = subscriptionService?.fetchSubscriptionsSync() {
channels = syncChannels
}
// A channel can be subscribed under several account scopes.
subscriptionMetadata = Dictionary(
uniqueKeysWithValues: (dataManager?.subscriptions() ?? []).map { ($0.channelID, $0) }
(dataManager?.subscriptions() ?? []).map { ($0.channelID, $0) },
uniquingKeysWith: { first, _ in first }
)
}
.task {