From 22ed64a199dec5d36b81937d04e7a19eb6a3623e Mon Sep 17 00:00:00 2001 From: Yaroslav Yefimtsev Date: Mon, 21 Oct 2024 01:08:28 +0300 Subject: [PATCH] Extend configuration to include colors and fonts * Add Colors struct to the configuration to handle color customization of the buttons, instruction and background * Add Fonts struct to the configuration to handle font customization of the buttons and instruction * Remove hardcoded color and font references in CropView * Fix trailing whitespaces in CropView.swift --- .../Models/SwiftyCropConfiguration.swift | 46 +++++++++++++++- Sources/SwiftyCrop/View/CropView.swift | 54 ++++++++++--------- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift b/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift index 3683735..85ac796 100644 --- a/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift +++ b/Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift @@ -1,4 +1,5 @@ import CoreGraphics +import SwiftUI /// `SwiftyCropConfiguration` is a struct that defines the configuration for cropping behavior. public struct SwiftyCropConfiguration { @@ -9,7 +10,9 @@ public struct SwiftyCropConfiguration { public let zoomSensitivity: CGFloat public let rectAspectRatio: CGFloat public let customTexts: Texts? - + public let fonts: Fonts + public let colors: Colors + public struct Texts { public init( cancelButtonText: String, @@ -26,6 +29,41 @@ public struct SwiftyCropConfiguration { public let saveButtonText: String } + public struct Colors { + public init( + cancelButton: Color = .white, + interactionInstructions: Color = .white, + saveButton: Color = .white, + background: Color = .black + ) { + self.cancelButton = cancelButton + self.interactionInstructions = interactionInstructions + self.saveButton = saveButton + self.background = background + } + + public let cancelButton: Color + public let interactionInstructions: Color + public let saveButton: Color + public let background: Color + } + + public struct Fonts { + public init( + cancelButton: Font? = nil, + interactionInstructions: Font? = nil, + saveButton: Font? = nil + ) { + self.cancelButton = cancelButton + self.interactionInstructions = interactionInstructions ?? .system(size: 16, weight: .regular) + self.saveButton = saveButton + } + + public let cancelButton: Font? + public let interactionInstructions: Font + public let saveButton: Font? + } + /// Creates a new instance of `SwiftyCropConfiguration`. /// /// - Parameters: @@ -49,7 +87,9 @@ public struct SwiftyCropConfiguration { rotateImage: Bool = false, zoomSensitivity: CGFloat = 1, rectAspectRatio: CGFloat = 4/3, - customTexts: Texts? = nil + customTexts: Texts? = nil, + fonts: Fonts = .init(), + colors: Colors = .init() ) { self.maxMagnificationScale = maxMagnificationScale self.maskRadius = maskRadius @@ -58,5 +98,7 @@ public struct SwiftyCropConfiguration { self.zoomSensitivity = zoomSensitivity self.rectAspectRatio = rectAspectRatio self.customTexts = customTexts + self.fonts = fonts + self.colors = colors } } diff --git a/Sources/SwiftyCrop/View/CropView.swift b/Sources/SwiftyCrop/View/CropView.swift index a2dd0f1..6b688d0 100644 --- a/Sources/SwiftyCrop/View/CropView.swift +++ b/Sources/SwiftyCrop/View/CropView.swift @@ -3,13 +3,13 @@ import SwiftUI struct CropView: View { @Environment(\.dismiss) private var dismiss @StateObject private var viewModel: CropViewModel - + private let image: UIImage private let maskShape: MaskShape private let configuration: SwiftyCropConfiguration private let onComplete: (UIImage?) -> Void private let localizableTableName: String - + init( image: UIImage, maskShape: MaskShape, @@ -30,23 +30,23 @@ struct CropView: View { ) localizableTableName = "Localizable" } - + var body: some View { let magnificationGesture = MagnificationGesture() .onChanged { value in let sensitivity: CGFloat = 0.1 * configuration.zoomSensitivity let scaledValue = (value.magnitude - 1) * sensitivity + 1 - + let maxScaleValues = viewModel.calculateMagnificationGestureMaxValues() viewModel.scale = min(max(scaledValue * viewModel.lastScale, maxScaleValues.0), maxScaleValues.1) - + updateOffset() } .onEnded { _ in viewModel.lastScale = viewModel.scale viewModel.lastOffset = viewModel.offset } - + let dragGesture = DragGesture() .onChanged { value in let maxOffsetPoint = viewModel.calculateDragGestureMax() @@ -63,7 +63,7 @@ struct CropView: View { .onEnded { _ in viewModel.lastOffset = viewModel.offset } - + let rotationGesture = RotationGesture() .onChanged { value in viewModel.angle = value @@ -71,17 +71,17 @@ struct CropView: View { .onEnded { _ in viewModel.lastAngle = viewModel.angle } - + VStack { Text( configuration.customTexts?.interactionInstructionsText ?? NSLocalizedString("interaction_instructions", tableName: localizableTableName, bundle: .module, comment: "") ) - .font(.system(size: 16, weight: .regular)) - .foregroundColor(.white) - .padding(.top, 30) - .zIndex(1) - + .font(configuration.fonts.interactionInstructions) + .foregroundColor(configuration.colors.interactionInstructions) + .padding(.top, 30) + .zIndex(1) + ZStack { Image(uiImage: image) .resizable() @@ -98,7 +98,7 @@ struct CropView: View { } } ) - + Image(uiImage: image) .resizable() .scaledToFit() @@ -114,7 +114,7 @@ struct CropView: View { .simultaneousGesture(magnificationGesture) .simultaneousGesture(dragGesture) .simultaneousGesture(configuration.rotateImage ? rotationGesture : nil) - + HStack { Button { dismiss() @@ -122,12 +122,13 @@ struct CropView: View { Text( configuration.customTexts?.cancelButtonText ?? NSLocalizedString("cancel_button", tableName: localizableTableName, bundle: .module, comment: "") - ) + ) } - .foregroundColor(.white) - + .font(configuration.fonts.cancelButton) + .foregroundColor(configuration.colors.cancelButton) + Spacer() - + Button { onComplete(cropImage()) dismiss() @@ -135,16 +136,17 @@ struct CropView: View { Text( configuration.customTexts?.saveButtonText ?? NSLocalizedString("save_button", tableName: localizableTableName, bundle: .module, comment: "") - ) + ) + .font(configuration.fonts.saveButton) } - .foregroundColor(.white) + .foregroundColor(configuration.colors.saveButton) } .frame(maxWidth: .infinity, alignment: .bottom) .padding() } - .background(.black) + .background(configuration.colors.background) } - + private func updateOffset() { let maxOffsetPoint = viewModel.calculateDragGestureMax() let newX = min(max(viewModel.offset.width, -maxOffsetPoint.x), maxOffsetPoint.x) @@ -152,7 +154,7 @@ struct CropView: View { viewModel.offset = CGSize(width: newX, height: newY) viewModel.lastOffset = viewModel.offset } - + private func cropImage() -> UIImage? { var editedImage: UIImage = image if configuration.rotateImage { @@ -171,10 +173,10 @@ struct CropView: View { return viewModel.cropToSquare(editedImage) } } - + private struct MaskShapeView: View { let maskShape: MaskShape - + var body: some View { Group { switch maskShape {