mirror of
https://github.com/wahyd4/image-flow.git
synced 2026-08-09 05:05:59 +10:00
User now can select clock position
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user