forked from shadowfacts/Tusker
Make attachment description scrollable beyond a certain height
Closes #168
This commit is contained in:
parent
dc3c2d027c
commit
565d17970f
|
@ -17,8 +17,7 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
|
|
||||||
@IBOutlet weak var scrollView: UIScrollView!
|
@IBOutlet weak var scrollView: UIScrollView!
|
||||||
@IBOutlet weak var topControlsView: UIView!
|
@IBOutlet weak var topControlsView: UIView!
|
||||||
@IBOutlet weak var bottomControlsView: UIView!
|
@IBOutlet weak var descriptionTextView: UITextView!
|
||||||
@IBOutlet weak var descriptionLabel: UILabel!
|
|
||||||
|
|
||||||
private var shareContainer: UIView!
|
private var shareContainer: UIView!
|
||||||
private var closeContainer: UIView!
|
private var closeContainer: UIView!
|
||||||
|
@ -47,6 +46,7 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
}
|
}
|
||||||
var shrinkGestureEnabled = true
|
var shrinkGestureEnabled = true
|
||||||
|
|
||||||
|
private var isInitialAppearance = true
|
||||||
private var prevZoomScale: CGFloat?
|
private var prevZoomScale: CGFloat?
|
||||||
private var isGrayscale = false
|
private var isGrayscale = false
|
||||||
private var contentViewSizeObservation: NSKeyValueObservation?
|
private var contentViewSizeObservation: NSKeyValueObservation?
|
||||||
|
@ -99,9 +99,14 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
|
|
||||||
if let imageDescription = imageDescription,
|
if let imageDescription = imageDescription,
|
||||||
!imageDescription.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
!imageDescription.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
descriptionLabel.text = imageDescription.trimmingCharacters(in: .whitespacesAndNewlines)
|
descriptionTextView.text = imageDescription.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
descriptionTextView.textContainerInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
|
||||||
|
// i'm not sure why .automatic doesn't work for this
|
||||||
|
descriptionTextView.contentInsetAdjustmentBehavior = .always
|
||||||
|
let height = min(150, descriptionTextView.contentSize.height)
|
||||||
|
descriptionTextView.topAnchor.constraint(equalTo: descriptionTextView.safeAreaLayoutGuide.bottomAnchor, constant: -(height + 16)).isActive = true
|
||||||
} else {
|
} else {
|
||||||
bottomControlsView.isHidden = true
|
descriptionTextView.isHidden = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if shrinkGestureEnabled {
|
if shrinkGestureEnabled {
|
||||||
|
@ -121,7 +126,7 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
accessibilityElements = [
|
accessibilityElements = [
|
||||||
topControlsView!,
|
topControlsView!,
|
||||||
contentView,
|
contentView,
|
||||||
bottomControlsView!,
|
descriptionTextView!,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +248,20 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
// on the first appearance, the text view flashes its own scroll indicators automatically
|
||||||
|
// so we only need to do it on subsequent appearances
|
||||||
|
if isInitialAppearance {
|
||||||
|
isInitialAppearance = false
|
||||||
|
} else {
|
||||||
|
if animated && controlsVisible && !descriptionTextView.isHidden {
|
||||||
|
descriptionTextView.flashScrollIndicators()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func preferencesChanged() {
|
@objc private func preferencesChanged() {
|
||||||
if isGrayscale != Preferences.shared.grayscaleImages {
|
if isGrayscale != Preferences.shared.grayscaleImages {
|
||||||
isGrayscale = Preferences.shared.grayscaleImages
|
isGrayscale = Preferences.shared.grayscaleImages
|
||||||
|
@ -257,6 +276,9 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
self.contentView.setControlsVisible(controlsVisible)
|
self.contentView.setControlsVisible(controlsVisible)
|
||||||
self.updateControlsView()
|
self.updateControlsView()
|
||||||
}
|
}
|
||||||
|
if controlsVisible && !descriptionTextView.isHidden {
|
||||||
|
descriptionTextView.flashScrollIndicators()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
updateControlsView()
|
updateControlsView()
|
||||||
}
|
}
|
||||||
|
@ -266,8 +288,8 @@ class LargeImageViewController: UIViewController, UIScrollViewDelegate, LargeIma
|
||||||
let topOffset = self.controlsVisible ? 0 : -self.topControlsView.bounds.height
|
let topOffset = self.controlsVisible ? 0 : -self.topControlsView.bounds.height
|
||||||
self.topControlsView.transform = CGAffineTransform(translationX: 0, y: topOffset)
|
self.topControlsView.transform = CGAffineTransform(translationX: 0, y: topOffset)
|
||||||
if self.imageDescription != nil {
|
if self.imageDescription != nil {
|
||||||
let bottomOffset = self.controlsVisible ? 0 : self.bottomControlsView.bounds.height + self.view.safeAreaInsets.bottom
|
let bottomOffset = self.controlsVisible ? 0 : self.descriptionTextView.bounds.height + self.view.safeAreaInsets.bottom
|
||||||
self.bottomControlsView.transform = CGAffineTransform(translationX: 0, y: bottomOffset)
|
self.descriptionTextView.transform = CGAffineTransform(translationX: 0, y: bottomOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
<objects>
|
<objects>
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="LargeImageViewController" customModule="Tusker" customModuleProvider="target">
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="LargeImageViewController" customModule="Tusker" customModuleProvider="target">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="bottomControlsView" destination="rPa-Zu-T6g" id="Rgz-AQ-9nt"/>
|
<outlet property="descriptionTextView" destination="JZk-BO-2Vh" id="cby-Hc-ezg"/>
|
||||||
<outlet property="descriptionLabel" destination="eo5-fc-RV8" id="vrW-RJ-y5k"/>
|
|
||||||
<outlet property="scrollView" destination="Skj-xq-AgQ" id="TFb-zF-m1b"/>
|
<outlet property="scrollView" destination="Skj-xq-AgQ" id="TFb-zF-m1b"/>
|
||||||
<outlet property="topControlsView" destination="kHo-B9-R7a" id="8sJ-xQ-7ix"/>
|
<outlet property="topControlsView" destination="kHo-B9-R7a" id="8sJ-xQ-7ix"/>
|
||||||
<outlet property="view" destination="BJw-5C-9nT" id="1C2-VA-mNf"/>
|
<outlet property="view" destination="BJw-5C-9nT" id="1C2-VA-mNf"/>
|
||||||
|
@ -29,41 +28,34 @@
|
||||||
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kHo-B9-R7a">
|
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kHo-B9-R7a">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="36"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="36"/>
|
||||||
</view>
|
</view>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rPa-Zu-T6g">
|
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" textAlignment="natural" adjustsFontForContentSizeCategory="YES" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JZk-BO-2Vh">
|
||||||
<rect key="frame" x="0.0" y="622.5" width="375" height="44.5"/>
|
<rect key="frame" x="0.0" y="517" width="375" height="150"/>
|
||||||
<subviews>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eo5-fc-RV8">
|
|
||||||
<rect key="frame" x="16" y="8" width="343" height="20.5"/>
|
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="eo5-fc-RV8" firstAttribute="top" secondItem="rPa-Zu-T6g" secondAttribute="top" constant="8" id="6n3-E0-2G6"/>
|
<constraint firstAttribute="height" constant="150" placeholder="YES" id="YfV-kQ-0RT"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="eo5-fc-RV8" secondAttribute="trailing" constant="16" id="6uL-vY-tqk"/>
|
|
||||||
<constraint firstItem="eo5-fc-RV8" firstAttribute="leading" secondItem="rPa-Zu-T6g" secondAttribute="leading" constant="16" id="KIF-vw-K7n"/>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="eo5-fc-RV8" secondAttribute="bottom" constant="16" id="v43-mS-tyR"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
|
</textView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<viewLayoutGuide key="safeArea" id="w1g-VC-Ll9"/>
|
<viewLayoutGuide key="safeArea" id="w1g-VC-Ll9"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<gestureRecognizers/>
|
<gestureRecognizers/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="Skj-xq-AgQ" firstAttribute="centerY" secondItem="BJw-5C-9nT" secondAttribute="centerY" id="0Xb-ib-2hg"/>
|
<constraint firstItem="Skj-xq-AgQ" firstAttribute="centerY" secondItem="BJw-5C-9nT" secondAttribute="centerY" id="0Xb-ib-2hg"/>
|
||||||
<constraint firstItem="w1g-VC-Ll9" firstAttribute="trailing" secondItem="rPa-Zu-T6g" secondAttribute="trailing" id="2GG-7P-Qv1"/>
|
<constraint firstAttribute="bottom" secondItem="JZk-BO-2Vh" secondAttribute="bottom" id="7Z2-gW-sPj"/>
|
||||||
<constraint firstItem="w1g-VC-Ll9" firstAttribute="bottom" secondItem="rPa-Zu-T6g" secondAttribute="bottom" id="3qf-5e-vl0"/>
|
|
||||||
<constraint firstItem="kHo-B9-R7a" firstAttribute="leading" secondItem="w1g-VC-Ll9" secondAttribute="leading" id="IvH-gU-Kie"/>
|
<constraint firstItem="kHo-B9-R7a" firstAttribute="leading" secondItem="w1g-VC-Ll9" secondAttribute="leading" id="IvH-gU-Kie"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="JZk-BO-2Vh" secondAttribute="trailing" id="JgV-jy-qjS"/>
|
||||||
<constraint firstItem="Skj-xq-AgQ" firstAttribute="centerX" secondItem="BJw-5C-9nT" secondAttribute="centerX" id="KMe-Zc-NZq"/>
|
<constraint firstItem="Skj-xq-AgQ" firstAttribute="centerX" secondItem="BJw-5C-9nT" secondAttribute="centerX" id="KMe-Zc-NZq"/>
|
||||||
<constraint firstItem="Skj-xq-AgQ" firstAttribute="width" secondItem="BJw-5C-9nT" secondAttribute="width" id="Onj-l9-fBu"/>
|
<constraint firstItem="Skj-xq-AgQ" firstAttribute="width" secondItem="BJw-5C-9nT" secondAttribute="width" id="Onj-l9-fBu"/>
|
||||||
<constraint firstItem="w1g-VC-Ll9" firstAttribute="trailing" secondItem="kHo-B9-R7a" secondAttribute="trailing" id="Uh0-ub-R9V"/>
|
<constraint firstItem="w1g-VC-Ll9" firstAttribute="trailing" secondItem="kHo-B9-R7a" secondAttribute="trailing" id="Uh0-ub-R9V"/>
|
||||||
<constraint firstItem="rPa-Zu-T6g" firstAttribute="leading" secondItem="w1g-VC-Ll9" secondAttribute="leading" id="asz-Xj-FUC"/>
|
|
||||||
<constraint firstItem="Skj-xq-AgQ" firstAttribute="height" secondItem="BJw-5C-9nT" secondAttribute="height" id="jvz-QW-n9c"/>
|
<constraint firstItem="Skj-xq-AgQ" firstAttribute="height" secondItem="BJw-5C-9nT" secondAttribute="height" id="jvz-QW-n9c"/>
|
||||||
|
<constraint firstItem="JZk-BO-2Vh" firstAttribute="leading" secondItem="BJw-5C-9nT" secondAttribute="leading" id="kkj-O9-1rE"/>
|
||||||
<constraint firstItem="kHo-B9-R7a" firstAttribute="top" secondItem="BJw-5C-9nT" secondAttribute="top" id="n1O-C3-yQR"/>
|
<constraint firstItem="kHo-B9-R7a" firstAttribute="top" secondItem="BJw-5C-9nT" secondAttribute="top" id="n1O-C3-yQR"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<point key="canvasLocation" x="-164" y="476"/>
|
<point key="canvasLocation" x="-164" y="475.41229385307349"/>
|
||||||
</view>
|
</view>
|
||||||
</objects>
|
</objects>
|
||||||
</document>
|
</document>
|
||||||
|
|
Loading…
Reference in New Issue