diff --git a/TelegramUI/ChatHistoryEntry.swift b/TelegramUI/ChatHistoryEntry.swift index 60a394e3b6..5587fc4c35 100644 --- a/TelegramUI/ChatHistoryEntry.swift +++ b/TelegramUI/ChatHistoryEntry.swift @@ -37,16 +37,20 @@ enum ChatHistoryEntry: Identifiable, Comparable { var stableId: UInt64 { switch self { - case let .MessageEntry(message, _, _, _, _, _): - return UInt64(message.stableId) | ((UInt64(2) << 40)) + case let .MessageEntry(message, presentationData, _, _, _, _): + var type = 2 + if presentationData.largeEmoji && message.elligibleForLargeEmoji { + type = 3 + } + return UInt64(message.stableId) | ((UInt64(type) << 40)) case let .MessageGroupEntry(groupInfo, _, _): return UInt64(groupInfo.stableId) | ((UInt64(2) << 40)) case .UnreadEntry: - return UInt64(3) << 40 - case .ChatInfoEntry: return UInt64(4) << 40 - case .SearchEntry: + case .ChatInfoEntry: return UInt64(5) << 40 + case .SearchEntry: + return UInt64(6) << 40 } } diff --git a/TelegramUI/ChatListBadgeNode.swift b/TelegramUI/ChatListBadgeNode.swift index 3f441a7e56..0289cdfc2f 100644 --- a/TelegramUI/ChatListBadgeNode.swift +++ b/TelegramUI/ChatListBadgeNode.swift @@ -117,11 +117,15 @@ final class ChatListBadgeNode: ASDisplayNode { if currentIsEmpty && !nextIsEmpty { strongSelf.isHiddenInternal = false - strongSelf.layer.animateScale(from: 0.0001, to: 1.2, duration: 0.2, removeOnCompletion: false, completion: { [weak self] finished in - if let strongSelf = self { - strongSelf.layer.animateScale(from: 1.15, to: 1.0, duration: 0.12, removeOnCompletion: false) - } - }) + if bounce { + strongSelf.layer.animateScale(from: 0.0001, to: 1.2, duration: 0.2, removeOnCompletion: false, completion: { [weak self] finished in + if let strongSelf = self { + strongSelf.layer.animateScale(from: 1.15, to: 1.0, duration: 0.12, removeOnCompletion: false) + } + }) + } else { + strongSelf.layer.animateScale(from: 0.0001, to: 1.0, duration: 0.2, removeOnCompletion: false) + } } else if !currentIsEmpty && !nextIsEmpty && currentContent?.text != content.text { var animateScale = bounce strongSelf.isHiddenInternal = false diff --git a/TelegramUI/ChatListItem.swift b/TelegramUI/ChatListItem.swift index 61bf7d9174..fa2b9fa64f 100644 --- a/TelegramUI/ChatListItem.swift +++ b/TelegramUI/ChatListItem.swift @@ -1478,6 +1478,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } case RevealOptionKey.unarchive.rawValue: item.interaction.updatePeerGrouping(item.index.messageIndex.id.peerId, false) + close = false + self.skipFadeout = true + self.animateRevealOptionsFill { + self.revealOptionsInteractivelyClosed() + } case RevealOptionKey.toggleMarkedUnread.rawValue: item.interaction.togglePeerMarkedUnread(item.index.messageIndex.id.peerId, animated) close = false diff --git a/TelegramUI/ChatMessageItem.swift b/TelegramUI/ChatMessageItem.swift index 8d2cdc0a2b..2ef804f2b7 100644 --- a/TelegramUI/ChatMessageItem.swift +++ b/TelegramUI/ChatMessageItem.swift @@ -352,7 +352,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { } } - if viewClassName == ChatMessageBubbleItemNode.self && self.message.media.isEmpty && !self.message.text.isEmpty && self.message.text.containsOnlyEmoji && self.presentationData.largeEmoji, self.message.text.emojis.count < 4 { + if self.presentationData.largeEmoji && self.message.elligibleForLargeEmoji && viewClassName == ChatMessageBubbleItemNode.self { viewClassName = ChatMessageStickerItemNode.self } @@ -444,6 +444,4 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { public var description: String { return "(ChatMessageItem id: \(self.message.id), text: \"\(self.message.text)\")" } - - } diff --git a/TelegramUI/ChatMessageStickerItemNode.swift b/TelegramUI/ChatMessageStickerItemNode.swift index 5f625ed4cc..b07268fba5 100644 --- a/TelegramUI/ChatMessageStickerItemNode.swift +++ b/TelegramUI/ChatMessageStickerItemNode.swift @@ -70,7 +70,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { return .fail } - if let item = strongSelf.item, !item.message.text.isEmpty && item.message.text.containsOnlyEmoji && item.presentationData.largeEmoji { + if let item = strongSelf.item, item.presentationData.largeEmoji && item.message.elligibleForLargeEmoji { if strongSelf.imageNode.frame.contains(point) { return .waitForDoubleTap } @@ -109,7 +109,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } } - if self.telegramFile == nil && !item.message.text.isEmpty && item.message.text.containsOnlyEmoji && item.presentationData.largeEmoji { + if self.telegramFile == nil && item.presentationData.largeEmoji && item.message.elligibleForLargeEmoji { self.imageNode.setSignal(largeEmoji(postbox: item.context.account.postbox, emoji: item.message.text)) } } @@ -142,7 +142,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { var textLayoutAndApply: (TextNodeLayout, () -> TextNode)? var isEmoji = false - if !item.message.text.isEmpty && item.message.text.containsOnlyEmoji && item.presentationData.largeEmoji { + if item.presentationData.largeEmoji && item.message.elligibleForLargeEmoji { let attributedText = NSAttributedString(string: item.message.text, font: item.presentationData.messageEmojiFont1, textColor: .black) textLayoutAndApply = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: 180.0, height: 90.0), alignment: .natural)) diff --git a/TelegramUI/MessageUtils.swift b/TelegramUI/MessageUtils.swift index 8d2bc2bd1d..7eef9418b4 100644 --- a/TelegramUI/MessageUtils.swift +++ b/TelegramUI/MessageUtils.swift @@ -18,4 +18,12 @@ extension Message { return false } } + + var elligibleForLargeEmoji: Bool { + if self.media.isEmpty && !self.text.isEmpty && self.text.containsOnlyEmoji && self.text.emojis.count < 4 { + return true + } else { + return false + } + } } diff --git a/TelegramUI/PasscodeEntryController.swift b/TelegramUI/PasscodeEntryController.swift index 3c4a7e20de..829425a2fd 100644 --- a/TelegramUI/PasscodeEntryController.swift +++ b/TelegramUI/PasscodeEntryController.swift @@ -81,7 +81,7 @@ final public class PasscodeEntryController: ViewController { let biometricsType: LocalAuthBiometricAuthentication? if case let .enabled(data) = self.biometrics { if #available(iOSApplicationExtension 9.0, *) { - if data != nil { + if data == LocalAuth.evaluatedPolicyDomainState { biometricsType = LocalAuth.biometricAuthentication } else { biometricsType = nil @@ -236,7 +236,7 @@ final public class PasscodeEntryController: ViewController { } if #available(iOSApplicationExtension 9.0, *) { - if case let .enabled(storedDomainState) = strongSelf.biometrics { + if case let .enabled(storedDomainState) = strongSelf.biometrics, evaluatedPolicyDomainState != nil { if storedDomainState != evaluatedPolicyDomainState { let _ = updatePresentationPasscodeSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { settings in return settings.withUpdatedBiometricsDomainState(evaluatedPolicyDomainState).withUpdatedDisableBiometricsAuth(true) diff --git a/TelegramUI/PasscodeOptionsController.swift b/TelegramUI/PasscodeOptionsController.swift index d7f9b78c7f..b0baf4c9f8 100644 --- a/TelegramUI/PasscodeOptionsController.swift +++ b/TelegramUI/PasscodeOptionsController.swift @@ -249,7 +249,7 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { } transaction.setAccessChallengeData(data) - updatePresentationPasscodeSettingsInternal(transaction: transaction, { $0.withUpdatedAutolockTimeout(1 * 60 * 60) }) + updatePresentationPasscodeSettingsInternal(transaction: transaction, { $0.withUpdatedAutolockTimeout(1 * 60 * 60).withUpdatedBiometricsDomainState(LocalAuth.evaluatedPolicyDomainState) }) }) |> deliverOnMainQueue).start(next: { _ in }, error: { _ in }, completed: { @@ -398,7 +398,7 @@ public func passcodeOptionsAccessController(context: AccountContext, animateIn: } transaction.setAccessChallengeData(data) - updatePresentationPasscodeSettingsInternal(transaction: transaction, { $0.withUpdatedAutolockTimeout(1 * 60 * 60) }) + updatePresentationPasscodeSettingsInternal(transaction: transaction, { $0.withUpdatedAutolockTimeout(1 * 60 * 60).withUpdatedBiometricsDomainState(LocalAuth.evaluatedPolicyDomainState) }) }) |> deliverOnMainQueue).start(next: { _ in }, error: { _ in }, completed: { diff --git a/TelegramUI/PasscodeSetupControllerNode.swift b/TelegramUI/PasscodeSetupControllerNode.swift index 20bf93d8a4..cef9b22c6a 100644 --- a/TelegramUI/PasscodeSetupControllerNode.swift +++ b/TelegramUI/PasscodeSetupControllerNode.swift @@ -151,6 +151,9 @@ final class PasscodeSetupControllerNode: ASDisplayNode { let titleSize = self.titleNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: inputFieldFrame.minY - titleSize.height - 20.0), size: titleSize)) + let subtitleSize = self.subtitleNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) + transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - subtitleSize.width) / 2.0), y: inputFieldFrame.maxY + 20.0), size: subtitleSize)) + transition.updateFrame(node: self.modeButtonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - 53.0), size: CGSize(width: layout.size.width, height: 44.0))) } @@ -172,6 +175,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode { let previousAlpha = self.inputFieldBackgroundNode.alpha self.inputFieldBackgroundNode.alpha = fieldBackgroundAlpha self.inputFieldBackgroundNode.layer.animateAlpha(from: previousAlpha, to: fieldBackgroundAlpha, duration: 0.25) + self.subtitleNode.isHidden = true } } @@ -198,7 +202,24 @@ final class PasscodeSetupControllerNode: ASDisplayNode { } self.complete?(self.currentPasscode, numerical) } else { - self.animateError() + if let snapshotView = self.wrapperNode.view.snapshotContentTree() { + snapshotView.frame = self.wrapperNode.frame + self.wrapperNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.wrapperNode.view) + snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: self.wrapperNode.bounds.width, y: 0.0), duration: 0.25, removeOnCompletion: false, additive: true, completion : { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + self.wrapperNode.layer.animatePosition(from: CGPoint(x: -self.wrapperNode.bounds.width, y: 0.0), to: CGPoint(), duration: 0.25, additive: true) + + self.inputFieldNode.reset(animated: false) + self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.EnterPasscode_RepeatNewPasscode, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) + self.subtitleNode.isHidden = false + self.subtitleNode.attributedText = NSAttributedString(string: "Passcodes don't match. Please try again.", font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) + self.modeButtonNode.isHidden = false + + if let validLayout = self.validLayout { + self.containerLayoutUpdated(validLayout.0, navigationBarHeight: validLayout.1, transition: .immediate) + } + } } } else { self.previousPasscode = self.currentPasscode @@ -213,6 +234,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode { self.inputFieldNode.reset(animated: false) self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.EnterPasscode_RepeatNewPasscode, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) + self.subtitleNode.isHidden = true self.modeButtonNode.isHidden = true if let validLayout = self.validLayout { diff --git a/TelegramUI/PresentationPasscodeSettings.swift b/TelegramUI/PresentationPasscodeSettings.swift index 24c916b177..87fe047e1c 100644 --- a/TelegramUI/PresentationPasscodeSettings.swift +++ b/TelegramUI/PresentationPasscodeSettings.swift @@ -9,7 +9,7 @@ public struct PresentationPasscodeSettings: PreferencesEntry, Equatable { public var disableBiometricsAuth: Bool public static var defaultSettings: PresentationPasscodeSettings { - return PresentationPasscodeSettings(enableBiometrics: false, autolockTimeout: nil, biometricsDomainState: nil, disableBiometricsAuth: true) + return PresentationPasscodeSettings(enableBiometrics: false, autolockTimeout: nil, biometricsDomainState: nil, disableBiometricsAuth: false) } init(enableBiometrics: Bool, autolockTimeout: Int32?, biometricsDomainState: Data?, disableBiometricsAuth: Bool) { diff --git a/TelegramUI/SearchBarPlaceholderNode.swift b/TelegramUI/SearchBarPlaceholderNode.swift index 37d8c46f03..837234908b 100644 --- a/TelegramUI/SearchBarPlaceholderNode.swift +++ b/TelegramUI/SearchBarPlaceholderNode.swift @@ -133,7 +133,7 @@ class SearchBarPlaceholderNode: ASDisplayNode { if let iconImage = strongSelf.iconNode.image { iconSize = iconImage.size totalWidth += iconSize.width + spacing - transition.updateFrame(node: strongSelf.iconNode, frame: CGRect(origin: CGPoint(x: floor((constrainedSize.width - totalWidth) / 2.0), y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize)) + transition.updateFrame(node: strongSelf.iconNode, frame: CGRect(origin: CGPoint(x: floor((constrainedSize.width - totalWidth) / 2.0), y: floorToScreenPixels((height - iconSize.height) / 2.0)), size: iconSize)) } var textOffset: CGFloat = 0.0 if constrainedSize.height >= 36.0 { @@ -148,6 +148,10 @@ class SearchBarPlaceholderNode: ASDisplayNode { } else if innerAlpha < 0.0001 { innerAlpha = 0.0 } + if !transition.isAnimated { + strongSelf.labelNode.layer.removeAnimation(forKey: "opacity") + strongSelf.iconNode.layer.removeAnimation(forKey: "opacity") + } if strongSelf.labelNode.alpha != innerAlpha { transition.updateAlpha(node: strongSelf.labelNode, alpha: innerAlpha) transition.updateAlpha(node: strongSelf.iconNode, alpha: innerAlpha)