Skip to content

Commit

Permalink
Merge branch 'develop' into setting/#198
Browse files Browse the repository at this point in the history
  • Loading branch information
mini-min committed Dec 2, 2024
2 parents 3001619 + 72a2ff2 commit e31ae37
Show file tree
Hide file tree
Showing 70 changed files with 2,837 additions and 817 deletions.
280 changes: 230 additions & 50 deletions TOASTER-iOS.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

9 changes: 3 additions & 6 deletions TOASTER-iOS/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,22 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {

let appDelegate = UIApplication.shared.delegate as! AppDelegate

if let pasteboardString = UIPasteboard.general.url {
if let pasteboardUrl = UIPasteboard.general.url {
if appDelegate.isLogin {
guard let rootVC = window?.rootViewController as? ToasterNavigationController else { return }
let addLinkViewController = AddLinkViewController()
rootVC.pushViewController(addLinkViewController, animated: true)
addLinkViewController.embedURL(url: UIPasteboard.general.string ?? "")
addLinkViewController.embedURL(url: pasteboardUrl.absoluteString)

if let presentedVC = rootVC.presentedViewController {
presentedVC.dismiss(animated: false)
}
}
}
UIPasteboard.general.string = nil
}

func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
UIPasteboard.general.url = nil
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ final class ToasterBottomSheetViewController: UIViewController {
extension ToasterBottomSheetViewController {
func setupSheetPresentation(bottomHeight: CGFloat) {
if let sheet = self.sheetPresentationController {
sheet.detents = [.custom(resolver: { _ in bottomHeight - 40 })]
sheet.detents = [.custom(resolver: { _ in bottomHeight - (self.view.hasNotch ? 34 : 0)})]
sheet.preferredCornerRadius = 20
}
}

func setupSheetHeightChanges(bottomHeight: CGFloat) {
if let sheet = self.sheetPresentationController {
sheet.animateChanges {
sheet.detents = [.custom(resolver: { _ in bottomHeight - 40 })]
sheet.detents = [.custom(resolver: { _ in bottomHeight - (self.view.hasNotch ? 34 : 0)})]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//
// ToasterLoadingView.swift
// TOASTER-iOS
//
// Created by 민 on 10/7/24.
//

import UIKit

import SnapKit

final class ToasterLoadingView: UIView {

// MARK: - Properties

/// 현재 로딩 뷰의 애니메이션이 동작하고 있는지를 Bool 값으로 반환
private(set) var isAnimating: Bool = false

/// 애니메이션이 중단될 때 로딩 뷰를 사라지게할지/말지를 Bool 값으로 결정
var hidesWhenStopped: Bool = true

// MARK: - UI Components

private let backgroundShapeLayer = CAShapeLayer()
private let loadingShapeLayer = CAShapeLayer()

// MARK: - Life Cycles

override init(frame: CGRect) {
super.init(frame: frame)
setupStyle()
setupHierarchy()
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func layoutSubviews() {
super.layoutSubviews()
setupLayers()
}
}

// MARK: - Extensions

extension ToasterLoadingView {
/// 커스텀 로딩 애니메이션을 시작합니다
func startAnimation() {
guard !isAnimating else { return }

let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.toValue = 2 * CGFloat.pi
rotationAnimation.duration = 1
rotationAnimation.isRemovedOnCompletion = false
rotationAnimation.repeatCount = .infinity

layer.add(rotationAnimation, forKey: "rotationAnimation")

isAnimating = true
if hidesWhenStopped { self.isHidden = false }
}

/// 커스텀 로딩 애니메이션을 멈춥니다
func stopAnimation() {
guard isAnimating else { return }
layer.removeAnimation(forKey: "rotationAnimation")

isAnimating = false
if hidesWhenStopped { self.isHidden = true }
}
}

// MARK: - Private Extensions

private extension ToasterLoadingView {
func setupStyle() {
backgroundShapeLayer.do {
$0.strokeColor = UIColor.toasterWhite.cgColor
$0.fillColor = UIColor.clear.cgColor
}

loadingShapeLayer.do {
$0.strokeColor = UIColor.black850.cgColor
$0.fillColor = UIColor.clear.cgColor
$0.strokeEnd = 0.25
$0.lineCap = .round
}
}

func setupLayers() {
let centerPoint = CGPoint(x: frame.width / 2, y: bounds.height / 2)
let radius = bounds.width / 2

// 흰색 부분의 동그라미 배경 경로
let backgroundPath = UIBezierPath(
arcCenter: centerPoint,
radius: radius,
startAngle: 0,
endAngle: 2 * CGFloat.pi,
clockwise: true
)
backgroundShapeLayer.path = backgroundPath.cgPath
backgroundShapeLayer.lineWidth = radius / 3

// 검정색 실제 로딩이 되는 부분의 경로
let loadingPath = UIBezierPath(
arcCenter: centerPoint,
radius: radius,
startAngle: 0,
endAngle: 2 * CGFloat.pi,
clockwise: true
)
loadingShapeLayer.path = loadingPath.cgPath
loadingShapeLayer.lineWidth = radius / 3
}

func setupHierarchy() {
[backgroundShapeLayer, loadingShapeLayer].forEach {
layer.addSublayer($0)
}
}
}
94 changes: 94 additions & 0 deletions TOASTER-iOS/Global/Components/ToasterTipView/TipPathView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//
// TipType.swift
// TOASTER-iOS
//
// Created by 민 on 10/11/24.
//

import UIKit

import SnapKit

enum TipType {
case top, bottom, left, right
}

final class TipPathView: UIView {

// MARK: - Properties

private var tipType: TipType

private let arrowWidth: CGFloat = 10.0
private let arrowHeight: CGFloat = 9.0

// MARK: - UI Components

private let tipPath = UIBezierPath()

// MARK: - Life Cycles

init(tipType: TipType) {
self.tipType = tipType
super.init(frame: .zero)
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func draw(_ rect: CGRect) {
switch tipType {
case .top: drawTopTip(rect)
case .bottom: drawBottomTip(rect)
case .left: drawLeftTip(rect)
case .right: drawRightTip(rect)
}
setupTip()
}
}

// MARK: - Private Extensions

private extension TipPathView {
func setupTip() {
tipPath.do {
$0.lineJoinStyle = .round
$0.lineWidth = 2
tipPath.close()
UIColor.black900.setStroke()
tipPath.stroke()
UIColor.black900.setFill()
tipPath.fill()
}
}

/// 팁이 상단에 위치했을 때 - 아래를 가리키는 방향
func drawTopTip(_ rect: CGRect) {
tipPath.move(to: CGPoint(x: rect.midX - arrowWidth/2, y: rect.maxY - arrowHeight))
tipPath.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
tipPath.addLine(to: CGPoint(x: rect.midX + arrowWidth/2, y: rect.maxY - arrowHeight))
}

/// 팁이 하단에 위치했을 때 - 위를 가리키는 방향
func drawBottomTip(_ rect: CGRect) {
tipPath.move(to: CGPoint(x: rect.midX - arrowWidth/2, y: rect.minY + arrowHeight))
tipPath.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
tipPath.addLine(to: CGPoint(x: rect.midX + arrowWidth/2, y: rect.minY + arrowHeight))
}

/// 팁이 좌측에 위치했을 때 - 오른쪽을 가리키는 방향
func drawLeftTip(_ rect: CGRect) {
tipPath.move(to: CGPoint(x: rect.maxX - arrowHeight, y: rect.midY - arrowWidth/2))
tipPath.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
tipPath.addLine(to: CGPoint(x: rect.maxX - arrowHeight, y: rect.midY + arrowWidth/2))
}

/// 팁이 우측에 위치했을 때 - 왼쪽을 가리키는 방향
func drawRightTip(_ rect: CGRect) {
tipPath.move(to: CGPoint(x: rect.minX + arrowHeight, y: rect.midY - arrowWidth/2))
tipPath.addLine(to: CGPoint(x: rect.minX, y: rect.midY))
tipPath.addLine(to: CGPoint(x: rect.minX + arrowHeight, y: rect.midY + arrowWidth/2))
}
}
14 changes: 14 additions & 0 deletions TOASTER-iOS/Global/Components/ToasterTipView/TipUserDefaults.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// TipUserDefaults.swift
// TOASTER-iOS
//
// Created by 민 on 10/29/24.
//

import Foundation

enum TipUserDefaults {
static let isShowHomeViewToolTip = "homeViewToolTip"
static let isShowDetailClipViewToolTip = "detailClipViewToolTip"
static let isShowLinkWebViewToolTip = "linkWebViewToolTip"
}
Loading

0 comments on commit e31ae37

Please sign in to comment.