Skip to content

Commit

Permalink
Merge pull request #135 from Team-Ampersand/116-pull-to-refresh-lotti…
Browse files Browse the repository at this point in the history
…e-animation

🔀 :: [#116] Pull To Refresh 애니메이션 추가
  • Loading branch information
baekteun authored Jul 30, 2023
2 parents 59d22fa + 20050f1 commit c4e23f7
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public extension TargetDependency {
}

public extension TargetDependency.SPM {
static let Lottie = TargetDependency.external(name: "Lottie")
static let Nuke = TargetDependency.external(name: "Nuke")
static let Anim = TargetDependency.external(name: "Anim")
static let CombineMiniature = TargetDependency.external(name: "CombineMiniature")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class MassageViewController: BaseStoredViewController<MassageStore> {
.then {
$0.register(cellType: MassageCell.self)
}
private let massageRefreshContorol = UIRefreshControl()
private let massageRefreshContorol = DotoriRefreshControl()
private lazy var massageTableAdapter = TableViewAdapter<GenericSectionModel<MassageRankModel>>(
tableView: massageTableView
) { tableView, indexPath, item in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class MusicViewController: BaseStoredViewController<MusicStore> {
.then {
$0.register(cellType: MusicCell.self)
}
private let musicRefreshControl = UIRefreshControl()
private let musicRefreshControl = DotoriRefreshControl()
private lazy var musicTableAdapter = TableViewAdapter<GenericSectionModel<MusicModel>>(
tableView: musicTableView
) { [weak self] tableView, indexPath, item in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ final class NoticeViewController: BaseStoredViewController<NoticeStore> {
.then {
$0.register(cellType: NoticeCell.self)
}
private let noticeRefreshControl = UIRefreshControl()
private let noticeRefreshControl = DotoriRefreshControl()
private lazy var noticeTableAdapter = TableViewAdapter<GenericSectionModel<NoticeModel>>(
tableView: noticeTableView
) { tableView, indexPath, notice in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class SelfStudyViewController: BaseStoredViewController<SelfStudyStore> {
.then {
$0.register(cellType: SelfStudyCell.self)
}
private let selfStudyRefreshContorol = UIRefreshControl()
private let selfStudyRefreshContorol = DotoriRefreshControl()
private lazy var selfStudyTableAdapter = TableViewAdapter<GenericSectionModel<SelfStudyRankModel>>(
tableView: selfStudyTableView
) { [weak self] tableView, indexPath, item in
Expand Down
4 changes: 4 additions & 0 deletions Projects/UserInterface/DesignSystem/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let project = Project.module(
dependencies: [
.SPM.Anim,
.SPM.MSGLayout,
.SPM.Lottie,
.userInterface(target: .DWebKit),
.shared(target: .GlobalThirdPartyLibrary),
.shared(target: .UIKitUtil)
Expand All @@ -22,5 +23,8 @@ let project = Project.module(
.demo(module: .userInterface(.DesignSystem), dependencies: [
.userInterface(target: .DesignSystem)
])
],
resourceSynthesizers: .default + [
.custom(name: "Lottie", parser: .json, extensions: ["json"])
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"4.6.3","fr":25,"ip":0,"op":15,"w":200,"h":200,"nm":"Graph Load","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 3","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":9,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":12,"s":[100],"e":[0]},{"t":15}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[128,100,0]},"a":{"a":0,"k":[3.481,-1.019,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[14.963,14.963]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[0.7921569,0.8156863,0.8352941,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[3.481,-1.019],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":15,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":3,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":9,"s":[100],"e":[0]},{"t":12}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[99.875,100,0]},"a":{"a":0,"k":[3.481,-1.019,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[14.963,14.963]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[0.7921569,0.8156863,0.8352941,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[3.481,-1.019],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":15,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 2","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":3,"s":[100],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":6,"s":[100],"e":[0]},{"t":9}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[71.75,100,0]},"a":{"a":0,"k":[3.481,-1.019,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[14.963,14.963]},"p":{"a":0,"k":[0,0]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"fl","c":{"a":0,"k":[0.7921569,0.8156863,0.8352941,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[3.481,-1.019],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":15,"st":0,"bm":0,"sr":1}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Lottie
import MSGLayout
import UIKit

public final class DotoriRefreshControl: UIRefreshControl {
private let dotoriLoadingView = LottieAnimationView(
animation: AnimationAsset.dotoriLoading.animation
)

public override init() {
super.init()
self.tintColor = .clear
dotoriLoadingView.loopMode = .loop
self.addSubviews {
dotoriLoadingView
}
MSGLayout.buildLayout {
dotoriLoadingView.layout
.size(100)
.center(.toSuperview())
}
dotoriLoadingView.play()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

public override func beginRefreshing() {
super.beginRefreshing()
dotoriLoadingView.play()
}
}
1 change: 1 addition & 0 deletions Tuist/Dependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ let dependencies = Dependencies(
carthage: nil,
swiftPackageManager: SwiftPackageManagerDependencies(
[
.remote(url: "https://github.com/airbnb/lottie-ios.git", requirement: .exact("4.2.0")),
.remote(url: "https://github.com/kean/Nuke.git", requirement: .exact("12.1.4")),
.remote(url: "https://github.com/GSM-MSG/Anim.git", requirement: .exact("1.1.0")),
.remote(url: "https://github.com/GSM-MSG/Miniature.git", requirement: .exact("1.3.1")),
Expand Down
56 changes: 56 additions & 0 deletions Tuist/ResourceSynthesizers/Lottie.stencil
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// swiftformat:disable all
// swiftlint:disable all
{% if files %}
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
{% set documentPrefix %}{{param.documentName|default:"Document"}}{% endset %}
import Foundation
#if canImport(Lottie)
import Lottie
// MARK: - Animations Assets
{{accessModifier}} extension AnimationAsset {
{% for file in files %}
static let {{file.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = Self(named: "{{file.name}}")
{% endfor %}
}
// MARK: - Animation Helpers
{{accessModifier}} extension AnimationAsset {
/// All the available animation. Can be used to preload them
static let allAnimations: [Self] = [
{% for file in files %}
Self.{{file.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}},
{% endfor %}
]
}
// MARK: - Structures
{{accessModifier}} struct AnimationAsset: Hashable {
{{accessModifier}} fileprivate(set) var name: String
{{accessModifier}} let animation: LottieAnimation?
{{accessModifier}} init(named name: String) {
self.name = name
if let url = Bundle.module.url(forResource: name, withExtension: "json") {
self.animation = LottieAnimation.filepath(url.path)
} else {
self.animation = nil
}
}
// MARK: Hashable Conformance
{{accessModifier}} static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.name == rhs.name
}
{{accessModifier}} func hash(into hasher: inout Hasher) {
hasher.combine(self.name)
}
}
// MARK: - Preload Helpers
{{accessModifier}} extension AnimationAsset {
/// Preloads all the Lottie Animations to avoid performance issues when loading them
static func preload() -> Void {
for animationAsset in Self.allAnimations {
_ = animationAsset.animation
}
}
}
#endif
{% else %}
// No files found
{% endif %}

0 comments on commit c4e23f7

Please sign in to comment.