Skip to content

Commit

Permalink
feat: add limit to video and button animations
Browse files Browse the repository at this point in the history
  • Loading branch information
FranAlarza committed Sep 16, 2024
1 parent 49ecde5 commit f4de7f0
Show file tree
Hide file tree
Showing 14 changed files with 189 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
import SwiftUI

struct ScreenshootPreviewScreen: View {
let viewModel = ScreenshootViewModel()
@ObservedObject var viewModel = ScreenshootViewModel()
@Environment(\.dismiss) var dismiss
@State var screenshot: UIImage?
@State var user: String = ""
@State var description: String = ""
@State var reportType: FeedbackType = .feedback
@State var imageLines: [Line] = []
@State var imageIsSelected: Bool = true
@FocusState var focused: Bool

var body: some View {
Expand All @@ -38,18 +39,21 @@ struct ScreenshootPreviewScreen: View {
.frame(maxHeight: .infinity)
.lineLimit(0)
.focused($focused)
#if DEBUG
if let screenshot {
Image(uiImage: screenshot)
.resizable()
.frame(width: 200, height: 300)
.aspectRatio(contentMode: .fit)
}
#endif
ScreenShootRowView(image: $screenshot, lines: $imageLines)
ScreenShootRowView(
image: $screenshot,
lines: $imageLines,
isSelected: $imageIsSelected
)
.frame(height: 64)
Spacer()
}
.alert(viewModel.isReportSended.title ?? "", isPresented: $viewModel.isAlertPresented, actions: {
Button(action: {
dismiss.callAsFunction()
}, label: {
Text("Ok")
})
})
.padding()
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("Send \(reportType.rawValue.capitalized)")
Expand All @@ -71,7 +75,16 @@ struct ScreenshootPreviewScreen: View {
image: screenshot,
lines: imageLines
)
self.screenshot = newScreenShot

if let newScreenShot {
viewModel.sendScreenshootFeedback(
feedback: .init(
feedbackType: reportType,
message: description,
screenshot: imageIsSelected ? .init(image: newScreenShot) : nil
)
)
}
},
label: {
Image(systemName: "location.fill")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,28 @@ import Foundation
import UIKit
import SwiftUI

final class ScreenshootViewModel {
enum ReportRequestState {
case idle
case success
case failed
case loading

var title: String? {
switch self {
case .idle, .loading:
nil
case .success:
"Feedback sended succesfully!"
case .failed:
"Feedback sended error"
}
}
}

final class ScreenshootViewModel: ObservableObject {

@Published var isReportSended: ReportRequestState = .idle
@Published var isAlertPresented: Bool = false

private let feedbackService: PFeedbackService

Expand All @@ -23,18 +44,24 @@ final class ScreenshootViewModel {
self.feedbackService = feedbackService
}

@MainActor
func sendScreenshootFeedback(feedback: Feedback) {
isReportSended = .loading
feedbackService.postFeedback(feedback) { result in
switch result {
case .success(let successType):
case .success:
self.isReportSended = .success
self.isAlertPresented = true
print("Feedback sended succesfully")
case .error(let errorType):
case .error:
self.isReportSended = .failed
self.isAlertPresented = true
print("Feedback sended error:")
}
}
}

func exportDrawing(image: UIImage, lines: [Line]) -> UIImage {
func exportDrawing(image: UIImage, lines: [Line]) -> UIImage? {

// Create a context of the starting image size and set it as the current one
UIGraphicsBeginImageContext(image.size)
Expand All @@ -43,30 +70,32 @@ final class ScreenshootViewModel {
image.draw(at: CGPoint.zero)

// Get the current context
let context = UIGraphicsGetCurrentContext()!
let context = UIGraphicsGetCurrentContext()

func toImagePoint(point: CGPoint) -> CGPoint {
.init(x: point.x * image.size.width, y: point.y * image.size.height)
}

for line in lines {
context.setStrokeColor(line.color.cgColor ?? UIColor.systemPink.cgColor)
context.setLineWidth(line.lineWidth)
context?.setStrokeColor(line.color.cgColor ?? UIColor.systemPink.cgColor)
context?.setLineWidth(line.lineWidth)

var points = line.points
let firstPoint = points.removeFirst()

context.move(to: toImagePoint(point: firstPoint))
for point in points {
context.addLine(to: toImagePoint(point: point))
if !points.isEmpty {
let firstPoint = points.removeFirst()

context?.move(to: toImagePoint(point: firstPoint))
for point in points {
context?.addLine(to: toImagePoint(point: point))
}
context?.strokePath()
}
context.strokePath()
}
// Save the context as a new UIImage
let myImage = UIGraphicsGetImageFromCurrentImageContext()
let renderedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

// Return modified image
return myImage!
return renderedImage
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,15 @@ struct EditScreenshotView: View {
.padding(.horizontal, 100)
}

func screenPoint(_ point: CGPoint) -> CGPoint {
// Convert 0->1 to view's coordinates
debugPrint("ViewSize \(viewSize)")
let vw = viewSize.width
let vh = viewSize.height
let nextX = min(1, max(0, point.x)) * vw
let nextY = min(1, max(0, point.y)) * vh
return CGPoint(x: nextX, y: nextY)
}
// func screenPoint(_ point: CGPoint) -> CGPoint {
// // Convert 0->1 to view's coordinates
// debugPrint("ViewSize \(viewSize)")
// let vw = viewSize.width
// let vh = viewSize.height
// let nextX = min(1, max(0, point.x)) * vw
// let nextY = min(1, max(0, point.y)) * vh
// return CGPoint(x: nextX, y: nextY)
// }

func limitPoint(_ point: CGPoint) -> CGPoint {
debugPrint("ViewSize \(viewSize)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import SwiftUI
struct ScreenShootRowView: View {
@Binding var image: UIImage?
@Binding var lines: [Line]
@State var isSelected: Bool = true
@Binding var isSelected: Bool
@State var editScreenshootSheetIsPresented = false

var body: some View {
Expand Down Expand Up @@ -55,5 +55,9 @@ struct ScreenShootRowView: View {
}

#Preview {
ScreenShootRowView(image: .constant(UIImage(systemName: "checkmark.circle.fill")), lines: .constant([]))
ScreenShootRowView(
image: .constant(UIImage(systemName: "checkmark.circle.fill")),
lines: .constant([]),
isSelected: .constant(false)
)
}
31 changes: 31 additions & 0 deletions AppliverySDK/Applivery/Modules/VideoReport/TimedButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// TimedButton.swift
//
//
// Created by Fran Alarza on 16/9/24.
//

import SwiftUI

struct TimedButton: View {
let action: () -> Void

var body: some View {
Button {
action()
} label: {
Image(systemName: "play.circle.fill")
.resizable()
.frame(width: 60, height: 60)
}
.clipShape(Circle())
.overlay {
Circle()
.stroke(lineWidth: 4)
}
}
}

#Preview {
TimedButton(action: {})
}
82 changes: 38 additions & 44 deletions AppliverySDK/Applivery/Views/RecordingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import UIKit
class RecordingViewController: UIViewController {

private var recordButton: UIButton = UIButton(type: .system)
private let borderLayer = CAShapeLayer()
private var actionSheet: UIAlertController = UIAlertController()
var buttonAction: (() -> Void)?

private var feedbackCoordinator: PFeedbackCoordinator
private let shapeLayer = CAShapeLayer()

init(feedbackCoordinator: PFeedbackCoordinator) {
self.feedbackCoordinator = feedbackCoordinator
Expand All @@ -29,7 +29,16 @@ class RecordingViewController: UIViewController {
super.viewDidLoad()
view.backgroundColor = .clear
addRecordButton()
setupProgressBorder()
}


override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

recordButton.layer.cornerRadius = recordButton.bounds.size.width / 2

borderLayer.frame = recordButton.bounds
borderLayer.path = UIBezierPath(ovalIn: borderLayer.bounds).cgPath
}

deinit {
Expand All @@ -41,23 +50,43 @@ class RecordingViewController: UIViewController {
}

private func addRecordButton() {
let configuration = UIImage.SymbolConfiguration(pointSize: 32, weight: .heavy)
let configuration = UIImage.SymbolConfiguration(pointSize: 48, weight: .heavy)
let symbolImage = UIImage(systemName: "stop.circle.fill", withConfiguration: configuration)
recordButton.setImage(symbolImage, for: .normal)
recordButton.tintColor = .white
recordButton.addTarget(self, action: #selector(recordButtonTapped), for: .touchUpInside)
recordButton.translatesAutoresizingMaskIntoConstraints = false
recordButton.clipsToBounds = true
recordButton.isHidden = true

view.addSubview(self.recordButton)

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
recordButton.addGestureRecognizer(panGesture)

// Set up constraints
NSLayoutConstraint.activate([
recordButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
recordButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
recordButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 48),
recordButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -48),
recordButton.widthAnchor.constraint(equalToConstant: 48),
recordButton.heightAnchor.constraint(equalToConstant: 48),
])

borderLayer.strokeColor = UIColor.red.cgColor
borderLayer.lineWidth = 8
borderLayer.fillColor = nil

recordButton.layer.addSublayer(borderLayer)

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
recordButton.addGestureRecognizer(panGesture)
}

private func animateBorder() {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = 30
animation.fromValue = 0
animation.toValue = 1
animation.timingFunction = CAMediaTimingFunction(name: .linear)

borderLayer.add(animation, forKey: "borderAnimation")
}

@objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
Expand All @@ -70,44 +99,9 @@ class RecordingViewController: UIViewController {
gesture.setTranslation(.zero, in: view)
}

private func setupProgressBorder() {
let circularPath = UIBezierPath(
arcCenter: .init(
x: recordButton.frame.midX,
y: recordButton.frame.midY
),
radius: recordButton.bounds.width + 10,
startAngle: -CGFloat.pi / 2,
endAngle: 1.5 * CGFloat.pi,
clockwise: true
)

shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 4
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineCap = .round
shapeLayer.strokeEnd = 0

//view.layer.addSublayer(shapeLayer)

}

private func startProgressAnimation() {
shapeLayer.strokeEnd = 0

let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
basicAnimation.toValue = 1
basicAnimation.duration = 30
basicAnimation.fillMode = .forwards
basicAnimation.isRemovedOnCompletion = false

shapeLayer.add(basicAnimation, forKey: "progressAnimation")
}

func showRecordButton() {
self.recordButton.isHidden = false
startProgressAnimation()
animateBorder()
}

func hideRecordButton() {
Expand Down
Loading

0 comments on commit f4de7f0

Please sign in to comment.