forked from shadowfacts/Tusker
Fix sometimes broken masking of text view link preview animations
This commit is contained in:
parent
864fd77ecc
commit
f86d3a0ed1
|
@ -178,6 +178,7 @@
|
||||||
D68E525B24A3D77E0054355A /* TuskerRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */; };
|
D68E525B24A3D77E0054355A /* TuskerRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */; };
|
||||||
D68E525D24A3E8F00054355A /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525C24A3E8F00054355A /* SearchViewController.swift */; };
|
D68E525D24A3E8F00054355A /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525C24A3E8F00054355A /* SearchViewController.swift */; };
|
||||||
D68FEC4F232C5BC300C84F23 /* SegmentedPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68FEC4E232C5BC300C84F23 /* SegmentedPageViewController.swift */; };
|
D68FEC4F232C5BC300C84F23 /* SegmentedPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68FEC4E232C5BC300C84F23 /* SegmentedPageViewController.swift */; };
|
||||||
|
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */; };
|
||||||
D693DE5723FE1A6A0061E07D /* EnhancedNavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693DE5623FE1A6A0061E07D /* EnhancedNavigationViewController.swift */; };
|
D693DE5723FE1A6A0061E07D /* EnhancedNavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693DE5623FE1A6A0061E07D /* EnhancedNavigationViewController.swift */; };
|
||||||
D693DE5923FE24310061E07D /* InteractivePushTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693DE5823FE24300061E07D /* InteractivePushTransition.swift */; };
|
D693DE5923FE24310061E07D /* InteractivePushTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693DE5823FE24300061E07D /* InteractivePushTransition.swift */; };
|
||||||
D6945C2F23AC47C3005C403C /* SavedDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6945C2E23AC47C3005C403C /* SavedDataManager.swift */; };
|
D6945C2F23AC47C3005C403C /* SavedDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6945C2E23AC47C3005C403C /* SavedDataManager.swift */; };
|
||||||
|
@ -490,6 +491,7 @@
|
||||||
D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerRootViewController.swift; sourceTree = "<group>"; };
|
D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerRootViewController.swift; sourceTree = "<group>"; };
|
||||||
D68E525C24A3E8F00054355A /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = "<group>"; };
|
D68E525C24A3E8F00054355A /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = "<group>"; };
|
||||||
D68FEC4E232C5BC300C84F23 /* SegmentedPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedPageViewController.swift; sourceTree = "<group>"; };
|
D68FEC4E232C5BC300C84F23 /* SegmentedPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedPageViewController.swift; sourceTree = "<group>"; };
|
||||||
|
D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBezierPath+Helpers.swift"; sourceTree = "<group>"; };
|
||||||
D693DE5623FE1A6A0061E07D /* EnhancedNavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnhancedNavigationViewController.swift; sourceTree = "<group>"; };
|
D693DE5623FE1A6A0061E07D /* EnhancedNavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnhancedNavigationViewController.swift; sourceTree = "<group>"; };
|
||||||
D693DE5823FE24300061E07D /* InteractivePushTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractivePushTransition.swift; sourceTree = "<group>"; };
|
D693DE5823FE24300061E07D /* InteractivePushTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractivePushTransition.swift; sourceTree = "<group>"; };
|
||||||
D6945C2E23AC47C3005C403C /* SavedDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedDataManager.swift; sourceTree = "<group>"; };
|
D6945C2E23AC47C3005C403C /* SavedDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedDataManager.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1073,6 +1075,7 @@
|
||||||
D6EBF01623C55E0D00AE061B /* UISceneSession+MastodonController.swift */,
|
D6EBF01623C55E0D00AE061B /* UISceneSession+MastodonController.swift */,
|
||||||
D6969E9D240C81B9002843CE /* NSTextAttachment+Emoji.swift */,
|
D6969E9D240C81B9002843CE /* NSTextAttachment+Emoji.swift */,
|
||||||
D67895BB24671E6D00D4CD9E /* PKDrawing+Render.swift */,
|
D67895BB24671E6D00D4CD9E /* PKDrawing+Render.swift */,
|
||||||
|
D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1870,6 +1873,7 @@
|
||||||
D667E5E721349D4C0057A976 /* ProfileTableViewController.swift in Sources */,
|
D667E5E721349D4C0057A976 /* ProfileTableViewController.swift in Sources */,
|
||||||
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
|
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
|
||||||
D6B053A423BD2C8100A066FA /* AssetCollectionsListViewController.swift in Sources */,
|
D6B053A423BD2C8100A066FA /* AssetCollectionsListViewController.swift in Sources */,
|
||||||
|
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */,
|
||||||
D693DE5723FE1A6A0061E07D /* EnhancedNavigationViewController.swift in Sources */,
|
D693DE5723FE1A6A0061E07D /* EnhancedNavigationViewController.swift in Sources */,
|
||||||
D6163F2C21AA0AF1008DAC41 /* MyProfileTableViewController.swift in Sources */,
|
D6163F2C21AA0AF1008DAC41 /* MyProfileTableViewController.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// UIBezierPath+Helpers.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 6/25/20.
|
||||||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
// TODO: write unit tests for this
|
||||||
|
extension UIBezierPath {
|
||||||
|
|
||||||
|
/// Create a new UIBezierPath that wraps around the given array of rectangles.
|
||||||
|
/// This is not a convex hull aglorithm. What this does is it takes a set of rectangles
|
||||||
|
/// and draws a line around the outer borders of the combined shape.
|
||||||
|
convenience init(wrappingAround rects: [CGRect]) {
|
||||||
|
precondition(rects.count > 0)
|
||||||
|
let rects = rects.sorted { $0.minY < $1.minY }
|
||||||
|
|
||||||
|
self.init()
|
||||||
|
|
||||||
|
// start at the top left corner
|
||||||
|
self.move(to: CGPoint(x: rects.first!.minX, y: rects.first!.minY))
|
||||||
|
|
||||||
|
// walk down the left side
|
||||||
|
var prevLeft = rects.first!.minX
|
||||||
|
for rect in rects where !rect.minX.isEqual(to: prevLeft) {
|
||||||
|
self.addLine(to: CGPoint(x: prevLeft, y: rect.minY))
|
||||||
|
self.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
|
||||||
|
prevLeft = rect.minX
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure at the bottom left if not already
|
||||||
|
let bottomLeft = CGPoint(x: rects.last!.minX, y: rects.last!.maxY)
|
||||||
|
if !self.currentPoint.equalTo(bottomLeft) {
|
||||||
|
self.addLine(to: bottomLeft)
|
||||||
|
}
|
||||||
|
|
||||||
|
// across the bottom of the last rect
|
||||||
|
self.addLine(to: CGPoint(x: rects.last!.maxX, y: rects.last!.maxY))
|
||||||
|
|
||||||
|
// walk up the right side
|
||||||
|
var prevRight = rects.last!.maxX
|
||||||
|
for rect in rects.reversed() where !rect.maxX.isEqual(to: prevRight) {
|
||||||
|
self.addLine(to: CGPoint(x: prevRight, y: rect.maxY))
|
||||||
|
self.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
|
||||||
|
prevRight = rect.maxX
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure at the top right if not already
|
||||||
|
let topRight = CGPoint(x: rects.first!.maxX, y: rects.first!.minY)
|
||||||
|
if !self.currentPoint.equalTo(topRight) {
|
||||||
|
self.addLine(to: topRight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// across the top of the first rect
|
||||||
|
self.addLine(to: CGPoint(x: rects.first!.minX, y: rects.first!.minY))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -327,7 +327,13 @@ extension ContentTextView: UIContextMenuInteractionDelegate {
|
||||||
|
|
||||||
// The preview parameters describe how the preview view is shown inside the prev.
|
// The preview parameters describe how the preview view is shown inside the prev.
|
||||||
let parameters = UIPreviewParameters(textLineRects: rectsInCoordinateSpaceOfEnclosingRect as [NSValue])
|
let parameters = UIPreviewParameters(textLineRects: rectsInCoordinateSpaceOfEnclosingRect as [NSValue])
|
||||||
// todo: parameters.visiblePath around text
|
|
||||||
|
// Mask the snapshot layer to only show the text of the link, and nothing else.
|
||||||
|
// By default, the system-applied mask is too wide and other content may seep in.
|
||||||
|
let path = UIBezierPath(wrappingAround: rectsInCoordinateSpaceOfEnclosingRect)
|
||||||
|
let maskLayer = CAShapeLayer()
|
||||||
|
maskLayer.path = path.cgPath
|
||||||
|
snapshot.layer.mask = maskLayer
|
||||||
|
|
||||||
// The center point of the the minimum enclosing rect in our coordinate space is the point where the
|
// The center point of the the minimum enclosing rect in our coordinate space is the point where the
|
||||||
// center of the preview should be, since that's also in this view's coordinate space.
|
// center of the preview should be, since that's also in this view's coordinate space.
|
||||||
|
@ -336,7 +342,12 @@ extension ContentTextView: UIContextMenuInteractionDelegate {
|
||||||
// The preview target describes how the preview is positioned.
|
// The preview target describes how the preview is positioned.
|
||||||
let target = UIPreviewTarget(container: self, center: rectsCenter)
|
let target = UIPreviewTarget(container: self, center: rectsCenter)
|
||||||
|
|
||||||
return UITargetedPreview(view: snapshot, parameters: parameters, target: target)
|
// Create a dummy containerview for the snapshot view, since using a view with a CALayer mask and UIPreviewParameters(textLineRects:)
|
||||||
|
// causes the mask to be ignored. See FB7832297
|
||||||
|
let snapshotContainer = UIView(frame: snapshot.bounds)
|
||||||
|
snapshotContainer.addSubview(snapshot)
|
||||||
|
|
||||||
|
return UITargetedPreview(view: snapshotContainer, parameters: parameters, target: target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
|
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
|
||||||
|
|
Loading…
Reference in New Issue