Просмотр исходного кода

MediaLibrary: Sort by category

Closes #162
Soomin Lee 6 лет назад
Родитель
Сommit
cfd437fe3a

+ 14 - 0
Resources/en.lproj/Localizable.strings

@@ -320,3 +320,17 @@
 
 //EDIT
 "ADD_TO_PLAYLIST" = "Add to Playlist";
+
+// VLCMediaLibraryKit - Sorting Criteria
+
+"ALPHA" = "Alphanumerically";
+"DURATION" = "Duration";
+"INSERTION_DATE" = "Insertion date";
+"LAST_MODIFICATION_DATE" = "Last modification date";
+"RELEASE_DATE" = "Release date";
+"FILE_SIZE" = "File size";
+"ARTIST" = "Artist";
+"PLAY_COUNT" = "Play count";
+"ALBUM" = "Album";
+"FILENAME" = "Filename";
+"TRACK_NUMBER" = "Track number";

+ 15 - 0
SharedSources/MediaLibraryModel/AlbumModel.swift

@@ -12,6 +12,11 @@
 class AlbumModel: MLBaseModel {
     typealias MLType = VLCMLAlbum
 
+    var sortModel = SortModel(alpha: true,
+                              duration: true,
+                              releaseDate: true,
+                              trackNumber: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLAlbum]()
@@ -37,6 +42,16 @@ class AlbumModel: MLBaseModel {
     }
 }
 
+// MARK: - Sort
+
+extension AlbumModel {
+    func sort(by criteria: VLCMLSortingCriteria) {
+        files = medialibrary.albums(sortingCriteria: criteria)
+        sortModel.currentSort = criteria
+        updateView?()
+    }
+}
+
 extension AlbumModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: VLCMediaLibraryManager, didAddAlbums albums: [VLCMLAlbum]) {
         albums.forEach({ append($0) })

+ 12 - 0
SharedSources/MediaLibraryModel/ArtistModel.swift

@@ -12,6 +12,8 @@
 class ArtistModel: MLBaseModel {
     typealias MLType = VLCMLArtist
 
+    var sortModel = SortModel(alpha: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLArtist]()
@@ -37,6 +39,16 @@ class ArtistModel: MLBaseModel {
     }
 }
 
+// MARK: - Sort
+
+extension ArtistModel {
+    func sort(by criteria: VLCMLSortingCriteria) {
+        files = medialibrary.artists(sortingCriteria: criteria)
+        sortModel.currentSort = criteria
+        updateView?()
+    }
+}
+
 extension ArtistModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: VLCMediaLibraryManager, didAddArtists artists: [VLCMLArtist]) {
         artists.forEach({ append($0) })

+ 6 - 1
SharedSources/MediaLibraryModel/AudioModel.swift

@@ -12,6 +12,10 @@
 class AudioModel: MediaModel {
     typealias MLType = VLCMLMedia
 
+    var sortModel = SortModel(alpha: true,
+                              duration: true,
+                              fileSize: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLMedia]()
@@ -34,7 +38,8 @@ class AudioModel: MediaModel {
 extension AudioModel {
     func sort(by criteria: VLCMLSortingCriteria) {
         // FIXME: Currently if sorted by name, the files are sorted by filename but displaying title
-        files = medialibrary.media(ofType: .audio, sortingCriteria: criteria, desc: false)
+        files = medialibrary.media(ofType: .audio, sortingCriteria: criteria)
+        sortModel.currentSort = criteria
         updateView?()
     }
 }

+ 12 - 0
SharedSources/MediaLibraryModel/GenreModel.swift

@@ -12,6 +12,8 @@
 class GenreModel: MLBaseModel {
     typealias MLType = VLCMLGenre
 
+    var sortModel = SortModel(alpha: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLGenre]()
@@ -37,6 +39,16 @@ class GenreModel: MLBaseModel {
     }
 }
 
+// MARK: - Sort
+
+extension GenreModel {
+    func sort(by criteria: VLCMLSortingCriteria) {
+        files = medialibrary.genres(sortingCriteria: criteria)
+        sortModel.currentSort = criteria
+        updateView?()
+    }
+}
+
 extension GenreModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: VLCMediaLibraryManager, didAddGenres genres: [VLCMLGenre]) {
         genres.forEach({ append($0) })

+ 2 - 0
SharedSources/MediaLibraryModel/MediaLibraryBaseModel.swift

@@ -15,6 +15,8 @@ protocol MediaLibraryBaseModel {
 
     var anyfiles: [VLCMLObject] { get }
 
+    var sortModel: SortModel { get }
+
     var updateView: (() -> Void)? { get set }
 
     var indicatorName: String { get }

+ 13 - 0
SharedSources/MediaLibraryModel/PlaylistModel.swift

@@ -12,6 +12,9 @@
 class PlaylistModel: MLBaseModel {
     typealias MLType = VLCMLPlaylist
 
+    var sortModel = SortModel(alpha: true,
+                              duration: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLPlaylist]()
@@ -52,6 +55,16 @@ class PlaylistModel: MLBaseModel {
     }
 }
 
+// MARK: - Sort
+
+extension PlaylistModel {
+    func sort(by criteria: VLCMLSortingCriteria) {
+        files = medialibrary.playlists(sortingCriteria: criteria)
+        sortModel.currentSort = criteria
+        updateView?()
+    }
+}
+
 extension PlaylistModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: VLCMediaLibraryManager, didAddPlaylists playlists: [VLCMLPlaylist]) {
         playlists.forEach({ append($0) })

+ 14 - 0
SharedSources/MediaLibraryModel/ShowEpisodeModel.swift

@@ -12,6 +12,12 @@
 class ShowEpisodeModel: MLBaseModel {
     typealias MLType = VLCMLMedia
 
+    var sortModel = SortModel(alpha: true,
+                              duration: true,
+                              insertionDate: true,
+                              releaseDate: true,
+                              fileSize: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLMedia]()
@@ -36,6 +42,14 @@ class ShowEpisodeModel: MLBaseModel {
     }
 }
 
+// MARK: - Sort
+
+extension ShowEpisodeModel {
+    func sort(by criteria: VLCMLSortingCriteria) {
+        // Currently no show specific getter on medialibrary.
+    }
+}
+
 extension ShowEpisodeModel: MediaLibraryObserver {
     func medialibrary(_ medialibrary: VLCMediaLibraryManager, didAddShowEpisodes showEpisodes: [VLCMLMedia]) {
         showEpisodes.forEach({ append($0) })

+ 8 - 1
SharedSources/MediaLibraryModel/VideoModel.swift

@@ -12,6 +12,12 @@
 class VideoModel: MediaModel {
     typealias MLType = VLCMLMedia
 
+    var sortModel = SortModel(alpha: true,
+                              duration: true,
+                              insertionDate: true,
+                              releaseDate: true,
+                              fileSize: true)
+
     var updateView: (() -> Void)?
 
     var files = [VLCMLMedia]()
@@ -42,7 +48,8 @@ extension VideoModel: EditableMLModel {
 
 extension VideoModel {
     func sort(by criteria: VLCMLSortingCriteria) {
-        files = medialibrary.media(ofType: .video, sortingCriteria: criteria, desc: false)
+        files = medialibrary.media(ofType: .video, sortingCriteria: criteria)
+        sortModel.currentSort = criteria
         updateView?()
     }
 }

+ 88 - 0
Sources/Coordinators/SortModel.swift

@@ -0,0 +1,88 @@
+/*****************************************************************************
+ * SortModel.swift
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2018 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Carola Nitz <nitz.carola # gmail.com>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+struct SortModel {
+    var currentSort: VLCMLSortingCriteria
+    var desc: Bool
+    var sortingCriteria: [Bool]
+
+    init(alpha: Bool = true,
+         duration: Bool = false,
+         insertionDate: Bool = false,
+         lastModificationDate: Bool = false,
+         releaseDate: Bool = false,
+         fileSize: Bool = false,
+         artist: Bool = false,
+         playCount: Bool = false,
+         album: Bool = false,
+         filename: Bool = false,
+         trackNumber: Bool = false) {
+
+        currentSort = .default
+        desc = false
+        // The first element of this array should always be VLCMLSortingCriteriaDefault
+        sortingCriteria = [false,
+                           alpha,
+                           duration,
+                           insertionDate,
+                           lastModificationDate,
+                           releaseDate,
+                           fileSize,
+                           artist,
+                           playCount,
+                           album,
+                           filename,
+                           trackNumber]
+    }
+}
+
+// MARK: - VLCMLSortingCriteria extension
+
+extension VLCMLSortingCriteria: CustomStringConvertible {
+    init(value: UInt) {
+        guard let sortingCriteria = VLCMLSortingCriteria(rawValue: value) else {
+            assertionFailure("VLCMLSortingCriteria: Unable to init with the given value: \(value)")
+            self = .default
+            return
+        }
+        self = sortingCriteria
+    }
+
+    public var description: String {
+        switch self {
+        case .alpha:
+            return NSLocalizedString("ALPHA", comment: "")
+        case .duration:
+            return NSLocalizedString("DURATION", comment: "")
+        case .insertionDate:
+            return NSLocalizedString("INSERTION_DATE", comment: "")
+        case .lastModificationDate:
+            return NSLocalizedString("LAST_MODIFICATION_DATE", comment: "")
+        case .releaseDate:
+            return NSLocalizedString("RELEASE_DATE", comment: "")
+        case .fileSize:
+            return NSLocalizedString("FILE_SIZE", comment: "")
+        case .artist:
+            return NSLocalizedString("ARTIST", comment: "")
+        case .playCount:
+            return NSLocalizedString("PLAY_COUNT", comment: "")
+        case  .album:
+            return NSLocalizedString("ALBUM", comment: "")
+        case .filename:
+            return NSLocalizedString("FILENAME", comment: "")
+        case .trackNumber:
+            return NSLocalizedString("TRACK_NUMBER", comment: "")
+        default:
+            return NSLocalizedString("DEFAULT", comment: "")
+        }
+    }
+}

+ 0 - 21
Sources/Coordinators/SortOption.swift

@@ -1,21 +0,0 @@
-/*****************************************************************************
- * SortOption.swift
- * VLC for iOS
- *****************************************************************************
- * Copyright (c) 2018 VideoLAN. All rights reserved.
- * $Id$
- *
- * Authors: Carola Nitz <nitz.carola # gmail.com>
- *
- * Refer to the COPYING file of the official project for license.
- *****************************************************************************/
-
-enum SortOption: String {
-    case alphabetically = "Name"
-    case insertonDate = "Date"
-    case size = "Size"
-
-    var localizedDescription: String {
-        return NSLocalizedString(rawValue, comment: "")
-    }
-}

+ 29 - 18
Sources/MediaCategories/MediaCategoryViewController.swift

@@ -233,6 +233,35 @@ class VLCMediaCategoryViewController: UICollectionViewController, UICollectionVi
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
         return model.cellType.cellPadding
     }
+
+    override func handleSort() {
+        let sortOptionsAlertController = UIAlertController(title: NSLocalizedString("SORT_BY", comment: ""),
+                                                           message: nil,
+                                                           preferredStyle: .actionSheet)
+
+        var alertActions = [UIAlertAction]()
+
+        for (index, enabled) in model.sortModel.sortingCriteria.enumerated() {
+            guard enabled else { continue }
+            let criteria = VLCMLSortingCriteria(value: UInt(index))
+
+            alertActions.append(UIAlertAction(title: String(describing: criteria), style: .default) {
+                [weak self] action in
+                self?.model.sort(by: criteria)
+            })
+        }
+        alertActions.forEach() { sortOptionsAlertController.addAction($0) }
+
+        let cancelAction = UIAlertAction(title: NSLocalizedString("CANCEL", comment: ""),
+                                         style: .cancel,
+                                         handler: nil)
+
+        sortOptionsAlertController.addAction(cancelAction)
+        sortOptionsAlertController.view.tintColor = UIColor.vlcOrangeTint
+        sortOptionsAlertController.popoverPresentationController?.sourceView = self.view
+
+        present(sortOptionsAlertController, animated: true)
+    }
 }
 
 private extension VLCMediaCategoryViewController {
@@ -267,24 +296,6 @@ private extension VLCMediaCategoryViewController {
     }
 }
 
-// MARK: - Sort
-
-extension VLCMediaCategoryViewController {
-    // FIXME: Need to add a button for ascending/descending result
-    func sortByFileName() {
-        // The issue is that for audio we show title which is quite confusing if we use filename
-        model.sort(by: .alpha)
-    }
-
-    func sortByDate() {
-        model.sort(by: .insertionDate)
-    }
-
-    func sortBySize() {
-        model.sort(by: .fileSize)
-    }
-}
-
 // MARK: - Player
 
 extension VLCMediaCategoryViewController {

+ 13 - 38
Sources/MediaViewControllers/MediaViewController.swift

@@ -39,45 +39,11 @@ class VLCMediaViewController: VLCPagingViewController<VLCLabelCell> {
             navigationController?.navigationBar.prefersLargeTitles = false
         }
         navigationController?.navigationBar.isTranslucent = false
-        sortButton = UIBarButtonItem(title: NSLocalizedString("SORT", comment: ""), style: .plain, target: self, action: #selector(sort))
-        navigationItem.leftBarButtonItem = sortButton
         navigationItem.rightBarButtonItems = [editButtonItem, UIBarButtonItem(customView: rendererButton)]
-    }
-
-    @objc func sort() {
-        // This should be in a subclass
-        let sortOptionsAlertController = UIAlertController(title: NSLocalizedString("SORT_BY", comment: ""), message: nil, preferredStyle: .actionSheet)
-        let sortByNameAction = UIAlertAction(title: SortOption.alphabetically.localizedDescription, style: .default) {
-            [weak self] action in
-            // call medialibrary
-            if let index = self?.currentIndex {
-                let currentViewController = self?.viewControllers[index] as? VLCMediaCategoryViewController
-                currentViewController?.sortByFileName()
-            }
-        }
-        let sortBySizeAction = UIAlertAction(title: SortOption.size.localizedDescription, style: .default) {
-            [weak self] action in
-            if let index = self?.currentIndex {
-                let currentViewController = self?.viewControllers[index] as? VLCMediaCategoryViewController
-                currentViewController?.sortBySize()
-            }
-
-        }
-        let sortbyDateAction = UIAlertAction(title: SortOption.insertonDate.localizedDescription, style: .default) {
-            [weak self] action in
-            if let index = self?.currentIndex {
-                let currentViewController = self?.viewControllers[index] as? VLCMediaCategoryViewController
-                currentViewController?.sortByDate()
-            }
-        }
-        let cancelAction = UIAlertAction(title: NSLocalizedString("CANCEL", comment: ""), style: .cancel, handler: nil)
-        sortOptionsAlertController.addAction(sortByNameAction)
-        sortOptionsAlertController.addAction(sortbyDateAction)
-        sortOptionsAlertController.addAction(sortBySizeAction)
-        sortOptionsAlertController.addAction(cancelAction)
-        sortOptionsAlertController.view.tintColor = .vlcOrangeTint
-        sortOptionsAlertController.popoverPresentationController?.sourceView = self.view
-        present(sortOptionsAlertController, animated: true)
+        navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("SORT", comment: ""),
+                                                           style: .plain,
+                                                           target: self,
+                                                           action: #selector(handleSort))
     }
 
     // MARK: - PagerTabStripDataSource
@@ -105,4 +71,13 @@ class VLCMediaViewController: VLCPagingViewController<VLCLabelCell> {
         navigationItem.leftBarButtonItem = editing ? nil : sortButton
         viewControllers[currentIndex].setEditing(editing, animated: animated)
     }
+
+    // Hack to send to the child vc the sort event
+    override func handleSort() {
+        viewControllers[currentIndex].handleSort()
+    }
+}
+
+extension UIViewController {
+    @objc func handleSort() {}
 }

+ 4 - 4
VLC.xcodeproj/project.pbxproj

@@ -18,7 +18,7 @@
 		41273A3D1A955C4100A2EF77 /* VLCMigrationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 41273A3B1A955C4100A2EF77 /* VLCMigrationViewController.xib */; };
 		41364DF621FF5B7D00AC22B3 /* ArtistCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41364DF521FF5B7D00AC22B3 /* ArtistCollectionViewCell.swift */; };
 		41364DF821FF5D2600AC22B3 /* ArtistCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 41364DF721FF5D2600AC22B3 /* ArtistCollectionViewCell.xib */; };
-		413EC987201A329D00BF412F /* SortOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413EC986201A329D00BF412F /* SortOption.swift */; };
+		413EC987201A329D00BF412F /* SortModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413EC986201A329D00BF412F /* SortModel.swift */; };
 		413EC98B201B4F2C00BF412F /* PresentationTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 413EC98A201B4F2B00BF412F /* PresentationTheme.swift */; };
 		414327A521B6E55700B061F6 /* PlaybackSpeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414327A421B6E55700B061F6 /* PlaybackSpeedView.swift */; };
 		414327A721B6E66E00B061F6 /* PlaybackSpeedView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 414327A621B6E66E00B061F6 /* PlaybackSpeedView.xib */; };
@@ -425,7 +425,7 @@
 		412BE7521FC4947400ACCC42 /* VLCMediaSubcategory+VLCDragAndDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "VLCMediaSubcategory+VLCDragAndDrop.swift"; path = "Sources/VLCMediaSubcategory+VLCDragAndDrop.swift"; sourceTree = SOURCE_ROOT; };
 		41364DF521FF5B7D00AC22B3 /* ArtistCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtistCollectionViewCell.swift; sourceTree = "<group>"; };
 		41364DF721FF5D2600AC22B3 /* ArtistCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ArtistCollectionViewCell.xib; sourceTree = "<group>"; };
-		413EC986201A329D00BF412F /* SortOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SortOption.swift; path = Sources/Coordinators/SortOption.swift; sourceTree = SOURCE_ROOT; };
+		413EC986201A329D00BF412F /* SortModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SortModel.swift; path = Sources/Coordinators/SortModel.swift; sourceTree = SOURCE_ROOT; };
 		413EC98A201B4F2B00BF412F /* PresentationTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresentationTheme.swift; sourceTree = "<group>"; };
 		414327A421B6E55700B061F6 /* PlaybackSpeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PlaybackSpeedView.swift; path = Sources/PlaybackSpeedView.swift; sourceTree = "<group>"; };
 		414327A621B6E66E00B061F6 /* PlaybackSpeedView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = PlaybackSpeedView.xib; path = Resources/PlaybackSpeedView.xib; sourceTree = "<group>"; };
@@ -1117,7 +1117,7 @@
 			children = (
 				41251ECE1FD0CF7900099110 /* AppCoordinator.swift */,
 				418B144C20179C74000447AA /* VLCTabBarCoordinator.swift */,
-				413EC986201A329D00BF412F /* SortOption.swift */,
+				413EC986201A329D00BF412F /* SortModel.swift */,
 				414396C12023316C005E3FAF /* AppearanceManager.swift */,
 			);
 			name = Coordinators;
@@ -2896,7 +2896,7 @@
 				CA9734B521083EDA00BBE7C7 /* VLCSettingsSheetCell.swift in Sources */,
 				8DE1887621089BB100A091D2 /* VideoModel.swift in Sources */,
 				DD3EFF351BDEBCE500B68579 /* VLCLocalNetworkServiceBrowserNetService.m in Sources */,
-				413EC987201A329D00BF412F /* SortOption.swift in Sources */,
+				413EC987201A329D00BF412F /* SortModel.swift in Sources */,
 				41B93C011A53833B00102E8B /* VLCProgressView.m in Sources */,
 				417CDA231A48D1F300D9ACE7 /* VLCCloudServicesTableViewController.m in Sources */,
 				418B145920179E50000447AA /* VLCDragAndDropManager.swift in Sources */,