mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
fc609c6c70
commit
aa46e81a49
@ -38,6 +38,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
var controllerRemoved: ((ViewController) -> Void)?
|
var controllerRemoved: ((ViewController) -> Void)?
|
||||||
|
|
||||||
var shouldCancelPanGesture: (() -> Bool)?
|
var shouldCancelPanGesture: (() -> Bool)?
|
||||||
|
var requestDismiss: (() -> Void)?
|
||||||
|
|
||||||
var updateModalProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
|
var updateModalProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
|
||||||
|
|
||||||
@ -236,6 +237,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
|
|
||||||
if !self.isExpanded, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() {
|
if !self.isExpanded, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() {
|
||||||
self.cancelPanGesture()
|
self.cancelPanGesture()
|
||||||
|
self.requestDismiss?()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,8 +286,13 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
let offset = currentTopInset + panOffset
|
let offset = currentTopInset + panOffset
|
||||||
let topInset: CGFloat = edgeTopInset
|
let topInset: CGFloat = edgeTopInset
|
||||||
|
|
||||||
|
var ignoreDismiss = false
|
||||||
|
if let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() {
|
||||||
|
ignoreDismiss = true
|
||||||
|
}
|
||||||
|
|
||||||
var dismissing = false
|
var dismissing = false
|
||||||
if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) {
|
if (bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0)) && !ignoreDismiss {
|
||||||
self.interactivelyDismissed?()
|
self.interactivelyDismissed?()
|
||||||
dismissing = true
|
dismissing = true
|
||||||
} else if self.isExpanded {
|
} else if self.isExpanded {
|
||||||
|
@ -320,11 +320,6 @@ public class AttachmentController: ViewController {
|
|||||||
self.container.shouldCancelPanGesture = { [weak self] in
|
self.container.shouldCancelPanGesture = { [weak self] in
|
||||||
if let strongSelf = self, let currentController = strongSelf.currentControllers.last {
|
if let strongSelf = self, let currentController = strongSelf.currentControllers.last {
|
||||||
if !currentController.shouldDismissImmediately() {
|
if !currentController.shouldDismissImmediately() {
|
||||||
currentController.requestDismiss { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.controller?.dismiss(animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -334,6 +329,16 @@ public class AttachmentController: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.container.requestDismiss = { [weak self] in
|
||||||
|
if let strongSelf = self, let currentController = strongSelf.currentControllers.last {
|
||||||
|
currentController.requestDismiss { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.controller?.dismiss(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.panel.selectionChanged = { [weak self] type in
|
self.panel.selectionChanged = { [weak self] type in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
return strongSelf.switchToController(type)
|
return strongSelf.switchToController(type)
|
||||||
|
@ -50,11 +50,11 @@ private func generateDiffuseTexture() -> UIImage {
|
|||||||
|
|
||||||
class GiftAvatarComponent: Component {
|
class GiftAvatarComponent: Component {
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peer: EnginePeer
|
let peer: EnginePeer?
|
||||||
let isVisible: Bool
|
let isVisible: Bool
|
||||||
let hasIdleAnimations: Bool
|
let hasIdleAnimations: Bool
|
||||||
|
|
||||||
init(context: AccountContext, peer: EnginePeer, isVisible: Bool, hasIdleAnimations: Bool) {
|
init(context: AccountContext, peer: EnginePeer?, isVisible: Bool, hasIdleAnimations: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.isVisible = isVisible
|
self.isVisible = isVisible
|
||||||
@ -62,7 +62,7 @@ class GiftAvatarComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: GiftAvatarComponent, rhs: GiftAvatarComponent) -> Bool {
|
static func ==(lhs: GiftAvatarComponent, rhs: GiftAvatarComponent) -> Bool {
|
||||||
return lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations
|
return lhs.peer == rhs.peer && lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations
|
||||||
}
|
}
|
||||||
|
|
||||||
final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView {
|
final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView {
|
||||||
@ -276,7 +276,9 @@ class GiftAvatarComponent: Component {
|
|||||||
|
|
||||||
self.hasIdleAnimations = component.hasIdleAnimations
|
self.hasIdleAnimations = component.hasIdleAnimations
|
||||||
let avatarSize = CGSize(width: 100.0, height: 100.0)
|
let avatarSize = CGSize(width: 100.0, height: 100.0)
|
||||||
self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: component.peer, size: avatarSize, font: avatarPlaceholderFont(size: 43.0), fullSize: true))
|
if let peer = component.peer {
|
||||||
|
self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: peer, size: avatarSize, font: avatarPlaceholderFont(size: 43.0), fullSize: true))
|
||||||
|
}
|
||||||
self.avatarNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - avatarSize.width) / 2.0), y: 63.0), size: avatarSize)
|
self.avatarNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - avatarSize.width) / 2.0), y: 63.0), size: avatarSize)
|
||||||
|
|
||||||
return availableSize
|
return availableSize
|
||||||
|
@ -500,14 +500,14 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment)
|
typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment)
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peer: EnginePeer
|
let peer: EnginePeer?
|
||||||
let products: [InAppPurchaseManager.Product]
|
let products: [InAppPurchaseManager.Product]?
|
||||||
let selectedProductId: String
|
let selectedProductId: String?
|
||||||
|
|
||||||
let present: (ViewController) -> Void
|
let present: (ViewController) -> Void
|
||||||
let selectProduct: (String) -> Void
|
let selectProduct: (String) -> Void
|
||||||
|
|
||||||
init(context: AccountContext, peer: EnginePeer, products: [InAppPurchaseManager.Product], selectedProductId: String, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) {
|
init(context: AccountContext, peer: EnginePeer?, products: [InAppPurchaseManager.Product]?, selectedProductId: String?, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.products = products
|
self.products = products
|
||||||
@ -583,7 +583,6 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
|
|
||||||
let textColor = theme.list.itemPrimaryTextColor
|
let textColor = theme.list.itemPrimaryTextColor
|
||||||
let subtitleColor = theme.list.itemSecondaryTextColor
|
let subtitleColor = theme.list.itemSecondaryTextColor
|
||||||
// let arrowColor = theme.list.disclosureArrowColor
|
|
||||||
|
|
||||||
let textFont = Font.regular(15.0)
|
let textFont = Font.regular(15.0)
|
||||||
let boldTextFont = Font.semibold(15.0)
|
let boldTextFont = Font.semibold(15.0)
|
||||||
@ -594,7 +593,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
let text = text.update(
|
let text = text.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .markdown(
|
text: .markdown(
|
||||||
text: strings.Premium_Gift_Description(component.peer.compactDisplayTitle).string,
|
text: strings.Premium_Gift_Description(component.peer?.compactDisplayTitle ?? "").string,
|
||||||
attributes: markdownAttributes
|
attributes: markdownAttributes
|
||||||
),
|
),
|
||||||
horizontalAlignment: .center,
|
horizontalAlignment: .center,
|
||||||
@ -620,52 +619,54 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
]
|
]
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
for product in component.products {
|
if let products = component.products {
|
||||||
let monthsCount: Int
|
for product in products {
|
||||||
let giftTitle: String
|
let monthsCount: Int
|
||||||
let discount: String
|
let giftTitle: String
|
||||||
switch product.id {
|
let discount: String
|
||||||
case "org.telegram.telegramPremium.twelveMonths":
|
switch product.id {
|
||||||
giftTitle = strings.Premium_Gift_Years(1)
|
case "org.telegram.telegramPremium.twelveMonths":
|
||||||
monthsCount = 12
|
giftTitle = strings.Premium_Gift_Years(1)
|
||||||
discount = "-15%"
|
monthsCount = 12
|
||||||
case "org.telegram.telegramPremium.sixMonths":
|
discount = "-15%"
|
||||||
giftTitle = strings.Premium_Gift_Months(6)
|
case "org.telegram.telegramPremium.sixMonths":
|
||||||
monthsCount = 6
|
giftTitle = strings.Premium_Gift_Months(6)
|
||||||
discount = "-10%"
|
monthsCount = 6
|
||||||
case "org.telegram.telegramPremium.threeMonths":
|
discount = "-10%"
|
||||||
giftTitle = strings.Premium_Gift_Months(3)
|
case "org.telegram.telegramPremium.threeMonths":
|
||||||
monthsCount = 3
|
giftTitle = strings.Premium_Gift_Months(3)
|
||||||
discount = "-7%"
|
monthsCount = 3
|
||||||
default:
|
discount = "-7%"
|
||||||
giftTitle = ""
|
default:
|
||||||
monthsCount = 1
|
giftTitle = ""
|
||||||
discount = ""
|
monthsCount = 1
|
||||||
}
|
discount = ""
|
||||||
|
}
|
||||||
items.append(ProductGroupComponent.Item(
|
|
||||||
AnyComponentWithIdentity(
|
items.append(ProductGroupComponent.Item(
|
||||||
id: product.id,
|
AnyComponentWithIdentity(
|
||||||
component: AnyComponent(
|
id: product.id,
|
||||||
GiftComponent(
|
component: AnyComponent(
|
||||||
title: giftTitle,
|
GiftComponent(
|
||||||
totalPrice: product.price,
|
title: giftTitle,
|
||||||
perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).string,
|
totalPrice: product.price,
|
||||||
discount: discount,
|
perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).string,
|
||||||
selected: product.id == component.selectedProductId,
|
discount: discount,
|
||||||
primaryTextColor: textColor,
|
selected: product.id == component.selectedProductId,
|
||||||
secondaryTextColor: subtitleColor,
|
primaryTextColor: textColor,
|
||||||
accentColor: gradientColors[i],
|
secondaryTextColor: subtitleColor,
|
||||||
checkForegroundColor: environment.theme.list.itemCheckColors.foregroundColor,
|
accentColor: gradientColors[i],
|
||||||
checkBorderColor: environment.theme.list.itemCheckColors.strokeColor
|
checkForegroundColor: environment.theme.list.itemCheckColors.foregroundColor,
|
||||||
|
checkBorderColor: environment.theme.list.itemCheckColors.strokeColor
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
),
|
action: {
|
||||||
action: {
|
component.selectProduct(product.id)
|
||||||
component.selectProduct(product.id)
|
})
|
||||||
})
|
)
|
||||||
)
|
i += 1
|
||||||
i += 1
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let section = section.update(
|
let section = section.update(
|
||||||
@ -960,45 +961,43 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
||||||
)
|
)
|
||||||
|
|
||||||
if let peer = state.peer, let products = state.products, let selectedProductId = state.selectedProductId {
|
let scrollContent = scrollContent.update(
|
||||||
let scrollContent = scrollContent.update(
|
component: ScrollComponent<EnvironmentType>(
|
||||||
component: ScrollComponent<EnvironmentType>(
|
content: AnyComponent(PremiumGiftScreenContentComponent(
|
||||||
content: AnyComponent(PremiumGiftScreenContentComponent(
|
context: context.component.context,
|
||||||
context: context.component.context,
|
peer: state.peer,
|
||||||
peer: peer,
|
products: state.products,
|
||||||
products: products,
|
selectedProductId: state.selectedProductId,
|
||||||
selectedProductId: selectedProductId,
|
present: context.component.present,
|
||||||
present: context.component.present,
|
selectProduct: { [weak state] productId in
|
||||||
selectProduct: { [weak state] productId in
|
state?.selectProduct(id: productId)
|
||||||
state?.selectProduct(id: productId)
|
|
||||||
}
|
|
||||||
)),
|
|
||||||
contentInsets: UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: bottomPanelHeight, right: 0.0),
|
|
||||||
contentOffsetUpdated: { [weak state] topContentOffset, bottomContentOffset in
|
|
||||||
state?.topContentOffset = topContentOffset
|
|
||||||
state?.bottomContentOffset = bottomContentOffset
|
|
||||||
Queue.mainQueue().justDispatch {
|
|
||||||
state?.updated(transition: .immediate)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
contentOffsetWillCommit: { targetContentOffset in
|
|
||||||
if targetContentOffset.pointee.y < 100.0 {
|
|
||||||
targetContentOffset.pointee = CGPoint(x: 0.0, y: 0.0)
|
|
||||||
} else if targetContentOffset.pointee.y < 123.0 {
|
|
||||||
targetContentOffset.pointee = CGPoint(x: 0.0, y: 123.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
),
|
)),
|
||||||
environment: { environment },
|
contentInsets: UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: bottomPanelHeight, right: 0.0),
|
||||||
availableSize: context.availableSize,
|
contentOffsetUpdated: { [weak state] topContentOffset, bottomContentOffset in
|
||||||
transition: context.transition
|
state?.topContentOffset = topContentOffset
|
||||||
)
|
state?.bottomContentOffset = bottomContentOffset
|
||||||
|
Queue.mainQueue().justDispatch {
|
||||||
context.add(scrollContent
|
state?.updated(transition: .immediate)
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
}
|
||||||
)
|
},
|
||||||
}
|
contentOffsetWillCommit: { targetContentOffset in
|
||||||
|
if targetContentOffset.pointee.y < 100.0 {
|
||||||
|
targetContentOffset.pointee = CGPoint(x: 0.0, y: 0.0)
|
||||||
|
} else if targetContentOffset.pointee.y < 123.0 {
|
||||||
|
targetContentOffset.pointee = CGPoint(x: 0.0, y: 123.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
environment: { environment },
|
||||||
|
availableSize: context.availableSize,
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add(scrollContent
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
let topPanelAlpha: CGFloat
|
let topPanelAlpha: CGFloat
|
||||||
let titleOffset: CGFloat
|
let titleOffset: CGFloat
|
||||||
let titleScale: CGFloat
|
let titleScale: CGFloat
|
||||||
@ -1019,23 +1018,21 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
titleAlpha = 1.0
|
titleAlpha = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
if let peer = context.state.peer {
|
let star = star.update(
|
||||||
let star = star.update(
|
component: GiftAvatarComponent(
|
||||||
component: GiftAvatarComponent(
|
context: context.component.context,
|
||||||
context: context.component.context,
|
peer: context.state.peer,
|
||||||
peer: peer,
|
isVisible: starIsVisible,
|
||||||
isVisible: starIsVisible,
|
hasIdleAnimations: state.hasIdleAnimations
|
||||||
hasIdleAnimations: state.hasIdleAnimations
|
),
|
||||||
),
|
availableSize: CGSize(width: min(390.0, context.availableSize.width), height: 220.0),
|
||||||
availableSize: CGSize(width: min(390.0, context.availableSize.width), height: 220.0),
|
transition: context.transition
|
||||||
transition: context.transition
|
)
|
||||||
)
|
|
||||||
|
context.add(star
|
||||||
context.add(star
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: topInset + star.size.height / 2.0 - 30.0 - titleOffset * titleScale))
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: topInset + star.size.height / 2.0 - 30.0 - titleOffset * titleScale))
|
.scale(titleScale)
|
||||||
.scale(titleScale)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.add(topPanel
|
context.add(topPanel
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0))
|
||||||
@ -1251,27 +1248,16 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer {
|
|||||||
strongSelf.view.disablesInteractiveModalDismiss = inProgress
|
strongSelf.view.disablesInteractiveModalDismiss = inProgress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// presentImpl = { [weak self] c in
|
|
||||||
// self?.present(c, in: .window(.root))
|
|
||||||
// }
|
|
||||||
|
|
||||||
pushImpl = { [weak self] c in
|
pushImpl = { [weak self] c in
|
||||||
self?.push(c)
|
self?.push(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
completionImpl = { [weak self] duration in
|
completionImpl = { [weak self] duration in
|
||||||
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
// let introController = PremiumIntroScreen(context: context, source: .gift(from: context.account.peerId, to: peerId, duration: duration))
|
|
||||||
var controllers = navigationController.viewControllers
|
var controllers = navigationController.viewControllers
|
||||||
controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) }
|
controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) }
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
|
|
||||||
Queue.mainQueue().after(2.8, {
|
|
||||||
if let topController = navigationController.viewControllers.last {
|
|
||||||
topController.view.addSubview(ConfettiView(frame: topController.view.bounds))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -650,21 +650,23 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
let doneImpl: (Bool) -> Void = { [weak self] shouldDelay in
|
let doneImpl: (Bool) -> Void = { [weak self] shouldDelay in
|
||||||
let minDelay: Double = shouldDelay ? 0.9 : 0.6
|
let minDelay: Double = shouldDelay ? 0.9 : 0.6
|
||||||
let delay: Double
|
let delay: Double
|
||||||
|
let hapticDelay: Double
|
||||||
|
|
||||||
if let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareProlongedLoadingContainerNode {
|
if let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareProlongedLoadingContainerNode {
|
||||||
delay = contentNode.completionDuration
|
delay = contentNode.completionDuration
|
||||||
|
hapticDelay = shouldDelay ? delay - 1.5 : delay
|
||||||
if shouldDelay {
|
|
||||||
Queue.mainQueue().after(delay - 1.5, {
|
|
||||||
if strongSelf.hapticFeedback == nil {
|
|
||||||
strongSelf.hapticFeedback = HapticFeedback()
|
|
||||||
}
|
|
||||||
strongSelf.hapticFeedback?.success()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
delay = max(minDelay, (timestamp + minDelay) - CACurrentMediaTime())
|
delay = max(minDelay, (timestamp + minDelay) - CACurrentMediaTime())
|
||||||
|
hapticDelay = delay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Queue.mainQueue().after(hapticDelay, {
|
||||||
|
if self?.hapticFeedback == nil {
|
||||||
|
self?.hapticFeedback = HapticFeedback()
|
||||||
|
}
|
||||||
|
self?.hapticFeedback?.success()
|
||||||
|
})
|
||||||
|
|
||||||
Queue.mainQueue().after(delay, {
|
Queue.mainQueue().after(delay, {
|
||||||
self?.animateOut(shared: true, completion: {
|
self?.animateOut(shared: true, completion: {
|
||||||
self?.dismiss?(true)
|
self?.dismiss?(true)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user