Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
687ca8cca4
commit
3190d610f3
@ -22,104 +22,43 @@ struct ClockView: View {
|
||||
|
||||
GeometryReader { geometry in
|
||||
ZStack {
|
||||
// Time display - fills entire available space
|
||||
TimeDisplayView(
|
||||
date: viewModel.currentTime,
|
||||
use24Hour: viewModel.style.use24Hour,
|
||||
showSeconds: viewModel.style.showSeconds,
|
||||
digitColor: viewModel.style.digitColor,
|
||||
glowIntensity: viewModel.style.glowIntensity,
|
||||
manualScale: viewModel.style.digitScale,
|
||||
stretched: viewModel.style.stretched,
|
||||
showAmPmBadge: viewModel.style.showAmPmBadge,
|
||||
clockOpacity: viewModel.style.clockOpacity,
|
||||
fontFamily: viewModel.style.fontFamily,
|
||||
fontWeight: viewModel.style.fontWeight,
|
||||
fontDesign: viewModel.style.fontDesign
|
||||
// Main clock display container
|
||||
ClockDisplayContainer(
|
||||
currentTime: viewModel.currentTime,
|
||||
style: viewModel.style,
|
||||
isDisplayMode: viewModel.isDisplayMode
|
||||
)
|
||||
.transition(.opacity)
|
||||
|
||||
// Top overlay - positioned at top with safe area consideration
|
||||
VStack {
|
||||
if viewModel.style.showBattery || viewModel.style.showDate {
|
||||
TopOverlayView(
|
||||
showBattery: viewModel.style.showBattery,
|
||||
showDate: viewModel.style.showDate,
|
||||
color: viewModel.style.digitColor.opacity(UIConstants.Opacity.primary),
|
||||
opacity: viewModel.style.overlayOpacity
|
||||
)
|
||||
.padding(.top, UIConstants.Spacing.small)
|
||||
.padding(.horizontal, UIConstants.Spacing.large)
|
||||
.transition(.opacity)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
// Top overlay container
|
||||
ClockOverlayContainer(style: viewModel.style)
|
||||
}
|
||||
.scaleEffect(viewModel.isDisplayMode ? 1.0 : 0.995)
|
||||
.animation(UIConstants.AnimationCurves.smooth, value: viewModel.isDisplayMode)
|
||||
}
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: viewModel.isDisplayMode ? .bottom : [])
|
||||
.navigationTitle(viewModel.isDisplayMode ? "" : "Clock")
|
||||
.toolbar {
|
||||
if !viewModel.isDisplayMode {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
showSettings = true
|
||||
} label: {
|
||||
Image(systemName: "gear")
|
||||
.font(.title2)
|
||||
.transition(.opacity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarBackButtonHidden(viewModel.isDisplayMode)
|
||||
.toolbar(viewModel.isDisplayMode ? .hidden : .automatic)
|
||||
.statusBarHidden(viewModel.isDisplayMode)
|
||||
.onAppear {
|
||||
setTabBarHidden(viewModel.isDisplayMode, animated: false)
|
||||
}
|
||||
.onDisappear {
|
||||
setTabBarHidden(false, animated: false)
|
||||
}
|
||||
.sheet(isPresented: $showSettings) {
|
||||
ClockSettingsView(style: viewModel.style) { newStyle in
|
||||
viewModel.updateStyle(newStyle)
|
||||
}
|
||||
.presentationDetents([.medium, .large])
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.simultaneousGesture(
|
||||
LongPressGesture(minimumDuration: AppConstants.DisplayMode.longPressDuration)
|
||||
.onEnded { _ in
|
||||
viewModel.toggleDisplayMode()
|
||||
setTabBarHidden(viewModel.isDisplayMode, animated: true)
|
||||
// Status bar hiding is handled by the .statusBarHidden modifier
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Private Methods
|
||||
private func setTabBarHidden(_ hidden: Bool, animated: Bool) {
|
||||
// This will be handled by the View extension
|
||||
// For now, we'll keep the UIKit implementation
|
||||
#if canImport(UIKit)
|
||||
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||
let window = windowScene.windows.first,
|
||||
let tabBarController = window.rootViewController?.findTabBarController() else { return }
|
||||
|
||||
let tabBar = tabBarController.tabBar
|
||||
let changes = {
|
||||
tabBar.alpha = hidden ? 0 : 1
|
||||
.overlay {
|
||||
// Toolbar overlay
|
||||
ClockToolbar(
|
||||
isDisplayMode: viewModel.isDisplayMode,
|
||||
onSettingsTap: { showSettings = true }
|
||||
)
|
||||
}
|
||||
if animated {
|
||||
UIView.animate(withDuration: AppConstants.AnimationDurations.short, animations: changes)
|
||||
} else {
|
||||
changes()
|
||||
.overlay {
|
||||
// Tab bar management overlay
|
||||
ClockTabBarManager(isDisplayMode: viewModel.isDisplayMode, animated: true)
|
||||
}
|
||||
.overlay {
|
||||
// Gesture handling overlay
|
||||
ClockGestureHandler {
|
||||
viewModel.toggleDisplayMode()
|
||||
}
|
||||
}
|
||||
tabBar.isUserInteractionEnabled = !hidden
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
//
|
||||
// ClockDisplayContainer.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Container component that handles the main clock display layout and scaling
|
||||
struct ClockDisplayContainer: View {
|
||||
|
||||
// MARK: - Properties
|
||||
let currentTime: Date
|
||||
let style: ClockStyle
|
||||
let isDisplayMode: Bool
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
ZStack {
|
||||
// Time display - fills entire available space
|
||||
TimeDisplayView(
|
||||
date: currentTime,
|
||||
use24Hour: style.use24Hour,
|
||||
showSeconds: style.showSeconds,
|
||||
digitColor: style.digitColor,
|
||||
glowIntensity: style.glowIntensity,
|
||||
manualScale: style.digitScale,
|
||||
stretched: style.stretched,
|
||||
showAmPmBadge: style.showAmPmBadge,
|
||||
clockOpacity: style.clockOpacity,
|
||||
fontFamily: style.fontFamily,
|
||||
fontWeight: style.fontWeight,
|
||||
fontDesign: style.fontDesign
|
||||
)
|
||||
.transition(.opacity)
|
||||
}
|
||||
.scaleEffect(isDisplayMode ? 1.0 : 0.995)
|
||||
.animation(UIConstants.AnimationCurves.smooth, value: isDisplayMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
#Preview {
|
||||
ClockDisplayContainer(
|
||||
currentTime: Date(),
|
||||
style: ClockStyle(),
|
||||
isDisplayMode: false
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
//
|
||||
// ClockGestureHandler.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Component that handles gesture interactions for the clock view
|
||||
struct ClockGestureHandler: View {
|
||||
|
||||
// MARK: - Properties
|
||||
let onLongPress: () -> Void
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
EmptyView()
|
||||
.contentShape(Rectangle())
|
||||
.simultaneousGesture(
|
||||
LongPressGesture(minimumDuration: AppConstants.DisplayMode.longPressDuration)
|
||||
.onEnded { _ in
|
||||
onLongPress()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
#Preview {
|
||||
ClockGestureHandler(onLongPress: {})
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
//
|
||||
// ClockOverlayContainer.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Container component that handles the positioning and display of top overlays
|
||||
struct ClockOverlayContainer: View {
|
||||
|
||||
// MARK: - Properties
|
||||
let style: ClockStyle
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
VStack {
|
||||
if style.showBattery || style.showDate {
|
||||
TopOverlayView(
|
||||
showBattery: style.showBattery,
|
||||
showDate: style.showDate,
|
||||
color: style.digitColor.opacity(UIConstants.Opacity.primary),
|
||||
opacity: style.overlayOpacity
|
||||
)
|
||||
.padding(.top, UIConstants.Spacing.small)
|
||||
.padding(.horizontal, UIConstants.Spacing.large)
|
||||
.transition(.opacity)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
#Preview {
|
||||
ClockOverlayContainer(style: ClockStyle())
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
//
|
||||
// ClockTabBarManager.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Component that manages tab bar visibility for display mode
|
||||
struct ClockTabBarManager: View {
|
||||
|
||||
// MARK: - Properties
|
||||
let isDisplayMode: Bool
|
||||
let animated: Bool
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
EmptyView()
|
||||
.onAppear {
|
||||
setTabBarHidden(isDisplayMode, animated: false)
|
||||
}
|
||||
.onDisappear {
|
||||
setTabBarHidden(false, animated: false)
|
||||
}
|
||||
.onChange(of: isDisplayMode) { _, newValue in
|
||||
setTabBarHidden(newValue, animated: animated)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private Methods
|
||||
private func setTabBarHidden(_ hidden: Bool, animated: Bool) {
|
||||
#if canImport(UIKit)
|
||||
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||
let window = windowScene.windows.first,
|
||||
let tabBarController = window.rootViewController?.findTabBarController() else { return }
|
||||
|
||||
let tabBar = tabBarController.tabBar
|
||||
let changes = {
|
||||
tabBar.alpha = hidden ? 0 : 1
|
||||
}
|
||||
if animated {
|
||||
UIView.animate(withDuration: AppConstants.AnimationDurations.short, animations: changes)
|
||||
} else {
|
||||
changes()
|
||||
}
|
||||
tabBar.isUserInteractionEnabled = !hidden
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
#Preview {
|
||||
ClockTabBarManager(isDisplayMode: false, animated: false)
|
||||
}
|
||||
47
TheNoiseClock/Views/Clock/Components/ClockToolbar.swift
Normal file
47
TheNoiseClock/Views/Clock/Components/ClockToolbar.swift
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// ClockToolbar.swift
|
||||
// TheNoiseClock
|
||||
//
|
||||
// Created by Matt Bruce on 9/8/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Component that handles the clock view toolbar and navigation
|
||||
struct ClockToolbar: View {
|
||||
|
||||
// MARK: - Properties
|
||||
let isDisplayMode: Bool
|
||||
let onSettingsTap: () -> Void
|
||||
|
||||
// MARK: - Body
|
||||
var body: some View {
|
||||
EmptyView()
|
||||
.navigationTitle(isDisplayMode ? "" : "Clock")
|
||||
.toolbar {
|
||||
if !isDisplayMode {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
onSettingsTap()
|
||||
} label: {
|
||||
Image(systemName: "gear")
|
||||
.font(.title2)
|
||||
.transition(.opacity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarBackButtonHidden(isDisplayMode)
|
||||
.toolbar(isDisplayMode ? .hidden : .automatic)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
ClockToolbar(
|
||||
isDisplayMode: false,
|
||||
onSettingsTap: {}
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user