forked from shadowfacts/Tusker
Fix sometimes broken masking of text view link preview animations
This commit is contained in:
parent
fdcdbced38
commit
47dc00ab8f
|
@ -175,6 +175,7 @@
|
|||
D681E4D9246E346E0053414F /* AccountActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */; };
|
||||
D68232F72464F4FD00325FB8 /* ComposeDrawingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.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 */; };
|
||||
D693DE5923FE24310061E07D /* InteractivePushTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D693DE5823FE24300061E07D /* InteractivePushTransition.swift */; };
|
||||
D6945C2F23AC47C3005C403C /* SavedDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6945C2E23AC47C3005C403C /* SavedDataManager.swift */; };
|
||||
|
@ -484,6 +485,7 @@
|
|||
D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountActivityItemSource.swift; sourceTree = "<group>"; };
|
||||
D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeDrawingViewController.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>"; };
|
||||
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>"; };
|
||||
|
@ -1064,6 +1066,7 @@
|
|||
D6EBF01623C55E0D00AE061B /* UISceneSession+MastodonController.swift */,
|
||||
D6969E9D240C81B9002843CE /* NSTextAttachment+Emoji.swift */,
|
||||
D67895BB24671E6D00D4CD9E /* PKDrawing+Render.swift */,
|
||||
D690797224A4EF9700023A34 /* UIBezierPath+Helpers.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1849,6 +1852,7 @@
|
|||
D667E5E721349D4C0057A976 /* ProfileTableViewController.swift in Sources */,
|
||||
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
|
||||
D6B053A423BD2C8100A066FA /* AssetCollectionsListViewController.swift in Sources */,
|
||||
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */,
|
||||
D693DE5723FE1A6A0061E07D /* EnhancedNavigationViewController.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.
|
||||
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
|
||||
// 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.
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue