mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit 'c851ec30464ca87cb8c908e90ab9251d472a19d0'
This commit is contained in:
commit
bffc9534e4
@ -6760,6 +6760,7 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Conversation.ForwardOptions.Text" = "What whould you like to do with %1$@ from %2$@?";
|
||||
"Conversation.ForwardOptions.TextPersonal" = "What whould you like to do with %1$@ from your chat with %2$@?";
|
||||
"Conversation.ForwardOptions.TextSaved" = "What whould you like to do with %1$@ from your Saved Messages?";
|
||||
"Conversation.ForwardOptions.ShowOptions" = "Show Forwarding Options";
|
||||
"Conversation.ForwardOptions.CancelForwarding" = "Cancel Forwarding";
|
||||
|
||||
|
@ -710,6 +710,9 @@ final class CallListControllerNode: ASDisplayNode {
|
||||
self.emptyButtonTextNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.25)
|
||||
self.emptyButtonNode.isUserInteractionEnabled = !isHidden
|
||||
|
||||
self.listNode.alpha = 1.0 - alpha
|
||||
self.listNode.layer.animateAlpha(from: 1.0 - previousAlpha, to: 1.0 - alpha, duration: 0.25)
|
||||
|
||||
if !isHidden {
|
||||
let type = self.currentLocationAndType.scope
|
||||
let emptyText: String
|
||||
|
@ -2248,12 +2248,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
switch item.content {
|
||||
case let .peer(peerData):
|
||||
if let peer = peerData.messages.last?.author {
|
||||
if case let .user(user) = peer, let emojiStatus = user.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isScam {
|
||||
if peer.isScam {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
||||
} else if peer.isFake {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||
} else if case let .user(user) = peer, let emojiStatus = user.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isVerified {
|
||||
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||
@ -2264,12 +2264,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
break
|
||||
}
|
||||
} else if case let .chat(itemPeer) = contentPeer, let peer = itemPeer.chatMainPeer {
|
||||
if case let .user(user) = peer, let emojiStatus = user.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isScam {
|
||||
if peer.isScam {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
||||
} else if peer.isFake {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||
} else if case let .user(user) = peer, let emojiStatus = user.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isVerified {
|
||||
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||
|
@ -440,11 +440,10 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
||||
});
|
||||
};
|
||||
|
||||
NSTimeInterval delta = CFAbsoluteTimeGetCurrent() - _captureStartTime;
|
||||
if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 0.8)
|
||||
if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 1.5)
|
||||
startRecording();
|
||||
else
|
||||
TGDispatchAfter(0.8 - delta, [[PGCamera cameraQueue] _dispatch_queue], startRecording);
|
||||
TGDispatchAfter(1.5, [[PGCamera cameraQueue] _dispatch_queue], startRecording);
|
||||
|
||||
TGDispatchOnMainThread(^
|
||||
{
|
||||
@ -501,6 +500,8 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
||||
{
|
||||
strongSelf.captureSession.currentMode = cameraMode;
|
||||
|
||||
_captureStartTime = CFAbsoluteTimeGetCurrent();
|
||||
|
||||
if (strongSelf.finishedModeChange != nil)
|
||||
strongSelf.finishedModeChange();
|
||||
|
||||
|
@ -2214,7 +2214,7 @@ final class StorageUsageScreenComponent: Component {
|
||||
|
||||
let clearingSize = CGSize(width: availableSize.width, height: availableSize.height)
|
||||
clearingNode.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - clearingSize.width) / 2.0), y: floor((availableSize.height - clearingSize.height) / 2.0)), size: clearingSize)
|
||||
clearingNode.updateLayout(size: clearingSize, transition: .immediate)
|
||||
clearingNode.updateLayout(size: clearingSize, bottomInset: environment.safeInsets.bottom, transition: .immediate)
|
||||
|
||||
if animateIn {
|
||||
clearingNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.4)
|
||||
@ -3494,7 +3494,7 @@ private class StorageUsageClearProgressOverlayNode: ASDisplayNode {
|
||||
|
||||
private let progressDisposable = MetaDisposable()
|
||||
|
||||
private var validLayout: CGSize?
|
||||
private var validLayout: (CGSize, CGFloat)?
|
||||
|
||||
init(presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
@ -3547,13 +3547,13 @@ private class StorageUsageClearProgressOverlayNode: ASDisplayNode {
|
||||
func setProgress(_ progress: Float) {
|
||||
self.progress = progress
|
||||
|
||||
if let size = self.validLayout {
|
||||
self.updateLayout(size: size, transition: .animated(duration: 0.5, curve: .linear))
|
||||
if let (size, bottomInset) = self.validLayout {
|
||||
self.updateLayout(size: size, bottomInset: bottomInset, transition: .animated(duration: 0.5, curve: .linear))
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = size
|
||||
func updateLayout(size: CGSize, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, bottomInset)
|
||||
|
||||
transition.updateFrame(view: self.blurredView, frame: CGRect(origin: CGPoint(), size: size))
|
||||
self.blurredView.update(size: size, transition: transition)
|
||||
@ -3569,9 +3569,14 @@ private class StorageUsageClearProgressOverlayNode: ASDisplayNode {
|
||||
self.animationNode.frame = animationFrame
|
||||
self.animationNode.updateLayout(size: imageSize)
|
||||
|
||||
let progressFrame = CGRect(x: inset, y: size.height - inset - progressHeight, width: size.width - inset * 2.0, height: progressHeight)
|
||||
var bottomInset = bottomInset
|
||||
if bottomInset.isZero {
|
||||
bottomInset = inset
|
||||
}
|
||||
|
||||
let progressFrame = CGRect(x: inset, y: size.height - bottomInset - progressHeight, width: size.width - inset * 2.0, height: progressHeight)
|
||||
self.progressBackgroundNode.frame = progressFrame
|
||||
let progressForegroundFrame = CGRect(x: inset, y: size.height - inset - progressHeight, width: floorToScreenPixels(progressFrame.width * CGFloat(self.progress)), height: progressHeight)
|
||||
let progressForegroundFrame = CGRect(x: inset, y: size.height - bottomInset - progressHeight, width: floorToScreenPixels(progressFrame.width * CGFloat(self.progress)), height: progressHeight)
|
||||
if !self.progressForegroundNode.frame.origin.x.isZero {
|
||||
transition.updateFrame(node: self.progressForegroundNode, frame: progressForegroundFrame, beginWithCurrentState: true)
|
||||
} else {
|
||||
|
@ -2114,18 +2114,18 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
||||
if #available(iOS 10.0, *) {
|
||||
var startCallContacts: [INPerson]?
|
||||
var startCallIsVideo = false
|
||||
var isVideo = false
|
||||
if let startCallIntent = userActivity.interaction?.intent as? SupportedStartCallIntent {
|
||||
startCallContacts = startCallIntent.contacts
|
||||
startCallIsVideo = false
|
||||
isVideo = false
|
||||
} else if let startCallIntent = userActivity.interaction?.intent as? SupportedStartVideoCallIntent {
|
||||
startCallContacts = startCallIntent.contacts
|
||||
startCallIsVideo = true
|
||||
isVideo = true
|
||||
}
|
||||
|
||||
if let startCallContacts = startCallContacts {
|
||||
let startCall: (Int64) -> Void = { userId in
|
||||
self.startCallWhenReady(accountId: nil, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), isVideo: startCallIsVideo)
|
||||
let startCall: (PeerId) -> Void = { peerId in
|
||||
self.startCallWhenReady(accountId: nil, peerId: peerId, isVideo: isVideo)
|
||||
}
|
||||
|
||||
func cleanPhoneNumber(_ text: String) -> String {
|
||||
@ -2163,20 +2163,20 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
let _ = (contactByIdentifier |> deliverOnMainQueue).start(next: { peerByContact in
|
||||
var processed = false
|
||||
if let peerByContact = peerByContact {
|
||||
startCall(peerByContact.id.id._internalGetInt64Value())
|
||||
startCall(peerByContact.id)
|
||||
processed = true
|
||||
} else if let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
||||
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
||||
if let userId = Int64(string) {
|
||||
startCall(userId)
|
||||
if let value = Int64(string) {
|
||||
startCall(PeerId(value))
|
||||
processed = true
|
||||
}
|
||||
}
|
||||
if !processed, let handle = contact.personHandle, let value = handle.value {
|
||||
switch handle.type {
|
||||
case .unknown:
|
||||
if let userId = Int64(value) {
|
||||
startCall(userId)
|
||||
if let value = Int64(value) {
|
||||
startCall(PeerId(value))
|
||||
processed = true
|
||||
}
|
||||
case .phoneNumber:
|
||||
@ -2200,7 +2200,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
startCall(peerId.id._internalGetInt64Value())
|
||||
startCall(peerId)
|
||||
}
|
||||
})
|
||||
processed = true
|
||||
@ -2216,8 +2216,8 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
} else if let sendMessageIntent = userActivity.interaction?.intent as? INSendMessageIntent {
|
||||
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
||||
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
||||
if let userId = Int64(string) {
|
||||
self.openChatWhenReady(accountId: nil, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), threadId: nil, activateInput: true)
|
||||
if let value = Int64(string) {
|
||||
self.openChatWhenReady(accountId: nil, peerId: PeerId(value), threadId: nil, activateInput: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6927,7 +6927,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if (isPremium || maybeSuggestPremium) && !isHidden {
|
||||
return chatTranslationState(context: context, peerId: peerId)
|
||||
|> map { translationState -> ChatPresentationTranslationState? in
|
||||
if let translationState, !translationState.fromLang.isEmpty {
|
||||
if let translationState, !translationState.fromLang.isEmpty && (translationState.fromLang != baseLanguageCode || translationState.isEnabled) {
|
||||
return ChatPresentationTranslationState(isEnabled: translationState.isEnabled, fromLang: translationState.fromLang, toLang: translationState.toLang ?? baseLanguageCode)
|
||||
} else {
|
||||
return nil
|
||||
|
@ -1050,6 +1050,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
var isEmoji = false
|
||||
if let _ = telegramDice {
|
||||
imageSize = displaySize
|
||||
|
@ -1354,6 +1354,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
var tmpWidth: CGFloat
|
||||
if allowFullWidth {
|
||||
tmpWidth = baseWidth
|
||||
|
@ -362,6 +362,10 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
var layoutInsets = layoutConstants.instantVideo.insets
|
||||
if dateHeaderAtBottom {
|
||||
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
||||
|
@ -513,6 +513,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
var layoutInsets = UIEdgeInsets(top: mergedTop.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, left: 0.0, bottom: mergedBottom.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, right: 0.0)
|
||||
if dateHeaderAtBottom {
|
||||
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
||||
|
@ -86,7 +86,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
let messageIds: [MessageId]
|
||||
private var messages: [Message] = []
|
||||
private var authors: String?
|
||||
private var sourcePeer: (isPersonal: Bool, displayTitle: String)?
|
||||
private var sourcePeer: (peerId: PeerId, displayTitle: String)?
|
||||
|
||||
let closeButton: HighlightableButtonNode
|
||||
let lineNode: ASImageNode
|
||||
@ -172,7 +172,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
var uniquePeerIds = Set<PeerId>()
|
||||
var title = ""
|
||||
var text = NSMutableAttributedString(string: "")
|
||||
var sourcePeer: (Bool, String)?
|
||||
var sourcePeer: (PeerId, String)?
|
||||
for message in messages {
|
||||
if let author = message.forwardInfo?.author ?? message.effectiveAuthor, !uniquePeerIds.contains(author.id) {
|
||||
uniquePeerIds.insert(author.id)
|
||||
@ -186,7 +186,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
}
|
||||
if let peer = message.peers[message.id.peerId] {
|
||||
sourcePeer = (peer.id.namespace == Namespaces.Peer.CloudUser, EnginePeer(peer).displayTitle(strings: strongSelf.strings, displayOrder: strongSelf.nameDisplayOrder))
|
||||
sourcePeer = (peer.id, EnginePeer(peer).displayTitle(strings: strongSelf.strings, displayOrder: strongSelf.nameDisplayOrder))
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,12 +361,19 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
|
||||
@objc func closePressed() {
|
||||
guard let (isPersonal, peerDisplayTitle) = self.sourcePeer else {
|
||||
guard let (peerId, peerDisplayTitle) = self.sourcePeer else {
|
||||
return
|
||||
}
|
||||
let messageCount = Int32(self.messageIds.count)
|
||||
let messages = self.strings.Conversation_ForwardOptions_Messages(messageCount)
|
||||
let string = isPersonal ? self.strings.Conversation_ForwardOptions_TextPersonal(messages, peerDisplayTitle) : self.strings.Conversation_ForwardOptions_Text(messages, peerDisplayTitle)
|
||||
let string: PresentationStrings.FormattedString
|
||||
if peerId == self.context.account.peerId {
|
||||
string = self.strings.Conversation_ForwardOptions_TextSaved(messages)
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
string = self.strings.Conversation_ForwardOptions_TextPersonal(messages, peerDisplayTitle)
|
||||
} else {
|
||||
string = self.strings.Conversation_ForwardOptions_Text(messages, peerDisplayTitle)
|
||||
}
|
||||
|
||||
let font = Font.regular(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
|
||||
let boldFont = Font.semibold(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
|
||||
|
@ -3703,9 +3703,24 @@ private class DynamicIslandBlurNode: ASDisplayNode {
|
||||
private let fadeNode = ASDisplayNode()
|
||||
private let gradientNode = ASImageNode()
|
||||
|
||||
private var hierarchyTrackingNode: HierarchyTrackingNode?
|
||||
|
||||
deinit {
|
||||
self.animator?.stopAnimation(true)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let hierarchyTrackingNode = HierarchyTrackingNode({ [weak self] value in
|
||||
if !value {
|
||||
self?.animator?.stopAnimation(true)
|
||||
self?.animator = nil
|
||||
}
|
||||
})
|
||||
self.hierarchyTrackingNode = hierarchyTrackingNode
|
||||
self.addSubnode(hierarchyTrackingNode)
|
||||
|
||||
self.fadeNode.backgroundColor = .black
|
||||
self.fadeNode.alpha = 0.0
|
||||
|
||||
@ -3733,25 +3748,33 @@ private class DynamicIslandBlurNode: ASDisplayNode {
|
||||
self.addSubnode(self.fadeNode)
|
||||
}
|
||||
|
||||
func prepare() {
|
||||
guard let effectView = self.effectView, effectView.layer.animation(forKey: "effect") == nil else {
|
||||
return
|
||||
private var animator: UIViewPropertyAnimator?
|
||||
|
||||
func prepare() -> Bool {
|
||||
guard self.animator == nil else {
|
||||
return false
|
||||
}
|
||||
UIView.animate(withDuration: 1.0) {
|
||||
effectView.effect = UIBlurEffect(style: .dark)
|
||||
let animator = UIViewPropertyAnimator(duration: 1.0, curve: .linear)
|
||||
self.animator = animator
|
||||
self.effectView?.effect = nil
|
||||
animator.addAnimations { [weak self] in
|
||||
self?.effectView?.effect = UIBlurEffect(style: .dark)
|
||||
}
|
||||
effectView.layer.speed = 0.0
|
||||
return true
|
||||
}
|
||||
|
||||
func update(_ value: CGFloat) {
|
||||
let fadeAlpha = min(1.0, max(0.0, -0.25 + value * 1.55))
|
||||
if value > 0.0 {
|
||||
self.prepare()
|
||||
self.effectView?.layer.timeOffset = max(0.0, -0.1 + value * 1.1)
|
||||
var value = value
|
||||
let updated = self.prepare()
|
||||
if value > 0.99 && updated {
|
||||
value = 0.99
|
||||
}
|
||||
self.animator?.fractionComplete = max(0.0, -0.1 + value * 1.1)
|
||||
} else {
|
||||
self.effectView?.layer.removeAllAnimations()
|
||||
self.effectView?.layer.speed = 1.0
|
||||
self.effectView?.layer.timeOffset = 0.0
|
||||
self.animator?.stopAnimation(true)
|
||||
self.animator = nil
|
||||
self.effectView?.effect = nil
|
||||
}
|
||||
self.fadeNode.alpha = fadeAlpha
|
||||
|
Loading…
x
Reference in New Issue
Block a user