Browse Source

Merge pull request #1721 from marinofaggiana/Refactoring_viewer

Refactoring viewer
Marino Faggiana 3 years ago
parent
commit
68ef6bd395

+ 9 - 21
Nextcloud.xcodeproj/project.pbxproj

@@ -137,7 +137,6 @@
 		F7434B3420E23FD700417916 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7434B3420E23FD700417916 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
 		F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
 		F7434B3820E2400600417916 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
 		F7434B3820E2400600417916 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
-		F744583C270DCFD50004631B /* NCViewerMediaDetailView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F744583B270DCFD50004631B /* NCViewerMediaDetailView.xib */; };
 		F745B253222D88AE00346520 /* NCLoginQRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F745B252222D88AE00346520 /* NCLoginQRCode.swift */; };
 		F745B253222D88AE00346520 /* NCLoginQRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F745B252222D88AE00346520 /* NCLoginQRCode.swift */; };
 		F747BA1F22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */; };
 		F747BA1F22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */; };
 		F749C10B23C4A5340027D966 /* NCIntroCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F749C10723C4A5330027D966 /* NCIntroCollectionViewCell.swift */; };
 		F749C10B23C4A5340027D966 /* NCIntroCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F749C10723C4A5330027D966 /* NCIntroCollectionViewCell.swift */; };
@@ -543,7 +542,6 @@
 		F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrashSectionHeaderFooter.swift; sourceTree = "<group>"; };
 		F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrashSectionHeaderFooter.swift; sourceTree = "<group>"; };
 		F7421EAE2294044B00C4B7C1 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
 		F7421EAE2294044B00C4B7C1 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
 		F7434B5F20E2440600417916 /* FileProviderExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileProviderExtension-Bridging-Header.h"; sourceTree = "<group>"; };
 		F7434B5F20E2440600417916 /* FileProviderExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileProviderExtension-Bridging-Header.h"; sourceTree = "<group>"; };
-		F744583B270DCFD50004631B /* NCViewerMediaDetailView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCViewerMediaDetailView.xib; sourceTree = "<group>"; };
 		F745B250222D871800346520 /* QRCodeReader.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QRCodeReader.framework; path = Carthage/Build/iOS/QRCodeReader.framework; sourceTree = "<group>"; };
 		F745B250222D871800346520 /* QRCodeReader.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QRCodeReader.framework; path = Carthage/Build/iOS/QRCodeReader.framework; sourceTree = "<group>"; };
 		F745B252222D88AE00346520 /* NCLoginQRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginQRCode.swift; sourceTree = "<group>"; };
 		F745B252222D88AE00346520 /* NCLoginQRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCLoginQRCode.swift; sourceTree = "<group>"; };
 		F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCCreateFormUploadVoiceNote.storyboard; sourceTree = "<group>"; };
 		F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCCreateFormUploadVoiceNote.storyboard; sourceTree = "<group>"; };
@@ -921,14 +919,6 @@
 			path = BackgroundImageColor;
 			path = BackgroundImageColor;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
-		F70D08D7270F3A4B0023FC25 /* Zzz */ = {
-			isa = PBXGroup;
-			children = (
-				F744583B270DCFD50004631B /* NCViewerMediaDetailView.xib */,
-			);
-			path = Zzz;
-			sourceTree = "<group>";
-		};
 		F70D87CC25EE6E58008CBBBD /* Rename file */ = {
 		F70D87CC25EE6E58008CBBBD /* Rename file */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -1533,7 +1523,6 @@
 				F7A0D14E259229FA008F8A13 /* Extensions */,
 				F7A0D14E259229FA008F8A13 /* Extensions */,
 				F7BFFA991A24D7BB0044ED85 /* Utility */,
 				F7BFFA991A24D7BB0044ED85 /* Utility */,
 				F79630EC215526B60015EEA5 /* Viewer */,
 				F79630EC215526B60015EEA5 /* Viewer */,
-				F70D08D7270F3A4B0023FC25 /* Zzz */,
 			);
 			);
 			path = iOSClient;
 			path = iOSClient;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -1996,7 +1985,6 @@
 				F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */,
 				F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */,
 				F73CB3B222E072A000AD728E /* NCShareHeaderView.xib in Resources */,
 				F73CB3B222E072A000AD728E /* NCShareHeaderView.xib in Resources */,
 				F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */,
 				F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */,
-				F744583C270DCFD50004631B /* NCViewerMediaDetailView.xib in Resources */,
 				F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */,
 				F7EDE514262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib in Resources */,
 				F78ACD58219048040088454D /* NCSectionHeaderMenu.xib in Resources */,
 				F78ACD58219048040088454D /* NCSectionHeaderMenu.xib in Resources */,
 				F7501C322212E57500FB1415 /* NCMedia.storyboard in Resources */,
 				F7501C322212E57500FB1415 /* NCMedia.storyboard in Resources */,
@@ -2345,7 +2333,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2398,7 +2386,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2442,7 +2430,7 @@
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2487,7 +2475,7 @@
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2539,7 +2527,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2591,7 +2579,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				CODE_SIGN_STYLE = Automatic;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2635,7 +2623,7 @@
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
 				CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements;
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				ENABLE_BITCODE = YES;
 				ENABLE_BITCODE = YES;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2682,7 +2670,7 @@
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				CODE_SIGN_IDENTITY = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
 				COPY_PHASE_STRIP = NO;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 6;
+				CURRENT_PROJECT_VERSION = 9;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				ENABLE_BITCODE = YES;
 				ENABLE_BITCODE = YES;
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
 				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -2951,7 +2939,7 @@
 			repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
 			repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
 			requirement = {
 			requirement = {
 				kind = revision;
 				kind = revision;
-				revision = 763477f64d0d6a8e01b8ba37337fc2ee1363f7aa;
+				revision = 9b748dd71eff508307e6091f790b5a05be0509e4;
 			};
 			};
 		};
 		};
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {

+ 1 - 1
Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -105,7 +105,7 @@
         "repositoryURL": "https://github.com/nextcloud/ios-communication-library/",
         "repositoryURL": "https://github.com/nextcloud/ios-communication-library/",
         "state": {
         "state": {
           "branch": null,
           "branch": null,
-          "revision": "763477f64d0d6a8e01b8ba37337fc2ee1363f7aa",
+          "revision": "9b748dd71eff508307e6091f790b5a05be0509e4",
           "version": null
           "version": null
         }
         }
       },
       },

+ 15 - 0
iOSClient/Images.xcassets/backward.imageset/Contents.json

@@ -0,0 +1,15 @@
+{
+  "images" : [
+    {
+      "filename" : "backward.svg",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  },
+  "properties" : {
+    "preserves-vector-representation" : true
+  }
+}

+ 4 - 0
iOSClient/Images.xcassets/backward.imageset/backward.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+  <path d="M 15 14.1 L 18 12 L 15 9.9 L 15 14.1 M 6 14.1 L 9 12 L 6 9.9 L 6 14.1 M 13 18 L 13 6 L 21.5 12 L 13 18 M 4 18 L 4 6 L 12.5 12 L 4 18 Z" transform="matrix(-1, 0, 0, -1, 25.5, 24)"/>
+</svg>

+ 15 - 0
iOSClient/Images.xcassets/forward.imageset/Contents.json

@@ -0,0 +1,15 @@
+{
+  "images" : [
+    {
+      "filename" : "forward.svg",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  },
+  "properties" : {
+    "preserves-vector-representation" : true
+  }
+}

+ 1 - 0
iOSClient/Images.xcassets/forward.imageset/forward.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M15,9.9L18,12L15,14.1V9.9M6,9.9L9,12L6,14.1V9.9M13,6V18L21.5,12L13,6M4,6V18L12.5,12L4,6Z" /></svg>

+ 1 - 1
iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift

@@ -192,7 +192,7 @@ open class NCAudioRecorder : NSObject {
         super.init()
         super.init()
         
         
         do {
         do {
-            try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
+            try AVAudioSession.sharedInstance().setCategory(.playAndRecord)
             try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
             try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSession.PortOverride.speaker)
             try AVAudioSession.sharedInstance().setActive(true)
             try AVAudioSession.sharedInstance().setActive(true)
         } catch {
         } catch {

+ 0 - 1
iOSClient/Media/NCMedia.swift

@@ -80,7 +80,6 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
         collectionView.alwaysBounceVertical = true
         collectionView.alwaysBounceVertical = true
         collectionView.contentInset = UIEdgeInsets(top: insetsTop, left: 0, bottom: 50, right: 0);
         collectionView.contentInset = UIEdgeInsets(top: insetsTop, left: 0, bottom: 50, right: 0);
         collectionView.backgroundColor = NCBrandColor.shared.systemBackground
         collectionView.backgroundColor = NCBrandColor.shared.systemBackground
-        collectionView.bounces = false
                 
                 
         gridLayout = NCGridMediaLayout()
         gridLayout = NCGridMediaLayout()
         gridLayout.itemForLine = CGFloat(min(CCUtility.getMediaWidthImage(), 5))
         gridLayout.itemForLine = CGFloat(min(CCUtility.getMediaWidthImage(), 5))

+ 78 - 80
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift

@@ -34,8 +34,6 @@ private var activeNCPlayer = Set<NCPlayer>()
 class NCPlayer: NSObject {
 class NCPlayer: NSObject {
    
    
     private let appDelegate = UIApplication.shared.delegate as! AppDelegate
     private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-    private var url: URL?
-    private var imageVideoContainer: imageVideoContainerView?
     private var playerToolBar: NCPlayerToolBar?
     private var playerToolBar: NCPlayerToolBar?
     private var detailView: NCViewerMediaDetailView?
     private var detailView: NCViewerMediaDetailView?
     private var observerAVPlayerItemDidPlayToEndTime: Any?
     private var observerAVPlayerItemDidPlayToEndTime: Any?
@@ -47,19 +45,17 @@ class NCPlayer: NSObject {
     public var videoLayer: AVPlayerLayer?
     public var videoLayer: AVPlayerLayer?
     public var pictureInPictureController: AVPictureInPictureController?
     public var pictureInPictureController: AVPictureInPictureController?
     
     
-    init(url: URL, imageVideoContainer: imageVideoContainerView?, playerToolBar: NCPlayerToolBar?, metadata: tableMetadata, detailView: NCViewerMediaDetailView?) {
-        super.init()
+    // MARK: - View Life Cycle
 
 
-        var timeSeek: CMTime = .zero
+    init(url: URL, autoPlay: Bool, imageVideoContainer: imageVideoContainerView, playerToolBar: NCPlayerToolBar?, metadata: tableMetadata, detailView: NCViewerMediaDetailView?) {
+        super.init()
         
         
-        self.url = url
-        self.playerToolBar = playerToolBar
         self.metadata = metadata
         self.metadata = metadata
         self.detailView = detailView
         self.detailView = detailView
 
 
         do {
         do {
+            try AVAudioSession.sharedInstance().setCategory(.playback)
             try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSession.PortOverride.none)
             try AVAudioSession.sharedInstance().overrideOutputAudioPort(AVAudioSession.PortOverride.none)
-            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: [.allowAirPlay])
             try AVAudioSession.sharedInstance().setActive(true)
             try AVAudioSession.sharedInstance().setActive(true)
         } catch {
         } catch {
             print(error)
             print(error)
@@ -68,6 +64,9 @@ class NCPlayer: NSObject {
         print("Play URL: \(url)")
         print("Play URL: \(url)")
         player = AVPlayer(url: url)
         player = AVPlayer(url: url)
         
         
+        self.durationTime = self.player?.currentItem?.asset.duration ?? .zero
+        NCManageDatabase.shared.addVideoTime(metadata: metadata, time: nil, durationTime: self.durationTime)
+
         if metadata.livePhoto {
         if metadata.livePhoto {
             player?.isMuted = false
             player?.isMuted = false
         } else if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
         } else if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
@@ -75,69 +74,50 @@ class NCPlayer: NSObject {
         } else {
         } else {
             player?.isMuted = CCUtility.getAudioMute()
             player?.isMuted = CCUtility.getAudioMute()
             if let time = NCManageDatabase.shared.getVideoTime(metadata: metadata) {
             if let time = NCManageDatabase.shared.getVideoTime(metadata: metadata) {
-                timeSeek = time
-            }
-        }
-        player?.seek(to: timeSeek)
-        
-        // At end go back to start & show toolbar
-        observerAVPlayerItemDidPlayToEndTime = NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: .main) { (notification) in
-            if let item = notification.object as? AVPlayerItem, let currentItem = self.player?.currentItem, item == currentItem {
-                NCKTVHTTPCache.shared.saveCache(metadata: metadata)
-                self.videoSeek(time: .zero)
-                if !(detailView?.isShow() ?? false) {
-                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":metadata.ocId, "enableTimerAutoHide": false])
-                }
-                playerToolBar?.updateToolBar(commandCenter: true)
+                player?.seek(to: time)
             }
             }
         }
         }
         
         
-        observerAVPlayertTime = player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: .main, using: { (CMTime) in
-            if self.player?.currentItem?.status == .readyToPlay {
-                self.playerToolBar?.updateToolBar()
-            }
-        })
-        
         player?.currentItem?.asset.loadValuesAsynchronously(forKeys: ["playable"], completionHandler: {
         player?.currentItem?.asset.loadValuesAsynchronously(forKeys: ["playable"], completionHandler: {
             var error: NSError? = nil
             var error: NSError? = nil
             let status = self.player?.currentItem?.asset.statusOfValue(forKey: "playable", error: &error)
             let status = self.player?.currentItem?.asset.statusOfValue(forKey: "playable", error: &error)
             switch status {
             switch status {
             case .loaded:
             case .loaded:
                 DispatchQueue.main.async {
                 DispatchQueue.main.async {
-                    if let imageVideoContainer = imageVideoContainer {
-                        
-                        self.imageVideoContainer = imageVideoContainer
-                        self.videoLayer = AVPlayerLayer(player: self.player)
-                        self.videoLayer!.frame = imageVideoContainer.bounds
-                        self.videoLayer!.videoGravity = .resizeAspect
-                        
-                        if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
-                        
-                            imageVideoContainer.layer.addSublayer(self.videoLayer!)
-                            imageVideoContainer.playerLayer = self.videoLayer
-                            imageVideoContainer.metadata = self.metadata
-                            if !metadata.livePhoto {
-                                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
-                                    imageVideoContainer.image = imageVideoContainer.image?.image(alpha: 0)
-                                }
-                            }
-                            
-                            // PIP
-                            if let playerLayer = self.videoLayer, CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) {
-                                self.pictureInPictureController = AVPictureInPictureController(playerLayer: playerLayer)
-                                self.pictureInPictureController?.delegate = self
+                    
+                    self.activateObserver(playerToolBar: playerToolBar)
+                    
+                    self.videoLayer = AVPlayerLayer(player: self.player)
+                    self.videoLayer!.frame = imageVideoContainer.bounds
+                    self.videoLayer!.videoGravity = .resizeAspect
+                    
+                    if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+                    
+                        imageVideoContainer.layer.addSublayer(self.videoLayer!)
+                        imageVideoContainer.playerLayer = self.videoLayer
+                        imageVideoContainer.metadata = self.metadata
+                        if !metadata.livePhoto {
+                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+                                imageVideoContainer.image = imageVideoContainer.image?.image(alpha: 0)
                             }
                             }
                         }
                         }
+                        
+                        // PIP
+                        if let playerLayer = self.videoLayer, CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView), metadata.livePhoto == false {
+                            self.pictureInPictureController = AVPictureInPictureController(playerLayer: playerLayer)
+                            self.pictureInPictureController?.delegate = self
+                        }
                     }
                     }
                     
                     
-                    self.durationTime = self.player?.currentItem?.asset.duration ?? .zero
-                    NCManageDatabase.shared.addVideoTime(metadata: metadata, time: nil, durationTime: self.durationTime)
-                    
-                    self.playerToolBar?.setBarPlayer(ncplayer: self, timeSeek: timeSeek, metadata: metadata, image: imageVideoContainer?.image)
+                    self.playerToolBar?.setBarPlayer(ncplayer: self, metadata: metadata, image: imageVideoContainer.image)
                     self.generatorImagePreview()
                     self.generatorImagePreview()
                     if !(detailView?.isShow() ?? false) {
                     if !(detailView?.isShow() ?? false) {
                         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":metadata.ocId, "enableTimerAutoHide": false])
                         NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":metadata.ocId, "enableTimerAutoHide": false])
                     }
                     }
+
+                    if autoPlay {
+                        self.player?.play()
+                    }
                 }
                 }
                 break
                 break
             case .failed:
             case .failed:
@@ -158,51 +138,68 @@ class NCPlayer: NSObject {
                 break
                 break
             }
             }
         })
         })
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(generatorImagePreview), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil)
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
     }
     }
 
 
     deinit {
     deinit {
         print("deinit NCPlayer")
         print("deinit NCPlayer")
+    }
+    
+    func activateObserver(playerToolBar: NCPlayerToolBar?) {
+        guard let metadata = self.metadata else { return }
         
         
-        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil)
+        self.playerToolBar = playerToolBar
         
         
-        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
-        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
-
-        videoRemoved()
+        // At end go back to start & show toolbar
+        observerAVPlayerItemDidPlayToEndTime = NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: .main) { (notification) in
+            if let item = notification.object as? AVPlayerItem, let currentItem = self.player?.currentItem, item == currentItem {
+                NCKTVHTTPCache.shared.saveCache(metadata: metadata)
+                self.videoSeek(time: .zero)
+                if !(self.detailView?.isShow() ?? false) {
+                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":metadata.ocId, "enableTimerAutoHide": false])
+                }
+                self.playerToolBar?.updateToolBar(commandCenter: true)
+            }
+        }
+        
+        // Evey 1 second update toolbar
+        observerAVPlayertTime = player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: .main, using: { (CMTime) in
+            if self.player?.currentItem?.status == .readyToPlay, let playerToolBar = self.playerToolBar, playerToolBar.isShow() {
+                self.playerToolBar?.updateToolBar()
+            }
+        })
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(generatorImagePreview), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
     }
     }
     
     
-    func videoRemoved() {
-
+    func deactivateObserver(livePhoto: Bool) {
+        
         if isPlay() {
         if isPlay() {
             playerPause()
             playerPause()
         }
         }
-
+        
+        self.playerToolBar?.disableCommandCenter()
+        self.playerToolBar = nil
+        
+        if livePhoto {
+            self.videoLayer?.removeFromSuperlayer()
+            self.videoLayer = nil
+        }
+        
         if let observerAVPlayerItemDidPlayToEndTime = self.observerAVPlayerItemDidPlayToEndTime {
         if let observerAVPlayerItemDidPlayToEndTime = self.observerAVPlayerItemDidPlayToEndTime {
             NotificationCenter.default.removeObserver(observerAVPlayerItemDidPlayToEndTime)
             NotificationCenter.default.removeObserver(observerAVPlayerItemDidPlayToEndTime)
         }
         }
+        self.observerAVPlayerItemDidPlayToEndTime = nil
+        
         if  let observerAVPlayertTime = self.observerAVPlayertTime {
         if  let observerAVPlayertTime = self.observerAVPlayertTime {
             player?.removeTimeObserver(observerAVPlayertTime)
             player?.removeTimeObserver(observerAVPlayertTime)
         }
         }
-        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
-        
-        self.videoLayer?.removeFromSuperlayer()
-        self.videoLayer = nil
-        self.observerAVPlayerItemDidPlayToEndTime = nil
         self.observerAVPlayertTime = nil
         self.observerAVPlayertTime = nil
-        self.imageVideoContainer = nil
-        self.playerToolBar = nil
-        self.metadata = nil
         
         
-        do {
-            try AVAudioSession.sharedInstance().setActive(false)
-        } catch {
-            print(error)
-        }
+        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationWillResignActive), object: nil)
+        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidEnterBackground), object: nil)
+        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterApplicationDidBecomeActive), object: nil)
     }
     }
     
     
     //MARK: - NotificationCenter
     //MARK: - NotificationCenter
@@ -316,6 +313,7 @@ class NCPlayer: NSObject {
 extension NCPlayer: AVPictureInPictureControllerDelegate {
 extension NCPlayer: AVPictureInPictureControllerDelegate {
     
     
     func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
     func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
+        
         activeNCPlayer.insert(self)
         activeNCPlayer.insert(self)
     }
     }
     
     

+ 137 - 42
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift

@@ -54,12 +54,8 @@ class NCPlayerToolBar: UIView {
     private var metadata: tableMetadata?
     private var metadata: tableMetadata?
     private var image: UIImage?
     private var image: UIImage?
     
     
-    var commandCenterPlayCommand: Any?
-    var commandCenterPauseCommand: Any?
-    var commandCenterSkipForwardCommand: Any?
-    var commandCenterSkipBackwardCommand: Any?
+    weak var viewerMedia: NCViewerMedia?
 
 
-    
     // MARK: - View Life Cycle
     // MARK: - View Life Cycle
 
 
     override func awakeFromNib() {
     override func awakeFromNib() {
@@ -71,7 +67,6 @@ class NCPlayerToolBar: UIView {
         let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSingleTapWith(gestureRecognizer:)))
         let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSingleTapWith(gestureRecognizer:)))
         addGestureRecognizer(singleTapGestureRecognizer)
         addGestureRecognizer(singleTapGestureRecognizer)
         
         
-        // self
         self.layer.cornerRadius = 15
         self.layer.cornerRadius = 15
         self.layer.masksToBounds = true
         self.layer.masksToBounds = true
         
         
@@ -80,7 +75,6 @@ class NCPlayerToolBar: UIView {
         blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
         blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
         self.insertSubview(blurEffectView, at:0)
         self.insertSubview(blurEffectView, at:0)
         
         
-        // Top ToolBar
         playerTopToolBarView.layer.cornerRadius = 10
         playerTopToolBarView.layer.cornerRadius = 10
         playerTopToolBarView.layer.masksToBounds = true
         playerTopToolBarView.layer.masksToBounds = true
         
         
@@ -107,13 +101,9 @@ class NCPlayerToolBar: UIView {
         labelLeftTime.text = NCUtility.shared.stringFromTime(.zero)
         labelLeftTime.text = NCUtility.shared.stringFromTime(.zero)
         labelLeftTime.textColor = .lightGray
         labelLeftTime.textColor = .lightGray
         
         
-        backButton.setImage(NCUtility.shared.loadImage(named: "gobackward.10", color: .lightGray), for: .normal)
         backButton.isEnabled = false
         backButton.isEnabled = false
-        
         playButton.setImage(NCUtility.shared.loadImage(named: "play.fill", color: .lightGray), for: .normal)
         playButton.setImage(NCUtility.shared.loadImage(named: "play.fill", color: .lightGray), for: .normal)
         playButton.isEnabled = false
         playButton.isEnabled = false
-        
-        forwardButton.setImage(NCUtility.shared.loadImage(named: "goforward.10", color: .lightGray), for: .normal)
         forwardButton.isEnabled = false
         forwardButton.isEnabled = false
         
         
         NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption), name: AVAudioSession.interruptionNotification, object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption), name: AVAudioSession.interruptionNotification, object: nil)
@@ -129,7 +119,7 @@ class NCPlayerToolBar: UIView {
     
     
     // MARK: -
     // MARK: -
 
 
-    func setBarPlayer(ncplayer: NCPlayer, timeSeek: CMTime,metadata: tableMetadata, image: UIImage?) {
+    func setBarPlayer(ncplayer: NCPlayer, metadata: tableMetadata, image: UIImage?) {
                         
                         
         self.ncplayer = ncplayer
         self.ncplayer = ncplayer
         self.metadata = metadata
         self.metadata = metadata
@@ -151,6 +141,16 @@ class NCPlayerToolBar: UIView {
         guard let ncplayer = self.ncplayer else { return }
         guard let ncplayer = self.ncplayer else { return }
         var time: CMTime = .zero
         var time: CMTime = .zero
         
         
+        let imageNameBackward = "gobackward.10"
+        let imageNameForward = "goforward.10"
+        
+        /*
+        if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+            imageNameBackward = "backward"
+            imageNameForward = "forward"
+        }
+        */
+        
         // COMMAND CENTER
         // COMMAND CENTER
         if commandCenter && CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) {
         if commandCenter && CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) {
             enableCommandCenter()
             enableCommandCenter()
@@ -196,9 +196,9 @@ class NCPlayerToolBar: UIView {
         
         
         // BACK
         // BACK
         if #available(iOS 13.0, *) {
         if #available(iOS 13.0, *) {
-            backButton.setImage(NCUtility.shared.loadImage(named: "gobackward.10", color: .white), for: .normal)
+            backButton.setImage(NCUtility.shared.loadImage(named: imageNameBackward, color: .white), for: .normal)
         } else {
         } else {
-            backButton.setImage(NCUtility.shared.loadImage(named: "gobackward.10", color: .white, size: 30), for: .normal)
+            backButton.setImage(NCUtility.shared.loadImage(named: imageNameBackward, color: .white, size: 30), for: .normal)
         }
         }
         backButton.isEnabled = true
         backButton.isEnabled = true
                  
                  
@@ -218,9 +218,9 @@ class NCPlayerToolBar: UIView {
         
         
         // FORWARD
         // FORWARD
         if #available(iOS 13.0, *) {
         if #available(iOS 13.0, *) {
-            forwardButton.setImage(NCUtility.shared.loadImage(named: "goforward.10", color: .white), for: .normal)
+            forwardButton.setImage(NCUtility.shared.loadImage(named: imageNameForward, color: .white), for: .normal)
         } else {
         } else {
-            forwardButton.setImage(NCUtility.shared.loadImage(named: "goforward.10", color: .white, size: 30), for: .normal)
+            forwardButton.setImage(NCUtility.shared.loadImage(named: imageNameForward, color: .white, size: 30), for: .normal)
         }
         }
         forwardButton.isEnabled = true
         forwardButton.isEnabled = true
     }
     }
@@ -231,11 +231,11 @@ class NCPlayerToolBar: UIView {
         guard let ncplayer = self.ncplayer else { return }
         guard let ncplayer = self.ncplayer else { return }
         
         
         UIApplication.shared.beginReceivingRemoteControlEvents()
         UIApplication.shared.beginReceivingRemoteControlEvents()
-        MPRemoteCommandCenter.shared().playCommand.isEnabled = true
         var nowPlayingInfo = [String : Any]()
         var nowPlayingInfo = [String : Any]()
 
 
         // Add handler for Play Command
         // Add handler for Play Command
-        commandCenterPlayCommand = MPRemoteCommandCenter.shared().playCommand.addTarget { event in
+        MPRemoteCommandCenter.shared().playCommand.isEnabled = true
+        viewerMedia?.playCommand = MPRemoteCommandCenter.shared().playCommand.addTarget { event in
             
             
             if !ncplayer.isPlay() {
             if !ncplayer.isPlay() {
                 ncplayer.playerPlay()
                 ncplayer.playerPlay()
@@ -245,7 +245,8 @@ class NCPlayerToolBar: UIView {
         }
         }
       
       
         // Add handler for Pause Command
         // Add handler for Pause Command
-        commandCenterPauseCommand = MPRemoteCommandCenter.shared().pauseCommand.addTarget { event in
+        MPRemoteCommandCenter.shared().pauseCommand.isEnabled = true
+        viewerMedia?.pauseCommand = MPRemoteCommandCenter.shared().pauseCommand.addTarget { event in
           
           
             if ncplayer.isPlay() {
             if ncplayer.isPlay() {
                 ncplayer.playerPause()
                 ncplayer.playerPause()
@@ -254,21 +255,45 @@ class NCPlayerToolBar: UIView {
             return .commandFailed
             return .commandFailed
         }
         }
         
         
-        // Add handler for Backward Command
-        commandCenterSkipBackwardCommand = MPRemoteCommandCenter.shared().skipBackwardCommand.addTarget { event in
+        // VIDEO / AUDIO () ()
+        if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
             
             
-            let seconds = Float64((event as! MPSkipIntervalCommandEvent).interval)
-            self.skip(seconds: -seconds)
-            return.success
-        }
+            MPRemoteCommandCenter.shared().skipForwardCommand.isEnabled = true
+            viewerMedia?.skipForwardCommand = MPRemoteCommandCenter.shared().skipForwardCommand.addTarget { event in
+                
+                let seconds = Float64((event as! MPSkipIntervalCommandEvent).interval)
+                self.skip(seconds: seconds)
+                return.success
+            }
             
             
-        // Add handler for Forward Command
-        commandCenterSkipForwardCommand = MPRemoteCommandCenter.shared().skipForwardCommand.addTarget { event in
+            MPRemoteCommandCenter.shared().skipBackwardCommand.isEnabled = true
+            viewerMedia?.skipBackwardCommand = MPRemoteCommandCenter.shared().skipBackwardCommand.addTarget { event in
+                
+                let seconds = Float64((event as! MPSkipIntervalCommandEvent).interval)
+                self.skip(seconds: -seconds)
+                return.success
+            }
+        }
+                
+        // AUDIO < >
+        /*
+        if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+                        
+            MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = true
+            appDelegate.nextTrackCommand = MPRemoteCommandCenter.shared().nextTrackCommand.addTarget { event in
+                
+                self.forward()
+                return .success
+            }
             
             
-            let seconds = Float64((event as! MPSkipIntervalCommandEvent).interval)
-            self.skip(seconds: seconds)
-            return.success
+            MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = true
+            appDelegate.previousTrackCommand = MPRemoteCommandCenter.shared().previousTrackCommand.addTarget { event in
+             
+                self.backward()
+                return .success
+            }
         }
         }
+        */
         
         
         nowPlayingInfo[MPMediaItemPropertyTitle] = metadata?.fileNameView
         nowPlayingInfo[MPMediaItemPropertyTitle] = metadata?.fileNameView
         nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = ncplayer.player?.currentItem?.asset.duration.seconds
         nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = ncplayer.player?.currentItem?.asset.duration.seconds
@@ -284,23 +309,37 @@ class NCPlayerToolBar: UIView {
         
         
         UIApplication.shared.endReceivingRemoteControlEvents()
         UIApplication.shared.endReceivingRemoteControlEvents()
         MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]
         MPNowPlayingInfoCenter.default().nowPlayingInfo = [:]
+
         MPRemoteCommandCenter.shared().playCommand.isEnabled = false
         MPRemoteCommandCenter.shared().playCommand.isEnabled = false
+        MPRemoteCommandCenter.shared().pauseCommand.isEnabled = false
+        MPRemoteCommandCenter.shared().skipForwardCommand.isEnabled = false
+        MPRemoteCommandCenter.shared().skipBackwardCommand.isEnabled = false
+        MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = false
+        MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = false
 
 
-        if let playCommand = self.commandCenterPlayCommand {
+        if let playCommand = viewerMedia?.playCommand {
             MPRemoteCommandCenter.shared().playCommand.removeTarget(playCommand)
             MPRemoteCommandCenter.shared().playCommand.removeTarget(playCommand)
-            self.commandCenterPlayCommand = nil
+            viewerMedia?.playCommand = nil
         }
         }
-        if let pauseCommand = self.commandCenterPauseCommand {
+        if let pauseCommand = viewerMedia?.pauseCommand {
             MPRemoteCommandCenter.shared().pauseCommand.removeTarget(pauseCommand)
             MPRemoteCommandCenter.shared().pauseCommand.removeTarget(pauseCommand)
-            self.commandCenterPauseCommand = nil
+            viewerMedia?.pauseCommand = nil
+        }
+        if let skipForwardCommand = viewerMedia?.skipForwardCommand {
+            MPRemoteCommandCenter.shared().skipForwardCommand.removeTarget(skipForwardCommand)
+            viewerMedia?.skipForwardCommand = nil
+        }
+        if let skipBackwardCommand = viewerMedia?.skipBackwardCommand {
+            MPRemoteCommandCenter.shared().skipBackwardCommand.removeTarget(skipBackwardCommand)
+            viewerMedia?.skipBackwardCommand = nil
         }
         }
-        if let commandCenterSkipBackwardCommand = self.commandCenterSkipBackwardCommand {
-            MPRemoteCommandCenter.shared().previousTrackCommand.removeTarget(commandCenterSkipBackwardCommand)
-            self.commandCenterSkipBackwardCommand = nil
+        if let nextTrackCommand = viewerMedia?.nextTrackCommand {
+            MPRemoteCommandCenter.shared().nextTrackCommand.removeTarget(nextTrackCommand)
+            viewerMedia?.nextTrackCommand = nil
         }
         }
-        if let commandCenterSkipForwardCommand = self.commandCenterSkipForwardCommand {
-            MPRemoteCommandCenter.shared().nextTrackCommand.removeTarget(commandCenterSkipForwardCommand)
-            self.commandCenterSkipForwardCommand = nil
+        if let previousTrackCommand = viewerMedia?.previousTrackCommand {
+            MPRemoteCommandCenter.shared().previousTrackCommand.removeTarget(previousTrackCommand)
+            viewerMedia?.previousTrackCommand = nil
         }
         }
     }
     }
     
     
@@ -376,9 +415,12 @@ class NCPlayerToolBar: UIView {
             self.isHidden = false
             self.isHidden = false
             self.playerTopToolBarView.isHidden = false
             self.playerTopToolBarView.isHidden = false
         })
         })
+        
+        updateToolBar()
     }
     }
     
     
     func isShow() -> Bool {
     func isShow() -> Bool {
+        
         return !self.isHidden
         return !self.isHidden
     }
     }
     
     
@@ -441,6 +483,38 @@ class NCPlayerToolBar: UIView {
         reStartTimerAutoHide()
         reStartTimerAutoHide()
     }
     }
     
     
+    func forward() {
+        
+        var index: Int = 0
+        
+        if let currentIndex = self.viewerMedia?.currentIndex, let metadatas = self.viewerMedia?.metadatas, let ncplayer = self.ncplayer {
+        
+            if currentIndex == metadatas.count - 1 {
+                index = 0
+            } else {
+                index = currentIndex + 1
+            }
+            
+            self.viewerMedia?.goTo(index: index, direction: .forward, autoPlay: ncplayer.isPlay())
+        }
+    }
+    
+    func backward() {
+        
+        var index: Int = 0
+
+        if let currentIndex = self.viewerMedia?.currentIndex, let metadatas = self.viewerMedia?.metadatas, let ncplayer = self.ncplayer {
+            
+            if currentIndex == 0 {
+                index = metadatas.count - 1
+            } else {
+                index = currentIndex - 1
+            }
+            
+            self.viewerMedia?.goTo(index: index, direction: .reverse, autoPlay: ncplayer.isPlay())
+        }
+    }
+    
     //MARK: - Event / Gesture
     //MARK: - Event / Gesture
     
     
     @objc func onSliderValChanged(slider: UISlider, event: UIEvent) {
     @objc func onSliderValChanged(slider: UISlider, event: UIEvent) {
@@ -472,12 +546,15 @@ class NCPlayerToolBar: UIView {
         }
         }
     }
     }
     
     
+    //MARK: - Action
+    
     @objc func didSingleTapWith(gestureRecognizer: UITapGestureRecognizer) {
     @objc func didSingleTapWith(gestureRecognizer: UITapGestureRecognizer) {
     }
     }
     
     
-    //MARK: - Action
+    @IBAction func buttonPlayerToolBarTouchInside(_ sender: UIButton) {
+    }
     
     
-    @IBAction func buttonTouchInside(_ sender: UIButton) {
+    @IBAction func buttonPlayerTopToolBarTouchInside(_ sender: UIButton) {
     }
     }
     
     
     @IBAction func playerPause(_ sender: Any) {
     @IBAction func playerPause(_ sender: Any) {
@@ -524,11 +601,29 @@ class NCPlayerToolBar: UIView {
     }
     }
     
     
     @IBAction func forwardButtonSec(_ sender: Any) {
     @IBAction func forwardButtonSec(_ sender: Any) {
+        
         skip(seconds: 10)
         skip(seconds: 10)
+        
+        /*
+        if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+            skip(seconds: 10)
+        } else if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+            forward()
+        }
+        */
     }
     }
     
     
     @IBAction func backButtonSec(_ sender: Any) {
     @IBAction func backButtonSec(_ sender: Any) {
+        
         skip(seconds: -10)
         skip(seconds: -10)
+        
+        /*
+        if metadata?.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
+            skip(seconds: -10)
+        } else if metadata?.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue {
+            backward()
+        }
+        */
     }
     }
 }
 }
 
 

+ 13 - 2
iOSClient/Viewer/NCViewerMedia/NCViewerMedia.storyboard

@@ -245,6 +245,13 @@
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dgJ-dQ-lSp" userLabel="Player Top Tool Bar">
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dgJ-dQ-lSp" userLabel="Player Top Tool Bar">
                                         <rect key="frame" x="299" y="10" width="100" height="45"/>
                                         <rect key="frame" x="299" y="10" width="100" height="45"/>
                                         <subviews>
                                         <subviews>
+                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9aW-Pg-83x" userLabel="Button Player Top Tool Bar">
+                                                <rect key="frame" x="0.0" y="0.0" width="100" height="45"/>
+                                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                                <connections>
+                                                    <action selector="buttonPlayerTopToolBarTouchInside:" destination="sBp-t2-eFh" eventType="touchUpInside" id="Afs-Nt-FaQ"/>
+                                                </connections>
+                                            </button>
                                             <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8AB-hx-yqN" userLabel="Mute Button">
                                             <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8AB-hx-yqN" userLabel="Mute Button">
                                                 <rect key="frame" x="60" y="10" width="25" height="25"/>
                                                 <rect key="frame" x="60" y="10" width="25" height="25"/>
                                                 <constraints>
                                                 <constraints>
@@ -270,10 +277,14 @@
                                         </subviews>
                                         </subviews>
                                         <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                         <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                         <constraints>
                                         <constraints>
+                                            <constraint firstAttribute="trailing" secondItem="9aW-Pg-83x" secondAttribute="trailing" id="8db-gr-hzG"/>
                                             <constraint firstItem="NwE-zQ-Y5D" firstAttribute="centerY" secondItem="dgJ-dQ-lSp" secondAttribute="centerY" id="Ad6-Aj-hvc"/>
                                             <constraint firstItem="NwE-zQ-Y5D" firstAttribute="centerY" secondItem="dgJ-dQ-lSp" secondAttribute="centerY" id="Ad6-Aj-hvc"/>
+                                            <constraint firstAttribute="bottom" secondItem="9aW-Pg-83x" secondAttribute="bottom" id="B8A-Zh-HYL"/>
                                             <constraint firstAttribute="width" constant="100" id="LTs-QZ-nVw"/>
                                             <constraint firstAttribute="width" constant="100" id="LTs-QZ-nVw"/>
                                             <constraint firstAttribute="trailing" secondItem="8AB-hx-yqN" secondAttribute="trailing" constant="15" id="bQK-xA-Jyu"/>
                                             <constraint firstAttribute="trailing" secondItem="8AB-hx-yqN" secondAttribute="trailing" constant="15" id="bQK-xA-Jyu"/>
                                             <constraint firstItem="NwE-zQ-Y5D" firstAttribute="leading" secondItem="dgJ-dQ-lSp" secondAttribute="leading" constant="15" id="cZY-tl-BOh"/>
                                             <constraint firstItem="NwE-zQ-Y5D" firstAttribute="leading" secondItem="dgJ-dQ-lSp" secondAttribute="leading" constant="15" id="cZY-tl-BOh"/>
+                                            <constraint firstItem="9aW-Pg-83x" firstAttribute="leading" secondItem="dgJ-dQ-lSp" secondAttribute="leading" id="clL-y7-JuR"/>
+                                            <constraint firstItem="9aW-Pg-83x" firstAttribute="top" secondItem="dgJ-dQ-lSp" secondAttribute="top" id="jQP-bV-BQ9"/>
                                             <constraint firstItem="8AB-hx-yqN" firstAttribute="centerY" secondItem="dgJ-dQ-lSp" secondAttribute="centerY" id="uNT-D4-mK3"/>
                                             <constraint firstItem="8AB-hx-yqN" firstAttribute="centerY" secondItem="dgJ-dQ-lSp" secondAttribute="centerY" id="uNT-D4-mK3"/>
                                             <constraint firstAttribute="height" constant="45" id="xf9-B5-HMs"/>
                                             <constraint firstAttribute="height" constant="45" id="xf9-B5-HMs"/>
                                         </constraints>
                                         </constraints>
@@ -281,10 +292,10 @@
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sBp-t2-eFh" customClass="NCPlayerToolBar" customModule="Nextcloud" customModuleProvider="target">
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sBp-t2-eFh" customClass="NCPlayerToolBar" customModule="Nextcloud" customModuleProvider="target">
                                         <rect key="frame" x="15" y="661" width="384" height="65"/>
                                         <rect key="frame" x="15" y="661" width="384" height="65"/>
                                         <subviews>
                                         <subviews>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a0D-B0-eGX">
+                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a0D-B0-eGX" userLabel="Button Player Tool Bar">
                                                 <rect key="frame" x="0.0" y="0.0" width="384" height="65"/>
                                                 <rect key="frame" x="0.0" y="0.0" width="384" height="65"/>
                                                 <connections>
                                                 <connections>
-                                                    <action selector="buttonTouchInside:" destination="sBp-t2-eFh" eventType="touchUpInside" id="5fA-20-TD3"/>
+                                                    <action selector="buttonPlayerToolBarTouchInside:" destination="sBp-t2-eFh" eventType="touchUpInside" id="hyl-lR-OGD"/>
                                                 </connections>
                                                 </connections>
                                             </button>
                                             </button>
                                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z2D-bl-6Qu" userLabel="Container play">
                                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Z2D-bl-6Qu" userLabel="Container play">

+ 60 - 57
iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift

@@ -48,12 +48,21 @@ class NCViewerMedia: UIViewController {
     var metadatas: [tableMetadata] = []
     var metadatas: [tableMetadata] = []
     var currentIndex = 0
     var currentIndex = 0
     var nextIndex: Int?
     var nextIndex: Int?
+    var IndexInPlay: Int = -1
     var ncplayerLivePhoto: NCPlayer?
     var ncplayerLivePhoto: NCPlayer?
     var panGestureRecognizer: UIPanGestureRecognizer!
     var panGestureRecognizer: UIPanGestureRecognizer!
     var singleTapGestureRecognizer: UITapGestureRecognizer!
     var singleTapGestureRecognizer: UITapGestureRecognizer!
     var longtapGestureRecognizer: UILongPressGestureRecognizer!
     var longtapGestureRecognizer: UILongPressGestureRecognizer!
     
     
     var textColor: UIColor = NCBrandColor.shared.label
     var textColor: UIColor = NCBrandColor.shared.label
+    
+    var playCommand: Any?
+    var pauseCommand: Any?
+    var skipForwardCommand: Any?
+    var skipBackwardCommand: Any?
+    var nextTrackCommand: Any?
+    var previousTrackCommand: Any?
+    
 
 
     // MARK: - View Life Cycle
     // MARK: - View Life Cycle
 
 
@@ -76,16 +85,7 @@ class NCViewerMedia: UIViewController {
         pageViewController.view.addGestureRecognizer(singleTapGestureRecognizer)
         pageViewController.view.addGestureRecognizer(singleTapGestureRecognizer)
         pageViewController.view.addGestureRecognizer(longtapGestureRecognizer)
         pageViewController.view.addGestureRecognizer(longtapGestureRecognizer)
         
         
-        let viewerMediaZoom = UIStoryboard(name: "NCViewerMedia", bundle: nil).instantiateViewController(withIdentifier: "NCViewerMediaZoom") as! NCViewerMediaZoom
-                
-        viewerMediaZoom.index = currentIndex
-        viewerMediaZoom.image = getImageMetadata(metadatas[currentIndex])
-        viewerMediaZoom.metadata = metadatas[currentIndex]
-        viewerMediaZoom.viewerMedia = self
-        viewerMediaZoom.isShowDetail = false
-
-        singleTapGestureRecognizer.require(toFail: viewerMediaZoom.doubleTapGestureRecognizer)
-        
+        let viewerMediaZoom = getViewerMediaZoom(index: currentIndex, image: getImageMetadata(metadatas[currentIndex]), metadata: metadatas[currentIndex], direction: .forward)
         pageViewController.setViewControllers([viewerMediaZoom], direction: .forward, animated: true, completion: nil)
         pageViewController.setViewControllers([viewerMediaZoom], direction: .forward, animated: true, completion: nil)
         
         
         NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
@@ -94,11 +94,7 @@ class NCViewerMedia: UIViewController {
         progressView.tintColor = NCBrandColor.shared.brandElement
         progressView.tintColor = NCBrandColor.shared.brandElement
         progressView.trackTintColor = .clear
         progressView.trackTintColor = .clear
         progressView.progress = 0
         progressView.progress = 0
-    }
-    
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-    
+        
         NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(deleteFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(renameFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(renameFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(moveFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(moveFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil)
@@ -113,15 +109,20 @@ class NCViewerMedia: UIViewController {
         NotificationCenter.default.addObserver(self, selector: #selector(showPlayerToolBar(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterShowPlayerToolBar), object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(showPlayerToolBar(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterShowPlayerToolBar), object: nil)
     }
     }
     
     
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
+    override func viewDidDisappear(_ animated: Bool) {
+        super.viewDidDisappear(animated)
         
         
-        // Save time video
+        // Clear
         if let ncplayer = currentViewController.ncplayer, ncplayer.isPlay() {
         if let ncplayer = currentViewController.ncplayer, ncplayer.isPlay() {
             ncplayer.playerPause()
             ncplayer.playerPause()
             ncplayer.saveCurrentTime()
             ncplayer.saveCurrentTime()
         }
         }
         
         
+        currentViewController.playerToolBar.disableCommandCenter()
+        
+        metadatas.removeAll()
+        ncplayerLivePhoto = nil
+        
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterMoveFile), object: nil)
@@ -131,6 +132,9 @@ class NCViewerMedia: UIViewController {
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil)
         
         
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedThumbnail), object: nil)
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedThumbnail), object: nil)
+        
+        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterHidePlayerToolBar), object: nil)
+        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterShowPlayerToolBar), object: nil)
     }
     }
     
     
     override var preferredStatusBarStyle: UIStatusBarStyle {
     override var preferredStatusBarStyle: UIStatusBarStyle {
@@ -141,6 +145,21 @@ class NCViewerMedia: UIViewController {
             return .lightContent
             return .lightContent
         }
         }
     }
     }
+    
+    // MARK: -
+    
+    func getViewerMediaZoom(index: Int, image: UIImage?, metadata: tableMetadata, direction: UIPageViewController.NavigationDirection) -> NCViewerMediaZoom {
+        
+        let viewerMediaZoom = UIStoryboard(name: "NCViewerMedia", bundle: nil).instantiateViewController(withIdentifier: "NCViewerMediaZoom") as! NCViewerMediaZoom
+        viewerMediaZoom.index = index
+        viewerMediaZoom.image = image
+        viewerMediaZoom.metadata = metadata
+        viewerMediaZoom.viewerMedia = self
+
+        singleTapGestureRecognizer.require(toFail: viewerMediaZoom.doubleTapGestureRecognizer)
+       
+        return viewerMediaZoom
+    }
 
 
     @objc func viewUnload() {
     @objc func viewUnload() {
         
         
@@ -153,10 +172,6 @@ class NCViewerMedia: UIViewController {
         NCViewer.shared.toggleMenu(viewController: self, metadata: currentViewController.metadata, webView: false, imageIcon: imageIcon)
         NCViewer.shared.toggleMenu(viewController: self, metadata: currentViewController.metadata, webView: false, imageIcon: imageIcon)
     }
     }
     
     
-    deinit {
-        print("deinit NCViewerMedia")        
-    }
-    
     func changeScreenMode(mode: ScreenMode, enableTimerAutoHide: Bool = false) {
     func changeScreenMode(mode: ScreenMode, enableTimerAutoHide: Bool = false) {
         
         
         if mode == .normal {
         if mode == .normal {
@@ -380,58 +395,48 @@ class NCViewerMedia: UIViewController {
 extension NCViewerMedia: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
 extension NCViewerMedia: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
     
     
     func shiftCurrentPage() -> Bool {
     func shiftCurrentPage() -> Bool {
+        
         if metadatas.count == 0 { return false }
         if metadatas.count == 0 { return false }
         
         
         var direction: UIPageViewController.NavigationDirection = .forward
         var direction: UIPageViewController.NavigationDirection = .forward
+        
         if currentIndex == metadatas.count {
         if currentIndex == metadatas.count {
             currentIndex -= 1
             currentIndex -= 1
             direction = .reverse
             direction = .reverse
         }
         }
         
         
-        let viewerMediaZoom = UIStoryboard(name: "NCViewerMedia", bundle: nil).instantiateViewController(withIdentifier: "NCViewerMediaZoom") as! NCViewerMediaZoom
-        
-        viewerMediaZoom.index = currentIndex
-        viewerMediaZoom.image = getImageMetadata(metadatas[currentIndex])
-        viewerMediaZoom.metadata = metadatas[currentIndex]
-        viewerMediaZoom.viewerMedia = self
-        viewerMediaZoom.isShowDetail = false
-
-        singleTapGestureRecognizer.require(toFail: viewerMediaZoom.doubleTapGestureRecognizer)
+        currentViewController.ncplayer?.deactivateObserver(livePhoto: currentViewController.metadata.livePhoto)
         
         
+        let viewerMediaZoom = getViewerMediaZoom(index: currentIndex, image: getImageMetadata(metadatas[currentIndex]), metadata: metadatas[currentIndex], direction: direction)
         pageViewController.setViewControllers([viewerMediaZoom], direction: direction, animated: true, completion: nil)
         pageViewController.setViewControllers([viewerMediaZoom], direction: direction, animated: true, completion: nil)
         
         
         return true
         return true
     }
     }
     
     
-    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
-        if currentIndex == 0 { return nil }
+    func goTo(index: Int, direction: UIPageViewController.NavigationDirection, autoPlay: Bool) {
         
         
-        let viewerMediaZoom = UIStoryboard(name: "NCViewerMedia", bundle: nil).instantiateViewController(withIdentifier: "NCViewerMediaZoom") as! NCViewerMediaZoom
-                
-        viewerMediaZoom.index = currentIndex - 1
-        viewerMediaZoom.image = getImageMetadata(metadatas[currentIndex - 1])
-        viewerMediaZoom.metadata = metadatas[currentIndex - 1]
-        viewerMediaZoom.viewerMedia = self
-        viewerMediaZoom.isShowDetail = false
+        currentIndex = index
+        
+        currentViewController.ncplayer?.deactivateObserver(livePhoto: currentViewController.metadata.livePhoto)
 
 
-        self.singleTapGestureRecognizer.require(toFail: viewerMediaZoom.doubleTapGestureRecognizer)
+        let viewerMediaZoom = getViewerMediaZoom(index: currentIndex, image: getImageMetadata(metadatas[currentIndex]), metadata: metadatas[currentIndex], direction: direction)
+        viewerMediaZoom.autoPlay = autoPlay
+        pageViewController.setViewControllers([viewerMediaZoom], direction: direction, animated: true, completion: nil)
+    }
+    
+    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
         
         
+        if currentIndex == 0 { return nil }
+
+        let viewerMediaZoom = getViewerMediaZoom(index: currentIndex-1, image: getImageMetadata(metadatas[currentIndex-1]), metadata: metadatas[currentIndex-1], direction: .reverse)
         return viewerMediaZoom
         return viewerMediaZoom
     }
     }
     
     
     func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
     func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
-        if currentIndex == metadatas.count - 1 { return nil }
-                
-        let viewerMediaZoom = UIStoryboard(name: "NCViewerMedia", bundle: nil).instantiateViewController(withIdentifier: "NCViewerMediaZoom") as! NCViewerMediaZoom
         
         
-        viewerMediaZoom.index = currentIndex + 1
-        viewerMediaZoom.image = getImageMetadata(metadatas[currentIndex + 1])
-        viewerMediaZoom.metadata = metadatas[currentIndex + 1]
-        viewerMediaZoom.viewerMedia = self
-        viewerMediaZoom.isShowDetail = false
-
-        singleTapGestureRecognizer.require(toFail: viewerMediaZoom.doubleTapGestureRecognizer)
+        if currentIndex == metadatas.count-1 { return nil }
 
 
+        let viewerMediaZoom = getViewerMediaZoom(index: currentIndex+1, image: getImageMetadata(metadatas[currentIndex+1]), metadata: metadatas[currentIndex+1], direction: .forward)
         return viewerMediaZoom
         return viewerMediaZoom
     }
     }
     
     
@@ -453,7 +458,7 @@ extension NCViewerMedia: UIPageViewControllerDelegate, UIPageViewControllerDataS
         if (completed && nextIndex != nil) {
         if (completed && nextIndex != nil) {
             previousViewControllers.forEach { viewController in
             previousViewControllers.forEach { viewController in
                 let viewerMediaZoom = viewController as! NCViewerMediaZoom
                 let viewerMediaZoom = viewController as! NCViewerMediaZoom
-                viewerMediaZoom.scrollView.zoomScale = viewerMediaZoom.scrollView.minimumZoomScale
+                viewerMediaZoom.ncplayer?.deactivateObserver(livePhoto: false)
             }
             }
             currentIndex = nextIndex!
             currentIndex = nextIndex!
         }
         }
@@ -542,8 +547,7 @@ extension NCViewerMedia: UIGestureRecognizerDelegate {
                     AudioServicesPlaySystemSound(1519) // peek feedback
                     AudioServicesPlaySystemSound(1519) // peek feedback
                     
                     
                     if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
                     if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
-                        self.ncplayerLivePhoto = NCPlayer.init(url: url, imageVideoContainer: self.currentViewController.imageVideoContainer, playerToolBar: nil, metadata: metadata, detailView: nil)
-                        self.ncplayerLivePhoto?.playerPlay()
+                        self.ncplayerLivePhoto = NCPlayer.init(url: url, autoPlay: true, imageVideoContainer: self.currentViewController.imageVideoContainer, playerToolBar: nil, metadata: metadata, detailView: nil)
                     }
                     }
                     
                     
                 } else {
                 } else {
@@ -571,8 +575,7 @@ extension NCViewerMedia: UIGestureRecognizerDelegate {
                                 AudioServicesPlaySystemSound(1519) // peek feedback
                                 AudioServicesPlaySystemSound(1519) // peek feedback
                                 
                                 
                                 if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
                                 if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
-                                    self.ncplayerLivePhoto = NCPlayer.init(url: url, imageVideoContainer: self.currentViewController.imageVideoContainer, playerToolBar: nil, metadata: metadata, detailView: nil)
-                                    self.ncplayerLivePhoto?.playerPlay()
+                                    self.ncplayerLivePhoto = NCPlayer.init(url: url, autoPlay: true, imageVideoContainer: self.currentViewController.imageVideoContainer, playerToolBar: nil, metadata: metadata, detailView: nil)
                                 }
                                 }
                             }
                             }
                         }
                         }
@@ -584,7 +587,7 @@ extension NCViewerMedia: UIGestureRecognizerDelegate {
             
             
             currentViewController.statusViewImage.isHidden = false
             currentViewController.statusViewImage.isHidden = false
             currentViewController.statusLabel.isHidden = false
             currentViewController.statusLabel.isHidden = false
-            self.ncplayerLivePhoto?.videoRemoved()
+            self.ncplayerLivePhoto?.deactivateObserver(livePhoto: true)
         }
         }
     }
     }
 }
 }

+ 26 - 9
iOSClient/Viewer/NCViewerMedia/NCViewerMediaZoom.swift

@@ -37,17 +37,29 @@ class NCViewerMediaZoom: UIViewController {
     @IBOutlet weak var detailView: NCViewerMediaDetailView!
     @IBOutlet weak var detailView: NCViewerMediaDetailView!
     @IBOutlet weak var playerToolBar: NCPlayerToolBar!
     @IBOutlet weak var playerToolBar: NCPlayerToolBar!
     
     
+    private var _autoPlay: Bool = false
+
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
     var viewerMedia: NCViewerMedia?
     var viewerMedia: NCViewerMedia?
     var ncplayer: NCPlayer?
     var ncplayer: NCPlayer?
     var image: UIImage?
     var image: UIImage?
     var metadata: tableMetadata = tableMetadata()
     var metadata: tableMetadata = tableMetadata()
     var index: Int = 0
     var index: Int = 0
-    var isShowDetail: Bool = false
     var doubleTapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
     var doubleTapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
     var imageViewConstraint: CGFloat = 0
     var imageViewConstraint: CGFloat = 0
     var isDetailViewInitializze: Bool = false
     var isDetailViewInitializze: Bool = false
-                
+    
+    var autoPlay: Bool {
+        get {
+            let temp = _autoPlay
+            _autoPlay = false
+            return temp
+        }
+        set(newVal) {
+            _autoPlay = newVal
+        }
+    }
+    
     // MARK: - View Life Cycle
     // MARK: - View Life Cycle
 
 
     required init?(coder aDecoder: NSCoder) {
     required init?(coder aDecoder: NSCoder) {
@@ -59,6 +71,8 @@ class NCViewerMediaZoom: UIViewController {
     
     
     deinit {
     deinit {
         print("deinit NCViewerMediaZoom")
         print("deinit NCViewerMediaZoom")
+        
+        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
     }
     }
     
     
     override func viewDidLoad() {
     override func viewDidLoad() {
@@ -100,6 +114,8 @@ class NCViewerMediaZoom: UIViewController {
             statusLabel.text = ""
             statusLabel.text = ""
         }
         }
         
         
+        playerToolBar.viewerMedia = viewerMedia
+        
         detailViewTopConstraint.constant = 0
         detailViewTopConstraint.constant = 0
         detailView.hide()
         detailView.hide()
     }
     }
@@ -142,8 +158,14 @@ class NCViewerMediaZoom: UIViewController {
         super.viewDidAppear(animated)
         super.viewDidAppear(animated)
         
         
         if (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue) {
         if (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue) {
-            if let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
-                self.ncplayer = NCPlayer.init(url: url, imageVideoContainer: self.imageVideoContainer, playerToolBar: self.playerToolBar, metadata: self.metadata, detailView: self.detailView)
+            
+            if ncplayer == nil, let url = NCKTVHTTPCache.shared.getVideoURL(metadata: metadata) {
+                self.ncplayer = NCPlayer.init(url: url, autoPlay: self.autoPlay, imageVideoContainer: self.imageVideoContainer, playerToolBar: self.playerToolBar, metadata: self.metadata, detailView: self.detailView)
+            } else {
+                self.ncplayer?.activateObserver(playerToolBar: self.playerToolBar)
+                if detailView.isShow() == false && ncplayer?.isPlay() == false {
+                    NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterShowPlayerToolBar, userInfo: ["ocId":metadata.ocId, "enableTimerAutoHide": false])
+                }
             }
             }
         }
         }
         
         
@@ -155,11 +177,6 @@ class NCViewerMediaZoom: UIViewController {
     
     
     override func viewDidDisappear(_ animated: Bool) {
     override func viewDidDisappear(_ animated: Bool) {
         super.viewDidDisappear(animated)
         super.viewDidDisappear(animated)
-        
-        self.ncplayer?.videoRemoved()
-        playerToolBar?.disableCommandCenter()
-        
-        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
     }
     }
     
     
     override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
     override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

+ 0 - 165
iOSClient/Zzz/NCViewerMediaDetailView.xib

@@ -1,165 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina5_5" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCViewerMediaDetailView" customModule="Nextcloud" customModuleProvider="target">
-            <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <subviews>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vfh-7h-knB">
-                    <rect key="frame" x="16" y="20" width="383" height="1"/>
-                    <color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="1" id="9yq-eZ-sEM"/>
-                    </constraints>
-                </view>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="size" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EcH-At-xUC">
-                    <rect key="frame" x="15" y="36" width="80" height="16"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="80" id="cg1-8k-qbS"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="size value" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CVj-Qv-laX">
-                    <rect key="frame" x="105" y="36" width="294" height="16"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="date" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dlG-kQ-oGT">
-                    <rect key="frame" x="15" y="67" width="80" height="16"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="80" id="GNV-lY-xjZ"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="date value" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cGN-I7-3e4">
-                    <rect key="frame" x="105" y="67" width="294" height="16"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="dim" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MX3-5v-hDP">
-                    <rect key="frame" x="15" y="98" width="80" height="16"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="80" id="eVC-4q-Koo"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="dim value" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="khY-FW-U5G">
-                    <rect key="frame" x="105" y="98" width="294" height="16"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="lens" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mCm-dF-HVt">
-                    <rect key="frame" x="15" y="129" width="80" height="16"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="80" id="PxL-TZ-nFK"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="lens value" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hmr-2m-q93">
-                    <rect key="frame" x="105" y="129" width="294" height="16"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="message" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hIh-Bh-Vi7">
-                    <rect key="frame" x="15" y="160" width="384" height="31"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="31" id="2HA-1o-IcO"/>
-                    </constraints>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <color key="textColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <mapView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" mapType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="snG-1k-HmS">
-                    <rect key="frame" x="15" y="160" width="384" height="548"/>
-                </mapView>
-                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="drq-Kr-R07">
-                    <rect key="frame" x="15" y="708" width="384" height="28"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                    <state key="normal" title="location"/>
-                    <connections>
-                        <action selector="touchLocation:" destination="iN0-l3-epB" eventType="touchUpInside" id="Kqi-oe-WAT"/>
-                    </connections>
-                </button>
-            </subviews>
-            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
-            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
-            <constraints>
-                <constraint firstItem="dlG-kQ-oGT" firstAttribute="top" secondItem="EcH-At-xUC" secondAttribute="bottom" constant="15" id="0Of-Q9-Hl2"/>
-                <constraint firstItem="Hmr-2m-q93" firstAttribute="centerY" secondItem="mCm-dF-HVt" secondAttribute="centerY" id="1MY-1H-KaA"/>
-                <constraint firstItem="EcH-At-xUC" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="4K4-g2-pH5"/>
-                <constraint firstItem="drq-Kr-R07" firstAttribute="top" secondItem="snG-1k-HmS" secondAttribute="bottom" id="4vU-DF-2YK"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="drq-Kr-R07" secondAttribute="trailing" constant="15" id="52Z-Ke-8Xi"/>
-                <constraint firstItem="khY-FW-U5G" firstAttribute="leading" secondItem="MX3-5v-hDP" secondAttribute="trailing" constant="10" id="7q8-EE-Hyk"/>
-                <constraint firstItem="snG-1k-HmS" firstAttribute="top" secondItem="mCm-dF-HVt" secondAttribute="bottom" constant="15" id="8ax-hx-czr"/>
-                <constraint firstItem="vfh-7h-knB" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="16" id="BZe-Rb-6ct"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="hIh-Bh-Vi7" secondAttribute="trailing" constant="15" id="IEl-eR-0h6"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="snG-1k-HmS" secondAttribute="trailing" constant="15" id="KMR-fn-x76"/>
-                <constraint firstItem="vfh-7h-knB" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" constant="20" id="KlX-gU-mXi"/>
-                <constraint firstItem="cGN-I7-3e4" firstAttribute="leading" secondItem="dlG-kQ-oGT" secondAttribute="trailing" constant="10" id="L5M-SC-YKl"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="cGN-I7-3e4" secondAttribute="trailing" constant="15" id="M3m-Qf-OLa"/>
-                <constraint firstItem="dlG-kQ-oGT" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="M5J-7h-Kl0"/>
-                <constraint firstItem="MX3-5v-hDP" firstAttribute="top" secondItem="dlG-kQ-oGT" secondAttribute="bottom" constant="15" id="Omf-ef-2sV"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="Hmr-2m-q93" secondAttribute="trailing" constant="15" id="UHq-oa-pBX"/>
-                <constraint firstItem="EcH-At-xUC" firstAttribute="top" secondItem="vfh-7h-knB" secondAttribute="bottom" constant="15" id="XEf-tP-JSp"/>
-                <constraint firstItem="hIh-Bh-Vi7" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="b9P-Kd-5eU"/>
-                <constraint firstItem="CVj-Qv-laX" firstAttribute="leading" secondItem="EcH-At-xUC" secondAttribute="trailing" constant="10" id="bgZ-H9-tHA"/>
-                <constraint firstItem="MX3-5v-hDP" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="dPD-gx-JDh"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="CVj-Qv-laX" secondAttribute="trailing" constant="15" id="dhJ-G2-IIA"/>
-                <constraint firstItem="hIh-Bh-Vi7" firstAttribute="top" secondItem="mCm-dF-HVt" secondAttribute="bottom" constant="15" id="eRW-8O-CRi"/>
-                <constraint firstItem="drq-Kr-R07" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="f11-b0-Rnc"/>
-                <constraint firstItem="mCm-dF-HVt" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="hzW-Wz-ReU"/>
-                <constraint firstItem="khY-FW-U5G" firstAttribute="centerY" secondItem="MX3-5v-hDP" secondAttribute="centerY" id="lNa-IL-htI"/>
-                <constraint firstItem="cGN-I7-3e4" firstAttribute="centerY" secondItem="dlG-kQ-oGT" secondAttribute="centerY" id="nUy-Dh-aiP"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="drq-Kr-R07" secondAttribute="bottom" id="pEo-vl-dAo"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="vfh-7h-knB" secondAttribute="trailing" constant="15" id="q3I-og-2ys"/>
-                <constraint firstItem="CVj-Qv-laX" firstAttribute="centerY" secondItem="EcH-At-xUC" secondAttribute="centerY" id="r7D-zh-hzt"/>
-                <constraint firstItem="mCm-dF-HVt" firstAttribute="top" secondItem="MX3-5v-hDP" secondAttribute="bottom" constant="15" id="rIJ-LG-DMc"/>
-                <constraint firstItem="snG-1k-HmS" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="15" id="sR2-BD-fdE"/>
-                <constraint firstItem="Hmr-2m-q93" firstAttribute="leading" secondItem="mCm-dF-HVt" secondAttribute="trailing" constant="10" id="tiN-dt-3dL"/>
-                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="khY-FW-U5G" secondAttribute="trailing" constant="15" id="z3l-cS-tuh"/>
-            </constraints>
-            <connections>
-                <outlet property="dateLabel" destination="dlG-kQ-oGT" id="ICs-ea-l3H"/>
-                <outlet property="dateValue" destination="cGN-I7-3e4" id="39e-UM-1T4"/>
-                <outlet property="dimLabel" destination="MX3-5v-hDP" id="Sd8-VZ-jyI"/>
-                <outlet property="dimValue" destination="khY-FW-U5G" id="gha-mh-2cj"/>
-                <outlet property="lensModelLabel" destination="mCm-dF-HVt" id="6IB-VE-uic"/>
-                <outlet property="lensModelValue" destination="Hmr-2m-q93" id="lYj-fL-sZ2"/>
-                <outlet property="locationButton" destination="drq-Kr-R07" id="as2-Tv-OtA"/>
-                <outlet property="mapView" destination="snG-1k-HmS" id="vDK-1x-nQR"/>
-                <outlet property="messageLabel" destination="hIh-Bh-Vi7" id="uLd-IC-mNO"/>
-                <outlet property="separator" destination="vfh-7h-knB" id="BcM-QY-v4Z"/>
-                <outlet property="sizeLabel" destination="EcH-At-xUC" id="ye2-zz-5hn"/>
-                <outlet property="sizeValue" destination="CVj-Qv-laX" id="YPA-b9-LHQ"/>
-            </connections>
-            <point key="canvasLocation" x="138.75" y="152.11267605633802"/>
-        </view>
-    </objects>
-    <resources>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-    </resources>
-</document>