Эх сурвалжийг харах

Merge pull request #1959 from nextcloud/ImprovedVideo

Improved video
Marino Faggiana 3 жил өмнө
parent
commit
f0b1f44983

+ 0 - 8
Nextcloud.xcodeproj/project.pbxproj

@@ -392,9 +392,7 @@
 		F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */; };
 		F7F1E54C2492369A00E42386 /* NCMediaCommandView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */; };
 		F7F4F0F727ECDBA4008676F9 /* NCSubtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F0F327ECDBA4008676F9 /* NCSubtitles.swift */; };
-		F7F4F0F827ECDBA4008676F9 /* NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F0F427ECDBA4008676F9 /* NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift */; };
 		F7F4F0F927ECDBA4008676F9 /* NCSubtitlePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F0F527ECDBA4008676F9 /* NCSubtitlePlayer.swift */; };
-		F7F4F0FA27ECDBA4008676F9 /* NCSubtitlePlayer+PlayerSubtitleDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F4F0F627ECDBA4008676F9 /* NCSubtitlePlayer+PlayerSubtitleDelegate.swift */; };
 		F7F4F10527ECDBDB008676F9 /* Inconsolata-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */; };
 		F7F4F10627ECDBDB008676F9 /* Inconsolata-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FE27ECDBDB008676F9 /* Inconsolata-Medium.ttf */; };
 		F7F4F10727ECDBDB008676F9 /* Inconsolata-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F7F4F0FF27ECDBDB008676F9 /* Inconsolata-Black.ttf */; };
@@ -916,9 +914,7 @@
 		F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCMediaCommandView.xib; sourceTree = "<group>"; };
 		F7F35B592578FB63003F5589 /* CollaboraOnlineWebViewKeyboardManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CollaboraOnlineWebViewKeyboardManager.framework; path = Carthage/Build/iOS/CollaboraOnlineWebViewKeyboardManager.framework; sourceTree = "<group>"; };
 		F7F4F0F327ECDBA4008676F9 /* NCSubtitles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSubtitles.swift; sourceTree = "<group>"; };
-		F7F4F0F427ECDBA4008676F9 /* NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift"; sourceTree = "<group>"; };
 		F7F4F0F527ECDBA4008676F9 /* NCSubtitlePlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCSubtitlePlayer.swift; sourceTree = "<group>"; };
-		F7F4F0F627ECDBA4008676F9 /* NCSubtitlePlayer+PlayerSubtitleDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCSubtitlePlayer+PlayerSubtitleDelegate.swift"; sourceTree = "<group>"; };
 		F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-SemiBold.ttf"; sourceTree = "<group>"; };
 		F7F4F0FE27ECDBDB008676F9 /* Inconsolata-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Medium.ttf"; sourceTree = "<group>"; };
 		F7F4F0FF27ECDBDB008676F9 /* Inconsolata-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Black.ttf"; sourceTree = "<group>"; };
@@ -1693,9 +1689,7 @@
 			isa = PBXGroup;
 			children = (
 				F7F4F0F327ECDBA4008676F9 /* NCSubtitles.swift */,
-				F7F4F0F427ECDBA4008676F9 /* NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift */,
 				F7F4F0F527ECDBA4008676F9 /* NCSubtitlePlayer.swift */,
-				F7F4F0F627ECDBA4008676F9 /* NCSubtitlePlayer+PlayerSubtitleDelegate.swift */,
 			);
 			path = NCSubtitle;
 			sourceTree = "<group>";
@@ -2537,7 +2531,6 @@
 				F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */,
 				F7A80BCB252624C100C7CD01 /* NCFileViewInFolder.swift in Sources */,
 				F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */,
-				F7F4F0FA27ECDBA4008676F9 /* NCSubtitlePlayer+PlayerSubtitleDelegate.swift in Sources */,
 				F77910AB25DD53C700CEDB9E /* NCSettingsBundleHelper.swift in Sources */,
 				AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
 				F78A18B623CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift in Sources */,
@@ -2637,7 +2630,6 @@
 				F7CBC31C24F78E79004D3812 /* NCSortMenu.swift in Sources */,
 				F769454822E9F20D000A798A /* NCShareNetworking.swift in Sources */,
 				F7C9555521F0C5470024296E /* NCActivity.swift in Sources */,
-				F7F4F0F827ECDBA4008676F9 /* NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift in Sources */,
 				F7725A60251F33BB00D125E0 /* NCFiles.swift in Sources */,
 				F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */,
 				F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */,

+ 5 - 9
iOSClient/Data/NCManageDatabase+Metadata.swift

@@ -808,22 +808,18 @@ extension NCManageDatabase {
         return getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView == %@", account, serverUrl, fileNameConflict))
     }
 
-    func getSubtitles(account: String, serverUrl: String, fileName: String, exists: Bool) -> [tableMetadata] {
+    func getSubtitles(account: String, serverUrl: String, fileName: String) -> (all:[tableMetadata], exists:[tableMetadata]) {
 
         let realm = try! Realm()
         let nameOnly = (fileName as NSString).deletingPathExtension + "."
         var metadatas: [tableMetadata] = []
 
         let results = realm.objects(tableMetadata.self).filter("account == %@ AND serverUrl == %@ AND fileName BEGINSWITH[c] %@ AND fileName ENDSWITH[c] '.srt'", account, serverUrl, nameOnly)
-        if exists {
-            for result in results {
-                if CCUtility.fileProviderStorageExists(result) {
-                    metadatas.append(result)
-                }
+        for result in results {
+            if CCUtility.fileProviderStorageExists(result) {
+                metadatas.append(result)
             }
-            return Array(metadatas.map { tableMetadata.init(value: $0) })
-        } else {
-            return Array(results.map { tableMetadata.init(value: $0) })
         }
+        return(Array(results.map { tableMetadata.init(value: $0) }), Array(metadatas.map { tableMetadata.init(value: $0) }))
     }
 }

+ 0 - 16
iOSClient/Extensions/String+Extensions.swift

@@ -27,22 +27,6 @@ import CommonCrypto
 
 extension String {
 
-    func urlSafeBase64Decoded() -> String? {
-        var st = self
-            .replacingOccurrences(of: "_", with: "/")
-            .replacingOccurrences(of: "-", with: "+")
-        let remainder = self.count % 4
-        if remainder > 0 {
-            st = self.padding(toLength: self.count + 4 - remainder,
-                              withPad: "=",
-                              startingAt: 0)
-        }
-        guard let d = Data(base64Encoded: st, options: .ignoreUnknownCharacters) else {
-            return nil
-        }
-        return String(data: d, encoding: .utf8)
-    }
-
     var alphanumeric: String {
         return self.components(separatedBy: CharacterSet.alphanumerics.inverted).joined().lowercased()
     }

+ 2 - 2
iOSClient/Extensions/UIDevice+Extensions.swift

@@ -3,9 +3,9 @@
 //  Nextcloud
 //
 //  Created by Federico Malagoni on 23/02/22.
-//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//  Copyright © 2022 Federico Malagoni. All rights reserved.
 //
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//  Author Federico Malagoni <federico.malagoni@astrairidium.com>
 //
 //  This program is free software: you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by

+ 3 - 0
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -847,3 +847,6 @@
 "_conversion_max_compatibility_"    = "Max compatibility, the conversion can take much longer";
 "_video_tap_for_close_"     = "A slight pressure to close the processing";
 "_subtitle_not_found_"      = "Subtitle not found";
+"_disable_"                 = "Disable";
+"_subtitle_not_dowloaded_"  = "There are subtitles not downloaded locally";
+

+ 16 - 12
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift

@@ -38,6 +38,9 @@ class NCPlayer: NSObject {
     internal var autoPlay: Bool
     internal var isProxy: Bool
     internal var isStartPlayer: Bool
+    internal var isStartObserver: Bool
+    internal var subtitleUrls: [URL] = []
+    internal var currentSubtitle: URL?
 
     private weak var imageVideoContainer: imageVideoContainerView?
     private weak var detailView: NCViewerMediaDetailView?
@@ -50,13 +53,6 @@ class NCPlayer: NSObject {
     public var metadata: tableMetadata
     public var videoLayer: AVPlayerLayer?
 
-    public var isSubtitleShowed: Bool = false{
-        didSet {
-            self.playerToolBar?.changeSubtitleIconTo(visible: isSubtitleShowed)
-        }
-    }
-    public var subtitleUrls: [URL] = []
-
     // MARK: - View Life Cycle
 
     init(url: URL, autoPlay: Bool, isProxy: Bool, imageVideoContainer: imageVideoContainerView, playerToolBar: NCPlayerToolBar?, metadata: tableMetadata, detailView: NCViewerMediaDetailView?, viewController: UIViewController) {
@@ -65,6 +61,7 @@ class NCPlayer: NSObject {
         self.autoPlay = autoPlay
         self.isProxy = isProxy
         self.isStartPlayer = false
+        self.isStartObserver = false
         self.imageVideoContainer = imageVideoContainer
         self.playerToolBar = playerToolBar
         self.metadata = metadata
@@ -105,15 +102,18 @@ class NCPlayer: NSObject {
 #endif
 
         // Check already started
-        if isStartPlayer { return }
-
-        playerToolBar?.show()
-        setUpForSubtitle()
-        isSubtitleShowed = false
+        if isStartPlayer {
+            if !isStartObserver {
+                activateObserver()
+            }
+            return
+        }
 
         print("Play URL: \(self.url)")
         player = AVPlayer(url: self.url)
+        playerToolBar?.show()
         playerToolBar?.setMetadata(self.metadata)
+        setUpForSubtitle()
 
         if metadata.livePhoto {
             player?.isMuted = false
@@ -266,6 +266,8 @@ class NCPlayer: NSObject {
         if let player = self.player {
             NotificationCenter.default.addObserver(self, selector: #selector(playerStalled), name: NSNotification.Name.AVPlayerItemPlaybackStalled, object: player.currentItem)
         }
+
+        isStartObserver = true
     }
 
     func deactivateObserver() {
@@ -299,6 +301,8 @@ class NCPlayer: NSObject {
 
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterPauseMedia), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterPlayMedia), object: nil)
+
+        isStartObserver = false
     }
 
     // MARK: - NotificationCenter

+ 17 - 4
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift

@@ -54,6 +54,19 @@ class NCPlayerToolBar: UIView {
     private var playbackSliderEvent: sliderEventType = .ended
     private var timerAutoHide: Timer?
 
+    private var timerAutoHideSeconds: Double {
+        get {
+            if NCUtility.shared.isSimulator() { // for test
+                return 15
+            } else {
+                return 3.5
+            }
+        }
+    }
+
+
+// NCUtility.shared.isSimulatorOrTestFlight()
+
     var pictureInPictureController: AVPictureInPictureController?
     weak var viewerMediaPage: NCViewerMediaPage?
 
@@ -84,8 +97,8 @@ class NCPlayerToolBar: UIView {
         muteButton.setImage(NCUtility.shared.loadImage(named: "audioOff", color: .lightGray), for: .normal)
         muteButton.isEnabled = false
 
-        subtitleButton.setImage(NCUtility.shared.loadImage(named: "captions.bubble", color: .lightGray), for: .normal)
-        subtitleButton.isEnabled = false
+        subtitleButton.setImage(NCUtility.shared.loadImage(named: "captions.bubble", color: .white), for: .normal)
+        subtitleButton.isEnabled = true
         subtitleButton.isHidden = true
 
         playbackSlider.value = 0
@@ -319,7 +332,7 @@ class NCPlayerToolBar: UIView {
     private func startTimerAutoHide() {
 
         timerAutoHide?.invalidate()
-        timerAutoHide = Timer.scheduledTimer(timeInterval: 3.5, target: self, selector: #selector(automaticHide), userInfo: nil, repeats: false)
+        timerAutoHide = Timer.scheduledTimer(timeInterval: timerAutoHideSeconds, target: self, selector: #selector(automaticHide), userInfo: nil, repeats: false)
     }
 
     private func reStartTimerAutoHide() {
@@ -496,7 +509,7 @@ class NCPlayerToolBar: UIView {
     }
 
     @IBAction func tapSubtitle(_ sender: Any) {
-        self.subtitleIconTapped()
+        self.ncplayer?.showAlertSubtitles()
     }
 
     func forward() {

+ 0 - 56
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift

@@ -1,56 +0,0 @@
-//
-//  NCPlayerToolBar+SubtitlePlayerToolBarDelegate.swift
-//  Nextcloud
-//
-//  Created by Federico Malagoni on 11/03/22.
-//  Copyright © 2022 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import Foundation
-
-protocol SubtitlePlayerToolBarDelegate: AnyObject {
-    func subtitleIconTapped()
-    func changeSubtitleIconTo(visible: Bool)
-    func showIconSubtitle()
-}
-
-extension NCPlayerToolBar: SubtitlePlayerToolBarDelegate {
-
-    func subtitleIconTapped() {
-
-        self.ncplayer?.hideOrShowSubtitle()
-    }
-
-    func changeSubtitleIconTo(visible: Bool) {
-
-        let color: UIColor = visible ? .white : .lightGray
-        self.subtitleButton.setImage(NCUtility.shared.loadImage(named: "captions.bubble", color: color), for: .normal)
-    }
-
-    func showIconSubtitle() {
-
-        self.subtitleButton.isEnabled = true
-        self.subtitleButton.isHidden = false
-    }
-
-    func hideIconSubtitle() {
-
-        self.subtitleButton.isEnabled = false
-        self.subtitleButton.isHidden = true
-    }
-}

+ 0 - 94
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitlePlayer+PlayerSubtitleDelegate.swift

@@ -1,94 +0,0 @@
-//
-//  NCSubtitlePlayer+PlayerSubtitleDelegate.swift
-//  Nextcloud
-//
-//  Created by Federico Malagoni on 11/03/22.
-//  Copyright © 2022 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import Foundation
-import NCCommunication
-import UIKit
-import AVFoundation
-import MediaPlayer
-import Alamofire
-import RealmSwift
-
-public protocol PlayerSubtitleDelegate: AnyObject {
-    func hideOrShowSubtitle()
-    func showAlertSubtitles()
-}
-
-extension NCPlayer: PlayerSubtitleDelegate {
-
-    func hideOrShowSubtitle() {
-        if self.isSubtitleShowed {
-            self.hideSubtitle()
-            self.isSubtitleShowed = false
-        } else {
-            self.showAlertSubtitles()
-        }
-    }
-
-    internal func showAlertSubtitles() {
-
-        let alert = UIAlertController(title: nil, message: NSLocalizedString("_subtitle_", comment: ""), preferredStyle: .actionSheet)
-
-        for url in subtitleUrls {
-
-            print("Play Subtitle at:\n\(url.path)")
-
-            let videoUrlTitle = self.metadata.fileName.alphanumeric.dropLast(3)
-            let subtitleUrlTitle = url.lastPathComponent.alphanumeric.dropLast(3)
-
-            var titleSubtitle = String(subtitleUrlTitle.dropFirst(videoUrlTitle.count))
-            if titleSubtitle.isEmpty {
-                titleSubtitle = NSLocalizedString("_subtitle_", comment: "")
-            }
-
-            alert.addAction(UIAlertAction(title: titleSubtitle, style: .default, handler: { [self] _ in
-
-                if NCUtilityFileSystem.shared.getFileSize(filePath: url.path) > 0 {
-
-                    self.open(fileFromLocal: url)
-                    if let viewController = viewController {
-                        self.addSubtitlesTo(viewController, self.playerToolBar)
-                        self.isSubtitleShowed = true
-                        self.showSubtitle()
-                    }
-
-                } else {
-
-                    let alertError = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_subtitle_not_found_", comment: ""), preferredStyle: .alert)
-                    alertError.addAction(UIKit.UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: nil))
-
-                    viewController?.present(alertError, animated: true, completion: nil)
-                    self.isSubtitleShowed = false
-                }
-            }))
-        }
-
-        alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in
-            self.isSubtitleShowed = false
-        }))
-
-        alert.popoverPresentationController?.sourceView = self.viewController?.view
-
-        self.viewController?.present(alert, animated: true, completion: nil)
-    }
-}

+ 71 - 9
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCSubtitle/NCSubtitlePlayer.swift

@@ -4,8 +4,10 @@
 //
 //  Created by Federico Malagoni on 18/02/22.
 //  Copyright © 2022 Federico Malagoni. All rights reserved.
+//  Copyright © 2022 Marino Faggiana All rights reserved.
 //
 //  Author Federico Malagoni <federico.malagoni@astrairidium.com>
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //
 //  This program is free software: you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -124,23 +126,25 @@ extension NCPlayer {
                 }
             }
         }
-        let subtitles = NCManageDatabase.shared.getSubtitles(account: metadata.account, serverUrl: metadata.serverUrl, fileName: metadata.fileName, exists: true)
-        if !subtitles.isEmpty {
-            for subtitle in subtitles {
+        let results = NCManageDatabase.shared.getSubtitles(account: metadata.account, serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+        if !results.exists.isEmpty {
+            for subtitle in results.exists {
                 let subtitleUrl = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(subtitle.ocId, fileNameView: subtitle.fileName))
                 self.subtitleUrls.append(subtitleUrl)
             }
         }
+        if results.all.count != results.exists.count {
+            NCContentPresenter.shared.messageNotification("_info_", description: "_subtitle_not_dowloaded_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorNoError)
+        }
         self.setSubtitleToolbarIcon(subtitleUrls: subtitleUrls)
         self.hideSubtitle()
-        self.isSubtitleShowed = false
     }
 
     func setSubtitleToolbarIcon(subtitleUrls: [URL]) {
         if subtitleUrls.isEmpty {
-            self.playerToolBar?.hideIconSubtitle()
+            playerToolBar?.subtitleButton.isHidden = true
         } else {
-            self.playerToolBar?.showIconSubtitle()
+            playerToolBar?.subtitleButton.isHidden = false
         }
     }
 
@@ -163,11 +167,11 @@ extension NCPlayer {
          }
     }
 
-    func open(fileFromLocal filePath: URL) {
+    func open(fileFromLocal url: URL) {
 
         subtitleLabel?.text = ""
 
-        self.loadText(filePath: filePath) { contents in
+        self.loadText(filePath: url) { contents in
             guard let contents = contents else {
                 return
             }
@@ -181,11 +185,13 @@ extension NCPlayer {
     @objc public func hideSubtitle() {
         self.subtitleLabel?.isHidden = true
         self.subtitleContainerView?.isHidden = true
+        self.currentSubtitle = nil
     }
 
-    @objc public func showSubtitle() {
+    @objc public func showSubtitle(url: URL) {
         self.subtitleLabel?.isHidden = false
         self.subtitleContainerView?.isHidden = false
+        self.currentSubtitle = url
     }
 
     private func show(subtitles string: String) {
@@ -340,4 +346,60 @@ extension NCPlayer {
         vc.view?.addConstraint(subtitleLabelWidthConstraint!)
         vc.view?.addConstraint(subtitleLabelBottomConstraint!)
     }
+
+    internal func showAlertSubtitles() {
+
+        let alert = UIAlertController(title: nil, message: NSLocalizedString("_subtitle_", comment: ""), preferredStyle: .actionSheet)
+
+        for url in subtitleUrls {
+
+            print("Play Subtitle at:\n\(url.path)")
+
+            let videoUrlTitle = self.metadata.fileName.alphanumeric.dropLast(3)
+            let subtitleUrlTitle = url.lastPathComponent.alphanumeric.dropLast(3)
+
+            var titleSubtitle = String(subtitleUrlTitle.dropFirst(videoUrlTitle.count))
+            if titleSubtitle.isEmpty {
+                titleSubtitle = NSLocalizedString("_subtitle_", comment: "")
+            }
+
+            let action = UIAlertAction(title: titleSubtitle, style: .default, handler: { [self] _ in
+
+                if NCUtilityFileSystem.shared.getFileSize(filePath: url.path) > 0 {
+
+                    self.open(fileFromLocal: url)
+                    if let viewController = viewController {
+                        self.addSubtitlesTo(viewController, self.playerToolBar)
+                        self.showSubtitle(url: url)
+                    }
+
+                } else {
+
+                    let alertError = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: NSLocalizedString("_subtitle_not_found_", comment: ""), preferredStyle: .alert)
+                    alertError.addAction(UIKit.UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: nil))
+
+                    viewController?.present(alertError, animated: true, completion: nil)
+                }
+            })
+            alert.addAction(action)
+            if currentSubtitle == url {
+                action.setValue(true, forKey: "checked")
+            }
+        }
+
+        let disable = UIAlertAction(title: NSLocalizedString("_disable_", comment: ""), style: .default, handler: { _ in
+            self.hideSubtitle()
+        })
+        alert.addAction(disable)
+        if currentSubtitle == nil {
+            disable.setValue(true, forKey: "checked")
+        }
+
+        alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in
+        }))
+
+        alert.popoverPresentationController?.sourceView = self.viewController?.view
+
+        self.viewController?.present(alert, animated: true, completion: nil)
+    }
 }