mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '94c269ec8cfeff898aca61715c323b47126ce645'
This commit is contained in:
commit
c462b92952
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,4 +121,8 @@ final class WebAppWebView: WKWebView {
|
||||
@objc func handleTap() {
|
||||
self.didTouchOnce = true
|
||||
}
|
||||
|
||||
override var inputAccessoryView: UIView? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user