From c911da1222ed6ce5ec2529fc67b44a34c1af3e31 Mon Sep 17 00:00:00 2001 From: Ryan Nystrom Date: Fri, 19 May 2017 18:21:28 -0400 Subject: [PATCH] setup to add issue cells, title cell working, fixup vc title --- Classes/Issues/IssueCommentDetailCell.swift | 15 ++++++++ Classes/Issues/IssueCommentTextCell.swift | 15 ++++++++ Classes/Issues/IssueImageCell.swift | 14 +++++++ Classes/Issues/IssueReactionsCell.swift | 15 ++++++++ Classes/Issues/IssueTitleCell.swift | 37 +++++++++++++++++++ .../Issues/IssueTitleSectionController.swift | 29 +++++++++++++++ Classes/Issues/IssueViewModels.swift | 23 ++++++++++++ Classes/Issues/IssuesViewController.swift | 14 +++++-- .../Systems/NSAttributedStringSizing.swift | 17 ++++++++- .../RootViewControllers.swift | 1 + Classes/Views/Styles.swift | 1 + Freetime.xcodeproj/project.pbxproj | 32 +++++++++++++++- 12 files changed, 207 insertions(+), 6 deletions(-) create mode 100644 Classes/Issues/IssueCommentDetailCell.swift create mode 100644 Classes/Issues/IssueCommentTextCell.swift create mode 100644 Classes/Issues/IssueImageCell.swift create mode 100644 Classes/Issues/IssueReactionsCell.swift create mode 100644 Classes/Issues/IssueTitleCell.swift create mode 100644 Classes/Issues/IssueTitleSectionController.swift create mode 100644 Classes/Issues/IssueViewModels.swift diff --git a/Classes/Issues/IssueCommentDetailCell.swift b/Classes/Issues/IssueCommentDetailCell.swift new file mode 100644 index 00000000..5e1cc342 --- /dev/null +++ b/Classes/Issues/IssueCommentDetailCell.swift @@ -0,0 +1,15 @@ +// +// IssueCommentDetailCell.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit +import SnapKit +import IGListKit + +final class IssueCommentDetailCell: UICollectionViewCell { + +} diff --git a/Classes/Issues/IssueCommentTextCell.swift b/Classes/Issues/IssueCommentTextCell.swift new file mode 100644 index 00000000..a1ccb0ee --- /dev/null +++ b/Classes/Issues/IssueCommentTextCell.swift @@ -0,0 +1,15 @@ +// +// IssueCommentTextCell.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit +import SnapKit +import IGListKit + +final class IssueCommentTextCell: UICollectionViewCell { + +} diff --git a/Classes/Issues/IssueImageCell.swift b/Classes/Issues/IssueImageCell.swift new file mode 100644 index 00000000..db161a25 --- /dev/null +++ b/Classes/Issues/IssueImageCell.swift @@ -0,0 +1,14 @@ +// +// IssueImageCell.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit +import SnapKit + +final class IssueImageCell: UICollectionViewCell { + +} diff --git a/Classes/Issues/IssueReactionsCell.swift b/Classes/Issues/IssueReactionsCell.swift new file mode 100644 index 00000000..5565c8fb --- /dev/null +++ b/Classes/Issues/IssueReactionsCell.swift @@ -0,0 +1,15 @@ +// +// IssueReactionsCell.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit +import SnapKit +import IGListKit + +final class IssueReactionsCell: UICollectionViewCell { + +} diff --git a/Classes/Issues/IssueTitleCell.swift b/Classes/Issues/IssueTitleCell.swift new file mode 100644 index 00000000..6f0be9ec --- /dev/null +++ b/Classes/Issues/IssueTitleCell.swift @@ -0,0 +1,37 @@ +// +// IssueTitleCell.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit +import SnapKit + +final class IssueTitleCell: UICollectionViewCell { + + static let inset = UIEdgeInsets( + top: Styles.Sizes.rowSpacing, + left: Styles.Sizes.gutter, + bottom: Styles.Sizes.rowSpacing, + right: Styles.Sizes.gutter + ) + + let label = UILabel() + + override init(frame: CGRect) { + super.init(frame: frame) + + label.numberOfLines = 0 + contentView.addSubview(label) + label.snp.makeConstraints { make in + make.edges.equalTo(contentView).inset(IssueTitleCell.inset) + } + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/Classes/Issues/IssueTitleSectionController.swift b/Classes/Issues/IssueTitleSectionController.swift new file mode 100644 index 00000000..5f57316f --- /dev/null +++ b/Classes/Issues/IssueTitleSectionController.swift @@ -0,0 +1,29 @@ +// +// IssueTitleSectionController.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit +import IGListKit + +final class IssueTitleSectionController: IGListGenericSectionController { + + override func sizeForItem(at index: Int) -> CGSize { + guard let context = collectionContext + else { return .zero } + return CGSize(width: context.containerSize.width, height: self.object?.textViewSize.height ?? 0) + } + + override func cellForItem(at index: Int) -> UICollectionViewCell { + guard let context = collectionContext, + let object = self.object, + let cell = context.dequeueReusableCell(of: IssueTitleCell.self, for: self, at: index) as? IssueTitleCell + else { return UICollectionViewCell() } + cell.label.attributedText = object.attributedText + return cell + } + +} diff --git a/Classes/Issues/IssueViewModels.swift b/Classes/Issues/IssueViewModels.swift new file mode 100644 index 00000000..60426df8 --- /dev/null +++ b/Classes/Issues/IssueViewModels.swift @@ -0,0 +1,23 @@ +// +// IssueViewModels.swift +// Freetime +// +// Created by Ryan Nystrom on 5/19/17. +// Copyright © 2017 Ryan Nystrom. All rights reserved. +// + +import UIKit + +func createIssueTitleString(issue: Issue, width: CGFloat) -> NSAttributedStringSizing { + let attributedString = NSAttributedString( + string: issue.title ?? "", + attributes: [ + NSFontAttributeName: Styles.Fonts.headline, + NSForegroundColorAttributeName: Styles.Colors.Gray.dark + ]) + return NSAttributedStringSizing( + containerWidth: width, + attributedText: attributedString, + inset: IssueTitleCell.inset + ) +} diff --git a/Classes/Issues/IssuesViewController.swift b/Classes/Issues/IssuesViewController.swift index ec0fb5f1..7e4c3587 100644 --- a/Classes/Issues/IssuesViewController.swift +++ b/Classes/Issues/IssuesViewController.swift @@ -15,6 +15,7 @@ final class IssuesViewController: UIViewController { fileprivate let owner: String fileprivate let repo: String fileprivate let number: String + fileprivate var issue: Issue? lazy fileprivate var feed: Feed = { Feed(viewController: self, delegate: self) }() init( @@ -28,7 +29,7 @@ final class IssuesViewController: UIViewController { self.repo = repo self.number = number super.init(nibName: nil, bundle: nil) - title = "\(owner)/\(owner)#\(number)" + title = "\(owner)/\(repo)#\(number)" } required init?(coder aDecoder: NSCoder) { @@ -47,10 +48,16 @@ final class IssuesViewController: UIViewController { extension IssuesViewController: IGListAdapterDataSource { func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] { - return [] + guard let issue = self.issue else { return [] } + let width = view.bounds.width + let title = createIssueTitleString(issue: issue, width: width) + return [ title ] } func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController { + if object is NSAttributedStringSizing { + return IssueTitleSectionController() + } return IGListSectionController() } @@ -65,7 +72,8 @@ extension IssuesViewController: FeedDelegate { func loadFromNetwork(feed: Feed) { client.requestIssue(owner: owner, repo: repo, number: number) { result in switch result { - case .success: print("yay") + case .success(let issue): + self.issue = issue case .failure: print("nope") } feed.finishLoading(fromNetwork: true) diff --git a/Classes/Systems/NSAttributedStringSizing.swift b/Classes/Systems/NSAttributedStringSizing.swift index be17b91d..2e1c6db9 100644 --- a/Classes/Systems/NSAttributedStringSizing.swift +++ b/Classes/Systems/NSAttributedStringSizing.swift @@ -7,8 +7,9 @@ // import UIKit +import IGListKit -struct NSAttributedStringSizing { +final class NSAttributedStringSizing: NSObject { let inset: UIEdgeInsets let attributedText: NSAttributedString let textViewSize: CGSize @@ -102,3 +103,17 @@ struct NSAttributedStringSizing { layoutManager.addTextContainer(textContainer) } } + +extension NSAttributedStringSizing: IGListDiffable { + + func diffIdentifier() -> NSObjectProtocol { + return attributedText + } + + func isEqual(toDiffableObject object: IGListDiffable?) -> Bool { + if self === object { return true } + guard let object = object as? NSAttributedStringSizing else { return false } + return textViewSize == object.textViewSize + } + +} diff --git a/Classes/View Controllers/RootViewControllers.swift b/Classes/View Controllers/RootViewControllers.swift index 5eab1264..9183564a 100644 --- a/Classes/View Controllers/RootViewControllers.swift +++ b/Classes/View Controllers/RootViewControllers.swift @@ -29,6 +29,7 @@ func newNotificationsRootViewController(client: GithubClient) -> UIViewControlle let nav = UINavigationController(rootViewController: controller) let title = NSLocalizedString("Notifications", comment: "") controller.navigationItem.title = title + controller.navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil) nav.tabBarItem.title = title nav.tabBarItem.image = UIImage(named: "inbox") return nav diff --git a/Classes/Views/Styles.swift b/Classes/Views/Styles.swift index 3bddb4a2..bc2ad406 100644 --- a/Classes/Views/Styles.swift +++ b/Classes/Views/Styles.swift @@ -27,6 +27,7 @@ struct Styles { static let secondary = UIFont.systemFont(ofSize: 13) static let title = UIFont.boldSystemFont(ofSize: 14) static let button = UIFont.systemFont(ofSize: 17) + static let headline = UIFont.boldSystemFont(ofSize: 22) } struct Colors { diff --git a/Freetime.xcodeproj/project.pbxproj b/Freetime.xcodeproj/project.pbxproj index f1ed88a4..ed50bec8 100644 --- a/Freetime.xcodeproj/project.pbxproj +++ b/Freetime.xcodeproj/project.pbxproj @@ -44,6 +44,13 @@ 298BA0971EC947F100B01946 /* SegmentedControlCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298BA0951EC947F100B01946 /* SegmentedControlCell.swift */; }; 298BA0981EC947F100B01946 /* SegmentedControlSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298BA0961EC947F100B01946 /* SegmentedControlSectionController.swift */; }; 298BA09A1EC947FC00B01946 /* SegmentedControlModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298BA0991EC947FC00B01946 /* SegmentedControlModel.swift */; }; + 299217391ECFA01D00883760 /* IssueCommentDetailCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299217381ECFA01D00883760 /* IssueCommentDetailCell.swift */; }; + 2992173B1ECFA02B00883760 /* IssueCommentTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2992173A1ECFA02B00883760 /* IssueCommentTextCell.swift */; }; + 2992173D1ECFA03800883760 /* IssueTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2992173C1ECFA03800883760 /* IssueTitleCell.swift */; }; + 2992173F1ECFA08600883760 /* IssueReactionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2992173E1ECFA08600883760 /* IssueReactionsCell.swift */; }; + 299217411ECFA09A00883760 /* IssueImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299217401ECFA09A00883760 /* IssueImageCell.swift */; }; + 299217431ECFA2C700883760 /* IssueTitleSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299217421ECFA2C700883760 /* IssueTitleSectionController.swift */; }; + 299217451ECFA41E00883760 /* IssueViewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299217441ECFA41E00883760 /* IssueViewModels.swift */; }; 299F2A121EC3BCF0006CE9D7 /* GithubSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299F2A111EC3BCF0006CE9D7 /* GithubSessionManager.swift */; }; 29A195021EC66B8B00C3E289 /* UIColor+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A195011EC66B8B00C3E289 /* UIColor+Hex.swift */; }; 29A195041EC74C4800C3E289 /* Date+Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29A195031EC74C4800C3E289 /* Date+Display.swift */; }; @@ -162,6 +169,13 @@ 298BA0951EC947F100B01946 /* SegmentedControlCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlCell.swift; sourceTree = ""; }; 298BA0961EC947F100B01946 /* SegmentedControlSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlSectionController.swift; sourceTree = ""; }; 298BA0991EC947FC00B01946 /* SegmentedControlModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedControlModel.swift; sourceTree = ""; }; + 299217381ECFA01D00883760 /* IssueCommentDetailCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueCommentDetailCell.swift; sourceTree = ""; }; + 2992173A1ECFA02B00883760 /* IssueCommentTextCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueCommentTextCell.swift; sourceTree = ""; }; + 2992173C1ECFA03800883760 /* IssueTitleCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueTitleCell.swift; sourceTree = ""; }; + 2992173E1ECFA08600883760 /* IssueReactionsCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueReactionsCell.swift; sourceTree = ""; }; + 299217401ECFA09A00883760 /* IssueImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueImageCell.swift; sourceTree = ""; }; + 299217421ECFA2C700883760 /* IssueTitleSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueTitleSectionController.swift; sourceTree = ""; }; + 299217441ECFA41E00883760 /* IssueViewModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueViewModels.swift; sourceTree = ""; }; 299F2A111EC3BCF0006CE9D7 /* GithubSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubSessionManager.swift; sourceTree = ""; }; 29A195011EC66B8B00C3E289 /* UIColor+Hex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Hex.swift"; sourceTree = ""; }; 29A195031EC74C4800C3E289 /* Date+Display.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Display.swift"; sourceTree = ""; }; @@ -439,9 +453,16 @@ 29C167801ECA4ACC00439D62 /* Issues */ = { isa = PBXGroup; children = ( - 29C167811ECA4B1C00439D62 /* IssueEvent.swift */, - 29316DCE1ECD3442007CAE3F /* IssuesViewController.swift */, 29316DD01ECD358B007CAE3F /* GithubClient+Issues.swift */, + 299217381ECFA01D00883760 /* IssueCommentDetailCell.swift */, + 2992173A1ECFA02B00883760 /* IssueCommentTextCell.swift */, + 29C167811ECA4B1C00439D62 /* IssueEvent.swift */, + 299217401ECFA09A00883760 /* IssueImageCell.swift */, + 2992173E1ECFA08600883760 /* IssueReactionsCell.swift */, + 29316DCE1ECD3442007CAE3F /* IssuesViewController.swift */, + 2992173C1ECFA03800883760 /* IssueTitleCell.swift */, + 299217421ECFA2C700883760 /* IssueTitleSectionController.swift */, + 299217441ECFA41E00883760 /* IssueViewModels.swift */, ); path = Issues; sourceTree = ""; @@ -702,8 +723,10 @@ 29316DCD1ECD31E9007CAE3F /* StatusBar.swift in Sources */, 29C9FDC71EC65FEE00EE3A52 /* Commit.swift in Sources */, 299F2A121EC3BCF0006CE9D7 /* GithubSessionManager.swift in Sources */, + 2992173F1ECFA08600883760 /* IssueReactionsCell.swift in Sources */, 29A195021EC66B8B00C3E289 /* UIColor+Hex.swift in Sources */, 29C167691ECA016500439D62 /* EmptyView.swift in Sources */, + 2992173D1ECFA03800883760 /* IssueTitleCell.swift in Sources */, 29C9FDCB1EC65FEE00EE3A52 /* Label.swift in Sources */, 29A1950A1EC78B4800C3E289 /* NotificationType+Icon.swift in Sources */, 29C9FDD31EC65FEE00EE3A52 /* Repository.swift in Sources */, @@ -712,9 +735,12 @@ 29C9FDD01EC65FEE00EE3A52 /* Permission.swift in Sources */, 29C1676B1ECA0B0A00439D62 /* RepoNotifications+Filter.swift in Sources */, 29316DD11ECD358B007CAE3F /* GithubClient+Issues.swift in Sources */, + 299217431ECFA2C700883760 /* IssueTitleSectionController.swift in Sources */, 290DB4F41ECBF11300CA2790 /* SettingsButtonCell.swift in Sources */, + 299217411ECFA09A00883760 /* IssueImageCell.swift in Sources */, 29C9FDE11EC667AE00EE3A52 /* Styles.swift in Sources */, 297AE87C1EC0D5C200B44A1F /* Secrets.swift in Sources */, + 2992173B1ECFA02B00883760 /* IssueCommentTextCell.swift in Sources */, 29C1677F1ECA1D7300439D62 /* SettingsViewController.swift in Sources */, 298BA08B1EC9031E00B01946 /* RepoNotifications+Notification.swift in Sources */, 29C167821ECA4B1C00439D62 /* IssueEvent.swift in Sources */, @@ -741,6 +767,7 @@ 29A195041EC74C4800C3E289 /* Date+Display.swift in Sources */, 29A195131EC7AD2D00C3E289 /* RepoNotificationsSectionController.swift in Sources */, 298BA0971EC947F100B01946 /* SegmentedControlCell.swift in Sources */, + 299217451ECFA41E00883760 /* IssueViewModels.swift in Sources */, 29316DCB1ECCA581007CAE3F /* SettingsSignoutSectionController.swift in Sources */, 29316DC51ECC9841007CAE3F /* Alamofire+GithubAPI.swift in Sources */, 29316DC91ECCA47E007CAE3F /* SettingsAddAccountSectionController.swift in Sources */, @@ -752,6 +779,7 @@ 29C9FDCA1EC65FEE00EE3A52 /* Issue.swift in Sources */, 297AE87A1EC0D5C200B44A1F /* Authorization.swift in Sources */, 29C1677A1ECA14F700439D62 /* Feed.swift in Sources */, + 299217391ECFA01D00883760 /* IssueCommentDetailCell.swift in Sources */, 29316DB91ECC8483007CAE3F /* GithubSession+IGListDiffable.swift in Sources */, 29C295171EC7BCDA00D46CD2 /* NotificationsViewController.swift in Sources */, 29C9FDD51EC65FEE00EE3A52 /* Self_.swift in Sources */,