Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2026-01-31 12:01:12 -06:00
parent 7bd01554de
commit a88a02b671
2 changed files with 54 additions and 34 deletions

View File

@ -14,6 +14,8 @@ struct ClockView: View {
// MARK: - Properties
@Bindable var viewModel: ClockViewModel
@State private var showFullScreenHint = false
@State private var idleTimer: Timer?
@State private var didHandleTouch = false
// MARK: - Body
var body: some View {
@ -45,32 +47,66 @@ struct ClockView: View {
.overlay {
// Toolbar overlay
ClockToolbar(
isDisplayMode: viewModel.isDisplayMode,
onFullScreenTap: {
if !viewModel.isDisplayMode {
viewModel.toggleDisplayMode()
// Show hint after a brief delay to allow transition
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
showFullScreenHint = true
}
} else {
viewModel.toggleDisplayMode()
}
}
isDisplayMode: viewModel.isDisplayMode
)
}
.overlay {
// Tab bar management overlay
ClockTabBarManager(isDisplayMode: viewModel.isDisplayMode)
}
.overlay {
// Gesture handling overlay
ClockGestureHandler {
viewModel.toggleDisplayMode()
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
guard !didHandleTouch else { return }
didHandleTouch = true
handleUserInteraction()
}
.onEnded { _ in
didHandleTouch = false
}
)
.onAppear {
resetIdleTimer()
}
.onDisappear {
idleTimer?.invalidate()
idleTimer = nil
}
.onChange(of: viewModel.isDisplayMode) { _, isDisplayMode in
if isDisplayMode {
idleTimer?.invalidate()
idleTimer = nil
} else {
resetIdleTimer()
}
}
}
// MARK: - Idle Timer
private func resetIdleTimer() {
idleTimer?.invalidate()
idleTimer = nil
guard !viewModel.isDisplayMode else { return }
idleTimer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { _ in
enterDisplayModeFromIdle()
}
}
private func enterDisplayModeFromIdle() {
guard !viewModel.isDisplayMode else { return }
viewModel.toggleDisplayMode()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
showFullScreenHint = true
}
}
private func handleUserInteraction() {
if viewModel.isDisplayMode {
viewModel.toggleDisplayMode()
showFullScreenHint = false
}
resetIdleTimer()
}
}
// MARK: - Preview

View File

@ -12,26 +12,11 @@ struct ClockToolbar: View {
// MARK: - Properties
let isDisplayMode: Bool
let onFullScreenTap: () -> Void
// MARK: - Body
var body: some View {
EmptyView()
.navigationTitle(isDisplayMode ? "" : "Clock")
.toolbar {
if !isDisplayMode {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
onFullScreenTap()
} label: {
Image(systemName: "rectangle.expand.diagonal")
.font(.title2)
.transition(.opacity)
}
.accessibilityLabel("Enter Full Screen Mode")
}
}
}
.navigationBarBackButtonHidden(isDisplayMode)
.toolbar(isDisplayMode ? .hidden : .automatic)
}
@ -41,8 +26,7 @@ struct ClockToolbar: View {
#Preview {
NavigationStack {
ClockToolbar(
isDisplayMode: false,
onFullScreenTap: {}
isDisplayMode: false
)
}
}