diff --git a/Dear-World/Dear-World.xcodeproj/project.pbxproj b/Dear-World/Dear-World.xcodeproj/project.pbxproj index 07bd2ff..8c62f9c 100644 --- a/Dear-World/Dear-World.xcodeproj/project.pbxproj +++ b/Dear-World/Dear-World.xcodeproj/project.pbxproj @@ -22,6 +22,8 @@ 3902F12425970E5600A3DF8C /* Number+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3902F12325970E5600A3DF8C /* Number+.swift */; }; 3902F12A259714D800A3DF8C /* RankerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3902F129259714D800A3DF8C /* RankerTableViewCell.swift */; }; 3914D9E6259F3FA1009765B0 /* Message.Model.Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3914D9E5259F3FA1009765B0 /* Message.Model.Messages.swift */; }; + 393E0D4025A23A12000DB3B9 /* World.Model.Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393E0D3F25A23A12000DB3B9 /* World.Model.Map.swift */; }; + 393E0D4525A23A7B000DB3B9 /* World.API.Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393E0D4425A23A7B000DB3B9 /* World.API.Map.swift */; }; 3958257B25948E41007325AB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3958257A25948E41007325AB /* AppDelegate.swift */; }; 3958258425948E43007325AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3958258325948E43007325AB /* Assets.xcassets */; }; 3958258725948E43007325AB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3958258525948E43007325AB /* LaunchScreen.storyboard */; }; @@ -61,7 +63,6 @@ 39E9F7E025A1BC3C00BC2CC2 /* NoticeBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E9F7DF25A1BC3C00BC2CC2 /* NoticeBadge.swift */; }; 39E9F7E625A1C80300BC2CC2 /* WorldMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E9F7E525A1C80300BC2CC2 /* WorldMap.swift */; }; 39E9F7ED25A1C84900BC2CC2 /* WorldMap.Model.Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E9F7EC25A1C84900BC2CC2 /* WorldMap.Model.Country.swift */; }; - 39EED22E259CFEB8007452E1 /* World.Model.Ranker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EED22D259CFEB8007452E1 /* World.Model.Ranker.swift */; }; 39EED23C259D00F8007452E1 /* CheeringMapReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EED23B259D00F8007452E1 /* CheeringMapReactor.swift */; }; 39EED241259D0227007452E1 /* Revision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EED240259D0227007452E1 /* Revision.swift */; }; 39F0C1632597B34F00A7001F /* UIView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39F0C1622597B34F00A7001F /* UIView+.swift */; }; @@ -110,6 +111,8 @@ 3902F12325970E5600A3DF8C /* Number+.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = "Number+.swift"; sourceTree = ""; tabWidth = 2; }; 3902F129259714D800A3DF8C /* RankerTableViewCell.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = RankerTableViewCell.swift; sourceTree = ""; tabWidth = 2; }; 3914D9E5259F3FA1009765B0 /* Message.Model.Messages.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = Message.Model.Messages.swift; path = "Dear-World/Source/Presentation/Scene/Main/Message.Model.Messages.swift"; sourceTree = SOURCE_ROOT; tabWidth = 2; }; + 393E0D3F25A23A12000DB3B9 /* World.Model.Map.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.Model.Map.swift; sourceTree = ""; }; + 393E0D4425A23A7B000DB3B9 /* World.API.Map.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.API.Map.swift; sourceTree = ""; }; 3958257725948E41007325AB /* Dear-World.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Dear-World.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 3958257A25948E41007325AB /* AppDelegate.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; tabWidth = 2; }; 3958258325948E43007325AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -144,7 +147,6 @@ 39E9F7DF25A1BC3C00BC2CC2 /* NoticeBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeBadge.swift; sourceTree = ""; }; 39E9F7E525A1C80300BC2CC2 /* WorldMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorldMap.swift; sourceTree = ""; }; 39E9F7EC25A1C84900BC2CC2 /* WorldMap.Model.Country.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorldMap.Model.Country.swift; sourceTree = ""; }; - 39EED22D259CFEB8007452E1 /* World.Model.Ranker.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = World.Model.Ranker.swift; sourceTree = ""; tabWidth = 2; }; 39EED23B259D00F8007452E1 /* CheeringMapReactor.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = CheeringMapReactor.swift; sourceTree = ""; tabWidth = 2; }; 39EED240259D0227007452E1 /* Revision.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Revision.swift; sourceTree = ""; }; 39F0C1622597B34F00A7001F /* UIView+.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = "UIView+.swift"; sourceTree = ""; tabWidth = 2; }; @@ -469,8 +471,8 @@ isa = PBXGroup; children = ( 39658FBA259AE55C0050D180 /* World.Model.Rank.swift */, - 39EED22D259CFEB8007452E1 /* World.Model.Ranker.swift */, 39658FBF259AE58C0050D180 /* World.Model.Country.swift */, + 393E0D3F25A23A12000DB3B9 /* World.Model.Map.swift */, ); path = Model; sourceTree = ""; @@ -479,6 +481,7 @@ isa = PBXGroup; children = ( 39658FB5259AE5250050D180 /* World.API.Rank.swift */, + 393E0D4425A23A7B000DB3B9 /* World.API.Map.swift */, ); path = API; sourceTree = ""; @@ -733,12 +736,12 @@ 3902F118259704AF00A3DF8C /* AboutViewController.swift in Sources */, 3902F12425970E5600A3DF8C /* Number+.swift in Sources */, 39EED23C259D00F8007452E1 /* CheeringMapReactor.swift in Sources */, + 393E0D4525A23A7B000DB3B9 /* World.API.Map.swift in Sources */, 39F0C18B2598799200A7001F /* Network.swift in Sources */, 3971EB37259A9C550084E6DC /* Message.API.SendMessage.swift in Sources */, 395826122596322B007325AB /* DiscoverViewController.swift in Sources */, 395A4177259DF9F900F10531 /* MainTabBarController.swift in Sources */, 3971EB18259A7BC10084E6DC /* Emoji.swift in Sources */, - 39EED22E259CFEB8007452E1 /* World.Model.Ranker.swift in Sources */, 3902F1132597049D00A3DF8C /* SendMessageViewController.swift in Sources */, 3914D9E6259F3FA1009765B0 /* Message.Model.Messages.swift in Sources */, 39F0C1A02598877600A7001F /* NetworkError.swift in Sources */, @@ -763,6 +766,7 @@ 3971EB24259A7C420084E6DC /* Emoji.Model.Random.swift in Sources */, 39F0C1632597B34F00A7001F /* UIView+.swift in Sources */, 3971EB1F259A7C0E0084E6DC /* Emoji.API.Random.swift in Sources */, + 393E0D4025A23A12000DB3B9 /* World.Model.Map.swift in Sources */, 3902F1052596F26D00A3DF8C /* CheeringMapViewController.swift in Sources */, 39F0C1B72598927C00A7001F /* ErrorView.swift in Sources */, 39672DC12598E95A001D7E69 /* TextView.swift in Sources */, diff --git a/Dear-World/Dear-World/Source/Domain/World Map/Model/WorldMap.Model.Country.swift b/Dear-World/Dear-World/Source/Domain/World Map/Model/WorldMap.Model.Country.swift index c4de4a0..64ce9db 100644 --- a/Dear-World/Dear-World/Source/Domain/World Map/Model/WorldMap.Model.Country.swift +++ b/Dear-World/Dear-World/Source/Domain/World Map/Model/WorldMap.Model.Country.swift @@ -105,7 +105,7 @@ extension WorldMap.Model { Location(x: 20, y: 26), Location(x: 20, y: 27), Location(x: 20, y: 28), - Location(x: 21, y: 26), + Location(x: 21, y: 26) ] ) static let CA: Country = Country( @@ -1155,7 +1155,7 @@ extension WorldMap.Model { Location(x: 40, y: 21), Location(x: 41, y: 16), Location(x: 41, y: 17), - Location(x: 41, y: 18), + Location(x: 41, y: 18) ] ) static let FI: Country = Country( @@ -1170,7 +1170,7 @@ extension WorldMap.Model { Location(x: 43, y: 16), Location(x: 43, y: 17), Location(x: 43, y: 18), - Location(x: 43, y: 19), + Location(x: 43, y: 19) ] ) static let EE: Country = Country( @@ -1582,7 +1582,7 @@ extension WorldMap.Model { Location(x: 51, y: 31), Location(x: 52, y: 29), Location(x: 52, y: 30), - Location(x: 52, y: 31), + Location(x: 52, y: 31) ] ) static let AF: Country = Country( @@ -1678,7 +1678,7 @@ extension WorldMap.Model { Location(x: 60, y: 25), Location(x: 60, y: 26), Location(x: 61, y: 25), - Location(x: 62, y: 25), + Location(x: 62, y: 25) ] ) static let KP: Country = Country( @@ -1737,7 +1737,7 @@ extension WorldMap.Model { name: "Vietnam", locations: [ Location(x: 60, y: 33), - Location(x: 60, y: 34), + Location(x: 60, y: 34) ] ) static let TW: Country = Country( @@ -1746,7 +1746,7 @@ extension WorldMap.Model { locations: [ Location(x: 58, y: 33), Location(x: 58, y: 34), - Location(x: 59, y: 33), + Location(x: 59, y: 33) ] ) static let MY: Country = Country( @@ -1761,7 +1761,7 @@ extension WorldMap.Model { name: "Nepal", locations: [ Location(x: 54, y: 30), - Location(x: 55, y: 30), + Location(x: 55, y: 30) ] ) static let LK: Country = Country( diff --git a/Dear-World/Dear-World/Source/Domain/World/API/World.API.Map.swift b/Dear-World/Dear-World/Source/Domain/World/API/World.API.Map.swift new file mode 100644 index 0000000..055124b --- /dev/null +++ b/Dear-World/Dear-World/Source/Domain/World/API/World.API.Map.swift @@ -0,0 +1,18 @@ +// +// World.API.Map.swift +// Dear-World +// +// Created by dongyoung.lee on 2021/01/04. +// + +import Alamofire +import Foundation + +extension World.API { + struct Map: ServiceAPI { + typealias Response = World.Model.Map + + var method: HTTPMethod { .get } + var path: String { "api/v1/countries/count" } + } +} diff --git a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Country.swift b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Country.swift index 7e4c582..981d1aa 100644 --- a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Country.swift +++ b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Country.swift @@ -24,7 +24,7 @@ extension World.Model { } } } -extension World.Model { +extension World.Model.Country { struct Status: Decodable { let id: Int let messageCount: Int diff --git a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Map.swift b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Map.swift new file mode 100644 index 0000000..58f8d6d --- /dev/null +++ b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Map.swift @@ -0,0 +1,14 @@ +// +// World.Model.Map.swift +// Dear-World +// +// Created by dongyoung.lee on 2021/01/04. +// + +import Foundation + +extension World.Model { + struct Map: Decodable { + let countries: [Country] + } +} diff --git a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Rank.swift b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Rank.swift index 798e2ba..5c24981 100644 --- a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Rank.swift +++ b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Rank.swift @@ -9,6 +9,6 @@ import Foundation extension World.Model { struct Rank: Decodable { - let ranking: [Ranker] + let ranking: [Country] } } diff --git a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Ranker.swift b/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Ranker.swift deleted file mode 100644 index 03fe753..0000000 --- a/Dear-World/Dear-World/Source/Domain/World/Model/World.Model.Ranker.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// World.Model.Ranker.swift -// Dear-World -// -// Created by dongyoung.lee on 2020/12/31. -// - -import Foundation - -extension World.Model { - struct Ranker: Decodable { - let messageCount: Int - let likeCount: Int - let population: Int? - let level: String - let country: Country - } -} diff --git a/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/Cell/RankerTableViewCell.swift b/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/Cell/RankerTableViewCell.swift index 59a95f9..e8145ec 100644 --- a/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/Cell/RankerTableViewCell.swift +++ b/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/Cell/RankerTableViewCell.swift @@ -111,11 +111,11 @@ final class RankerTableViewCell: UITableViewCell { } // MARK: 🔩 Configuration - func configure(with ranker: World.Model.Ranker, ranking: Int) { + func configure(with country: World.Model.Country, ranking: Int) { rankLabel.attributedText = formatRank(ranking) - countryNameLabel.text = ranker.country.name - countryFlagLabel.text = ranker.country.emoji - messageCountLabel.text = ranker.messageCount.formatted + countryNameLabel.text = country.name + countryFlagLabel.text = country.emoji + messageCountLabel.text = country.status?.messageCount.formatted } private func formatRank(_ rank: Int) -> NSAttributedString { diff --git a/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapReactor.swift b/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapReactor.swift index f929583..d14076d 100644 --- a/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapReactor.swift +++ b/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapReactor.swift @@ -18,12 +18,14 @@ final class CheeringMapReactor: Reactor { } enum Mutation { - case setRankers([Model.Ranker]) + case setRankers([Model.Country]) + case setCountries([Model.Country]) } struct State { var messageCount: Int = 100_000 - @Revision var rankers: [Model.Ranker] = [] + @Revision var rankers: [Model.Country] = [] + @Revision var countries: [Model.Country] = [] @Revision var selectedCountries: [Model.Country] = [] } @@ -33,10 +35,16 @@ final class CheeringMapReactor: Reactor { func mutate(action: Action) -> Observable { switch action { case .viewDidLoad: - return Network.request(API.Rank()) - .map { $0?.ranking } - .filterNil() - .map { .setRankers($0) } + return .merge( + Network.request(API.Map()) + .map { $0?.countries } + .filterNil() + .map { .setCountries($0) }, + Network.request(API.Rank()) + .map { $0?.ranking } + .filterNil() + .map { .setRankers($0) } + ) case .tapLikeAt(let index): return .empty() @@ -47,8 +55,11 @@ final class CheeringMapReactor: Reactor { func reduce(state: State, mutation: Mutation) -> State { var newState = currentState switch mutation { - case .setRankers(let rankers): - newState.rankers = rankers + case .setRankers(let countries): + newState.rankers = countries + + case .setCountries(let countries): + newState.countries = countries default: () diff --git a/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapViewController.swift b/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapViewController.swift index fdb19af..4f572b1 100644 --- a/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapViewController.swift +++ b/Dear-World/Dear-World/Source/Presentation/Scene/Cheering Map/CheeringMapViewController.swift @@ -46,6 +46,7 @@ final class CheeringMapViewController: UIViewController, ReactorKit.View { setupUI() } + // MARK: 🔗 Bind func bind(reactor: CheeringMapReactor) { reactor.state .map { $0.messageCount } @@ -64,6 +65,14 @@ final class CheeringMapViewController: UIViewController, ReactorKit.View { cell.cheerUpButton.anchorView = self?.view }.disposed(by: disposeBag) + reactor.state + .distinctUntilChanged(\.$countries) + .map { $0.countries } + .subscribe(onNext: { [weak self] in + self?.worldMapView.drawCountries($0) + }) + .disposed(by: disposeBag) + rankingTableView.rx.didScroll .map { [weak self] in self?.rankingTableView.contentOffset.y } .filterNil() @@ -72,6 +81,9 @@ final class CheeringMapViewController: UIViewController, ReactorKit.View { .subscribe(onNext: { [weak self] y in guard let self = self else { return } self.updateLayouts(y) + if let countries = self.reactor?.currentState.countries { + self.worldMapView.drawCountries(countries) + } }) .disposed(by: disposeBag) diff --git a/Dear-World/Dear-World/Source/Presentation/View/PixelWorldMapView.swift b/Dear-World/Dear-World/Source/Presentation/View/PixelWorldMapView.swift index 925ea67..9c07b5d 100644 --- a/Dear-World/Dear-World/Source/Presentation/View/PixelWorldMapView.swift +++ b/Dear-World/Dear-World/Source/Presentation/View/PixelWorldMapView.swift @@ -16,6 +16,8 @@ final class PixelMapView: UIView { } func drawCountries(_ countries: [Model.Country]) { + layoutIfNeeded() + self.layer.sublayers?.removeAll() countries.forEach { drawCountry($0) } } @@ -55,7 +57,7 @@ final class PixelMapView: UIView { ) let path: UIBezierPath = UIBezierPath( arcCenter: center, - radius: locationSize.width, + radius: locationSize.width / 2, startAngle: CGFloat(0), endAngle: CGFloat(Double.pi * 2), clockwise: true