mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
6fab49a229
commit
25624f2ce1
@ -1819,7 +1819,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
if let index = node.index {
|
if let index = node.index {
|
||||||
nodes.append(.Node(index: index, frame: node.apparentFrame, referenceNode: QueueLocalObject(queue: Queue.mainQueue(), generate: {
|
nodes.append(.Node(index: index, frame: node.apparentFrame, referenceNode: QueueLocalObject(queue: Queue.mainQueue(), generate: {
|
||||||
return node
|
return node
|
||||||
})))
|
}), newNode: nil))
|
||||||
} else {
|
} else {
|
||||||
nodes.append(.Placeholder(frame: node.apparentFrame))
|
nodes.append(.Placeholder(frame: node.apparentFrame))
|
||||||
}
|
}
|
||||||
@ -2000,10 +2000,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch state.nodes[i] {
|
switch state.nodes[i] {
|
||||||
case let .Node(_, frame, referenceNode):
|
case let .Node(_, frame, referenceNode, newNode):
|
||||||
state.nodes[i] = .Node(index: updatedIndex, frame: frame, referenceNode: referenceNode)
|
state.nodes[i] = .Node(index: updatedIndex, frame: frame, referenceNode: referenceNode, newNode: newNode)
|
||||||
case .Placeholder:
|
case .Placeholder:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
@ -2039,10 +2039,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch state.nodes[i] {
|
switch state.nodes[i] {
|
||||||
case let .Node(_, frame, referenceNode):
|
case let .Node(_, frame, referenceNode, newNode):
|
||||||
state.nodes[i] = .Node(index: updatedIndex, frame: frame, referenceNode: referenceNode)
|
state.nodes[i] = .Node(index: updatedIndex, frame: frame, referenceNode: referenceNode, newNode: newNode)
|
||||||
case .Placeholder:
|
case .Placeholder:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2097,7 +2097,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
|
|
||||||
var updateIndices = updateAdjacentItemsIndices
|
var updateIndices = updateAdjacentItemsIndices
|
||||||
if widthUpdated {
|
if widthUpdated {
|
||||||
for case let .Node(index, _, _) in updatedState.nodes {
|
for case let .Node(index, _, _, _) in updatedState.nodes {
|
||||||
updateIndices.insert(index)
|
updateIndices.insert(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2205,7 +2205,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
for node in state.nodes {
|
for node in state.nodes {
|
||||||
if case let .Node(index, _, referenceNode) = node , index == nodeIndex {
|
if case let .Node(index, _, referenceNode, _) = node, index == nodeIndex {
|
||||||
if let referenceNode = referenceNode {
|
if let referenceNode = referenceNode {
|
||||||
continueWithoutNode = false
|
continueWithoutNode = false
|
||||||
var controlledTransition: ControlledTransition?
|
var controlledTransition: ControlledTransition?
|
||||||
|
@ -332,9 +332,13 @@ struct ListViewState {
|
|||||||
case let .custom(getOverflow):
|
case let .custom(getOverflow):
|
||||||
if Thread.isMainThread, case let .Node(_, _, referenceNode, newNode) = node, let listNode = referenceNode?.syncWith({ $0 }) ?? newNode?.syncWith({ $0 }) {
|
if Thread.isMainThread, case let .Node(_, _, referenceNode, newNode) = node, let listNode = referenceNode?.syncWith({ $0 }) ?? newNode?.syncWith({ $0 }) {
|
||||||
let overflow = getOverflow(listNode)
|
let overflow = getOverflow(listNode)
|
||||||
offset = (self.visibleSize.height - self.insets.bottom) - node.frame.maxY
|
if overflow == 0.0 {
|
||||||
offset += overflow
|
offset = self.insets.top - node.frame.minY
|
||||||
offset -= floor((self.visibleSize.height - self.insets.bottom - self.insets.top) * 0.5)
|
} else {
|
||||||
|
offset = (self.visibleSize.height - self.insets.bottom) - node.frame.maxY
|
||||||
|
offset += overflow
|
||||||
|
offset -= floor((self.visibleSize.height - self.insets.bottom - self.insets.top) * 0.5)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
offset = self.insets.top - node.frame.minY
|
offset = self.insets.top - node.frame.minY
|
||||||
}
|
}
|
||||||
|
@ -804,7 +804,7 @@ public func chatMessagePhotoInternal(photoData: Signal<Tuple4<Data?, Data?, Chat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func chatMessagePhotoThumbnailDatas(account: Account, userLocation: MediaResourceUserLocation, photoReference: ImageMediaReference, onlyFullSize: Bool = false, forceThumbnail: Bool = false) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
private func chatMessagePhotoThumbnailDatas(account: Account, userLocation: MediaResourceUserLocation, photoReference: ImageMediaReference, onlyFullSize: Bool = false, forceThumbnail: Bool = false) -> Signal<Tuple3<(Data, Bool)?, Data?, Bool>, NoError> {
|
||||||
let fullRepresentationSize: CGSize = CGSize(width: 1280.0, height: 1280.0)
|
let fullRepresentationSize: CGSize = CGSize(width: 1280.0, height: 1280.0)
|
||||||
if let smallestRepresentation = smallestImageRepresentation(photoReference.media.representations), let largestRepresentation = photoReference.media.representationForDisplayAtSize(PixelDimensions(width: Int32(fullRepresentationSize.width), height: Int32(fullRepresentationSize.height))) {
|
if let smallestRepresentation = smallestImageRepresentation(photoReference.media.representations), let largestRepresentation = photoReference.media.representationForDisplayAtSize(PixelDimensions(width: Int32(fullRepresentationSize.width), height: Int32(fullRepresentationSize.height))) {
|
||||||
|
|
||||||
@ -813,17 +813,23 @@ private func chatMessagePhotoThumbnailDatas(account: Account, userLocation: Medi
|
|||||||
|
|
||||||
let signal = maybeFullSize
|
let signal = maybeFullSize
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> mapToSignal { maybeData -> Signal<Tuple3<Data?, Data?, Bool>, NoError> in
|
|> mapToSignal { maybeData -> Signal<Tuple3<(Data, Bool)?, Data?, Bool>, NoError> in
|
||||||
if maybeData.complete, !forceThumbnail {
|
if maybeData.complete, !forceThumbnail {
|
||||||
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
||||||
return .single(Tuple(nil, loadedData, true))
|
return .single(Tuple(nil, loadedData, true))
|
||||||
} else {
|
} else {
|
||||||
let fetchedThumbnail = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: userLocation, userContentType: .image, reference: photoReference.resourceReference(smallestRepresentation.resource), statsCategory: .image)
|
let fetchedThumbnail = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: userLocation, userContentType: .image, reference: photoReference.resourceReference(smallestRepresentation.resource), statsCategory: .image)
|
||||||
|
|
||||||
let thumbnail = Signal<Data?, NoError> { subscriber in
|
let thumbnail = Signal<(Data, Bool)?, NoError> { subscriber in
|
||||||
let fetchedDisposable = fetchedThumbnail.start()
|
let fetchedDisposable = fetchedThumbnail.start()
|
||||||
let thumbnailDisposable = account.postbox.mediaBox.resourceData(smallestRepresentation.resource).start(next: { next in
|
let thumbnailDisposable = account.postbox.mediaBox.resourceData(smallestRepresentation.resource).start(next: { next in
|
||||||
subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []))
|
if next.size == 0 {
|
||||||
|
subscriber.putNext(nil)
|
||||||
|
} else if let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []) {
|
||||||
|
subscriber.putNext((data, false))
|
||||||
|
} else {
|
||||||
|
subscriber.putNext(nil)
|
||||||
|
}
|
||||||
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
|
|
||||||
return ActionDisposable {
|
return ActionDisposable {
|
||||||
@ -858,7 +864,8 @@ public func chatMessagePhotoThumbnail(account: Account, userLocation: MediaResou
|
|||||||
let signal = chatMessagePhotoThumbnailDatas(account: account, userLocation: userLocation, photoReference: photoReference, onlyFullSize: onlyFullSize, forceThumbnail: blurred)
|
let signal = chatMessagePhotoThumbnailDatas(account: account, userLocation: userLocation, photoReference: photoReference, onlyFullSize: onlyFullSize, forceThumbnail: blurred)
|
||||||
return signal
|
return signal
|
||||||
|> map { value in
|
|> map { value in
|
||||||
let thumbnailData = value._0
|
let thumbnailData: Data? = value._0?.0
|
||||||
|
let thumbnailIsBlurred: Bool = value._0?.1 ?? false
|
||||||
let fullSizeData = value._1
|
let fullSizeData = value._1
|
||||||
let fullSizeComplete = value._2
|
let fullSizeComplete = value._2
|
||||||
return { arguments in
|
return { arguments in
|
||||||
@ -905,23 +912,27 @@ public func chatMessagePhotoThumbnail(account: Account, userLocation: MediaResou
|
|||||||
thumbnailImage = image
|
thumbnailImage = image
|
||||||
}
|
}
|
||||||
|
|
||||||
var blurredThumbnailImage: UIImage?
|
var blurredThumbnailImage: CGImage?
|
||||||
if let thumbnailImage = thumbnailImage {
|
if let thumbnailImage = thumbnailImage {
|
||||||
let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height)
|
if thumbnailIsBlurred {
|
||||||
let thumbnailContextSize = thumbnailSize.aspectFitted(blurred ? CGSize(width: 50.0, height: 50.0) : CGSize(width: 150.0, height: 150.0))
|
let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height)
|
||||||
if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) {
|
let thumbnailContextSize = thumbnailSize.aspectFitted(blurred ? CGSize(width: 50.0, height: 50.0) : CGSize(width: 150.0, height: 150.0))
|
||||||
thumbnailContext.withFlippedContext { c in
|
if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) {
|
||||||
c.interpolationQuality = .none
|
thumbnailContext.withFlippedContext { c in
|
||||||
c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
c.interpolationQuality = .none
|
||||||
}
|
c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize))
|
||||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
}
|
||||||
|
|
||||||
if blurred {
|
|
||||||
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||||
adjustSaturationInContext(context: thumbnailContext, saturation: 1.7)
|
|
||||||
|
if blurred {
|
||||||
|
imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes)
|
||||||
|
adjustSaturationInContext(context: thumbnailContext, saturation: 1.7)
|
||||||
|
}
|
||||||
|
|
||||||
|
blurredThumbnailImage = thumbnailContext.generateImage()?.cgImage
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
blurredThumbnailImage = thumbnailContext.generateImage()
|
blurredThumbnailImage = thumbnailImage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -933,9 +944,9 @@ public func chatMessagePhotoThumbnail(account: Account, userLocation: MediaResou
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.setBlendMode(.copy)
|
c.setBlendMode(.copy)
|
||||||
if let blurredThumbnailImage = blurredThumbnailImage, let cgImage = blurredThumbnailImage.cgImage {
|
if let blurredThumbnailImage {
|
||||||
c.interpolationQuality = .low
|
c.interpolationQuality = .low
|
||||||
drawImage(context: c, image: cgImage, orientation: imageOrientation, in: fittedRect)
|
drawImage(context: c, image: blurredThumbnailImage, orientation: imageOrientation, in: fittedRect)
|
||||||
c.setBlendMode(.normal)
|
c.setBlendMode(.normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,7 +359,7 @@ public func trimStringWithEntities(string: String, entities: [MessageTextEntity]
|
|||||||
}
|
}
|
||||||
|
|
||||||
while range.upperBound > range.lowerBound {
|
while range.upperBound > range.lowerBound {
|
||||||
let c = nsString.character(at: range.lowerBound)
|
let c = nsString.character(at: range.upperBound - 1)
|
||||||
if c == 0x0a || c == 0x20 {
|
if c == 0x0a || c == 0x20 {
|
||||||
range = range.lowerBound ..< (range.upperBound - 1)
|
range = range.lowerBound ..< (range.upperBound - 1)
|
||||||
} else {
|
} else {
|
||||||
|
@ -240,7 +240,7 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
var titleText: [CompositeTextNode.Component] = []
|
var titleText: [CompositeTextNode.Component] = []
|
||||||
if let peer = message?.peers[strongSelf.messageId.peerId] as? TelegramChannel, case .broadcast = peer.info {
|
if let peer = message?.peers[strongSelf.messageId.peerId] as? TelegramChannel, case .broadcast = peer.info {
|
||||||
let icon: UIImage?
|
let icon: UIImage?
|
||||||
icon = UIImage(bundleImageName: "Chat/Input/Accessory Panels/PanelTextChannelIcon")?.withRenderingMode(.alwaysTemplate)
|
icon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/PanelTextChannelIcon"), color: theme.chat.inputPanel.panelControlAccentColor)
|
||||||
|
|
||||||
if let icon {
|
if let icon {
|
||||||
let rawString: PresentationStrings.FormattedString
|
let rawString: PresentationStrings.FormattedString
|
||||||
@ -279,9 +279,9 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
if let peer = message?.peers[strongSelf.messageId.peerId], (peer is TelegramChannel || peer is TelegramGroup) {
|
if let peer = message?.peers[strongSelf.messageId.peerId], (peer is TelegramChannel || peer is TelegramGroup) {
|
||||||
let icon: UIImage?
|
let icon: UIImage?
|
||||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||||
icon = UIImage(bundleImageName: "Chat/Input/Accessory Panels/PanelTextChannelIcon")?.withRenderingMode(.alwaysTemplate)
|
icon = UIImage(bundleImageName: "Chat/Input/Accessory Panels/PanelTextChannelIcon")
|
||||||
} else {
|
} else {
|
||||||
icon = UIImage(bundleImageName: "Chat/Input/Accessory Panels/PanelTextGroupIcon")?.withRenderingMode(.alwaysTemplate)
|
icon = UIImage(bundleImageName: "Chat/Input/Accessory Panels/PanelTextGroupIcon")
|
||||||
}
|
}
|
||||||
if let iconImage = generateTintedImage(image: icon, color: strongSelf.theme.chat.inputPanel.panelControlAccentColor) {
|
if let iconImage = generateTintedImage(image: icon, color: strongSelf.theme.chat.inputPanel.panelControlAccentColor) {
|
||||||
titleText.append(.icon(iconImage))
|
titleText.append(.icon(iconImage))
|
||||||
|
@ -273,6 +273,41 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let applyCurrentQuoteSelection: () -> Void = { [weak selfController, weak chatController] in
|
||||||
|
guard let selfController, let chatController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var messageItemNode: ChatMessageItemView?
|
||||||
|
chatController.chatDisplayNode.historyNode.enumerateItemNodes { itemNode in
|
||||||
|
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item, item.message.id == replySubject.messageId {
|
||||||
|
messageItemNode = itemNode
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var targetContentNode: ChatMessageTextBubbleContentNode?
|
||||||
|
if let messageItemNode = messageItemNode as? ChatMessageBubbleItemNode {
|
||||||
|
for contentNode in messageItemNode.contentNodes {
|
||||||
|
if let contentNode = contentNode as? ChatMessageTextBubbleContentNode {
|
||||||
|
targetContentNode = contentNode
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guard let contentNode = targetContentNode else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let textSelection = contentNode.getCurrentTextSelection() else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var quote: EngineMessageReplyQuote?
|
||||||
|
let trimmedText = trimStringWithEntities(string: textSelection.text, entities: textSelection.entities, maxLength: quoteMaxLength(appConfig: selfController.context.currentAppConfiguration.with({ $0 })))
|
||||||
|
if !trimmedText.string.isEmpty {
|
||||||
|
quote = EngineMessageReplyQuote(text: trimmedText.string, entities: trimmedText.entities, media: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(messageId: replySubject.messageId, quote: quote)).withoutSelectionState() }) })
|
||||||
|
}
|
||||||
|
|
||||||
let items = combineLatest(queue: .mainQueue(),
|
let items = combineLatest(queue: .mainQueue(),
|
||||||
selfController.context.account.postbox.messagesAtIds([replySubject.messageId]),
|
selfController.context.account.postbox.messagesAtIds([replySubject.messageId]),
|
||||||
ApplicationSpecificNotice.getReplyQuoteTextSelectionTips(accountManager: selfController.context.sharedContext.accountManager)
|
ApplicationSpecificNotice.getReplyQuoteTextSelectionTips(accountManager: selfController.context.sharedContext.accountManager)
|
||||||
@ -288,40 +323,8 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
if replySubject.quote != nil {
|
if replySubject.quote != nil {
|
||||||
items.append(.action(ContextMenuActionItem(text: selfController.presentationData.strings.Conversation_MessageOptionsQuoteSelectedPart, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: selfController.presentationData.strings.Conversation_MessageOptionsQuoteSelectedPart, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/QuoteSelected"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/QuoteSelected"), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { [weak selfController, weak chatController] _, f in
|
}, action: { _, f in
|
||||||
guard let selfController, let chatController else {
|
applyCurrentQuoteSelection()
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var messageItemNode: ChatMessageItemView?
|
|
||||||
chatController.chatDisplayNode.historyNode.enumerateItemNodes { itemNode in
|
|
||||||
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item, item.message.id == replySubject.messageId {
|
|
||||||
messageItemNode = itemNode
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
var targetContentNode: ChatMessageTextBubbleContentNode?
|
|
||||||
if let messageItemNode = messageItemNode as? ChatMessageBubbleItemNode {
|
|
||||||
for contentNode in messageItemNode.contentNodes {
|
|
||||||
if let contentNode = contentNode as? ChatMessageTextBubbleContentNode {
|
|
||||||
targetContentNode = contentNode
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
guard let contentNode = targetContentNode else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let textSelection = contentNode.getCurrentTextSelection() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var quote: EngineMessageReplyQuote?
|
|
||||||
let trimmedText = trimStringWithEntities(string: textSelection.text, entities: textSelection.entities, maxLength: quoteMaxLength(appConfig: selfController.context.currentAppConfiguration.with({ $0 })))
|
|
||||||
if !trimmedText.string.isEmpty {
|
|
||||||
quote = EngineMessageReplyQuote(text: trimmedText.string, entities: trimmedText.entities, media: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(messageId: replySubject.messageId, quote: quote)).withoutSelectionState() }) })
|
|
||||||
|
|
||||||
f(.default)
|
f(.default)
|
||||||
})))
|
})))
|
||||||
@ -418,6 +421,8 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
|
|
||||||
if canReplyInAnotherChat {
|
if canReplyInAnotherChat {
|
||||||
items.append(.action(ContextMenuActionItem(text: selfController.presentationData.strings.Conversation_MessageOptionsReplyInAnotherChat, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Replace"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController] c, f in
|
items.append(.action(ContextMenuActionItem(text: selfController.presentationData.strings.Conversation_MessageOptionsReplyInAnotherChat, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Replace"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController] c, f in
|
||||||
|
applyCurrentQuoteSelection()
|
||||||
|
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
guard let selfController else {
|
guard let selfController else {
|
||||||
@ -434,6 +439,8 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
items.append(.separator)
|
items.append(.separator)
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: selfController.presentationData.strings.Conversation_MessageOptionsApplyChanges, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
items.append(.action(ContextMenuActionItem(text: selfController.presentationData.strings.Conversation_MessageOptionsApplyChanges, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor) }, action: { _, f in
|
||||||
|
applyCurrentQuoteSelection()
|
||||||
|
|
||||||
f(.default)
|
f(.default)
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -1375,7 +1375,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
initialSearchLocation = .index(.absoluteUpperBound())
|
initialSearchLocation = .index(.absoluteUpperBound())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: initialSearchLocation, quote: nil), count: historyMessageCount, highlight: highlight != nil), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: initialSearchLocation, quote: highlight?.quote), count: historyMessageCount, highlight: highlight != nil), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||||
} else if let subject = subject, case let .pinnedMessages(maybeMessageId) = subject, let messageId = maybeMessageId {
|
} else if let subject = subject, case let .pinnedMessages(maybeMessageId) = subject, let messageId = maybeMessageId {
|
||||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: .id(messageId), quote: nil), count: historyMessageCount, highlight: true), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: .id(messageId), quote: nil), count: historyMessageCount, highlight: true), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||||
} else if var chatHistoryLocation = strongSelf.chatHistoryLocationValue {
|
} else if var chatHistoryLocation = strongSelf.chatHistoryLocationValue {
|
||||||
|
@ -73,11 +73,11 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
controller.updateTextInputState(updateTextInputState)
|
controller.updateTextInputState(updateTextInputState)
|
||||||
}
|
}
|
||||||
var popAndComplete = true
|
var popAndComplete = true
|
||||||
if let subject = params.subject, case let .message(messageSubject, _, timecode) = subject {
|
if let subject = params.subject, case let .message(messageSubject, highlight, timecode) = subject {
|
||||||
if case let .id(messageId) = messageSubject {
|
if case let .id(messageId) = messageSubject {
|
||||||
let navigationController = params.navigationController
|
let navigationController = params.navigationController
|
||||||
let animated = params.animated
|
let animated = params.animated
|
||||||
controller.navigateToMessage(messageLocation: .id(messageId, NavigateToMessageParams(timestamp: timecode, quote: nil)), animated: isFirst, completion: { [weak navigationController, weak controller] in
|
controller.navigateToMessage(messageLocation: .id(messageId, NavigateToMessageParams(timestamp: timecode, quote: highlight?.quote)), animated: isFirst, completion: { [weak navigationController, weak controller] in
|
||||||
if let navigationController = navigationController, let controller = controller {
|
if let navigationController = navigationController, let controller = controller {
|
||||||
let _ = navigationController.popToViewController(controller, animated: animated)
|
let _ = navigationController.popToViewController(controller, animated: animated)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user