feat(ios): TabBar 显示/隐藏增加入场出场动画
- TabBarState ObservableObject 管理可见性 - ContentView 用 .toolbar(hidden)+animation 驱动动画 - 子页面 hideTabBarWithAnimation() 替代静态 toolbar hidden - 0.28s easeInOut 淡入淡出 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
7f252b48f0
commit
f6df01d9ca
@ -1,7 +1,40 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
// MARK: - TabBar visibility state
|
||||||
|
|
||||||
|
class TabBarState: ObservableObject {
|
||||||
|
@Published var isHidden = false
|
||||||
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
func hideTabBarWithAnimation() -> some View {
|
||||||
|
modifier(HideTabBarModifier())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HideTabBarModifier: ViewModifier {
|
||||||
|
@EnvironmentObject private var tabBarState: TabBarState
|
||||||
|
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.onAppear {
|
||||||
|
withAnimation(.easeInOut(duration: 0.28)) {
|
||||||
|
tabBarState.isHidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
withAnimation(.easeInOut(duration: 0.28)) {
|
||||||
|
tabBarState.isHidden = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - ContentView
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@State private var selectedTab = "study"
|
@State private var selectedTab = "study"
|
||||||
|
@StateObject private var tabBarState = TabBarState()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TabView(selection: $selectedTab) {
|
TabView(selection: $selectedTab) {
|
||||||
@ -41,7 +74,10 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
.tag("profile")
|
.tag("profile")
|
||||||
}
|
}
|
||||||
|
.environmentObject(tabBarState)
|
||||||
.tint(Color.zxPrimary)
|
.tint(Color.zxPrimary)
|
||||||
|
.toolbar(tabBarState.isHidden ? .hidden : .visible, for: .tabBar)
|
||||||
|
.animation(.easeInOut(duration: 0.28), value: tabBarState.isHidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@ struct AIChatPage: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .topBarTrailing) {
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
|
|||||||
@ -101,7 +101,7 @@ struct AIFeedbackPageView: View {
|
|||||||
.transition(.opacity.combined(with: .scale(scale: 0.95)))
|
.transition(.opacity.combined(with: .scale(scale: 0.95)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ struct ActiveRecallView: View {
|
|||||||
.scrollIndicators(.hidden)
|
.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.task { await viewModel.loadQuestions() }
|
.task { await viewModel.loadQuestions() }
|
||||||
.overlay {
|
.overlay {
|
||||||
|
|||||||
@ -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))}
|
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() }
|
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)
|
}.padding(.horizontal,20).padding(.top, 8).padding(.bottom,120) }.scrollIndicators(.hidden)
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden,for:.navigationBar)
|
}.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden,for:.navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ struct RecallTestPage: View {
|
|||||||
}
|
}
|
||||||
.scrollIndicators(.hidden)
|
.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ struct WeakPointsPage: View {
|
|||||||
}
|
}
|
||||||
.scrollIndicators(.hidden)
|
.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -133,6 +133,6 @@ struct LibrarySearchView: View {
|
|||||||
}
|
}
|
||||||
}.padding(.horizontal, 20) }.scrollIndicators(.hidden)
|
}.padding(.horizontal, 20) }.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
}.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,7 +72,7 @@ struct CreateLibraryPage: View {
|
|||||||
}
|
}
|
||||||
.disabled(isCreating || name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || desc.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
.disabled(isCreating || name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || desc.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
||||||
}.padding(.horizontal, 20).padding(.top, 20) }.scrollIndicators(.hidden) }
|
}.padding(.horizontal, 20).padding(.top, 20) }.scrollIndicators(.hidden) }
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)
|
}.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()
|
||||||
.photosPicker(isPresented: $showCoverPicker, selection: $coverPhotoItem, matching: .images)
|
.photosPicker(isPresented: $showCoverPicker, selection: $coverPhotoItem, matching: .images)
|
||||||
.onChange(of: coverPhotoItem) { _, item in
|
.onChange(of: coverPhotoItem) { _, item in
|
||||||
guard let item else { return }
|
guard let item else { return }
|
||||||
@ -238,7 +238,7 @@ struct LibraryDetailPage: View {
|
|||||||
.zxPullToRefresh { await viewModel.refresh(knowledgeBaseId: knowledgeBaseId) }
|
.zxPullToRefresh { await viewModel.refresh(knowledgeBaseId: knowledgeBaseId) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()
|
||||||
.onChange(of: detailTab) { _, newTab in
|
.onChange(of: detailTab) { _, newTab in
|
||||||
if newTab == 1 && sources.isEmpty { Task { await loadSources() } }
|
if newTab == 1 && sources.isEmpty { Task { await loadSources() } }
|
||||||
}
|
}
|
||||||
@ -455,7 +455,7 @@ struct AddKnowledgePage: View {
|
|||||||
.disabled(!canSave || isSaving)
|
.disabled(!canSave || isSaving)
|
||||||
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) }
|
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) }
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()
|
||||||
.fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.plainText, .pdf, .image], allowsMultipleSelection: true) { result in
|
.fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.plainText, .pdf, .image], allowsMultipleSelection: true) { result in
|
||||||
if case .success(let urls) = result { handleFiles(urls) }
|
if case .success(let urls) = result { handleFiles(urls) }
|
||||||
}
|
}
|
||||||
@ -643,7 +643,7 @@ struct KnowledgeDetailPage: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.padding(.horizontal, 20).padding(.bottom, 80) }.scrollIndicators(.hidden) }
|
}.padding(.horizontal, 20).padding(.bottom, 80) }.scrollIndicators(.hidden) }
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)}
|
}.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()}
|
||||||
}
|
}
|
||||||
struct ZXChip: View { let text: String; let color: Color
|
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()) }
|
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) }
|
}.padding(.horizontal, 20).padding(.top, 8) }.scrollIndicators(.hidden) }
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()
|
||||||
.disabled(isImporting)
|
.disabled(isImporting)
|
||||||
.task { do { let kbs = try await KnowledgeBaseService.shared.list(page: 1, limit: 1); kbId = kbs.first?.id } catch {} }
|
.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
|
.fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.pdf, .plainText], allowsMultipleSelection: true) { result in
|
||||||
@ -851,7 +851,7 @@ struct ImportReviewPage: View {
|
|||||||
.scrollIndicators(.hidden)
|
.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
.navigationTitle("候选审批").navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)
|
.navigationTitle("候选审批").navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()
|
||||||
.disabled(isProcessing)
|
.disabled(isProcessing)
|
||||||
.task { await load() }
|
.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) }
|
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)) }
|
} 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) }
|
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80) }.scrollIndicators(.hidden) }
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).toolbar(.hidden, for: .tabBar)
|
}.navigationBarTitleDisplayMode(.inline).toolbarBackground(.hidden, for: .navigationBar).hideTabBarWithAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,7 +142,7 @@ struct EditProfilePage: View {
|
|||||||
}
|
}
|
||||||
.navigationTitle("编辑资料")
|
.navigationTitle("编辑资料")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.toolbar(.hidden, for: .tabBar)
|
.hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.photosPicker(isPresented: $showPhotoPicker, selection: $selectedPhotoItem, matching: .images)
|
.photosPicker(isPresented: $showPhotoPicker, selection: $selectedPhotoItem, matching: .images)
|
||||||
.onChange(of: selectedPhotoItem) { _, item in
|
.onChange(of: selectedPhotoItem) { _, item in
|
||||||
|
|||||||
@ -39,6 +39,6 @@ struct FeedbackFormView: View {
|
|||||||
.disabled(isSubmitting)
|
.disabled(isSubmitting)
|
||||||
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
||||||
}.scrollIndicators(.hidden)
|
}.scrollIndicators(.hidden)
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
}.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,6 @@ struct GoalSettingDetailView: View {
|
|||||||
.disabled(isSaving)
|
.disabled(isSaving)
|
||||||
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
||||||
}.scrollIndicators(.hidden)
|
}.scrollIndicators(.hidden)
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
}.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,6 @@ struct MethodPreferenceView: View {
|
|||||||
.disabled(isSaving)
|
.disabled(isSaving)
|
||||||
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
}.padding(.horizontal, 20).padding(.top, 8).padding(.bottom, 80)
|
||||||
}.scrollIndicators(.hidden)
|
}.scrollIndicators(.hidden)
|
||||||
}.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
}.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ struct NotificationListView: View {
|
|||||||
.zxPullToRefresh { await refresh() }
|
.zxPullToRefresh { await refresh() }
|
||||||
}
|
}
|
||||||
.navigationTitle("消息中心")
|
.navigationTitle("消息中心")
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .topBarTrailing) {
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
|
|||||||
@ -115,7 +115,7 @@ struct SettingsView: View {
|
|||||||
notificationEnabled = p.notificationEnabled ?? true
|
notificationEnabled = p.notificationEnabled ?? true
|
||||||
reviewReminder = notificationEnabled
|
reviewReminder = notificationEnabled
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sectionHeader(_ text: String) -> some View {
|
private func sectionHeader(_ text: String) -> some View {
|
||||||
|
|||||||
@ -51,7 +51,7 @@ struct QuizListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("测验").navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
.navigationTitle("测验").navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.task { await load() }
|
.task { await load() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ struct QuizTakerView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.task { await load() }
|
.task { await load() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ struct QuizResultView: View {
|
|||||||
}.scrollIndicators(.hidden)
|
}.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar).toolbarBackground(.hidden, for: .navigationBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation().toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.task { await load() }
|
.task { await load() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,7 @@ struct LearningSessionView: View {
|
|||||||
bottomBar
|
bottomBar
|
||||||
}.ignoresSafeArea(edges: .bottom)
|
}.ignoresSafeArea(edges: .bottom)
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.onReceive(timer) { _ in
|
.onReceive(timer) { _ in
|
||||||
if isRunning { elapsed += 1 }
|
if isRunning { elapsed += 1 }
|
||||||
|
|||||||
@ -40,7 +40,7 @@ struct ReviewCardView: View {
|
|||||||
.scrollIndicators(.hidden)
|
.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationBarTitleDisplayMode(.inline).toolbar(.hidden, for: .tabBar)
|
.navigationBarTitleDisplayMode(.inline).hideTabBarWithAnimation()
|
||||||
.toolbarBackground(.hidden, for: .navigationBar)
|
.toolbarBackground(.hidden, for: .navigationBar)
|
||||||
.task { await viewModel.loadDueCards() }
|
.task { await viewModel.loadDueCards() }
|
||||||
.overlay {
|
.overlay {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user