add rough comment to episode detail
MODIFY
Podcast.xcodeproj/project.pbxproj
Podcast.xcodeproj/project.pbxproj
420BC2DE1E9C8E650096A9A0 /* EpisodeDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 420BC2DD1E9C8E650096A9A0 /* EpisodeDetailViewController.swift */; };
420BC2E01E9D4B900096A9A0 /* EpisodeDetailHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 420BC2DF1E9D4B900096A9A0 /* EpisodeDetailHeaderView.swift */; };
421501271D9F5FE1002839D1 /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421501261D9F5FE1002839D1 /* Player.swift */; };
+ 422575171E9DEDE10071E419 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422575161E9DEDE10071E419 /* Comment.swift */; };
+ 422575191E9DF0260071E419 /* CommentsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 422575181E9DF0260071E419 /* CommentsTableViewCell.swift */; };
+ 4225751B1E9E71630071E419 /* CommentsTableViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4225751A1E9E71630071E419 /* CommentsTableViewHeader.swift */; };
4253114D1E5E4CC500DF06F6 /* MiniPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4253114C1E5E4CC500DF06F6 /* MiniPlayerView.swift */; };
425B393D1E512F5D00283CA4 /* PlayerControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425B393C1E512F5D00283CA4 /* PlayerControlsView.swift */; };
425C90621E5A5827004BB7AD /* PlayerEpisodeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425C90611E5A5827004BB7AD /* PlayerEpisodeDetailView.swift */; };
420BC2DD1E9C8E650096A9A0 /* EpisodeDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EpisodeDetailViewController.swift; sourceTree = "<group>"; };
420BC2DF1E9D4B900096A9A0 /* EpisodeDetailHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EpisodeDetailHeaderView.swift; sourceTree = "<group>"; };
421501261D9F5FE1002839D1 /* Player.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Player.swift; sourceTree = "<group>"; };
+ 422575161E9DEDE10071E419 /* Comment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = "<group>"; };
+ 422575181E9DF0260071E419 /* CommentsTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentsTableViewCell.swift; sourceTree = "<group>"; };
+ 4225751A1E9E71630071E419 /* CommentsTableViewHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentsTableViewHeader.swift; sourceTree = "<group>"; };
4253114C1E5E4CC500DF06F6 /* MiniPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MiniPlayerView.swift; sourceTree = "<group>"; };
425B393C1E512F5D00283CA4 /* PlayerControlsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerControlsView.swift; sourceTree = "<group>"; };
425C90611E5A5827004BB7AD /* PlayerEpisodeDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerEpisodeDetailView.swift; sourceTree = "<group>"; };
D360AB891E6F80400036B051 /* SeriesGridCollectionViewCell.swift */,
FDE8D6EC1E6FAB2F00DF7548 /* InternalProfileTableViewCell.swift */,
D3B9A0591E861EB800B634FF /* ListeningHistoryTableViewCell.swift */,
+ 422575181E9DF0260071E419 /* CommentsTableViewCell.swift */,
);
name = Cells;
sourceTree = "<group>";
D354024D1E67C224008B8A0C /* SearchSeries.swift */,
D354024F1E67C5C4008B8A0C /* Session.swift */,
D353AF361E8F5CBF003B3D88 /* SubscriptionSeries.swift */,
+ 422575161E9DEDE10071E419 /* Comment.swift */,
);
name = Models;
sourceTree = "<group>";
443ED30C1E745C5D001CFFF5 /* PlayButton.swift */,
D30D374A1E76082700E9260B /* TagTableViewHeader.swift */,
420BC2DF1E9D4B900096A9A0 /* EpisodeDetailHeaderView.swift */,
+ 4225751A1E9E71630071E419 /* CommentsTableViewHeader.swift */,
);
name = Views;
sourceTree = "<group>";
447DA8621E5C99790002BCA0 /* RecommendedTagsCollectionViewCell.swift in Sources */,
D30761721E8D9DE30047EA6F /* FetchEpisodesBySeriesIdEndpointRequest.swift in Sources */,
D357FB4D1E5105AA00C71857 /* CardTableViewCell.swift in Sources */,
+ 422575171E9DEDE10071E419 /* Comment.swift in Sources */,
443ED3111E78E908001CFFF5 /* SearchAllEndpointRequest.swift in Sources */,
9568DFE11E5F5ADD006D4131 /* TabBarAccessoryViewController.swift in Sources */,
D3DB5A681DA1B19800E550E8 /* PodcastCollectionViewFlowLayout.swift in Sources */,
447DA8661E5C99810002BCA0 /* RecommendedSeriesCollectionViewFlowLayout.swift in Sources */,
FD8F7DFE1DDD36D600DCC511 /* ProfileSectionHeaderView.swift in Sources */,
+ 4225751B1E9E71630071E419 /* CommentsTableViewHeader.swift in Sources */,
44D0EA951E6C8F3C00C3339B /* SearchTagTableViewCell.swift in Sources */,
FDD71F341E801BBE0060BBB0 /* BookmarkTableViewCell.swift in Sources */,
956D85141E51926800D95F7A /* EndpointRequestQueue.swift in Sources */,
95FD28F61E77AF8800A52506 /* UpdateSessionEndpointRequest.swift in Sources */,
D307616C1E8CCA000047EA6F /* CreateUserSubscriptioEndpointRequest.swift in Sources */,
44AA26091E842F2A00C74FAD /* SearchEndpointRequest.swift in Sources */,
+ 422575191E9DF0260071E419 /* CommentsTableViewCell.swift in Sources */,
D353AF371E8F5CBF003B3D88 /* SubscriptionSeries.swift in Sources */,
D354024E1E67C224008B8A0C /* SearchSeries.swift in Sources */,
447DA85C1E5C996E0002BCA0 /* RecommendedEpisodesOuterTableViewCell.swift in Sources */,

MODIFY
Podcast/BookmarkViewController.swift
Podcast/BookmarkViewController.swift
@@ -80,9 +80,9 @@ class BookmarkViewController: UIViewController, UITableViewDelegate, UITableView
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-// guard let cell = bookmarkTableView.cellForRow(at: indexPath) as? BookmarkTableViewCell else { return }
-
- // Open Episode Detail View here
+ let episodeViewController = EpisodeDetailViewController()
+ episodeViewController.episode = episodes[indexPath.row]
+ navigationController?.pushViewController(episodeViewController, animated: true)
}

MODIFY
Podcast/EpisodeDetailHeaderView.swift
Podcast/EpisodeDetailHeaderView.swift
@@ -15,6 +15,8 @@ class EpisodeDetailHeaderView: UIView {
var episodeTitleLabel: UILabel!
var dateLabel: UILabel!
var descriptionLabel: UILabel!
+ var playButton: PlayButton!
+ // TODO: likeButton, bookmarkButton, moreButton
let marginSpacing: CGFloat = 18
let artworkDimension: CGFloat = 79
@@ -31,11 +33,16 @@ class EpisodeDetailHeaderView: UIView {
let dateLabelYSpacing: CGFloat = 6
let descriptionLabelYSpacing: CGFloat = 6
+
+ let playButtonYSpacing: CGFloat = 24
+ let playButtonWidth: CGFloat = 47
+ let playButtonHeight: CGFloat = 18
+
let bottomSpacing: CGFloat = 20
override init(frame: CGRect) {
super.init(frame: frame)
- backgroundColor = .white
+ backgroundColor = UIColor.colorFromCode(0xfcfcfe)
episodeArtworkImageView = UIImageView(frame: CGRect(x: marginSpacing,
y: marginSpacing,
@@ -75,6 +82,9 @@ class EpisodeDetailHeaderView: UIView {
descriptionLabel.lineBreakMode = .byWordWrapping
descriptionLabel.numberOfLines = 0
addSubview(descriptionLabel)
+
+ playButton = PlayButton(frame: CGRect(x: marginSpacing, y: 0, width: playButtonWidth, height: playButtonHeight))
+ addSubview(playButton)
}
required init?(coder aDecoder: NSCoder) {
@@ -82,9 +92,8 @@ class EpisodeDetailHeaderView: UIView {
}
func setupForEpisode(episode: Episode) {
- // TODO: load from URL
episodeArtworkImageView.image = #imageLiteral(resourceName: "filler_image")
- if let url = episode.smallArtworkImageURL {
+ if let url = episode.largeArtworkImageURL {
if let data = try? Data(contentsOf: url) {
episodeArtworkImageView.image = UIImage(data: data)
}
@@ -101,13 +110,14 @@ class EpisodeDetailHeaderView: UIView {
episodeTitleLabel.text = episode.title
episodeTitleLabel.sizeToFit()
- dateLabel.text = episode.dateTimeSeriesString()
+ dateLabel.text = episode.dateString()
dateLabel.sizeToFit()
dateLabel.frame.origin.y = episodeTitleLabel.frame.maxY + dateLabelYSpacing
descriptionLabel.text = episode.descriptionText
descriptionLabel.sizeToFit()
descriptionLabel.frame.origin.y = dateLabel.frame.maxY + descriptionLabelYSpacing
- frame.size.height = descriptionLabel.frame.maxY + bottomSpacing
+ playButton.frame.origin.y = descriptionLabel.frame.maxY + playButtonYSpacing
+ frame.size.height = playButton.frame.maxY + bottomSpacing
}
}

MODIFY
Podcast/EpisodeDetailViewController.swift
Podcast/EpisodeDetailViewController.swift
import UIKit
-class EpisodeDetailViewController: UIViewController {
+class EpisodeDetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
+ var scrollView: UIScrollView!
var episodeDetailHeaderView: EpisodeDetailHeaderView!
var episode: Episode?
+ var commentsTableViewHeader: CommentsTableViewHeader!
+ var commentsTableView: UITableView!
+ var comments: [Comment] = Array.init(repeating: Comment(episodeId: "", creator: "Mark Bryan", text: "Great point here!!", creationDate: "5 months ago", time: "5:13"), count: 10)
override func viewDidLoad() {
super.viewDidLoad()
- view.backgroundColor = .white
+ scrollView = UIScrollView(frame: view.frame)
+ scrollView.backgroundColor = .white
+ scrollView.contentSize = CGSize(width: view.frame.width, height: 0)
+ view.addSubview(scrollView)
- episodeDetailHeaderView = EpisodeDetailHeaderView(frame: CGRect(x: 0, y: navigationController?.navigationBar.frame.maxY ?? 0, width: self.view.frame.width, height: 0))
- view.addSubview(episodeDetailHeaderView)
+ episodeDetailHeaderView = EpisodeDetailHeaderView(frame: CGRect(x: 0, y: 0, width: scrollView.frame.width, height: 0))
+ scrollView.addSubview(episodeDetailHeaderView)
+
+ commentsTableViewHeader = CommentsTableViewHeader(frame: CGRect(x: 0, y: 0, width: scrollView.frame.width, height: 0))
+ scrollView.addSubview(commentsTableViewHeader)
+
+ commentsTableView = UITableView(frame: .zero)
+ commentsTableView.dataSource = self
+ commentsTableView.delegate = self
+ commentsTableView.register(CommentsTableViewCell.self, forCellReuseIdentifier: "CommentsTableViewCellIdentifier")
+ scrollView.addSubview(commentsTableView)
}
override func viewWillAppear(_ animated: Bool) {
guard let episode = episode else { return }
episodeDetailHeaderView.setupForEpisode(episode: episode)
+ commentsTableViewHeader.frame.origin = CGPoint(x: 0, y: episodeDetailHeaderView.frame.maxY)
+ commentsTableView.frame = CGRect(x: 0, y: commentsTableViewHeader.frame.maxY, width: scrollView.frame.width, height: 300)
+ scrollView.contentSize.height = commentsTableView.frame.maxY
+ }
+
+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ guard let cell = tableView.dequeueReusableCell(withIdentifier: "CommentsTableViewCellIdentifier") as? CommentsTableViewCell else { return UITableViewCell() }
+ cell.setupForComment(comment: comments[indexPath.row])
+ commentsTableView.rowHeight = cell.frame.height
+ return cell
+ }
+
+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+ return comments.count
}
}

MODIFY
Podcast/PlayButton.swift
Podcast/PlayButton.swift
@@ -10,8 +10,12 @@ import UIKit
class PlayButton: UIButton {
- init() {
- super.init(frame: .zero)
+ convenience init() {
+ self.init(frame: .zero)
+ }
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
setImage(#imageLiteral(resourceName: "play_feed_icon"), for: .normal)
setImage(#imageLiteral(resourceName: "play_feed_icon_selected"), for: .selected)
setTitle(" Play", for: .normal)

MODIFY
Podcast/PlayerEpisodeDetailView.swift
Podcast/PlayerEpisodeDetailView.swift
@@ -72,7 +72,7 @@ class PlayerEpisodeDetailView: UIView {
episodeArtworkImageView.image = #imageLiteral(resourceName: "sample_series_artwork")
seriesTitleLabel.text = episode.seriesTitle
episodeTitleLabel.text = episode.title
- dateLabel.text = episode.dateTimeSeriesString()
+ dateLabel.text = episode.dateString()
descriptionLabel.text = episode.descriptionText
layoutUI()
}

add rough comment to episode detail