mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Various improvements
This commit is contained in:
@@ -114,7 +114,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
private let scrollView: ScrollView
|
||||
private let backgroundView: UIView
|
||||
private var effectView: UIVisualEffectView?
|
||||
private let contentView: ComponentHostView<ChildEnvironmentType>
|
||||
private let contentView: ComponentView<ChildEnvironmentType>
|
||||
|
||||
private var isAnimatingOut: Bool = false
|
||||
private var previousIsDisplaying: Bool = false
|
||||
@@ -139,7 +139,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
self.backgroundView.layer.cornerRadius = 12.0
|
||||
self.backgroundView.layer.masksToBounds = true
|
||||
|
||||
self.contentView = ComponentHostView<ChildEnvironmentType>()
|
||||
self.contentView = ComponentView<ChildEnvironmentType>()
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
@@ -147,7 +147,6 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
|
||||
self.addSubview(self.dimView)
|
||||
self.scrollView.addSubview(self.backgroundView)
|
||||
self.scrollView.addSubview(self.contentView)
|
||||
self.addSubview(self.scrollView)
|
||||
|
||||
self.dimView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimViewTapGesture(_:))))
|
||||
@@ -251,18 +250,21 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
self.isUserInteractionEnabled = false
|
||||
self.dimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
|
||||
guard let contentView = self.contentView.view else {
|
||||
return
|
||||
}
|
||||
if let initialVelocity = initialVelocity {
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.35, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
||||
|
||||
let contentOffset = (self.scrollView.contentOffset.y + self.scrollView.contentInset.top - self.scrollView.contentSize.height) * -1.0
|
||||
let dismissalOffset = self.scrollView.contentSize.height + abs(self.contentView.frame.minY)
|
||||
let dismissalOffset = self.scrollView.contentSize.height + abs(contentView.frame.minY)
|
||||
let delta = dismissalOffset - contentOffset
|
||||
|
||||
transition.updatePosition(layer: self.scrollView.layer, position: CGPoint(x: self.scrollView.center.x, y: self.scrollView.center.y + delta), completion: { _ in
|
||||
completion()
|
||||
})
|
||||
} else {
|
||||
self.scrollView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.scrollView.contentSize.height + abs(self.contentView.frame.minY)), duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, additive: true, completion: { _ in
|
||||
self.scrollView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.scrollView.contentSize.height + abs(contentView.frame.minY)), duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, additive: true, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
}
|
||||
@@ -316,6 +318,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
containerSize = CGSize(width: availableSize.width, height: .greatestFiniteMagnitude)
|
||||
}
|
||||
|
||||
self.contentView.parentState = state
|
||||
let contentSize = self.contentView.update(
|
||||
transition: transition,
|
||||
component: component.content,
|
||||
@@ -326,21 +329,25 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
)
|
||||
|
||||
self.ignoreScrolling = true
|
||||
|
||||
if let contentView = self.contentView.view {
|
||||
if contentView.superview == nil {
|
||||
self.scrollView.addSubview(contentView)
|
||||
}
|
||||
if sheetEnvironment.isCentered {
|
||||
let y: CGFloat = floorToScreenPixels((availableSize.height - contentSize.height) / 2.0)
|
||||
transition.setFrame(view: self.contentView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - contentSize.width) / 2.0), y: -y), size: contentSize), completion: nil)
|
||||
transition.setFrame(view: contentView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - contentSize.width) / 2.0), y: -y), size: contentSize), completion: nil)
|
||||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - contentSize.width) / 2.0), y: -y), size: contentSize), completion: nil)
|
||||
if let effectView = self.effectView {
|
||||
transition.setFrame(view: effectView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - contentSize.width) / 2.0), y: -y), size: contentSize), completion: nil)
|
||||
}
|
||||
} else {
|
||||
transition.setFrame(view: self.contentView, frame: CGRect(origin: .zero, size: contentSize), completion: nil)
|
||||
transition.setFrame(view: contentView, frame: CGRect(origin: .zero, size: contentSize), completion: nil)
|
||||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: CGSize(width: contentSize.width, height: contentSize.height + 1000.0)), completion: nil)
|
||||
if let effectView = self.effectView {
|
||||
transition.setFrame(view: effectView, frame: CGRect(origin: .zero, size: CGSize(width: contentSize.width, height: contentSize.height + 1000.0)), completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil)
|
||||
|
||||
let previousContentSize = self.scrollView.contentSize
|
||||
|
||||
@@ -23,12 +23,17 @@ public func PremiumBoostScreen(
|
||||
pushController: @escaping (ViewController) -> Void,
|
||||
dismissed: @escaping () -> Void
|
||||
) {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||
|> deliverOnMainQueue).startStandalone(next: { peer in
|
||||
guard let peer, let status else {
|
||||
let _ = (context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)
|
||||
)
|
||||
|> deliverOnMainQueue).startStandalone(next: { peer, accountPeer in
|
||||
guard let peer, let accountPeer, let status else {
|
||||
return
|
||||
}
|
||||
|
||||
let isPremium = accountPeer.isPremium
|
||||
|
||||
var myBoostCount: Int32 = 0
|
||||
var availableBoosts: [MyBoostStatus.Boost] = []
|
||||
var occupiedBoosts: [MyBoostStatus.Boost] = []
|
||||
@@ -94,6 +99,19 @@ public func PremiumBoostScreen(
|
||||
})
|
||||
dismissImpl?()
|
||||
pushController(replaceController)
|
||||
} else {
|
||||
if isPremium {
|
||||
let controller = textAlertController(
|
||||
sharedContext: context.sharedContext,
|
||||
updatedPresentationData: nil,
|
||||
title: "More Boosts Needed",
|
||||
text: "To boost **\(peer.compactDisplayTitle)**, get more boosts by gifting **Telegram Premium** to a friend.",
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})
|
||||
],
|
||||
parseMarkdown: true
|
||||
)
|
||||
presentController(controller)
|
||||
} else {
|
||||
let controller = textAlertController(
|
||||
sharedContext: context.sharedContext,
|
||||
@@ -101,7 +119,7 @@ public func PremiumBoostScreen(
|
||||
title: presentationData.strings.ChannelBoost_Error_PremiumNeededTitle,
|
||||
text: presentationData.strings.ChannelBoost_Error_PremiumNeededText,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}),
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: {
|
||||
dismissImpl?()
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .channelBoost(peerId), forceDark: forceDark, dismissed: nil)
|
||||
@@ -112,6 +130,7 @@ public func PremiumBoostScreen(
|
||||
)
|
||||
presentController(controller)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dismissImpl?()
|
||||
}
|
||||
|
||||
@@ -1159,7 +1159,7 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
state.myBoostCount = myBoostCount
|
||||
boostUpdated = true
|
||||
}
|
||||
useAlternateText = myBoostCount > 0
|
||||
useAlternateText = (myBoostCount % 2) != 0
|
||||
|
||||
iconName = "Premium/Boost"
|
||||
badgeText = "\(component.count)"
|
||||
@@ -1390,7 +1390,7 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
)
|
||||
|
||||
var buttonOffset: CGFloat = 0.0
|
||||
var textOffset: CGFloat = 228.0 + topOffset
|
||||
var textOffset: CGFloat = 184.0 + topOffset
|
||||
|
||||
if case let .storiesChannelBoost(_, _, _, _, _, link, _) = component.subject {
|
||||
if let link {
|
||||
@@ -1421,8 +1421,6 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
context.add(linkButton
|
||||
.position(CGPoint(x: linkFrame.midX, y: linkFrame.midY))
|
||||
)
|
||||
} else {
|
||||
textOffset -= 26.0
|
||||
}
|
||||
}
|
||||
if isPremiumDisabled {
|
||||
@@ -1436,6 +1434,9 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
var textSize: CGSize
|
||||
if let textChild {
|
||||
textSize = textChild.size
|
||||
|
||||
textOffset += textSize.height / 2.0
|
||||
|
||||
context.add(textChild
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: textOffset))
|
||||
.appear(Transition.Appear({ _, view, transition in
|
||||
@@ -1451,8 +1452,10 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
}))
|
||||
)
|
||||
} else if let alternateTextChild {
|
||||
textOffset += 9.0
|
||||
textSize = alternateTextChild.size
|
||||
|
||||
textOffset += textSize.height / 2.0
|
||||
|
||||
context.add(alternateTextChild
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: textOffset))
|
||||
.appear(Transition.Appear({ _, view, transition in
|
||||
@@ -1559,7 +1562,7 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: buttonFrame.maxY + 50.0 + giftText.size.height / 2.0))
|
||||
)
|
||||
|
||||
additionalContentHeight += giftText.size.height + 30.0
|
||||
additionalContentHeight += giftText.size.height + 50.0
|
||||
}
|
||||
|
||||
contentSize = CGSize(width: context.availableSize.width, height: buttonFrame.maxY + additionalContentHeight + 5.0 + environment.safeInsets.bottom)
|
||||
|
||||
@@ -27,13 +27,15 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||
let context: AccountContext
|
||||
let peerId: EnginePeer.Id
|
||||
let myBoostStatus: MyBoostStatus
|
||||
let initiallySelectedSlot: Int32?
|
||||
let selectedSlotsUpdated: ([Int32]) -> Void
|
||||
let presentController: (ViewController) -> Void
|
||||
|
||||
init(context: AccountContext, peerId: EnginePeer.Id, myBoostStatus: MyBoostStatus, selectedSlotsUpdated: @escaping ([Int32]) -> Void, presentController: @escaping (ViewController) -> Void) {
|
||||
init(context: AccountContext, peerId: EnginePeer.Id, myBoostStatus: MyBoostStatus, initiallySelectedSlot: Int32?, selectedSlotsUpdated: @escaping ([Int32]) -> Void, presentController: @escaping (ViewController) -> Void) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.myBoostStatus = myBoostStatus
|
||||
self.initiallySelectedSlot = initiallySelectedSlot
|
||||
self.selectedSlotsUpdated = selectedSlotsUpdated
|
||||
self.presentController = presentController
|
||||
}
|
||||
@@ -62,13 +64,17 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||
|
||||
var cachedCloseImage: (UIImage, PresentationTheme)?
|
||||
|
||||
init(context: AccountContext, peerId: EnginePeer.Id) {
|
||||
init(context: AccountContext, peerId: EnginePeer.Id, initiallySelectedSlot: Int32?) {
|
||||
self.context = context
|
||||
|
||||
self.currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
|
||||
super.init()
|
||||
|
||||
if let initiallySelectedSlot {
|
||||
self.selectedSlots.append(initiallySelectedSlot)
|
||||
}
|
||||
|
||||
self.disposable.set((context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] peer in
|
||||
guard let self else {
|
||||
@@ -94,7 +100,7 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||
}
|
||||
|
||||
func makeState() -> State {
|
||||
return State(context: self.context, peerId: self.peerId)
|
||||
return State(context: self.context, peerId: self.peerId, initiallySelectedSlot: self.initiallySelectedSlot)
|
||||
}
|
||||
|
||||
static var body: Body {
|
||||
@@ -180,6 +186,8 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||
.position(CGPoint(x: availableSize.width / 2.0, y: 172.0))
|
||||
)
|
||||
|
||||
let hasSelection = occupiedBoosts.count > 1
|
||||
|
||||
let selectedSlotsUpdated = context.component.selectedSlotsUpdated
|
||||
let presentController = context.component.presentController
|
||||
for i in 0 ..< occupiedBoosts.count {
|
||||
@@ -193,11 +201,11 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||
if let cooldownUntil = boost.cooldownUntil, cooldownUntil > state.currentTime {
|
||||
let duration = cooldownUntil - state.currentTime
|
||||
let durationValue = stringForDuration(duration, position: nil)
|
||||
subtitle = "available in \(durationValue)"
|
||||
subtitle = "Available in \(durationValue)"
|
||||
isEnabled = false
|
||||
} else {
|
||||
let expiresValue = stringForDate(timestamp: boost.expires, strings: strings)
|
||||
subtitle = "boost expires on \(expiresValue)"
|
||||
subtitle = "Boost expires on \(expiresValue)"
|
||||
}
|
||||
|
||||
let accountContext = context.component.context
|
||||
@@ -216,12 +224,12 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||
subtitle: subtitle,
|
||||
subtitleAccessory: .none,
|
||||
presence: nil,
|
||||
selectionState: .editing(isSelected: state.selectedSlots.contains(boost.slot), isTinted: false),
|
||||
selectionState: hasSelection ? .editing(isSelected: state.selectedSlots.contains(boost.slot), isTinted: false) : .none,
|
||||
selectionPosition: .right,
|
||||
isEnabled: isEnabled,
|
||||
hasNext: i != occupiedBoosts.count - 1,
|
||||
action: { [weak state] _ in
|
||||
guard let state else {
|
||||
guard let state, hasSelection else {
|
||||
return
|
||||
}
|
||||
if isEnabled {
|
||||
@@ -433,6 +441,35 @@ public class ReplaceBoostScreen: ViewController {
|
||||
effectiveExpanded = true
|
||||
}
|
||||
|
||||
let environment = ViewControllerComponentContainer.Environment(
|
||||
statusBarHeight: 0.0,
|
||||
navigationHeight: navigationHeight,
|
||||
safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right),
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
isVisible: self.currentIsVisible,
|
||||
theme: self.presentationData.theme,
|
||||
strings: self.presentationData.strings,
|
||||
dateTimeFormat: self.presentationData.dateTimeFormat,
|
||||
controller: { [weak self] in
|
||||
return self?.controller
|
||||
}
|
||||
)
|
||||
let contentSize = self.hostView.update(
|
||||
transition: transition,
|
||||
component: self.component,
|
||||
environment: {
|
||||
environment
|
||||
},
|
||||
forceUpdate: true,
|
||||
containerSize: CGSize(width: layout.size.width, height: 10000.0)
|
||||
)
|
||||
// contentSize.height = max(layout.size.height - navigationHeight, contentSize.height)
|
||||
transition.setFrame(view: self.hostView, frame: CGRect(origin: CGPoint(), size: contentSize), completion: nil)
|
||||
|
||||
self.scrollView.contentSize = contentSize
|
||||
|
||||
let isLandscape = layout.orientation == .landscape
|
||||
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
|
||||
let topInset: CGFloat
|
||||
@@ -500,35 +537,6 @@ public class ReplaceBoostScreen: ViewController {
|
||||
transition.setFrame(view: self.containerView, frame: clipFrame)
|
||||
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: clipFrame.size), completion: nil)
|
||||
|
||||
let environment = ViewControllerComponentContainer.Environment(
|
||||
statusBarHeight: 0.0,
|
||||
navigationHeight: navigationHeight,
|
||||
safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right),
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
isVisible: self.currentIsVisible,
|
||||
theme: self.presentationData.theme,
|
||||
strings: self.presentationData.strings,
|
||||
dateTimeFormat: self.presentationData.dateTimeFormat,
|
||||
controller: { [weak self] in
|
||||
return self?.controller
|
||||
}
|
||||
)
|
||||
var contentSize = self.hostView.update(
|
||||
transition: transition,
|
||||
component: self.component,
|
||||
environment: {
|
||||
environment
|
||||
},
|
||||
forceUpdate: true,
|
||||
containerSize: CGSize(width: clipFrame.size.width, height: 10000.0)
|
||||
)
|
||||
contentSize.height = max(layout.size.height - navigationHeight, contentSize.height)
|
||||
transition.setFrame(view: self.hostView, frame: CGRect(origin: CGPoint(), size: contentSize), completion: nil)
|
||||
|
||||
self.scrollView.contentSize = contentSize
|
||||
|
||||
let footerInsets = UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right)
|
||||
|
||||
transition.setFrame(view: self.footerView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topInset), size: layout.size))
|
||||
@@ -564,7 +572,11 @@ public class ReplaceBoostScreen: ViewController {
|
||||
if layout.size.width <= 320.0 {
|
||||
factor = 0.15
|
||||
}
|
||||
if self.scrollView.contentSize.height > 0.0 && self.scrollView.contentSize.height < layout.size.height / 2.0 {
|
||||
return layout.size.height - self.scrollView.contentSize.height - layout.intrinsicInsets.bottom - 154.0
|
||||
} else {
|
||||
return floor(max(layout.size.width, layout.size.height) * factor)
|
||||
}
|
||||
} else {
|
||||
return 210.0
|
||||
}
|
||||
@@ -590,7 +602,7 @@ public class ReplaceBoostScreen: ViewController {
|
||||
}
|
||||
|
||||
let isLandscape = layout.orientation == .landscape
|
||||
let edgeTopInset = isLandscape ? 0.0 : defaultTopInset
|
||||
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
|
||||
|
||||
switch recognizer.state {
|
||||
case .began:
|
||||
@@ -783,15 +795,23 @@ public class ReplaceBoostScreen: ViewController {
|
||||
public convenience init(context: AccountContext, peerId: EnginePeer.Id, myBoostStatus: MyBoostStatus, replaceBoosts: @escaping ([Int32]) -> Void) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var initiallySelectedSlot: Int32?
|
||||
let occupiedBoosts = myBoostStatus.boosts.filter { $0.peer?.id != peerId && $0.peer != nil }.sorted { lhs, rhs in
|
||||
return lhs.date < rhs.date
|
||||
}
|
||||
if occupiedBoosts.count == 1, let boost = occupiedBoosts.first {
|
||||
initiallySelectedSlot = boost.slot
|
||||
}
|
||||
|
||||
var selectedSlotsUpdatedImpl: (([Int32]) -> Void)?
|
||||
var presentControllerImpl: ((ViewController) -> Void)?
|
||||
self.init(context: context, component: ReplaceBoostScreenComponent(context: context, peerId: peerId, myBoostStatus: myBoostStatus, selectedSlotsUpdated: { slots in
|
||||
self.init(context: context, component: ReplaceBoostScreenComponent(context: context, peerId: peerId, myBoostStatus: myBoostStatus, initiallySelectedSlot: initiallySelectedSlot, selectedSlotsUpdated: { slots in
|
||||
selectedSlotsUpdatedImpl?(slots)
|
||||
}, presentController: { c in
|
||||
presentControllerImpl?(c)
|
||||
}))
|
||||
|
||||
self.title = "Reassign Boost"
|
||||
self.title = "Reassign Boosts"
|
||||
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Close, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||
|
||||
@@ -806,6 +826,10 @@ public class ReplaceBoostScreen: ViewController {
|
||||
}
|
||||
|
||||
self.replaceBoosts = replaceBoosts
|
||||
|
||||
if let initiallySelectedSlot {
|
||||
self.node.selectedSlots = [initiallySelectedSlot]
|
||||
}
|
||||
}
|
||||
|
||||
private init<C: Component>(context: AccountContext, component: C, theme: PresentationTheme? = nil) where C.EnvironmentType == ViewControllerComponentContainer.Environment {
|
||||
@@ -989,6 +1013,9 @@ private final class FooterView: UIView {
|
||||
self.addSubview(view)
|
||||
}
|
||||
view.frame = CGRect(origin: CGPoint(x: insets.left + buttonInset, y: panelFrame.minY + inset), size: buttonSize)
|
||||
|
||||
buttonTransition.setAlpha(view: view, alpha: count > 0 ? 1.0 : 0.3)
|
||||
view.isUserInteractionEnabled = count > 0
|
||||
}
|
||||
|
||||
self.backgroundNode.frame = panelFrame
|
||||
|
||||
@@ -978,13 +978,28 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
}
|
||||
case "web_app_read_text_from_clipboard":
|
||||
if let json = json, let requestId = json["req_id"] as? String {
|
||||
let botId = controller.botId
|
||||
let isAttachMenu = controller.url == nil
|
||||
|
||||
let _ = (self.context.engine.messages.attachMenuBots()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] attachMenuBots in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let currentTimestamp = CACurrentMediaTime()
|
||||
var fillData = false
|
||||
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0, self.controller?.url == nil {
|
||||
|
||||
let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) })
|
||||
if isAttachMenu || attachMenuBot != nil {
|
||||
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0 {
|
||||
self.webView?.lastTouchTimestamp = nil
|
||||
fillData = true
|
||||
}
|
||||
}
|
||||
|
||||
self.sendClipboardTextEvent(requestId: requestId, fillData: fillData)
|
||||
})
|
||||
}
|
||||
case "web_app_request_write_access":
|
||||
self.requestWriteAccess()
|
||||
@@ -1499,16 +1514,6 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
|
||||
let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) })
|
||||
|
||||
// if url == nil {
|
||||
// if forceHasSettings {
|
||||
// hasSettings = true
|
||||
// } else {
|
||||
// hasSettings = attachMenuBot?.flags.contains(.hasSettings) == true
|
||||
// }
|
||||
// } else {
|
||||
// hasSettings = forceHasSettings
|
||||
// }
|
||||
|
||||
if hasSettings {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_Settings, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Settings"), color: theme.contextMenu.primaryColor)
|
||||
|
||||
Reference in New Issue
Block a user