mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
6de1267a1d
commit
1e6c6d6091
@ -8930,3 +8930,5 @@ Sorry for the inconvenience.";
|
||||
"VoiceOver.Chat.NotPlayedByRecipients" = "Not played by recipients";
|
||||
|
||||
"VoiceOver.Chat.ReplyingToMessage" = "In reply to message: %@";
|
||||
|
||||
"MediaPicker.VoiceOver.Camera" = "Camera";
|
||||
|
@ -277,6 +277,7 @@ public enum ResolvedUrl {
|
||||
case inaccessiblePeer
|
||||
case botStart(peer: Peer, payload: String)
|
||||
case groupBotStart(peerId: PeerId, payload: String, adminRights: ResolvedBotAdminRights?)
|
||||
case gameStart(peerId: PeerId, game: String)
|
||||
case channelMessage(peer: Peer, messageId: MessageId, timecode: Double?)
|
||||
case replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage, messageId: MessageId)
|
||||
case replyThread(messageId: MessageId)
|
||||
|
@ -2461,7 +2461,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true)))
|
||||
|
||||
if strongSelf.backgroundColor != nil {
|
||||
strongSelf.backgroundColor = presentationData.theme.chatList.backgroundColor
|
||||
}
|
||||
strongSelf.listNode.forEachItemHeaderNode({ itemHeaderNode in
|
||||
if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode {
|
||||
itemHeaderNode.updateTheme(theme: presentationData.theme)
|
||||
|
@ -1648,6 +1648,10 @@ public final class ChatListNode: ListView {
|
||||
guard !filter.contains(.onlyPrivateChats) || peer.peerId.namespace == Namespaces.Peer.CloudUser else { return false }
|
||||
|
||||
if let peer = peer.peer {
|
||||
if peer.id.isReplies {
|
||||
return false
|
||||
}
|
||||
|
||||
switch peer {
|
||||
case let .user(user):
|
||||
if user.botInfo != nil {
|
||||
|
@ -994,15 +994,16 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
if let _ = self.presentationNode {
|
||||
self.currentPresentationStateTransition = .animateOut(result: initialResult, completion: completion)
|
||||
if let validLayout = self.validLayout {
|
||||
if case .custom = initialResult {
|
||||
if case let .custom(transition) = initialResult {
|
||||
self.delayLayoutUpdate = true
|
||||
Queue.mainQueue().after(0.05) {
|
||||
Queue.mainQueue().after(0.1) {
|
||||
self.delayLayoutUpdate = false
|
||||
self.updateLayout(
|
||||
layout: validLayout,
|
||||
transition: .animated(duration: 0.35, curve: .easeInOut),
|
||||
transition: transition,
|
||||
previousActionsContainerNode: nil
|
||||
)
|
||||
self.isAnimatingOut = true
|
||||
}
|
||||
} else {
|
||||
self.updateLayout(
|
||||
|
@ -80,3 +80,7 @@ public func isBoldTextEnabled() -> Signal<Bool, NoError> {
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
}
|
||||
|
||||
public func isReduceTransparencyEnabled() -> Bool {
|
||||
UIAccessibility.isReduceTransparencyEnabled
|
||||
}
|
||||
|
@ -544,6 +544,23 @@ public final class InviteLinkViewController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
var creatorIsBot: Signal<Bool, NoError>
|
||||
if case let .link(_, _, _, _, _, adminId, _, _, _, _, _, _) = invite {
|
||||
creatorIsBot = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: adminId))
|
||||
|> map { peer -> Bool in
|
||||
if let peer, case let .user(user) = peer, user.botInfo != nil {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
creatorIsBot = .single(false)
|
||||
}
|
||||
|
||||
let _ = (creatorIsBot
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { creatorIsBot in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
@ -611,6 +628,7 @@ public final class InviteLinkViewController: ViewController {
|
||||
})
|
||||
})))
|
||||
}
|
||||
if !creatorIsBot {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.InviteLink_ContextRevoke, textColor: .destructive, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
|
||||
}, action: { [weak self] _, f in
|
||||
@ -657,10 +675,12 @@ public final class InviteLinkViewController: ViewController {
|
||||
})
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||
self?.controller?.presentInGlobalOverlay(contextController)
|
||||
})
|
||||
})
|
||||
|
||||
let previousEntries = Atomic<[InviteLinkViewEntry]?>(value: nil)
|
||||
let previousCount = Atomic<Int32?>(value: nil)
|
||||
|
@ -15,7 +15,7 @@ public extension EnginePeer {
|
||||
} else if let _ = user.phone {
|
||||
return "" //formatPhoneNumber("+\(phone)")
|
||||
} else {
|
||||
return ""
|
||||
return "Deleted Account"
|
||||
}
|
||||
case let .legacyGroup(group):
|
||||
return group.title
|
||||
|
@ -238,28 +238,29 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
||||
}
|
||||
|
||||
let legacySheetController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil)
|
||||
let controller = TGMediaPickerSendActionSheetController(context: legacyController.context, isDark: true, sendButtonFrame: model.interfaceView.doneButtonFrame, canSendSilently: hasSilentPosting, canSchedule: effectiveHasSchedule, reminder: reminder, hasTimer: hasTimer)
|
||||
let sheetController = TGMediaPickerSendActionSheetController(context: legacyController.context, isDark: true, sendButtonFrame: model.interfaceView.doneButtonFrame, canSendSilently: hasSilentPosting, canSchedule: effectiveHasSchedule, reminder: reminder, hasTimer: hasTimer)
|
||||
let dismissImpl = { [weak model] in
|
||||
model?.dismiss(true, false)
|
||||
dismissAll()
|
||||
}
|
||||
controller.send = {
|
||||
sheetController.send = {
|
||||
completed(item.asset, false, nil, {
|
||||
dismissImpl()
|
||||
})
|
||||
}
|
||||
controller.sendSilently = {
|
||||
sheetController.sendSilently = {
|
||||
completed(item.asset, true, nil, {
|
||||
dismissImpl()
|
||||
})
|
||||
}
|
||||
controller.schedule = {
|
||||
sheetController.schedule = {
|
||||
presentSchedulePicker(true, { time in
|
||||
completed(item.asset, false, time, {
|
||||
dismissImpl()
|
||||
})
|
||||
})
|
||||
}
|
||||
controller.sendWithTimer = {
|
||||
sheetController.sendWithTimer = {
|
||||
presentTimerPicker { time in
|
||||
var items = selectionContext.selectedItems() ?? []
|
||||
items.append(item.asset as Any)
|
||||
@ -273,10 +274,10 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
||||
})
|
||||
}
|
||||
}
|
||||
controller.customDismissBlock = { [weak legacySheetController] in
|
||||
sheetController.customDismissBlock = { [weak legacySheetController] in
|
||||
legacySheetController?.dismiss()
|
||||
}
|
||||
legacySheetController.bind(controller: controller)
|
||||
legacySheetController.bind(controller: sheetController)
|
||||
present(legacySheetController, nil)
|
||||
|
||||
let hapticFeedback = HapticFeedback()
|
||||
|
@ -235,7 +235,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
self.scrollingArea = SparseItemGridScrollingArea()
|
||||
|
||||
self.cameraActivateAreaNode = AccessibilityAreaNode()
|
||||
self.cameraActivateAreaNode.accessibilityLabel = "Camera"
|
||||
self.cameraActivateAreaNode.accessibilityLabel = self.presentationData.strings.MediaPicker_VoiceOver_Camera
|
||||
self.cameraActivateAreaNode.accessibilityTraits = [.button]
|
||||
|
||||
super.init()
|
||||
|
@ -119,6 +119,10 @@ final class PasscodeEntryButtonNode: HighlightTrackingButtonNode {
|
||||
let blurredBackgroundColor = (background.inverted ? UIColor(rgb: 0xffffff, alpha: 0.1) : UIColor(rgb: 0x000000, alpha: 0.2), dateFillNeedsBlur(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper))
|
||||
let blurredBackgroundNode = NavigationBackgroundNode(color: blurredBackgroundColor.0, enableBlur: blurredBackgroundColor.1)
|
||||
self.blurredBackgroundNode = blurredBackgroundNode
|
||||
|
||||
if isReduceTransparencyEnabled() {
|
||||
blurredBackgroundNode.alpha = 0.1
|
||||
}
|
||||
}
|
||||
|
||||
self.backgroundNode = ASImageNode()
|
||||
|
@ -1100,11 +1100,11 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
|
||||
return
|
||||
}
|
||||
|
||||
if updateFlags != currentFlags {
|
||||
if let updateFlags, updateFlags != currentFlags {
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags ?? []), rank: effectiveRank) |> deliverOnMainQueue).start(error: { error in
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: effectiveRank) |> deliverOnMainQueue).start(error: { error in
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(false)
|
||||
}
|
||||
@ -1145,7 +1145,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
|
||||
}
|
||||
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
}, completed: {
|
||||
updated(TelegramChatAdminRights(rights: updateFlags ?? []))
|
||||
updated(TelegramChatAdminRights(rights: updateFlags))
|
||||
dismissImpl?()
|
||||
}))
|
||||
} else if let updateRank = updateRank, let currentFlags = currentFlags {
|
||||
|
@ -623,7 +623,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
|
||||
|
||||
let inputPanel = PresentationThemeChatInputPanel(
|
||||
panelBackgroundColor: rootNavigationBar.blurredBackgroundColor,
|
||||
panelBackgroundColorNoWallpaper: UIColor(rgb: 0x000000, alpha: 0.94),
|
||||
panelBackgroundColorNoWallpaper: UIColor(rgb: 0x000000),
|
||||
panelSeparatorColor: UIColor(rgb: 0x545458, alpha: 0.55),
|
||||
panelControlAccentColor: UIColor(rgb: 0xffffff),
|
||||
panelControlColor: UIColor(rgb: 0x808080),
|
||||
|
@ -877,7 +877,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
|
||||
|
||||
let inputPanel = PresentationThemeChatInputPanel(
|
||||
panelBackgroundColor: rootNavigationBar.blurredBackgroundColor,
|
||||
panelBackgroundColorNoWallpaper: rootNavigationBar.blurredBackgroundColor,
|
||||
panelBackgroundColorNoWallpaper: UIColor(rgb: 0xffffff),
|
||||
panelSeparatorColor: UIColor(rgb: 0xb2b2b2),
|
||||
panelControlAccentColor: defaultDayAccentColor,
|
||||
panelControlColor: UIColor(rgb: 0x858e99),
|
||||
|
@ -51,6 +51,34 @@ public func plainServiceMessageString(strings: PresentationStrings, nameDisplayO
|
||||
}
|
||||
}
|
||||
|
||||
private func peerDisplayTitles(_ peerIds: [PeerId], _ dict: SimpleDictionary<PeerId, Peer>, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) -> String {
|
||||
var peers: [Peer] = []
|
||||
for id in peerIds {
|
||||
if let peer = dict[id] {
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
return peerDisplayTitles(peers, strings: strings, nameDisplayOrder: nameDisplayOrder)
|
||||
}
|
||||
|
||||
private func peerDisplayTitles(_ peers: [Peer], strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) -> String {
|
||||
if peers.count == 0 {
|
||||
return ""
|
||||
} else {
|
||||
var string = ""
|
||||
var first = true
|
||||
for peer in peers {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string.append(", ")
|
||||
}
|
||||
string.append(EnginePeer(peer).displayTitle(strings: strings, displayOrder: nameDisplayOrder))
|
||||
}
|
||||
return string
|
||||
}
|
||||
}
|
||||
|
||||
public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool, forForumOverview: Bool) -> NSAttributedString? {
|
||||
var attributedString: NSAttributedString?
|
||||
|
||||
@ -96,9 +124,9 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
let resultTitleString: PresentationStrings.FormattedString
|
||||
if peerIds.count == 1 {
|
||||
attributePeerIds.append((1, peerIds.first))
|
||||
resultTitleString = strings.Notification_Invited(authorName, peerDebugDisplayTitles(peerIds, message.peers))
|
||||
resultTitleString = strings.Notification_Invited(authorName, peerDisplayTitles(peerIds, message.peers, strings: strings, nameDisplayOrder: nameDisplayOrder))
|
||||
} else {
|
||||
resultTitleString = strings.Notification_InvitedMultiple(authorName, peerDebugDisplayTitles(peerIds, message.peers))
|
||||
resultTitleString = strings.Notification_InvitedMultiple(authorName, peerDisplayTitles(peerIds, message.peers, strings: strings, nameDisplayOrder: nameDisplayOrder))
|
||||
}
|
||||
|
||||
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||
@ -115,7 +143,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
if peerIds.count == 1 {
|
||||
attributePeerIds.append((1, peerIds.first))
|
||||
}
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_Kicked(authorName, peerDebugDisplayTitles(peerIds, message.peers))._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_Kicked(authorName, peerDisplayTitles(peerIds, message.peers, strings: strings, nameDisplayOrder: nameDisplayOrder))._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||
}
|
||||
case let .photoUpdated(image):
|
||||
if authorName.isEmpty || isChannel {
|
||||
@ -652,10 +680,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
resultTitleString = strings.Notification_VoiceChatInvitationForYou(authorName)
|
||||
} else {
|
||||
attributePeerIds.append((1, peerIds.first))
|
||||
resultTitleString = strings.Notification_VoiceChatInvitation(authorName, peerDebugDisplayTitles(peerIds, message.peers))
|
||||
resultTitleString = strings.Notification_VoiceChatInvitation(authorName, peerDisplayTitles(peerIds, message.peers, strings: strings, nameDisplayOrder: nameDisplayOrder))
|
||||
}
|
||||
} else {
|
||||
resultTitleString = strings.Notification_VoiceChatInvitation(authorName, peerDebugDisplayTitles(peerIds, message.peers))
|
||||
resultTitleString = strings.Notification_VoiceChatInvitation(authorName, peerDisplayTitles(peerIds, message.peers, strings: strings, nameDisplayOrder: nameDisplayOrder))
|
||||
}
|
||||
|
||||
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||
|
@ -3061,6 +3061,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
strongSelf.commitPurposefulAction()
|
||||
|
||||
var isScheduledMessages = false
|
||||
if case .scheduledMessages = strongSelf.presentationInterfaceState.subject {
|
||||
isScheduledMessages = true
|
||||
}
|
||||
|
||||
guard !isScheduledMessages else {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
||||
|> deliverOnMainQueue).start(next: { message in
|
||||
guard let strongSelf = self, let message = message else {
|
||||
@ -4238,6 +4248,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if case .user = peerType {
|
||||
let _ = context.engine.peers.sendBotRequestedPeer(messageId: messageId, buttonId: buttonId, requestedPeerId: peer.id).start()
|
||||
} else {
|
||||
var isChannel = false
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
isChannel = true
|
||||
@ -4248,6 +4261,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
controller?.dismiss()
|
||||
})
|
||||
}
|
||||
}
|
||||
createNewGroupImpl = { [weak controller] in
|
||||
switch peerType {
|
||||
case .user:
|
||||
@ -14591,7 +14605,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
let replyMessageId = self.presentationInterfaceState.interfaceState.replyMessageId
|
||||
if self.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peerId, threadId: self.chatLocation.threadId, botId: results.botId, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting) {
|
||||
if self.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peerId, threadId: self.chatLocation.threadId, botId: results.botId, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime) {
|
||||
self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
@ -238,7 +238,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
|
||||
var viaBotApply: (TextNodeLayout, () -> TextNode)?
|
||||
var replyInfoApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode)?
|
||||
var updatedReplyBackgroundNode: NavigationBackgroundNode?
|
||||
|
||||
var updatedInstantVideoBackgroundImage: UIImage?
|
||||
let instantVideoBackgroundImage: UIImage?
|
||||
@ -557,6 +556,15 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
|
||||
let effectiveAudioTranscriptionState = updatedAudioTranscriptionState ?? audioTranscriptionState
|
||||
|
||||
return (result, { [weak self] layoutData, animation in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
strongSelf.videoFrame = displayVideoFrame
|
||||
strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature)
|
||||
strongSelf.secretProgressIcon = secretProgressIcon
|
||||
strongSelf.automaticDownload = automaticDownload
|
||||
|
||||
var updatedReplyBackgroundNode: NavigationBackgroundNode?
|
||||
if replyInfoApply != nil || viaBotApply != nil || forwardInfoSizeApply != nil {
|
||||
if let currentReplyBackgroundNode = currentReplyBackgroundNode {
|
||||
updatedReplyBackgroundNode = currentReplyBackgroundNode
|
||||
@ -567,14 +575,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
updatedReplyBackgroundNode?.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)
|
||||
}
|
||||
|
||||
return (result, { [weak self] layoutData, animation in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
strongSelf.videoFrame = displayVideoFrame
|
||||
strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature)
|
||||
strongSelf.secretProgressIcon = secretProgressIcon
|
||||
strongSelf.automaticDownload = automaticDownload
|
||||
|
||||
if let updatedAudioTranscriptionState = updatedAudioTranscriptionState {
|
||||
strongSelf.audioTranscriptionState = updatedAudioTranscriptionState
|
||||
strongSelf.updateTranscriptionExpanded?(strongSelf.audioTranscriptionState)
|
||||
@ -928,7 +928,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
strongSelf.addSubnode(viaBotNode)
|
||||
}
|
||||
|
||||
let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? 11.0 : (width - messageInfoSize.width - bubbleEdgeInset - 9.0 + 10.0)), y: 8.0), size: viaBotLayout.size)
|
||||
let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (displayVideoFrame.maxX - width + 6.0) : (width - messageInfoSize.width - bubbleEdgeInset - 9.0 + 10.0)), y: 8.0), size: viaBotLayout.size)
|
||||
animation.animator.updateFrame(layer: viaBotNode.layer, frame: viaBotFrame, completion: nil)
|
||||
|
||||
messageInfoSize = CGSize(width: messageInfoSize.width, height: viaBotLayout.size.height)
|
||||
@ -1226,6 +1226,30 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
||||
switch gesture {
|
||||
case .tap:
|
||||
if let viaBotNode = self.viaBotNode, viaBotNode.frame.contains(location) {
|
||||
if let item = self.item {
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? InlineBotMessageAttribute {
|
||||
var botAddressName: String?
|
||||
if let peerId = attribute.peerId, let botPeer = item.message.peers[peerId], let addressName = botPeer.addressName {
|
||||
botAddressName = addressName
|
||||
} else {
|
||||
botAddressName = attribute.title
|
||||
}
|
||||
|
||||
if let botAddressName = botAddressName {
|
||||
item.controllerInteraction.updateInputState { textInputState in
|
||||
return ChatTextInputState(inputText: NSAttributedString(string: "@" + botAddressName + " "))
|
||||
}
|
||||
item.controllerInteraction.updateInputMode { _ in
|
||||
return .text
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let replyInfoNode = self.replyInfoNode, replyInfoNode.frame.contains(location) {
|
||||
if let item = self.item {
|
||||
for attribute in item.message.attributes {
|
||||
@ -1315,6 +1339,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
return playbackNode.view
|
||||
}
|
||||
}
|
||||
if let viaBotNode = self.viaBotNode, viaBotNode.frame.contains(point), !viaBotNode.alpha.isZero {
|
||||
return self.view
|
||||
}
|
||||
if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(point), !forwardInfoNode.alpha.isZero {
|
||||
return self.view
|
||||
}
|
||||
|
@ -975,6 +975,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
break
|
||||
case .groupBotStart:
|
||||
break
|
||||
case .gameStart:
|
||||
break
|
||||
case let .channelMessage(peer, messageId, timecode):
|
||||
if let navigationController = strongSelf.getNavigationController() {
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), subject: .message(id: .id(messageId), highlight: true, timecode: timecode)))
|
||||
|
@ -379,11 +379,11 @@ private func calculateTextFieldRealInsets(presentationInterfaceState: ChatPresen
|
||||
return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: right)
|
||||
}
|
||||
|
||||
private var currentTextInputBackgroundImage: (UIColor, UIColor, CGFloat, UIImage)?
|
||||
private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackgroundColor: UIColor?, strokeColor: UIColor, diameter: CGFloat) -> UIImage? {
|
||||
private var currentTextInputBackgroundImage: (UIColor, UIColor, CGFloat, CGFloat, UIImage)?
|
||||
private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackgroundColor: UIColor?, strokeColor: UIColor, diameter: CGFloat, strokeWidth: CGFloat) -> UIImage? {
|
||||
if let backgroundColor = backgroundColor, let current = currentTextInputBackgroundImage {
|
||||
if current.0.isEqual(backgroundColor) && current.1.isEqual(strokeColor) && current.2.isEqual(to: diameter) {
|
||||
return current.3
|
||||
if current.0.isEqual(backgroundColor) && current.1.isEqual(strokeColor) && current.2.isEqual(to: diameter) && current.3.isEqual(to: strokeWidth) {
|
||||
return current.4
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,13 +401,12 @@ private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackground
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
context.setStrokeColor(strokeColor.cgColor)
|
||||
let strokeWidth: CGFloat = UIScreenPixel
|
||||
context.setLineWidth(strokeWidth)
|
||||
context.strokeEllipse(in: CGRect(x: strokeWidth / 2.0, y: strokeWidth / 2.0, width: diameter - strokeWidth, height: diameter - strokeWidth))
|
||||
})?.stretchableImage(withLeftCapWidth: Int(diameter) / 2, topCapHeight: Int(diameter) / 2)
|
||||
if let image = image {
|
||||
if let backgroundColor = backgroundColor {
|
||||
currentTextInputBackgroundImage = (backgroundColor, strokeColor, diameter, image)
|
||||
currentTextInputBackgroundImage = (backgroundColor, strokeColor, diameter, strokeWidth, image)
|
||||
}
|
||||
return image
|
||||
} else {
|
||||
@ -1290,7 +1289,6 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
|
||||
if self.theme == nil || !self.theme!.chat.inputPanel.inputTextColor.isEqual(interfaceState.theme.chat.inputPanel.inputTextColor) {
|
||||
let textColor = interfaceState.theme.chat.inputPanel.inputTextColor
|
||||
let tintColor = interfaceState.theme.list.itemAccentColor
|
||||
let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize)
|
||||
|
||||
if let textInputNode = self.textInputNode {
|
||||
@ -1302,12 +1300,17 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
textInputNode.selectedRange = range
|
||||
}
|
||||
textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(baseFontSize), NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||
textInputNode.tintColor = tintColor
|
||||
|
||||
self.updateSpoiler()
|
||||
}
|
||||
}
|
||||
|
||||
let tintColor = interfaceState.theme.list.itemAccentColor
|
||||
if let textInputNode = self.textInputNode, tintColor != textInputNode.tintColor {
|
||||
textInputNode.tintColor = tintColor
|
||||
textInputNode.tintColorDidChange()
|
||||
}
|
||||
|
||||
let keyboardAppearance = interfaceState.theme.rootController.keyboardColor.keyboardAppearance
|
||||
if let textInputNode = self.textInputNode, textInputNode.keyboardAppearance != keyboardAppearance, textInputNode.isFirstResponder() {
|
||||
if textInputNode.isCurrentlyEmoji() {
|
||||
@ -1332,15 +1335,18 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics)
|
||||
let minimalInputHeight: CGFloat = 2.0 + textFieldMinHeight
|
||||
|
||||
let strokeWidth: CGFloat
|
||||
let backgroundColor: UIColor
|
||||
if case let .color(color) = interfaceState.chatWallpaper, UIColor(rgb: color).isEqual(interfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) {
|
||||
backgroundColor = interfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper
|
||||
strokeWidth = 1.0 - UIScreenPixel
|
||||
} else {
|
||||
backgroundColor = interfaceState.theme.chat.inputPanel.panelBackgroundColor
|
||||
strokeWidth = UIScreenPixel
|
||||
}
|
||||
|
||||
self.textInputBackgroundNode.image = textInputBackgroundImage(backgroundColor: backgroundColor, inputBackgroundColor: nil, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight)
|
||||
self.transparentTextInputBackgroundImage = textInputBackgroundImage(backgroundColor: nil, inputBackgroundColor: interfaceState.theme.chat.inputPanel.inputBackgroundColor, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight)
|
||||
self.textInputBackgroundNode.image = textInputBackgroundImage(backgroundColor: backgroundColor, inputBackgroundColor: nil, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight, strokeWidth: strokeWidth)
|
||||
self.transparentTextInputBackgroundImage = textInputBackgroundImage(backgroundColor: nil, inputBackgroundColor: interfaceState.theme.chat.inputPanel.inputBackgroundColor, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight, strokeWidth: strokeWidth)
|
||||
self.textInputContainerBackgroundNode.image = generateStretchableFilledCircleImage(diameter: minimalInputHeight, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor)
|
||||
|
||||
self.searchLayoutClearImageNode.image = PresentationResourcesChat.chatInputTextFieldClearImage(interfaceState.theme)
|
||||
|
@ -162,6 +162,26 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
||||
}
|
||||
dismissInput()
|
||||
navigationController?.pushViewController(controller)
|
||||
case let .gameStart(peerId, game):
|
||||
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyManageable, .excludeDisabled, .excludeRecent, .doNotSearchMessages], hasContactSelector: false, title: presentationData.strings.Bot_AddToChat_Title, selectForumThreads: true))
|
||||
controller.peerSelected = { [weak controller] peer, _ in
|
||||
let peerId = peer.id
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String
|
||||
if let peer = peer as? TelegramUser {
|
||||
text = presentationData.strings.Target_ShareGameConfirmationPrivate(EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
} else {
|
||||
text = presentationData.strings.Target_ShareGameConfirmationGroup(EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
|
||||
let alertController = textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.RequestPeer_SelectionConfirmationSend, action: {
|
||||
controller?.dismiss()
|
||||
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
})])
|
||||
present(alertController, nil)
|
||||
}
|
||||
dismissInput()
|
||||
navigationController?.pushViewController(controller)
|
||||
case let .channelMessage(peer, messageId, timecode):
|
||||
openPeer(EnginePeer(peer), .chat(textInputState: nil, subject: .message(id: .id(messageId), highlight: true, timecode: timecode), peekData: nil))
|
||||
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||
|
@ -2495,7 +2495,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
if actions.options.contains(.deleteGlobally) {
|
||||
let globalTitle: String
|
||||
if isChannel {
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForMe
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesForEveryone
|
||||
} else if let personalPeerName = personalPeerName {
|
||||
globalTitle = strongSelf.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).string
|
||||
} else {
|
||||
|
@ -67,6 +67,7 @@ public enum ParsedInternalPeerUrlParameter {
|
||||
case botStart(String)
|
||||
case groupBotStart(String, ResolvedBotAdminRights?)
|
||||
case attachBotStart(String, String?)
|
||||
case gameStart(String)
|
||||
case channelMessage(Int32, Double?)
|
||||
case replyThread(Int32, Int32)
|
||||
case voiceChat(String?)
|
||||
@ -212,7 +213,7 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
|
||||
}
|
||||
return .peer(.name(peerName), .groupBotStart(value, botAdminRights))
|
||||
} else if queryItem.name == "game" {
|
||||
return nil
|
||||
return .peer(.name(peerName), .gameStart(value))
|
||||
} else if ["voicechat", "videochat", "livestream"].contains(queryItem.name) {
|
||||
return .peer(.name(peerName), .voiceChat(value))
|
||||
} else if queryItem.name == "startattach" {
|
||||
@ -582,6 +583,8 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .single(.botStart(peer: peer, payload: payload))
|
||||
case let .groupBotStart(payload, adminRights):
|
||||
return .single(.groupBotStart(peerId: peer.id, payload: payload, adminRights: adminRights))
|
||||
case let .gameStart(game):
|
||||
return .single(.gameStart(peerId: peer.id, game: game))
|
||||
case let .attachBotStart(name, payload):
|
||||
return context.engine.peers.resolvePeerByName(name: name)
|
||||
|> take(1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user