fix: Reader pre-loads on app launch, no more glitchy initial state
- ReaderViewModel starts with isLoading=true (shows spinner, not "No articles") - MainTabView owns ReaderViewModel and pre-fetches in background on launch - Sub-tabs and feed chips hidden during initial load (no tiny squished layout) - VStack fills full screen with frame(maxWidth/maxHeight: .infinity) - WebKit warmer triggers when Reader tab appears - By the time user taps Reader, data is already loaded Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ struct MainTabView: View {
|
||||
@State private var selectedTab = 0
|
||||
@State private var showAssistant = false
|
||||
@State private var confettiTrigger = 0
|
||||
@State private var readerVM = ReaderViewModel()
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
@@ -38,12 +39,16 @@ struct MainTabView: View {
|
||||
.tabItem { Label("Fitness", systemImage: "flame.fill") }
|
||||
.tag(1)
|
||||
|
||||
ReaderTabView()
|
||||
ReaderTabView(vm: readerVM)
|
||||
.tabItem { Label("Reader", systemImage: "newspaper.fill") }
|
||||
.tag(2)
|
||||
}
|
||||
.tint(Color.accentWarm)
|
||||
.modifier(TabBarMinimizeModifier())
|
||||
.task {
|
||||
// Pre-fetch reader data in background while user is on Home/Fitness
|
||||
await readerVM.loadInitial()
|
||||
}
|
||||
|
||||
// Floating buttons
|
||||
VStack {
|
||||
|
||||
@@ -10,7 +10,7 @@ final class ReaderViewModel {
|
||||
var categories: [ReaderCategory] = []
|
||||
var counters: ReaderCounters?
|
||||
var total = 0
|
||||
var isLoading = false
|
||||
var isLoading = true
|
||||
var isLoadingMore = false
|
||||
var isRefreshing = false
|
||||
var error: String?
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ReaderTabView: View {
|
||||
@State private var vm = ReaderViewModel()
|
||||
@Bindable var vm: ReaderViewModel
|
||||
@State private var selectedSubTab = 0
|
||||
@State private var showFeedSheet = false
|
||||
@State private var showFeedManagement = false
|
||||
@@ -10,7 +10,8 @@ struct ReaderTabView: View {
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack(spacing: 0) {
|
||||
// Sub-tab selector
|
||||
if !vm.isLoading || !vm.entries.isEmpty {
|
||||
// Sub-tab selector — only show after initial load
|
||||
HStack(spacing: 0) {
|
||||
ForEach(Array(subTabs.enumerated()), id: \.offset) { index, tab in
|
||||
Button {
|
||||
@@ -54,6 +55,7 @@ struct ReaderTabView: View {
|
||||
.padding(.top, 8)
|
||||
|
||||
// Feed filter bar
|
||||
if !vm.feeds.isEmpty {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
feedFilterChip("All", isSelected: isAllSelected) {
|
||||
@@ -80,10 +82,13 @@ struct ReaderTabView: View {
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Entry list
|
||||
// Entry list (shows LoadingView when isLoading)
|
||||
EntryListView(vm: vm, isCardView: isCardView)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background(Color.canvas)
|
||||
.navigationBarHidden(true)
|
||||
.toolbar {
|
||||
@@ -137,9 +142,8 @@ struct ReaderTabView: View {
|
||||
FeedManagementSheet(vm: vm)
|
||||
}
|
||||
}
|
||||
.task {
|
||||
.onAppear {
|
||||
WebKitWarmer.shared.warmUp()
|
||||
await vm.loadInitial()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user