Skip to content

Commit

Permalink
Extend configuration to include colors and fonts
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
yefimtsev committed Oct 20, 2024
1 parent 8b6fc8b commit 22ed64a
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 28 deletions.
46 changes: 44 additions & 2 deletions Sources/SwiftyCrop/Models/SwiftyCropConfiguration.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CoreGraphics
import SwiftUI

/// `SwiftyCropConfiguration` is a struct that defines the configuration for cropping behavior.
public struct SwiftyCropConfiguration {
Expand All @@ -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,
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -58,5 +98,7 @@ public struct SwiftyCropConfiguration {
self.zoomSensitivity = zoomSensitivity
self.rectAspectRatio = rectAspectRatio
self.customTexts = customTexts
self.fonts = fonts
self.colors = colors
}
}
54 changes: 28 additions & 26 deletions Sources/SwiftyCrop/View/CropView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()
Expand All @@ -63,25 +63,25 @@ struct CropView: View {
.onEnded { _ in
viewModel.lastOffset = viewModel.offset
}

let rotationGesture = RotationGesture()
.onChanged { value in
viewModel.angle = value
}
.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()
Expand All @@ -98,7 +98,7 @@ struct CropView: View {
}
}
)

Image(uiImage: image)
.resizable()
.scaledToFit()
Expand All @@ -114,45 +114,47 @@ struct CropView: View {
.simultaneousGesture(magnificationGesture)
.simultaneousGesture(dragGesture)
.simultaneousGesture(configuration.rotateImage ? rotationGesture : nil)

HStack {
Button {
dismiss()
} label: {
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()
} label: {
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)
let newY = min(max(viewModel.offset.height, -maxOffsetPoint.y), maxOffsetPoint.y)
viewModel.offset = CGSize(width: newX, height: newY)
viewModel.lastOffset = viewModel.offset
}

private func cropImage() -> UIImage? {
var editedImage: UIImage = image
if configuration.rotateImage {
Expand All @@ -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 {
Expand Down

0 comments on commit 22ed64a

Please sign in to comment.