diff --git a/AIStudyApp/AIStudyApp/ContentView.swift b/AIStudyApp/AIStudyApp/ContentView.swift index 9b339a2..6324362 100644 --- a/AIStudyApp/AIStudyApp/ContentView.swift +++ b/AIStudyApp/AIStudyApp/ContentView.swift @@ -1,48 +1,7 @@ import SwiftUI -// MARK: - TabBar hide animation key - -struct TabBarVisibleKey: EnvironmentKey { - static let defaultValue: Binding = .constant(false) -} - -extension EnvironmentValues { - var isTabBarHidden: Binding { - get { self[TabBarVisibleKey.self] } - set { self[TabBarVisibleKey.self] = newValue } - } -} - -/// 子页面添加此 modifier 即可获得带动画的 TabBar 隐藏/出现效果 -struct AnimatedTabBarHide: ViewModifier { - @Environment(\.isTabBarHidden) private var isTabBarHidden - - func body(content: Content) -> some View { - content - .onAppear { - withAnimation(.easeInOut(duration: 0.28)) { - isTabBarHidden.wrappedValue = true - } - } - .onDisappear { - withAnimation(.easeInOut(duration: 0.28)) { - isTabBarHidden.wrappedValue = false - } - } - } -} - -extension View { - func animatedTabBarHide() -> some View { - modifier(AnimatedTabBarHide()) - } -} - -// MARK: - ContentView - struct ContentView: View { @State private var selectedTab = "study" - @State private var tabBarHidden = false var body: some View { TabView(selection: $selectedTab) { @@ -83,9 +42,6 @@ struct ContentView: View { .tag("profile") } .tint(Color.zxPrimary) - .toolbar(tabBarHidden ? .hidden : .visible, for: .tabBar) - .animation(.easeInOut(duration: 0.28), value: tabBarHidden) - .environment(\.isTabBarHidden, $tabBarHidden) } } diff --git a/AIStudyApp/AIStudyApp/Features/AI/AIChatPage.swift b/AIStudyApp/AIStudyApp/Features/AI/AIChatPage.swift index ce78956..1c08afe 100644 --- a/AIStudyApp/AIStudyApp/Features/AI/AIChatPage.swift +++ b/AIStudyApp/AIStudyApp/Features/AI/AIChatPage.swift @@ -68,7 +68,7 @@ struct AIChatPage: View { } } } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) .toolbar { ToolbarItem(placement: .topBarTrailing) { diff --git a/AIStudyApp/AIStudyApp/Features/AI/AIFeedbackPageView.swift b/AIStudyApp/AIStudyApp/Features/AI/AIFeedbackPageView.swift index f9cf580..1c675ce 100644 --- a/AIStudyApp/AIStudyApp/Features/AI/AIFeedbackPageView.swift +++ b/AIStudyApp/AIStudyApp/Features/AI/AIFeedbackPageView.swift @@ -101,7 +101,7 @@ struct AIFeedbackPageView: View { .transition(.opacity.combined(with: .scale(scale: 0.95))) } } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/AI/ActiveRecallView.swift b/AIStudyApp/AIStudyApp/Features/AI/ActiveRecallView.swift index 3ffd719..749e553 100644 --- a/AIStudyApp/AIStudyApp/Features/AI/ActiveRecallView.swift +++ b/AIStudyApp/AIStudyApp/Features/AI/ActiveRecallView.swift @@ -39,7 +39,7 @@ struct ActiveRecallView: View { .scrollIndicators(.hidden) } } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) .task { await viewModel.loadQuestions() } .overlay { diff --git a/AIStudyApp/AIStudyApp/Features/AI/DailyThinkingPage.swift b/AIStudyApp/AIStudyApp/Features/AI/DailyThinkingPage.swift index 8a2c219..d5a1b0c 100644 --- a/AIStudyApp/AIStudyApp/Features/AI/DailyThinkingPage.swift +++ b/AIStudyApp/AIStudyApp/Features/AI/DailyThinkingPage.swift @@ -12,6 +12,6 @@ struct DailyThinkingPage: View { VStack(alignment:.leading,spacing:8){Text("你的回答").font(.system(size:13,weight:.semibold)).foregroundColor(Color.zxF04);TextEditor(text:$answer).zxFontScaled(size:13).foregroundColor(Color.zxF0).tint(Color.zxPurple).frame(minHeight:160).scrollContentBackground(.hidden).padding(12).background(Color.zxFill004).clipShape(RoundedRectangle(cornerRadius:14)).overlay(RoundedRectangle(cornerRadius:14).stroke(Color.zxBorder008,lineWidth:1))} if !submitted{ NavigationLink(value: Route.aiFeedback){ Text("提交回答,获取 AI 反馈").font(.system(size:14,weight:.bold)).foregroundColor(.white).frame(maxWidth:.infinity).frame(height:52).background(ZXGradient.ctaPurple).clipShape(RoundedRectangle(cornerRadius:16)).shadow(color:Color(hex:"#7C6EFA",opacity:0.3),radius:24) }.zxPressable() } }.padding(.horizontal,20).padding(.top, 8).padding(.bottom,120) }.scrollIndicators(.hidden) - }.navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden,for:.navigationBar) + }.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden,for:.navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/AI/RecallTestPage.swift b/AIStudyApp/AIStudyApp/Features/AI/RecallTestPage.swift index 1a666fe..f07e52e 100644 --- a/AIStudyApp/AIStudyApp/Features/AI/RecallTestPage.swift +++ b/AIStudyApp/AIStudyApp/Features/AI/RecallTestPage.swift @@ -32,7 +32,7 @@ struct RecallTestPage: View { } .scrollIndicators(.hidden) } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/AI/WeakPointsPage.swift b/AIStudyApp/AIStudyApp/Features/AI/WeakPointsPage.swift index ae799b3..8d147ed 100644 --- a/AIStudyApp/AIStudyApp/Features/AI/WeakPointsPage.swift +++ b/AIStudyApp/AIStudyApp/Features/AI/WeakPointsPage.swift @@ -16,7 +16,7 @@ struct WeakPointsPage: View { } .scrollIndicators(.hidden) } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/Library/LibraryHomeView.swift b/AIStudyApp/AIStudyApp/Features/Library/LibraryHomeView.swift index ae5fc9c..dbb167a 100644 --- a/AIStudyApp/AIStudyApp/Features/Library/LibraryHomeView.swift +++ b/AIStudyApp/AIStudyApp/Features/Library/LibraryHomeView.swift @@ -133,6 +133,6 @@ struct LibrarySearchView: View { } }.padding(.horizontal, 20) }.scrollIndicators(.hidden) } - }.navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + }.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift b/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift index cbe8225..8622a88 100644 --- a/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift +++ b/AIStudyApp/AIStudyApp/Features/Library/LibrarySubpages.swift @@ -72,7 +72,7 @@ struct CreateLibraryPage: View { } .disabled(isCreating || name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || desc.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) }.padding(.horizontal, 20).padding(.top, 20) }.scrollIndicators(.hidden) } - }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide() + }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) .photosPicker(isPresented: $showCoverPicker, selection: $coverPhotoItem, matching: .images) .onChange(of: coverPhotoItem) { _, item in guard let item else { return } @@ -238,7 +238,7 @@ struct LibraryDetailPage: View { .zxPullToRefresh { await viewModel.refresh(knowledgeBaseId: knowledgeBaseId) } } } - .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) .onChange(of: detailTab) { _, newTab in if newTab == 1 && sources.isEmpty { Task { await loadSources() } } } @@ -455,7 +455,7 @@ struct AddKnowledgePage: View { .disabled(!canSave || isSaving) }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) } } - .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) .fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.plainText, .pdf, .image], allowsMultipleSelection: true) { result in if case .success(let urls) = result { handleFiles(urls) } } @@ -643,7 +643,7 @@ struct KnowledgeDetailPage: View { } } }.padding(.horizontal, 20).padding(.bottom, 80) }.scrollIndicators(.hidden) } - }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide()} + }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)} } struct ZXChip: View { let text: String; let color: Color var body: some View { Text(text).font(.system(size: 10, weight: .semibold)).foregroundColor(color).padding(.horizontal, 8).padding(.vertical, 2).background(color.opacity(0.12)).clipShape(Capsule()) } @@ -683,7 +683,7 @@ struct ImportPage: View { } }.padding(.horizontal, 20).padding(.top, 8) }.scrollIndicators(.hidden) } } - .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) .disabled(isImporting) .task { do { let kbs = try await KnowledgeBaseService.shared.list(page: 1, limit: 1); kbId = kbs.first?.id } catch {} } .fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.pdf, .plainText], allowsMultipleSelection: true) { result in @@ -851,7 +851,7 @@ struct ImportReviewPage: View { .scrollIndicators(.hidden) } }} - .navigationTitle("候选审批").navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide() + .navigationTitle("候选审批").navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) .disabled(isProcessing) .task { await load() } } @@ -911,6 +911,6 @@ struct EditKnowledgePage: View { Task { _ = try? await KnowledgeItemService.shared.update(id: item.id, title: title, content: content, summary: nil) } } label: { Text("保存修改").font(.system(size: 14, weight: .bold)).foregroundColor(.white).frame(maxWidth: .infinity).frame(height: 52).background(ZXGradient.ctaPurple).clipShape(RoundedRectangle(cornerRadius: 16)) } }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) } - }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).animatedTabBarHide() + }.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/Profile/EditProfilePage.swift b/AIStudyApp/AIStudyApp/Features/Profile/EditProfilePage.swift index d4356a6..add11aa 100644 --- a/AIStudyApp/AIStudyApp/Features/Profile/EditProfilePage.swift +++ b/AIStudyApp/AIStudyApp/Features/Profile/EditProfilePage.swift @@ -142,7 +142,7 @@ struct EditProfilePage: View { } .navigationTitle("编辑资料") .navigationBarTitleDisplayMode(.inline) - .animatedTabBarHide() + .toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) .photosPicker(isPresented: $showPhotoPicker, selection: $selectedPhotoItem, matching: .images) .onChange(of: selectedPhotoItem) { _, item in diff --git a/AIStudyApp/AIStudyApp/Features/Profile/FeedbackFormView.swift b/AIStudyApp/AIStudyApp/Features/Profile/FeedbackFormView.swift index 6ceb413..0b4b1a8 100644 --- a/AIStudyApp/AIStudyApp/Features/Profile/FeedbackFormView.swift +++ b/AIStudyApp/AIStudyApp/Features/Profile/FeedbackFormView.swift @@ -39,6 +39,6 @@ struct FeedbackFormView: View { .disabled(isSubmitting) }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) - }.navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + }.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/Profile/GoalSettingDetailView.swift b/AIStudyApp/AIStudyApp/Features/Profile/GoalSettingDetailView.swift index e7f8930..41f4df1 100644 --- a/AIStudyApp/AIStudyApp/Features/Profile/GoalSettingDetailView.swift +++ b/AIStudyApp/AIStudyApp/Features/Profile/GoalSettingDetailView.swift @@ -49,6 +49,6 @@ struct GoalSettingDetailView: View { .disabled(isSaving) }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) - }.navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + }.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/Profile/MethodPreferenceView.swift b/AIStudyApp/AIStudyApp/Features/Profile/MethodPreferenceView.swift index 003f4a9..0856be9 100644 --- a/AIStudyApp/AIStudyApp/Features/Profile/MethodPreferenceView.swift +++ b/AIStudyApp/AIStudyApp/Features/Profile/MethodPreferenceView.swift @@ -46,6 +46,6 @@ struct MethodPreferenceView: View { .disabled(isSaving) }.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) - }.navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + }.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) } } diff --git a/AIStudyApp/AIStudyApp/Features/Profile/NotificationListView.swift b/AIStudyApp/AIStudyApp/Features/Profile/NotificationListView.swift index b3faa67..f61b9ac 100644 --- a/AIStudyApp/AIStudyApp/Features/Profile/NotificationListView.swift +++ b/AIStudyApp/AIStudyApp/Features/Profile/NotificationListView.swift @@ -35,7 +35,7 @@ struct NotificationListView: View { .zxPullToRefresh { await refresh() } } .navigationTitle("消息中心") - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) .toolbar { ToolbarItem(placement: .topBarTrailing) { diff --git a/AIStudyApp/AIStudyApp/Features/Profile/SettingsView.swift b/AIStudyApp/AIStudyApp/Features/Profile/SettingsView.swift index 15e89ac..e3838b3 100644 --- a/AIStudyApp/AIStudyApp/Features/Profile/SettingsView.swift +++ b/AIStudyApp/AIStudyApp/Features/Profile/SettingsView.swift @@ -115,7 +115,7 @@ struct SettingsView: View { notificationEnabled = p.notificationEnabled ?? true reviewReminder = notificationEnabled } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) } private func sectionHeader(_ text: String) -> some View { diff --git a/AIStudyApp/AIStudyApp/Features/Quiz/QuizViews.swift b/AIStudyApp/AIStudyApp/Features/Quiz/QuizViews.swift index c9adcbd..f2b0573 100644 --- a/AIStudyApp/AIStudyApp/Features/Quiz/QuizViews.swift +++ b/AIStudyApp/AIStudyApp/Features/Quiz/QuizViews.swift @@ -51,7 +51,7 @@ struct QuizListView: View { } } } - .navigationTitle("测验").navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + .navigationTitle("测验").navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) .task { await load() } } @@ -164,7 +164,7 @@ struct QuizTakerView: View { } } } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) .task { await load() } } @@ -230,7 +230,7 @@ struct QuizResultView: View { }.scrollIndicators(.hidden) } } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide().toolbarBackground(.hidden, for: .navigationBar) + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar) .task { await load() } } diff --git a/AIStudyApp/AIStudyApp/Features/Study/LearningSessionView.swift b/AIStudyApp/AIStudyApp/Features/Study/LearningSessionView.swift index a17aabe..95f199a 100644 --- a/AIStudyApp/AIStudyApp/Features/Study/LearningSessionView.swift +++ b/AIStudyApp/AIStudyApp/Features/Study/LearningSessionView.swift @@ -36,7 +36,7 @@ struct LearningSessionView: View { bottomBar }.ignoresSafeArea(edges: .bottom) } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) .onReceive(timer) { _ in if isRunning { elapsed += 1 } diff --git a/AIStudyApp/AIStudyApp/Features/Study/ReviewCardView.swift b/AIStudyApp/AIStudyApp/Features/Study/ReviewCardView.swift index 450fe3a..8042831 100644 --- a/AIStudyApp/AIStudyApp/Features/Study/ReviewCardView.swift +++ b/AIStudyApp/AIStudyApp/Features/Study/ReviewCardView.swift @@ -40,7 +40,7 @@ struct ReviewCardView: View { .scrollIndicators(.hidden) } } - .navigationBarTitleDisplayMode(.inline).animatedTabBarHide() + .navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar) .toolbarBackground(.hidden, for: .navigationBar) .task { await viewModel.loadDueCards() } .overlay {