Browse Source

Add Corespotlight

Carola Nitz 6 years ago
parent
commit
6e651f3db7

+ 91 - 0
SharedSources/MediaLibraryModel/MediaModel.swift

@@ -63,3 +63,94 @@ extension VLCMLMedia {
         return integer == 0
     }
 }
+
+// MARK: - CoreSpotlight
+
+extension VLCMLMedia {
+    func coreSpotlightAttributeSet() -> CSSearchableItemAttributeSet {
+        let attributeSet = CSSearchableItemAttributeSet(itemContentType: "public.audiovisual-content")
+        attributeSet.title = title
+        attributeSet.metadataModificationDate = Date()
+        attributeSet.addedDate = Date()
+        attributeSet.duration = NSNumber(value: duration() / 1000)
+        attributeSet.streamable = 0
+        attributeSet.deliveryType = 0
+        attributeSet.local = 1
+        attributeSet.playCount = NSNumber(value: playCount())
+        if isThumbnailGenerated() {
+            attributeSet.thumbnailData = UIImage(contentsOfFile: thumbnail.path)?.jpegData(compressionQuality: 0.9)
+        }
+        attributeSet.codecs = codecs()
+        attributeSet.languages = languages()
+        if let audioTracks = audioTracks {
+            for track in audioTracks {
+                attributeSet.audioBitRate = NSNumber(value: track.bitrate())
+                attributeSet.audioChannelCount = NSNumber(value: track.nbChannels())
+                attributeSet.audioSampleRate = NSNumber(value: track.sampleRate())
+            }
+        }
+        if let albumTrack = albumTrack {
+            if let genre = albumTrack.genre {
+                attributeSet.genre = genre.name
+            }
+            if let artist = albumTrack.artist {
+                attributeSet.artist = artist.name
+            }
+            attributeSet.audioTrackNumber = NSNumber(value:albumTrack.trackNumber())
+            if let album = albumTrack.album {
+                attributeSet.artist = album.title
+            }
+        }
+
+        return attributeSet
+    }
+
+    func codecs() -> [String] {
+        var codecs = [String]()
+        if let videoTracks = videoTracks {
+            for track in videoTracks {
+                codecs.append(track.codec)
+            }
+        }
+        if let audioTracks = audioTracks {
+            for track in audioTracks {
+                codecs.append(track.codec)
+            }
+        }
+        if let subtitleTracks = subtitleTracks {
+            for track in subtitleTracks {
+                codecs.append(track.codec)
+            }
+        }
+        return codecs
+    }
+
+    func languages() -> [String] {
+        var languages = [String]()
+
+        if let videoTracks = videoTracks {
+            for track in videoTracks where track.language != "" {
+                languages.append(track.language)
+            }
+        }
+        if let audioTracks = audioTracks {
+            for track in audioTracks where track.language != "" {
+                languages.append(track.language)
+            }
+        }
+        if let subtitleTracks = subtitleTracks {
+            for track in subtitleTracks where track.language != "" {
+                languages.append(track.language)
+            }
+        }
+        return languages
+    }
+
+    func updateCoreSpotlightEntry() {
+        if !KeychainCoordinator.passcodeLockEnabled {
+            let groupIdentifier = ProcessInfo.processInfo.environment["GROUP_IDENTIFIER"]
+            let item = CSSearchableItem(uniqueIdentifier: "\(identifier())", domainIdentifier: groupIdentifier, attributeSet: coreSpotlightAttributeSet())
+            CSSearchableIndex.default().indexSearchableItems([item], completionHandler: nil)
+        }
+    }
+}

+ 16 - 1
SharedSources/MediaLibraryService.swift

@@ -289,12 +289,16 @@ extension MediaLibraryService {
                               : medialib.audioFiles(with: sort, desc: desc) ?? []
     }
 
-    func fetchMedia(with mrl: URL?) -> VLCMLMedia? {
+    @objc func fetchMedia(with mrl: URL?) -> VLCMLMedia? {
         guard let mrl = mrl  else {
             return nil
         }
         return medialib.media(withMrl: mrl)
     }
+
+    @objc func media(for identifier: VLCMLIdentifier) -> VLCMLMedia? {
+        return medialib.media(withIdentifier: identifier)
+    }
 }
 
 // MARK: - Audio methods
@@ -378,6 +382,9 @@ extension MediaLibraryService: VLCMediaFileDiscovererDelegate {
 
 extension MediaLibraryService: VLCMediaLibraryDelegate {
     func medialibrary(_ medialibrary: VLCMediaLibrary, didAddMedia media: [VLCMLMedia]) {
+
+        media.forEach { $0.updateCoreSpotlightEntry() }
+
         let videos = media.filter {( $0.type() == .video )}
         let audio = media.filter {( $0.type() == .audio )}
 
@@ -391,6 +398,9 @@ extension MediaLibraryService: VLCMediaLibraryDelegate {
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary, didModifyMedia media: [VLCMLMedia]) {
+
+        media.forEach { $0.updateCoreSpotlightEntry() }
+
         let showEpisodes = media.filter {( $0.subtype() == .showEpisode )}
         let albumTrack = media.filter {( $0.subtype() == .albumTrack )}
 
@@ -401,6 +411,11 @@ extension MediaLibraryService: VLCMediaLibraryDelegate {
     }
 
     func medialibrary(_ medialibrary: VLCMediaLibrary, didDeleteMediaWithIds mediaIds: [NSNumber]) {
+
+        var stringIds = [String]()
+        mediaIds.forEach { stringIds.append("\($0)") }
+        CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: stringIds, completionHandler: nil)
+
         for observer in observers {
             observer.value.observer?.medialibrary?(self, didDeleteMediaWithIds: mediaIds)
         }

+ 17 - 1
Sources/Coordinators/AppCoordinator.swift

@@ -17,11 +17,11 @@ class Services: NSObject {
 }
 
 @objc class AppCoordinator: NSObject {
+    private var services = Services()
     private var childCoordinators: [NSObject] = []
     private var playerController: VLCPlayerDisplayController
     private var tabBarController: UITabBarController
     private var tabBarCoordinator: VLCTabBarCoordinator
-    private var services = Services()
     private var migrationViewController = VLCMigrationViewController(nibName: String(describing: VLCMigrationViewController.self),
                                                                      bundle: nil)
 
@@ -57,6 +57,22 @@ class Services: NSObject {
     @objc func handleShortcutItem(_ item: UIApplicationShortcutItem) {
         tabBarCoordinator.handleShortcutItem(item)
     }
+
+    @objc func mediaForUserActivity(_ activity: NSUserActivity) -> VLCMLMedia? {
+        let userActivityType = activity.activityType
+        guard let dict = activity.userInfo else { return nil }
+        var identifier: Int64? = nil
+
+        if userActivityType == CSSearchableItemActionType, let searchIdentifier = dict[CSSearchableItemActivityIdentifier] as? NSString {
+            identifier = Int64(searchIdentifier.integerValue)
+        } else if let mediaIdentifier = dict["playingmedia"] as? Int64 {
+            identifier = mediaIdentifier
+        }
+        guard let mediaIdentifier = identifier else { return nil }
+
+        return services.medialibraryService.media(for: mediaIdentifier)
+    }
+
 }
 
 extension AppCoordinator: MediaLibraryMigrationDelegate {

+ 14 - 0
Sources/MediaCategories/MediaCategoryViewController.swift

@@ -233,11 +233,25 @@ class VLCMediaCategoryViewController: UICollectionViewController, UICollectionVi
     override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
         if let media = model.anyfiles[indexPath.row] as? VLCMLMedia {
             play(media: media)
+            createSpotlightItem(media: media)
         } else if let mediaCollection = model.anyfiles[indexPath.row] as? MediaCollectionModel {
             let collectionViewController = VLCCollectionCategoryViewController(services, mediaCollection: mediaCollection)
             navigationController?.pushViewController(collectionViewController, animated: true)
         }
     }
+
+    func createSpotlightItem(media: VLCMLMedia) {
+        if KeychainCoordinator.passcodeLockEnabled {
+            return
+        }
+        userActivity = NSUserActivity(activityType: kVLCUserActivityPlaying)
+        userActivity?.title = media.title
+        userActivity?.contentAttributeSet = media.coreSpotlightAttributeSet()
+        userActivity?.userInfo = ["playingmedia" : media.identifier()]
+        userActivity?.isEligibleForSearch = true
+        userActivity?.isEligibleForHandoff = true
+        userActivity?.becomeCurrent()
+    }
 }
 
 // MARK: - UICollectionViewDelegateFlowLayout

+ 7 - 39
Sources/VLCAppDelegate.m

@@ -92,10 +92,6 @@
         [self->appCoordinator start];
     };
     [self validatePasscodeIfNeededWithCompletion:setupAppCoordinator];
-
-    BOOL spotlightEnabled = ![VLCKeychainCoordinator passcodeLockEnabled];
-    [[MLMediaLibrary sharedMediaLibrary] setSpotlightIndexingEnabled:spotlightEnabled];
-    [[MLMediaLibrary sharedMediaLibrary] applicationWillStart];
 }
 
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
@@ -152,48 +148,20 @@
 
 - (BOOL)application:(UIApplication *)application willContinueUserActivityWithType:(NSString *)userActivityType
 {
-    if ([userActivityType isEqualToString:kVLCUserActivityLibraryMode] ||
-        [userActivityType isEqualToString:kVLCUserActivityPlaying] ||
-        [userActivityType isEqualToString:kVLCUserActivityLibrarySelection])
-        return YES;
-
-    return NO;
+    return [userActivityType isEqualToString:kVLCUserActivityPlaying];
 }
 
 - (BOOL)application:(UIApplication *)application
 continueUserActivity:(NSUserActivity *)userActivity
  restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *))restorationHandler
 {
-    NSString *userActivityType = userActivity.activityType;
-    NSDictionary *dict = userActivity.userInfo;
-    if([userActivityType isEqualToString:kVLCUserActivityLibraryMode] ||
-       [userActivityType isEqualToString:kVLCUserActivityLibrarySelection]) {
-        //TODO: Add restoreUserActivityState to the mediaviewcontroller
-        _isComingFromHandoff = YES;
-        return YES;
-    } else {
-        NSURL *uriRepresentation = nil;
-        if ([userActivityType isEqualToString:CSSearchableItemActionType]) {
-            uriRepresentation = [NSURL URLWithString:dict[CSSearchableItemActivityIdentifier]];
-        } else {
-            uriRepresentation = dict[@"playingmedia"];
-        }
-
-        if (!uriRepresentation) {
-            return NO;
-        }
+    VLCMLMedia *media = [appCoordinator mediaForUserActivity:userActivity];
+    if (!media) return NO;
 
-        NSManagedObject *managedObject = [[MLMediaLibrary sharedMediaLibrary] objectForURIRepresentation:uriRepresentation];
-        if (managedObject == nil) {
-            APLog(@"%s file not found: %@",__PRETTY_FUNCTION__,userActivity);
-            return NO;
-        }
-        [self validatePasscodeIfNeededWithCompletion:^{
-            [[VLCPlaybackController sharedInstance] openMediaLibraryObject:managedObject];
-        }];
-        return YES;
-    }
-    return NO;
+    [self validatePasscodeIfNeededWithCompletion:^{
+        [[VLCPlaybackController sharedInstance] playMedia:media];
+    }];
+    return YES;
 }
 
 - (void)application:(UIApplication *)application

+ 0 - 2
Sources/VLCConstants.h

@@ -97,8 +97,6 @@
 #define kVLCStoreGDriveCredentials @"kVLCStoreGDriveCredentials"
 
 #define kVLCUserActivityPlaying @"org.videolan.vlc-ios.playing"
-#define kVLCUserActivityLibrarySelection @"org.videolan.vlc-ios.libraryselection"
-#define kVLCUserActivityLibraryMode @"org.videolan.vlc-ios.librarymode"
 
 #define kVLCApplicationShortcutLocalVideo @"ApplicationShortcutLocalVideo"
 #define kVLCApplicationShortcutLocalAudio @"ApplicationShortcutLocalAudio"

+ 4 - 14
Sources/VLCSettingsController.m

@@ -145,17 +145,6 @@ NSString * const kVLCSectionTableHeaderViewIdentifier = @"VLCSectionTableHeaderV
     }
 }
 
-- (void)updateUIAndCoreSpotlightForPasscodeSetting:(BOOL)passcodeOn
-{
-    [self filterCellsWithAnimation:YES];
-
-    [[MLMediaLibrary sharedMediaLibrary] setSpotlightIndexingEnabled:!passcodeOn];
-    if (passcodeOn) {
-        // delete whole index for VLC
-        [[CSSearchableIndex defaultSearchableIndex] deleteAllSearchableItemsWithCompletionHandler:nil];
-    }
-}
-
 - (void)showAbout
 {
     VLCAboutViewController *aboutVC = [[VLCAboutViewController alloc] init];
@@ -191,10 +180,11 @@ NSString * const kVLCSectionTableHeaderViewIdentifier = @"VLCSectionTableHeaderV
     NSError *error = nil;
     [VLCKeychainCoordinator setPasscodeWithPasscode:passcode error:&error];
     if (error == nil) {
+        if (passcode != nil) {
+            [[CSSearchableIndex defaultSearchableIndex] deleteAllSearchableItemsWithCompletionHandler:nil];
+        }
         //Set manually the value to enable/disable the UISwitch.
-        BOOL passcodeEnabled = passcode != nil;
-        [[NSUserDefaults standardUserDefaults] setBool:passcodeEnabled forKey:kVLCSettingPasscodeOnKey];
-        [self updateUIAndCoreSpotlightForPasscodeSetting:passcode != nil];
+        [self filterCellsWithAnimation:YES];
     }
     if ([self.navigationController.presentedViewController isKindOfClass:[UINavigationController class]] && [((UINavigationController *)self.navigationController.presentedViewController).viewControllers.firstObject isKindOfClass:[PAPasscodeViewController class]]) {
         [self.navigationController.presentedViewController dismissViewControllerAnimated:YES completion:nil];