Merge commit 'develop' into release/0.4.0
This commit is contained in:
commit
ebc25be6a5
|
@ -8,7 +8,7 @@
|
|||
import Foundation
|
||||
import CoreData
|
||||
|
||||
public protocol Managed: class, NSFetchRequestResult {
|
||||
public protocol Managed: AnyObject, NSFetchRequestResult {
|
||||
static var entityName: String { get }
|
||||
static var defaultSortDescriptors: [NSSortDescriptor] { get }
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
protocol NeedsDependency: class {
|
||||
protocol NeedsDependency: AnyObject {
|
||||
var context: AppContext! { get set }
|
||||
var coordinator: SceneCoordinator! { get set }
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ extension ComposeStatusItem {
|
|||
}
|
||||
}
|
||||
|
||||
protocol ComposePollAttributeDelegate: class {
|
||||
protocol ComposePollAttributeDelegate: AnyObject {
|
||||
func composePollAttribute(_ attribute: ComposeStatusItem.ComposePollOptionAttribute, pollOptionDidChange: String?)
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,20 @@ extension StatusSection {
|
|||
emojiDict: (status.reblog ?? status).emojiDict
|
||||
)
|
||||
|
||||
// set visibility
|
||||
if let visibility = (status.reblog ?? status).visibility {
|
||||
cell.statusView.updateVisibility(visibility: visibility)
|
||||
|
||||
cell.statusView.revealContentWarningButton.publisher(for: \.isHidden)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak cell] isHidden in
|
||||
cell?.statusView.visibilityImageView.isHidden = !isHidden
|
||||
}
|
||||
.store(in: &cell.disposeBag)
|
||||
} else {
|
||||
cell.statusView.visibilityImageView.isHidden = true
|
||||
}
|
||||
|
||||
// prepare media attachments
|
||||
let mediaAttachments = Array((status.reblog ?? status).mediaAttachments ?? []).sorted { $0.index.compare($1.index) == .orderedAscending }
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
protocol ContentOffsetAdjustableTimelineViewControllerDelegate: class {
|
||||
protocol ContentOffsetAdjustableTimelineViewControllerDelegate: AnyObject {
|
||||
func navigationBar() -> UINavigationBar?
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
import Foundation
|
||||
import Combine
|
||||
|
||||
protocol DisposeBagCollectable: class {
|
||||
protocol DisposeBagCollectable: AnyObject {
|
||||
var disposeBag: Set<AnyCancellable> { get set }
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import UIKit
|
||||
import Combine
|
||||
|
||||
protocol ComposeStatusAttachmentCollectionViewCellDelegate: class {
|
||||
protocol ComposeStatusAttachmentCollectionViewCellDelegate: AnyObject {
|
||||
func composeStatusAttachmentCollectionViewCell(_ cell: ComposeStatusAttachmentCollectionViewCell, removeButtonDidPressed button: UIButton)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import UIKit
|
||||
import Combine
|
||||
|
||||
protocol ComposeStatusPollExpiresOptionCollectionViewCellDelegate: class {
|
||||
protocol ComposeStatusPollExpiresOptionCollectionViewCellDelegate: AnyObject {
|
||||
func composeStatusPollExpiresOptionCollectionViewCell(_ cell: ComposeStatusPollExpiresOptionCollectionViewCell, didSelectExpiresOption expiresOption: ComposeStatusItem.ComposePollExpiresOptionAttribute.ExpiresOption)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import os.log
|
||||
import UIKit
|
||||
|
||||
protocol ComposeStatusPollOptionAppendEntryCollectionViewCellDelegate: class {
|
||||
protocol ComposeStatusPollOptionAppendEntryCollectionViewCellDelegate: AnyObject {
|
||||
func composeStatusPollOptionAppendEntryCollectionViewCellDidPressed(_ cell: ComposeStatusPollOptionAppendEntryCollectionViewCell)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import UIKit
|
||||
import Combine
|
||||
|
||||
protocol ComposeStatusPollOptionCollectionViewCellDelegate: class {
|
||||
protocol ComposeStatusPollOptionCollectionViewCellDelegate: AnyObject {
|
||||
func composeStatusPollOptionCollectionViewCell(_ cell: ComposeStatusPollOptionCollectionViewCell, textFieldDidBeginEditing textField: UITextField)
|
||||
func composeStatusPollOptionCollectionViewCell(_ cell: ComposeStatusPollOptionCollectionViewCell, textBeforeDeleteBackward text: String?)
|
||||
func composeStatusPollOptionCollectionViewCell(_ cell: ComposeStatusPollOptionCollectionViewCell, pollOptionTextFieldDidReturn: UITextField)
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import UIKit
|
||||
import MastodonSDK
|
||||
|
||||
protocol ComposeToolbarViewDelegate: class {
|
||||
protocol ComposeToolbarViewDelegate: AnyObject {
|
||||
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: UIButton, mediaSelectionType type: ComposeToolbarView.MediaSelectionType)
|
||||
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, pollButtonDidPressed sender: UIButton)
|
||||
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, emojiButtonDidPressed sender: UIButton)
|
||||
|
@ -181,6 +181,15 @@ extension ComposeToolbarView {
|
|||
}
|
||||
}
|
||||
|
||||
func imageNameForTimeline() -> String {
|
||||
switch self {
|
||||
case .public: return "person.3"
|
||||
case .unlisted: return "eye.slash"
|
||||
case .private: return "person.crop.circle.badge.plus"
|
||||
case .direct: return "at"
|
||||
}
|
||||
}
|
||||
|
||||
var visibility: Mastodon.Entity.Status.Visibility {
|
||||
switch self {
|
||||
case .public: return .public
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import os.log
|
||||
import UIKit
|
||||
|
||||
protocol HomeTimelineNavigationBarTitleViewDelegate: class {
|
||||
protocol HomeTimelineNavigationBarTitleViewDelegate: AnyObject {
|
||||
func homeTimelineNavigationBarTitleView(_ titleView: HomeTimelineNavigationBarTitleView, buttonDidPressed sender: UIButton)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import MastodonSDK
|
|||
import AlamofireImage
|
||||
import Kanna
|
||||
|
||||
protocol PickServerCellDelegate: class {
|
||||
protocol PickServerCellDelegate: AnyObject {
|
||||
func pickServerCell(_ cell: PickServerCell, expandButtonPressed button: UIButton)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
protocol PickServerSearchCellDelegate: class {
|
||||
protocol PickServerSearchCellDelegate: AnyObject {
|
||||
func pickServerSearchCell(_ cell: PickServerSearchCell, searchTextDidChange searchText: String?)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import AlamofireImage
|
|||
import CropViewController
|
||||
import TwitterTextEditor
|
||||
|
||||
protocol ProfileHeaderViewControllerDelegate: class {
|
||||
protocol ProfileHeaderViewControllerDelegate: AnyObject {
|
||||
func profileHeaderViewController(_ viewController: ProfileHeaderViewController, viewLayoutDidUpdate view: UIView)
|
||||
func profileHeaderViewController(_ viewController: ProfileHeaderViewController, pageSegmentedControlValueChanged segmentedControl: UISegmentedControl, selectedSegmentIndex index: Int)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import os.log
|
||||
import UIKit
|
||||
|
||||
protocol ProfileStatusDashboardViewDelegate: class {
|
||||
protocol ProfileStatusDashboardViewDelegate: AnyObject {
|
||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, postDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, followingDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, followersDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
||||
|
|
|
@ -10,7 +10,7 @@ import UIKit
|
|||
import Pageboy
|
||||
import Tabman
|
||||
|
||||
protocol ProfilePagingViewControllerDelegate: class {
|
||||
protocol ProfilePagingViewControllerDelegate: AnyObject {
|
||||
func profilePagingViewController(_ viewController: ProfilePagingViewController, didScrollToPostCustomScrollViewContainerController customScrollViewContainerController: ScrollViewContainer, atIndex index: Int)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import UIKit
|
||||
import Combine
|
||||
|
||||
protocol SettingsAppearanceTableViewCellDelegate: class {
|
||||
protocol SettingsAppearanceTableViewCellDelegate: AnyObject {
|
||||
func settingsAppearanceCell(_ cell: SettingsAppearanceTableViewCell, didSelectAppearanceMode appearanceMode: SettingsItem.AppearanceMode)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import UIKit
|
||||
import Combine
|
||||
|
||||
protocol SettingsToggleCellDelegate: class {
|
||||
protocol SettingsToggleCellDelegate: AnyObject {
|
||||
func settingsToggleCell(_ cell: SettingsToggleTableViewCell, switchValueDidChange switch: UISwitch)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import AVKit
|
||||
import UIKit
|
||||
|
||||
protocol PlayerContainerViewDelegate: class {
|
||||
protocol PlayerContainerViewDelegate: AnyObject {
|
||||
func playerContainerView(_ playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import Foundation
|
||||
import UIKit
|
||||
|
||||
protocol ContentWarningOverlayViewDelegate: class {
|
||||
protocol ContentWarningOverlayViewDelegate: AnyObject {
|
||||
func contentWarningOverlayViewDidPressed(_ contentWarningOverlayView: ContentWarningOverlayView)
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,13 @@ final class StatusView: UIView {
|
|||
return button
|
||||
}()
|
||||
|
||||
let visibilityImageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
imageView.tintColor = Asset.Colors.Label.secondary.color
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
return imageView
|
||||
}()
|
||||
|
||||
let statusContainerStackView = UIStackView()
|
||||
let statusMosaicImageViewContainer = MosaicImageViewContainer()
|
||||
|
||||
|
@ -317,6 +324,10 @@ extension StatusView {
|
|||
authorContainerStackView.addArrangedSubview(revealContentWarningButton)
|
||||
revealContentWarningButton.setContentHuggingPriority(.required - 2, for: .horizontal)
|
||||
|
||||
// visibility ImageView
|
||||
authorContainerStackView.addArrangedSubview(visibilityImageView)
|
||||
visibilityImageView.setContentHuggingPriority(.required - 2, for: .horizontal)
|
||||
|
||||
authorContainerStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
authorContainerView.addSubview(authorContainerStackView)
|
||||
NSLayoutConstraint.activate([
|
||||
|
@ -479,6 +490,11 @@ extension StatusView {
|
|||
// TODO: a11y
|
||||
}
|
||||
|
||||
func updateVisibility(visibility: String) {
|
||||
guard let visibility = ComposeToolbarView.VisibilitySelectionType(rawValue: visibility) else { return }
|
||||
visibilityImageView.image = UIImage(systemName: visibility.imageNameForTimeline(), withConfiguration: UIImage.SymbolConfiguration(pointSize: 13, weight: .regular))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension StatusView {
|
||||
|
|
|
@ -9,7 +9,7 @@ import os.log
|
|||
import UIKit
|
||||
import Combine
|
||||
|
||||
protocol ThreadReplyLoaderTableViewCellDelegate: class {
|
||||
protocol ThreadReplyLoaderTableViewCellDelegate: AnyObject {
|
||||
func threadReplyLoaderTableViewCell(_ cell: ThreadReplyLoaderTableViewCell, loadMoreButtonDidPressed button: UIButton)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import CoreData
|
|||
import os.log
|
||||
import UIKit
|
||||
|
||||
protocol TimelineMiddleLoaderTableViewCellDelegate: class {
|
||||
protocol TimelineMiddleLoaderTableViewCellDelegate: AnyObject {
|
||||
func configure(cell: TimelineMiddleLoaderTableViewCell, upperTimelineStatusID: String?, timelineIndexobjectID:NSManagedObjectID?)
|
||||
func timelineMiddleLoaderTableViewCell(_ cell: TimelineMiddleLoaderTableViewCell, loadMoreButtonDidPressed button: UIButton)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
protocol DeleteBackwardResponseTextFieldDelegate: class {
|
||||
protocol DeleteBackwardResponseTextFieldDelegate: AnyObject {
|
||||
func deleteBackwardResponseTextField(_ textField: DeleteBackwardResponseTextField, textBeforeDelete: String?)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import os.log
|
||||
import UIKit
|
||||
|
||||
protocol ActionToolbarContainerDelegate: class {
|
||||
protocol ActionToolbarContainerDelegate: AnyObject {
|
||||
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, replayButtonDidPressed sender: UIButton)
|
||||
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, reblogButtonDidPressed sender: UIButton)
|
||||
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, starButtonDidPressed sender: UIButton)
|
||||
|
|
|
@ -81,16 +81,28 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
transitionItem.imageView = transitionImageView
|
||||
transitionContext.containerView.addSubview(transitionImageView)
|
||||
|
||||
toVC.closeButtonBackground.alpha = 0
|
||||
|
||||
if UIAccessibility.isReduceTransparencyEnabled {
|
||||
toVC.visualEffectView.alpha = 0
|
||||
}
|
||||
|
||||
let animator = MediaHostToMediaPreviewViewControllerAnimatedTransitioning.animator(initialVelocity: .zero)
|
||||
|
||||
animator.addAnimations {
|
||||
transitionImageView.frame = transitionTargetFrame
|
||||
toView.alpha = 1
|
||||
if UIAccessibility.isReduceTransparencyEnabled {
|
||||
toVC.visualEffectView.alpha = 1
|
||||
}
|
||||
}
|
||||
|
||||
animator.addCompletion { position in
|
||||
toVC.pagingViewConttroller.view.alpha = 1
|
||||
transitionImageView.removeFromSuperview()
|
||||
UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseInOut]) {
|
||||
toVC.closeButtonBackground.alpha = 1
|
||||
}
|
||||
transitionContext.completeTransition(position == .end)
|
||||
}
|
||||
|
||||
|
@ -121,9 +133,20 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
transitionContext.completeTransition(false)
|
||||
fatalError()
|
||||
}
|
||||
mediaPreviewImageViewController.view.insertSubview(snapshot, aboveSubview: mediaPreviewImageViewController.previewImageView)
|
||||
|
||||
snapshot.center = transitionContext.containerView.center
|
||||
let transitionMaskView = UIView(frame: transitionContext.containerView.bounds)
|
||||
transitionMaskView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
transitionContext.containerView.addSubview(transitionMaskView)
|
||||
|
||||
let maskLayer = CAShapeLayer()
|
||||
maskLayer.frame = transitionMaskView.bounds
|
||||
let maskLayerFromPath = UIBezierPath(rect: maskLayer.bounds).cgPath
|
||||
maskLayer.path = maskLayerFromPath
|
||||
transitionMaskView.layer.mask = maskLayer
|
||||
|
||||
transitionMaskView.addSubview(snapshot)
|
||||
snapshot.center = transitionMaskView.center
|
||||
fromVC.view.bringSubviewToFront(fromVC.closeButtonBackground)
|
||||
|
||||
transitionItem.imageView = imageView
|
||||
transitionItem.snapshotTransitioning = snapshot
|
||||
|
@ -136,6 +159,38 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
let animator = popInteractiveTransitionAnimator
|
||||
|
||||
self.transitionItem.snapshotRaw?.alpha = 0.0
|
||||
|
||||
var needsMaskWithAnimation = true
|
||||
let maskLayerToRect: CGRect? = {
|
||||
guard case .mosaic = transitionItem.source else { return nil }
|
||||
guard let navigationBar = toVC.navigationController?.navigationBar else { return nil }
|
||||
let navigationBarFrameInWindow = toVC.view.convert(navigationBar.frame, to: nil)
|
||||
var rect = transitionMaskView.frame
|
||||
rect.origin.y = navigationBarFrameInWindow.maxY + UIView.separatorLineHeight(of: toVC.view) // extra hairline
|
||||
|
||||
if rect.minY < snapshot.frame.minY {
|
||||
needsMaskWithAnimation = false
|
||||
}
|
||||
|
||||
return rect
|
||||
}()
|
||||
let maskLayerToPath = maskLayerToRect.flatMap { UIBezierPath(rect: $0) }?.cgPath
|
||||
let maskLayerToFinalRect: CGRect? = {
|
||||
guard case .mosaic = transitionItem.source else { return nil }
|
||||
guard let tabBarController = toVC.tabBarController else { return nil }
|
||||
let tabBarFrameInWindow = toVC.view.convert(tabBarController.tabBar.frame, to: nil)
|
||||
var rect = maskLayerToRect ?? transitionMaskView.frame
|
||||
let offset = rect.maxY - tabBarFrameInWindow.minY
|
||||
guard offset > 0 else { return rect }
|
||||
rect.size.height -= offset
|
||||
return rect
|
||||
}()
|
||||
let maskLayerToFinalPath = maskLayerToFinalRect.flatMap { UIBezierPath(rect: $0) }?.cgPath
|
||||
|
||||
if !needsMaskWithAnimation, let maskLayerToPath = maskLayerToPath {
|
||||
maskLayer.path = maskLayerToPath
|
||||
}
|
||||
|
||||
animator.addAnimations {
|
||||
if let targetFrame = targetFrame {
|
||||
self.transitionItem.snapshotTransitioning?.frame = targetFrame
|
||||
|
@ -145,6 +200,12 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
self.transitionItem.sourceImageViewCornerRadius.flatMap { self.transitionItem.snapshotTransitioning?.layer.cornerRadius = $0 }
|
||||
fromVC.closeButtonBackground.alpha = 0
|
||||
fromVC.visualEffectView.effect = nil
|
||||
if let maskLayerToFinalPath = maskLayerToFinalPath {
|
||||
maskLayer.path = maskLayerToFinalPath
|
||||
}
|
||||
if UIAccessibility.isReduceTransparencyEnabled {
|
||||
fromVC.visualEffectView.alpha = 0
|
||||
}
|
||||
}
|
||||
|
||||
animator.addCompletion { position in
|
||||
|
@ -199,9 +260,21 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
transitionContext.completeTransition(false)
|
||||
return
|
||||
}
|
||||
mediaPreviewImageViewController.view.insertSubview(snapshot, aboveSubview: mediaPreviewImageViewController.previewImageView)
|
||||
|
||||
snapshot.center = transitionContext.containerView.center
|
||||
let transitionMaskView = UIView(frame: transitionContext.containerView.bounds)
|
||||
transitionMaskView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
transitionContext.containerView.addSubview(transitionMaskView)
|
||||
transitionItem.interactiveTransitionMaskView = transitionMaskView
|
||||
|
||||
let maskLayer = CAShapeLayer()
|
||||
maskLayer.frame = transitionMaskView.bounds
|
||||
maskLayer.path = UIBezierPath(rect: maskLayer.bounds).cgPath
|
||||
transitionMaskView.layer.mask = maskLayer
|
||||
transitionItem.interactiveTransitionMaskLayer = maskLayer
|
||||
|
||||
transitionMaskView.addSubview(snapshot)
|
||||
snapshot.center = transitionMaskView.center
|
||||
fromVC.view.bringSubviewToFront(fromVC.closeButtonBackground)
|
||||
|
||||
transitionItem.imageView = imageView
|
||||
transitionItem.snapshotTransitioning = snapshot
|
||||
|
@ -216,6 +289,10 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
let blurEffect = fromVC.visualEffectView.effect
|
||||
self.transitionItem.snapshotRaw?.alpha = 0.0
|
||||
|
||||
UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseInOut]) {
|
||||
fromVC.closeButtonBackground.alpha = 0
|
||||
}
|
||||
|
||||
animator.addAnimations {
|
||||
switch self.transitionItem.source {
|
||||
case .profileBanner:
|
||||
|
@ -223,9 +300,11 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
default:
|
||||
break
|
||||
}
|
||||
fromVC.closeButtonBackground.alpha = 0
|
||||
fromVC.visualEffectView.effect = nil
|
||||
self.transitionItem.sourceImageViewCornerRadius.flatMap { self.transitionItem.snapshotTransitioning?.layer.cornerRadius = $0 }
|
||||
if UIAccessibility.isReduceTransparencyEnabled {
|
||||
fromVC.visualEffectView.alpha = 0
|
||||
}
|
||||
}
|
||||
|
||||
animator.addCompletion { position in
|
||||
|
@ -239,6 +318,13 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
self.transitionItem.source.updateAppearance(position: position, index: nil)
|
||||
}
|
||||
fromVC.visualEffectView.effect = position == .end ? nil : blurEffect
|
||||
transitionMaskView.removeFromSuperview()
|
||||
UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseInOut]) {
|
||||
fromVC.closeButtonBackground.alpha = position == .end ? 0 : 1
|
||||
}
|
||||
if UIAccessibility.isReduceTransparencyEnabled {
|
||||
fromVC.visualEffectView.alpha = position == .end ? 0 : 1
|
||||
}
|
||||
transitionContext.completeTransition(position == .end)
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +402,50 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
|
|||
let velocity = convert(gestureVelocity, for: transitionItem)
|
||||
let itemAnimator = MediaHostToMediaPreviewViewControllerAnimatedTransitioning.animator(initialVelocity: velocity)
|
||||
|
||||
var maskLayerToFinalPath: CGPath?
|
||||
if toPosition == .end,
|
||||
let transitionMaskView = transitionItem.interactiveTransitionMaskView,
|
||||
let snapshot = transitionItem.snapshotTransitioning {
|
||||
let toVC = transitionItem.previewableViewController
|
||||
|
||||
var needsMaskWithAnimation = true
|
||||
let maskLayerToRect: CGRect? = {
|
||||
guard case .mosaic = transitionItem.source else { return nil }
|
||||
guard let navigationBar = toVC.navigationController?.navigationBar else { return nil }
|
||||
let navigationBarFrameInWindow = toVC.view.convert(navigationBar.frame, to: nil)
|
||||
var rect = transitionMaskView.frame
|
||||
rect.origin.y = navigationBarFrameInWindow.maxY
|
||||
|
||||
if rect.minY < snapshot.frame.minY {
|
||||
needsMaskWithAnimation = false
|
||||
}
|
||||
|
||||
return rect
|
||||
}()
|
||||
let maskLayerToPath = maskLayerToRect.flatMap { UIBezierPath(rect: $0) }?.cgPath
|
||||
|
||||
if let maskLayer = transitionItem.interactiveTransitionMaskLayer, !needsMaskWithAnimation {
|
||||
maskLayer.path = maskLayerToPath
|
||||
}
|
||||
|
||||
let maskLayerToFinalRect: CGRect? = {
|
||||
guard case .mosaic = transitionItem.source else { return nil }
|
||||
guard let tabBarController = toVC.tabBarController else { return nil }
|
||||
let tabBarFrameInWindow = toVC.view.convert(tabBarController.tabBar.frame, to: nil)
|
||||
var rect = maskLayerToRect ?? transitionMaskView.frame
|
||||
let offset = rect.maxY - tabBarFrameInWindow.minY
|
||||
guard offset > 0 else { return rect }
|
||||
rect.size.height -= offset
|
||||
return rect
|
||||
}()
|
||||
maskLayerToFinalPath = maskLayerToFinalRect.flatMap { UIBezierPath(rect: $0) }?.cgPath
|
||||
}
|
||||
|
||||
itemAnimator.addAnimations {
|
||||
if let maskLayer = self.transitionItem.interactiveTransitionMaskLayer,
|
||||
let maskLayerToFinalPath = maskLayerToFinalPath {
|
||||
maskLayer.path = maskLayerToFinalPath
|
||||
}
|
||||
if toPosition == .end {
|
||||
switch self.transitionItem.source {
|
||||
case .profileBanner where toPosition == .end:
|
||||
|
|
|
@ -12,7 +12,7 @@ import Kingfisher
|
|||
import GameplayKit
|
||||
import MastodonSDK
|
||||
|
||||
protocol MastodonAttachmentServiceDelegate: class {
|
||||
protocol MastodonAttachmentServiceDelegate: AnyObject {
|
||||
func mastodonAttachmentService(_ service: MastodonAttachmentService, uploadStateDidChange state: MastodonAttachmentService.UploadState?)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue