Skip to content

Commit

Permalink
Merge pull request insidegui#377 from insidegui/rambo/related-ui
Browse files Browse the repository at this point in the history
Implemented UI for related sessions
  • Loading branch information
bcmn authored May 26, 2018
2 parents fe67f5e + a23b8ca commit 3f0f79a
Show file tree
Hide file tree
Showing 11 changed files with 564 additions and 236 deletions.
16 changes: 16 additions & 0 deletions WWDC.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
DD4648451ECA53A4005C57C6 /* CMSSubscriptionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4648441ECA53A4005C57C6 /* CMSSubscriptionManager.swift */; };
DD4648471ECA5947005C57C6 /* WWDCWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4648461ECA5947005C57C6 /* WWDCWindow.swift */; };
DD4648491ECA5EC0005C57C6 /* NSToolbarItemViewer+Overrides.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4648481ECA5EC0005C57C6 /* NSToolbarItemViewer+Overrides.m */; };
DD4873D320AE5FF3005033CE /* AppCoordinator+RelatedSessions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4873D220AE5FF3005033CE /* AppCoordinator+RelatedSessions.swift */; };
DD4DED611ED6577100624EAF /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD4DED601ED6577100624EAF /* Sparkle.framework */; };
DD4DED641ED6579900624EAF /* Sparkle.framework.dSYM in Carthage: Copy DSYMs */ = {isa = PBXBuildFile; fileRef = DD4DED631ED6579900624EAF /* Sparkle.framework.dSYM */; };
DD4DED681ED6604300624EAF /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD4DED661ED6604300624EAF /* Fabric.framework */; };
Expand Down Expand Up @@ -124,6 +125,9 @@
DD9564231ED27FBE00051D07 /* NSImage+Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9564221ED27FBE00051D07 /* NSImage+Thumbnail.swift */; };
DD9AEFBB20963D3C00EA203F /* StorageMigrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9AEFBA20963D3C00EA203F /* StorageMigrator.swift */; };
DDA5E4941EDCD6E7003B1780 /* WhiteSpinner.car in Resources */ = {isa = PBXBuildFile; fileRef = DDA5E4931EDCD6E7003B1780 /* WhiteSpinner.car */; };
DDA60E1320A90655002EECF5 /* SessionCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA60E1220A90655002EECF5 /* SessionCellView.swift */; };
DDA60E1520A907B6002EECF5 /* SessionCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA60E1420A907B6002EECF5 /* SessionCollectionViewItem.swift */; };
DDA60E1720A9083E002EECF5 /* RelatedSessionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA60E1620A9083E002EECF5 /* RelatedSessionsViewController.swift */; };
DDAE001B1EC52D2B0036C7E9 /* SessionProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAE001A1EC52D2B0036C7E9 /* SessionProgress.swift */; };
DDAE001D1EC534BF0036C7E9 /* TrackColorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAE001C1EC534BF0036C7E9 /* TrackColorView.swift */; };
DDAE7C4D1E5BA4D100CEA205 /* TranscriptsJSONAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAE7C4C1E5BA4D100CEA205 /* TranscriptsJSONAdapter.swift */; };
Expand Down Expand Up @@ -404,6 +408,7 @@
DD4648441ECA53A4005C57C6 /* CMSSubscriptionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CMSSubscriptionManager.swift; sourceTree = "<group>"; };
DD4648461ECA5947005C57C6 /* WWDCWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WWDCWindow.swift; sourceTree = "<group>"; };
DD4648481ECA5EC0005C57C6 /* NSToolbarItemViewer+Overrides.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSToolbarItemViewer+Overrides.m"; sourceTree = "<group>"; };
DD4873D220AE5FF3005033CE /* AppCoordinator+RelatedSessions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+RelatedSessions.swift"; sourceTree = "<group>"; };
DD4DED601ED6577100624EAF /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Carthage/Build/Mac/Sparkle.framework; sourceTree = "<group>"; };
DD4DED631ED6579900624EAF /* Sparkle.framework.dSYM */ = {isa = PBXFileReference; lastKnownFileType = wrapper.dsym; name = Sparkle.framework.dSYM; path = Carthage/Build/Mac/Sparkle.framework.dSYM; sourceTree = "<group>"; };
DD4DED661ED6604300624EAF /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Fabric.framework; sourceTree = "<group>"; };
Expand Down Expand Up @@ -479,6 +484,9 @@
DD9564221ED27FBE00051D07 /* NSImage+Thumbnail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSImage+Thumbnail.swift"; sourceTree = "<group>"; };
DD9AEFBA20963D3C00EA203F /* StorageMigrator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageMigrator.swift; sourceTree = "<group>"; };
DDA5E4931EDCD6E7003B1780 /* WhiteSpinner.car */ = {isa = PBXFileReference; lastKnownFileType = file; name = WhiteSpinner.car; path = Design/WhiteSpinner.car; sourceTree = SOURCE_ROOT; };
DDA60E1220A90655002EECF5 /* SessionCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCellView.swift; sourceTree = "<group>"; };
DDA60E1420A907B6002EECF5 /* SessionCollectionViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCollectionViewItem.swift; sourceTree = "<group>"; };
DDA60E1620A9083E002EECF5 /* RelatedSessionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedSessionsViewController.swift; sourceTree = "<group>"; };
DDAE001A1EC52D2B0036C7E9 /* SessionProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionProgress.swift; sourceTree = "<group>"; };
DDAE001C1EC534BF0036C7E9 /* TrackColorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackColorView.swift; sourceTree = "<group>"; };
DDAE7C4C1E5BA4D100CEA205 /* TranscriptsJSONAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranscriptsJSONAdapter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -790,6 +798,7 @@
DD0159A81ED09F5D00F980F1 /* AppCoordinator+Bookmarks.swift */,
DDF32EB61EBE65930028E39D /* AppCoordinator+UserActivity.swift */,
DDF32EBA1EBE65DD0028E39D /* AppCoordinator+SessionActions.swift */,
DD4873D220AE5FF3005033CE /* AppCoordinator+RelatedSessions.swift */,
DDFA10BE1EBEAAAD001DCF66 /* DownloadManager.swift */,
DD0159FB1ED23F7700F980F1 /* RemoteEnvironment.swift */,
DDB3529D1EC8D8CD00254815 /* main.m */,
Expand Down Expand Up @@ -831,6 +840,8 @@
DDC678181EDB2CD300A4E19C /* ActionLabel.swift */,
DD6E06F31EDBC11F000EAEA4 /* WWDCTextButton.swift */,
DD6E06F51EDBC379000EAEA4 /* WWDCBottomBorderView.swift */,
DDA60E1220A90655002EECF5 /* SessionCellView.swift */,
DDA60E1420A907B6002EECF5 /* SessionCollectionViewItem.swift */,
);
name = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -1022,6 +1033,7 @@
isa = PBXGroup;
children = (
DD7F38791EAC0CE3002D8C00 /* SessionSummaryViewController.swift */,
DDA60E1620A9083E002EECF5 /* RelatedSessionsViewController.swift */,
DDF32EB21EBE5C4D0028E39D /* SessionActionsViewController.swift */,
);
name = Summary;
Expand Down Expand Up @@ -1900,6 +1912,8 @@
DDFA10BF1EBEAAAD001DCF66 /* DownloadManager.swift in Sources */,
DDD930711ED4EF1F00D61BE3 /* Fonts.swift in Sources */,
DD0159A71ECFE26200F980F1 /* DeepLink.swift in Sources */,
DDA60E1720A9083E002EECF5 /* RelatedSessionsViewController.swift in Sources */,
DDA60E1520A907B6002EECF5 /* SessionCollectionViewItem.swift in Sources */,
DD7F38881EAC2275002D8C00 /* PathUtil.swift in Sources */,
DDB352821EC7C55300254815 /* DateProvider.swift in Sources */,
DDC678221EDB956700A4E19C /* BookmarkViewController.swift in Sources */,
Expand All @@ -1915,6 +1929,7 @@
DD0159A91ED09F5D00F980F1 /* AppCoordinator+Bookmarks.swift in Sources */,
DD6E06F41EDBC11F000EAEA4 /* WWDCTextButton.swift in Sources */,
DD7F38621EABD6CF002D8C00 /* SessionsTableViewController.swift in Sources */,
DDA60E1320A90655002EECF5 /* SessionCellView.swift in Sources */,
DDF32EAD1EBE2F9F0028E39D /* SessionRow.swift in Sources */,
DD6E06F81EDBC62D000EAEA4 /* TranscriptTableViewController.swift in Sources */,
DD36A4B01E478C6A00B2EA88 /* AppDelegate.swift in Sources */,
Expand All @@ -1940,6 +1955,7 @@
DD2E27881EAC2CCB0009D7B6 /* ShelfView.swift in Sources */,
DDEDFCF51ED9FF8A002477C8 /* WWDCSegmentedControl.swift in Sources */,
DDF32EB71EBE65930028E39D /* AppCoordinator+UserActivity.swift in Sources */,
DD4873D320AE5FF3005033CE /* AppCoordinator+RelatedSessions.swift in Sources */,
DD382B7C1EAC345F009760C4 /* NSImage+CGImage.m in Sources */,
DDEDFCEF1ED92785002477C8 /* MultipleChoiceFilter.swift in Sources */,
DDEA85FB1EB52AB5002AE0EB /* VideoPlayerViewController.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "2017-06-06T09:20:00-07:00"
argument = "2017-06-05T15:00:00-03:00"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
Expand Down
27 changes: 27 additions & 0 deletions WWDC/AppCoordinator+RelatedSessions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// AppCoordinator+RelatedSessions.swift
// WWDC
//
// Created by Guilherme Rambo on 17/05/18.
// Copyright © 2018 Guilherme Rambo. All rights reserved.
//

import Cocoa

extension AppCoordinator: RelatedSessionsViewControllerDelegate {

func selectSessionOnAppropriateTab(with viewModel: SessionViewModel) {
if ![.video, .session].contains(viewModel.sessionInstance.type) {
// If the related session selected is not a video or regular session, we must be
// on the schedule tab to show it, since the videos tab only shows videos
tabController.activeTab = .schedule
}

currentListController.selectSession(with: viewModel.identifier)
}

func relatedSessionsViewController(_ controller: RelatedSessionsViewController, didSelectSession viewModel: SessionViewModel) {
selectSessionOnAppropriateTab(with: viewModel)
}

}
2 changes: 2 additions & 0 deletions WWDC/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,13 @@ final class AppCoordinator {

videoDetail.shelfController.delegate = self
videoDetail.summaryController.actionsViewController.delegate = self
videoDetail.summaryController.relatedSessionsViewController.delegate = self

let scheduleDetail = scheduleController.detailViewController

scheduleDetail.shelfController.delegate = self
scheduleDetail.summaryController.actionsViewController.delegate = self
scheduleDetail.summaryController.relatedSessionsViewController.delegate = self

videosController.listViewController.delegate = self
scheduleController.listViewController.delegate = self
Expand Down
151 changes: 151 additions & 0 deletions WWDC/RelatedSessionsViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//
// RelatedSessionsViewController.swift
// WWDC
//
// Created by Guilherme Rambo on 13/05/18.
// Copyright © 2018 Guilherme Rambo. All rights reserved.
//

import Cocoa
import RxSwift
import RxCocoa

private extension NSUserInterfaceItemIdentifier {
static let sessionItem = NSUserInterfaceItemIdentifier("sessionCell")
}

protocol RelatedSessionsViewControllerDelegate: class {
func relatedSessionsViewController(_ controller: RelatedSessionsViewController, didSelectSession viewModel: SessionViewModel)
}

final class RelatedSessionsViewController: NSViewController {

init() {
super.init(nibName: nil, bundle: nil)
}

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

struct Metrics {
static let height: CGFloat = 96
static let itemHeight: CGFloat = 64
static let itemWidth: CGFloat = 360
static let padding: CGFloat = 24
}

private let disposeBag = DisposeBag()

var sessions: [SessionViewModel] = [] {
didSet {
collectionView.reloadData()
view.isHidden = sessions.count == 0
}
}

weak var delegate: RelatedSessionsViewControllerDelegate?

override var title: String? {
didSet {
titleLabel.stringValue = title ?? ""
}
}

private lazy var titleLabel: WWDCTextField = {
let l = WWDCTextField(labelWithString: "")
l.cell?.backgroundStyle = .dark
l.lineBreakMode = .byTruncatingTail
l.maximumNumberOfLines = 1
l.translatesAutoresizingMaskIntoConstraints = false
l.textColor = .secondaryText
l.font = .systemFont(ofSize: 20, weight: .semibold)

return l
}()

private lazy var scrollView: NSScrollView = {
let v = NSScrollView(frame: view.bounds)

v.hasHorizontalScroller = true
v.horizontalScroller?.alphaValue = 0

return v
}()

private lazy var collectionView: NSCollectionView = {
var rect = view.bounds
rect.size.height = Metrics.itemHeight

let v = NSCollectionView(frame: rect)

let layout = NSCollectionViewFlowLayout()
layout.itemSize = NSSize(width: Metrics.itemWidth, height: Metrics.itemHeight)
layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = Metrics.padding

v.collectionViewLayout = layout
v.dataSource = self
v.delegate = self
v.autoresizingMask = [.width, .minYMargin]

return v
}()

override func loadView() {
view = NSView(frame: NSRect(x: 0, y: 0, width: 600, height: Metrics.height))
view.wantsLayer = true

scrollView.frame = NSRect(x: 0, y: 0, width: view.bounds.width, height: Metrics.itemHeight)
scrollView.autoresizingMask = [.width, .minYMargin]
view.addSubview(scrollView)
scrollView.documentView = collectionView

view.addSubview(titleLabel)
titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
titleLabel.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
}

override func viewDidLoad() {
super.viewDidLoad()

collectionView.register(SessionCollectionViewItem.self, forItemWithIdentifier: .sessionItem)
}

override func scrollToBeginningOfDocument(_ sender: Any?) {
guard !sessions.isEmpty else { return }

let beginningSet = Set([IndexPath(item: 0, section: 0)])
collectionView.scrollToItems(at: beginningSet, scrollPosition: .leadingEdge)
}

}

extension RelatedSessionsViewController: NSCollectionViewDelegate, NSCollectionViewDataSource {

func numberOfSections(in collectionView: NSCollectionView) -> Int {
return 1
}

func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return sessions.count
}

func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
guard let item = collectionView.makeItem(withIdentifier: .sessionItem, for: indexPath) as? SessionCollectionViewItem else {
return NSCollectionViewItem()
}

item.viewModel = sessions[indexPath.item]
item.onClicked = { [unowned self] viewModel in
self.delegate?.relatedSessionsViewController(self, didSelectSession: viewModel)
}

return item
}

func collectionView(_ collectionView: NSCollectionView, shouldChangeItemsAt indexPaths: Set<IndexPath>, to highlightState: NSCollectionViewItem.HighlightState) -> Set<IndexPath> {
return Set<IndexPath>()
}

}
Loading

0 comments on commit 3f0f79a

Please sign in to comment.