Merge commit '94c269ec8cfeff898aca61715c323b47126ce645'

This commit is contained in:
Ali 2022-04-05 19:06:01 +04:00
commit c462b92952
23 changed files with 282 additions and 115 deletions

View File

@ -696,7 +696,7 @@ public protocol SharedAccountContext: AnyObject {
func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>) -> Signal<ChatAvailableMessageActions, NoError>
func chatAvailableMessageActions(postbox: Postbox, accountPeerId: EnginePeer.Id, messageIds: Set<EngineMessage.Id>, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal<ChatAvailableMessageActions, NoError>
func resolveUrl(context: AccountContext, peerId: PeerId?, url: String, skipUrlAuth: Bool) -> Signal<ResolvedUrl, NoError>
func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?)
func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?)
func openAddContact(context: AccountContext, firstName: String, lastName: String, phoneNumber: String, label: String, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void)
func openAddPersonContact(context: AccountContext, peerId: PeerId, pushController: @escaping (ViewController) -> Void, present: @escaping (ViewController, Any?) -> Void)
func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void)

View File

@ -17,8 +17,55 @@ public enum AttachmentButtonType: Equatable {
case location
case contact
case poll
case app(PeerId, String, [AttachMenuBots.Bot.IconName: TelegramMediaFile])
case app(Peer, String, [AttachMenuBots.Bot.IconName: TelegramMediaFile])
case standalone
public static func ==(lhs: AttachmentButtonType, rhs: AttachmentButtonType) -> Bool {
switch lhs {
case .gallery:
if case .gallery = rhs {
return true
} else {
return false
}
case .file:
if case .file = rhs {
return true
} else {
return false
}
case .location:
if case .location = rhs {
return true
} else {
return false
}
case .contact:
if case .contact = rhs {
return true
} else {
return false
}
case .poll:
if case .poll = rhs {
return true
} else {
return false
}
case let .app(lhsPeer, lhsTitle, lhsIcons):
if case let .app(rhsPeer, rhsTitle, rhsIcons) = rhs, arePeersEqual(lhsPeer, rhsPeer), lhsTitle == rhsTitle, lhsIcons == rhsIcons {
return true
} else {
return false
}
case .standalone:
if case .standalone = rhs {
return true
} else {
return false
}
}
}
}
public protocol AttachmentContainable: ViewController {
@ -169,7 +216,7 @@ public class AttachmentController: ViewController {
if let strongSelf = self {
strongSelf.panel.updateLoadingProgress(progress)
if let layout = strongSelf.validLayout {
strongSelf.containerLayoutUpdated(layout, transition: .immediate)
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .spring))
}
}
}))
@ -319,9 +366,9 @@ public class AttachmentController: ViewController {
if let controller = self.controller {
let _ = self.switchToController(controller.initialButton)
if case let .app(botId, _, _) = controller.initialButton {
if case let .app(bot, _, _) = controller.initialButton {
if let index = controller.buttons.firstIndex(where: {
if case let .app(otherBotId, _, _) = $0, otherBotId == botId {
if case let .app(otherBot, _, _) = $0, otherBot.id == bot.id {
return true
} else {
return false

View File

@ -24,14 +24,14 @@ private let sideInset: CGFloat = 3.0
private final class IconComponent: Component {
public let account: Account
public let name: String
public let file: TelegramMediaFile?
public let fileReference: FileMediaReference?
public let animationName: String?
public let tintColor: UIColor?
public init(account: Account, name: String, file: TelegramMediaFile?, animationName: String?, tintColor: UIColor?) {
public init(account: Account, name: String, fileReference: FileMediaReference?, animationName: String?, tintColor: UIColor?) {
self.account = account
self.name = name
self.file = file
self.fileReference = fileReference
self.animationName = animationName
self.tintColor = tintColor
}
@ -43,7 +43,7 @@ private final class IconComponent: Component {
if lhs.name != rhs.name {
return false
}
if lhs.file?.fileId != rhs.file?.fileId {
if lhs.fileReference?.media != rhs.fileReference?.media {
return false
}
if lhs.animationName != rhs.animationName {
@ -72,14 +72,14 @@ private final class IconComponent: Component {
}
func update(component: IconComponent, availableSize: CGSize, transition: Transition) -> CGSize {
if self.component?.name != component.name || self.component?.file?.fileId != component.file?.fileId || self.component?.tintColor != component.tintColor {
if let file = component.file {
if self.component?.name != component.name || self.component?.fileReference?.media.fileId != component.fileReference?.media.fileId || self.component?.tintColor != component.tintColor {
if let fileReference = component.fileReference {
let previousName = self.component?.name ?? ""
if !previousName.isEmpty {
self.image = nil
}
self.disposable = (svgIconImageFile(account: component.account, fileReference: .standalone(media: file), fetched: true)
self.disposable = (svgIconImageFile(account: component.account, fileReference: fileReference, fetched: true)
|> runOn(Queue.concurrentDefaultQueue())
|> deliverOnMainQueue).start(next: { [weak self] transform in
let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: availableSize, boundingSize: availableSize, intrinsicInsets: UIEdgeInsets())
@ -169,6 +169,7 @@ private final class AttachButtonComponent: CombinedComponent {
let imageName: String
var imageFile: TelegramMediaFile?
var animationFile: TelegramMediaFile?
var botPeer: Peer?
let component = context.component
let strings = component.strings
@ -189,7 +190,8 @@ private final class AttachButtonComponent: CombinedComponent {
case .poll:
name = strings.Attachment_Poll
imageName = "Chat/Attach Menu/Poll"
case let .app(_, appName, appIcons):
case let .app(peer, appName, appIcons):
botPeer = peer
name = appName
imageName = ""
if let file = appIcons[.iOSAnimated] {
@ -232,11 +234,16 @@ private final class AttachButtonComponent: CombinedComponent {
.position(CGPoint(x: iconFrame.midX, y: iconFrame.midY))
)
} else {
var fileReference: FileMediaReference?
if let peer = botPeer.flatMap({ PeerReference($0 )}), let imageFile = imageFile {
fileReference = .attachBot(peer: peer, media: imageFile)
}
let icon = icon.update(
component: IconComponent(
account: component.context.account,
name: imageName,
file: imageFile,
fileReference: fileReference,
animationName: nil,
tintColor: tintColor
),
@ -789,11 +796,11 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
}
let type = self.buttons[i]
if case let .app(_, _, iconFiles) = type {
if case let .app(peer, _, iconFiles) = type {
for (name, file) in iconFiles {
if [.default, .iOSAnimated].contains(name) {
if self.iconDisposables[file.fileId] == nil {
self.iconDisposables[file.fileId] = freeMediaFileInteractiveFetched(account: self.context.account, fileReference: .standalone(media: file)).start()
if self.iconDisposables[file.fileId] == nil, let peer = PeerReference(peer) {
self.iconDisposables[file.fileId] = freeMediaFileInteractiveFetched(account: self.context.account, fileReference: .attachBot(peer: peer, media: file)).start()
}
}
}
@ -905,15 +912,15 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
self.scrollNode.isUserInteractionEnabled = !isSelecting
let isButtonVisible = self.mainButtonState.isVisible
var insets = layout.insets(options: [])
if let inputHeight = layout.inputHeight, inputHeight > 0.0 && isSelecting {
if let inputHeight = layout.inputHeight, inputHeight > 0.0 && (isSelecting || isButtonVisible) {
insets.bottom = inputHeight
} else if layout.intrinsicInsets.bottom > 0.0 {
insets.bottom = layout.intrinsicInsets.bottom
}
let isButtonVisible = self.mainButtonState.isVisible
if isSelecting {
self.loadTextNodeIfNeeded()
} else {
@ -944,7 +951,13 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
let containerTransition: ContainedViewLayoutTransition
let containerFrame: CGRect
if isButtonVisible {
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: bounds.height + 9.0))
let height: CGFloat
if layout.intrinsicInsets.bottom > 0.0 && (layout.inputHeight ?? 0.0).isZero {
height = bounds.height + 9.0
} else {
height = bounds.height + 9.0 + 8.0
}
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: height))
} else if isSelecting {
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: textPanelHeight + insets.bottom))
} else {

View File

@ -171,7 +171,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
openUserGeneratedUrl(context: context, peerId: nil, url: url, concealed: false, present: { c in
present(c, nil)
}, openResolved: { [weak self] resolved in
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peerId, navigation in
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peerId, navigation in
}, sendFile: nil,
sendSticker: nil,

View File

@ -214,7 +214,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
} else {
UIPasteboard.general.setData(data, forPasteboardType: dataType)
}
context.sharedContext.openResolvedUrl(.importStickers, context: context, urlContext: .generic, navigationController: arguments.getNavigationController(), openPeer: { _, _ in }, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { c, a in arguments.presentController(c, a as? ViewControllerPresentationArguments) }, dismissInput: {}, contentContext: nil)
context.sharedContext.openResolvedUrl(.importStickers, context: context, urlContext: .generic, navigationController: arguments.getNavigationController(), forceExternal: false, openPeer: { _, _ in }, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { c, a in arguments.presentController(c, a as? ViewControllerPresentationArguments) }, dismissInput: {}, contentContext: nil)
}
})
case .sendLogs:

View File

@ -1046,7 +1046,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
})]
let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: true, ignoredLanguages: translationSettings.ignoredLanguages)
let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: false, ignoredLanguages: translationSettings.ignoredLanguages)
if canTranslate {
actions.append(ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuTranslate, accessibilityLabel: strings.Conversation_ContextMenuTranslate), action: { [weak self] in
let controller = TranslateScreen(context: context, text: text, fromLanguage: language)
@ -1238,7 +1238,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
default:
strongSelf.loadProgress.set(1.0)
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), openPeer: { peerId, navigation in
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), forceExternal: false, openPeer: { peerId, navigation in
switch navigation {
case let .chat(_, subject, peekData):
if let navigationController = strongSelf.getNavigationController() {

View File

@ -692,7 +692,7 @@ private final class QrCodeScanScreenNode: ViewControllerTracingNode, UIScrollVie
guard let navigationController = self.controller?.navigationController as? NavigationController else {
return false
}
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .generic, navigationController: navigationController, openPeer: { [weak self] peerId, navigation in
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { [weak self] peerId, navigation in
guard let strongSelf = self else {
return
}

View File

@ -181,7 +181,7 @@ public func logoutOptionsController(context: AccountContext, navigationControlle
controller?.dismiss()
dismissImpl?()
context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peer, navigation in
context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peer, navigation in
}, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { controller, arguments in
pushControllerImpl?(controller)
}, dismissInput: {}, contentContext: nil)

View File

@ -897,7 +897,7 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
let _ = (cachedFaqInstantPage(context: context)
|> deliverOnMainQueue).start(next: { resolvedUrl in
context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peer, navigation in
context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peer, navigation in
}, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { controller, arguments in
present(.push, controller)
}, dismissInput: {}, contentContext: nil)

View File

@ -225,6 +225,7 @@ private enum MediaReferenceRevalidationKey: Hashable {
case wallpapers
case themes
case peerAvatars(peer: PeerReference)
case attachBot(peer: PeerReference)
}
private final class MediaReferenceRevalidationItemContext {
@ -536,6 +537,25 @@ final class MediaReferenceRevalidationContext {
}
}
}
func attachBot(postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<AttachMenuBot, RevalidateMediaReferenceError> {
return self.genericItem(key: .attachBot(peer: peer), background: background, request: { next, error in
return (_internal_getAttachMenuBot(postbox: postbox, network: network, botId: peer.id, cached: false)
|> mapError { _ -> RevalidateMediaReferenceError in
return .generic
}).start(next: { value in
next(value)
}, error: { _ in
error(.generic)
})
}) |> mapToSignal { next -> Signal<AttachMenuBot, RevalidateMediaReferenceError> in
if let next = next as? AttachMenuBot {
return .single(next)
} else {
return .fail(.generic)
}
}
}
}
struct RevalidatedMediaResource {
@ -656,6 +676,16 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
}
return .fail(.generic)
}
case let .attachBot(peer, _):
return revalidationContext.attachBot(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|> mapToSignal { attachBot -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
for (_, icon) in attachBot.icons {
if let updatedResource = findUpdatedMediaResource(media: icon, previousMedia: nil, resource: resource) {
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
}
}
return .fail(.generic)
}
case let .standalone(media):
if let file = media as? TelegramMediaFile {
for attribute in file.attributes {

View File

@ -224,6 +224,7 @@ public enum AnyMediaReference: Equatable {
case stickerPack(stickerPack: StickerPackReference, media: Media)
case savedGif(media: Media)
case avatarList(peer: PeerReference, media: Media)
case attachBot(peer: PeerReference, media: Media)
public static func ==(lhs: AnyMediaReference, rhs: AnyMediaReference) -> Bool {
switch lhs {
@ -263,6 +264,12 @@ public enum AnyMediaReference: Equatable {
} else {
return false
}
case let .attachBot(lhsPeer, lhsMedia):
if case let .attachBot(rhsPeer, rhsMedia) = rhs, lhsPeer == rhsPeer, lhsMedia.isEqual(to: rhsMedia) {
return true
} else {
return false
}
}
}
@ -280,6 +287,8 @@ public enum AnyMediaReference: Equatable {
return .savedGif
case .avatarList:
return nil
case .attachBot:
return nil
}
}
@ -309,6 +318,10 @@ public enum AnyMediaReference: Equatable {
if let media = media as? T {
return .avatarList(peer: peer, media: media)
}
case let .attachBot(peer, media):
if let media = media as? T {
return .attachBot(peer: peer, media: media)
}
}
return nil
}
@ -327,6 +340,8 @@ public enum AnyMediaReference: Equatable {
return media
case let .avatarList(_, media):
return media
case let .attachBot(_, media):
return media
}
}
@ -405,6 +420,7 @@ public enum MediaReference<T: Media> {
case stickerPack
case savedGif
case avatarList
case attachBot
}
case standalone(media: T)
@ -413,6 +429,7 @@ public enum MediaReference<T: Media> {
case stickerPack(stickerPack: StickerPackReference, media: T)
case savedGif(media: T)
case avatarList(peer: PeerReference, media: T)
case attachBot(peer: PeerReference, media: T)
public init?(decoder: PostboxDecoder) {
guard let caseIdValue = decoder.decodeOptionalInt32ForKey("_r"), let caseId = CodingCase(rawValue: caseIdValue) else {
@ -448,11 +465,17 @@ public enum MediaReference<T: Media> {
}
self = .savedGif(media: media)
case .avatarList:
let peer = decoder.decodeObjectForKey("pr", decoder: { StickerPackReference(decoder: $0) }) as! PeerReference
let peer = decoder.decodeObjectForKey("pr", decoder: { PeerReference(decoder: $0) }) as! PeerReference
guard let media = decoder.decodeObjectForKey("m") as? T else {
return nil
}
self = .avatarList(peer: peer, media: media)
case .attachBot:
let peer = decoder.decodeObjectForKey("pr", decoder: { PeerReference(decoder: $0) }) as! PeerReference
guard let media = decoder.decodeObjectForKey("m") as? T else {
return nil
}
self = .attachBot(peer: peer, media: media)
}
}
@ -480,6 +503,10 @@ public enum MediaReference<T: Media> {
encoder.encodeInt32(CodingCase.avatarList.rawValue, forKey: "_r")
encoder.encodeObject(peer, forKey: "pr")
encoder.encodeObject(media, forKey: "m")
case let .attachBot(peer, media):
encoder.encodeInt32(CodingCase.attachBot.rawValue, forKey: "_r")
encoder.encodeObject(peer, forKey: "pr")
encoder.encodeObject(media, forKey: "m")
}
}
@ -497,6 +524,8 @@ public enum MediaReference<T: Media> {
return .savedGif(media: media)
case let .avatarList(peer, media):
return .avatarList(peer: peer, media: media)
case let .attachBot(peer, media):
return .attachBot(peer: peer, media: media)
}
}
@ -518,6 +547,8 @@ public enum MediaReference<T: Media> {
return media
case let .avatarList(_, media):
return media
case let .attachBot(_, media):
return media
}
}

View File

@ -258,8 +258,14 @@ func managedSynchronizeAttachMenuBots(postbox: Postbox, network: Network, force:
|> restart
}
func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, NoError> {
return postbox.transaction { transaction -> Signal<Bool, NoError> in
public enum AddBotToAttachMenuError {
case generic
}
func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: PeerId) -> Signal<Bool, AddBotToAttachMenuError> {
return postbox.transaction { transaction -> Signal<Bool, AddBotToAttachMenuError> in
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
return .complete()
}
@ -272,21 +278,23 @@ func _internal_addBotToAttachMenu(postbox: Postbox, network: Network, botId: Pee
return false
}
}
|> `catch` { error -> Signal<Bool, NoError> in
return .single(false)
|> mapError { _ -> AddBotToAttachMenuError in
return .generic
}
|> mapToSignal { value -> Signal<Bool, NoError> in
|> mapToSignal { value -> Signal<Bool, AddBotToAttachMenuError> in
if value {
return managedSynchronizeAttachMenuBots(postbox: postbox, network: network)
|> castError(AddBotToAttachMenuError.self)
|> take(1)
|> map { _ -> Bool in
return true
}
} else {
return .single(value)
return .fail(.generic)
}
}
}
|> castError(AddBotToAttachMenuError.self)
|> switchToLatest
}
@ -346,8 +354,14 @@ public enum GetAttachMenuBotError {
case generic
}
public func _internal_getAttachMenuBot(postbox: Postbox, network: Network, botId: PeerId) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
public func _internal_getAttachMenuBot(postbox: Postbox, network: Network, botId: PeerId, cached: Bool) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
return postbox.transaction { transaction -> Signal<AttachMenuBot, GetAttachMenuBotError> in
if cached, let cachedBots = cachedAttachMenuBots(transaction: transaction)?.bots {
if let bot = cachedBots.first(where: { $0.peerId == botId }), let peer = transaction.getPeer(bot.peerId) {
return .single(AttachMenuBot(peer: peer, shortName: bot.name, icons: bot.icons))
}
}
guard let peer = transaction.getPeer(botId), let inputUser = apiInputUser(peer) else {
return .complete()
}

View File

@ -335,7 +335,7 @@ public extension TelegramEngine {
return _internal_sendWebViewData(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, botId: botId, buttonText: buttonText, data: data)
}
public func addBotToAttachMenu(botId: PeerId) -> Signal<Bool, NoError> {
public func addBotToAttachMenu(botId: PeerId) -> Signal<Bool, AddBotToAttachMenuError> {
return _internal_addBotToAttachMenu(postbox: self.account.postbox, network: self.account.network, botId: botId)
}
@ -343,8 +343,8 @@ public extension TelegramEngine {
return _internal_removeBotFromAttachMenu(postbox: self.account.postbox, network: self.account.network, botId: botId)
}
public func getAttachMenuBot(botId: PeerId) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
return _internal_getAttachMenuBot(postbox: self.account.postbox, network: self.account.network, botId: botId)
public func getAttachMenuBot(botId: PeerId, cached: Bool = false) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
return _internal_getAttachMenuBot(postbox: self.account.postbox, network: self.account.network, botId: botId, cached: cached)
}
public func attachMenuBots() -> Signal<[AttachMenuBot], NoError> {

View File

@ -2940,7 +2940,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
translationSettings = TranslationSettings.defaultSettings
}
let (_, language) = canTranslateText(context: context, text: text.string, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: true, ignoredLanguages: translationSettings.ignoredLanguages)
var showTranslateIfTopical = false
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, !(peer.addressName ?? "").isEmpty {
showTranslateIfTopical = true
}
let (_, language) = canTranslateText(context: context, text: text.string, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: showTranslateIfTopical, ignoredLanguages: translationSettings.ignoredLanguages)
let controller = TranslateScreen(context: context, text: text.string, fromLanguage: language)
controller.pushController = { [weak self] c in
@ -3361,7 +3366,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: url, queryId: nil, buttonText: buttonText, keepAliveSignal: nil, openUrl: { [weak self] url in
self?.openUrl(url, concealed: true)
self?.openUrl(url, concealed: true, forceExternal: true)
})
strongSelf.present(controller, in: .window(.root))
// controller.getNavigationController = { [weak self] in
@ -3385,7 +3390,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, openUrl: { [weak self] url in
self?.openUrl(url, concealed: true)
self?.openUrl(url, concealed: true, forceExternal: true)
}, completion: { [weak self] in
self?.chatDisplayNode.historyNode.scrollToEndOfHistory()
})
@ -10579,7 +10584,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
initialButton = .gallery
}
for bot in attachMenuBots.reversed() {
let button: AttachmentButtonType = .app(bot.peer.id, bot.shortName, bot.icons)
let button: AttachmentButtonType = .app(bot.peer, bot.shortName, bot.icons)
buttons.insert(button, at: 1)
if initialButton == nil && bot.peer.id == botId {
@ -10607,9 +10612,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: {
let _ = context.engine.messages.addBotToAttachMenu(botId: botId).start()
Queue.mainQueue().after(1.0, {
let _ = (context.engine.messages.addBotToAttachMenu(botId: botId)
|> deliverOnMainQueue).start(error: { _ in
}, completed: {
strongSelf.presentAttachmentBot(botId: botId, payload: botPayload)
})
})
@ -10884,11 +10890,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let controller = strongSelf.configurePollCreation()
completion(controller, nil)
strongSelf.controllerNavigationDisposable.set(nil)
case let .app(botId, botName, _):
case let .app(bot, botName, _):
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peer.id, botId: botId, botName: botName, url: nil, queryId: nil, buttonText: nil, keepAliveSignal: nil, replyToMessageId: replyMessageId)
let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peer.id, botId: bot.id, botName: botName, url: nil, queryId: nil, buttonText: nil, keepAliveSignal: nil, replyToMessageId: replyMessageId)
controller.openUrl = { [weak self] url in
self?.openUrl(url, concealed: true)
self?.openUrl(url, concealed: true, forceExternal: true)
}
controller.getNavigationController = { [weak self] in
return self?.effectiveNavigationController
@ -14394,11 +14400,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}))
}
private func openResolved(result: ResolvedUrl, sourceMessageId: MessageId?) {
private func openResolved(result: ResolvedUrl, sourceMessageId: MessageId?, forceExternal: Bool = false) {
guard let peerId = self.chatLocation.peerId else {
return
}
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .chat(peerId: peerId, updatedPresentationData: self.updatedPresentationData), navigationController: self.effectiveNavigationController, openPeer: { [weak self] peerId, navigation in
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .chat(peerId: peerId, updatedPresentationData: self.updatedPresentationData), navigationController: self.effectiveNavigationController, forceExternal: forceExternal, openPeer: { [weak self] peerId, navigation in
guard let strongSelf = self else {
return
}
@ -14438,8 +14444,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
default:
break
}
}, sendFile: nil,
sendSticker: { [weak self] f, sourceNode, sourceRect in
}, sendFile: nil, sendSticker: { [weak self] f, sourceNode, sourceRect in
return self?.interfaceInteraction?.sendSticker(f, true, sourceNode, sourceRect) ?? false
}, requestMessageActionUrlAuth: { [weak self] subject in
if case let .url(url) = subject {
@ -14454,7 +14459,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}, contentContext: nil)
}
private func openUrl(_ url: String, concealed: Bool, skipUrlAuth: Bool = false, skipConcealedAlert: Bool = false, message: Message? = nil) {
private func openUrl(_ url: String, concealed: Bool, forceExternal: Bool = false, skipUrlAuth: Bool = false, skipConcealedAlert: Bool = false, message: Message? = nil) {
self.commitPurposefulAction()
let _ = self.presentVoiceMessageDiscardAlert(action: {
@ -14513,7 +14518,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
openUserGeneratedUrl(context: self.context, peerId: self.peerView?.peerId, url: url, concealed: concealed, skipUrlAuth: skipUrlAuth, skipConcealedAlert: skipConcealedAlert, present: { [weak self] c in
self?.present(c, in: .window(.root))
}, openResolved: { [weak self] resolved in
self?.openResolved(result: resolved, sourceMessageId: message?.id)
self?.openResolved(result: resolved, sourceMessageId: message?.id, forceExternal: forceExternal)
})
}, performAction: true)
}

View File

@ -857,7 +857,12 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
})))
}
let (canTranslate, _) = canTranslateText(context: context, text: messageText, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: true, ignoredLanguages: translationSettings.ignoredLanguages)
var showTranslateIfTopical = false
if let peer = chatPresentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, !(peer.addressName ?? "").isEmpty {
showTranslateIfTopical = true
}
let (canTranslate, _) = canTranslateText(context: context, text: messageText, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: showTranslateIfTopical, ignoredLanguages: translationSettings.ignoredLanguages)
if canTranslate {
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuTranslate, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Translate"), color: theme.actionSheet.primaryTextColor)

View File

@ -910,7 +910,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
case let .localization(identifier):
strongSelf.presentController(LanguageLinkPreviewController(context: strongSelf.context, identifier: identifier), .window(.root), nil)
case .proxy, .confirmationCode, .cancelAccountReset, .share:
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), openPeer: { peerId, _ in
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), forceExternal: false, openPeer: { peerId, _ in
if let strongSelf = self {
strongSelf.openPeer(peerId: peerId, peer: nil)
}

View File

@ -43,7 +43,7 @@ private func defaultNavigationForPeerId(_ peerId: PeerId?, navigation: ChatContr
}
}
func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)? = nil, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) {
func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)? = nil, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) {
let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
if case let .chat(_, maybeUpdatedPresentationData) = urlContext {
updatedPresentationData = maybeUpdatedPresentationData
@ -53,7 +53,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
switch resolvedUrl {
case let .externalUrl(url):
context.sharedContext.openExternalUrl(context: context, urlContext: urlContext, url: url, forceExternal: false, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: navigationController, dismissInput: dismissInput)
context.sharedContext.openExternalUrl(context: context, urlContext: urlContext, url: url, forceExternal: forceExternal, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: navigationController, dismissInput: dismissInput)
case let .urlAuth(url):
requestMessageActionUrlAuth?(.url(url))
dismissInput()
@ -469,13 +469,6 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
present(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}))
dismissInput()
#if ENABLE_WALLET
case let .wallet(address, amount, comment):
dismissInput()
context.sharedContext.openWallet(context: context, walletContext: .send(address: address, amount: amount, comment: comment)) { c in
navigationController?.pushViewController(c)
}
#endif
case let .settings(section):
dismissInput()
switch section {
@ -570,7 +563,9 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
}
let controller = addWebAppToAttachmentController(context: context, peerName: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peerIcon: icon, completion: {
let _ = (context.engine.messages.addBotToAttachMenu(botId: peerId)
|> deliverOnMainQueue).start(completed: {
|> deliverOnMainQueue).start(error: { _ in
presentError(presentationData.strings.WebApp_AddToAttachmentUnavailableError)
}, completed: {
if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext {
let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peer.id, payload: payload), useExisting: true))
}

View File

@ -188,7 +188,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
if case let .externalUrl(value) = resolved {
context.sharedContext.applicationBindings.openUrl(value)
} else {
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, openPeer: { peerId, navigation in
context.sharedContext.openResolvedUrl(resolved, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peerId, navigation in
switch navigation {
case .info:
let _ = (context.account.postbox.loadedPeerWithId(peerId)

View File

@ -3288,7 +3288,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
guard let navigationController = self.controller?.navigationController as? NavigationController else {
return
}
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .chat(peerId: self.peerId, updatedPresentationData: self.controller?.updatedPresentationData), navigationController: navigationController, openPeer: { [weak self] peerId, navigation in
self.context.sharedContext.openResolvedUrl(result, context: self.context, urlContext: .chat(peerId: self.peerId, updatedPresentationData: self.controller?.updatedPresentationData), navigationController: navigationController, forceExternal: false, openPeer: { [weak self] peerId, navigation in
guard let strongSelf = self else {
return
}
@ -3335,7 +3335,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
let result: ResolvedUrl = external ? .externalUrl(url) : tempResolved
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.controller?.navigationController as? NavigationController, openPeer: { peerId, navigation in
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.controller?.navigationController as? NavigationController, forceExternal: false, openPeer: { peerId, navigation in
self?.openPeer(peerId: peerId, navigation: navigation)
}, sendFile: nil,
sendSticker: nil,
@ -5241,7 +5241,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
guard let controller = self.controller else {
return
}
self.context.sharedContext.openResolvedUrl(.groupBotStart(peerId: peerId, payload: "", adminRights: nil), context: self.context, urlContext: .generic, navigationController: controller.navigationController as? NavigationController, openPeer: { id, navigation in
self.context.sharedContext.openResolvedUrl(.groupBotStart(peerId: peerId, payload: "", adminRights: nil), context: self.context, urlContext: .generic, navigationController: controller.navigationController as? NavigationController, forceExternal: false, openPeer: { id, navigation in
}, sendFile: nil,
sendSticker: nil,
requestMessageActionUrlAuth: nil,
@ -5481,7 +5481,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_TextCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
})]
let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: true, ignoredLanguages: translationSettings.ignoredLanguages)
let (canTranslate, language) = canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, showTranslateIfTopical: false, ignoredLanguages: translationSettings.ignoredLanguages)
if canTranslate {
actions.append(ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuTranslate, accessibilityLabel: presentationData.strings.Conversation_ContextMenuTranslate), action: { [weak self] in
@ -6177,7 +6177,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if case let .instantView(webPage, _) = resolvedUrl, let customAnchor = anchor {
resolvedUrl = .instantView(webPage, customAnchor)
}
strongSelf.context.sharedContext.openResolvedUrl(resolvedUrl, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.controller?.navigationController as? NavigationController, openPeer: { peer, navigation in
strongSelf.context.sharedContext.openResolvedUrl(resolvedUrl, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.controller?.navigationController as? NavigationController, forceExternal: false, openPeer: { peer, navigation in
}, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { [weak self] controller, arguments in
self?.controller?.push(controller)
}, dismissInput: {}, contentContext: nil)

View File

@ -1197,8 +1197,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return resolveUrlImpl(context: context, peerId: peerId, url: url, skipUrlAuth: skipUrlAuth)
}
public func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) {
openResolvedUrlImpl(resolvedUrl, context: context, urlContext: urlContext, navigationController: navigationController, openPeer: openPeer, sendFile: sendFile, sendSticker: sendSticker, requestMessageActionUrlAuth: requestMessageActionUrlAuth, joinVoiceChat: joinVoiceChat, present: present, dismissInput: dismissInput, contentContext: contentContext)
public func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) {
openResolvedUrlImpl(resolvedUrl, context: context, urlContext: urlContext, navigationController: navigationController, forceExternal: forceExternal, openPeer: openPeer, sendFile: sendFile, sendSticker: sendSticker, requestMessageActionUrlAuth: requestMessageActionUrlAuth, joinVoiceChat: joinVoiceChat, present: present, dismissInput: dismissInput, contentContext: contentContext)
}
public func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController {

View File

@ -23,7 +23,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
}
let openResolvedPeerImpl: (PeerId?, ChatControllerInteractionNavigateToPeer) -> Void = { [weak controller] peerId, navigation in
context.sharedContext.openResolvedUrl(.peer(peerId, navigation), context: context, urlContext: .generic, navigationController: (controller?.navigationController as? NavigationController), openPeer: { (peerId, navigation) in
context.sharedContext.openResolvedUrl(.peer(peerId, navigation), context: context, urlContext: .generic, navigationController: (controller?.navigationController as? NavigationController), forceExternal: false, openPeer: { (peerId, navigation) in
switch navigation {
case let .chat(_, subject, peekData):
if let navigationController = controller?.navigationController as? NavigationController {

View File

@ -88,36 +88,33 @@ public final class WebAppController: ViewController, AttachmentContainable {
self.addSubnode(placeholderNode)
self.placeholderNode = placeholderNode
let botId = controller.botId
let _ = (self.context.engine.messages.attachMenuBots()
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] bots in
let _ = (self.context.engine.messages.getAttachMenuBot(botId: controller.botId, cached: true)
|> deliverOnMainQueue).start(next: { [weak self] bot in
guard let strongSelf = self else {
return
}
if let bot = bots.first(where: { $0.peer.id == botId }) {
var iconFile: TelegramMediaFile?
if let file = bot.icons[.iOSStatic] {
iconFile = file
} else if let file = bot.icons[.default] {
iconFile = file
}
if let iconFile = iconFile {
let _ = freeMediaFileInteractiveFetched(account: strongSelf.context.account, fileReference: .standalone(media: iconFile)).start()
strongSelf.iconDisposable = (svgIconImageFile(account: strongSelf.context.account, fileReference: .standalone(media: iconFile))
|> deliverOnMainQueue).start(next: { [weak self] transform in
if let strongSelf = self {
let imageSize = CGSize(width: 75.0, height: 75.0)
let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())
let drawingContext = transform(arguments)
if let image = drawingContext?.generateImage()?.withRenderingMode(.alwaysTemplate) {
strongSelf.placeholderIcon = image
strongSelf.updatePlaceholder()
var iconFile: TelegramMediaFile?
if let file = bot.icons[.iOSStatic] {
iconFile = file
} else if let file = bot.icons[.default] {
iconFile = file
}
if let iconFile = iconFile, let peer = PeerReference(bot.peer) {
let _ = freeMediaFileInteractiveFetched(account: strongSelf.context.account, fileReference: .attachBot(peer: peer, media: iconFile)).start()
strongSelf.iconDisposable = (svgIconImageFile(account: strongSelf.context.account, fileReference: .attachBot(peer: peer, media: iconFile))
|> deliverOnMainQueue).start(next: { [weak self] transform in
if let strongSelf = self {
let imageSize = CGSize(width: 75.0, height: 75.0)
let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())
let drawingContext = transform(arguments)
if let image = drawingContext?.generateImage()?.withRenderingMode(.alwaysTemplate) {
strongSelf.placeholderIcon = image
if let (layout, navigationBarHeight) = strongSelf.validLayout {
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
}
}
})
}
}
})
}
})
@ -185,12 +182,35 @@ public final class WebAppController: ViewController, AttachmentContainable {
self.webView?.sendEvent(name: "main_button_pressed", data: nil)
}
private func updatePlaceholder() {
guard let image = self.placeholderIcon else {
return
private func updatePlaceholder(grid: Bool, layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize {
var shapes: [ShimmerEffect.ShimmerEffectNode.Shape] = []
var placeholderSize: CGSize = CGSize()
if grid {
let spacing: CGFloat = 8.0
let cols: Int = min(4, Int(floor(layout.size.width / 118.0)))
let itemSize: CGSize = CGSize(width: cols == 4 ? 111.0 : 118.0, height: 150.0)
let rows: Int = 4
let sideInset = floorToScreenPixels((layout.size.width - layout.safeInsets.left - layout.safeInsets.right - itemSize.width * CGFloat(cols) - spacing * CGFloat(cols - 1)) / 2.0)
for row in 0 ..< rows {
for col in 0 ..< cols {
shapes.append(.roundedRect(rect: CGRect(x: layout.safeInsets.left + sideInset + CGFloat(col) * (itemSize.width + spacing), y: navigationBarHeight + CGFloat(row) * (itemSize.height + spacing), width: itemSize.width, height: itemSize.height), cornerRadius: 10.0))
}
}
placeholderSize = layout.size
} else {
if let icon = self.placeholderIcon {
shapes = [.image(image: icon, rect: CGRect(origin: CGPoint(), size: icon.size))]
placeholderSize = icon.size
}
}
let theme = self.presentationData.theme
self.placeholderNode?.update(backgroundColor: self.backgroundColor ?? .clear, foregroundColor: theme.list.mediaPlaceholderColor, shimmeringColor: theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), shapes: [.image(image: image, rect: CGRect(origin: CGPoint(), size: image.size))], horizontal: true, size: image.size)
self.placeholderNode?.update(backgroundColor: self.backgroundColor ?? .clear, foregroundColor: theme.list.mediaPlaceholderColor, shimmeringColor: theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), shapes: shapes, horizontal: true, size: placeholderSize)
return placeholderSize
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
@ -258,22 +278,25 @@ public final class WebAppController: ViewController, AttachmentContainable {
}
if let placeholderNode = self.placeholderNode {
let iconSize = CGSize(width: 75.0, height: 75.0)
// let height: CGFloat
// if case .compact = layout.metrics.widthClass {
// height = layout.size.height - layout.additionalInsets.bottom - layout.intrinsicInsets.bottom
// } else {
// height = layout.size.height - layout.intrinsicInsets.bottom
// }
let height: CGFloat
if case .compact = layout.metrics.widthClass {
height = layout.size.height - layout.additionalInsets.bottom - layout.intrinsicInsets.bottom
} else {
height = layout.size.height - layout.intrinsicInsets.bottom
}
let placeholderFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - iconSize.width) / 2.0), y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize)
let grid = true
let placeholderSize = self.updatePlaceholder(grid: grid, layout: layout, navigationBarHeight: navigationBarHeight, transition: transition)
let placeholderY: CGFloat = 0.0 // grid ? 0.0 : floorToScreenPixels((height - placeholderSize.height) / 2.0)
let placeholderFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - placeholderSize.width) / 2.0), y: placeholderY), size: placeholderSize)
transition.updateFrame(node: placeholderNode, frame: placeholderFrame)
placeholderNode.updateAbsoluteRect(placeholderFrame, within: layout.size)
}
if let previousLayout = previousLayout, (previousLayout.inputHeight ?? 0.0).isZero, let inputHeight = layout.inputHeight, inputHeight > 44.0 {
self.controller?.requestAttachmentMenuExpansion()
Queue.mainQueue().justDispatch {
self.controller?.requestAttachmentMenuExpansion()
}
}
}

View File

@ -121,4 +121,8 @@ final class WebAppWebView: WKWebView {
@objc func handleTap() {
self.didTouchOnce = true
}
override var inputAccessoryView: UIView? {
return nil
}
}