simplify: remove sub-tabs, starred, feed filter chips from Reader
Reader now shows only unread entries. Removed: - Unread/Starred/All sub-tab selector - Feed filter chip bar (categories) - All related state (selectedSubTab) and helpers Glass nav bar shows: "Reader" title + "74 unread" subtitle Trailing toolbar: grid/list toggle + ellipsis menu Auto-scroll: speed controls in leading toolbar Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,6 @@ struct ReaderTabView: View {
|
|||||||
@Bindable var vm: ReaderViewModel
|
@Bindable var vm: ReaderViewModel
|
||||||
@Binding var isAutoScrolling: Bool
|
@Binding var isAutoScrolling: Bool
|
||||||
@Binding var scrollSpeed: Double
|
@Binding var scrollSpeed: Double
|
||||||
@State private var selectedSubTab = 0
|
|
||||||
@State private var showFeedSheet = false
|
@State private var showFeedSheet = false
|
||||||
@State private var showFeedManagement = false
|
@State private var showFeedManagement = false
|
||||||
@State private var isCardView = true
|
@State private var isCardView = true
|
||||||
@@ -43,29 +42,7 @@ struct ReaderTabView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Normal mode: sub-tabs + controls
|
// Normal mode: controls
|
||||||
ToolbarItemGroup(placement: .topBarLeading) {
|
|
||||||
ForEach(Array(subTabs.enumerated()), id: \.offset) { index, tab in
|
|
||||||
Button {
|
|
||||||
withAnimation(.easeInOut(duration: 0.2)) {
|
|
||||||
selectedSubTab = index
|
|
||||||
switch index {
|
|
||||||
case 0: vm.applyFilter(.unread)
|
|
||||||
case 1: vm.applyFilter(.starred)
|
|
||||||
case 2: vm.applyFilter(.all)
|
|
||||||
default: break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
Text(tab)
|
|
||||||
.fontWeight(selectedSubTab == index ? .semibold : .regular)
|
|
||||||
}
|
|
||||||
.tint(selectedSubTab == index ? Color.accentWarm : Color.textSecondary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolbarSpacer(.fixed, placement: .topBarTrailing)
|
|
||||||
|
|
||||||
ToolbarItemGroup(placement: .topBarTrailing) {
|
ToolbarItemGroup(placement: .topBarTrailing) {
|
||||||
Button {
|
Button {
|
||||||
withAnimation(.easeInOut(duration: 0.2)) {
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
@@ -107,33 +84,6 @@ struct ReaderTabView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feed filter chips — bottom toolbar (scrolls with content)
|
|
||||||
ToolbarItem(placement: .bottomBar) {
|
|
||||||
ScrollView(.horizontal, showsIndicators: false) {
|
|
||||||
HStack(spacing: 8) {
|
|
||||||
feedFilterChip("All", isSelected: isAllSelected) {
|
|
||||||
let tab = selectedSubTab
|
|
||||||
switch tab {
|
|
||||||
case 0: vm.applyFilter(.unread)
|
|
||||||
case 1: vm.applyFilter(.starred)
|
|
||||||
case 2: vm.applyFilter(.all)
|
|
||||||
default: vm.applyFilter(.unread)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ForEach(vm.feeds) { feed in
|
|
||||||
let count = vm.counters?.count(forFeed: feed.id) ?? 0
|
|
||||||
feedFilterChip(
|
|
||||||
feed.title,
|
|
||||||
count: selectedSubTab == 0 ? count : nil,
|
|
||||||
isSelected: vm.currentFilter == .feed(feed.id)
|
|
||||||
) {
|
|
||||||
vm.applyFilter(.feed(feed.id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $showFeedSheet) {
|
.sheet(isPresented: $showFeedSheet) {
|
||||||
AddFeedSheet(vm: vm)
|
AddFeedSheet(vm: vm)
|
||||||
@@ -145,46 +95,8 @@ struct ReaderTabView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
ArticleRenderer.shared.reWarmIfNeeded()
|
ArticleRenderer.shared.reWarmIfNeeded()
|
||||||
}
|
}
|
||||||
.onChange(of: selectedSubTab) { _, _ in
|
|
||||||
isAutoScrolling = false
|
|
||||||
}
|
|
||||||
.onChange(of: vm.currentFilter) { _, _ in
|
.onChange(of: vm.currentFilter) { _, _ in
|
||||||
isAutoScrolling = false
|
isAutoScrolling = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Helpers
|
|
||||||
|
|
||||||
private var subTabs: [String] { ["Unread", "Starred", "All"] }
|
|
||||||
|
|
||||||
private var isAllSelected: Bool {
|
|
||||||
switch vm.currentFilter {
|
|
||||||
case .unread, .starred, .all: return true
|
|
||||||
default: return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func feedFilterChip(
|
|
||||||
_ title: String,
|
|
||||||
count: Int? = nil,
|
|
||||||
isSelected: Bool,
|
|
||||||
action: @escaping () -> Void
|
|
||||||
) -> some View {
|
|
||||||
Button(action: action) {
|
|
||||||
HStack(spacing: 4) {
|
|
||||||
Text(title)
|
|
||||||
.font(.caption.weight(isSelected ? .semibold : .regular))
|
|
||||||
.lineLimit(1)
|
|
||||||
if let count, count > 0 {
|
|
||||||
Text("\(count)")
|
|
||||||
.font(.system(size: 10).weight(.bold))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.foregroundStyle(isSelected ? Color.accentWarm : Color.textSecondary)
|
|
||||||
.padding(.horizontal, 12)
|
|
||||||
.padding(.vertical, 6)
|
|
||||||
.background(isSelected ? Color.accentWarm.opacity(0.12) : Color.surfaceCard)
|
|
||||||
.clipShape(Capsule())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user