-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
12 changed files
with
244 additions
and
0 deletions.
There are no files selected for viewing
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
23 changes: 23 additions & 0 deletions
23
Sources/Core/FeaturePrelude/Banner/BannerClient+Interface.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,23 @@ | ||
import Dependencies | ||
import UIKit | ||
|
||
// MARK: - BannerClient | ||
@MainActor | ||
public struct BannerClient { | ||
public var setWindowScene: SetWindowScene | ||
public var presentBanner: PresentBanner | ||
static var scene: UIWindowScene? | ||
static var window: UIWindow? | ||
} | ||
|
||
extension BannerClient { | ||
public typealias SetWindowScene = (UIWindowScene) async -> Void | ||
public typealias PresentBanner = (String) async -> Void | ||
} | ||
|
||
extension DependencyValues { | ||
public var bannerClient: BannerClient { | ||
get { self[BannerClient.self] } | ||
set { self[BannerClient.self] = newValue } | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
Sources/Core/FeaturePrelude/Banner/BannerClient+Live.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,24 @@ | ||
import Dependencies | ||
import UIKit | ||
|
||
extension BannerClient: DependencyKey { | ||
public static let liveValue: Self = .init( | ||
setWindowScene: { windowScene in | ||
scene = windowScene | ||
}, | ||
presentBanner: { text in | ||
guard window == nil, let windowScene = scene else { return } | ||
window = UIWindow(windowScene: windowScene) | ||
guard let bannerWindow = window else { return } | ||
bannerWindow.rootViewController = BannerViewController( | ||
text: text, | ||
completed: { | ||
window = nil | ||
} | ||
) | ||
bannerWindow.windowLevel = .normal + 1 | ||
bannerWindow.isUserInteractionEnabled = false | ||
bannerWindow.makeKeyAndVisible() | ||
} | ||
) | ||
} |
17 changes: 17 additions & 0 deletions
17
Sources/Core/FeaturePrelude/Banner/BannerClient+Test.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,17 @@ | ||
import Dependencies | ||
|
||
// MARK: - BannerClient + TestDependencyKey | ||
extension BannerClient: TestDependencyKey { | ||
public static let previewValue = Self.noop | ||
public static let testValue: Self = .init( | ||
setWindowScene: unimplemented("\(Self.self).setWindowScene"), | ||
presentBanner: unimplemented("\(Self.self).presentBanner") | ||
) | ||
} | ||
|
||
extension BannerClient { | ||
public static let noop: Self = .init( | ||
setWindowScene: { _ in }, | ||
presentBanner: { _ in } | ||
) | ||
} |
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,64 @@ | ||
import DesignSystem | ||
import Resources | ||
import SwiftUI | ||
import UIKit | ||
|
||
// MARK: - BannerView | ||
public final class BannerView: UIView { | ||
private let text: String | ||
private let label = UILabel() | ||
private let padding: CGFloat = .small1 | ||
private var shadowLayer: CAShapeLayer? | ||
|
||
override public var intrinsicContentSize: CGSize { | ||
.init(width: label.intrinsicContentSize.width + .large1, | ||
height: label.intrinsicContentSize.height + .medium1) | ||
} | ||
|
||
public init(text: String) { | ||
self.text = text | ||
super.init(frame: .zero) | ||
setUpLabel() | ||
} | ||
|
||
@available(*, unavailable) | ||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
override public func layoutSubviews() { | ||
super.layoutSubviews() | ||
guard shadowLayer == nil else { return } | ||
setUpShadowLayer() | ||
} | ||
} | ||
|
||
// MARK: - Private Methods | ||
extension BannerView { | ||
private func setUpLabel() { | ||
label.text = text | ||
label.textColor = UIColor(Color.app.gray1) | ||
label.font = UIFont(name: FontFamily.IBMPlexSans.medium.name, size: 16) | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
addSubview(label) | ||
NSLayoutConstraint.activate([ | ||
label.centerXAnchor.constraint(equalTo: centerXAnchor), | ||
label.centerYAnchor.constraint(equalTo: centerYAnchor), | ||
]) | ||
} | ||
|
||
private func setUpShadowLayer() { | ||
shadowLayer = CAShapeLayer() | ||
shadowLayer?.path = UIBezierPath(roundedRect: bounds, cornerRadius: frame.height / 2).cgPath | ||
shadowLayer?.fillColor = UIColor(Color.app.white).cgColor | ||
|
||
shadowLayer?.shadowColor = UIColor.black.cgColor | ||
shadowLayer?.shadowPath = shadowLayer?.path | ||
shadowLayer?.shadowOffset = CGSize(width: 0, height: 2) | ||
shadowLayer?.shadowOpacity = 0.3 | ||
shadowLayer?.shadowRadius = 5 | ||
|
||
guard let shadowLayer = shadowLayer else { return } | ||
layer.insertSublayer(shadowLayer, at: 0) | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
Sources/Core/FeaturePrelude/Banner/BannerViewController.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,75 @@ | ||
import UIKit | ||
|
||
// MARK: - BannerViewController | ||
public final class BannerViewController: UIViewController { | ||
private let banner: BannerView | ||
private let completed: () -> Void | ||
|
||
public init( | ||
text: String, | ||
completed: @escaping () -> Void | ||
) { | ||
self.banner = BannerView(text: text) | ||
self.completed = completed | ||
super.init(nibName: nil, bundle: nil) | ||
} | ||
|
||
@available(*, unavailable) | ||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
override public func viewDidLoad() { | ||
super.viewDidLoad() | ||
setInitialState() | ||
} | ||
|
||
override public func viewDidAppear(_ animated: Bool) { | ||
super.viewDidAppear(animated) | ||
showBannerView() | ||
} | ||
} | ||
|
||
// MARK: - Private Methods | ||
extension BannerViewController { | ||
private func setInitialState() { | ||
banner.alpha = 0 | ||
banner.translatesAutoresizingMaskIntoConstraints = false | ||
view.addSubview(banner) | ||
NSLayoutConstraint.activate([ | ||
banner.centerXAnchor.constraint(equalTo: view.centerXAnchor), | ||
banner.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100), | ||
]) | ||
} | ||
|
||
private func showBannerView() { | ||
UIView.animate( | ||
withDuration: Constants.animationDuration, | ||
animations: { [weak self] in | ||
self?.banner.alpha = 1 | ||
}, completion: { [weak self] _ in | ||
self?.hideBannerView() | ||
} | ||
) | ||
} | ||
|
||
private func hideBannerView() { | ||
UIView.animate( | ||
withDuration: Constants.animationDuration, | ||
delay: Constants.presentationDuration, | ||
animations: { [weak self] in | ||
self?.banner.alpha = 0 | ||
}, completion: { [weak self] _ in | ||
self?.completed() | ||
} | ||
) | ||
} | ||
} | ||
|
||
// MARK: BannerViewController.Constants | ||
extension BannerViewController { | ||
private enum Constants { | ||
static let animationDuration: TimeInterval = 0.15 | ||
static let presentationDuration: TimeInterval = 2 | ||
} | ||
} |
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
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,13 @@ | ||
import UIKit | ||
|
||
public final class AppDelegate: NSObject, UIApplicationDelegate { | ||
public func application( | ||
_ application: UIApplication, | ||
configurationForConnecting connectingSceneSession: UISceneSession, | ||
options: UIScene.ConnectionOptions | ||
) -> UISceneConfiguration { | ||
let sceneConfig = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role) | ||
sceneConfig.delegateClass = SceneDelegate.self | ||
return sceneConfig | ||
} | ||
} |
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,13 @@ | ||
import UIKit | ||
|
||
public final class SceneDelegate: NSObject, UIWindowSceneDelegate, ObservableObject { | ||
public weak var windowScene: UIWindowScene? | ||
|
||
public func scene( | ||
_ scene: UIScene, | ||
willConnectTo session: UISceneSession, | ||
options connectionOptions: UIScene.ConnectionOptions | ||
) { | ||
windowScene = scene as? UIWindowScene | ||
} | ||
} |