feat(offline): ⭐ star in place — keep files in their show group
Starring no longer relocates a file into a separate 'Starred' section; every item stays in its own show group and the row's star button just toggles on/off (filled-yellow vs outline) as the keep-from-cull indicator. Show headers show a '★N' badge for how many in that group are starred. Drops the leading star-swap and the now-unused nonPinnedGrouped grouping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
40188f85a9
commit
e532fe14bc
1 changed files with 11 additions and 31 deletions
|
|
@ -104,23 +104,18 @@ struct OfflineCacheView: View {
|
|||
}
|
||||
}
|
||||
|
||||
if !pinnedItems.isEmpty {
|
||||
Section {
|
||||
ForEach(pinnedItems) { item in
|
||||
row(for: item)
|
||||
}
|
||||
} header: {
|
||||
sectionHeader("Starred (kept from cull) · \(pinnedItems.count)")
|
||||
}
|
||||
}
|
||||
|
||||
ForEach(nonPinnedGrouped, id: \.show) { group in
|
||||
// Items stay in their own show group regardless of star
|
||||
// state — starring just toggles the star on the row (and
|
||||
// protection from cull), it doesn't relocate the file.
|
||||
ForEach(groupedFiltered, id: \.show) { group in
|
||||
Section {
|
||||
ForEach(group.items) { item in
|
||||
row(for: item)
|
||||
}
|
||||
} header: {
|
||||
sectionHeader("\(group.show) · \(group.items.count)")
|
||||
let starred = group.items.filter(isPinned).count
|
||||
sectionHeader("\(group.show) · \(group.items.count)"
|
||||
+ (starred > 0 ? " · ★\(starred)" : ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,14 +182,6 @@ struct OfflineCacheView: View {
|
|||
.sorted { $0.modifiedAt > $1.modifiedAt }
|
||||
}
|
||||
|
||||
private var nonPinnedGrouped: [(show: String, items: [OfflineCachedFile])] {
|
||||
let pinSet = Set(localPolicy.pinned.map { $0.lowercased() })
|
||||
let non = filteredItems.filter { !pinSet.contains($0.name.lowercased()) }
|
||||
let dict = Dictionary(grouping: non, by: \.showDir)
|
||||
return dict.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == .orderedAscending }
|
||||
.map { k in (k, dict[k]!.sorted { $0.modifiedAt > $1.modifiedAt }) }
|
||||
}
|
||||
|
||||
private var canPlayAll: Bool { !filteredItems.isEmpty }
|
||||
|
||||
private var localDevice: DeviceConfig? {
|
||||
|
|
@ -279,17 +266,10 @@ struct OfflineCacheView: View {
|
|||
|
||||
private func row(for item: OfflineCachedFile) -> some View {
|
||||
HStack(spacing: 10) {
|
||||
if isPinned(item) {
|
||||
Image(systemName: "star.fill")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.yellow)
|
||||
.frame(width: 20)
|
||||
} else {
|
||||
Image(systemName: "play.rectangle.on.rectangle.fill")
|
||||
.font(.body)
|
||||
.foregroundStyle(.tint)
|
||||
.frame(width: 20)
|
||||
}
|
||||
Image(systemName: "play.rectangle.on.rectangle.fill")
|
||||
.font(.body)
|
||||
.foregroundStyle(.tint)
|
||||
.frame(width: 20)
|
||||
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
Text(item.name)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue