CarPlay & Siri fixes

Silent posting fixes
This commit is contained in:
Ilya Laktyushin 2019-07-28 19:46:55 +02:00
parent b6fa9a7006
commit 659d360a65
16 changed files with 136 additions and 37 deletions

View File

@ -294,8 +294,18 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|> introduceError(IntentHandlingError.self) |> introduceError(IntentHandlingError.self)
|> mapToSignal { account -> Signal<[INMessage], IntentHandlingError> in |> mapToSignal { account -> Signal<[INMessage], IntentHandlingError> in
account.shouldBeServiceTaskMaster.set(.single(.now)) account.shouldBeServiceTaskMaster.set(.single(.now))
let completedUpdating: Signal<Bool, IntentHandlingError> = (.single(true) |> then(account.stateManager.isUpdating))
|> introduceError(IntentHandlingError.self)
|> filter { !$0 }
|> take(1)
|> timeout(3.0, queue: Queue.mainQueue(), alternate: .fail(.generic))
return completedUpdating
|> mapToSignal { value -> Signal<[INMessage], IntentHandlingError> in
return unreadMessages(account: account) return unreadMessages(account: account)
|> introduceError(IntentHandlingError.self) |> introduceError(IntentHandlingError.self)
}
|> afterDisposed { |> afterDisposed {
account.shouldBeServiceTaskMaster.set(.single(.never)) account.shouldBeServiceTaskMaster.set(.single(.never))
} }

View File

@ -14,8 +14,10 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
for entry in view.0.entries { for entry in view.0.entries {
if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _) = entry { if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _) = entry {
var hasUnread = false var hasUnread = false
var fixedCombinedReadStates: MessageHistoryViewReadState?
if let readState = readState { if let readState = readState {
hasUnread = readState.count != 0 hasUnread = readState.count != 0
fixedCombinedReadStates = .peer([index.messageIndex.id.peerId: readState])
} }
var isMuted = false var isMuted = false
if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings { if let notificationSettings = notificationSettings as? TelegramPeerNotificationSettings {
@ -25,12 +27,17 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
} }
if !isMuted && hasUnread { if !isMuted && hasUnread {
signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tagMask: nil, orderStatistics: .combinedLocation) signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, orderStatistics: .combinedLocation)
|> take(1) |> take(1)
|> map { view -> [INMessage] in |> map { view -> [INMessage] in
var messages: [INMessage] = [] var messages: [INMessage] = []
for entry in view.0.entries { for entry in view.0.entries {
if !entry.isRead { var isRead = true
if let readState = readState {
isRead = readState.isIncomingMessageIndexRead(entry.message.index)
}
if !isRead {
if let message = messageWithTelegramMessage(entry.message, account: account) { if let message = messageWithTelegramMessage(entry.message, account: account) {
messages.append(message) messages.append(message)
} }
@ -150,7 +157,8 @@ private func messageWithTelegramMessage(_ telegramMessage: Message, account: Acc
personHandle = INPersonHandle(value: user.phone ?? "", type: .phoneNumber) personHandle = INPersonHandle(value: user.phone ?? "", type: .phoneNumber)
} }
let sender = INPerson(personHandle: personHandle, nameComponents: nil, displayName: user.displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(user.id.toInt64())") let personIdentifier = "tg\(user.id.toInt64())"
let sender = INPerson(personHandle: personHandle, nameComponents: nil, displayName: user.displayTitle, image: nil, contactIdentifier: personIdentifier, customIdentifier: personIdentifier)
let date = Date(timeIntervalSince1970: TimeInterval(telegramMessage.timestamp)) let date = Date(timeIntervalSince1970: TimeInterval(telegramMessage.timestamp))
let message: INMessage let message: INMessage

View File

@ -1183,7 +1183,7 @@ public class Account {
self.networkTypeValue.set(currentNetworkType()) self.networkTypeValue.set(currentNetworkType())
let serviceTasksMasterBecomeMaster = shouldBeServiceTaskMaster.get() let serviceTasksMasterBecomeMaster = self.shouldBeServiceTaskMaster.get()
|> distinctUntilChanged |> distinctUntilChanged
|> deliverOn(self.serviceQueue) |> deliverOn(self.serviceQueue)
@ -1193,7 +1193,7 @@ public class Account {
} }
})) }))
let shouldBeMaster = combineLatest(shouldBeServiceTaskMaster.get(), postbox.isMasterClient()) let shouldBeMaster = combineLatest(self.shouldBeServiceTaskMaster.get(), postbox.isMasterClient())
|> map { [weak self] shouldBeMaster, isMaster -> Bool in |> map { [weak self] shouldBeMaster, isMaster -> Bool in
if shouldBeMaster == .always && !isMaster { if shouldBeMaster == .always && !isMaster {
self?.postbox.becomeMasterClient() self?.postbox.becomeMasterClient()

View File

@ -16,7 +16,7 @@ public enum EnqueueMessageGrouping {
public enum EnqueueMessage { public enum EnqueueMessage {
case message(text: String, attributes: [MessageAttribute], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?) case message(text: String, attributes: [MessageAttribute], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?)
case forward(source: MessageId, grouping: EnqueueMessageGrouping) case forward(source: MessageId, grouping: EnqueueMessageGrouping, attributes: [MessageAttribute])
public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage { public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage {
switch self { switch self {
@ -31,8 +31,8 @@ public enum EnqueueMessage {
switch self { switch self {
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey): case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey):
return .message(text: text, attributes: f(attributes), mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey) return .message(text: text, attributes: f(attributes), mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey)
case .forward: case let .forward(source, grouping, attributes):
return self return .forward(source: source, grouping: grouping, attributes: f(attributes))
} }
} }
} }
@ -97,6 +97,8 @@ private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAt
return true return true
case _ as InlineBotMessageAttribute: case _ as InlineBotMessageAttribute:
return true return true
case _ as NotificationInfoMessageAttribute:
return true
default: default:
return false return false
} }
@ -246,10 +248,10 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
} }
} }
if canBeForwarded { if canBeForwarded {
updatedMessages.append((true, .forward(source: replyToMessageId, grouping: .none))) updatedMessages.append((true, .forward(source: replyToMessageId, grouping: .none, attributes: [])))
} }
} }
case let .forward(sourceId, _): case let .forward(sourceId, _, _):
if let sourceMessage = forwardedMessageToBeReuploaded(transaction: transaction, id: sourceId) { if let sourceMessage = forwardedMessageToBeReuploaded(transaction: transaction, id: sourceId) {
var mediaReference: AnyMediaReference? var mediaReference: AnyMediaReference?
if sourceMessage.id.peerId.namespace == Namespaces.Peer.SecretChat { if sourceMessage.id.peerId.namespace == Namespaces.Peer.SecretChat {
@ -383,7 +385,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
} }
storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, groupingKey: localGroupingKey, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList)) storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, groupingKey: localGroupingKey, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList))
case let .forward(source, grouping): case let .forward(source, grouping, requestedAttributes):
let sourceMessage = transaction.getMessage(source) let sourceMessage = transaction.getMessage(source)
if let sourceMessage = sourceMessage, let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] { if let sourceMessage = sourceMessage, let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] {
if let peer = peer as? TelegramSecretChat { if let peer = peer as? TelegramSecretChat {
@ -407,6 +409,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
attributes.append(SourceReferenceMessageAttribute(messageId: sourceMessage.id)) attributes.append(SourceReferenceMessageAttribute(messageId: sourceMessage.id))
} }
attributes.append(contentsOf: filterMessageAttributesForForwardedMessage(requestedAttributes))
attributes.append(contentsOf: filterMessageAttributesForForwardedMessage(sourceMessage.attributes)) attributes.append(contentsOf: filterMessageAttributesForForwardedMessage(sourceMessage.attributes))
var sourceReplyMarkup: ReplyMarkupMessageAttribute? = nil var sourceReplyMarkup: ReplyMarkupMessageAttribute? = nil

View File

@ -901,8 +901,19 @@ public final class PendingMessageManager {
var flags: Int32 = 0 var flags: Int32 = 0
if case .forward = content.content {
} else {
flags |= (1 << 7) flags |= (1 << 7)
if let _ = replyMessageId {
flags |= Int32(1 << 0)
}
if let _ = messageEntities {
flags |= Int32(1 << 3)
}
}
for attribute in message.attributes { for attribute in message.attributes {
if let replyAttribute = attribute as? ReplyMessageAttribute { if let replyAttribute = attribute as? ReplyMessageAttribute {
replyMessageId = replyAttribute.messageId.id replyMessageId = replyAttribute.messageId.id
@ -923,13 +934,6 @@ public final class PendingMessageManager {
} }
} }
if let _ = replyMessageId {
flags |= Int32(1 << 0)
}
if let _ = messageEntities {
flags |= Int32(1 << 3)
}
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messageId) let dependencyTag = PendingMessageRequestDependencyTag(messageId: messageId)
let sendMessageRequest: Signal<NetworkRequestResult<Api.Updates>, MTRpcError> let sendMessageRequest: Signal<NetworkRequestResult<Api.Updates>, MTRpcError>
@ -941,7 +945,7 @@ public final class PendingMessageManager {
|> map(NetworkRequestResult.result) |> map(NetworkRequestResult.result)
case let .forward(sourceInfo): case let .forward(sourceInfo):
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) { if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: 0, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer), tag: dependencyTag) sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer), tag: dependencyTag)
|> map(NetworkRequestResult.result) |> map(NetworkRequestResult.result)
} else { } else {
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal")) sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))

View File

@ -16,8 +16,9 @@ private final class ChannelAdminControllerArguments {
let updateFocusedOnRank: (Bool) -> Void let updateFocusedOnRank: (Bool) -> Void
let dismissAdmin: () -> Void let dismissAdmin: () -> Void
let dismissInput: () -> Void let dismissInput: () -> Void
let animateError: () -> Void
init(account: Account, toggleRight: @escaping (TelegramChatAdminRightsFlags, TelegramChatAdminRightsFlags) -> Void, transferOwnership: @escaping () -> Void, updateRank: @escaping (String, String) -> Void, updateFocusedOnRank: @escaping (Bool) -> Void, dismissAdmin: @escaping () -> Void, dismissInput: @escaping () -> Void) { init(account: Account, toggleRight: @escaping (TelegramChatAdminRightsFlags, TelegramChatAdminRightsFlags) -> Void, transferOwnership: @escaping () -> Void, updateRank: @escaping (String, String) -> Void, updateFocusedOnRank: @escaping (Bool) -> Void, dismissAdmin: @escaping () -> Void, dismissInput: @escaping () -> Void, animateError: @escaping () -> Void) {
self.account = account self.account = account
self.toggleRight = toggleRight self.toggleRight = toggleRight
self.transferOwnership = transferOwnership self.transferOwnership = transferOwnership
@ -25,6 +26,7 @@ private final class ChannelAdminControllerArguments {
self.updateFocusedOnRank = updateFocusedOnRank self.updateFocusedOnRank = updateFocusedOnRank
self.dismissAdmin = dismissAdmin self.dismissAdmin = dismissAdmin
self.dismissInput = dismissInput self.dismissInput = dismissInput
self.animateError = animateError
} }
} }
@ -368,7 +370,11 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearButton: enabled, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in return ItemListSingleLineInputItem(theme: theme, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearButton: enabled, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in
arguments.updateRank(text, updatedText) arguments.updateRank(text, updatedText)
}, shouldUpdateText: { text in }, shouldUpdateText: { text in
return !text.containsEmoji if text.containsEmoji {
arguments.animateError()
return false
}
return true
}, updatedFocus: { focus in }, updatedFocus: { focus in
arguments.updateFocusedOnRank(focus) arguments.updateFocusedOnRank(focus)
}, action: { }, action: {
@ -827,6 +833,8 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
presentControllerImpl?(actionSheet, nil) presentControllerImpl?(actionSheet, nil)
}, dismissInput: { }, dismissInput: {
dismissInputImpl?() dismissInputImpl?()
}, animateError: {
errorImpl?()
}) })
let combinedView = context.account.postbox.combinedView(keys: [.peer(peerId: peerId, components: .all), .peer(peerId: adminId, components: .all)]) let combinedView = context.account.postbox.combinedView(keys: [.peer(peerId: peerId, components: .all), .peer(peerId: adminId, components: .all)])

View File

@ -5818,7 +5818,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
strongController.dismiss() strongController.dismiss()
} else if peerId == strongSelf.context.account.peerId { } else if peerId == strongSelf.context.account.peerId {
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in
return .forward(source: id, grouping: .auto) return .forward(source: id, grouping: .auto, attributes: [])
}) })
|> deliverOnMainQueue).start(next: { messageIds in |> deliverOnMainQueue).start(next: { messageIds in
if let strongSelf = self { if let strongSelf = self {

View File

@ -2062,7 +2062,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds { if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
for id in forwardMessageIds { for id in forwardMessageIds {
messages.append(.forward(source: id, grouping: .auto)) messages.append(.forward(source: id, grouping: .auto, attributes: []))
} }
} }

View File

@ -74,6 +74,12 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if let shareButtonNode = strongSelf.shareButtonNode, shareButtonNode.frame.contains(point) { if let shareButtonNode = strongSelf.shareButtonNode, shareButtonNode.frame.contains(point) {
return .fail return .fail
} }
if strongSelf.telegramFile == nil {
if strongSelf.animationNode.frame.contains(point) {
return .waitForDoubleTap
}
}
} }
return .waitForSingleTap return .waitForSingleTap
} }

View File

@ -2,6 +2,7 @@ import Foundation
import UIKit import UIKit
import Display import Display
import AsyncDisplayKit import AsyncDisplayKit
import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
final class ChatSendMessageActionSheetController: ViewController { final class ChatSendMessageActionSheetController: ViewController {
@ -14,6 +15,8 @@ final class ChatSendMessageActionSheetController: ViewController {
private let sendButtonFrame: CGRect private let sendButtonFrame: CGRect
private let textInputNode: EditableTextNode private let textInputNode: EditableTextNode
private var presentationDataDisposable: Disposable?
private var didPlayPresentationAnimation = false private var didPlayPresentationAnimation = false
private let hapticFeedback = HapticFeedback() private let hapticFeedback = HapticFeedback()
@ -26,6 +29,13 @@ final class ChatSendMessageActionSheetController: ViewController {
super.init(navigationBarPresentationData: nil) super.init(navigationBarPresentationData: nil)
self.presentationDataDisposable = (context.sharedContext.presentationData
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
if let strongSelf = self {
strongSelf.controllerNode.updatePresentationData(presentationData)
}
})
self.statusBar.statusBarStyle = .Hide self.statusBar.statusBarStyle = .Hide
self.statusBar.ignoreInCall = true self.statusBar.ignoreInCall = true
} }
@ -34,6 +44,10 @@ final class ChatSendMessageActionSheetController: ViewController {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit {
self.presentationDataDisposable?.dispose()
}
override func loadDisplayNode() { override func loadDisplayNode() {
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, send: { [weak self] in self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, send: { [weak self] in
self?.controllerInteraction?.sendCurrentMessage(false) self?.controllerInteraction?.sendCurrentMessage(false)

View File

@ -82,7 +82,7 @@ private final class ActionSheetItemNode: ASDisplayNode {
} }
final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, UIScrollViewDelegate {
private let presentationData: PresentationData private var presentationData: PresentationData
private let sendButtonFrame: CGRect private let sendButtonFrame: CGRect
private let textFieldFrame: CGRect private let textFieldFrame: CGRect
private let textInputNode: EditableTextNode private let textInputNode: EditableTextNode
@ -141,7 +141,6 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
self.sendButtonNode = HighlightableButtonNode() self.sendButtonNode = HighlightableButtonNode()
self.sendButtonNode.imageNode.displayWithoutProcessing = false self.sendButtonNode.imageNode.displayWithoutProcessing = false
self.sendButtonNode.imageNode.displaysAsynchronously = false self.sendButtonNode.imageNode.displaysAsynchronously = false
self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: [])
self.messageClipNode = ASDisplayNode() self.messageClipNode = ASDisplayNode()
self.messageClipNode.clipsToBounds = true self.messageClipNode.clipsToBounds = true
@ -229,6 +228,35 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
} }
func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark)
} else {
self.effectView.effect = UIBlurEffect(style: .light)
}
if self.presentationData.theme.chatList.searchBarKeyboardColor == .light {
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04)
} else {
self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2)
}
self.contentContainerNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor
self.textCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.inputBackgroundColor
self.buttonCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor
self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: [])
if let toAttributedText = self.textInputNode.attributedText?.mutableCopy() as? NSMutableAttributedString {
toAttributedText.addAttribute(NSAttributedStringKey.foregroundColor, value: self.presentationData.theme.chat.message.outgoing.primaryTextColor, range: NSMakeRange(0, (toAttributedText.string as NSString).length))
self.toMessageTextNode.attributedText = toAttributedText
}
let graphics = PresentationResourcesChat.principalGraphics(self.presentationData.theme, wallpaper: self.presentationData.chatWallpaper)
self.messageBackgroundNode.image = graphics.chatMessageBackgroundOutgoingImage
}
func animateIn() { func animateIn() {
UIView.animate(withDuration: 0.4, animations: { UIView.animate(withDuration: 0.4, animations: {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
@ -270,7 +298,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
self.toMessageTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, removeOnCompletion: false) self.toMessageTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, removeOnCompletion: false)
if let layout = self.validLayout { if let layout = self.validLayout {
let duration = 0.6 let duration = 0.4
self.sendButtonNode.layer.animateScale(from: 0.75, to: 1.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear) self.sendButtonNode.layer.animateScale(from: 0.75, to: 1.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear)
self.sendButtonNode.layer.animatePosition(from: self.sendButtonFrame.center, to: self.sendButtonNode.position, duration: duration, timingFunction: kCAMediaTimingFunctionSpring) self.sendButtonNode.layer.animatePosition(from: self.sendButtonFrame.center, to: self.sendButtonNode.position, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
@ -349,7 +377,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
if let layout = self.validLayout { if let layout = self.validLayout {
let duration = 0.6 let duration = 0.4
self.sendButtonNode.layer.animatePosition(from: self.sendButtonNode.position, to: self.sendButtonFrame.center, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in self.sendButtonNode.layer.animatePosition(from: self.sendButtonNode.position, to: self.sendButtonFrame.center, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
completedButton = true completedButton = true

View File

@ -57,6 +57,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case resetBiometricsData(PresentationTheme) case resetBiometricsData(PresentationTheme)
case optimizeDatabase(PresentationTheme) case optimizeDatabase(PresentationTheme)
case photoPreview(PresentationTheme, Bool) case photoPreview(PresentationTheme, Bool)
case playAnimatedEmojiOnce(PresentationTheme, Bool)
case exportTheme(PresentationTheme) case exportTheme(PresentationTheme)
case versionInfo(PresentationTheme) case versionInfo(PresentationTheme)
@ -70,7 +71,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.logging.rawValue return DebugControllerSection.logging.rawValue
case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .resetBiometricsData, .optimizeDatabase, .photoPreview, .exportTheme: case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .resetBiometricsData, .optimizeDatabase, .photoPreview, .playAnimatedEmojiOnce, .exportTheme:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .versionInfo: case .versionInfo:
return DebugControllerSection.info.rawValue return DebugControllerSection.info.rawValue
@ -119,10 +120,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 18 return 18
case .photoPreview: case .photoPreview:
return 19 return 19
case .exportTheme: case .playAnimatedEmojiOnce:
return 20 return 20
case .versionInfo: case .exportTheme:
return 21 return 21
case .versionInfo:
return 22
} }
} }
@ -469,6 +472,16 @@ private enum DebugControllerEntry: ItemListNodeEntry {
}) })
}).start() }).start()
}) })
case let .playAnimatedEmojiOnce(theme, value):
return ItemListSwitchItem(theme: theme, title: "Play Emoji Once", value: value, sectionId: self.section, style: .blocks, updated: { value in
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
settings.playAnimatedEmojiOnce = value
return settings
})
}).start()
})
case let .exportTheme(theme): case let .exportTheme(theme):
return ItemListActionItem(theme: theme, title: "Export Theme", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { return ItemListActionItem(theme: theme, title: "Export Theme", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
guard let context = arguments.context else { guard let context = arguments.context else {
@ -536,6 +549,7 @@ private func debugControllerEntries(presentationData: PresentationData, loggingS
entries.append(.resetHoles(presentationData.theme)) entries.append(.resetHoles(presentationData.theme))
entries.append(.optimizeDatabase(presentationData.theme)) entries.append(.optimizeDatabase(presentationData.theme))
entries.append(.photoPreview(presentationData.theme, experimentalSettings.chatListPhotos)) entries.append(.photoPreview(presentationData.theme, experimentalSettings.chatListPhotos))
entries.append(.playAnimatedEmojiOnce(presentationData.theme, experimentalSettings.playAnimatedEmojiOnce))
entries.append(.versionInfo(presentationData.theme)) entries.append(.versionInfo(presentationData.theme))

View File

@ -654,7 +654,7 @@ public class PeerMediaCollectionController: TelegramController {
if peerId == strongSelf.context.account.peerId { if peerId == strongSelf.context.account.peerId {
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in
return .forward(source: id, grouping: .auto) return .forward(source: id, grouping: .auto, attributes: [])
}) })
|> deliverOnMainQueue).start(next: { [weak self] messageIds in |> deliverOnMainQueue).start(next: { [weak self] messageIds in
if let strongSelf = self { if let strongSelf = self {

View File

@ -425,7 +425,7 @@ public final class ShareController: ViewController {
messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)) messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
} }
for message in messages { for message in messages {
messagesToEnqueue.append(.forward(source: message.id, grouping: .auto)) messagesToEnqueue.append(.forward(source: message.id, grouping: .auto, attributes: []))
} }
let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue).start() let _ = enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue).start()
} }

View File

@ -212,7 +212,7 @@ final class WatchSendMessageHandler: WatchRequestHandler {
} else if let args = subscription as? TGBridgeSendForwardedMessageSubscription { } else if let args = subscription as? TGBridgeSendForwardedMessageSubscription {
let peerId = makePeerIdFromBridgeIdentifier(args.targetPeerId) let peerId = makePeerIdFromBridgeIdentifier(args.targetPeerId)
if let forwardPeerId = makePeerIdFromBridgeIdentifier(args.peerId) { if let forwardPeerId = makePeerIdFromBridgeIdentifier(args.peerId) {
messageSignal = .single((.forward(source: MessageId(peerId: forwardPeerId, namespace: Namespaces.Message.Cloud, id: args.messageId), grouping: .none), peerId)) messageSignal = .single((.forward(source: MessageId(peerId: forwardPeerId, namespace: Namespaces.Message.Cloud, id: args.messageId), grouping: .none, attributes: []), peerId))
} }
} }

View File

@ -7,16 +7,18 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
public var skipReadHistory: Bool public var skipReadHistory: Bool
public var crashOnLongQueries: Bool public var crashOnLongQueries: Bool
public var chatListPhotos: Bool public var chatListPhotos: Bool
public var playAnimatedEmojiOnce: Bool
public static var defaultSettings: ExperimentalUISettings { public static var defaultSettings: ExperimentalUISettings {
return ExperimentalUISettings(keepChatNavigationStack: false, skipReadHistory: false, crashOnLongQueries: false, chatListPhotos: false) return ExperimentalUISettings(keepChatNavigationStack: false, skipReadHistory: false, crashOnLongQueries: false, chatListPhotos: false, playAnimatedEmojiOnce: false)
} }
public init(keepChatNavigationStack: Bool, skipReadHistory: Bool, crashOnLongQueries: Bool, chatListPhotos: Bool) { public init(keepChatNavigationStack: Bool, skipReadHistory: Bool, crashOnLongQueries: Bool, chatListPhotos: Bool, playAnimatedEmojiOnce: Bool) {
self.keepChatNavigationStack = keepChatNavigationStack self.keepChatNavigationStack = keepChatNavigationStack
self.skipReadHistory = skipReadHistory self.skipReadHistory = skipReadHistory
self.crashOnLongQueries = crashOnLongQueries self.crashOnLongQueries = crashOnLongQueries
self.chatListPhotos = chatListPhotos self.chatListPhotos = chatListPhotos
self.playAnimatedEmojiOnce = playAnimatedEmojiOnce
} }
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
@ -24,6 +26,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
self.skipReadHistory = decoder.decodeInt32ForKey("skipReadHistory", orElse: 0) != 0 self.skipReadHistory = decoder.decodeInt32ForKey("skipReadHistory", orElse: 0) != 0
self.crashOnLongQueries = decoder.decodeInt32ForKey("crashOnLongQueries", orElse: 0) != 0 self.crashOnLongQueries = decoder.decodeInt32ForKey("crashOnLongQueries", orElse: 0) != 0
self.chatListPhotos = decoder.decodeInt32ForKey("chatListPhotos", orElse: 0) != 0 self.chatListPhotos = decoder.decodeInt32ForKey("chatListPhotos", orElse: 0) != 0
self.playAnimatedEmojiOnce = decoder.decodeInt32ForKey("playAnimatedEmojiOnce", orElse: 0) != 0
} }
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
@ -31,6 +34,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
encoder.encodeInt32(self.skipReadHistory ? 1 : 0, forKey: "skipReadHistory") encoder.encodeInt32(self.skipReadHistory ? 1 : 0, forKey: "skipReadHistory")
encoder.encodeInt32(self.crashOnLongQueries ? 1 : 0, forKey: "crashOnLongQueries") encoder.encodeInt32(self.crashOnLongQueries ? 1 : 0, forKey: "crashOnLongQueries")
encoder.encodeInt32(self.chatListPhotos ? 1 : 0, forKey: "chatListPhotos") encoder.encodeInt32(self.chatListPhotos ? 1 : 0, forKey: "chatListPhotos")
encoder.encodeInt32(self.playAnimatedEmojiOnce ? 1 : 0, forKey: "playAnimatedEmojiOnce")
} }
public func isEqual(to: PreferencesEntry) -> Bool { public func isEqual(to: PreferencesEntry) -> Bool {