Преглед на файлове

Slider video / audio usability (#2593)

* improvements

Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>

* improvements

Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>

* improvements

Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>

---------

Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>
Marino Faggiana преди 1 година
родител
ревизия
96d8c57477
променени са 2 файла, в които са добавени 81 реда и са изтрити 42 реда
  1. 58 19
      iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift
  2. 23 23
      iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.xib

+ 58 - 19
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift

@@ -45,7 +45,7 @@ class NCPlayerToolBar: UIView {
     @IBOutlet weak var forwardButton: UIButton!
 
     @IBOutlet weak var playbackSliderView: UIView!
-    @IBOutlet weak var playbackSlider: UISlider!
+    @IBOutlet weak var playbackSlider: NCPlayerToolBarSlider!
     @IBOutlet weak var labelLeftTime: UILabel!
     @IBOutlet weak var labelCurrentTime: UILabel!
     @IBOutlet weak var repeatButton: UIButton!
@@ -95,6 +95,7 @@ class NCPlayerToolBar: UIView {
         playButton.setImage(NCUtility.shared.loadImage(named: "play.fill", color: .white, symbolConfiguration: UIImage.SymbolConfiguration(pointSize: pointSize)), for: .normal)
         forwardButton.setImage(NCUtility.shared.loadImage(named: "goforward.10", color: .white, symbolConfiguration: UIImage.SymbolConfiguration(pointSize: pointSize)), for: .normal)
 
+        playbackSlider.addTapGesture()
         playbackSlider.setThumbImage(UIImage(systemName: "circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 15)), for: .normal)
         playbackSlider.value = 0
         playbackSlider.tintColor = .white
@@ -103,6 +104,7 @@ class NCPlayerToolBar: UIView {
 
         utilityView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(gestureRecognizer:))))
         playbackSliderView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(gestureRecognizer:))))
+        playbackSliderView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(tap(gestureRecognizer:))))
         playerButtonView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(gestureRecognizer:))))
 
         labelCurrentTime.textColor = .white
@@ -216,27 +218,29 @@ class NCPlayerToolBar: UIView {
 
     @objc func playbackValChanged(slider: UISlider, event: UIEvent) {
 
-        guard let touchEvent = event.allTouches?.first,
-              let ncplayer = ncplayer
-        else { return }
-
+        guard let ncplayer = ncplayer else { return }
         let newPosition = playbackSlider.value
 
-        switch touchEvent.phase {
-        case .began:
-            viewerMediaPage?.timerAutoHide?.invalidate()
-            playbackSliderEvent = .began
-        case .moved:
-            ncplayer.playerPosition(newPosition)
-            playbackSliderEvent = .moved
-        case .ended:
-            ncplayer.playerPosition(newPosition)
-            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                self.playbackSliderEvent = .ended
-                self.viewerMediaPage?.startTimerAutoHide()
+        if let touchEvent = event.allTouches?.first {
+            switch touchEvent.phase {
+            case .began:
+                viewerMediaPage?.timerAutoHide?.invalidate()
+                playbackSliderEvent = .began
+            case .moved:
+                ncplayer.playerPosition(newPosition)
+                playbackSliderEvent = .moved
+            case .ended:
+                ncplayer.playerPosition(newPosition)
+                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+                    self.playbackSliderEvent = .ended
+                    self.viewerMediaPage?.startTimerAutoHide()
+                }
+            default:
+                break
             }
-        default:
-            break
+        } else {
+            ncplayer.playerPosition(newPosition)
+            self.viewerMediaPage?.startTimerAutoHide()
         }
     }
 
@@ -504,3 +508,38 @@ extension NCPlayerToolBar: NCSelectDelegate {
         }
     }
 }
+
+// https://stackoverflow.com/questions/13196263/custom-uislider-increase-hot-spot-size
+//
+class NCPlayerToolBarSlider: UISlider {
+
+    private var thumbTouchSize = CGSize(width: 100, height: 100)
+
+    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
+        let increasedBounds = bounds.insetBy(dx: -thumbTouchSize.width, dy: -thumbTouchSize.height)
+        let containsPoint = increasedBounds.contains(point)
+        return containsPoint
+    }
+
+    override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
+        let percentage = CGFloat((value - minimumValue) / (maximumValue - minimumValue))
+        let thumbSizeHeight = thumbRect(forBounds: bounds, trackRect:trackRect(forBounds: bounds), value:0).size.height
+        let thumbPosition = thumbSizeHeight + (percentage * (bounds.size.width - (2 * thumbSizeHeight)))
+        let touchLocation = touch.location(in: self)
+        return touchLocation.x <= (thumbPosition + thumbTouchSize.width) && touchLocation.x >= (thumbPosition - thumbTouchSize.width)
+    }
+
+    public func addTapGesture() {
+
+        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
+        addGestureRecognizer(tap)
+    }
+
+    @objc private func handleTap(_ sender: UITapGestureRecognizer) {
+
+        let location = sender.location(in: self)
+        let percent = minimumValue + Float(location.x / bounds.width) * (maximumValue - minimumValue)
+        setValue(percent, animated: true)
+        sendActions(for: .valueChanged)
+    }
+}

+ 23 - 23
iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.xib

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina4_7" orientation="portrait" appearance="light"/>
+    <device id="retina5_9" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
@@ -11,14 +11,14 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
         <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="NCPlayerToolBar" customModule="Nextcloud" customModuleProvider="target">
-            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+            <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="orv-9i-XUs">
                     <rect key="frame" x="20" y="0.0" width="335" height="50"/>
                     <subviews>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qqZ-QN-TsW">
-                            <rect key="frame" x="217" y="10" width="22.5" height="22"/>
+                            <rect key="frame" x="217" y="10" width="22.333333333333343" height="22"/>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="captions.bubble" catalog="system"/>
                             <connections>
@@ -26,7 +26,7 @@
                             </connections>
                         </button>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sMY-qo-4CE">
-                            <rect key="frame" x="264.5" y="10" width="25.5" height="22"/>
+                            <rect key="frame" x="264.33333333333331" y="10" width="25.666666666666686" height="22"/>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="speaker.zzz" catalog="system"/>
                             <connections>
@@ -54,10 +54,10 @@
                     </constraints>
                 </view>
                 <stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" alignment="center" spacing="30" translatesAutoresizingMaskIntoConstraints="NO" id="ncM-9U-phl" userLabel="Player Top Tool Bar">
-                    <rect key="frame" x="125" y="317.5" width="125" height="32.5"/>
+                    <rect key="frame" x="125.33333333333334" y="390" width="124.33333333333334" height="32.333333333333314"/>
                     <subviews>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xja-nq-uD3">
-                            <rect key="frame" x="5" y="5" width="20" height="22.5"/>
+                            <rect key="frame" x="5.0000000000000142" y="4.9999999999999982" width="19.666666666666668" height="22.333333333333329"/>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="gobackward.10" catalog="system"/>
                             <connections>
@@ -65,7 +65,7 @@
                             </connections>
                         </button>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qo0-x8-OfL">
-                            <rect key="frame" x="55" y="5" width="15" height="22"/>
+                            <rect key="frame" x="54.666666666666671" y="5" width="15" height="22"/>
                             <fontDescription key="fontDescription" type="system" pointSize="18"/>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="play.fill" catalog="system"/>
@@ -74,7 +74,7 @@
                             </connections>
                         </button>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5Zd-By-Fko">
-                            <rect key="frame" x="100" y="5" width="20" height="22.5"/>
+                            <rect key="frame" x="99.666666666666671" y="4.9999999999999982" width="19.666666666666671" height="22.333333333333329"/>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="goforward.10" catalog="system"/>
                             <connections>
@@ -86,25 +86,25 @@
                     <directionalEdgeInsets key="directionalLayoutMargins" top="5" leading="5" bottom="5" trailing="5"/>
                 </stackView>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="85m-50-8yp">
-                    <rect key="frame" x="20" y="594" width="335" height="58"/>
+                    <rect key="frame" x="0.0" y="662" width="375" height="150"/>
                     <subviews>
-                        <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="MY0-FC-j88">
-                            <rect key="frame" x="-2" y="14" width="297" height="31"/>
+                        <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="MY0-FC-j88" customClass="NCPlayerToolBarSlider" customModule="Nextcloud" customModuleProvider="target">
+                            <rect key="frame" x="48" y="70" width="277" height="31"/>
                         </slider>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="--:--" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="svM-TQ-AyQ">
-                            <rect key="frame" x="270.5" y="44" width="22.5" height="12"/>
+                            <rect key="frame" x="300.33333333333331" y="100" width="22.666666666666686" height="12"/>
                             <fontDescription key="fontDescription" type="system" pointSize="10"/>
                             <nil key="textColor"/>
                             <nil key="highlightedColor"/>
                         </label>
                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="--:--" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OHB-2J-Gqb">
-                            <rect key="frame" x="0.0" y="44" width="22.5" height="12"/>
+                            <rect key="frame" x="50" y="100" width="22.666666666666671" height="12"/>
                             <fontDescription key="fontDescription" type="system" pointSize="10"/>
                             <nil key="textColor"/>
                             <nil key="highlightedColor"/>
                         </label>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VLW-it-fXU">
-                            <rect key="frame" x="313" y="18" width="22" height="22"/>
+                            <rect key="frame" x="333" y="74" width="22" height="22"/>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="repeat" catalog="system"/>
                             <connections>
@@ -115,25 +115,25 @@
                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                     <constraints>
                         <constraint firstItem="OHB-2J-Gqb" firstAttribute="leading" secondItem="MY0-FC-j88" secondAttribute="leading" id="6n7-If-xdS"/>
-                        <constraint firstAttribute="height" constant="58" id="9Uv-dV-to4"/>
+                        <constraint firstAttribute="height" constant="150" id="9Uv-dV-to4"/>
                         <constraint firstItem="svM-TQ-AyQ" firstAttribute="top" secondItem="MY0-FC-j88" secondAttribute="bottom" id="Aan-ac-nr9"/>
-                        <constraint firstItem="MY0-FC-j88" firstAttribute="leading" secondItem="85m-50-8yp" secondAttribute="leading" id="Hjo-k0-bpn"/>
+                        <constraint firstItem="MY0-FC-j88" firstAttribute="leading" secondItem="85m-50-8yp" secondAttribute="leading" constant="50" id="Hjo-k0-bpn"/>
                         <constraint firstItem="VLW-it-fXU" firstAttribute="centerY" secondItem="MY0-FC-j88" secondAttribute="centerY" id="OYO-ej-jdC"/>
                         <constraint firstItem="svM-TQ-AyQ" firstAttribute="trailing" secondItem="MY0-FC-j88" secondAttribute="trailing" id="gso-SX-bYq"/>
                         <constraint firstItem="OHB-2J-Gqb" firstAttribute="top" secondItem="MY0-FC-j88" secondAttribute="bottom" id="jdb-Vq-WoF"/>
-                        <constraint firstItem="MY0-FC-j88" firstAttribute="centerY" secondItem="85m-50-8yp" secondAttribute="centerY" id="lG8-DN-rTE"/>
-                        <constraint firstAttribute="trailing" secondItem="VLW-it-fXU" secondAttribute="trailing" id="mZX-EK-qnC"/>
-                        <constraint firstItem="VLW-it-fXU" firstAttribute="leading" secondItem="MY0-FC-j88" secondAttribute="trailing" constant="20" id="vSb-In-qqx"/>
+                        <constraint firstAttribute="trailing" secondItem="VLW-it-fXU" secondAttribute="trailing" constant="20" id="mZX-EK-qnC"/>
+                        <constraint firstItem="VLW-it-fXU" firstAttribute="leading" secondItem="MY0-FC-j88" secondAttribute="trailing" constant="10" id="vSb-In-qqx"/>
+                        <constraint firstItem="MY0-FC-j88" firstAttribute="top" secondItem="85m-50-8yp" secondAttribute="top" constant="70" id="xFW-iH-iIj"/>
                     </constraints>
                 </view>
             </subviews>
             <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <constraints>
-                <constraint firstItem="85m-50-8yp" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" id="5H2-Gg-PEb"/>
-                <constraint firstAttribute="trailing" secondItem="85m-50-8yp" secondAttribute="trailing" constant="20" id="BXT-Qo-qFl"/>
+                <constraint firstItem="85m-50-8yp" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="5H2-Gg-PEb"/>
+                <constraint firstAttribute="trailing" secondItem="85m-50-8yp" secondAttribute="trailing" id="BXT-Qo-qFl"/>
                 <constraint firstItem="ncM-9U-phl" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="DAA-xj-35k"/>
-                <constraint firstAttribute="bottom" secondItem="85m-50-8yp" secondAttribute="bottom" constant="15" id="N7Q-PF-7lb"/>
+                <constraint firstAttribute="bottom" secondItem="85m-50-8yp" secondAttribute="bottom" id="N7Q-PF-7lb"/>
                 <constraint firstAttribute="trailing" secondItem="orv-9i-XUs" secondAttribute="trailing" constant="20" id="Nnr-hx-a2V"/>
                 <constraint firstItem="ncM-9U-phl" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="dPB-Kf-Ad7"/>
                 <constraint firstItem="orv-9i-XUs" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" id="xBn-BF-JVz"/>
@@ -154,7 +154,7 @@
                 <outlet property="subtitleButton" destination="qqZ-QN-TsW" id="XCP-hb-eZB"/>
                 <outlet property="utilityView" destination="orv-9i-XUs" id="AGX-4E-dOr"/>
             </connections>
-            <point key="canvasLocation" x="136.80000000000001" y="152.47376311844079"/>
+            <point key="canvasLocation" x="136.80000000000001" y="152.21674876847291"/>
         </view>
     </objects>
     <resources>