Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clear playlistItems when navigating on YT #2587

Open
wants to merge 14 commits into
base: feature/Playlists
from
Open
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Removed AddedToPlaylist controller. Fixed bugs and added download and…

… swipe to delete.
  • Loading branch information
Brandon-T committed Apr 9, 2020
commit 9f75e1b62a7d689a6b4c94b8600f27aa5c96163e
@@ -80,13 +80,15 @@ struct PlaylistInfo: Decodable {
let src: String
let pageSrc: String
let pageTitle: String
let mimeType: String
var duration: Float

init(name: String, src: String, pageSrc: String, pageTitle: String, duration: Float) {
init(name: String, src: String, pageSrc: String, pageTitle: String, mimeType: String, duration: Float) {
self.name = name
self.src = src
self.pageSrc = pageSrc
self.pageTitle = pageTitle
self.mimeType = mimeType
self.duration = duration
}

@@ -105,6 +107,7 @@ struct PlaylistInfo: Decodable {
self.src = (try? container.decode(String.self, forKey: .src)) ?? ""
self.pageSrc = (try? container.decode(String.self, forKey: .pageSrc)) ?? ""
self.pageTitle = (try? container.decode(String.self, forKey: .pageTitle)) ?? ""
self.mimeType = (try? container.decode(String.self, forKey: .mimeType)) ?? ""
self.duration = (try? container.decode(Float.self, forKey: .duration)) ?? 0.0
}

@@ -113,6 +116,7 @@ struct PlaylistInfo: Decodable {
case src
case pageSrc
case pageTitle
case mimeType
case duration
}
}
@@ -5,225 +5,6 @@
import Foundation
import UIKit

class AddToPlaylistViewController: UIViewController {
private var tabManager: TabManager

private let stackView = UIStackView().then {
$0.isLayoutMarginsRelativeArrangement = true
$0.layoutMargins = UIEdgeInsets(top: 5.0, left: 20.0, bottom: 5.0, right: 20.0)
}

private let infoLabel = UILabel().then {
$0.font = .systemFont(ofSize: 12.0, weight: .regular)
$0.textColor = .white
$0.textAlignment = .center
$0.appearanceTextColor = .white
$0.numberOfLines = 2
$0.text = "Multiple items were found on this page.\nSelect all items you would like to add to playlist."
}

private let separator = UIView().then {
$0.backgroundColor = #colorLiteral(red: 0.5176470588, green: 0.5411764706, blue: 0.568627451, alpha: 1)
}

private var tableView = UITableView(frame: .zero, style: .grouped)
private var footerButton = UIButton().then {
$0.setTitle("Add Item(s) to Playlist", for: .normal)
$0.backgroundColor = #colorLiteral(red: 0, green: 0.6666666667, blue: 1, alpha: 1)
$0.titleLabel?.font = .systemFont(ofSize: 14.0, weight: .medium)
$0.isHidden = true
}
private var footerStackView = UIStackView().then {
$0.axis = .vertical
}

private var playlistItems = [PlaylistInfo]()
private var checkedItems = [Bool]()
private var isSelectingAll = true

init(tabManager: TabManager) {
self.tabManager = tabManager
super.init(nibName: nil, bundle: nil)
}

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

override func viewDidLoad() {
super.viewDidLoad()

title = "Add to Playlist"
navigationController?.navigationBar.tintColor = #colorLiteral(red: 0, green: 0.6666666667, blue: 1, alpha: 1)
navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.barTintColor = #colorLiteral(red: 0.231372549, green: 0.2431372549, blue: 0.3137254902, alpha: 1)
navigationController?.navigationBar.appearanceBarTintColor = #colorLiteral(red: 0.231372549, green: 0.2431372549, blue: 0.3137254902, alpha: 1)
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Select All", style: .plain, target: self, action: #selector(onSelectAll(_:)))

navigationController?.navigationBar.titleTextAttributes = [
.foregroundColor: UIColor.white,
.font: UIFont.systemFont(ofSize: 17.0, weight: .medium)
]

view.backgroundColor = #colorLiteral(red: 0.231372549, green: 0.2431372549, blue: 0.3137254902, alpha: 1)

tableView.backgroundView = UIView()
tableView.backgroundColor = #colorLiteral(red: 0.231372549, green: 0.2431372549, blue: 0.3137254902, alpha: 1)
tableView.appearanceBackgroundColor = #colorLiteral(red: 0.231372549, green: 0.2431372549, blue: 0.3137254902, alpha: 1)
tableView.separatorColor = .clear
tableView.appearanceSeparatorColor = .clear

tableView.register(PlaylistSelectionCell.self, forCellReuseIdentifier: "PlaylistSelectionCell")
tableView.dataSource = self
tableView.delegate = self

view.addSubview(tableView)
view.addSubview(stackView)
view.addSubview(separator)
view.addSubview(footerStackView)
stackView.addArrangedSubview(infoLabel)
footerStackView.addArrangedSubview(footerButton)

stackView.snp.makeConstraints {
$0.leading.trailing.top.equalTo(view.safeAreaLayoutGuide)
$0.height.equalTo(40.0)
}

separator.snp.makeConstraints {
$0.top.equalTo(stackView.snp.bottom).offset(10.0)
$0.left.right.equalToSuperview()
$0.height.equalTo(1.0 / UIScreen.main.scale)
}

tableView.snp.makeConstraints {
$0.edges.equalTo(view.safeArea.edges)
}

footerStackView.snp.makeConstraints {
$0.left.right.bottom.equalTo(view.safeAreaLayoutGuide)
$0.height.equalTo(42.0)
}

//tableView.contentInsetAdjustmentBehavior = .never
tableView.contentInset = UIEdgeInsets(top: 50.0, left: 0.0, bottom: 0.0, right: 0.0)
tableView.contentOffset = CGPoint(x: 0.0, y: -50.0)

tabManager.tabsForCurrentMode.forEach({
$0.playlistItems.observe { [weak self] _, _ in
guard let self = self else { return }
self.updateItems()
}.bind(to: self)
})

footerButton.addTarget(self, action: #selector(onAddItemsToPlaylist(_:)), for: .touchUpInside)
}

private func updateItems() {
playlistItems = tabManager.tabsForCurrentMode.map({ $0.playlistItems }).flatMap({ $0.value })
checkedItems = [Bool](repeating: false, count: playlistItems.count)
footerButton.isHidden = true
}

@objc
private func onSelectAll(_ button: UIBarButtonItem) {
for i in 0..<checkedItems.count {
checkedItems[i] = isSelectingAll
}

if isSelectingAll {
footerButton.isHidden = false
footerButton.setTitle("Add \(playlistItems.count) Item(s) to Playlist", for: .normal)
} else {
footerButton.isHidden = true
footerButton.setTitle("Add Item(s) to Playlist", for: .normal)
}

isSelectingAll.toggle()
navigationItem.rightBarButtonItem = UIBarButtonItem(title: isSelectingAll ? "Select All" : "Deselect All", style: .plain, target: self, action: #selector(onSelectAll(_:)))
tableView.reloadData()
}

@objc
private func onAddItemsToPlaylist(_ button: UIButton) {
let group = DispatchGroup()

playlistItems.forEach({
group.enter()
Playlist.shared.addItem(item: $0, completion: {
group.leave()
})
})

group.notify(queue: .main) {
self.tabManager.tabsForCurrentMode.forEach({
$0.playlistItems.value.removeAll(where: {
Playlist.shared.itemExists(item: $0)
})
})

let playlistController = PlaylistViewController(tabManager: self.tabManager)
self.present(playlistController, animated: true, completion: nil)
}
}
}

extension AddToPlaylistViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return playlistItems.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 45.0
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return .leastNormalMagnitude
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "PlaylistSelectionCell", for: indexPath) as? PlaylistSelectionCell else {
return UITableViewCell()
}

let item = self.playlistItems[indexPath.row]

cell.selectionStyle = .none
cell.thumbnailView.image = #imageLiteral(resourceName: "shields-menu-icon")
cell.titleLabel.text = item.name
cell.detailLabel.text = String(format: "%.2f mins", item.duration / 60.0)
cell.contentView.backgroundColor = .clear
cell.backgroundColor = .clear

cell.thumbnailView.setFavicon(forSite: .init(url: item.pageSrc, title: item.pageTitle))
cell.checkedIcon.isHidden = !checkedItems[indexPath.row]

return cell
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return UIView()
}
}

extension AddToPlaylistViewController: UITableViewDelegate {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
checkedItems[indexPath.row].toggle()
tableView.reloadRows(at: [indexPath], with: .automatic)

let countOfCheckedItems = checkedItems.filter({ $0 }).count
footerButton.isHidden = countOfCheckedItems == 0
footerButton.setTitle("Add \(countOfCheckedItems) Item(s) to Playlist", for: .normal)
}
}

public class PlaylistSelectionCell: UITableViewCell {

public let thumbnailView = UIImageView().then {
@@ -15,7 +15,7 @@ class Playlist {

public var currentlyPlayingInfo: PlaylistInfo?

func addItem(item: PlaylistInfo, completion: @escaping () -> Void) {
func addItem(item: PlaylistInfo, cachedData: Data?, completion: @escaping () -> Void) {
if !self.itemExists(item: item) {
self.backgroundContext.perform { [weak self] in
guard let self = self else { return }
@@ -25,11 +25,12 @@ class Playlist {
playlistItem.pageTitle = item.pageTitle
playlistItem.pageSrc = item.pageSrc
playlistItem.dateAdded = Date()
playlistItem.cachedData = (try? Data(contentsOf: URL(string: item.src)!)) ?? Data()
playlistItem.cachedData = cachedData ?? Data()
playlistItem.duration = item.duration
playlistItem.mimeType = item.mimeType
playlistItem.mediaSrc = item.src

self.saveContext(self.backgroundContext)

completion()
}
} else {
@@ -80,7 +81,7 @@ class Playlist {
func getItems() -> [PlaylistInfo] {
let request: NSFetchRequest<PlaylistItem> = PlaylistItem.fetchRequest()
return (try? self.mainContext.fetch(request))?.map({
return PlaylistInfo(name: $0.name, src: "", pageSrc: $0.pageSrc, pageTitle: $0.pageTitle, duration: $0.duration)
return PlaylistInfo(name: $0.name, src: $0.mediaSrc, pageSrc: $0.pageSrc, pageTitle: $0.pageTitle, mimeType: $0.mimeType, duration: $0.duration)
}) ?? []
}

@@ -91,6 +92,15 @@ class Playlist {
return (try? self.mainContext.fetch(request))?.first?.cachedData ?? Data()
}

func updateCache(item: PlaylistInfo, cachedData: Data) {
let request: NSFetchRequest<PlaylistItem> = PlaylistItem.fetchRequest()
request.predicate = NSPredicate(format: "pageSrc == %@", item.pageSrc)
request.fetchLimit = 1

(try? self.mainContext.fetch(request))?.first?.cachedData = cachedData
self.saveContext(self.mainContext)
}

func itemExists(item: PlaylistInfo) -> Bool {
let request: NSFetchRequest<PlaylistItem> = PlaylistItem.fetchRequest()
request.predicate = NSPredicate(format: "pageSrc == %@", item.pageSrc)
@@ -1,14 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="19D76" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="16119" systemVersion="19E266" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="PlaylistItem" representedClassName="PlaylistItem" syncable="YES" codeGenerationType="class">
<attribute name="cachedData" attributeType="Binary"/>
<attribute name="dateAdded" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="duration" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="mediaSrc" attributeType="String"/>
<attribute name="mimeType" attributeType="String"/>
<attribute name="name" attributeType="String"/>
<attribute name="pageSrc" attributeType="String"/>
<attribute name="pageTitle" optional="YES" attributeType="String"/>
</entity>
<elements>
<element name="PlaylistItem" positionX="-63" positionY="-18" width="128" height="133"/>
<element name="PlaylistItem" positionX="-63" positionY="-18" width="128" height="163"/>
</elements>
</model>
@@ -18,5 +18,6 @@ extension PlaylistItem {
@NSManaged public var dateAdded: Date
@NSManaged public var cachedData: Data
@NSManaged public var duration: Float

@NSManaged public var mimeType: String
@NSManaged public var mediaSrc: String
}
@@ -65,7 +65,7 @@ class PlaylistMultipleSelectionController: UIViewController {

playlistItems.forEach({
group.enter()
Playlist.shared.addItem(item: $0, completion: {
Playlist.shared.addItem(item: $0, cachedData: nil, completion: {
group.leave()
})
})
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.