瀏覽代碼

Merge pull request #2101 from nextcloud/fix/441

Fix/441
Marino Faggiana 2 年之前
父節點
當前提交
bff7433523

二進制
Animation.gif


+ 14 - 18
Nextcloud.xcodeproj/project.pbxproj

@@ -282,6 +282,9 @@
 		F77B0F611D118A16002130FE /* Acknowledgements.rtf in Resources */ = {isa = PBXBuildFile; fileRef = F7ACE42B1BAC0268006C0017 /* Acknowledgements.rtf */; };
 		F77B0F631D118A16002130FE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F7E70DE91A24DE4100E1B66A /* Localizable.strings */; };
 		F77B0F7D1D118A16002130FE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F7F67BB81A24D27800EE80DA /* Images.xcassets */; };
+		F77BB746289984CA0090FC19 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */; };
+		F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB747289985270090FC19 /* UITabBarController+Extension.swift */; };
+		F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */; };
 		F78071091EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */; };
 		F780710A1EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m in Sources */ = {isa = PBXBuildFile; fileRef = F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */; };
 		F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
@@ -332,8 +335,6 @@
 		F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */ = {isa = PBXBuildFile; fileRef = F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */; };
 		F7A76DC8256A71CD00119AB3 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
 		F7A76DCD256A71CE00119AB3 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; };
-		F7A80BCA252624C100C7CD01 /* NCFileViewInFolder.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */; };
-		F7A80BCB252624C100C7CD01 /* NCFileViewInFolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */; };
 		F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F4230D5F9E007ACF8A /* NCLoginWeb.swift */; };
 		F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F7230E81CB007ACF8A /* NCBrowserWeb.swift */; };
 		F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */; };
@@ -771,6 +772,9 @@
 		F77910A425DD517B00CEDB9E /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
 		F77910AA25DD53C700CEDB9E /* NCSettingsBundleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSettingsBundleHelper.swift; sourceTree = "<group>"; };
 		F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+Menu.swift"; sourceTree = "<group>"; };
+		F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = "<group>"; };
+		F77BB747289985270090FC19 /* UITabBarController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITabBarController+Extension.swift"; sourceTree = "<group>"; };
+		F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
 		F78071071EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNotificationCenter+MainThread.h"; sourceTree = "<group>"; };
 		F78071081EDAB65800EAFFF6 /* NSNotificationCenter+MainThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSNotificationCenter+MainThread.m"; sourceTree = "<group>"; };
 		F785EE9C246196DF00B3F945 /* NCNetworkingE2EE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingE2EE.swift; sourceTree = "<group>"; };
@@ -806,8 +810,6 @@
 		F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
 		F7A321AB1E9E6AD50069AD1B /* CCAdvanced.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAdvanced.h; sourceTree = "<group>"; };
 		F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = "<group>"; };
-		F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCFileViewInFolder.storyboard; sourceTree = "<group>"; };
-		F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCFileViewInFolder.swift; sourceTree = "<group>"; };
 		F7AA41B827C7CF4600494705 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		F7AA41B927C7CF4B00494705 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
 		F7AA41BA27C7CF5000494705 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
@@ -1452,6 +1454,9 @@
 				F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */,
 				F79B645F26CA661600838ACA /* UIControl+Extensions.swift */,
 				F7F4F10F27ECDC4A008676F9 /* UIDevice+Extensions.swift */,
+				F77BB747289985270090FC19 /* UITabBarController+Extension.swift */,
+				F77BB745289984CA0090FC19 /* UIViewController+Extension.swift */,
+				F77BB7492899857B0090FC19 /* UINavigationController+Extension.swift */,
 				F7F4F11127ECDC52008676F9 /* UIFont+Extension.swift */,
 				F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */,
 				F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */,
@@ -1481,15 +1486,6 @@
 			path = Activity;
 			sourceTree = "<group>";
 		};
-		F7A80BC7252624C100C7CD01 /* FileViewInFolder */ = {
-			isa = PBXGroup;
-			children = (
-				F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */,
-				F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */,
-			);
-			path = FileViewInFolder;
-			sourceTree = "<group>";
-		};
 		F7ACE4281BAC0268006C0017 /* Settings */ = {
 			isa = PBXGroup;
 			children = (
@@ -1771,7 +1767,6 @@
 				F7A0D14E259229FA008F8A13 /* Extensions */,
 				F7A3214D1E9E2A070069AD1B /* Favorites */,
 				F7725A5D251F33BB00D125E0 /* Files */,
-				F7A80BC7252624C100C7CD01 /* FileViewInFolder */,
 				F7BFFA621A24D7300044ED85 /* Login */,
 				F7EC9CB921185F2000F1C5CE /* Media */,
 				371B5A2F23D0B04B00FAFAE9 /* Menu */,
@@ -2266,7 +2261,6 @@
 				F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */,
 				F769453C22E9CFFF000A798A /* NCShareUserCell.xib in Resources */,
 				F7F4F10927ECDBDB008676F9 /* Inconsolata-Bold.ttf in Resources */,
-				F7A80BCA252624C100C7CD01 /* NCFileViewInFolder.storyboard in Resources */,
 				F76D3CF52428D0C1005DFA87 /* NCViewerPDF.storyboard in Resources */,
 				F700222C1EC479840080073F /* Custom.xcassets in Resources */,
 				F702F2F125EE5CDB008F8E80 /* NCLogin.storyboard in Resources */,
@@ -2539,11 +2533,11 @@
 				371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */,
 				F79EDAA326B004980007D134 /* NCPlayerToolBar.swift in Sources */,
 				F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */,
+				F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */,
 				F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */,
 				F769454622E9F1B0000A798A /* NCShareCommon.swift in Sources */,
 				F738E8421F90FFD100F95C8E /* NCManageEndToEndEncryption.m in Sources */,
 				F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */,
-				F7A80BCB252624C100C7CD01 /* NCFileViewInFolder.swift in Sources */,
 				F78A18B823CDE2B300F681F3 /* NCViewerRichWorkspace.swift in Sources */,
 				F77910AB25DD53C700CEDB9E /* NCSettingsBundleHelper.swift in Sources */,
 				AF4BF61927562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */,
@@ -2563,6 +2557,7 @@
 				F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */,
 				F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */,
 				AFCE353927E5DE0500FEA6C2 /* NCShare+Helper.swift in Sources */,
+				F77BB746289984CA0090FC19 /* UIViewController+Extension.swift in Sources */,
 				F700510522DF6A89003A3356 /* NCShare.swift in Sources */,
 				F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */,
 				F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */,
@@ -2655,6 +2650,7 @@
 				F704B5E52430AA8000632F5F /* NCCreateFormUploadConflict.swift in Sources */,
 				F765608F23BF813600765969 /* NCContentPresenter.swift in Sources */,
 				F70CEF5623E9C7E50007035B /* UIColor+Extensions.swift in Sources */,
+				F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */,
 				F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */,
 				F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */,
 				F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */,
@@ -2991,7 +2987,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 13;
+				CURRENT_PROJECT_VERSION = 14;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				ENABLE_BITCODE = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -3054,7 +3050,7 @@
 				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
-				CURRENT_PROJECT_VERSION = 13;
+				CURRENT_PROJECT_VERSION = 14;
 				DEVELOPMENT_TEAM = 6JLRKY9ZV7;
 				ENABLE_BITCODE = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;

+ 1 - 4
iOSClient/AppDelegate.swift

@@ -42,11 +42,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
 
     var deletePasswordSession: Bool = false
     var activeAppConfigView: NCAppConfigView?
-    var activeFiles: NCFiles?
-    var activeFileViewInFolder: NCFileViewInFolder?
     var activeLogin: NCLogin?
     var activeLoginWeb: NCLoginWeb?
-    @objc var activeMedia: NCMedia?
     var activeServerUrl: String = ""
     @objc var activeViewController: UIViewController?
     var mainTabBar: NCMainTabBar?
@@ -868,7 +865,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
                         }
 
                         DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
-                            NCFunctionCenter.shared.openFileViewInFolder(serverUrl: serverUrl, fileName: fileName)
+                            NCFunctionCenter.shared.openFileViewInFolder(serverUrl: serverUrl, fileNameBlink: fileName)
                         }
 
                     } else {

+ 32 - 0
iOSClient/Extensions/UINavigationController+Extension.swift

@@ -0,0 +1,32 @@
+//
+//  UINavigationController+Extension.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 02/08/2022.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+extension UINavigationController {
+
+    // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios
+    override func topMostViewController() -> UIViewController {
+        return self.visibleViewController!.topMostViewController()
+    }
+}

+ 32 - 0
iOSClient/Extensions/UITabBarController+Extension.swift

@@ -0,0 +1,32 @@
+//
+//  UITabBarController+Extension.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 02/08/2022.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+extension UITabBarController {
+
+    // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios
+    override func topMostViewController() -> UIViewController {
+        return self.selectedViewController!.topMostViewController()
+    }
+}

+ 64 - 0
iOSClient/Extensions/UIViewController+Extension.swift

@@ -0,0 +1,64 @@
+//
+//  UIViewController+Extension.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 02/08/2022.
+//  Copyright © 2022 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+extension UIViewController {
+
+    // https://stackoverflow.com/questions/6131205/how-to-find-topmost-view-controller-on-ios
+    @objc func topMostViewController() -> UIViewController {
+        // Handling Modal views
+        if let presentedViewController = self.presentedViewController {
+            return presentedViewController.topMostViewController()
+        }
+        // Handling UIViewController's added as subviews to some other views.
+        else {
+            for view in self.view.subviews {
+                // Key property which most of us are unaware of / rarely use.
+                if let subViewController = view.next {
+                    if subViewController is UIViewController {
+                        if let viewController = subViewController as? UIViewController {
+                            return viewController.topMostViewController()
+                        }
+                    }
+                }
+            }
+            return self
+        }
+    }
+
+    // https://stackoverflow.com/questions/23620276/how-to-check-if-a-view-controller-is-presented-modally-or-pushed-on-a-navigation
+    var isModal: Bool {
+        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
+            return false
+        } else if presentingViewController != nil {
+            return true
+        } else if navigationController?.presentingViewController?.presentedViewController == navigationController {
+            return true
+        } else if tabBarController?.presentingViewController is UITabBarController {
+            return true
+        } else {
+            return false
+        }
+    }
+}

+ 0 - 53
iOSClient/FileViewInFolder/NCFileViewInFolder.storyboard

@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EFX-fO-Oip">
-    <device id="retina5_9" orientation="portrait" appearance="light"/>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--File View In Folder-->
-        <scene sceneID="X4W-6b-l7s">
-            <objects>
-                <viewController storyboardIdentifier="NCFileViewInFolder.storyboard" extendedLayoutIncludesOpaqueBars="YES" id="EFX-fO-Oip" customClass="NCFileViewInFolder" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
-                    <view key="view" contentMode="scaleToFill" id="QEs-gO-Cmp">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="Zaz-Cl-qpZ">
-                                <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
-                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="fF1-wd-0xN">
-                                    <size key="itemSize" width="0.0" height="0.0"/>
-                                    <size key="headerReferenceSize" width="0.0" height="0.0"/>
-                                    <size key="footerReferenceSize" width="0.0" height="0.0"/>
-                                    <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
-                                </collectionViewFlowLayout>
-                                <cells/>
-                                <connections>
-                                    <outlet property="dataSource" destination="EFX-fO-Oip" id="2On-qP-zuG"/>
-                                    <outlet property="delegate" destination="EFX-fO-Oip" id="s3n-CL-8X2"/>
-                                </connections>
-                            </collectionView>
-                        </subviews>
-                        <viewLayoutGuide key="safeArea" id="Meh-VD-wWh"/>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                        <constraints>
-                            <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="leading" secondItem="Meh-VD-wWh" secondAttribute="leading" id="1bp-sm-u0X"/>
-                            <constraint firstItem="Meh-VD-wWh" firstAttribute="trailing" secondItem="Zaz-Cl-qpZ" secondAttribute="trailing" id="aNd-UL-hmu"/>
-                            <constraint firstItem="Meh-VD-wWh" firstAttribute="bottom" secondItem="Zaz-Cl-qpZ" secondAttribute="bottom" constant="-34" id="aNr-tf-2AH"/>
-                            <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="top" secondItem="QEs-gO-Cmp" secondAttribute="top" id="tji-wt-R7s"/>
-                        </constraints>
-                    </view>
-                    <connections>
-                        <outlet property="collectionView" destination="Zaz-Cl-qpZ" id="8oA-Gx-z7T"/>
-                    </connections>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="JJ0-Le-6eT" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="256.80000000000001" y="228.32512315270938"/>
-        </scene>
-    </scenes>
-</document>

+ 0 - 160
iOSClient/FileViewInFolder/NCFileViewInFolder.swift

@@ -1,160 +0,0 @@
-//
-//  NCFileViewInFolder.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 01/10/2020.
-//  Copyright © 2020 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import NCCommunication
-
-class NCFileViewInFolder: NCCollectionViewCommon {
-
-    internal var fileName: String?
-
-    // MARK: - View Life Cycle
-
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-
-        appDelegate.activeFileViewInFolder = self
-        titleCurrentFolder = NCBrandOptions.shared.brand
-        layoutKey = NCGlobal.shared.layoutViewViewInFolder
-        enableSearchBar = false
-        headerMenuButtonsCommand = false
-        headerMenuButtonsView = true
-        headerRichWorkspaceDisable = true
-        emptyImage = UIImage(named: "folder")?.image(color: NCBrandColor.shared.brandElement, size: UIScreen.main.bounds.width)
-        emptyTitle = "_files_no_files_"
-        emptyDescription = "_no_file_pull_down_"
-    }
-
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-
-        appDelegate.activeViewController = self
-
-        if serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) {
-            self.navigationItem.title = NCBrandOptions.shared.brand
-        } else {
-            self.navigationItem.title = (serverUrl as NSString).lastPathComponent
-        }
-
-        presentationController?.delegate = self
-
-        layoutForView = NCUtility.shared.getLayoutForView(key: layoutKey, serverUrl: serverUrl)
-        gridLayout.itemForLine = CGFloat(layoutForView?.itemForLine ?? 3)
-
-        if layoutForView?.layout == NCGlobal.shared.layoutList {
-            collectionView?.collectionViewLayout = listLayout
-        } else {
-            collectionView?.collectionViewLayout = gridLayout
-        }
-
-        self.navigationItem.leftBarButtonItem = nil
-        self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_close_", comment: ""), style: .plain, target: self, action: #selector(tapClose(sender:)))
-    }
-
-    // MARK: - TAP EVENT
-
-    @objc func tapClose(sender: Any) {
-        dismiss(animated: true)
-    }
-
-    // MARK: - DataSource + NC Endpoint
-
-    override func reloadDataSource(forced: Bool = true) {
-        super.reloadDataSource()
-
-        DispatchQueue.global().async {
-            let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
-            if self.metadataFolder == nil {
-                self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, serverUrl: self.serverUrl)
-            }
-
-            self.dataSource = NCDataSource(metadatas: metadatas,
-                                           account: self.appDelegate.account,
-                                           sort: self.layoutForView?.sort,
-                                           ascending: self.layoutForView?.ascending,
-                                           directoryOnTop: self.layoutForView?.directoryOnTop,
-                                           favoriteOnTop: true,
-                                           filterLivePhoto: true,
-                                           groupByField: self.groupByField,
-                                           providers: self.providers,
-                                           searchResults: self.searchResults)
-
-            DispatchQueue.main.async {
-                self.refreshControl.endRefreshing()
-                self.collectionView.reloadData()
-                // Blink file
-                if self.fileName != nil {
-                    if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, self.fileName!)) {
-                        let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
-                        if let indexPath = indexPath {
-                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
-                                UIView.animate(withDuration: 0.3) {
-                                    self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false)
-                                } completion: { _ in
-                                    if let cell = self.collectionView.cellForItem(at: indexPath) {
-                                        cell.backgroundColor = .darkGray
-                                        UIView.animate(withDuration: 2) {
-                                            cell.backgroundColor = .clear
-                                            self.fileName = nil
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    override func reloadDataSourceNetwork(forced: Bool = false) {
-        super.reloadDataSourceNetwork(forced: forced)
-
-        if isSearching {
-            networkSearch()
-            return
-        }
-
-        isReloadDataSourceNetworkInProgress = true
-        collectionView?.reloadData()
-
-        networkReadFolder(forced: forced) { tableDirectory, metadatas, _, _, errorCode, _ in
-            if errorCode == 0 {
-                for metadata in metadatas ?? [] {
-                    if !metadata.directory {
-                        if NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) {
-                            NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)
-                        }
-                    }
-                }
-            }
-
-            DispatchQueue.main.async {
-                self.refreshControl.endRefreshing()
-                self.isReloadDataSourceNetworkInProgress = false
-                self.richWorkspaceText = tableDirectory?.richWorkspace
-                self.reloadDataSource()
-            }
-        }
-    }
-}

+ 40 - 4
iOSClient/Files/NCFiles.swift

@@ -27,13 +27,13 @@ import NCCommunication
 class NCFiles: NCCollectionViewCommon {
 
     internal var isRoot: Bool = true
+    internal var fileNameBlink: String?
 
     // MARK: - View Life Cycle
 
     required init?(coder aDecoder: NSCoder) {
         super.init(coder: aDecoder)
 
-        appDelegate.activeFiles = self
         titleCurrentFolder = NCBrandOptions.shared.brand
         layoutKey = NCGlobal.shared.layoutViewFiles
         enableSearchBar = true
@@ -54,6 +54,12 @@ class NCFiles: NCCollectionViewCommon {
         super.viewWillAppear(animated)
     }
 
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+
+        fileNameBlink = nil
+    }
+
     // MARK: - NotificationCenter
 
     override func initialize(_ notification: NSNotification) {
@@ -76,6 +82,7 @@ class NCFiles: NCCollectionViewCommon {
     //
     // forced: do no make the etag of directory test (default)
     //
+
     override func reloadDataSource(forced: Bool = true) {
         super.reloadDataSource()
 
@@ -92,7 +99,7 @@ class NCFiles: NCCollectionViewCommon {
             self.richWorkspaceText = directory?.richWorkspace
 
             // FORCED false: test the directory.etag
-            if !forced, let directory = directory, directory.etag == self.dataSource.directory?.etag, metadataTransfer == nil {
+            if !forced, let directory = directory, directory.etag == self.dataSource.directory?.etag, metadataTransfer == nil, self.fileNameBlink == nil {
                 return
             }
 
@@ -109,7 +116,13 @@ class NCFiles: NCCollectionViewCommon {
                 providers: self.providers,
                 searchResults: self.searchResults)
 
-            DispatchQueue.main.async { self.collectionView.reloadData() }
+            DispatchQueue.main.async {
+                self.collectionView.reloadData()
+                if !self.dataSource.metadatas.isEmpty {
+                    self.blinkCell(fileName: self.fileNameBlink)
+                    self.fileNameBlink = nil
+                }
+            }
         }
     }
 
@@ -136,7 +149,30 @@ class NCFiles: NCCollectionViewCommon {
             if metadatasUpdate?.count ?? 0 > 0 || metadatasDelete?.count ?? 0 > 0 || forced {
                 self.reloadDataSource(forced: false)
             } else if self.dataSource.getMetadataSourceForAllSections().isEmpty {
-                DispatchQueue.main.async { self.collectionView.reloadData() }
+                DispatchQueue.main.async {
+                    self.collectionView.reloadData()
+                }
+            }
+        }
+    }
+
+    func blinkCell(fileName: String?) {
+
+        if let fileName = fileName, let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, fileName)) {
+            let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
+            if let indexPath = indexPath {
+                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+                    UIView.animate(withDuration: 0.3) {
+                        self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false)
+                    } completion: { _ in
+                        if let cell = self.collectionView.cellForItem(at: indexPath) {
+                            cell.backgroundColor = .darkGray
+                            UIView.animate(withDuration: 2) {
+                                cell.backgroundColor = .clear
+                            }
+                        }
+                    }
+                }
             }
         }
     }

+ 4 - 0
iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift

@@ -63,6 +63,10 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
         super.viewWillAppear(animated)
     }
 
+    override func viewDidAppear(_ animated: Bool) {
+        super.viewDidAppear(animated)
+    }
+
     override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
         super.traitCollectionDidChange(previousTraitCollection)
     }

+ 3 - 14
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -883,7 +883,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             if let viewerRichWorkspace = navigationController.topViewController as? NCViewerRichWorkspace {
                 viewerRichWorkspace.richWorkspaceText = richWorkspaceText ?? ""
                 viewerRichWorkspace.serverUrl = serverUrl
-
+                viewerRichWorkspace.delegate = self
+                
                 navigationController.modalPresentationStyle = .fullScreen
                 self.present(navigationController, animated: true, completion: nil)
             }
@@ -1214,18 +1215,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
             }
         }
 
-        // VIEW IN FOLDER
-        if layoutKey == NCGlobal.shared.layoutViewViewInFolder && !pushed {
-
-            if let viewController: NCFileViewInFolder = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as? NCFileViewInFolder {
-
-                viewController.serverUrl = serverUrlPush
-                viewController.titleCurrentFolder = metadata.fileNameView
-
-                pushViewController(viewController: viewController)
-            }
-        }
-
         // SHARES ( for push use Files ... he he he )
         if layoutKey == NCGlobal.shared.layoutViewShares && !pushed {
 
@@ -1282,7 +1271,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
 
             pushMetadata(metadata)
             
-        } else if !(self is NCFileViewInFolder) {
+        } else {
             
             let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag))
 

+ 41 - 32
iOSClient/Main/NCFunctionCenter.swift

@@ -454,49 +454,58 @@ import Photos
 
     // MARK: -
 
-    func openFileViewInFolder(serverUrl: String, fileName: String) {
+    func openFileViewInFolder(serverUrl: String, fileNameBlink: String?) {
 
-        let viewController = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as! NCFileViewInFolder
-        let navigationController = UINavigationController(rootViewController: viewController)
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+            var topNavigationController: UINavigationController?
+            var pushServerUrl = NCUtilityFileSystem.shared.getHomeServer(account: self.appDelegate.account)
+            var mostViewController = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController()
 
-        let topViewController = viewController
-        var listViewController = [NCFileViewInFolder]()
-        var serverUrl = serverUrl
-        let homeUrl = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account)
-
-        while true {
+            if mostViewController.isModal {
+                mostViewController.dismiss(animated: false)
+                mostViewController = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController()
+            }
+            mostViewController.navigationController?.popToRootViewController(animated: false)
 
-            var viewController: NCFileViewInFolder?
-            if serverUrl != homeUrl {
-                viewController = UIStoryboard(name: "NCFileViewInFolder", bundle: nil).instantiateInitialViewController() as? NCFileViewInFolder
-                if viewController == nil {
-                    return
+            if let tabBarController = self.appDelegate.window?.rootViewController as? UITabBarController {
+                tabBarController.selectedIndex = 0
+                if let navigationController = tabBarController.viewControllers?.first as? UINavigationController {
+                    navigationController.popToRootViewController(animated: false)
+                    topNavigationController = navigationController
                 }
-                viewController!.titleCurrentFolder = (serverUrl as NSString).lastPathComponent
-            } else {
-                viewController = topViewController
             }
-            guard let vc = viewController else { return }
+            if pushServerUrl == serverUrl {
+                let viewController = topNavigationController?.topViewController as? NCFiles
+                viewController?.blinkCell(fileName: fileNameBlink)
+                return
+            }
+            guard let topNavigationController = topNavigationController else { return }
 
-            vc.serverUrl = serverUrl
-            vc.fileName = fileName
+            let diffDirectory = serverUrl.replacingOccurrences(of: pushServerUrl, with: "")
+            var subDirs = diffDirectory.split(separator: "/")
 
-            vc.navigationItem.backButtonTitle = vc.titleCurrentFolder
-            listViewController.insert(vc, at: 0)
+            while pushServerUrl != serverUrl, subDirs.count > 0  {
 
-            if serverUrl != homeUrl {
-                serverUrl = NCUtilityFileSystem.shared.deletingLastPathComponent(account: appDelegate.account, serverUrl: serverUrl)
-            } else {
-                break
-            }
-        }
+                guard let dir = subDirs.first, let viewController = UIStoryboard(name: "NCFiles", bundle: nil).instantiateInitialViewController() as? NCFiles else { return }
+                pushServerUrl = pushServerUrl + "/" + dir
 
-        navigationController.setViewControllers(listViewController, animated: false)
-        navigationController.modalPresentationStyle = .formSheet
+                viewController.serverUrl = pushServerUrl
+                viewController.isRoot = false
+                viewController.titleCurrentFolder = String(dir)
+                if pushServerUrl == serverUrl {
+                    viewController.fileNameBlink = fileNameBlink
+                }
+                self.appDelegate.listFilesVC[serverUrl] = viewController
 
-        appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil)
+                viewController.navigationItem.backButtonTitle = viewController.titleCurrentFolder
+                topNavigationController.pushViewController(viewController, animated: false)
+
+                subDirs.remove(at: 0)
+            }
+        }
     }
 
+
     // MARK: - NCSelect + Delegate
 
     func dismissSelect(serverUrl: String?, metadata: tableMetadata?, type: String, items: [Any], overwrite: Bool, copy: Bool, move: Bool) {
@@ -633,7 +642,7 @@ import Photos
         }
 
         let viewInFolder = UIAction(title: NSLocalizedString("_view_in_folder_", comment: ""), image: UIImage(systemName: "arrow.forward.square")) { _ in
-            self.openFileViewInFolder(serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+            self.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName)
         }
 
         let openIn = UIAction(title: NSLocalizedString("_open_in_", comment: ""), image: UIImage(systemName: "square.and.arrow.up") ) { _ in

+ 1 - 1
iOSClient/Main/Section Header Footer/NCSectionFooter.xib

@@ -29,7 +29,7 @@
                         <action selector="touchUpInsideButton:" destination="Vin-9E-7nW" eventType="touchUpInside" id="XSh-0v-WHJ"/>
                     </connections>
                 </button>
-                <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="qWG-SR-Qly">
+                <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="qWG-SR-Qly">
                     <rect key="frame" x="177.5" y="5" width="20" height="20"/>
                 </activityIndicatorView>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="s2m-yO-4x0" userLabel="separator">

+ 0 - 2
iOSClient/Media/NCMedia.swift

@@ -71,8 +71,6 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate {
     override func viewDidLoad() {
         super.viewDidLoad()
 
-        appDelegate.activeMedia = self
-
         view.backgroundColor = NCBrandColor.shared.systemBackground
 
         collectionView.register(UINib(nibName: "NCGridMediaCell", bundle: nil), forCellWithReuseIdentifier: "gridCell")

+ 1 - 7
iOSClient/Menu/NCCollectionViewCommon+Menu.swift

@@ -281,13 +281,7 @@ extension NCCollectionViewCommon {
                         title: NSLocalizedString("_modify_", comment: ""),
                         icon: NCUtility.shared.loadImage(named: "pencil.tip.crop.circle"),
                         action: { menuAction in
-                            if self is NCFileViewInFolder {
-                                self.dismiss(animated: true) {
-                                    NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook)
-                                }
-                            } else {
-                                NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook)
-                            }
+                            NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileQuickLook)
                         }
                     )
                 )

+ 1 - 7
iOSClient/Menu/NCMenuAction.swift

@@ -154,13 +154,7 @@ extension NCMenuAction {
             title: NSLocalizedString("_open_in_", comment: ""),
             icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"),
             action: { _ in
-                if viewController is NCFileViewInFolder {
-                    viewController.dismiss(animated: true) {
-                        NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
-                    }
-                } else {
-                    NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
-                }
+                NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas)
                 completion?()
             }
         )

+ 1 - 1
iOSClient/Menu/NCViewer+Menu.swift

@@ -192,7 +192,7 @@ extension NCViewer {
                     title: NSLocalizedString("_view_in_folder_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "arrow.forward.square"),
                     action: { menuAction in
-                        NCFunctionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileName: metadata.fileName)
+                        NCFunctionCenter.shared.openFileViewInFolder(serverUrl: metadata.serverUrl, fileNameBlink: metadata.fileName)
                     }
                 )
             )

+ 1 - 0
iOSClient/NCGlobal.swift

@@ -373,4 +373,5 @@ class NCGlobal: NSObject {
     let tipNCViewerPDFThumbnail                                 = "tipncviewerpdfthumbnail"
     let tipNCCollectionViewCommonAccountRequest                 = "tipnccollectionviewcommonaccountrequest"
     let tipNCScanAddImage                                       = "tipncscanaddimage"
+    let tipNCViewerMediaDetailView                              = "tipncviewermediadetailview"
 }

+ 4 - 3
iOSClient/RichWorkspace/NCViewerRichWorkspace.swift

@@ -34,8 +34,9 @@ import MarkdownKit
     private var markdownParser = MarkdownParser()
     private var textViewColor: UIColor?
 
-    @objc public var richWorkspaceText: String = ""
-    @objc public var serverUrl: String = ""
+    var richWorkspaceText: String = ""
+    var serverUrl: String = ""
+    var delegate: NCCollectionViewCommon?
 
     // MARK: - View Life Cycle
 
@@ -66,7 +67,7 @@ import MarkdownKit
                 guard let metadata = metadata else { return }
                 NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadata.richWorkspace, account: account)
                 if self.richWorkspaceText != metadata.richWorkspace && metadata.richWorkspace != nil {
-                    self.appDelegate.activeFiles?.richWorkspaceText = self.richWorkspaceText
+                    self.delegate?.richWorkspaceText = self.richWorkspaceText
                     self.richWorkspaceText = metadata.richWorkspace!
                     DispatchQueue.main.async {
                         self.textView.attributedText = self.markdownParser.parse(metadata.richWorkspace!)

+ 0 - 3
iOSClient/Settings/CCAdvanced.m

@@ -403,9 +403,6 @@
     // Inizialized home
     [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:NCGlobal.shared.notificationCenterInitialize object:nil userInfo:nil];
     
-    // Clear Media
-    [appDelegate.activeMedia reloadDataSourceWithCompletion:^(NSArray *metadatas) { }];
-    
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
         [[NCUtility shared] stopActivityIndicator];
         [self calculateSize];

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

@@ -903,6 +903,7 @@
 "_tip_pdf_thumbnails_"      = "Swipe left from the right edge of the screen to show the thumbnails.";
 "_tip_accountrequest_"      = "Touch here to change account or to add a new one";
 "_tip_addcopyimage_"        = "Long press to paste a copied image";
+"_tip_open_mediadetail_"    = "Swipe up to show the details";
 
 // MARK: Accessibility
 

+ 49 - 3
iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift

@@ -24,6 +24,8 @@
 import UIKit
 import SVGKit
 import NCCommunication
+import EasyTipView
+import SwiftUI
 
 class NCViewerMedia: UIViewController {
 
@@ -38,6 +40,7 @@ class NCViewerMedia: UIViewController {
     @IBOutlet weak var detailView: NCViewerMediaDetailView!
 
     private var _autoPlay: Bool = false
+    private var tipView: EasyTipView?
 
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
     weak var viewerMediaPage: NCViewerMediaPage?
@@ -73,6 +76,7 @@ class NCViewerMedia: UIViewController {
     deinit {
         print("deinit NCViewerMedia")
 
+        self.tipView?.dismiss()
         NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
     }
 
@@ -111,7 +115,23 @@ class NCViewerMedia: UIViewController {
                 self.ncplayer = NCPlayer.init(url: url, autoPlay: self.autoPlay, isProxy: urlVideo.isProxy, imageVideoContainer: self.imageVideoContainer, playerToolBar: self.playerToolBar, metadata: self.metadata, detailView: self.detailView, viewController: self)
             }
         }
-        
+
+        // TIP
+        var preferences = EasyTipView.Preferences()
+        preferences.drawing.foregroundColor = .white
+        preferences.drawing.backgroundColor = NCBrandColor.shared.nextcloud
+        preferences.drawing.textAlignment = .left
+        preferences.drawing.arrowPosition = .top
+        preferences.drawing.cornerRadius = 10
+
+        preferences.animating.dismissTransform = CGAffineTransform(translationX: 0, y: 100)
+        preferences.animating.showInitialTransform = CGAffineTransform(translationX: 0, y: -100)
+        preferences.animating.showInitialAlpha = 0
+        preferences.animating.showDuration = 0.5
+        preferences.animating.dismissDuration = 0
+
+        tipView = EasyTipView(text: NSLocalizedString("_tip_open_mediadetail_", comment: ""), preferences: preferences, delegate: self)
+
         detailViewTopConstraint.constant = 0
         detailView.hide()
 
@@ -172,16 +192,25 @@ class NCViewerMedia: UIViewController {
             viewerMediaPage?.clearCommandCenter()
         }
 
+        // TIP
+        if !NCManageDatabase.shared.tipExists(NCGlobal.shared.tipNCViewerMediaDetailView), let view = self.navigationController?.navigationBar {
+            self.tipView?.show(forView: view)
+        }
+
         NotificationCenter.default.addObserver(self, selector: #selector(openDetail(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterOpenMediaDetail), object: nil)
     }
 
-    override func viewDidDisappear(_ animated: Bool) {
-        super.viewDidDisappear(animated)
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+
+        self.tipView?.dismiss()
     }
 
     override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
         super.viewWillTransition(to: size, with: coordinator)
 
+        self.tipView?.dismiss()
+
         coordinator.animate(alongsideTransition: { context in
             // back to the original size
             self.scrollView.zoom(to: CGRect(x: 0, y: 0, width: self.scrollView.bounds.width, height: self.scrollView.bounds.height), animated: false)
@@ -423,6 +452,8 @@ extension NCViewerMedia {
 
     private func openDetail() {
 
+        self.dismissTip()
+        
         CCUtility.setExif(metadata) { latitude, longitude, location, date, lensModel in
 
             if latitude != -1 && latitude != 0 && longitude != -1 && longitude != 0 {
@@ -539,6 +570,21 @@ extension NCViewerMedia: NCViewerMediaDetailViewDelegate {
     }
 }
 
+extension NCViewerMedia: EasyTipViewDelegate {
+
+    // TIP
+    func easyTipViewDidTap(_ tipView: EasyTipView) {
+        NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerMediaDetailView)
+    }
+
+    func easyTipViewDidDismiss(_ tipView: EasyTipView) { }
+
+    func dismissTip() {
+        NCManageDatabase.shared.addTip(NCGlobal.shared.tipNCViewerMediaDetailView)
+        self.tipView?.dismiss()
+    }
+}
+
 // MARK: -
 
 class imageVideoContainerView: UIImageView {

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

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ne8-hS-cp3">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ne8-hS-cp3">
     <device id="retina5_5" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
         <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"/>