Skip to content

Commit

Permalink
RadiosVC: show play/random button and support context
Browse files Browse the repository at this point in the history
  • Loading branch information
BLeeEZ committed Jan 2, 2025
1 parent df75e67 commit 24a0cc1
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 20 deletions.
25 changes: 19 additions & 6 deletions Amperfy/CarPlaySceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -542,18 +542,31 @@ class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {
private func createRadioItems(from fetchedController: BasicFetchedResultsController<RadioMO>?) -> [CPListTemplateItem] {
var items = [CPListTemplateItem]()
guard let fetchedController = fetchedController else { return items }

guard let fetchedRadios = fetchedController.fetchedObjects else { return items }
let itemCount = min(fetchedRadios.count, CPListTemplate.maximumSectionCount)
let itemCount = min(fetchedRadios.count, CPListTemplate.maximumSectionCount-2)
guard itemCount > 0 else { return items }
for radioIndex in 0...(itemCount-1) {
let radioMO = fetchedRadios[radioIndex]
let radio = Radio(managedObject: radioMO)
let listItem = createDetailTemplate(for: radio, playContext: PlayContext(containable: radio), isTrackDisplayed: false)
let radios = fetchedRadios.prefix(itemCount).compactMap{ Radio(managedObject: $0) }

items.append(self.createPlayRandomListItem(playContext: PlayContext(name: "Radios", playables: radios)))
for (index, radio) in radios.enumerated() {
let listItem = createDetailTemplate(for: radio, playContext: PlayContext(name: "Radios", index: index, playables: Array(radios)), isTrackDisplayed: false)
items.append(listItem)
}
return items
}

private func createPlayRandomListItem(playContext: PlayContext, text: String = "Random") -> CPListItem {
let img = UIImage.createArtwork(with: UIImage.shuffle, iconSizeType: .small, theme: appDelegate.storage.settings.themePreference, switchColors: true).carPlayImage(carTraitCollection: traits)
let listItem = CPListItem(text: text, detailText: nil, image: img)
listItem.handler = { [weak self] item, completion in
guard let `self` = self else { completion(); return }
self.appDelegate.player.play(context: playContext.getWithShuffledIndex())
self.displayNowPlaying() {
completion()
}
}
return listItem
}

private func createPlayShuffledListItem(playContext: PlayContext, text: String = "Shuffle") -> CPListItem {
let img = UIImage.createArtwork(with: UIImage.shuffle, iconSizeType: .small, theme: appDelegate.storage.settings.themePreference, switchColors: true).carPlayImage(carTraitCollection: traits)
Expand Down
5 changes: 1 addition & 4 deletions Amperfy/Screens/ViewController/AlbumDetailVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,7 @@ class AlbumDetailVC: SingleSnapshotFetchedResultsTableViewController<SongMO> {
containableAtIndexPathCallback = { (indexPath) in
return self.fetchedResultsController.getWrappedEntity(at: indexPath)
}
playContextAtIndexPathCallback = { (indexPath) in
let entity = self.fetchedResultsController.getWrappedEntity(at: indexPath)
return PlayContext(containable: entity)
}
playContextAtIndexPathCallback = self.convertIndexPathToPlayContext
swipeCallback = { (indexPath, completionHandler) in
let song = self.fetchedResultsController.getWrappedEntity(at: indexPath)
let playContext = self.convertIndexPathToPlayContext(songIndexPath: indexPath)
Expand Down
37 changes: 29 additions & 8 deletions Amperfy/Screens/ViewController/RadiosVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class RadiosVC: SingleFetchedResultsTableViewController<RadioMO> {
}

private var fetchedResultsController: RadiosFetchedResultsController!

private var detailHeaderView: LibraryElementDetailTableHeaderView?

override func viewDidLoad() {
super.viewDidLoad()

Expand All @@ -50,17 +51,20 @@ class RadiosVC: SingleFetchedResultsTableViewController<RadioMO> {
tableView.rowHeight = PlayableTableCell.rowHeight
tableView.estimatedRowHeight = PlayableTableCell.rowHeight

#if !targetEnvironment(macCatalyst)
let playShuffleConfig = PlayShuffleInfoConfiguration(
infoCB: { "\(self.fetchedResultsController.fetchedObjects?.count ?? 0) Radio\((self.fetchedResultsController.fetchedObjects?.count ?? 0) == 1 ? "" : "s")" },
playContextCb: self.handleHeaderPlay,
player: appDelegate.player,
isInfoAlwaysHidden: false,
isShuffleOnContextNeccessary: false,
shuffleContextCb: self.handleHeaderShuffle)
detailHeaderView = LibraryElementDetailTableHeaderView.createTableHeader(rootView: self, configuration: playShuffleConfig)
self.refreshControl?.addTarget(self, action: #selector(Self.handleRefresh), for: UIControl.Event.valueChanged)
#endif

containableAtIndexPathCallback = { (indexPath) in
return self.fetchedResultsController.getWrappedEntity(at: indexPath)
}
playContextAtIndexPathCallback = { (indexPath) in
let entity = self.fetchedResultsController.getWrappedEntity(at: indexPath)
return PlayContext(containable: entity)
}
playContextAtIndexPathCallback = convertIndexPathToPlayContext
swipeCallback = { (indexPath, completionHandler) in
let radio = self.fetchedResultsController.getWrappedEntity(at: indexPath)
let playContext = self.convertIndexPathToPlayContext(radioIndexPath: indexPath)
Expand All @@ -81,10 +85,23 @@ class RadiosVC: SingleFetchedResultsTableViewController<RadioMO> {
}.catch { error in
self.appDelegate.eventLogger.report(topic: "Radios Sync", error: error)
}.finally {
self.detailHeaderView?.refresh()
self.updateSearchResults(for: self.searchController)
}
}

public func handleHeaderPlay() -> PlayContext {
guard let displayedRadiosMO = self.fetchedResultsController.fetchedObjects else { return PlayContext(name: sceneTitle ?? "", playables: []) }
let radios = displayedRadiosMO.prefix(appDelegate.player.maxSongsToAddOnce).compactMap{ Radio(managedObject: $0) }
return PlayContext(name: sceneTitle ?? "", playables: radios)
}

public func handleHeaderShuffle() -> PlayContext {
guard let displayedRadiosMO = self.fetchedResultsController.fetchedObjects else { return PlayContext(name: sceneTitle ?? "", playables: []) }
let radios = displayedRadiosMO.prefix(appDelegate.player.maxSongsToAddOnce).compactMap{ Radio(managedObject: $0) }
return PlayContext(name: sceneTitle ?? "", index: Int.random(in: 0..<radios.count), playables: radios)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: PlayableTableCell = dequeueCell(for: tableView, at: indexPath)
let radio = fetchedResultsController.getWrappedEntity(at: indexPath)
Expand All @@ -101,8 +118,11 @@ class RadiosVC: SingleFetchedResultsTableViewController<RadioMO> {
}

func convertIndexPathToPlayContext(radioIndexPath: IndexPath) -> PlayContext? {
guard let radios = self.fetchedResultsController.getContextRadios()
else { return nil }
let selectedRadio = self.fetchedResultsController.getWrappedEntity(at: radioIndexPath)
return PlayContext(containable: selectedRadio)
guard let playContextIndex = radios.firstIndex(of: selectedRadio) else { return nil }
return PlayContext(name: sceneTitle ?? "", index: playContextIndex, playables: radios)
}

func convertCellViewToPlayContext(cell: UITableViewCell) -> PlayContext? {
Expand Down Expand Up @@ -132,6 +152,7 @@ class RadiosVC: SingleFetchedResultsTableViewController<RadioMO> {
}.catch { error in
self.appDelegate.eventLogger.report(topic: "Radios Sync", error: error)
}.finally {
self.detailHeaderView?.refresh()
self.updateSearchResults(for: self.searchController)
#if !targetEnvironment(macCatalyst)
self.refreshControl?.endRefreshing()
Expand Down
2 changes: 1 addition & 1 deletion AmperfyKit/Player/PlayerFacade.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public struct PlayContext {
return playables[index]
}

func getWithShuffledIndex() -> PlayContext {
public func getWithShuffledIndex() -> PlayContext {
guard !isKeepIndexDuringShuffle else { return self }
return PlayContext(name: name, index: Int.random(in: 0...playables.count-1), playables: playables)
}
Expand Down
9 changes: 9 additions & 0 deletions AmperfyKit/Storage/LibraryStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,7 @@ public class LibraryStorage: PlayableFileCachable {

public func getRadios() -> [Radio] {
let fetchRequest = RadioMO.identifierSortedFetchRequest
fetchRequest.predicate = RadioMO.excludeServerDeleteRadiosFetchPredicate
let foundRadios = try? context.fetch(fetchRequest)
let radios = foundRadios?.compactMap{ Radio(managedObject: $0) }
return radios ?? [Radio]()
Expand Down Expand Up @@ -992,6 +993,14 @@ public class LibraryStorage: PlayableFileCachable {
return wrapped ?? [Playlist]()
}

public func getSearchRadiosPredicate(searchText: String) -> NSPredicate {
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
RadioMO.excludeServerDeleteRadiosFetchPredicate,
RadioMO.getIdentifierBasedSearchPredicate(searchText: searchText)
])
return predicate
}

public func getSearchSongsPredicate(searchText: String, onlyCached: Bool, displayFilter: DisplayCategoryFilter) -> NSPredicate {
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
SongMO.excludeServerDeleteUncachedSongsFetchPredicate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,15 @@ extension BasicFetchedResultsController where ResultType == RadioMO {
let radioMO = fetchResultsController.object(at: indexPath) as! ResultType
return Radio(managedObject: radioMO)
}

public func getContextRadios() -> [AbstractPlayable]? {
guard let basicPredicate = defaultPredicate else { return nil }
let cachedFetchRequest = fetchResultsController.fetchRequest.copy() as! NSFetchRequest<RadioMO>
cachedFetchRequest.predicate = basicPredicate
let radiosMO = try? coreDataCompanion.context.fetch(cachedFetchRequest)
let radios = radiosMO?.compactMap{ Radio(managedObject: $0) }
return radios
}
}

extension BasicFetchedResultsController where ResultType == PlaylistMO {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,8 @@ public class RadiosFetchedResultsController: CachedFetchedResultsController<Radi

public func search(searchText: String) {
if searchText.count > 0 {
search(predicate: RadioMO.excludeServerDeleteRadiosFetchPredicate)
let predicate = coreDataCompanion.library.getSearchRadiosPredicate(searchText: searchText)
search(predicate: predicate)
} else {
showAllResults()
}
Expand Down

0 comments on commit 24a0cc1

Please sign in to comment.