Commit 6809c301 authored by Carola Nitz's avatar Carola Nitz

VLCMediaSubcategory: added generic Subcategory and adjusted classes

parent 6a94aeca
/*****************************************************************************
* VLCMediaSubcategory.swift
* VLC for iOS
*****************************************************************************
* Copyright (c) 2017 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <caro # videolan.org>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
import Foundation
extension Notification.Name {
static let VLCMoviesDidChangeNotification = Notification.Name("MoviesDidChangeNotfication")
static let VLCEpisodesDidChangeNotification = Notification.Name("EpisodesDidChangeNotfication")
static let VLCArtistsDidChangeNotification = Notification.Name("ArtistsDidChangeNotfication")
static let VLCAlbumsDidChangeNotification = Notification.Name("AlbumsDidChangeNotfication")
static let VLCTracksDidChangeNotification = Notification.Name("TracksDidChangeNotfication")
static let VLCGenresDidChangeNotification = Notification.Name("GenresDidChangeNotfication")
static let VLCAudioPlaylistsDidChangeNotification = Notification.Name("AudioPlaylistsDidChangeNotfication")
static let VLCVideoPlaylistsDidChangeNotification = Notification.Name("VideoPlaylistsDidChangeNotfication")
static let VLCVideosDidChangeNotification = Notification.Name("VideosDidChangeNotfication")
}
enum VLCDataUnit {
case file(MLFile)
case episode(MLShowEpisode)
case album(MLAlbum)
case label(MLLabel)
}
class VLCMediaSubcategory<T>: NSObject {
var files: [T]
var indicatorInfoName: String
var notificationName: Notification.Name
var includesFunc: (VLCDataUnit) -> Bool
var appendFunc: (VLCDataUnit) -> Void
var indicatorInfo: IndicatorInfo {
return IndicatorInfo(title: indicatorInfoName)
}
init(files: [T],
indicatorInfoName: String,
notificationName: Notification.Name,
includesFunc: @escaping (VLCDataUnit) -> Bool,
appendFunc: @escaping (VLCDataUnit) -> Void) {
self.files = files
self.indicatorInfoName = indicatorInfoName
self.notificationName = notificationName
self.includesFunc = includesFunc
self.appendFunc = appendFunc
}
}
struct VLCMediaSubcategories {
static var movies = VLCMediaSubcategory<MLFile>(
files: {
(MLFile.allFiles() as! [MLFile]).filter {
($0 as MLFile).isKind(ofType: kMLFileTypeMovie) ||
($0 as MLFile).isKind(ofType: kMLFileTypeTVShowEpisode) ||
($0 as MLFile).isKind(ofType: kMLFileTypeClip)
}
}(),
indicatorInfoName: NSLocalizedString("MOVIES", comment: ""),
notificationName: .VLCMoviesDidChangeNotification,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .file(let f) = dataUnit {
return f.isMovie()
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var episodes = VLCMediaSubcategory<MLShowEpisode>(
files: MLShowEpisode.allEpisodes() as! [MLShowEpisode],
indicatorInfoName: NSLocalizedString("EPISODES", comment: ""),
notificationName: .VLCEpisodesDidChangeNotification,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .episode(let f) = dataUnit {
return true
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var artists = VLCMediaSubcategory<String>(
files: {
let tracksWithArtist = (MLAlbumTrack.allTracks() as! [MLAlbumTrack]).filter { $0.artist != nil && $0.artist != "" }
return tracksWithArtist.map { $0.artist } as! [String]
}(),
indicatorInfoName: NSLocalizedString("ARTISTS", comment: ""),
notificationName: .VLCArtistsDidChangeNotification,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .file(let f) = dataUnit {
return f.artist != nil
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var albums = VLCMediaSubcategory<MLAlbum>(
files: MLAlbum.allAlbums() as! [MLAlbum],
indicatorInfoName: NSLocalizedString("ALBUMS", comment: ""),
notificationName: .VLCAlbumsDidChangeNotification,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .album(let f) = dataUnit {
return true
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var tracks = VLCMediaSubcategory<MLFile>(
files: (MLFile.allFiles() as! [MLFile]).filter { $0.isSupportedAudioFile()},
indicatorInfoName: NSLocalizedString("SONGS", comment: ""),
notificationName: .VLCTracksDidChangeNotification,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .file(let f) = dataUnit {
return f.isSupportedAudioFile()
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var genres = VLCMediaSubcategory<String>(
files: {
let albumtracks = MLAlbumTrack.allTracks() as! [MLAlbumTrack]
let tracksWithArtist = albumtracks.filter { $0.genre != nil && $0.genre != "" }
return tracksWithArtist.map { $0.genre }
}(),
indicatorInfoName: NSLocalizedString("GENRES", comment: ""),
notificationName: .VLCGenresDidChangeNotification ,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .file(let f) = dataUnit {
return f.genre != nil
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var audioPlaylists = VLCMediaSubcategory<MLLabel>(
files: {
let labels = MLLabel.allLabels() as! [MLLabel]
let audioPlaylist = labels.filter {
let audioFiles = $0.files.filter {
if let file = $0 as? MLFile {
return file.isSupportedAudioFile()
}
return false
}
return !audioFiles.isEmpty
}
return audioPlaylist
}(),
indicatorInfoName: NSLocalizedString("AUDIO_PLAYLISTS", comment: ""),
notificationName: .VLCAudioPlaylistsDidChangeNotification ,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .label(let l) = dataUnit {
let audioFiles = l.files.filter {
if let file = $0 as? MLFile {
return file.isSupportedAudioFile()
} else {
return false
}
}
return !audioFiles.isEmpty
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
static var videoPlaylists = VLCMediaSubcategory<MLLabel>(
files: {
let labels = MLLabel.allLabels() as! [MLLabel]
let audioPlaylist = labels.filter {
let audioFiles = $0.files.filter {
if let file = $0 as? MLFile {
return file.isShowEpisode() || file.isMovie() || file.isClip()
}
return false
}
return !audioFiles.isEmpty
}
return audioPlaylist
}(),
indicatorInfoName: NSLocalizedString("VIDEO_PLAYLISTS", comment: ""),
notificationName: .VLCVideoPlaylistsDidChangeNotification ,
includesFunc: { (dataUnit: VLCDataUnit) in
if case .label(let l) = dataUnit {
let videoFiles = l.files.filter {
if let file = $0 as? MLFile {
return file.isShowEpisode() || file.isMovie() || file.isClip()
} else {
return false
}
}
return !videoFiles.isEmpty
}
return false
},
appendFunc: { (dataUnit: VLCDataUnit) in
})
}
......@@ -14,25 +14,29 @@ import UIKit
class VLCVideoSubcategoryViewController: VLCMediaSubcategoryViewController {
override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
let movies = VLCMediaViewController(services: services, type: VLCMediaType(category: .video, subcategory: .allVideos))
let episodes = VLCMediaViewController(services: services, type: VLCMediaType(category: .video, subcategory: .episodes))
let playlists = VLCMediaViewController(services: services, type: VLCMediaType(category: .video, subcategory: .videoPlaylists))
let viewControllers = [movies, episodes, playlists]
viewControllers.forEach { $0.delegate = mediaDelegate }
return viewControllers
let movies = VLCMediaViewController<MLFile>(services: services, subcategory: VLCMediaSubcategories.movies)
movies.delegate = mediaDelegate
let episodes = VLCMediaViewController<MLShowEpisode>(services: services, subcategory: VLCMediaSubcategories.episodes)
episodes.delegate = mediaDelegate
let playlists = VLCMediaViewController<MLLabel>(services: services, subcategory: VLCMediaSubcategories.videoPlaylists)
playlists.delegate = mediaDelegate
return [movies, episodes, playlists]
}
}
class VLCAudioSubcategoryViewController: VLCMediaSubcategoryViewController {
override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
let tracks = VLCMediaViewController(services: services, type: VLCMediaType(category: .audio, subcategory: .tracks))
let genres = VLCMediaViewController(services: services, type: VLCMediaType(category: .audio, subcategory: .genres))
let artists = VLCMediaViewController(services: services, type: VLCMediaType(category: .audio, subcategory: .artists))
let albums = VLCMediaViewController(services: services, type: VLCMediaType(category: .audio, subcategory: .albums))
let playlists = VLCMediaViewController(services: services, type: VLCMediaType(category: .audio, subcategory: .audioPlaylists))
let viewControllers = [tracks, genres, artists, albums, playlists]
viewControllers.forEach { $0.delegate = mediaDelegate }
return viewControllers
let tracks = VLCMediaViewController<MLFile>(services: services, subcategory: VLCMediaSubcategories.tracks)
tracks.delegate = mediaDelegate
let genres = VLCMediaViewController<String>(services: services, subcategory: VLCMediaSubcategories.genres)
genres.delegate = mediaDelegate
let artists = VLCMediaViewController<String>(services: services, subcategory: VLCMediaSubcategories.artists)
artists.delegate = mediaDelegate
let albums = VLCMediaViewController<MLAlbum>(services: services, subcategory: VLCMediaSubcategories.albums)
albums.delegate = mediaDelegate
let playlists = VLCMediaViewController<MLLabel>(services: services, subcategory: VLCMediaSubcategories.audioPlaylists)
playlists.delegate = mediaDelegate
return [tracks, genres, artists, albums, playlists]
}
}
......
/*****************************************************************************
* MediaViewController+DataSourceDelegate.swift
* VLC for iOS
*****************************************************************************
* Copyright (c) 2018 VideoLAN. All rights reserved.
* $Id$
*
* Authors: Carola Nitz <nitz.carola # gmail.com>
* Mike JS. Choi <mkchoi212 # icloud.com>
*
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
extension Notification.Name {
static let VLCTracksDidChangeNotification = Notification.Name("kTracksDidChangeNotification")
static let VLCAllVideosDidChangeNotification = Notification.Name("kAllVideosDidChangeNotification")
}
// These are the delegate and datasource calls from the MediaViewController
extension VLCMediaViewController: UICollectionViewDelegateFlowLayout {
// MARK: - UICollectionViewDataSource
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Int(services.mediaDataSource.numberOfFiles(subcategory: mediaType.subcategory))
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let playlistCell = collectionView.dequeueReusableCell(withReuseIdentifier: VLCPlaylistCollectionViewCell.cellIdentifier(), for: indexPath) as? VLCPlaylistCollectionViewCell {
if let mediaObject = services.mediaDataSource.object(at: indexPath.row, subcategory: mediaType.subcategory) as? NSManagedObject {
playlistCell.mediaObject = mediaObject
}
return playlistCell
}
return UICollectionViewCell()
}
// MARK: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let mediaObject = services.mediaDataSource.object(at: indexPath.row, subcategory: mediaType.subcategory) as? NSManagedObject {
delegate?.mediaViewControllerDidSelectMediaObject(self, mediaObject: mediaObject)
}
}
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let numberOfCells: CGFloat = collectionView.traitCollection.horizontalSizeClass == .regular ? 3.0 : 2.0
let aspectRatio: CGFloat = 10.0 / 16.0
// We have the number of cells and we always have numberofCells + 1 padding spaces. -pad-[Cell]-pad-[Cell]-pad-
// we then have the entire padding, we divide the entire padding by the number of Cells to know how much needs to be substracted from ech cell
// since this might be an uneven number we ceil
var cellWidth = collectionView.bounds.size.width / numberOfCells
cellWidth = cellWidth - ceil(((numberOfCells + 1) * cellPadding) / numberOfCells)
return CGSize(width: cellWidth, height: cellWidth * aspectRatio)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: cellPadding, left: cellPadding, bottom: cellPadding, right: cellPadding)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return cellPadding
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return cellPadding
}
}
......@@ -13,23 +13,22 @@
import Foundation
@objc protocol VLCMediaViewControllerDelegate: class {
func mediaViewControllerDidSelectMediaObject(_ mediaViewController: VLCMediaViewController, mediaObject: NSManagedObject)
protocol VLCMediaViewControllerDelegate: class {
func mediaViewControllerDidSelectMediaObject(_ mediaViewController: UIViewController, mediaObject: NSManagedObject)
}
class VLCMediaViewController: UICollectionViewController, UISearchResultsUpdating, UISearchControllerDelegate, IndicatorInfoProvider {
class VLCMediaViewController<T>: UICollectionViewController, UICollectionViewDelegateFlowLayout, UISearchResultsUpdating, UISearchControllerDelegate, IndicatorInfoProvider {
let cellPadding: CGFloat = 5.0
var services: Services
var mediaType: VLCMediaType
weak var delegate: VLCMediaViewControllerDelegate?
private var services: Services
private var searchController: UISearchController?
private let searchDataSource = VLCLibrarySearchDisplayDataSource()
var subcategory: VLCMediaSubcategory<T>
weak var delegate: VLCMediaViewControllerDelegate?
@available(iOS 11.0, *)
lazy var dragAndDropManager: VLCDragAndDropManager = {
let dragAndDropManager = VLCDragAndDropManager(type: mediaType)
dragAndDropManager.delegate = services.mediaDataSource
return dragAndDropManager
lazy var dragAndDropManager: VLCDragAndDropManager = { () -> VLCDragAndDropManager<T> in
VLCDragAndDropManager<T>(subcategory: subcategory)
}()
lazy var emptyView: VLCEmptyLibraryView = {
......@@ -44,17 +43,13 @@ class VLCMediaViewController: UICollectionViewController, UISearchResultsUpdatin
fatalError()
}
init(services: Services, type: VLCMediaType) {
init(services: Services, subcategory: VLCMediaSubcategory<T>) {
self.services = services
mediaType = type
self.subcategory = subcategory
super.init(collectionViewLayout: UICollectionViewFlowLayout())
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .VLCThemeDidChangeNotification, object: nil)
if mediaType.category == .video {
NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: .VLCAllVideosDidChangeNotification, object: nil)
} else {
NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: .VLCTracksDidChangeNotification, object: nil)
}
NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: subcategory.notificationName, object: nil)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
......@@ -98,8 +93,6 @@ class VLCMediaViewController: UICollectionViewController, UISearchResultsUpdatin
collectionView?.register(playlistnib, forCellWithReuseIdentifier: VLCPlaylistCollectionViewCell.cellIdentifier())
collectionView?.backgroundColor = PresentationTheme.current.colors.background
collectionView?.alwaysBounceVertical = true
collectionView?.dataSource = self
collectionView?.delegate = self
if #available(iOS 11.0, *) {
collectionView?.dragDelegate = dragAndDropManager
collectionView?.dropDelegate = dragAndDropManager
......@@ -149,7 +142,7 @@ class VLCMediaViewController: UICollectionViewController, UISearchResultsUpdatin
// MARK: - Search
func updateSearchResults(for searchController: UISearchController) {
searchDataSource.shouldReloadTable(forSearch: searchController.searchBar.text, searchableFiles: services.mediaDataSource.allObjects(for: mediaType.subcategory))
searchDataSource.shouldReloadTable(forSearch: searchController.searchBar.text, searchableFiles: subcategory.files)
collectionView?.reloadData()
}
......@@ -162,6 +155,55 @@ class VLCMediaViewController: UICollectionViewController, UISearchResultsUpdatin
}
func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
return services.mediaDataSource.indicatorInfo(for:mediaType.subcategory)
return IndicatorInfo(title:subcategory.indicatorInfoName)
}
// MARK: - UICollectionViewDataSource
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return subcategory.files.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let playlistCell = collectionView.dequeueReusableCell(withReuseIdentifier: VLCPlaylistCollectionViewCell.cellIdentifier(), for: indexPath) as? VLCPlaylistCollectionViewCell {
if let mediaObject = subcategory.files[indexPath.row] as? NSManagedObject {
playlistCell.mediaObject = mediaObject
}
return playlistCell
}
return UICollectionViewCell()
}
// MARK: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let mediaObject = subcategory.files[indexPath.row] as? NSManagedObject {
delegate?.mediaViewControllerDidSelectMediaObject(self, mediaObject: mediaObject)
}
}
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let numberOfCells: CGFloat = collectionView.traitCollection.horizontalSizeClass == .regular ? 3.0 : 2.0
let aspectRatio: CGFloat = 10.0 / 16.0
// We have the number of cells and we always have numberofCells + 1 padding spaces. -pad-[Cell]-pad-[Cell]-pad-
// we then have the entire padding, we divide the entire padding by the number of Cells to know how much needs to be substracted from ech cell
// since this might be an uneven number we ceil
var cellWidth = collectionView.bounds.size.width / numberOfCells
cellWidth = cellWidth - ceil(((numberOfCells + 1) * cellPadding) / numberOfCells)
return CGSize(width: cellWidth, height: cellWidth * aspectRatio)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: cellPadding, left: cellPadding, bottom: cellPadding, right: cellPadding)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return cellPadding
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return cellPadding
}
}
......@@ -24,20 +24,19 @@ struct DropError: Error {
}
@available(iOS 11.0, *)
@objc protocol VLCDragAndDropManagerDelegate: NSObjectProtocol {
func dragAndDropManagerRequestsFile(manager: VLCDragAndDropManager, atIndexPath indexPath: IndexPath) -> Any?
func dragAndDropManagerInsertItem(manager: VLCDragAndDropManager, item: NSManagedObject, atIndexPath indexPath: IndexPath)
func dragAndDropManagerDeleteItem(manager: VLCDragAndDropManager, atIndexPath indexPath: IndexPath)
func dragAndDropManagerRemoveFileFromFolder(manager: VLCDragAndDropManager, file: NSManagedObject)
func dragAndDropManagerCurrentSelection(manager: VLCDragAndDropManager) -> AnyObject?
protocol VLCDragAndDropManagerDelegate: NSObjectProtocol {
func dragAndDropManagerRequestsFile(manager: NSObject, atIndexPath indexPath: IndexPath) -> Any?
func dragAndDropManagerInsertItem(manager: NSObject, item: NSManagedObject, atIndexPath indexPath: IndexPath)
func dragAndDropManagerDeleteItem(manager: NSObject, atIndexPath indexPath: IndexPath)
func dragAndDropManagerRemoveFileFromFolder(manager: NSObject, file: NSManagedObject)
func dragAndDropManagerCurrentSelection(manager: NSObject) -> AnyObject?
}
@available(iOS 11.0, *)
class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableViewDragDelegate, UICollectionViewDropDelegate, UITableViewDropDelegate, UIDropInteractionDelegate {
@objc weak var delegate: VLCDragAndDropManagerDelegate?
class VLCDragAndDropManager<T>: NSObject, UICollectionViewDragDelegate, UITableViewDragDelegate, UICollectionViewDropDelegate, UITableViewDropDelegate, UIDropInteractionDelegate {
let utiTypeIdentifiers: [String] = VLCDragAndDropManager.supportedTypeIdentifiers()
var mediaType: VLCMediaType
var subcategory: VLCMediaSubcategory<T>
/// Returns the supported type identifiers that VLC can process.
/// It fetches the identifiers in LSItemContentTypes from all the CFBundleDocumentTypes in the info.plist.
/// Video, Audio and Subtitle formats
......@@ -60,8 +59,8 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
fatalError()
}
init(type: VLCMediaType) {
mediaType = type
init(subcategory: VLCMediaSubcategory<T>) {
self.subcategory = subcategory
super.init()
}
......@@ -116,7 +115,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
if let file = file {
placeholderContext.commitInsertion() {
insertionIndexPath in
strongSelf.delegate?.dragAndDropManagerInsertItem(manager: strongSelf, item: file, atIndexPath: insertionIndexPath)
strongSelf.subcategory.dragAndDropManagerInsertItem(manager: strongSelf, item: file, atIndexPath: insertionIndexPath)
}
}
if let error = error as? DropError {
......@@ -128,15 +127,15 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
}
private func inFolder() -> Bool {
return delegate?.dragAndDropManagerCurrentSelection(manager: self) as? MLLabel != nil
return subcategory.dragAndDropManagerCurrentSelection(manager: self) as? MLLabel != nil
}
private func moveItem(tableView: UITableView, item: UITableViewDropItem, toIndexPath destinationPath: IndexPath) {
if let mlFile = item.dragItem.localObject as? MLFile, !mlFile.labels.isEmpty && !inFolder() {
tableView.performBatchUpdates({
tableView.insertRows(at: [destinationPath], with: .automatic)
delegate?.dragAndDropManagerInsertItem(manager: self, item: mlFile, atIndexPath: destinationPath)
delegate?.dragAndDropManagerRemoveFileFromFolder(manager: self, file: mlFile)
subcategory.dragAndDropManagerInsertItem(manager: self, item: mlFile, atIndexPath: destinationPath)
subcategory.dragAndDropManagerRemoveFileFromFolder(manager: self, file: mlFile)
}, completion: nil)
}
}
......@@ -144,10 +143,10 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
private func addDragItem(tableView: UITableView, dragItem item: UITableViewDropItem, toFolderAt index: IndexPath) {
if let sourcepath = item.sourceIndexPath { // local file that just needs to be moved
tableView.performBatchUpdates({
if let file = delegate?.dragAndDropManagerRequestsFile(manager: self, atIndexPath: sourcepath) as? MLFile {
if let file = subcategory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: sourcepath) as? MLFile {
tableView.deleteRows(at: [sourcepath], with: .automatic)
addFile(file: file, toFolderAt: index)
delegate?.dragAndDropManagerDeleteItem(manager: self, atIndexPath: sourcepath)
subcategory.dragAndDropManagerDeleteItem(manager: self, atIndexPath: sourcepath)
}
}, completion: nil)
return
......@@ -209,7 +208,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
if let file = file {
placeholderContext.commitInsertion() {
insertionIndexPath in
strongSelf.delegate?.dragAndDropManagerInsertItem(manager: strongSelf, item: file, atIndexPath: insertionIndexPath)
strongSelf.subcategory.dragAndDropManagerInsertItem(manager: strongSelf, item: file, atIndexPath: insertionIndexPath)
}
}
if let error = error as? DropError {
......@@ -224,8 +223,8 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
if let mlFile = item.dragItem.localObject as? MLFile, !mlFile.labels.isEmpty && !inFolder() {
collectionView.performBatchUpdates({
collectionView.insertItems(at: [destinationPath])
delegate?.dragAndDropManagerInsertItem(manager: self, item: mlFile, atIndexPath: destinationPath)
delegate?.dragAndDropManagerRemoveFileFromFolder(manager: self, file: mlFile)
subcategory.dragAndDropManagerInsertItem(manager: self, item: mlFile, atIndexPath: destinationPath)
subcategory.dragAndDropManagerRemoveFileFromFolder(manager: self, file: mlFile)
}, completion: nil)
}
}
......@@ -234,10 +233,10 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
if let sourcepath = item.sourceIndexPath {
// local file that just needs to be moved
collectionView.performBatchUpdates({
if let file = delegate?.dragAndDropManagerRequestsFile(manager: self, atIndexPath: sourcepath) as? MLFile {
if let file = subcategory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: sourcepath) as? MLFile {
collectionView.deleteItems(at: [sourcepath])
addFile(file: file, toFolderAt: index)
delegate?.dragAndDropManagerDeleteItem(manager: self, atIndexPath: sourcepath)
subcategory.dragAndDropManagerDeleteItem(manager: self, atIndexPath: sourcepath)
}
}, completion: nil)
} else {
......@@ -290,8 +289,8 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
/// - item: UIDragItem from session
/// - Returns: UIDropOperation
private func dropOperation(hasActiveDrag: Bool, firstSessionItem item: AnyObject?, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UIDropOperation {
let inAlbum = delegate?.dragAndDropManagerCurrentSelection(manager: self) as? MLAlbum != nil
let inShow = delegate?.dragAndDropManagerCurrentSelection(manager: self) as? MLShow != nil
let inAlbum = subcategory.dragAndDropManagerCurrentSelection(manager: self) as? MLAlbum != nil
let inShow = subcategory.dragAndDropManagerCurrentSelection(manager: self) as? MLShow != nil
// you can move files into a folder or copy from anothr app into a folder
if fileIsFolder(atIndexPath: destinationIndexPath) {
// no dragging entire shows and albums into folders
......@@ -337,7 +336,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
private func fileIsFolder(atIndexPath indexPath: IndexPath?) -> Bool {
if let indexPath = indexPath {
let file = delegate?.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath)
let file = subcategory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath)
return file as? MLLabel != nil
}
return false
......@@ -352,7 +351,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
private func fileIsCollection(atIndexPath indexPath: IndexPath?) -> Bool {
if let indexPath = indexPath {
if let file = delegate?.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath) {
if let file = subcategory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath) {
return fileIsCollection(file:file)
}
}
......@@ -361,7 +360,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
// creating dragItems for the file at indexpath
private func dragItems(forIndexPath indexPath: IndexPath) -> [UIDragItem] {
if let file = delegate?.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath) {
if let file = subcategory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: indexPath) {
if fileIsCollection(atIndexPath: indexPath) {
return dragItemsforCollection(file: file)
}
......@@ -445,7 +444,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
}
private func addFile(file: MLFile, toFolderAt folderIndex: IndexPath) {
let label = delegate?.dragAndDropManagerRequestsFile(manager: self, atIndexPath: folderIndex) as! MLLabel
let label = subcategory.dragAndDropManagerRequestsFile(manager: self, atIndexPath: folderIndex) as! MLLabel
DispatchQueue.main.async {
_ = label.files.insert(file)
file.labels = [label]
......@@ -483,7 +482,7 @@ class VLCDragAndDropManager: NSObject, UICollectionViewDragDelegate, UITableView
if let file = MLFile.file(for: destinationURL).first as? MLFile {
DispatchQueue.main.async {
// we dragged into a folder
if let selection = strongSelf.delegate?.dragAndDropManagerCurrentSelection(manager: strongSelf) as? MLLabel {
if let selection = strongSelf.subcategory.dragAndDropManagerCurrentSelection(manager: strongSelf) as? MLLabel {
file.labels = [selection]
}
completion(file, nil)
......
......@@ -12,216 +12,14 @@
import Foundation
@objc enum VLCMediaCategory: Int {
case unknown
case audio
case video
}
@objc enum VLCMediaSubcategory: Int {
case unknown
case movies
case episodes
case artists
case albums
case tracks
case genres
case videoPlaylists
case audioPlaylists
case allVideos
}
struct VLCMediaType {
let category: VLCMediaCategory
var subcategory: VLCMediaSubcategory
}
@objc class VLCMediaDataSource: NSObject {
var foundVideos = [MLFile]()
var foundAudio = [MLFile]()
var movies = [MLFile]()
var episodes = [MLShowEpisode]()
var artists = [String]()
var albums = [MLAlbum]()
var genres = [String]()
var audioPlaylist = [MLLabel]()
var videoPlaylist = [MLLabel]()
override init() {
super.init()
getAllVideos()
getAllAudio()
}
@objc
func numberOfFiles(subcategory: VLCMediaSubcategory) -> Int {
return array(for: subcategory).count
}
private func array(for subcategory: VLCMediaSubcategory ) -> [Any] {
switch subcategory {
case .unknown:
preconditionFailure("No")
case .movies:
return movies
case .episodes:
return episodes
case .artists:
return artists
case .albums:
return albums
case .tracks:
return foundAudio
case .genres:
return genres
case .audioPlaylists:
return audioPlaylist
case .videoPlaylists:
return videoPlaylist
case .allVideos:
return foundVideos