Emoji improvements

This commit is contained in:
Ali 2022-07-24 17:31:47 +02:00
parent 99207385b1
commit ea6929fef6
13 changed files with 191 additions and 42 deletions

View File

@ -7883,8 +7883,13 @@ Sorry for the inconvenience.";
"EmojiPackActionInfo.AddedTitle" = "Emoji Added"; "EmojiPackActionInfo.AddedTitle" = "Emoji Added";
"EmojiPackActionInfo.AddedText" = "%@ has been added to your emoji."; "EmojiPackActionInfo.AddedText" = "%@ has been added to your emoji.";
"EmojiPackActionInfo.RemovedTitle" = "Emoji Removed"; "EmojiPackActionInfo.RemovedTitle" = "Emoji Removed";
"EmojiPackActionInfo.ArchivedTitle" = "Emoji Archived";
"EmojiPackActionInfo.RemovedText" = "%@ is no longer in your emoji."; "EmojiPackActionInfo.RemovedText" = "%@ is no longer in your emoji.";
"MaskPackActionInfo.RemovedTitle" = "Masks Removed";
"MaskPackActionInfo.ArchivedTitle" = "Masks Archived";
"MaskPackActionInfo.RemovedText" = "%@ is no longer in your masks.";
"WebApp.ShareMyPhoneNumber" = "Share My Phone Number"; "WebApp.ShareMyPhoneNumber" = "Share My Phone Number";
"WebApp.ShareMyPhoneNumberConfirmation" = "Are you sure you want to share your phone number **%1$@** with **%2$@**?"; "WebApp.ShareMyPhoneNumberConfirmation" = "Are you sure you want to share your phone number **%1$@** with **%2$@**?";
@ -7893,3 +7898,15 @@ Sorry for the inconvenience.";
"Emoji.ClearRecent" = "Clear Recent Emoji"; "Emoji.ClearRecent" = "Clear Recent Emoji";
"Premium.AnimatedEmoji.Proceed" = "Unlock Animated Emoji"; "Premium.AnimatedEmoji.Proceed" = "Unlock Animated Emoji";
"EmojiPacksSettings.Title" = "Emoji";
"EmojiStickerSettings.Info" = "Artists are welcome to add their own emoji sets using our @stickers bot.\n\nTap on a message to view and add the whole set.";
"StickerPack.MaskCount_1" = "1 mask";
"StickerPack.MaskCount_any" = "%@ masks";
"StickerPack.EmojiCount_1" = "1 emoji";
"StickerPack.EmojiCount_any" = "%@ emoji";
"StickerSettings.EmojiContextInfo" = "If you archive an emoji set, you can quickly restore it later from the Archived Emoji section.";

View File

@ -127,7 +127,15 @@ private final class ArchivedStickersNoticeAlertContentNode: AlertContentNode {
var index: Int = 0 var index: Int = 0
var entries: [ArchivedStickersNoticeEntry] = [] var entries: [ArchivedStickersNoticeEntry] = []
for pack in archivedStickerPacks { for pack in archivedStickerPacks {
entries.append(ArchivedStickersNoticeEntry(index: index, info: pack.0, topItem: pack.1, count: presentationData.strings.StickerPack_StickerCount(pack.0.count))) let countTitle: String
if pack.0.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
countTitle = presentationData.strings.StickerPack_EmojiCount(pack.0.count)
} else if pack.0.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
countTitle = presentationData.strings.StickerPack_MaskCount(pack.0.count)
} else {
countTitle = presentationData.strings.StickerPack_StickerCount(pack.0.count)
}
entries.append(ArchivedStickersNoticeEntry(index: index, info: pack.0, topItem: pack.1, count: countTitle))
index += 1 index += 1
} }

View File

@ -405,6 +405,17 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
strongSelf.ensureFocused() strongSelf.ensureFocused()
} }
} }
recognizer.waitForTouchUp = { [weak self] in
guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else {
return true
}
if textInputNode.textView.isFirstResponder {
return true
} else {
return false
}
}
self.textInputBackgroundNode.view.addGestureRecognizer(recognizer) self.textInputBackgroundNode.view.addGestureRecognizer(recognizer)
self.emojiViewProvider = { [weak self] emoji in self.emojiViewProvider = { [weak self] emoji in
@ -525,6 +536,17 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
strongSelf.ensureFocused() strongSelf.ensureFocused()
} }
} }
recognizer.waitForTouchUp = { [weak self] in
guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else {
return true
}
if textInputNode.textView.isFirstResponder {
return true
} else {
return false
}
}
textInputNode.view.addGestureRecognizer(recognizer) textInputNode.view.addGestureRecognizer(recognizer)
textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string

View File

@ -430,6 +430,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
} }
var contentInsets = component.contentInsets var contentInsets = component.contentInsets
contentInsets.bottom = 0.0
var scrollingPanelOffsetFraction: CGFloat var scrollingPanelOffsetFraction: CGFloat
if case .show = component.panelHideBehavior { if case .show = component.panelHideBehavior {

View File

@ -154,7 +154,7 @@ public extension ContainedViewLayoutTransition {
} }
case let .animated(duration, curve): case let .animated(duration, curve):
let previousFrame: CGRect let previousFrame: CGRect
if beginWithCurrentState, let presentation = node.layer.presentation() { if beginWithCurrentState, (node.layer.animation(forKey: "position") != nil || node.layer.animation(forKey: "bounds") != nil), let presentation = node.layer.presentation() {
previousFrame = presentation.frame previousFrame = presentation.frame
} else { } else {
previousFrame = node.frame previousFrame = node.frame
@ -290,7 +290,7 @@ public extension ContainedViewLayoutTransition {
} }
case let .animated(duration, curve): case let .animated(duration, curve):
let previousBounds: CGRect let previousBounds: CGRect
if beginWithCurrentState, let presentation = node.layer.presentation() { if beginWithCurrentState, node.layer.animation(forKey: "bounds") != nil, let presentation = node.layer.presentation() {
previousBounds = presentation.bounds previousBounds = presentation.bounds
} else { } else {
previousBounds = node.bounds previousBounds = node.bounds
@ -341,8 +341,8 @@ public extension ContainedViewLayoutTransition {
} }
case let .animated(duration, curve): case let .animated(duration, curve):
let previousPosition: CGPoint let previousPosition: CGPoint
if beginWithCurrentState { if beginWithCurrentState, node.layer.animation(forKey: "position") != nil, let presentation = node.layer.presentation() {
previousPosition = node.layer.presentation()?.position ?? node.position previousPosition = presentation.position
} else { } else {
previousPosition = node.position previousPosition = node.position
} }

View File

@ -243,7 +243,7 @@ public final class NavigationBackgroundNode: ASDisplayNode {
self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur) self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur)
} }
public func update(size: CGSize, cornerRadius: CGFloat = 0.0, transition: ContainedViewLayoutTransition) { public func update(size: CGSize, cornerRadius: CGFloat = 0.0, transition: ContainedViewLayoutTransition, beginWithCurrentState: Bool = true) {
self.validLayout = (size, cornerRadius) self.validLayout = (size, cornerRadius)
let contentFrame = CGRect(origin: CGPoint(), size: size) let contentFrame = CGRect(origin: CGPoint(), size: size)

View File

@ -207,7 +207,16 @@ private func archivedStickerPacksControllerEntries(presentationData: Presentatio
var index: Int32 = 0 var index: Int32 = 0
for item in packs { for item in packs {
if !installedIds.contains(item.info.id) { if !installedIds.contains(item.info.id) {
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), stickerSettings.loopAnimatedStickers, !state.removingPackIds.contains(item.info.id), ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == item.info.id, reorderable: false, selectable: true))) let countTitle: String
if item.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
countTitle = presentationData.strings.StickerPack_EmojiCount(item.info.count)
} else if item.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
countTitle = presentationData.strings.StickerPack_MaskCount(item.info.count)
} else {
countTitle = presentationData.strings.StickerPack_StickerCount(item.info.count)
}
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, item.topItems.first, countTitle, stickerSettings.loopAnimatedStickers, !state.removingPackIds.contains(item.info.id), ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == item.info.id, reorderable: false, selectable: true)))
index += 1 index += 1
} }
} }

View File

@ -138,7 +138,17 @@ private func featuredStickerPacksControllerEntries(presentationData: Presentatio
if let value = unreadPacks[item.info.id] { if let value = unreadPacks[item.info.id] {
unread = value unread = value
} }
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), stickerSettings.loopAnimatedStickers, installedPacks.contains(item.info.id)))
let countTitle: String
if item.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
countTitle = presentationData.strings.StickerPack_EmojiCount(item.info.count)
} else if item.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
countTitle = presentationData.strings.StickerPack_MaskCount(item.info.count)
} else {
countTitle = presentationData.strings.StickerPack_StickerCount(item.info.count)
}
entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, countTitle, stickerSettings.loopAnimatedStickers, installedPacks.contains(item.info.id)))
index += 1 index += 1
} }
} }

View File

@ -589,7 +589,16 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
} }
for featuredPack in featuredPacks { for featuredPack in featuredPacks {
entries.append(.trendingPack(index, presentationData.theme, presentationData.strings, featuredPack.info, featuredPack.topItems.first, presentationData.strings.StickerPack_StickerCount(featuredPack.info.count), stickerSettings.loopAnimatedStickers, featuredPack.unread, installedPacks.contains(featuredPack.info.id))) let countTitle: String
if featuredPack.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
countTitle = presentationData.strings.StickerPack_EmojiCount(featuredPack.info.count)
} else if featuredPack.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
countTitle = presentationData.strings.StickerPack_MaskCount(featuredPack.info.count)
} else {
countTitle = presentationData.strings.StickerPack_StickerCount(featuredPack.info.count)
}
entries.append(.trendingPack(index, presentationData.theme, presentationData.strings, featuredPack.info, featuredPack.topItems.first, countTitle, stickerSettings.loopAnimatedStickers, featuredPack.unread, installedPacks.contains(featuredPack.info.id)))
index += 1 index += 1
} }
@ -637,7 +646,16 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
var index: Int32 = 0 var index: Int32 = 0
for entry in sortedPacks { for entry in sortedPacks {
if let info = entry.info as? StickerPackCollectionInfo { if let info = entry.info as? StickerPackCollectionInfo {
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), stickerSettings.loopAnimatedStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true, selectable: true), state.selectedPackIds?.contains(info.id))) let countTitle: String
if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
countTitle = presentationData.strings.StickerPack_EmojiCount(info.count == 0 ? entry.count : info.count)
} else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
countTitle = presentationData.strings.StickerPack_MaskCount(info.count == 0 ? entry.count : info.count)
} else {
countTitle = presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count)
}
entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, countTitle, stickerSettings.loopAnimatedStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true, selectable: true), state.selectedPackIds?.contains(info.id)))
index += 1 index += 1
} }
} }
@ -651,8 +669,7 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
case .masks: case .masks:
markdownString = presentationData.strings.MaskStickerSettings_Info markdownString = presentationData.strings.MaskStickerSettings_Info
case .emoji: case .emoji:
//TODO:localize markdownString = presentationData.strings.EmojiStickerSettings_Info
markdownString = "Emoji"
} }
let entities = generateTextEntities(markdownString, enabledTypes: [.mention]) let entities = generateTextEntities(markdownString, enabledTypes: [.mention])
if let entity = entities.first { if let entity = entities.first {
@ -727,7 +744,20 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
} }
} }
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: action == .archive ? presentationData.strings.StickerPackActionInfo_ArchivedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).string, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in let removedTitle: String
let removedText: String
if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
removedTitle = action == .archive ? presentationData.strings.EmojiPackActionInfo_ArchivedTitle : presentationData.strings.EmojiPackActionInfo_RemovedTitle
removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(archivedItem.info.title).string
} else if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
removedTitle = action == .archive ? presentationData.strings.MaskPackActionInfo_ArchivedTitle : presentationData.strings.MaskPackActionInfo_RemovedTitle
removedText = presentationData.strings.MaskPackActionInfo_RemovedText(archivedItem.info.title).string
} else {
removedTitle = action == .archive ? presentationData.strings.StickerPackActionInfo_ArchivedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle
removedText = presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).string
}
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
if case .undo = action { if case .undo = action {
let _ = context.engine.stickers.addStickerPackInteractively(info: archivedItem.info, items: items.compactMap({ $0 as? StickerPackItem }), positionInList: positionInList).start() let _ = context.engine.stickers.addStickerPackInteractively(info: archivedItem.info, items: items.compactMap({ $0 as? StickerPackItem }), positionInList: positionInList).start()
} }
@ -735,9 +765,19 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
})) }))
}) })
} }
let title: String
if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
title = presentationData.strings.StickerSettings_EmojiContextInfo
} else if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
title = presentationData.strings.StickerSettings_MaskContextInfo
} else {
title = presentationData.strings.StickerSettings_ContextInfo
}
controller.setItemGroups([ controller.setItemGroups([
ActionSheetItemGroup(items: [ ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.StickerSettings_ContextInfo), ActionSheetTextItem(title: title),
ActionSheetButtonItem(title: presentationData.strings.StickerSettings_ContextHide, color: .accent, action: { ActionSheetButtonItem(title: presentationData.strings.StickerSettings_ContextHide, color: .accent, action: {
dismissAction() dismissAction()
@ -1072,8 +1112,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
case .masks: case .masks:
title = presentationData.strings.MaskStickerSettings_Title title = presentationData.strings.MaskStickerSettings_Title
case .emoji: case .emoji:
//TODO:localize title = presentationData.strings.EmojiPacksSettings_Title
title = "Emoji"
} }
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
@ -1247,7 +1286,20 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
return true return true
})) }))
case let .remove(positionInList): case let .remove(positionInList):
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in let removedTitle: String
let removedText: String
if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks {
removedTitle = presentationData.strings.EmojiPackActionInfo_RemovedTitle
removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string
} else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks {
removedTitle = presentationData.strings.MaskPackActionInfo_RemovedTitle
removedText = presentationData.strings.MaskPackActionInfo_RemovedText(info.title).string
} else {
removedTitle = presentationData.strings.StickerPackActionInfo_RemovedTitle
removedText = presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string
}
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
if case .undo = action { if case .undo = action {
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
} }

View File

@ -1624,9 +1624,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
let previousInputPanelBackgroundFrame = self.inputPanelBackgroundNode.frame let previousInputPanelBackgroundFrame = self.inputPanelBackgroundNode.frame
transition.updateFrame(node: self.inputPanelContainerNode, frame: CGRect(origin: CGPoint(), size: layout.size)) transition.updateFrame(node: self.inputPanelContainerNode, frame: CGRect(origin: CGPoint(), size: layout.size))
self.inputPanelContainerNode.update(size: layout.size, scrollableDistance: max(0.0, maximumInputNodeHeight - layout.standardInputHeight), isExpansionEnabled: isInputExpansionEnabled, transition: transition) self.inputPanelContainerNode.update(size: layout.size, scrollableDistance: max(0.0, maximumInputNodeHeight - layout.standardInputHeight), isExpansionEnabled: isInputExpansionEnabled, transition: transition)
transition.updatePosition(node: self.inputPanelClippingNode, position: CGRect(origin: apparentInputBackgroundFrame.origin, size: layout.size).center) transition.updatePosition(node: self.inputPanelClippingNode, position: CGRect(origin: apparentInputBackgroundFrame.origin, size: layout.size).center, beginWithCurrentState: true)
transition.updateBounds(node: self.inputPanelClippingNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: apparentInputBackgroundFrame.origin.y), size: layout.size)) transition.updateBounds(node: self.inputPanelClippingNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: apparentInputBackgroundFrame.origin.y), size: layout.size), beginWithCurrentState: true)
transition.updateFrame(node: self.inputPanelBackgroundNode, frame: apparentInputBackgroundFrame) transition.updateFrame(node: self.inputPanelBackgroundNode, frame: apparentInputBackgroundFrame, beginWithCurrentState: true)
transition.updateFrame(node: self.contentDimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: apparentInputBackgroundFrame.origin.y))) transition.updateFrame(node: self.contentDimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: apparentInputBackgroundFrame.origin.y)))
@ -1644,7 +1644,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
inputPanelUpdateTransition = .immediate inputPanelUpdateTransition = .immediate
} }
self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition) self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition, beginWithCurrentState: true)
self.inputPanelBottomBackgroundSeparatorBaseOffset = intrinsicInputPanelBackgroundNodeSize.height self.inputPanelBottomBackgroundSeparatorBaseOffset = intrinsicInputPanelBackgroundNodeSize.height
inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: UIScreenPixel)), beginWithCurrentState: true) inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: UIScreenPixel)), beginWithCurrentState: true)

View File

@ -135,7 +135,7 @@ func chatHistoryEntriesForView(
} }
if presentationData.largeEmoji, message.media.isEmpty { if presentationData.largeEmoji, message.media.isEmpty {
if stickersEnabled && message.text.count == 1, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, case let .CustomEmoji(_, fileId) = entities[0].type, let _ = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] { if stickersEnabled && message.text.count == 1, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, case let .CustomEmoji(_, fileId) = entities[0].type, let file = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile, !file.isVideoEmoji {
contentTypeHint = .animatedEmoji contentTypeHint = .animatedEmoji
} else if stickersEnabled && message.text.count == 1, let _ = associatedData.animatedEmojiStickers[message.text.basicEmoji.0], (message.textEntitiesAttribute?.entities.isEmpty ?? true) { } else if stickersEnabled && message.text.count == 1, let _ = associatedData.animatedEmojiStickers[message.text.basicEmoji.0], (message.textEntitiesAttribute?.entities.isEmpty ?? true) {
contentTypeHint = .animatedEmoji contentTypeHint = .animatedEmoji

View File

@ -411,7 +411,7 @@ final class CustomEmojiContainerView: UIView {
preconditionFailure() preconditionFailure()
} }
func update(emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) { func update(fontSize: CGFloat, emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) {
var nextIndexById: [Int64: Int] = [:] var nextIndexById: [Int64: Int] = [:]
var validKeys = Set<InlineStickerItemLayer.Key>() var validKeys = Set<InlineStickerItemLayer.Key>()
@ -437,7 +437,8 @@ final class CustomEmojiContainerView: UIView {
continue continue
} }
let size = CGSize(width: 24.0, height: 24.0) let itemSize: CGFloat = floor(24.0 * fontSize / 17.0)
let size = CGSize(width: itemSize, height: itemSize)
view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size) view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size)
@ -896,6 +897,17 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
strongSelf.ensureFocused() strongSelf.ensureFocused()
} }
} }
recognizer.waitForTouchUp = { [weak self] in
guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else {
return true
}
if textInputNode.textView.isFirstResponder {
return true
} else {
return false
}
}
self.textInputBackgroundNode.isUserInteractionEnabled = true self.textInputBackgroundNode.isUserInteractionEnabled = true
self.textInputBackgroundNode.view.addGestureRecognizer(recognizer) self.textInputBackgroundNode.view.addGestureRecognizer(recognizer)
@ -992,6 +1004,26 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
strongSelf.ensureFocusedOnTap() strongSelf.ensureFocusedOnTap()
} }
} }
recognizer.waitForTouchUp = { [weak self] in
guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else {
return true
}
if textInputNode.textView.isFirstResponder {
return true
} else if let (_, _, _, bottomInset, _, _, metrics, _, _) = strongSelf.validLayout {
let textFieldWaitsForTouchUp: Bool
if case .regular = metrics.widthClass, bottomInset.isZero {
textFieldWaitsForTouchUp = true
} else {
textFieldWaitsForTouchUp = false
}
return textFieldWaitsForTouchUp
} else {
return false
}
}
textInputNode.view.addGestureRecognizer(recognizer) textInputNode.view.addGestureRecognizer(recognizer)
self.touchDownGestureRecognizer = recognizer self.touchDownGestureRecognizer = recognizer
@ -1082,14 +1114,6 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
let previousAdditionalSideInsets = self.validLayout?.4 let previousAdditionalSideInsets = self.validLayout?.4
self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded)
let textFieldWaitsForTouchUp: Bool
if case .regular = metrics.widthClass, bottomInset.isZero {
textFieldWaitsForTouchUp = true
} else {
textFieldWaitsForTouchUp = false
}
self.touchDownGestureRecognizer?.waitForTouchUp = textFieldWaitsForTouchUp
var transition = transition var transition = transition
var additionalOffset: CGFloat = 0.0 var additionalOffset: CGFloat = 0.0
if let previousAdditionalSideInsets = previousAdditionalSideInsets, previousAdditionalSideInsets.right != additionalSideInsets.right { if let previousAdditionalSideInsets = previousAdditionalSideInsets, previousAdditionalSideInsets.right != additionalSideInsets.right {
@ -2146,6 +2170,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
var rects: [CGRect] = [] var rects: [CGRect] = []
var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = []
let fontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
if let attributedText = textInputNode.attributedText { if let attributedText = textInputNode.attributedText {
let beginning = textInputNode.textView.beginningOfDocument let beginning = textInputNode.textView.beginningOfDocument
attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in
@ -2229,7 +2255,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
self.customEmojiContainerView = customEmojiContainerView self.customEmojiContainerView = customEmojiContainerView
} }
customEmojiContainerView.update(emojiRects: customEmojiRects) customEmojiContainerView.update(fontSize: fontSize, emojiRects: customEmojiRects)
} else if let customEmojiContainerView = self.customEmojiContainerView { } else if let customEmojiContainerView = self.customEmojiContainerView {
customEmojiContainerView.removeFromSuperview() customEmojiContainerView.removeFromSuperview()
self.customEmojiContainerView = nil self.customEmojiContainerView = nil

View File

@ -6,7 +6,8 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize
public var touchDown: (() -> Void)? public var touchDown: (() -> Void)?
private var touchLocation: CGPoint? private var touchLocation: CGPoint?
public var waitForTouchUp = false public var waitForTouchUp: (() -> Bool)?
private var isWaitingForTouchUp: Bool = false
override public init(target: Any?, action: Selector?) { override public init(target: Any?, action: Selector?) {
super.init(target: target, action: action) super.init(target: target, action: action)
@ -14,6 +15,13 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize
self.delegate = self self.delegate = self
} }
override public func reset() {
self.touchLocation = nil
self.isWaitingForTouchUp = false
super.reset()
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true return true
} }
@ -21,7 +29,8 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize
override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
if self.waitForTouchUp { if let waitForTouchUp = self.waitForTouchUp, waitForTouchUp() {
self.isWaitingForTouchUp = true
if let touch = touches.first { if let touch = touches.first {
self.touchLocation = touch.location(in: self.view) self.touchLocation = touch.location(in: self.view)
} }
@ -49,14 +58,9 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize
override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) { override public func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
if let touchDown = self.touchDown, self.waitForTouchUp { if let touchDown = self.touchDown, self.isWaitingForTouchUp {
self.isWaitingForTouchUp = false
touchDown() touchDown()
} }
} }
override public func reset() {
self.touchLocation = nil
super.reset()
}
} }