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

Playlists work from demo.

  • Loading branch information
Brandon-T committed Mar 25, 2020
commit 8b957c7f0a68d3d1fd868d06f15768e6dbff3f3c
@@ -684,6 +684,8 @@
5E0FCD23234253DC00AC831E /* CertificatePinning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E0FCD22234253DC00AC831E /* CertificatePinning.swift */; };
5E0FCD252342544C00AC831E /* URLSession+Requests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E0FCD242342544C00AC831E /* URLSession+Requests.swift */; };
5E22D0792418C9170005D8C5 /* AddToPlaylistViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E22D0782418C9170005D8C5 /* AddToPlaylistViewController.swift */; };
5E22D0812418DBEF0005D8C5 /* PlaylistManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E22D07F2418DBEE0005D8C5 /* PlaylistManager.swift */; };
5E2DF91D24194779000A8943 /* PlaylistCacheLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E2DF91C24194779000A8943 /* PlaylistCacheLoader.swift */; };
5E3477E922D7771700B0D5F8 /* ResourceDownloader.js in Resources */ = {isa = PBXBuildFile; fileRef = 5E3477E822D7771700B0D5F8 /* ResourceDownloader.js */; };
5E34781022D7A1D200B0D5F8 /* ResourceDownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E34780F22D7A1D200B0D5F8 /* ResourceDownloadManager.swift */; };
5E46C371234FACC600ACA8C1 /* root.cer in Resources */ = {isa = PBXBuildFile; fileRef = 5E46C36D234FACC600ACA8C1 /* root.cer */; };
@@ -701,7 +703,6 @@
5E612A90234B7FCD007D12B5 /* OnboardingRewardsAgreementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E1D8C6C232BF9C200BDE662 /* OnboardingRewardsAgreementView.swift */; };
5E6683A923D61CF7005B3A6C /* NTPDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6683A823D61CF7005B3A6C /* NTPDownloader.swift */; };
5E6B9A3D239573D100E6720C /* Playlist.js in Resources */ = {isa = PBXBuildFile; fileRef = 5E6B9A3C239573D100E6720C /* Playlist.js */; };
5E6B9A402395752300E6720C /* PlaylistManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6B9A3F2395752300E6720C /* PlaylistManager.swift */; };
5E6B9A4223957DB800E6720C /* PlaylistViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6B9A4123957DB800E6720C /* PlaylistViewController.swift */; };
5E77F9A8236B362800E1649C /* DeviceCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E856FE7235E083B0094E113 /* DeviceCheck.swift */; };
5E77F9AA236B362E00E1649C /* Cryptography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E856FE5235E08110094E113 /* Cryptography.swift */; };
@@ -2193,6 +2194,8 @@
5E1D8C6C232BF9C200BDE662 /* OnboardingRewardsAgreementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingRewardsAgreementView.swift; sourceTree = "<group>"; };
5E1D8C6E232C0BDB00BDE662 /* onboarding-rewards.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "onboarding-rewards.json"; sourceTree = "<group>"; };
5E22D0782418C9170005D8C5 /* AddToPlaylistViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddToPlaylistViewController.swift; sourceTree = "<group>"; };
5E22D07F2418DBEE0005D8C5 /* PlaylistManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PlaylistManager.swift; path = Client/Frontend/Browser/PlaylistManager.swift; sourceTree = SOURCE_ROOT; };
5E2DF91C24194779000A8943 /* PlaylistCacheLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistCacheLoader.swift; sourceTree = "<group>"; };
5E3477E822D7771700B0D5F8 /* ResourceDownloader.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = ResourceDownloader.js; sourceTree = "<group>"; };
5E34780F22D7A1D200B0D5F8 /* ResourceDownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceDownloadManager.swift; sourceTree = "<group>"; };
5E46C36D234FACC600ACA8C1 /* root.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = root.cer; sourceTree = "<group>"; };
@@ -2206,7 +2209,6 @@
5E4845C122DE3DF800372022 /* WindowRenderHelperScript.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowRenderHelperScript.swift; sourceTree = "<group>"; };
5E6683A823D61CF7005B3A6C /* NTPDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NTPDownloader.swift; sourceTree = "<group>"; };
5E6B9A3C239573D100E6720C /* Playlist.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Playlist.js; sourceTree = "<group>"; };
5E6B9A3F2395752300E6720C /* PlaylistManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistManager.swift; sourceTree = "<group>"; };
5E6B9A4123957DB800E6720C /* PlaylistViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistViewController.swift; sourceTree = "<group>"; };
5E77F9DC236BB68700E1649C /* AttestationDebugger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttestationDebugger.swift; sourceTree = "<group>"; };
5E856FE5235E08110094E113 /* Cryptography.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Cryptography.swift; sourceTree = "<group>"; tabWidth = 2; };
@@ -4269,11 +4271,14 @@
5E8B486723983BCA0075A4EF /* Playlists */ = {
isa = PBXGroup;
children = (
5ED3F38D239AD9A30048CE56 /* PlaylistItem+CoreDataClass.swift */,
5ED3F38E239AD9A30048CE56 /* PlaylistItem+CoreDataProperties.swift */,
5E6B9A3F2395752300E6720C /* PlaylistManager.swift */,
5E22D0782418C9170005D8C5 /* AddToPlaylistViewController.swift */,
5E6B9A4123957DB800E6720C /* PlaylistViewController.swift */,
5E22D07F2418DBEE0005D8C5 /* PlaylistManager.swift */,
5E8B486823983BFC0075A4EF /* CarplayMediaManager.swift */,
5ED3F387239AD7EC0048CE56 /* Playlist.swift */,
5ED3F38D239AD9A30048CE56 /* PlaylistItem+CoreDataClass.swift */,
5ED3F38E239AD9A30048CE56 /* PlaylistItem+CoreDataProperties.swift */,
5E2DF91C24194779000A8943 /* PlaylistCacheLoader.swift */,
5ED3F38A239AD89D0048CE56 /* Playlist.xcdatamodeld */,
);
path = Playlists;
@@ -4605,8 +4610,6 @@
5E4845C122DE3DF800372022 /* WindowRenderHelperScript.swift */,
0A19365323508756002E2B81 /* LinkPreviewViewController.swift */,
0A66550923E9D9750047EF2A /* UserAgent.swift */,
5E6B9A4123957DB800E6720C /* PlaylistViewController.swift */,
5E22D0782418C9170005D8C5 /* AddToPlaylistViewController.swift */,
);
indentWidth = 4;
path = Browser;
5E6B9A402395752300E6720C /* PlaylistManager.swift in Sources */,
0AB2442C22AA789B00B4D9DD /* ReaderModeButton.swift in Sources */,
4422D55E21BFFB7F00BF1855 /* mimics_pcre.cc in Sources */,
5E2DF91D24194779000A8943 /* PlaylistCacheLoader.swift in Sources */,
0A6112AC230B00E7001BBC45 /* OnboardingNavigationController.swift in Sources */,
4422D57321BFFB7F00BF1855 /* stringpiece.cc in Sources */,
27187808216526090006036E /* AlertPopupView.swift in Sources */,
E4A961181AC041C40069AD6F /* ReadabilityService.swift in Sources */,
5E612A90234B7FCD007D12B5 /* OnboardingRewardsAgreementView.swift in Sources */,
4422D56A21BFFB7F00BF1855 /* simplify.cc in Sources */,
5E22D0812418DBEF0005D8C5 /* PlaylistManager.swift in Sources */,
5EC594F1232C697200922111 /* OnboardingAdsCountdownView.swift in Sources */,
A134B88A20DA98BB00A581D0 /* ClientPreferences.swift in Sources */,
D3BE7B261B054D4400641031 /* main.swift in Sources */,
@@ -274,6 +274,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati
}

AdblockResourceDownloader.shared.startLoading()

CarplayMediaManager.shared.updateItems()

return shouldPerformAdditionalDelegateHandling
}
@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "VideoPlayIndicator.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -52,6 +52,12 @@ public class Observable<T> {
}
}

public func refresh() {
subscribers.forEach({
$0.0(value, value)
})
}

@discardableResult
public func observe(_ observer: @escaping Observer) -> Disposable {
let disposable = DisposableReference({ [weak self] in self?.removeObserver($0) })
@@ -74,6 +80,15 @@ struct PlaylistInfo: Decodable {
let src: String
let pageSrc: String
let pageTitle: String
var duration: Float

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

static func from(message: WKScriptMessage) throws -> PlaylistInfo? {
if !JSONSerialization.isValidJSONObject(message.body) {
@@ -90,13 +105,15 @@ 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.duration = (try? container.decode(Float.self, forKey: .duration)) ?? 0.0
}

private enum CodingKeys: String, CodingKey {
case name
case src
case pageSrc
case pageTitle
case duration
}
}

@@ -119,10 +136,16 @@ class PlaylistManager: TabContentScript {

do {
guard let item = try PlaylistInfo.from(message: message) else { return }

if tab?.playlistItems.value.contains(where: { $0.pageSrc == item.pageSrc }) == false {
if !item.src.isEmpty {
tab?.playlistItems.value.append(item)
if !Playlist.shared.itemExists(item: item) {
if let items = tab?.playlistItems, let index = items.value.firstIndex(where: { $0.pageSrc == item.pageSrc }) {
if items.value[index].duration < 0.01 {
items.value[index].duration = item.duration
items.refresh()
}
} else {
if !item.src.isEmpty {
tab?.playlistItems.value.append(item)
}
}
}
} catch {
@@ -27,7 +27,19 @@ class AddToPlaylistViewController: UIViewController {
}

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
@@ -71,7 +83,9 @@ class AddToPlaylistViewController: UIViewController {
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)
@@ -88,6 +102,11 @@ class AddToPlaylistViewController: UIViewController {
$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)
@@ -98,15 +117,56 @@ class AddToPlaylistViewController: UIViewController {
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)
}
}
}

@@ -132,15 +192,18 @@ extension AddToPlaylistViewController: UITableViewDataSource {
return UITableViewCell()
}

let item = self.playlistItems[indexPath.row]

cell.selectionStyle = .none
cell.indicatorIcon.image = #imageLiteral(resourceName: "videoThumbSlider").template
cell.indicatorIcon.tintColor = #colorLiteral(red: 0, green: 0.6666666667, blue: 1, alpha: 1)
cell.thumbnailView.image = #imageLiteral(resourceName: "shields-menu-icon")
cell.titleLabel.text = "Welcome to Brave Video Player"
cell.detailLabel.text = "22 mins"
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
}

@@ -152,16 +215,17 @@ extension AddToPlaylistViewController: UITableViewDataSource {
extension AddToPlaylistViewController: UITableViewDelegate {

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = self.playlistItems[indexPath.row]
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)
}
}

private class PlaylistSelectionCell: UITableViewCell {
public let indicatorIcon = UIImageView().then {
$0.contentMode = .scaleAspectFit
}


public let thumbnailView = UIImageView().then {
$0.contentMode = .scaleAspectFit
$0.layer.cornerRadius = 5.0
@@ -190,6 +254,14 @@ private class PlaylistSelectionCell: UITableViewCell {
$0.axis = .vertical
}

let checkedIcon = UIImageView().then {
$0.contentMode = .scaleAspectFit
$0.image = #imageLiteral(resourceName: "check").scale(toSize: CGSize(width: 20.0, height: 20.0)).template
$0.transform = CGAffineTransform(rotationAngle: 10 * .pi / 180.0)
$0.tintColor = .white
$0.isHidden = true
}

private let separator = UIView().then {
$0.backgroundColor = #colorLiteral(red: 0.5176470588, green: 0.5411764706, blue: 0.568627451, alpha: 1)
}
@@ -203,16 +275,12 @@ private class PlaylistSelectionCell: UITableViewCell {

contentView.addSubview(iconStackView)
contentView.addSubview(infoStackView)
iconStackView.addArrangedSubview(indicatorIcon)
iconStackView.addArrangedSubview(thumbnailView)
infoStackView.addArrangedSubview(titleLabel)
infoStackView.addArrangedSubview(detailLabel)
contentView.addSubview(checkedIcon)
contentView.addSubview(separator)

indicatorIcon.snp.makeConstraints {
$0.width.height.equalTo(12.0)
}

thumbnailView.snp.makeConstraints {
$0.width.height.equalTo(30.0)
}
@@ -225,11 +293,16 @@ private class PlaylistSelectionCell: UITableViewCell {

infoStackView.snp.makeConstraints {
$0.left.equalTo(iconStackView.snp.right).offset(15.0)
$0.right.equalToSuperview().offset(-15.0)
$0.top.equalToSuperview().offset(5.0)
$0.bottom.equalToSuperview().offset(-5.0)
}

checkedIcon.snp.makeConstraints {
$0.left.greaterThanOrEqualTo(infoStackView.snp.right).offset(15.0)
$0.right.equalToSuperview().offset(-15.0)
$0.centerY.equalToSuperview()
}

separator.snp.makeConstraints {
$0.left.equalTo(titleLabel.snp.left)
$0.right.bottom.equalToSuperview()
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.