From 71150af74acb0e59f834a70695051c7e1505bc82 Mon Sep 17 00:00:00 2001 From: SaltySkip Date: Mon, 19 Mar 2018 18:47:18 +0900 Subject: [PATCH 1/5] finish featured content --- O3.xcodeproj/project.pbxproj | 8 ++ O3/Base.lproj/Main.storyboard | 2 +- O3/Info.plist | Bin 2579 -> 2579 bytes O3/NewsFeed/FeaturedCollectionCell.swift | 23 ++++++ O3/NewsFeed/NewsFeed.storyboard | 93 +++++++++++++++++++++-- O3/NewsFeed/NewsFeedViewController.swift | 86 +++++++++++++++++---- O3/WalletHome/API/O3Client.swift | 29 ++++++- O3/WalletHome/Models/FeatureFeed.swift | 88 +++++++++++++++++++++ 8 files changed, 307 insertions(+), 22 deletions(-) create mode 100644 O3/NewsFeed/FeaturedCollectionCell.swift create mode 100644 O3/WalletHome/Models/FeatureFeed.swift diff --git a/O3.xcodeproj/project.pbxproj b/O3.xcodeproj/project.pbxproj index f953c1b..51e4b54 100644 --- a/O3.xcodeproj/project.pbxproj +++ b/O3.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 350100F5204541A6000F6648 /* SwiftTheme.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 350100F3204541A6000F6648 /* SwiftTheme.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 35051B1C1FFDB10800F9AD30 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35051B151FFDAD9300F9AD30 /* Crashlytics.framework */; }; 35051B1D1FFDB10800F9AD30 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35051B131FFDAD9200F9AD30 /* Fabric.framework */; }; + 35061E47205F5CFE004E89EB /* FeaturedCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35061E46205F5CFE004E89EB /* FeaturedCollectionCell.swift */; }; + 35061E49205F6306004E89EB /* FeatureFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35061E48205F6306004E89EB /* FeatureFeed.swift */; }; 353F364920037062002B4FE1 /* NewsFeed.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 353F364820037062002B4FE1 /* NewsFeed.storyboard */; }; 353F364B200370D6002B4FE1 /* NewsFeedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 353F364A200370D6002B4FE1 /* NewsFeedViewController.swift */; }; 353F364D2003755B002B4FE1 /* NewsFeedCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 353F364C2003755B002B4FE1 /* NewsFeedCell.swift */; }; @@ -175,6 +177,8 @@ 350100F3204541A6000F6648 /* SwiftTheme.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftTheme.framework; path = Carthage/Build/iOS/SwiftTheme.framework; sourceTree = ""; }; 35051B131FFDAD9200F9AD30 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = Carthage/Build/iOS/Fabric.framework; sourceTree = ""; }; 35051B151FFDAD9300F9AD30 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = Carthage/Build/iOS/Crashlytics.framework; sourceTree = ""; }; + 35061E46205F5CFE004E89EB /* FeaturedCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturedCollectionCell.swift; sourceTree = ""; }; + 35061E48205F6306004E89EB /* FeatureFeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFeed.swift; sourceTree = ""; }; 353F364820037062002B4FE1 /* NewsFeed.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NewsFeed.storyboard; sourceTree = ""; }; 353F364A200370D6002B4FE1 /* NewsFeedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsFeedViewController.swift; sourceTree = ""; }; 353F364C2003755B002B4FE1 /* NewsFeedCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsFeedCell.swift; sourceTree = ""; }; @@ -345,6 +349,7 @@ 353F364A200370D6002B4FE1 /* NewsFeedViewController.swift */, 353F364C2003755B002B4FE1 /* NewsFeedCell.swift */, 353F36512003842F002B4FE1 /* NewsItemViewController.swift */, + 35061E46205F5CFE004E89EB /* FeaturedCollectionCell.swift */, ); path = NewsFeed; sourceTree = ""; @@ -385,6 +390,7 @@ 6EA7F9261F6E2F4E00E31B78 /* PriceData.swift */, 6E61BBD01F729D3B00D2B30B /* Money.swift */, 358E95D8200358AA00A1878B /* NewsFeed.swift */, + 35061E48205F6306004E89EB /* FeatureFeed.swift */, ); path = Models; sourceTree = ""; @@ -818,9 +824,11 @@ 752017481F73F30B00090C4F /* UIImage.swift in Sources */, 752017341F72980A00090C4F /* SendCompleteViewController.swift in Sources */, 756AC1941F7FD1B1003BF8F7 /* AddressSelectionCell.swift in Sources */, + 35061E47205F5CFE004E89EB /* FeaturedCollectionCell.swift in Sources */, 75D5BFB41F6CEF2E00E64855 /* OnboardingCollectionCell.swift in Sources */, 35E5F616202ADF1E00D65BEA /* NEP5TokenSelectorTableViewCell.swift in Sources */, 7513FADB1F69541F003450ED /* TransactionsHeaderCell.swift in Sources */, + 35061E49205F6306004E89EB /* FeatureFeed.swift in Sources */, 75CEACE81F66B683005974CE /* SendTableViewController.swift in Sources */, 75E14E571F7D2AEC00BEAE22 /* UIApplication.swift in Sources */, 75179F021F7620E700F4C67F /* Double.swift in Sources */, diff --git a/O3/Base.lproj/Main.storyboard b/O3/Base.lproj/Main.storyboard index a3ff1bd..63ff32e 100644 --- a/O3/Base.lproj/Main.storyboard +++ b/O3/Base.lproj/Main.storyboard @@ -1667,7 +1667,7 @@ - + diff --git a/O3/Info.plist b/O3/Info.plist index 234f298603ee47e1654e1a9faf7afaefabbff7dd..d7ba7c18f855da51008a5c1885bb487fa84545f7 100644 GIT binary patch literal 2579 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 z

h5E9*6WTy--#FhaF&XZe6F8$x8Hsk9hH)bzPX`H)+3xmhZKrQ4+K3Il1S>2i>RV*rm#PxVScv*p_T62excd zlm~vSzzA@+ZPtWFmiC~3$?ToxV-KW$bZmq2>lbw>I_3qS4tXO}t*>T3)^;ALyU~c9>In^o@DwCrJv|fj7KaHyQwW4c`8dWK`I&*_qxB5hZE!~G&Yw_n$rL`X1{2!T@#Op) zn=!~&00DBO5s^>!K!|^K&0UR28aTmo?`zJh3G>y&{+=scU(@MZRi;%Fm>Ik~@Jf#^ zR4{!Ql`5TgD>|0qFzC>)rdDPTHbBWuH`kz+R$bwjr0AV-VU_I3#sA$_MHnRwxAOXm zf{{+`F#W+t8uaJP%#r6YACnsC`|vLnR!Wgq(zRl*_QH^`Fs6tekCD*X)zDegOCPqF zd?5zqIS+++492xD?#^QkLUF|%blAN5E|R}G!v6NzAscorG(Y+TppXOm(2aT&ChW0U9`NPKzp#*31K3#SW_hybVs1P}TB&*c4Ba5B6oybf+bqvR?+?J11a z?5v(VZcElrW8J4AW8}R>>yiF~S7kBYy^xl`%*9)H=n|cPa(zsbaU51IiBd*WLTy-i z#^?|?a%0%(7-Fhn4Vp-nIxe14y}E&O0Z$R~Pr53oceo-bKVAT#`ySp(2D;s)w4DQS zI^Z*jxoS7GW1uR`Nlq9=HLj``BZ%>QL^KAwJ9K!_!dRqty(kHVW!{|D?gY#HFpwIM z7X(gRRhOoX*Tan4uBPRW+QB|YWV7yC#dG6>W~$>_8TO2=Ar?-0?(#S5Qy5kir|wLt zOdUQ#M5ra~FESD=t0;Z9+xn6HcwYiOf@Dj9^DC-=n^QgfZKC$R{YJzVEM$^=F zZmCAa(fxAK(>K^!3t^1+400^bD_z8}3pljRdCTg47Us3aEI-hytmC$4S}ECuf|8-j zFuDd;knGg8{)UMPMe;#`_EEjoVN0ZWtk{9D^Q0yE-}d6nL5eyK0vMF_x%}z5@n3Vj z+F*52@%5t}mmqXgnf@rX!Xw3(bwSTnZF!zACS-sH-){?tb3!xouz!MCx_adBRG9EiNX4) zAv9_+;ld88`T0%8=N7d@pKHLc>n}&LHh&?bVTO+@FDRYNxi`UYkO8N@r}*SnCW~A= z>9oH$#3Nz9uc)eGIV9AS0PcoD3&QkD0p#&KbY?BsHR@3J8tIXJJTmo4b>_@(c`$8$ z5{+*Rq<4Z8?#v0uxoi-<$Z+piI(jcYsh3e3scrFa@4^WP<#4StN{I;z(oFi*K}qi_ zgD)YeXOxyz9!qD+BBYsxV6*=pM!<5HFqSL;%6p?HVd7v4#=6Qa7!gKy8w^6$7+pD- z1YRYp6wt}PFlQhjgKPC5+*QQcRMO5&Z48x%LO$@Ar9oavl`c5j;5mExH$h&YMuV{d zdei&22=L})62CxcH61rCDQpDab=Bs#1vwi#Sp~gete|Q8x-6=BStY~X6jc&WWa#Q3 z_A>vUm^K-;`Vj0{_BdD>b&n?9TFoW~Gj$8`@p@V8&zNK%oj6Tz9HBT=vKtwERHlwM zv$vf~(W(Yw+yo&c_8EaMo+4<%o*p9d87U1)s#%Z3o=N%v+^9ykIa2-|!qJ6={n(Uggo#qBx9~uSteALAXodE2zrQYwyH6;NopjVsp*a7Xakziil$!q+M6kn z#|<6RWk%e=tHr9S3(|qBk>cq8M+@;LpSN!BrTdCqj}A?%Yw6L=PoQ4Y2{XRPuFD0C zPE!E`OksLfpHY9MBHht_3r*vvv(4F)I{v_+pTNTpwj~MkATRL>gGM?^aVOiXm pLf;qoYvTq+b - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -82,21 +161,22 @@ - + + - + @@ -108,7 +188,7 @@ - + @@ -142,5 +222,8 @@ + + + diff --git a/O3/NewsFeed/NewsFeedViewController.swift b/O3/NewsFeed/NewsFeedViewController.swift index d76c23f..2c4db9c 100644 --- a/O3/NewsFeed/NewsFeedViewController.swift +++ b/O3/NewsFeed/NewsFeedViewController.swift @@ -10,9 +10,12 @@ import Foundation import UIKit import Kingfisher -class NewsFeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { +class NewsFeedViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + @IBOutlet weak var newsFeedTableView: UITableView! + @IBOutlet weak var featuredCollectionView: UICollectionView! var feedData: FeedData? + var featureData: FeatureFeed? var urlToLoad = "" func setThemedElements() { @@ -23,27 +26,50 @@ class NewsFeedViewController: UIViewController, UITableViewDelegate, UITableView } + func loadNews() { + O3Client.shared.getFeatures { result in + switch result { + case .failure: + return + case .success(let featureData): + DispatchQueue.main.async { + self.navigationItem.largeTitleDisplayMode = .always + if featureData.features.count == 0 { + self.newsFeedTableView.tableHeaderView?.frame.size = CGSize(width: self.newsFeedTableView.frame.width, height: 0) + } else { + let headerHeight = (self.newsFeedTableView.frame.width * 9 / 16) + 45 + self.newsFeedTableView.tableHeaderView?.frame.size = CGSize(width: self.newsFeedTableView.frame.width, height: headerHeight) + } + } + self.featureData = featureData + O3Client.shared.getNewsFeed { result in + switch result { + case .failure: + return + case .success(let feedData): + self.feedData = feedData + DispatchQueue.main.async { + self.featuredCollectionView.reloadData() + self.newsFeedTableView.reloadData() + } + } + } + } + } + } + override func viewDidLoad() { super.viewDidLoad() setThemedElements() newsFeedTableView.dataSource = self newsFeedTableView.delegate = self + featuredCollectionView.dataSource = self + featuredCollectionView.delegate = self newsFeedTableView.tableFooterView = UIView(frame: .zero) - + self.edgesForExtendedLayout = UIRectEdge.bottom self.navigationController?.hideHairline() - self.navigationItem.largeTitleDisplayMode = .automatic self.navigationItem.title = "News Feed" - O3Client.shared.getNewsFeed { result in - switch result { - case .failure: - return - case .success(let feedData): - self.feedData = feedData - DispatchQueue.main.async { - self.newsFeedTableView.reloadData() - } - } - } + loadNews() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @@ -67,6 +93,38 @@ class NewsFeedViewController: UIViewController, UITableViewDelegate, UITableView self.performSegue(withIdentifier: "segueToNewsItem", sender: nil) } + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return featureData?.features.count ?? 0 + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let featureItem = featureData?.features[indexPath.row] else { + fatalError("Undefined Selection Behavior") + } + if let link = URL(string: featureItem.actionURL) { + UIApplication.shared.open(link) + } + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "featuredCollectionCell", for: indexPath) as? FeaturedCollectionCell, + let featureItem = featureData?.features[indexPath.row] else { + fatalError("Undefined CollectionView Behavior") + } + + cell.featuredImage.kf.setImage(with: URL(string: featureItem.imageURL)) + cell.titleLabel.text = featureItem.title + cell.subtitleLabel.text = featureItem.subtitle + return cell + } + + func collectionView(_ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath) -> CGSize { + let screenSize = UIScreen.main.bounds + return CGSize(width: screenSize.width - 35, height: (newsFeedTableView.frame.width * 9 / 16) + 45) + } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let vc = segue.destination as? NewsItemViewController else { return diff --git a/O3/WalletHome/API/O3Client.swift b/O3/WalletHome/API/O3Client.swift index d8ea24a..a1ce40e 100644 --- a/O3/WalletHome/API/O3Client.swift +++ b/O3/WalletHome/API/O3Client.swift @@ -38,6 +38,7 @@ public class O3Client { case getPriceHistory = "/v1/price/" case getPortfolioValue = "/v1/historical" case getNewsFeed = "/v1/feed/" + case getFeatureFeed = "/v1/features" } enum HTTPMethod: String { @@ -47,8 +48,15 @@ public class O3Client { public static let shared = O3Client() - func sendRequest(_ endpointURL: String, method: HTTPMethod, data: [String: Any?]?, completion: @escaping (O3ClientResult) -> Void) { - let url = URL(string: baseURL + endpointURL) + func sendRequest(_ endpointURL: String, method: HTTPMethod, data: [String: Any?]?, + noBaseURL: Bool = false, completion: @escaping (O3ClientResult) -> Void) { + var urlString = "" + if noBaseURL { + urlString = endpointURL + } else { + urlString = baseURL + endpointURL + } + let url = URL(string: urlString) let request = NSMutableURLRequest(url: url!) request.httpMethod = "GET" request.setValue("application/json-rpc", forHTTPHeaderField: "Content-Type") @@ -152,4 +160,21 @@ public class O3Client { } } } + + func getFeatures(completion: @escaping(O3ClientResult) -> Void) { + let endpoint = "https://s3-ap-northeast-1.amazonaws.com/o3.network/_features/data.json" + sendRequest(endpoint, method: .GET, data: nil, noBaseURL: true) { result in + switch result { + case .failure(let error): + completion(.failure(error)) + case .success(let response): + let decoder = JSONDecoder() + guard let data = try? JSONSerialization.data(withJSONObject: response, options: .prettyPrinted), + let featureFeed = try? decoder.decode(FeatureFeed.self, from: data) else { + return + } + completion(.success(featureFeed)) + } + } + } } diff --git a/O3/WalletHome/Models/FeatureFeed.swift b/O3/WalletHome/Models/FeatureFeed.swift new file mode 100644 index 0000000..ddffb7e --- /dev/null +++ b/O3/WalletHome/Models/FeatureFeed.swift @@ -0,0 +1,88 @@ +// +// FeatureFeed.swift +// O3 +// +// Created by Andrei Terentiev on 3/19/18. +// Copyright © 2018 drei. All rights reserved. +// + +import Foundation + +/* + category": "featured", + "title": "SPOTCOIN PUBLIC SALE", + "subtitle": "SpotCoin delivers high volume fiat to cryptocurrency transaction services.", + "imageURL": "https://cdn.o3.network/featured/this_image_is_16x9.jpg", + "createdAt": "1521100225", + "index": 0, + "actionTitle": "Whitepaper", + "actionURL": "https://www.spotcoin.com/?ref=o3.network" + + + + */ + +public struct FeatureFeed: Codable { + var features: [Item] + + enum CodingKeys: String, CodingKey { + case features + } + + public init(features: [Item]) { + self.features = features + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let features: [Item] = try container.decode([Item].self, forKey: .features) + self.init(features: features) + } + + public struct Item: Codable { + var category: String + var title: String + var subtitle: String + var imageURL: String + var createdAt: Int + var index: Int + var actionTitle: String + var actionURL: String + + enum CodingKeys: String, CodingKey { + case category + case title + case subtitle + case imageURL + case createdAt + case index + case actionTitle + case actionURL + } + + public init(category: String, title: String, subtitle: String, imageURL: String, createdAt: Int, + index: Int, actionTitle: String, actionURL: String) { + self.category = category + self.title = title + self.subtitle = subtitle + self.imageURL = imageURL + self.createdAt = createdAt + self.index = index + self.actionTitle = actionTitle + self.actionURL = actionURL + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let category: String = try container.decode(String.self, forKey: .category) + let title: String = try container.decode(String.self, forKey: .title) + let subtitle: String = try container.decode(String.self, forKey: .subtitle) + let imageURL: String = try container.decode(String.self, forKey: .imageURL) + let createdAt: Int = try container.decode(Int.self, forKey: .createdAt) + let index: Int = try container.decode(Int.self, forKey: .index) + let actionTitle: String = try container.decode(String.self, forKey: .actionTitle) + let actionURL: String = try container.decode(String.self, forKey: .actionURL) + self.init(category: category, title: title, subtitle: title, imageURL: imageURL, createdAt: createdAt, index: index, actionTitle: actionTitle, actionURL: actionURL) + } + } +} From b9e341ca5351458e6b20a322480a2e0c5aa02804 Mon Sep 17 00:00:00 2001 From: andrei Date: Thu, 22 Mar 2018 13:15:33 +0900 Subject: [PATCH 2/5] Update FeatureFeed.swift --- O3/WalletHome/Models/FeatureFeed.swift | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/O3/WalletHome/Models/FeatureFeed.swift b/O3/WalletHome/Models/FeatureFeed.swift index ddffb7e..91b9b7e 100644 --- a/O3/WalletHome/Models/FeatureFeed.swift +++ b/O3/WalletHome/Models/FeatureFeed.swift @@ -8,20 +8,6 @@ import Foundation -/* - category": "featured", - "title": "SPOTCOIN PUBLIC SALE", - "subtitle": "SpotCoin delivers high volume fiat to cryptocurrency transaction services.", - "imageURL": "https://cdn.o3.network/featured/this_image_is_16x9.jpg", - "createdAt": "1521100225", - "index": 0, - "actionTitle": "Whitepaper", - "actionURL": "https://www.spotcoin.com/?ref=o3.network" - - - - */ - public struct FeatureFeed: Codable { var features: [Item] From 5169226278492caeb84d984b53450157b5bb9446 Mon Sep 17 00:00:00 2001 From: Apisit Toompakdee Date: Thu, 22 Mar 2018 18:58:38 +0900 Subject: [PATCH 3/5] refine, inapp-browser with share --- Cartfile | 2 +- Cartfile.resolved | 9 ++-- O3.xcodeproj/project.pbxproj | 8 ++++ O3/NewsFeed/NewsFeed.storyboard | 55 +++++++++++++++--------- O3/NewsFeed/NewsFeedViewController.swift | 38 +++++++++++++--- O3/WalletHome/API/O3Client.swift | 2 +- O3/WalletHome/Models/FeatureFeed.swift | 2 +- 7 files changed, 83 insertions(+), 33 deletions(-) diff --git a/Cartfile b/Cartfile index 9955d51..e1d5774 100644 --- a/Cartfile +++ b/Cartfile @@ -10,4 +10,4 @@ github "hyperoslo/Cache" binary "https://raw.githubusercontent.com/Building42/Specs/master/Carthage/Fabric.json" binary "https://raw.githubusercontent.com/Building42/Specs/master/Carthage/Crashlytics.json" github "jiecao-fm/SwiftTheme" - +github "teambition/WebBrowser" \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved index ea49526..7377c65 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,14 +1,15 @@ -binary "https://raw.githubusercontent.com/Building42/Specs/master/Carthage/Crashlytics.json" "3.9.3" -binary "https://raw.githubusercontent.com/Building42/Specs/master/Carthage/Fabric.json" "1.7.2" +binary "https://raw.githubusercontent.com/Building42/Specs/master/Carthage/Crashlytics.json" "3.10.1" +binary "https://raw.githubusercontent.com/Building42/Specs/master/Carthage/Fabric.json" "1.7.5" github "CityOfZion/neo-swift" "c8a414253b6aaf6fba00abdf070f3321a4d0734c" github "HarshilShah/DeckTransition" "2.0.0" github "ashleymills/Reachability.swift" "v4.1.0" github "hyperoslo/Cache" "4.1.2" github "jiecao-fm/SwiftTheme" "0.4.1" github "kishikawakatsumi/KeychainAccess" "v3.1.0" -github "onevcat/Kingfisher" "4.6.3" +github "onevcat/Kingfisher" "4.6.4" github "philackm/ScrollableGraphView" "4.0.4" github "pkluz/PKHUD" "4.2.3" -github "uias/AutoInsetter" "1.2.1" +github "teambition/WebBrowser" "0.1.2" +github "uias/AutoInsetter" "1.2.2" github "uias/Pageboy" "2.4.0" github "uias/Tabman" "1.6.0" diff --git a/O3.xcodeproj/project.pbxproj b/O3.xcodeproj/project.pbxproj index 51e4b54..22ebd90 100644 --- a/O3.xcodeproj/project.pbxproj +++ b/O3.xcodeproj/project.pbxproj @@ -38,6 +38,9 @@ 35E5F6122029477400D65BEA /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35E5F6112029477400D65BEA /* HomeViewModel.swift */; }; 35E5F614202ADE4300D65BEA /* NativeAssetSelectorTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35E5F613202ADE4300D65BEA /* NativeAssetSelectorTableViewCell.swift */; }; 35E5F616202ADF1E00D65BEA /* NEP5TokenSelectorTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35E5F615202ADF1E00D65BEA /* NEP5TokenSelectorTableViewCell.swift */; }; + 6E0BECC92063B41200FA0A03 /* WebBrowser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E0BECC82063B41200FA0A03 /* WebBrowser.framework */; }; + 6E0BECCA2063B47A00FA0A03 /* WebBrowser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E0BECC82063B41200FA0A03 /* WebBrowser.framework */; }; + 6E0BECCB2063B47A00FA0A03 /* WebBrowser.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6E0BECC82063B41200FA0A03 /* WebBrowser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6E1BBF7F1F77BEE30095F466 /* WalletHomeAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6E1BBF7E1F77BEE30095F466 /* WalletHomeAssets.xcassets */; }; 6E3E381A1FA4436E004965F8 /* FirstTimeLoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E3E38191FA4436E004965F8 /* FirstTimeLoginViewController.swift */; }; 6E3E381C1FA4437A004965F8 /* PreCreateWalletViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E3E381B1FA4437A004965F8 /* PreCreateWalletViewController.swift */; }; @@ -153,6 +156,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 6E0BECCB2063B47A00FA0A03 /* WebBrowser.framework in Embed Frameworks */, 35494574203C02B800332E53 /* Tabman.framework in Embed Frameworks */, 35494572203C01F500332E53 /* Pageboy.framework in Embed Frameworks */, 35494578203C03DC00332E53 /* AutoInsetter.framework in Embed Frameworks */, @@ -197,6 +201,7 @@ 35E5F6112029477400D65BEA /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; 35E5F613202ADE4300D65BEA /* NativeAssetSelectorTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeAssetSelectorTableViewCell.swift; sourceTree = ""; }; 35E5F615202ADF1E00D65BEA /* NEP5TokenSelectorTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NEP5TokenSelectorTableViewCell.swift; sourceTree = ""; }; + 6E0BECC82063B41200FA0A03 /* WebBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebBrowser.framework; path = Carthage/Build/iOS/WebBrowser.framework; sourceTree = ""; }; 6E1BBF7E1F77BEE30095F466 /* WalletHomeAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = WalletHomeAssets.xcassets; sourceTree = ""; }; 6E3E38191FA4436E004965F8 /* FirstTimeLoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstTimeLoginViewController.swift; sourceTree = ""; }; 6E3E381B1FA4437A004965F8 /* PreCreateWalletViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreCreateWalletViewController.swift; sourceTree = ""; }; @@ -309,8 +314,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6E0BECCA2063B47A00FA0A03 /* WebBrowser.framework in Frameworks */, 350100F4204541A6000F6648 /* SwiftTheme.framework in Frameworks */, 35494575203C030A00332E53 /* Tabman.framework in Frameworks */, + 6E0BECC92063B41200FA0A03 /* WebBrowser.framework in Frameworks */, 3549456D203BF1F700332E53 /* Pageboy.framework in Frameworks */, 6E97C4B91F7FCB4000526FF0 /* DeckTransition.framework in Frameworks */, 35051B1C1FFDB10800F9AD30 /* Crashlytics.framework in Frameworks */, @@ -473,6 +480,7 @@ 7575ADB91F6006AB0077007B = { isa = PBXGroup; children = ( + 6E0BECC82063B41200FA0A03 /* WebBrowser.framework */, 350100F3204541A6000F6648 /* SwiftTheme.framework */, 3549458A203FD02B00332E53 /* Cache.framework */, 35494576203C03DC00332E53 /* AutoInsetter.framework */, diff --git a/O3/NewsFeed/NewsFeed.storyboard b/O3/NewsFeed/NewsFeed.storyboard index ed7a5d9..555df86 100644 --- a/O3/NewsFeed/NewsFeed.storyboard +++ b/O3/NewsFeed/NewsFeed.storyboard @@ -14,6 +14,8 @@ Avenir-Book + Avenir-Heavy + Avenir-Medium @@ -26,14 +28,14 @@ - + - + - + @@ -47,20 +49,20 @@ -