mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-30 03:44:18 +00:00
Emoji improvements
This commit is contained in:
parent
cb83ca4ec8
commit
6fd38af0fe
@ -1200,7 +1200,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let draftText = stringWithAppliedEntities(draftState.text, entities: draftState.entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, message: nil)
|
let draftText = stringWithAppliedEntities(draftState.text, entities: draftState.entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, message: nil)
|
||||||
|
|
||||||
attributedText = foldLineBreaks(draftText)
|
attributedText = foldLineBreaks(draftText)
|
||||||
} else if let message = messages.last {
|
} else if let message = messages.first {
|
||||||
var composedString: NSMutableAttributedString
|
var composedString: NSMutableAttributedString
|
||||||
|
|
||||||
if let peerText = peerText {
|
if let peerText = peerText {
|
||||||
|
|||||||
@ -64,7 +64,7 @@ private final class PendingUpdateMessageManagerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool) {
|
func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool) {
|
||||||
if let context = self.contexts[messageId] {
|
if let context = self.contexts[messageId] {
|
||||||
self.contexts.removeValue(forKey: messageId)
|
self.contexts.removeValue(forKey: messageId)
|
||||||
context.disposable.dispose()
|
context.disposable.dispose()
|
||||||
@ -75,7 +75,7 @@ private final class PendingUpdateMessageManagerImpl {
|
|||||||
self.contexts[messageId] = context
|
self.contexts[messageId] = context
|
||||||
|
|
||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
disposable.set((requestEditMessage(postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: nil)
|
disposable.set((requestEditMessage(postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: nil)
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self, weak context] value in
|
|> deliverOn(self.queue)).start(next: { [weak self, weak context] value in
|
||||||
queue.async {
|
queue.async {
|
||||||
guard let strongSelf = self, let initialContext = context else {
|
guard let strongSelf = self, let initialContext = context else {
|
||||||
@ -163,9 +163,9 @@ public final class PendingUpdateMessageManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false) {
|
public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false) {
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
impl.add(messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview)
|
impl.add(messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,15 +27,15 @@ public enum RequestEditMessageError {
|
|||||||
case invalidGrouping
|
case invalidGrouping
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
||||||
return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
||||||
return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false)
|
return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false)
|
||||||
|> `catch` { error -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> in
|
|> `catch` { error -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> in
|
||||||
if case .invalidReference = error {
|
if case .invalidReference = error {
|
||||||
return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: true)
|
return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: true)
|
||||||
} else {
|
} else {
|
||||||
return .fail(error)
|
return .fail(error)
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ func requestEditMessage(postbox: Postbox, network: Network, stateManager: Accoun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> {
|
private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> {
|
||||||
let uploadedMedia: Signal<PendingMessageUploadedContentResult?, NoError>
|
let uploadedMedia: Signal<PendingMessageUploadedContentResult?, NoError>
|
||||||
switch media {
|
switch media {
|
||||||
case .keep:
|
case .keep:
|
||||||
@ -96,6 +96,10 @@ private func requestEditMessageInternal(postbox: Postbox, network: Network, stat
|
|||||||
return (nil, nil, SimpleDictionary())
|
return (nil, nil, SimpleDictionary())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (_, file) in inlineStickers {
|
||||||
|
transaction.storeMediaIfNotPresent(media: file)
|
||||||
|
}
|
||||||
|
|
||||||
if text.isEmpty {
|
if text.isEmpty {
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
switch media {
|
switch media {
|
||||||
|
|||||||
@ -85,8 +85,8 @@ public extension TelegramEngine {
|
|||||||
return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId)
|
return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
||||||
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal<Void, NoError> {
|
public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal<Void, NoError> {
|
||||||
|
|||||||
@ -1284,7 +1284,7 @@ public struct PresentationResourcesChat {
|
|||||||
|
|
||||||
public static func chatEntityKeyboardLock(_ theme: PresentationTheme, color: UIColor) -> UIImage? {
|
public static func chatEntityKeyboardLock(_ theme: PresentationTheme, color: UIColor) -> UIImage? {
|
||||||
return theme.image(PresentationResourceParameterKey.chatEntityKeyboardLock(color: color.argb), { theme in
|
return theme.image(PresentationResourceParameterKey.chatEntityKeyboardLock(color: color.argb), { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/SmallLock"), color: color)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelSectionLockIcon"), color: color)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -579,7 +579,7 @@ private final class GroupHeaderLayer: UIView {
|
|||||||
cache: AnimationCache,
|
cache: AnimationCache,
|
||||||
renderer: MultiAnimationRenderer,
|
renderer: MultiAnimationRenderer,
|
||||||
attemptSynchronousLoad: Bool
|
attemptSynchronousLoad: Bool
|
||||||
) -> CGSize {
|
) -> (size: CGSize, centralContentWidth: CGFloat) {
|
||||||
var themeUpdated = false
|
var themeUpdated = false
|
||||||
if self.theme !== theme {
|
if self.theme !== theme {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
@ -606,48 +606,8 @@ private final class GroupHeaderLayer: UIView {
|
|||||||
|
|
||||||
let titleHorizontalOffset: CGFloat
|
let titleHorizontalOffset: CGFloat
|
||||||
if isPremiumLocked {
|
if isPremiumLocked {
|
||||||
let lockIconLayer: SimpleLayer
|
titleHorizontalOffset = 10.0 + 2.0
|
||||||
if let current = self.lockIconLayer {
|
|
||||||
lockIconLayer = current
|
|
||||||
} else {
|
|
||||||
lockIconLayer = SimpleLayer()
|
|
||||||
self.lockIconLayer = lockIconLayer
|
|
||||||
self.layer.addSublayer(lockIconLayer)
|
|
||||||
}
|
|
||||||
if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: color) {
|
|
||||||
let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0))
|
|
||||||
lockIconLayer.contents = image.cgImage
|
|
||||||
titleHorizontalOffset = imageSize.width + 2.0
|
|
||||||
lockIconLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: imageSize)
|
|
||||||
} else {
|
|
||||||
lockIconLayer.contents = nil
|
|
||||||
titleHorizontalOffset = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
let tintLockIconLayer: SimpleLayer
|
|
||||||
if let current = self.tintLockIconLayer {
|
|
||||||
tintLockIconLayer = current
|
|
||||||
} else {
|
|
||||||
tintLockIconLayer = SimpleLayer()
|
|
||||||
self.tintLockIconLayer = tintLockIconLayer
|
|
||||||
self.tintContentLayer.addSublayer(tintLockIconLayer)
|
|
||||||
}
|
|
||||||
if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: .white) {
|
|
||||||
let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0))
|
|
||||||
tintLockIconLayer.contents = image.cgImage
|
|
||||||
tintLockIconLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: imageSize)
|
|
||||||
} else {
|
|
||||||
tintLockIconLayer.contents = nil
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if let lockIconLayer = self.lockIconLayer {
|
|
||||||
self.lockIconLayer = nil
|
|
||||||
lockIconLayer.removeFromSuperlayer()
|
|
||||||
}
|
|
||||||
if let tintLockIconLayer = self.tintLockIconLayer {
|
|
||||||
self.tintLockIconLayer = nil
|
|
||||||
tintLockIconLayer.removeFromSuperlayer()
|
|
||||||
}
|
|
||||||
titleHorizontalOffset = 0.0
|
titleHorizontalOffset = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,15 +672,53 @@ private final class GroupHeaderLayer: UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let textFrame: CGRect
|
let textFrame: CGRect
|
||||||
if (layoutType == .compact && hasClear) || subtitle != nil {
|
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - textSize.width) / 2.0), y: textOffsetY), size: textSize)
|
||||||
textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize)
|
|
||||||
} else {
|
|
||||||
textFrame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - textSize.width) / 2.0), y: textOffsetY), size: textSize)
|
|
||||||
}
|
|
||||||
self.textLayer.frame = textFrame
|
self.textLayer.frame = textFrame
|
||||||
self.tintTextLayer.frame = textFrame
|
self.tintTextLayer.frame = textFrame
|
||||||
self.tintTextLayer.isHidden = !needsTintText
|
self.tintTextLayer.isHidden = !needsTintText
|
||||||
|
|
||||||
|
if isPremiumLocked {
|
||||||
|
let lockIconLayer: SimpleLayer
|
||||||
|
if let current = self.lockIconLayer {
|
||||||
|
lockIconLayer = current
|
||||||
|
} else {
|
||||||
|
lockIconLayer = SimpleLayer()
|
||||||
|
self.lockIconLayer = lockIconLayer
|
||||||
|
self.layer.addSublayer(lockIconLayer)
|
||||||
|
}
|
||||||
|
if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: color) {
|
||||||
|
let imageSize = image.size
|
||||||
|
lockIconLayer.contents = image.cgImage
|
||||||
|
lockIconLayer.frame = CGRect(origin: CGPoint(x: textFrame.minX - imageSize.width - 3.0, y: 2.0 + UIScreenPixel), size: imageSize)
|
||||||
|
} else {
|
||||||
|
lockIconLayer.contents = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let tintLockIconLayer: SimpleLayer
|
||||||
|
if let current = self.tintLockIconLayer {
|
||||||
|
tintLockIconLayer = current
|
||||||
|
} else {
|
||||||
|
tintLockIconLayer = SimpleLayer()
|
||||||
|
self.tintLockIconLayer = tintLockIconLayer
|
||||||
|
self.tintContentLayer.addSublayer(tintLockIconLayer)
|
||||||
|
}
|
||||||
|
if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: .white) {
|
||||||
|
tintLockIconLayer.contents = image.cgImage
|
||||||
|
tintLockIconLayer.frame = lockIconLayer.frame
|
||||||
|
} else {
|
||||||
|
tintLockIconLayer.contents = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let lockIconLayer = self.lockIconLayer {
|
||||||
|
self.lockIconLayer = nil
|
||||||
|
lockIconLayer.removeFromSuperlayer()
|
||||||
|
}
|
||||||
|
if let tintLockIconLayer = self.tintLockIconLayer {
|
||||||
|
self.tintLockIconLayer = nil
|
||||||
|
tintLockIconLayer.removeFromSuperlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let subtitleSize: CGSize
|
let subtitleSize: CGSize
|
||||||
if let subtitle = subtitle {
|
if let subtitle = subtitle {
|
||||||
var updateSubtitleContents: UIImage?
|
var updateSubtitleContents: UIImage?
|
||||||
@ -836,11 +834,7 @@ private final class GroupHeaderLayer: UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var size: CGSize
|
var size: CGSize
|
||||||
if layoutType == .compact && hasClear {
|
size = CGSize(width: constrainedSize.width, height: constrainedSize.height)
|
||||||
size = CGSize(width: titleHorizontalOffset + textSize.width + clearWidth, height: constrainedSize.height)
|
|
||||||
} else {
|
|
||||||
size = CGSize(width: constrainedSize.width, height: constrainedSize.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let embeddedItems = embeddedItems {
|
if let embeddedItems = embeddedItems {
|
||||||
let groupEmbeddedView: GroupEmbeddedView
|
let groupEmbeddedView: GroupEmbeddedView
|
||||||
@ -908,7 +902,7 @@ private final class GroupHeaderLayer: UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return size
|
return (size, titleHorizontalOffset + textSize.width + clearWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
@ -1552,14 +1546,14 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
|
|
||||||
if width >= 420.0 {
|
if width >= 420.0 {
|
||||||
self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 5.0, bottom: containerInsets.bottom, right: containerInsets.right + 5.0)
|
self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 5.0, bottom: containerInsets.bottom, right: containerInsets.right + 5.0)
|
||||||
self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 5.0, bottom: containerInsets.bottom, right: containerInsets.right + 5.0)
|
|
||||||
minSpacing = 2.0
|
minSpacing = 2.0
|
||||||
} else {
|
} else {
|
||||||
self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 7.0, bottom: containerInsets.bottom, right: containerInsets.right + 7.0)
|
self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 7.0, bottom: containerInsets.bottom, right: containerInsets.right + 7.0)
|
||||||
self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 7.0, bottom: containerInsets.bottom, right: containerInsets.right + 7.0)
|
|
||||||
minSpacing = 9.0
|
minSpacing = 9.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 16.0, bottom: containerInsets.bottom, right: containerInsets.right + 16.0)
|
||||||
|
|
||||||
self.itemDefaultHeaderHeight = 24.0
|
self.itemDefaultHeaderHeight = 24.0
|
||||||
self.itemFeaturedHeaderHeight = self.itemDefaultHeaderHeight
|
self.itemFeaturedHeaderHeight = self.itemDefaultHeaderHeight
|
||||||
case .detailed:
|
case .detailed:
|
||||||
@ -3039,7 +3033,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
assignTopVisibleSubgroupId = true
|
assignTopVisibleSubgroupId = true
|
||||||
}
|
}
|
||||||
|
|
||||||
var headerSize: CGSize?
|
var headerCentralContentWidth: CGFloat?
|
||||||
var headerSizeUpdated = false
|
var headerSizeUpdated = false
|
||||||
if let title = itemGroup.title {
|
if let title = itemGroup.title {
|
||||||
validGroupHeaderIds.insert(itemGroup.groupId)
|
validGroupHeaderIds.insert(itemGroup.groupId)
|
||||||
@ -3076,7 +3070,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
|
|
||||||
let hasTopSeparator = false
|
let hasTopSeparator = false
|
||||||
|
|
||||||
let groupHeaderSize = groupHeaderView.update(
|
let (groupHeaderSize, centralContentWidth) = groupHeaderView.update(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
layoutType: itemLayout.layoutType,
|
layoutType: itemLayout.layoutType,
|
||||||
@ -3097,11 +3091,11 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
if groupHeaderView.bounds.size != groupHeaderSize {
|
if groupHeaderView.bounds.size != groupHeaderSize {
|
||||||
headerSizeUpdated = true
|
headerSizeUpdated = true
|
||||||
}
|
}
|
||||||
|
headerCentralContentWidth = centralContentWidth
|
||||||
|
|
||||||
let groupHeaderFrame = CGRect(origin: CGPoint(x: floor((itemLayout.contentSize.width - groupHeaderSize.width) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize)
|
let groupHeaderFrame = CGRect(origin: CGPoint(x: floor((itemLayout.contentSize.width - groupHeaderSize.width) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize)
|
||||||
groupHeaderView.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size)
|
groupHeaderView.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size)
|
||||||
groupHeaderTransition.setPosition(view: groupHeaderView, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY))
|
groupHeaderTransition.setPosition(view: groupHeaderView, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY))
|
||||||
headerSize = CGSize(width: groupHeaderSize.width, height: groupHeaderSize.height)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let groupBorderRadius: CGFloat = 16.0
|
let groupBorderRadius: CGFloat = 16.0
|
||||||
@ -3134,8 +3128,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
|
|
||||||
if groupBorderLayer.bounds.size != groupBorderFrame.size || headerSizeUpdated {
|
if groupBorderLayer.bounds.size != groupBorderFrame.size || headerSizeUpdated {
|
||||||
let headerWidth: CGFloat
|
let headerWidth: CGFloat
|
||||||
if let headerSize = headerSize {
|
if let headerCentralContentWidth = headerCentralContentWidth {
|
||||||
headerWidth = headerSize.width + 14.0
|
headerWidth = headerCentralContentWidth + 14.0
|
||||||
} else {
|
} else {
|
||||||
headerWidth = 0.0
|
headerWidth = 0.0
|
||||||
}
|
}
|
||||||
|
|||||||
@ -185,9 +185,14 @@ final class EntityKeyboardAnimationTopPanelComponent: Component {
|
|||||||
} else if let titleView = self.titleView {
|
} else if let titleView = self.titleView {
|
||||||
self.titleView = nil
|
self.titleView = nil
|
||||||
if let view = titleView.view {
|
if let view = titleView.view {
|
||||||
transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in
|
if !transition.animation.isImmediate {
|
||||||
view?.removeFromSuperview()
|
view.alpha = 0.0
|
||||||
})
|
view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, completion: { [weak view] _ in
|
||||||
|
view?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
view.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,9 +397,14 @@ final class EntityKeyboardIconTopPanelComponent: Component {
|
|||||||
} else if let titleView = self.titleView {
|
} else if let titleView = self.titleView {
|
||||||
self.titleView = nil
|
self.titleView = nil
|
||||||
if let view = titleView.view {
|
if let view = titleView.view {
|
||||||
transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in
|
if !transition.animation.isImmediate {
|
||||||
view?.removeFromSuperview()
|
view.alpha = 0.0
|
||||||
})
|
view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, completion: { [weak view] _ in
|
||||||
|
view?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
view.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,9 +734,14 @@ final class EntityKeyboardStaticStickersPanelComponent: Component {
|
|||||||
} else if let titleView = self.titleView {
|
} else if let titleView = self.titleView {
|
||||||
self.titleView = nil
|
self.titleView = nil
|
||||||
if let view = titleView.view {
|
if let view = titleView.view {
|
||||||
transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in
|
if !transition.animation.isImmediate {
|
||||||
view?.removeFromSuperview()
|
view.alpha = 0.0
|
||||||
})
|
view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, completion: { [weak view] _ in
|
||||||
|
view?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
view.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Locked.svg",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="7" height="10" viewBox="0 0 7 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.5 0.835039C2.02816 0.835039 0.835 2.0282 0.835 3.50004V4.67699C0.548874 4.82654 0.316237 5.06149 0.169545 5.34939C0 5.68214 0 6.11774 0 6.98893V7.51115C0 8.38234 0 8.81794 0.169545 9.15069C0.318682 9.44339 0.556652 9.68136 0.849348 9.83049C1.1821 10 1.6177 10 2.48889 10H4.51111C5.3823 10 5.8179 10 6.15065 9.83049C6.44335 9.68136 6.68132 9.44339 6.83045 9.15069C7 8.81794 7 8.38234 7 7.51115V6.98893C7 6.11774 7 5.68214 6.83045 5.34939C6.68376 5.06149 6.45113 4.82654 6.165 4.67699V3.50004C6.165 2.0282 4.97184 0.835039 3.5 0.835039ZM4.835 4.50043V3.50004C4.835 2.76274 4.2373 2.16504 3.5 2.16504C2.7627 2.16504 2.165 2.76274 2.165 3.50004V4.50043C2.26584 4.50004 2.37355 4.50004 2.48889 4.50004H4.51111C4.62645 4.50004 4.73416 4.50004 4.835 4.50043Z" fill="black" style="mix-blend-mode:overlay"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.5 0.835039C2.02816 0.835039 0.835 2.0282 0.835 3.50004V4.67699C0.548874 4.82654 0.316237 5.06149 0.169545 5.34939C0 5.68214 0 6.11774 0 6.98893V7.51115C0 8.38234 0 8.81794 0.169545 9.15069C0.318682 9.44339 0.556652 9.68136 0.849348 9.83049C1.1821 10 1.6177 10 2.48889 10H4.51111C5.3823 10 5.8179 10 6.15065 9.83049C6.44335 9.68136 6.68132 9.44339 6.83045 9.15069C7 8.81794 7 8.38234 7 7.51115V6.98893C7 6.11774 7 5.68214 6.83045 5.34939C6.68376 5.06149 6.45113 4.82654 6.165 4.67699V3.50004C6.165 2.0282 4.97184 0.835039 3.5 0.835039ZM4.835 4.50043V3.50004C4.835 2.76274 4.2373 2.16504 3.5 2.16504C2.7627 2.16504 2.165 2.76274 2.165 3.50004V4.50043C2.26584 4.50004 2.37355 4.50004 2.48889 4.50004H4.51111C4.62645 4.50004 4.73416 4.50004 4.835 4.50043Z" fill="black" fill-opacity="0.15"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
@ -3090,7 +3090,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, disableUrlPreview: false, scheduleTime: time) |> deliverOnMainQueue).start(next: { result in
|
|
||||||
|
let inlineStickers: [MediaId: TelegramMediaFile] = [:]
|
||||||
|
strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: false, scheduleTime: time) |> deliverOnMainQueue).start(next: { result in
|
||||||
}, error: { error in
|
}, error: { error in
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -7105,6 +7107,44 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
entitiesAttribute = TextEntitiesMessageAttribute(entities: entities)
|
entitiesAttribute = TextEntitiesMessageAttribute(entities: entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inlineStickers: [MediaId: TelegramMediaFile] = [:]
|
||||||
|
var firstLockedPremiumEmoji: TelegramMediaFile?
|
||||||
|
text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in
|
||||||
|
if let value = value as? ChatTextInputTextCustomEmojiAttribute {
|
||||||
|
if let file = value.file {
|
||||||
|
inlineStickers[file.fileId] = file
|
||||||
|
if file.isPremiumEmoji && !strongSelf.presentationInterfaceState.isPremium {
|
||||||
|
if firstLockedPremiumEmoji == nil {
|
||||||
|
firstLockedPremiumEmoji = file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if let firstLockedPremiumEmoji = firstLockedPremiumEmoji {
|
||||||
|
//let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
//TODO:localize
|
||||||
|
strongSelf.controllerInteraction?.displayUndo(.sticker(context: strongSelf.context, file: firstLockedPremiumEmoji, title: nil, text: "Subscribe to Telegram Premium to unlock premium emoji.", undoText: "More", customAction: {
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.chatDisplayNode.dismissTextInput()
|
||||||
|
|
||||||
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
|
let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: {
|
||||||
|
let controller = PremiumIntroScreen(context: strongSelf.context, source: .animatedEmoji)
|
||||||
|
replaceImpl?(controller)
|
||||||
|
})
|
||||||
|
replaceImpl = { [weak controller] c in
|
||||||
|
controller?.replace(with: c)
|
||||||
|
}
|
||||||
|
strongSelf.present(controller, in: .window(.root), with: nil)
|
||||||
|
}))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var updatingMedia = false
|
var updatingMedia = false
|
||||||
let media: RequestEditMessageMedia
|
let media: RequestEditMessageMedia
|
||||||
if let editMediaReference = strongSelf.presentationInterfaceState.editMessageState?.mediaReference {
|
if let editMediaReference = strongSelf.presentationInterfaceState.editMessageState?.mediaReference {
|
||||||
@ -7121,7 +7161,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let currentMessage = currentMessage {
|
if let currentMessage = currentMessage {
|
||||||
let currentEntities = currentMessage.textEntitiesAttribute?.entities ?? []
|
let currentEntities = currentMessage.textEntitiesAttribute?.entities ?? []
|
||||||
if currentMessage.text != text.string || currentEntities != entities || updatingMedia {
|
if currentMessage.text != text.string || currentEntities != entities || updatingMedia {
|
||||||
strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, disableUrlPreview: disableUrlPreview)
|
strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1374,6 +1374,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
case .overPanels:
|
case .overPanels:
|
||||||
self.inputContextPanelContainer.addSubnode(inputContextPanelNode)
|
self.inputContextPanelContainer.addSubnode(inputContextPanelNode)
|
||||||
case .overTextInput:
|
case .overTextInput:
|
||||||
|
inputContextPanelNode.view.disablesInteractiveKeyboardGestureRecognizer = true
|
||||||
self.inputContextOverTextPanelContainer.addSubnode(inputContextPanelNode)
|
self.inputContextOverTextPanelContainer.addSubnode(inputContextPanelNode)
|
||||||
}
|
}
|
||||||
immediatelyLayoutInputContextPanelAndAnimateAppearance = true
|
immediatelyLayoutInputContextPanelAndAnimateAppearance = true
|
||||||
|
|||||||
@ -945,6 +945,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
fileprivate var emojiInputInteraction: EmojiPagerContentComponent.InputInteraction?
|
fileprivate var emojiInputInteraction: EmojiPagerContentComponent.InputInteraction?
|
||||||
private var stickerInputInteraction: EmojiPagerContentComponent.InputInteraction?
|
private var stickerInputInteraction: EmojiPagerContentComponent.InputInteraction?
|
||||||
|
|
||||||
|
private weak var currentUndoOverlayController: UndoOverlayController?
|
||||||
|
|
||||||
init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal<InputData, NoError>, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, chatPeerId: PeerId?) {
|
init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal<InputData, NoError>, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, chatPeerId: PeerId?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.currentInputData = currentInputData
|
self.currentInputData = currentInputData
|
||||||
@ -973,9 +975,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
self.emojiInputInteraction = EmojiPagerContentComponent.InputInteraction(
|
self.emojiInputInteraction = EmojiPagerContentComponent.InputInteraction(
|
||||||
performItemAction: { [weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in
|
performItemAction: { [weak self, weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in
|
||||||
let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in
|
let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in
|
||||||
guard let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else {
|
guard let strongSelf = self, let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,10 +996,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if file.isPremiumEmoji && !hasPremium {
|
if file.isPremiumEmoji && !hasPremium {
|
||||||
|
var animateInAsReplacement = false
|
||||||
|
if let currentUndoOverlayController = strongSelf.currentUndoOverlayController {
|
||||||
|
currentUndoOverlayController.dismissWithCommitActionAndReplacementAnimation()
|
||||||
|
strongSelf.currentUndoOverlayController = nil
|
||||||
|
animateInAsReplacement = true
|
||||||
|
}
|
||||||
|
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in
|
let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in
|
||||||
guard let controllerInteraction = controllerInteraction else {
|
guard let controllerInteraction = controllerInteraction else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1014,7 +1023,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
|
|
||||||
/*let controller = PremiumIntroScreen(context: context, source: .stickers)
|
/*let controller = PremiumIntroScreen(context: context, source: .stickers)
|
||||||
controllerInteraction.navigationController()?.pushViewController(controller)*/
|
controllerInteraction.navigationController()?.pushViewController(controller)*/
|
||||||
}), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
|
}), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in return false })
|
||||||
|
strongSelf.currentUndoOverlayController = controller
|
||||||
|
controllerInteraction.presentController(controller, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user