-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
1,240 additions
and
35 deletions.
There are no files selected for viewing
8 changes: 8 additions & 0 deletions
8
Offroad-iOS/NotificationServiceExtension/NotificationServiceExtensionDebug.entitlements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>aps-environment</key> | ||
<string>development</string> | ||
</dict> | ||
</plist> |
Large diffs are not rendered by default.
Oops, something went wrong.
69 changes: 69 additions & 0 deletions
69
...ad-iOS/Offroad-iOS/Global/Components/NavigationController/ChatLogNavigationAnimator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// | ||
// ChatLogNavigationAnimator.swift | ||
// Offroad-iOS | ||
// | ||
// Created by 김민성 on 11/13/24. | ||
// | ||
|
||
import UIKit | ||
|
||
class ChatLogPushAnimator: NSObject, UIViewControllerAnimatedTransitioning { | ||
|
||
func transitionDuration(using transitionContext: (any UIViewControllerContextTransitioning)?) -> TimeInterval { | ||
return 0.5 | ||
} | ||
|
||
func animateTransition(using transitionContext: any UIViewControllerContextTransitioning) { | ||
guard let toView = transitionContext.view(forKey: .to), | ||
let fromView = transitionContext.view(forKey: .from) else { | ||
transitionContext.completeTransition(false) | ||
return | ||
} | ||
|
||
let containerView = transitionContext.containerView | ||
containerView.addSubview(toView) | ||
toView.frame = fromView.frame.offsetBy(dx: fromView.frame.width, dy: 0) | ||
|
||
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, animations: { | ||
toView.frame = fromView.frame | ||
}, completion: { finished in | ||
transitionContext.completeTransition(!transitionContext.transitionWasCancelled) | ||
}) | ||
} | ||
|
||
} | ||
|
||
class ChatLogPopAnimator: NSObject, UIViewControllerAnimatedTransitioning { | ||
|
||
func transitionDuration(using transitionContext: (any UIViewControllerContextTransitioning)?) -> TimeInterval { | ||
return 0.5 | ||
} | ||
|
||
func animateTransition(using transitionContext: any UIViewControllerContextTransitioning) { | ||
guard let toView = transitionContext.view(forKey: .to), | ||
let fromView = transitionContext.view(forKey: .from) else { | ||
transitionContext.completeTransition(false) | ||
return | ||
} | ||
|
||
let containerView = transitionContext.containerView | ||
let finalFrame = fromView.frame.offsetBy(dx: fromView.frame.width, dy: 0) | ||
containerView.insertSubview(toView, belowSubview: fromView) | ||
|
||
if transitionContext.isInteractive { | ||
UIView.animate(withDuration: 0.5, delay: 0, options: .curveLinear, animations: { | ||
fromView.frame = finalFrame | ||
}, completion: { finished in | ||
transitionContext.completeTransition(!transitionContext.transitionWasCancelled) | ||
}) | ||
} else { | ||
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, animations: { | ||
fromView.frame = finalFrame | ||
}, completion: { finished in | ||
transitionContext.completeTransition(!transitionContext.transitionWasCancelled) | ||
}) | ||
} | ||
|
||
} | ||
|
||
} |
129 changes: 129 additions & 0 deletions
129
Offroad-iOS/Offroad-iOS/Global/Components/NavigationController/ORBNavigationController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// | ||
// ORBNavigationController.swift | ||
// Offroad-iOS | ||
// | ||
// Created by 김민성 on 11/13/24. | ||
// | ||
|
||
import UIKit | ||
|
||
class ORBNavigationController: UINavigationController { | ||
|
||
var customPopTransition: UIPercentDrivenInteractiveTransition? | ||
lazy var screenEdgePanGesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
|
||
setupGestures() | ||
setupDelegates() | ||
} | ||
|
||
} | ||
|
||
|
||
extension ORBNavigationController { | ||
|
||
//MARK: - @objc Func | ||
|
||
@objc func handlePanGesture(_ gesture: UIScreenEdgePanGestureRecognizer) { | ||
let translation = gesture.translation(in: view) | ||
let progress = min(max(translation.x / view.bounds.width, 0), 1) | ||
|
||
switch gesture.state { | ||
case .began: | ||
customPopTransition = UIPercentDrivenInteractiveTransition() | ||
popViewController(animated: true) | ||
case .changed: | ||
customPopTransition?.update(progress) | ||
case .ended, .cancelled: | ||
let shouldFinish = progress > 0.5 || gesture.velocity(in: view).x > 0 | ||
if shouldFinish { | ||
customPopTransition?.finish() | ||
} else { | ||
customPopTransition?.cancel() | ||
} | ||
customPopTransition = nil | ||
default: | ||
break | ||
} | ||
} | ||
|
||
//MARK: - Private Func | ||
|
||
private func setupGestures() { | ||
screenEdgePanGesture.edges = .left | ||
view.addGestureRecognizer(screenEdgePanGesture) | ||
} | ||
|
||
private func setupDelegates() { | ||
delegate = self | ||
interactivePopGestureRecognizer?.delegate = self | ||
} | ||
|
||
//MARK: - Func | ||
|
||
func pushChatLogViewController(characterName: String) { | ||
guard let snapshot = topViewController?.view.snapshotView(afterScreenUpdates: true) else { return } | ||
let chatLogViewController = CharacterChatLogViewController(background: snapshot, characterName: characterName) | ||
pushViewController(chatLogViewController, animated: true) | ||
} | ||
|
||
} | ||
|
||
//MARK: - UINavigationControllerDelegate | ||
|
||
extension ORBNavigationController: UINavigationControllerDelegate { | ||
|
||
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { | ||
guard let tabBarController = tabBarController as? OffroadTabBarController else { return } | ||
guard !tabBarController.isTabBarShown else { return } | ||
tabBarController.disableTabBarInteraction() | ||
} | ||
|
||
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { | ||
|
||
if topViewController is CharacterChatLogViewController { | ||
screenEdgePanGesture.isEnabled = true | ||
interactivePopGestureRecognizer?.isEnabled = false | ||
} else { | ||
screenEdgePanGesture.isEnabled = false | ||
interactivePopGestureRecognizer?.isEnabled = true | ||
} | ||
|
||
guard let tabBarController = tabBarController as? OffroadTabBarController else { return } | ||
tabBarController.enableTabBarInteraction() | ||
} | ||
|
||
func navigationController(_ navigationController: UINavigationController, | ||
animationControllerFor operation: UINavigationController.Operation, | ||
from fromVC: UIViewController, | ||
to toVC: UIViewController | ||
) -> (any UIViewControllerAnimatedTransitioning)? { | ||
if operation == .push && toVC is CharacterChatLogViewController { | ||
return ChatLogPushAnimator() | ||
} else if operation == .pop && fromVC is CharacterChatLogViewController { | ||
return ChatLogPopAnimator() | ||
} | ||
return nil | ||
} | ||
|
||
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: any UIViewControllerAnimatedTransitioning) -> (any UIViewControllerInteractiveTransitioning)? { | ||
return customPopTransition | ||
} | ||
|
||
} | ||
|
||
//MARK: - UIGestureRecognizerDelegate | ||
|
||
extension ORBNavigationController: UIGestureRecognizerDelegate { | ||
|
||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { | ||
return true | ||
} | ||
|
||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { | ||
return gestureRecognizer == interactivePopGestureRecognizer | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.