mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Merge commit 'bc1598bb926aee4267a278857463f8ce8ac1dec9'
This commit is contained in:
commit
24260d3652
@ -102,7 +102,7 @@ final class CameraDeviceContext {
|
|||||||
return 30.0
|
return 30.0
|
||||||
}
|
}
|
||||||
switch DeviceModel.current {
|
switch DeviceModel.current {
|
||||||
case .iPhone15ProMax, .iPhone14ProMax, .iPhone13ProMax, .iPhone16ProMax:
|
case .iPhone15ProMax, .iPhone14ProMax, .iPhone13ProMax, .iPhone16ProMax, .iPhone17Pro, .iPhone17ProMax:
|
||||||
return 60.0
|
return 60.0
|
||||||
default:
|
default:
|
||||||
return 30.0
|
return 30.0
|
||||||
|
|||||||
@ -132,7 +132,6 @@ final class ComposePollScreenComponent: Component {
|
|||||||
private var reactionSelectionControl: ComponentView<Empty>?
|
private var reactionSelectionControl: ComponentView<Empty>?
|
||||||
|
|
||||||
private var isUpdating: Bool = false
|
private var isUpdating: Bool = false
|
||||||
private var ignoreScrolling: Bool = false
|
|
||||||
private var previousHadInputHeight: Bool = false
|
private var previousHadInputHeight: Bool = false
|
||||||
|
|
||||||
private var component: ComposePollScreenComponent?
|
private var component: ComposePollScreenComponent?
|
||||||
@ -467,21 +466,6 @@ final class ComposePollScreenComponent: Component {
|
|||||||
self.endEditing(true)
|
self.endEditing(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
||||||
if !self.ignoreScrolling {
|
|
||||||
self.updateScrolling(transition: .immediate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateScrolling(transition: ComponentTransition) {
|
|
||||||
let navigationAlphaDistance: CGFloat = 16.0
|
|
||||||
let navigationAlpha: CGFloat = max(0.0, min(1.0, self.scrollView.contentOffset.y / navigationAlphaDistance))
|
|
||||||
if let controller = self.environment?.controller(), let navigationBar = controller.navigationBar {
|
|
||||||
transition.setAlpha(layer: navigationBar.backgroundNode.layer, alpha: navigationAlpha)
|
|
||||||
transition.setAlpha(layer: navigationBar.stripeNode.layer, alpha: navigationAlpha)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isPanGestureEnabled() -> Bool {
|
func isPanGestureEnabled() -> Bool {
|
||||||
if self.inputMediaNode != nil {
|
if self.inputMediaNode != nil {
|
||||||
return false
|
return false
|
||||||
@ -1627,7 +1611,6 @@ final class ComposePollScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
self.previousHadInputHeight = (inputHeight > 0.0)
|
self.previousHadInputHeight = (inputHeight > 0.0)
|
||||||
|
|
||||||
self.ignoreScrolling = true
|
|
||||||
let previousBounds = self.scrollView.bounds
|
let previousBounds = self.scrollView.bounds
|
||||||
let contentSize = CGSize(width: availableSize.width, height: contentHeight)
|
let contentSize = CGSize(width: availableSize.width, height: contentHeight)
|
||||||
if self.scrollView.frame != CGRect(origin: CGPoint(), size: availableSize) {
|
if self.scrollView.frame != CGRect(origin: CGPoint(), size: availableSize) {
|
||||||
@ -1762,9 +1745,6 @@ final class ComposePollScreenComponent: Component {
|
|||||||
transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: offsetY), to: CGPoint(), additive: true)
|
transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: offsetY), to: CGPoint(), additive: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.ignoreScrolling = false
|
|
||||||
|
|
||||||
self.updateScrolling(transition: transition)
|
|
||||||
|
|
||||||
if isEditing {
|
if isEditing {
|
||||||
if let controller = environment.controller() as? ComposePollScreen {
|
if let controller = environment.controller() as? ComposePollScreen {
|
||||||
|
|||||||
@ -23,7 +23,9 @@ open class SwitchNode: ASDisplayNode {
|
|||||||
public var frameColor = UIColor(rgb: 0xe0e0e0) {
|
public var frameColor = UIColor(rgb: 0xe0e0e0) {
|
||||||
didSet {
|
didSet {
|
||||||
if self.isNodeLoaded {
|
if self.isNodeLoaded {
|
||||||
(self.view as! UISwitch).tintColor = self.frameColor
|
if oldValue != self.frameColor {
|
||||||
|
(self.view as! UISwitch).tintColor = self.frameColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +39,9 @@ open class SwitchNode: ASDisplayNode {
|
|||||||
public var contentColor = UIColor(rgb: 0x42d451) {
|
public var contentColor = UIColor(rgb: 0x42d451) {
|
||||||
didSet {
|
didSet {
|
||||||
if self.isNodeLoaded {
|
if self.isNodeLoaded {
|
||||||
(self.view as! UISwitch).onTintColor = self.contentColor
|
if oldValue != self.contentColor {
|
||||||
|
(self.view as! UISwitch).onTintColor = self.contentColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -129,8 +129,17 @@ final class VideoAdComponent: Component {
|
|||||||
self.imageNode.setSignal(signal)
|
self.imageNode.setSignal(signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let color = UIColor(rgb: 0x64d2ff)
|
||||||
|
if self.adIcon == nil {
|
||||||
|
self.adIcon = generateAdIcon(color: color, strings: component.strings)
|
||||||
|
}
|
||||||
|
|
||||||
let leftInset: CGFloat = media != nil ? 51.0 : 16.0
|
let leftInset: CGFloat = media != nil ? 51.0 : 16.0
|
||||||
let rightInset: CGFloat = 60.0
|
let rightInset: CGFloat = 60.0
|
||||||
|
var titleRightInset: CGFloat = 0.0
|
||||||
|
if let adIcon = self.adIcon {
|
||||||
|
titleRightInset += adIcon.size.width + 16.0
|
||||||
|
}
|
||||||
|
|
||||||
let titleSize = self.title.update(
|
let titleSize = self.title.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
@ -138,7 +147,7 @@ final class VideoAdComponent: Component {
|
|||||||
MultilineTextComponent(text: .plain(NSAttributedString(string: titleString, font: Font.semibold(14.0), textColor: .white)))
|
MultilineTextComponent(text: .plain(NSAttributedString(string: titleString, font: Font.semibold(14.0), textColor: .white)))
|
||||||
),
|
),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - leftInset - rightInset, height: availableSize.height)
|
containerSize: CGSize(width: availableSize.width - leftInset - rightInset - titleRightInset, height: availableSize.height)
|
||||||
)
|
)
|
||||||
|
|
||||||
let textColor = UIColor.white
|
let textColor = UIColor.white
|
||||||
@ -193,12 +202,7 @@ final class VideoAdComponent: Component {
|
|||||||
}
|
}
|
||||||
textView.frame = textFrame
|
textView.frame = textFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
let color = UIColor(rgb: 0x64d2ff)
|
|
||||||
if self.adIcon == nil {
|
|
||||||
self.adIcon = generateAdIcon(color: color, strings: component.strings)
|
|
||||||
}
|
|
||||||
|
|
||||||
let buttonSize = self.button.update(
|
let buttonSize = self.button.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
|
|||||||
@ -85,7 +85,6 @@ final class ComposeTodoScreenComponent: Component {
|
|||||||
private let doneButton = ComponentView<Empty>()
|
private let doneButton = ComponentView<Empty>()
|
||||||
|
|
||||||
private var isUpdating: Bool = false
|
private var isUpdating: Bool = false
|
||||||
private var ignoreScrolling: Bool = false
|
|
||||||
private var previousHadInputHeight: Bool = false
|
private var previousHadInputHeight: Bool = false
|
||||||
|
|
||||||
private var component: ComposeTodoScreenComponent?
|
private var component: ComposeTodoScreenComponent?
|
||||||
@ -381,25 +380,10 @@ final class ComposeTodoScreenComponent: Component {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
||||||
if !self.ignoreScrolling {
|
|
||||||
self.updateScrolling(transition: .immediate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||||
self.endEditing(true)
|
self.endEditing(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateScrolling(transition: ComponentTransition) {
|
|
||||||
let navigationAlphaDistance: CGFloat = 16.0
|
|
||||||
let navigationAlpha: CGFloat = max(0.0, min(1.0, self.scrollView.contentOffset.y / navigationAlphaDistance))
|
|
||||||
if let controller = self.environment?.controller(), let navigationBar = controller.navigationBar {
|
|
||||||
transition.setAlpha(layer: navigationBar.backgroundNode.layer, alpha: navigationAlpha)
|
|
||||||
transition.setAlpha(layer: navigationBar.stripeNode.layer, alpha: navigationAlpha)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isPanGestureEnabled() -> Bool {
|
func isPanGestureEnabled() -> Bool {
|
||||||
if self.inputMediaNode != nil {
|
if self.inputMediaNode != nil {
|
||||||
return false
|
return false
|
||||||
@ -1511,7 +1495,6 @@ final class ComposeTodoScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
self.previousHadInputHeight = (inputHeight > 0.0)
|
self.previousHadInputHeight = (inputHeight > 0.0)
|
||||||
|
|
||||||
self.ignoreScrolling = true
|
|
||||||
let previousBounds = self.scrollView.bounds
|
let previousBounds = self.scrollView.bounds
|
||||||
let contentSize = CGSize(width: availableSize.width, height: contentHeight)
|
let contentSize = CGSize(width: availableSize.width, height: contentHeight)
|
||||||
if self.scrollView.frame != CGRect(origin: CGPoint(), size: availableSize) {
|
if self.scrollView.frame != CGRect(origin: CGPoint(), size: availableSize) {
|
||||||
@ -1548,9 +1531,6 @@ final class ComposeTodoScreenComponent: Component {
|
|||||||
transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: offsetY), to: CGPoint(), additive: true)
|
transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: offsetY), to: CGPoint(), additive: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.ignoreScrolling = false
|
|
||||||
|
|
||||||
self.updateScrolling(transition: transition)
|
|
||||||
|
|
||||||
if isEditing {
|
if isEditing {
|
||||||
if let controller = environment.controller() as? ComposeTodoScreen {
|
if let controller = environment.controller() as? ComposeTodoScreen {
|
||||||
@ -1662,14 +1642,6 @@ final class ComposeTodoScreenComponent: Component {
|
|||||||
self.addSubview(doneButtonView)
|
self.addSubview(doneButtonView)
|
||||||
}
|
}
|
||||||
transition.setFrame(view: doneButtonView, frame: doneButtonFrame)
|
transition.setFrame(view: doneButtonView, frame: doneButtonFrame)
|
||||||
|
|
||||||
if isValid {
|
|
||||||
doneButtonView.layer.filters = []
|
|
||||||
} else {
|
|
||||||
if (doneButtonView.layer.filters ?? []).isEmpty, let monochrome = CALayer.monochrome() {
|
|
||||||
doneButtonView.layer.filters = [monochrome]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let currentEditingTag = self.currentEditingTag, previousEditingTag !== currentEditingTag, self.currentInputMode != .keyboard {
|
if let currentEditingTag = self.currentEditingTag, previousEditingTag !== currentEditingTag, self.currentInputMode != .keyboard {
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
#include <metal_stdlib>
|
|
||||||
#include "EditorCommon.h"
|
|
||||||
#include "EditorUtils.h"
|
|
||||||
|
|
||||||
using namespace metal;
|
|
||||||
|
|
||||||
kernel void morphologyMaximumFilter(texture2d<float, access::sample> inputTexture [[texture(0)]],
|
|
||||||
texture2d<float, access::write> outputTexture [[texture(1)]],
|
|
||||||
constant float& radius [[buffer(0)]],
|
|
||||||
uint2 gid [[thread_position_in_grid]]) {
|
|
||||||
uint2 size = uint2(inputTexture.get_width(), inputTexture.get_height());
|
|
||||||
uint2 pos = gid;
|
|
||||||
|
|
||||||
float maxIntensity = 0.0;
|
|
||||||
int kernelRadius = int(radius);
|
|
||||||
|
|
||||||
for (int y = -kernelRadius; y <= kernelRadius; ++y) {
|
|
||||||
for (int x = -kernelRadius; x <= kernelRadius; ++x) {
|
|
||||||
uint2 samplePos = pos + uint2(x, y);
|
|
||||||
|
|
||||||
if (samplePos.x >= 0 && samplePos.y >= 0 && samplePos.x < size.x && samplePos.y < size.y) {
|
|
||||||
float intensity = inputTexture.read(samplePos).a;
|
|
||||||
if (intensity > maxIntensity) {
|
|
||||||
maxIntensity = intensity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outputTexture.write(maxIntensity, gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment half4 stickerOutlineFragmentShader(RasterizerData in [[stage_in]],
|
|
||||||
texture2d<half, access::sample> sourceTexture [[texture(0)]],
|
|
||||||
texture2d<half, access::sample> maskTexture [[texture(1)]]
|
|
||||||
)
|
|
||||||
{
|
|
||||||
constexpr sampler colorSampler(min_filter::linear, mag_filter::linear, address::clamp_to_zero);
|
|
||||||
constexpr sampler maskSampler(min_filter::linear, mag_filter::linear, address::clamp_to_zero);
|
|
||||||
|
|
||||||
half4 color = sourceTexture.sample(colorSampler, in.texCoord);
|
|
||||||
half intensity = maskTexture.sample(maskSampler, in.texCoord).r;
|
|
||||||
|
|
||||||
half4 result = half4(intensity, intensity, intensity, max(color.a, intensity));
|
|
||||||
result.r = mix(result.r, color.r, color.a);
|
|
||||||
result.g = mix(result.g, color.g, color.a);
|
|
||||||
result.b = mix(result.b, color.b, color.a);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@ -85,6 +85,7 @@ public final class SearchInputPanelComponent: Component {
|
|||||||
|
|
||||||
public final class View: UIView, UITextFieldDelegate {
|
public final class View: UIView, UITextFieldDelegate {
|
||||||
private let edgeEffectView: EdgeEffectView
|
private let edgeEffectView: EdgeEffectView
|
||||||
|
private let containerView: GlassBackgroundContainerView
|
||||||
private let backgroundView: GlassBackgroundView
|
private let backgroundView: GlassBackgroundView
|
||||||
|
|
||||||
private let icon = ComponentView<Empty>()
|
private let icon = ComponentView<Empty>()
|
||||||
@ -106,13 +107,15 @@ public final class SearchInputPanelComponent: Component {
|
|||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
self.edgeEffectView = EdgeEffectView()
|
self.edgeEffectView = EdgeEffectView()
|
||||||
|
|
||||||
|
self.containerView = GlassBackgroundContainerView()
|
||||||
self.backgroundView = GlassBackgroundView()
|
self.backgroundView = GlassBackgroundView()
|
||||||
self.textField = TextField()
|
self.textField = TextField()
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.addSubview(self.edgeEffectView)
|
self.addSubview(self.edgeEffectView)
|
||||||
self.addSubview(self.backgroundView)
|
self.addSubview(self.containerView)
|
||||||
|
self.containerView.contentView.addSubview(self.backgroundView)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@ -196,7 +199,7 @@ public final class SearchInputPanelComponent: Component {
|
|||||||
let fieldFrame = CGRect(origin: CGPoint(x: edgeInsets.left, y: edgeInsets.top), size: CGSize(width: availableSize.width - edgeInsets.left - edgeInsets.right - fieldHeight - buttonSpacing, height: fieldHeight))
|
let fieldFrame = CGRect(origin: CGPoint(x: edgeInsets.left, y: edgeInsets.top), size: CGSize(width: availableSize.width - edgeInsets.left - edgeInsets.right - fieldHeight - buttonSpacing, height: fieldHeight))
|
||||||
let cancelButtonFrame = CGRect(origin: CGPoint(x: edgeInsets.left + fieldFrame.width + buttonSpacing, y: edgeInsets.top), size: CGSize(width: fieldHeight, height: fieldHeight))
|
let cancelButtonFrame = CGRect(origin: CGPoint(x: edgeInsets.left + fieldFrame.width + buttonSpacing, y: edgeInsets.top), size: CGSize(width: fieldHeight, height: fieldHeight))
|
||||||
|
|
||||||
self.backgroundView.update(size: fieldFrame.size, cornerRadius: fieldFrame.height * 0.5, isDark: component.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: backgroundColor), transition: transition)
|
self.backgroundView.update(size: fieldFrame.size, cornerRadius: fieldFrame.height * 0.5, isDark: component.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: backgroundColor), isInteractive: true, transition: transition)
|
||||||
transition.setFrame(view: self.backgroundView, frame: fieldFrame)
|
transition.setFrame(view: self.backgroundView, frame: fieldFrame)
|
||||||
|
|
||||||
let fieldSideInset: CGFloat = 41.0
|
let fieldSideInset: CGFloat = 41.0
|
||||||
@ -299,7 +302,7 @@ public final class SearchInputPanelComponent: Component {
|
|||||||
)
|
)
|
||||||
if let cancelButtonView = self.cancelButton.view {
|
if let cancelButtonView = self.cancelButton.view {
|
||||||
if cancelButtonView.superview == nil {
|
if cancelButtonView.superview == nil {
|
||||||
self.addSubview(cancelButtonView)
|
self.containerView.contentView.addSubview(cancelButtonView)
|
||||||
}
|
}
|
||||||
transition.setFrame(view: cancelButtonView, frame: cancelButtonFrame)
|
transition.setFrame(view: cancelButtonView, frame: cancelButtonFrame)
|
||||||
}
|
}
|
||||||
@ -312,6 +315,9 @@ public final class SearchInputPanelComponent: Component {
|
|||||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - edgeEffectHeight + 30.0), size: CGSize(width: size.width, height: edgeEffectHeight))
|
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - edgeEffectHeight + 30.0), size: CGSize(width: size.width, height: edgeEffectHeight))
|
||||||
transition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
|
transition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
|
||||||
self.edgeEffectView.update(content: edgeColor, blur: true, rect: edgeEffectFrame, edge: .bottom, edgeSize: edgeEffectFrame.height, transition: transition)
|
self.edgeEffectView.update(content: edgeColor, blur: true, rect: edgeEffectFrame, edge: .bottom, edgeSize: edgeEffectFrame.height, transition: transition)
|
||||||
|
|
||||||
|
transition.setFrame(view: self.containerView, frame: CGRect(origin: .zero, size: size))
|
||||||
|
self.containerView.update(size: size, isDark: component.theme.overallDarkAppearance, transition: transition)
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,16 @@ func openWebAppImpl(
|
|||||||
presentationData = context.sharedContext.currentPresentationData.with({ $0 })
|
presentationData = context.sharedContext.currentPresentationData.with({ $0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var skipTermsOfService = skipTermsOfService
|
||||||
|
if let whiteListedBots = context.currentAppConfiguration.with({ $0 }).data?["whitelisted_bots"] as? [Double] {
|
||||||
|
let botId = botPeer.id.id._internalGetInt64Value()
|
||||||
|
for bot in whiteListedBots {
|
||||||
|
if Int64(bot) == botId {
|
||||||
|
skipTermsOfService = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let botName: String
|
let botName: String
|
||||||
let botAddress: String
|
let botAddress: String
|
||||||
let botVerified: Bool
|
let botVerified: Bool
|
||||||
@ -529,6 +539,16 @@ public extension ChatControllerImpl {
|
|||||||
} else {
|
} else {
|
||||||
peerId = botPeer.id
|
peerId = botPeer.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var skipTermsOfService = false
|
||||||
|
if let whiteListedBots = context.currentAppConfiguration.with({ $0 }).data?["whitelisted_bots"] as? [Double] {
|
||||||
|
let botId = botPeer.id.id._internalGetInt64Value()
|
||||||
|
for bot in whiteListedBots {
|
||||||
|
if Int64(bot) == botId {
|
||||||
|
skipTermsOfService = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chatController?.attachmentController?.dismiss(animated: true, completion: nil)
|
chatController?.attachmentController?.dismiss(animated: true, completion: nil)
|
||||||
|
|
||||||
@ -657,17 +677,21 @@ public extension ChatControllerImpl {
|
|||||||
openBotApp(false, false, appSettings)
|
openBotApp(false, false, appSettings)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: updatedPresentationData, peer: botPeer, requestWriteAccess: botApp.flags.contains(.notActivated) && botApp.flags.contains(.requiresWriteAccess), completion: { allowWrite in
|
if skipTermsOfService {
|
||||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
openBotApp(true, false, appSettings)
|
||||||
openBotApp(allowWrite, false, appSettings)
|
} else {
|
||||||
}, showMore: chatController == nil ? nil : { [weak chatController] in
|
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: updatedPresentationData, peer: botPeer, requestWriteAccess: botApp.flags.contains(.notActivated) && botApp.flags.contains(.requiresWriteAccess), completion: { allowWrite in
|
||||||
if let chatController {
|
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||||
chatController.openResolved(result: .peer(botPeer._asPeer(), .info(nil)), sourceMessageId: nil)
|
openBotApp(allowWrite, false, appSettings)
|
||||||
}
|
}, showMore: chatController == nil ? nil : { [weak chatController] in
|
||||||
}, openTerms: {
|
if let chatController {
|
||||||
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: presentationData.strings.WebApp_LaunchTermsConfirmation_URL, forceExternal: false, presentationData: presentationData, navigationController: parentController?.navigationController as? NavigationController, dismissInput: {})
|
chatController.openResolved(result: .peer(botPeer._asPeer(), .info(nil)), sourceMessageId: nil)
|
||||||
})
|
}
|
||||||
parentController?.present(controller, in: .window(.root))
|
}, openTerms: {
|
||||||
|
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: presentationData.strings.WebApp_LaunchTermsConfirmation_URL, forceExternal: false, presentationData: presentationData, navigationController: parentController?.navigationController as? NavigationController, dismissInput: {})
|
||||||
|
})
|
||||||
|
parentController?.present(controller, in: .window(.root))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
openBotApp(false, false, appSettings)
|
openBotApp(false, false, appSettings)
|
||||||
|
|||||||
@ -1378,14 +1378,14 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
let _ = (self.context.engine.messages.attachMenuBots()
|
let _ = (self.context.engine.messages.attachMenuBots()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] attachMenuBots in
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] attachMenuBots in
|
||||||
guard let self else {
|
guard let self, let controller = self.controller else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let currentTimestamp = CACurrentMediaTime()
|
let currentTimestamp = CACurrentMediaTime()
|
||||||
var fillData = false
|
var fillData = false
|
||||||
|
|
||||||
let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) })
|
let attachMenuBot = attachMenuBots.first(where: { $0.peer.id == botId && !$0.flags.contains(.notActivated) })
|
||||||
if isAttachMenu || attachMenuBot != nil {
|
if isAttachMenu || attachMenuBot != nil || controller.isWhiteListedBot {
|
||||||
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0 {
|
if let lastTouchTimestamp = self.webView?.lastTouchTimestamp, currentTimestamp < lastTouchTimestamp + 10.0 {
|
||||||
self.webView?.lastTouchTimestamp = nil
|
self.webView?.lastTouchTimestamp = nil
|
||||||
fillData = true
|
fillData = true
|
||||||
@ -3492,6 +3492,18 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isWhiteListedBot: Bool {
|
||||||
|
if let whiteListedBots = self.context.currentAppConfiguration.with({ $0 }).data?["whitelisted_bots"] as? [Double] {
|
||||||
|
let botId = self.botId.id._internalGetInt64Value()
|
||||||
|
for bot in whiteListedBots {
|
||||||
|
if Int64(bot) == botId {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
public func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
public func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
||||||
switch self.source {
|
switch self.source {
|
||||||
case .generic, .settings:
|
case .generic, .settings:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user