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.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.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.ShowOptions" = "Show Forwarding Options";
|
||||||
"Conversation.ForwardOptions.CancelForwarding" = "Cancel Forwarding";
|
"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.emptyButtonTextNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: 0.25)
|
||||||
self.emptyButtonNode.isUserInteractionEnabled = !isHidden
|
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 {
|
if !isHidden {
|
||||||
let type = self.currentLocationAndType.scope
|
let type = self.currentLocationAndType.scope
|
||||||
let emptyText: String
|
let emptyText: String
|
||||||
|
@ -2248,12 +2248,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
switch item.content {
|
switch item.content {
|
||||||
case let .peer(peerData):
|
case let .peer(peerData):
|
||||||
if let peer = peerData.messages.last?.author {
|
if let peer = peerData.messages.last?.author {
|
||||||
if case let .user(user) = peer, let emojiStatus = user.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
if peer.isScam {
|
||||||
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 {
|
|
||||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
||||||
} else if peer.isFake {
|
} else if peer.isFake {
|
||||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
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 {
|
} else if peer.isVerified {
|
||||||
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||||
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
@ -2264,12 +2264,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if case let .chat(itemPeer) = contentPeer, let peer = itemPeer.chatMainPeer {
|
} else if case let .chat(itemPeer) = contentPeer, let peer = itemPeer.chatMainPeer {
|
||||||
if case let .user(user) = peer, let emojiStatus = user.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
if peer.isScam {
|
||||||
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 {
|
|
||||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
||||||
} else if peer.isFake {
|
} else if peer.isFake {
|
||||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
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 {
|
} else if peer.isVerified {
|
||||||
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||||
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
|
@ -440,11 +440,10 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
NSTimeInterval delta = CFAbsoluteTimeGetCurrent() - _captureStartTime;
|
if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 1.5)
|
||||||
if (CFAbsoluteTimeGetCurrent() - _captureStartTime > 0.8)
|
|
||||||
startRecording();
|
startRecording();
|
||||||
else
|
else
|
||||||
TGDispatchAfter(0.8 - delta, [[PGCamera cameraQueue] _dispatch_queue], startRecording);
|
TGDispatchAfter(1.5, [[PGCamera cameraQueue] _dispatch_queue], startRecording);
|
||||||
|
|
||||||
TGDispatchOnMainThread(^
|
TGDispatchOnMainThread(^
|
||||||
{
|
{
|
||||||
@ -500,6 +499,8 @@ NSString *const PGCameraAdjustingFocusKey = @"adjustingFocus";
|
|||||||
[[PGCamera cameraQueue] dispatch:^
|
[[PGCamera cameraQueue] dispatch:^
|
||||||
{
|
{
|
||||||
strongSelf.captureSession.currentMode = cameraMode;
|
strongSelf.captureSession.currentMode = cameraMode;
|
||||||
|
|
||||||
|
_captureStartTime = CFAbsoluteTimeGetCurrent();
|
||||||
|
|
||||||
if (strongSelf.finishedModeChange != nil)
|
if (strongSelf.finishedModeChange != nil)
|
||||||
strongSelf.finishedModeChange();
|
strongSelf.finishedModeChange();
|
||||||
|
@ -2214,7 +2214,7 @@ final class StorageUsageScreenComponent: Component {
|
|||||||
|
|
||||||
let clearingSize = CGSize(width: availableSize.width, height: availableSize.height)
|
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.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 {
|
if animateIn {
|
||||||
clearingNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.4)
|
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 let progressDisposable = MetaDisposable()
|
||||||
|
|
||||||
private var validLayout: CGSize?
|
private var validLayout: (CGSize, CGFloat)?
|
||||||
|
|
||||||
init(presentationData: PresentationData) {
|
init(presentationData: PresentationData) {
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
@ -3547,13 +3547,13 @@ private class StorageUsageClearProgressOverlayNode: ASDisplayNode {
|
|||||||
func setProgress(_ progress: Float) {
|
func setProgress(_ progress: Float) {
|
||||||
self.progress = progress
|
self.progress = progress
|
||||||
|
|
||||||
if let size = self.validLayout {
|
if let (size, bottomInset) = self.validLayout {
|
||||||
self.updateLayout(size: size, transition: .animated(duration: 0.5, curve: .linear))
|
self.updateLayout(size: size, bottomInset: bottomInset, transition: .animated(duration: 0.5, curve: .linear))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
|
func updateLayout(size: CGSize, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
self.validLayout = size
|
self.validLayout = (size, bottomInset)
|
||||||
|
|
||||||
transition.updateFrame(view: self.blurredView, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(view: self.blurredView, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
self.blurredView.update(size: size, transition: transition)
|
self.blurredView.update(size: size, transition: transition)
|
||||||
@ -3569,9 +3569,14 @@ private class StorageUsageClearProgressOverlayNode: ASDisplayNode {
|
|||||||
self.animationNode.frame = animationFrame
|
self.animationNode.frame = animationFrame
|
||||||
self.animationNode.updateLayout(size: imageSize)
|
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
|
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 {
|
if !self.progressForegroundNode.frame.origin.x.isZero {
|
||||||
transition.updateFrame(node: self.progressForegroundNode, frame: progressForegroundFrame, beginWithCurrentState: true)
|
transition.updateFrame(node: self.progressForegroundNode, frame: progressForegroundFrame, beginWithCurrentState: true)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2114,18 +2114,18 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
var startCallContacts: [INPerson]?
|
var startCallContacts: [INPerson]?
|
||||||
var startCallIsVideo = false
|
var isVideo = false
|
||||||
if let startCallIntent = userActivity.interaction?.intent as? SupportedStartCallIntent {
|
if let startCallIntent = userActivity.interaction?.intent as? SupportedStartCallIntent {
|
||||||
startCallContacts = startCallIntent.contacts
|
startCallContacts = startCallIntent.contacts
|
||||||
startCallIsVideo = false
|
isVideo = false
|
||||||
} else if let startCallIntent = userActivity.interaction?.intent as? SupportedStartVideoCallIntent {
|
} else if let startCallIntent = userActivity.interaction?.intent as? SupportedStartVideoCallIntent {
|
||||||
startCallContacts = startCallIntent.contacts
|
startCallContacts = startCallIntent.contacts
|
||||||
startCallIsVideo = true
|
isVideo = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let startCallContacts = startCallContacts {
|
if let startCallContacts = startCallContacts {
|
||||||
let startCall: (Int64) -> Void = { userId in
|
let startCall: (PeerId) -> Void = { peerId in
|
||||||
self.startCallWhenReady(accountId: nil, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), isVideo: startCallIsVideo)
|
self.startCallWhenReady(accountId: nil, peerId: peerId, isVideo: isVideo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanPhoneNumber(_ text: String) -> String {
|
func cleanPhoneNumber(_ text: String) -> String {
|
||||||
@ -2163,20 +2163,20 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
let _ = (contactByIdentifier |> deliverOnMainQueue).start(next: { peerByContact in
|
let _ = (contactByIdentifier |> deliverOnMainQueue).start(next: { peerByContact in
|
||||||
var processed = false
|
var processed = false
|
||||||
if let peerByContact = peerByContact {
|
if let peerByContact = peerByContact {
|
||||||
startCall(peerByContact.id.id._internalGetInt64Value())
|
startCall(peerByContact.id)
|
||||||
processed = true
|
processed = true
|
||||||
} else if let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
} else if let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
||||||
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
||||||
if let userId = Int64(string) {
|
if let value = Int64(string) {
|
||||||
startCall(userId)
|
startCall(PeerId(value))
|
||||||
processed = true
|
processed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !processed, let handle = contact.personHandle, let value = handle.value {
|
if !processed, let handle = contact.personHandle, let value = handle.value {
|
||||||
switch handle.type {
|
switch handle.type {
|
||||||
case .unknown:
|
case .unknown:
|
||||||
if let userId = Int64(value) {
|
if let value = Int64(value) {
|
||||||
startCall(userId)
|
startCall(PeerId(value))
|
||||||
processed = true
|
processed = true
|
||||||
}
|
}
|
||||||
case .phoneNumber:
|
case .phoneNumber:
|
||||||
@ -2200,7 +2200,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { peerId in
|
|> deliverOnMainQueue).start(next: { peerId in
|
||||||
if let peerId = peerId {
|
if let peerId = peerId {
|
||||||
startCall(peerId.id._internalGetInt64Value())
|
startCall(peerId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
processed = true
|
processed = true
|
||||||
@ -2216,8 +2216,8 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
} else if let sendMessageIntent = userActivity.interaction?.intent as? INSendMessageIntent {
|
} else if let sendMessageIntent = userActivity.interaction?.intent as? INSendMessageIntent {
|
||||||
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
||||||
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
||||||
if let userId = Int64(string) {
|
if let value = Int64(string) {
|
||||||
self.openChatWhenReady(accountId: nil, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), threadId: nil, activateInput: true)
|
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 {
|
if (isPremium || maybeSuggestPremium) && !isHidden {
|
||||||
return chatTranslationState(context: context, peerId: peerId)
|
return chatTranslationState(context: context, peerId: peerId)
|
||||||
|> map { translationState -> ChatPresentationTranslationState? in
|
|> 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)
|
return ChatPresentationTranslationState(isEnabled: translationState.isEnabled, fromLang: translationState.fromLang, toLang: translationState.toLang ?? baseLanguageCode)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -1050,6 +1050,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||||
|
needsShareButton = false
|
||||||
|
}
|
||||||
|
|
||||||
var isEmoji = false
|
var isEmoji = false
|
||||||
if let _ = telegramDice {
|
if let _ = telegramDice {
|
||||||
imageSize = displaySize
|
imageSize = displaySize
|
||||||
|
@ -1353,6 +1353,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
needsShareButton = false
|
needsShareButton = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||||
|
needsShareButton = false
|
||||||
|
}
|
||||||
|
|
||||||
var tmpWidth: CGFloat
|
var tmpWidth: CGFloat
|
||||||
if allowFullWidth {
|
if allowFullWidth {
|
||||||
|
@ -362,6 +362,10 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||||
|
needsShareButton = false
|
||||||
|
}
|
||||||
|
|
||||||
var layoutInsets = layoutConstants.instantVideo.insets
|
var layoutInsets = layoutConstants.instantVideo.insets
|
||||||
if dateHeaderAtBottom {
|
if dateHeaderAtBottom {
|
||||||
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
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)
|
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 {
|
if dateHeaderAtBottom {
|
||||||
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
layoutInsets.top += layoutConstants.timestampHeaderHeight
|
||||||
|
@ -86,7 +86,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
let messageIds: [MessageId]
|
let messageIds: [MessageId]
|
||||||
private var messages: [Message] = []
|
private var messages: [Message] = []
|
||||||
private var authors: String?
|
private var authors: String?
|
||||||
private var sourcePeer: (isPersonal: Bool, displayTitle: String)?
|
private var sourcePeer: (peerId: PeerId, displayTitle: String)?
|
||||||
|
|
||||||
let closeButton: HighlightableButtonNode
|
let closeButton: HighlightableButtonNode
|
||||||
let lineNode: ASImageNode
|
let lineNode: ASImageNode
|
||||||
@ -172,7 +172,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
var uniquePeerIds = Set<PeerId>()
|
var uniquePeerIds = Set<PeerId>()
|
||||||
var title = ""
|
var title = ""
|
||||||
var text = NSMutableAttributedString(string: "")
|
var text = NSMutableAttributedString(string: "")
|
||||||
var sourcePeer: (Bool, String)?
|
var sourcePeer: (PeerId, String)?
|
||||||
for message in messages {
|
for message in messages {
|
||||||
if let author = message.forwardInfo?.author ?? message.effectiveAuthor, !uniquePeerIds.contains(author.id) {
|
if let author = message.forwardInfo?.author ?? message.effectiveAuthor, !uniquePeerIds.contains(author.id) {
|
||||||
uniquePeerIds.insert(author.id)
|
uniquePeerIds.insert(author.id)
|
||||||
@ -186,7 +186,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let peer = message.peers[message.id.peerId] {
|
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,13 +361,20 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func closePressed() {
|
@objc func closePressed() {
|
||||||
guard let (isPersonal, peerDisplayTitle) = self.sourcePeer else {
|
guard let (peerId, peerDisplayTitle) = self.sourcePeer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let messageCount = Int32(self.messageIds.count)
|
let messageCount = Int32(self.messageIds.count)
|
||||||
let messages = self.strings.Conversation_ForwardOptions_Messages(messageCount)
|
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 font = Font.regular(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
|
||||||
let boldFont = Font.semibold(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
|
let boldFont = Font.semibold(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
|
||||||
let body = MarkdownAttributeSet(font: font, textColor: self.theme.actionSheet.secondaryTextColor)
|
let body = MarkdownAttributeSet(font: font, textColor: self.theme.actionSheet.secondaryTextColor)
|
||||||
|
@ -3702,10 +3702,25 @@ private class DynamicIslandBlurNode: ASDisplayNode {
|
|||||||
private var effectView: UIVisualEffectView?
|
private var effectView: UIVisualEffectView?
|
||||||
private let fadeNode = ASDisplayNode()
|
private let fadeNode = ASDisplayNode()
|
||||||
private let gradientNode = ASImageNode()
|
private let gradientNode = ASImageNode()
|
||||||
|
|
||||||
|
private var hierarchyTrackingNode: HierarchyTrackingNode?
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.animator?.stopAnimation(true)
|
||||||
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
super.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.backgroundColor = .black
|
||||||
self.fadeNode.alpha = 0.0
|
self.fadeNode.alpha = 0.0
|
||||||
|
|
||||||
@ -3733,25 +3748,33 @@ private class DynamicIslandBlurNode: ASDisplayNode {
|
|||||||
self.addSubnode(self.fadeNode)
|
self.addSubnode(self.fadeNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepare() {
|
private var animator: UIViewPropertyAnimator?
|
||||||
guard let effectView = self.effectView, effectView.layer.animation(forKey: "effect") == nil else {
|
|
||||||
return
|
func prepare() -> Bool {
|
||||||
|
guard self.animator == nil else {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
UIView.animate(withDuration: 1.0) {
|
let animator = UIViewPropertyAnimator(duration: 1.0, curve: .linear)
|
||||||
effectView.effect = UIBlurEffect(style: .dark)
|
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) {
|
func update(_ value: CGFloat) {
|
||||||
let fadeAlpha = min(1.0, max(0.0, -0.25 + value * 1.55))
|
let fadeAlpha = min(1.0, max(0.0, -0.25 + value * 1.55))
|
||||||
if value > 0.0 {
|
if value > 0.0 {
|
||||||
self.prepare()
|
var value = value
|
||||||
self.effectView?.layer.timeOffset = max(0.0, -0.1 + value * 1.1)
|
let updated = self.prepare()
|
||||||
|
if value > 0.99 && updated {
|
||||||
|
value = 0.99
|
||||||
|
}
|
||||||
|
self.animator?.fractionComplete = max(0.0, -0.1 + value * 1.1)
|
||||||
} else {
|
} else {
|
||||||
self.effectView?.layer.removeAllAnimations()
|
self.animator?.stopAnimation(true)
|
||||||
self.effectView?.layer.speed = 1.0
|
self.animator = nil
|
||||||
self.effectView?.layer.timeOffset = 0.0
|
|
||||||
self.effectView?.effect = nil
|
self.effectView?.effect = nil
|
||||||
}
|
}
|
||||||
self.fadeNode.alpha = fadeAlpha
|
self.fadeNode.alpha = fadeAlpha
|
||||||
|
Loading…
x
Reference in New Issue
Block a user