User now can select clock position

This commit is contained in:
2025-03-01 21:49:02 +11:00
parent 16f479b756
commit becdccbe7f
5 changed files with 197 additions and 19 deletions
+4 -4
View File
@@ -396,7 +396,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"image-flow/Preview Content\"";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = AQ879ZQMD2;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
@@ -407,7 +407,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 18.3;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -433,7 +433,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"image-flow/Preview Content\"";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = AQ879ZQMD2;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "";
@@ -444,7 +444,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 18.3;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
+2 -1
View File
@@ -6,9 +6,10 @@
//
import SwiftUI
// ClockStyle is defined in ClockStyle.swift
struct ClockPreviewView: View {
let clockStyle: ClockStyle
let clockStyle: ClockStyle // Using ClockStyle from ClockStyle.swift
@State private var currentTime = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
+30
View File
@@ -0,0 +1,30 @@
//
// ClockStyle.swift
// image-flow
//
// Created by Junv on 1/3/2025.
//
import Foundation
enum ClockStyle: String, CaseIterable {
case digital
case analog
case minimal
var displayName: String {
switch self {
case .digital: return "Digital"
case .analog: return "Analog"
case .minimal: return "Minimal"
}
}
var icon: String {
switch self {
case .digital: return "clock"
case .analog: return "clock.circle"
case .minimal: return "clock.badge"
}
}
}
+97 -8
View File
@@ -7,13 +7,15 @@
import SwiftUI
import PhotosUI
// ClockStyle is defined in the same module, no need for import
struct ContentView: View {
@StateObject private var photoManager = PhotoPickerManager()
@State private var clockStyle: ClockStyle = .digital
@State private var isFullscreen = false
@State private var currentImageIndex = 0
@State private var transitionAnimation: TransitionAnimation = .fade
@State private var clockStyle: ClockStyle = .digital
@State private var clockPosition: ClockPosition = .center
@State private var showingPermissionAlert = false
let timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect()
@@ -23,6 +25,7 @@ struct ContentView: View {
SlideshowView(
images: photoManager.selectedImages,
clockStyle: clockStyle,
clockPosition: clockPosition,
currentIndex: $currentImageIndex,
animation: transitionAnimation
)
@@ -95,7 +98,15 @@ struct ContentView: View {
}
.pickerStyle(.segmented)
// Preview of selected clock style
ClockPreviewView(clockStyle: clockStyle)
.frame(height: 100)
.padding(.vertical, 8)
}
Section("Clock Position") {
ClockPositionGrid(selectedPosition: $clockPosition)
.frame(height: 280)
.padding(.vertical, 8)
}
@@ -187,16 +198,42 @@ struct ContentView: View {
}
}
enum ClockStyle: String, CaseIterable {
case digital
case analog
case minimal
enum ClockPosition: String, CaseIterable {
case topCenter
case topLeft
case topRight
case centerLeft
case center
case centerRight
case bottomCenter
case bottomLeft
case bottomRight
var displayName: String {
switch self {
case .digital: return "Digital"
case .analog: return "Analog"
case .minimal: return "Minimal"
case .topCenter: return "Top"
case .topLeft: return "Top Left"
case .topRight: return "Top Right"
case .centerLeft: return "Left"
case .center: return "Center"
case .centerRight: return "Right"
case .bottomCenter: return "Bottom"
case .bottomLeft: return "Bottom Left"
case .bottomRight: return "Bottom Right"
}
}
var icon: String {
switch self {
case .topCenter: return "arrow.up.to.line"
case .topLeft: return "arrow.up.left.to.line"
case .topRight: return "arrow.up.right.to.line"
case .centerLeft: return "arrow.left.to.line"
case .center: return "plus"
case .centerRight: return "arrow.right.to.line"
case .bottomCenter: return "arrow.down.to.line"
case .bottomLeft: return "arrow.down.left.to.line"
case .bottomRight: return "arrow.down.right.to.line"
}
}
}
@@ -215,6 +252,58 @@ enum TransitionAnimation: String, CaseIterable {
}
}
struct ClockPositionGrid: View {
@Binding var selectedPosition: ClockPosition
var body: some View {
let positions: [[ClockPosition]] = [
[.topLeft, .topCenter, .topRight],
[.centerLeft, .center, .centerRight],
[.bottomLeft, .bottomCenter, .bottomRight]
]
VStack(spacing: 12) {
ForEach(positions, id: \.self) { row in
HStack(spacing: 12) {
ForEach(row, id: \.self) { position in
Button(action: {
selectedPosition = position
}) {
ZStack {
RoundedRectangle(cornerRadius: 12)
.fill(selectedPosition == position ? Color.blue : Color.gray.opacity(0.2))
.frame(width: 65, height: 65)
VStack(spacing: 4) {
Image(systemName: position.icon)
.font(.system(size: 24))
.foregroundColor(selectedPosition == position ? Color.white : Color.primary)
Text(position.displayName)
.font(.caption2)
.foregroundColor(selectedPosition == position ? Color.white : Color.primary)
.lineLimit(1)
.minimumScaleFactor(0.8)
}
.padding(.horizontal, 4)
}
}
.buttonStyle(PlainButtonStyle())
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(selectedPosition == position ? Color.blue : Color.clear, lineWidth: 2)
)
.shadow(color: selectedPosition == position ? Color.blue.opacity(0.5) : Color.clear, radius: 4)
}
}
}
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(16)
}
}
#Preview {
ContentView()
}
+63 -5
View File
@@ -10,6 +10,7 @@ import SwiftUI
struct SlideshowView: View {
let images: [UIImage]
let clockStyle: ClockStyle
let clockPosition: ClockPosition
@Binding var currentIndex: Int
let animation: TransitionAnimation
@@ -36,8 +37,8 @@ struct SlideshowView: View {
// Overlay gradient for better clock visibility
LinearGradient(
gradient: Gradient(colors: [Color.black.opacity(0.4), Color.clear]),
startPoint: .top,
endPoint: .center
startPoint: getGradientStartPoint(),
endPoint: getGradientEndPoint()
)
}
}
@@ -45,11 +46,14 @@ struct SlideshowView: View {
.animation(.easeInOut(duration: 1.0), value: currentIndex)
}
// Clock overlay
VStack {
// Clock overlay with positioning
GeometryReader { geometry in
clockView
.padding(.top, 50)
.position(getClockPosition(in: geometry.size))
}
// Image counter at the bottom
VStack {
Spacer()
// Image counter
@@ -82,6 +86,59 @@ struct SlideshowView: View {
}
}
private func getClockPosition(in size: CGSize) -> CGPoint {
switch clockPosition {
case .topCenter:
return CGPoint(x: size.width / 2, y: 100)
case .topLeft:
return CGPoint(x: size.width * 0.25, y: 100)
case .topRight:
return CGPoint(x: size.width * 0.75, y: 100)
case .centerLeft:
return CGPoint(x: 100, y: size.height / 2)
case .center:
return CGPoint(x: size.width / 2, y: size.height / 2)
case .centerRight:
return CGPoint(x: size.width - 100, y: size.height / 2)
case .bottomCenter:
return CGPoint(x: size.width / 2, y: size.height - 100)
case .bottomLeft:
return CGPoint(x: size.width * 0.25, y: size.height - 100)
case .bottomRight:
return CGPoint(x: size.width * 0.75, y: size.height - 100)
}
}
private func getGradientStartPoint() -> UnitPoint {
switch clockPosition {
case .topCenter, .topLeft, .topRight:
return .top
case .centerLeft:
return .leading
case .center:
return .center
case .centerRight:
return .trailing
case .bottomCenter, .bottomLeft, .bottomRight:
return .bottom
}
}
private func getGradientEndPoint() -> UnitPoint {
switch clockPosition {
case .topCenter, .topLeft, .topRight:
return .center
case .centerLeft:
return .trailing
case .center:
return .trailing
case .centerRight:
return .leading
case .bottomCenter, .bottomLeft, .bottomRight:
return .center
}
}
private func transitionEffect() -> AnyTransition {
switch animation {
case .fade:
@@ -229,6 +286,7 @@ struct MinimalClockView: View {
SlideshowView(
images: [UIImage(systemName: "photo")!],
clockStyle: .digital,
clockPosition: .topCenter,
currentIndex: .constant(0),
animation: .fade
)