mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Merge commit '3f9f29b7fb5b4f3dbe73800b32aafa9d4b88d3f9'
# Conflicts: # submodules/ChatSendMessageActionUI/BUILD # submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift
This commit is contained in:
commit
2a5523b266
@ -810,9 +810,9 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
||||
}
|
||||
}
|
||||
|
||||
let openNewCard: () -> Void = { [weak self] in
|
||||
let openNewCard: (String?) -> Void = { [weak self] customUrl in
|
||||
if let strongSelf = self, let paymentForm = strongSelf.paymentFormValue {
|
||||
if let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "stripe" {
|
||||
if customUrl == nil, let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "stripe" {
|
||||
guard let paramsData = nativeProvider.params.data(using: .utf8) else {
|
||||
return
|
||||
}
|
||||
@ -891,7 +891,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
||||
controller?.dismiss()
|
||||
}
|
||||
strongSelf.present(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
} else if let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "smartglocal" {
|
||||
} else if customUrl == nil, let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "smartglocal" {
|
||||
guard let paramsData = nativeProvider.params.data(using: .utf8) else {
|
||||
return
|
||||
}
|
||||
@ -961,7 +961,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
||||
strongSelf.present(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
} else {
|
||||
var dismissImpl: (() -> Void)?
|
||||
let controller = BotCheckoutWebInteractionController(context: context, url: paymentForm.url, intent: .addPaymentMethod({ [weak self] token in
|
||||
let controller = BotCheckoutWebInteractionController(context: context, url: customUrl ?? paymentForm.url, intent: .addPaymentMethod({ [weak self] token in
|
||||
dismissImpl?()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
@ -1060,12 +1060,14 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
||||
strongSelf.controller?.view.endEditing(true)
|
||||
let methods = availablePaymentMethods(form: paymentForm, current: strongSelf.currentPaymentMethod)
|
||||
if methods.isEmpty {
|
||||
openNewCard()
|
||||
openNewCard(nil)
|
||||
} else {
|
||||
strongSelf.present(BotCheckoutPaymentMethodSheetController(context: strongSelf.context, currentMethod: strongSelf.currentPaymentMethod, methods: methods, applyValue: { method in
|
||||
applyPaymentMethod(method)
|
||||
}, newCard: {
|
||||
openNewCard()
|
||||
openNewCard(nil)
|
||||
}, otherMethod: { url in
|
||||
openNewCard(url)
|
||||
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ enum BotCheckoutPaymentMethod: Equatable {
|
||||
final class BotCheckoutPaymentMethodSheetController: ActionSheetController {
|
||||
private var presentationDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, currentMethod: BotCheckoutPaymentMethod?, methods: [BotCheckoutPaymentMethod], applyValue: @escaping (BotCheckoutPaymentMethod) -> Void, newCard: @escaping () -> Void) {
|
||||
init(context: AccountContext, currentMethod: BotCheckoutPaymentMethod?, methods: [BotCheckoutPaymentMethod], applyValue: @escaping (BotCheckoutPaymentMethod) -> Void, newCard: @escaping () -> Void, otherMethod: @escaping (String) -> Void) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let strings = presentationData.strings
|
||||
|
||||
@ -82,7 +82,11 @@ final class BotCheckoutPaymentMethodSheetController: ActionSheetController {
|
||||
value = nil
|
||||
}
|
||||
items.append(BotCheckoutPaymentMethodItem(title: title, icon: icon, value: value, action: { [weak self] _ in
|
||||
applyValue(method)
|
||||
if case let .other(method) = method {
|
||||
otherMethod(method.url)
|
||||
} else {
|
||||
applyValue(method)
|
||||
}
|
||||
self?.dismissAnimated()
|
||||
}))
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ swift_library(
|
||||
"//submodules/ContextUI:ContextUI",
|
||||
"//submodules/AppBundle:AppBundle",
|
||||
"//submodules/TextFormat:TextFormat",
|
||||
"//submodules/TelegramUI/Components/TextNodeWithEntities:TextNodeWithEntities",
|
||||
"//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
||||
@ -57,7 +57,9 @@ public final class ChatSendMessageActionSheetController: ViewController {
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||
if strongSelf.isNodeLoaded {
|
||||
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -93,7 +95,7 @@ public final class ChatSendMessageActionSheetController: ViewController {
|
||||
hasEntityKeyboard = true
|
||||
}
|
||||
|
||||
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, hasEntityKeyboard: hasEntityKeyboard, send: { [weak self] in
|
||||
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, hasEntityKeyboard: hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in
|
||||
self?.sendMessage(false)
|
||||
self?.dismiss(cancel: false)
|
||||
}, sendSilently: { [weak self] in
|
||||
|
||||
@ -10,7 +10,7 @@ import AccountContext
|
||||
import AppBundle
|
||||
import ContextUI
|
||||
import TextFormat
|
||||
import TextNodeWithEntities
|
||||
import EmojiTextAttachmentView
|
||||
|
||||
private let leftInset: CGFloat = 16.0
|
||||
private let rightInset: CGFloat = 16.0
|
||||
@ -178,6 +178,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
private let toMessageTextNode: EditableTextNode
|
||||
private let scrollNode: ASScrollNode
|
||||
|
||||
private var fromCustomEmojiContainerView: CustomEmojiContainerView?
|
||||
private var toCustomEmojiContainerView: CustomEmojiContainerView?
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
private var sendButtonFrame: CGRect {
|
||||
@ -186,7 +189,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
|
||||
private var animateInputField = false
|
||||
|
||||
init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) {
|
||||
private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?
|
||||
|
||||
init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.sourceSendButton = sourceSendButton
|
||||
@ -195,6 +200,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
self.attachment = attachment
|
||||
self.forwardedCount = forwardedCount
|
||||
self.hasEntityKeyboard = hasEntityKeyboard
|
||||
self.emojiViewProvider = emojiViewProvider
|
||||
|
||||
self.send = send
|
||||
self.cancel = cancel
|
||||
@ -352,6 +358,64 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
}
|
||||
}
|
||||
|
||||
func updateTextContents() {
|
||||
var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = []
|
||||
|
||||
let textInputNode = self.fromMessageTextNode
|
||||
if let attributedText = textInputNode.attributedText {
|
||||
let beginning = textInputNode.textView.beginningOfDocument
|
||||
attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in
|
||||
if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute {
|
||||
if let start = textInputNode.textView.position(from: beginning, offset: range.location), let end = textInputNode.textView.position(from: start, offset: range.length), let textRange = textInputNode.textView.textRange(from: start, to: end) {
|
||||
let textRects = textInputNode.textView.selectionRects(for: textRange)
|
||||
for textRect in textRects {
|
||||
customEmojiRects.append((textRect.rect, value))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.updateTextContents(rects: customEmojiRects, textInputNode: self.fromMessageTextNode, from: true)
|
||||
self.updateTextContents(rects: customEmojiRects, textInputNode: self.toMessageTextNode, from: false)
|
||||
}
|
||||
|
||||
func updateTextContents(rects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)], textInputNode: EditableTextNode, from: Bool) {
|
||||
if !rects.isEmpty {
|
||||
let customEmojiContainerView: CustomEmojiContainerView
|
||||
if from, let current = self.fromCustomEmojiContainerView {
|
||||
customEmojiContainerView = current
|
||||
} else if !from, let current = self.toCustomEmojiContainerView {
|
||||
customEmojiContainerView = current
|
||||
} else {
|
||||
customEmojiContainerView = CustomEmojiContainerView(emojiViewProvider: { [weak self] emoji in
|
||||
guard let strongSelf = self, let emojiViewProvider = strongSelf.emojiViewProvider else {
|
||||
return nil
|
||||
}
|
||||
return emojiViewProvider(emoji)
|
||||
})
|
||||
customEmojiContainerView.isUserInteractionEnabled = false
|
||||
textInputNode.textView.addSubview(customEmojiContainerView)
|
||||
if from {
|
||||
self.fromCustomEmojiContainerView = customEmojiContainerView
|
||||
} else {
|
||||
self.toCustomEmojiContainerView = customEmojiContainerView
|
||||
}
|
||||
}
|
||||
|
||||
customEmojiContainerView.update(emojiRects: rects)
|
||||
} else {
|
||||
if from, let customEmojiContainerView = self.fromCustomEmojiContainerView {
|
||||
customEmojiContainerView.removeFromSuperview()
|
||||
self.fromCustomEmojiContainerView = nil
|
||||
} else if !from, let customEmojiContainerView = self.toCustomEmojiContainerView {
|
||||
customEmojiContainerView.removeFromSuperview()
|
||||
self.fromCustomEmojiContainerView = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
guard presentationData.theme !== self.presentationData.theme else {
|
||||
return
|
||||
@ -460,6 +524,10 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
let springDamping: CGFloat = 104.0
|
||||
self.contentContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping)
|
||||
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
||||
|
||||
Queue.mainQueue().after(0.01, {
|
||||
self.updateTextContents()
|
||||
})
|
||||
}
|
||||
|
||||
func animateOut(cancel: Bool, completion: @escaping () -> Void) {
|
||||
@ -693,3 +761,64 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
||||
self.send?()
|
||||
}
|
||||
}
|
||||
|
||||
final class CustomEmojiContainerView: UIView {
|
||||
private let emojiViewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView?
|
||||
|
||||
private var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:]
|
||||
|
||||
init(emojiViewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView?) {
|
||||
self.emojiViewProvider = emojiViewProvider
|
||||
|
||||
super.init(frame: CGRect())
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
func update(emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) {
|
||||
var nextIndexById: [Int64: Int] = [:]
|
||||
|
||||
var validKeys = Set<InlineStickerItemLayer.Key>()
|
||||
for (rect, emoji) in emojiRects {
|
||||
let index: Int
|
||||
if let nextIndex = nextIndexById[emoji.fileId] {
|
||||
index = nextIndex
|
||||
} else {
|
||||
index = 0
|
||||
}
|
||||
nextIndexById[emoji.fileId] = index + 1
|
||||
|
||||
let key = InlineStickerItemLayer.Key(id: emoji.fileId, index: index)
|
||||
|
||||
let view: UIView
|
||||
if let current = self.emojiLayers[key] {
|
||||
view = current
|
||||
} else if let newView = self.emojiViewProvider(emoji) {
|
||||
view = newView
|
||||
self.addSubview(newView)
|
||||
self.emojiLayers[key] = view
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
let size = CGSize(width: 24.0, height: 24.0)
|
||||
|
||||
view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size)
|
||||
|
||||
validKeys.insert(key)
|
||||
}
|
||||
|
||||
var removeKeys: [InlineStickerItemLayer.Key] = []
|
||||
for (key, view) in self.emojiLayers {
|
||||
if !validKeys.contains(key) {
|
||||
removeKeys.append(key)
|
||||
view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
for key in removeKeys {
|
||||
self.emojiLayers.removeValue(forKey: key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,9 +552,9 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate {
|
||||
}
|
||||
itemSize.height = height
|
||||
} else if let fillsRowWithDynamicHeight = item.fillsRowWithDynamicHeight {
|
||||
let height = fillsRowWithDynamicHeight(gridLayout.size.width)
|
||||
let height = fillsRowWithDynamicHeight(gridLayout.size.width - itemInsets.left - itemInsets.right)
|
||||
nextItemOrigin.x = initialSpacing + itemInsets.left
|
||||
itemSize.width = gridLayout.size.width
|
||||
itemSize.width = gridLayout.size.width - itemInsets.left - itemInsets.right
|
||||
itemSize.height = height
|
||||
} else if index == 0 {
|
||||
let itemsInRow = max(1, Int(effectiveWidth) / Int(itemSize.width))
|
||||
|
||||
@ -122,11 +122,12 @@ private final class HapticFeedbackImpl {
|
||||
}
|
||||
|
||||
func warning() {
|
||||
if let notificationGenerator = self.notificationGenerator {
|
||||
notificationGenerator.notificationOccurred(.warning)
|
||||
} else {
|
||||
|
||||
}
|
||||
AudioServicesPlaySystemSound(1102)
|
||||
// if let notificationGenerator = self.notificationGenerator {
|
||||
// notificationGenerator.notificationOccurred(.warning)
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
@objc dynamic func f() {
|
||||
|
||||
@ -331,6 +331,7 @@ public class Window1 {
|
||||
self.hostView = hostView
|
||||
self.badgeView = UIImageView()
|
||||
self.badgeView.image = UIImage(bundleImageName: "Components/AppBadge")
|
||||
self.badgeView.isHidden = true
|
||||
|
||||
self.systemUserInterfaceStyle = hostView.systemUserInterfaceStyle
|
||||
|
||||
@ -655,7 +656,7 @@ public class Window1 {
|
||||
}
|
||||
}
|
||||
|
||||
private var forceBadgeHidden = false
|
||||
private var forceBadgeHidden = true
|
||||
public func setForceBadgeHidden(_ hidden: Bool) {
|
||||
guard hidden != self.forceBadgeHidden else {
|
||||
return
|
||||
|
||||
@ -20,7 +20,7 @@ public enum ItemListDisclosureLabelStyle {
|
||||
case text
|
||||
case detailText
|
||||
case coloredText(UIColor)
|
||||
// case textWithIcon(UIColor)
|
||||
case textWithIcon(UIImage)
|
||||
case multilineDetailText
|
||||
case badge(UIColor)
|
||||
case color(UIColor)
|
||||
@ -236,7 +236,9 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
updatedLabelImage = generateFilledCircleImage(diameter: 17.0, color: color)
|
||||
}
|
||||
}
|
||||
if case let .image(image, _) = item.labelStyle {
|
||||
if case let .textWithIcon(image) = item.labelStyle {
|
||||
updatedLabelImage = generateTintedImage(image: image, color: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else if case let .image(image, _) = item.labelStyle {
|
||||
updatedLabelImage = image
|
||||
}
|
||||
|
||||
@ -474,7 +476,18 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
|
||||
if case let .image(_, size) = item.labelStyle {
|
||||
if case .textWithIcon = item.labelStyle {
|
||||
if let updatedLabelImage = updatedLabelImage {
|
||||
strongSelf.labelImageNode.image = updatedLabelImage
|
||||
}
|
||||
if strongSelf.labelImageNode.supernode == nil {
|
||||
strongSelf.addSubnode(strongSelf.labelImageNode)
|
||||
}
|
||||
|
||||
if let size = strongSelf.labelImageNode.image?.size {
|
||||
strongSelf.labelImageNode.frame = CGRect(origin: CGPoint(x: labelFrame.minX - size.width - 5.0, y: floor((layout.contentSize.height - size.height) / 2.0) - 1.0), size: size)
|
||||
}
|
||||
} else if case let .image(_, size) = item.labelStyle {
|
||||
if let updatedLabelImage = updatedLabelImage {
|
||||
strongSelf.labelImageNode.image = updatedLabelImage
|
||||
}
|
||||
|
||||
@ -478,7 +478,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat
|
||||
addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_cancel")
|
||||
|
||||
dismissImpl?()
|
||||
})]))
|
||||
})], actionLayout: .vertical))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
|
||||
case voiceCallPrivacy(PresentationTheme, String, String)
|
||||
case forwardPrivacy(PresentationTheme, String, String)
|
||||
case groupPrivacy(PresentationTheme, String, String)
|
||||
case voiceMessagePrivacy(PresentationTheme, String, String)
|
||||
case voiceMessagePrivacy(PresentationTheme, String, String, Bool)
|
||||
case selectivePrivacyInfo(PresentationTheme, String)
|
||||
case passcode(PresentationTheme, String, Bool, String)
|
||||
case twoStepVerification(PresentationTheme, String, String, TwoStepVerificationAccessConfiguration?)
|
||||
@ -209,8 +209,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue):
|
||||
if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue, lhsLocked):
|
||||
if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue, rhsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsLocked == rhsLocked {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -300,7 +300,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
|
||||
case let .privacyHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .blockedPeers(_, text, value):
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Settings/Menu/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Chat/Stickers/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openBlockedUsers()
|
||||
})
|
||||
case let .phoneNumberPrivacy(_, text, value):
|
||||
@ -323,8 +323,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openGroupsPrivacy()
|
||||
})
|
||||
case let .voiceMessagePrivacy(_, text, value):
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
case let .voiceMessagePrivacy(_, text, value, locked):
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: locked ? .textWithIcon(UIImage(bundleImageName: "Notification/SecretLock")!.precomposed()) : .text, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openVoiceMessagePrivacy()
|
||||
})
|
||||
case let .selectivePrivacyInfo(_, text):
|
||||
@ -411,7 +411,7 @@ private func stringForSelectiveSettings(strings: PresentationStrings, settings:
|
||||
}
|
||||
}
|
||||
|
||||
private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool) -> [PrivacyAndSecurityEntry] {
|
||||
private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool, isPremium: Bool) -> [PrivacyAndSecurityEntry] {
|
||||
var entries: [PrivacyAndSecurityEntry] = []
|
||||
|
||||
entries.append(.blockedPeers(presentationData.theme, presentationData.strings.Settings_BlockedUsers, blockedPeerCount == nil ? "" : (blockedPeerCount == 0 ? presentationData.strings.PrivacySettings_BlockedPeersEmpty : "\(blockedPeerCount!)")))
|
||||
@ -449,7 +449,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD
|
||||
entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.presence)))
|
||||
entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.profilePhoto)))
|
||||
entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceCalls)))
|
||||
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages)))
|
||||
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), !isPremium))
|
||||
entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.forwards)))
|
||||
entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.groupInvitations)))
|
||||
|
||||
@ -458,7 +458,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD
|
||||
entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, presentationData.strings.Channel_NotificationLoading))
|
||||
entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, presentationData.strings.Channel_NotificationLoading))
|
||||
entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, presentationData.strings.Channel_NotificationLoading))
|
||||
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading))
|
||||
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading, !isPremium))
|
||||
entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, presentationData.strings.Channel_NotificationLoading))
|
||||
entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, presentationData.strings.Channel_NotificationLoading))
|
||||
entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp))
|
||||
@ -944,9 +944,10 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
||||
webSessionsContext.state,
|
||||
context.sharedContext.accountManager.accessChallengeData(),
|
||||
combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()),
|
||||
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App())
|
||||
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()),
|
||||
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
||||
)
|
||||
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration, accountPeer -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
var canAutoarchive = false
|
||||
if let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool {
|
||||
canAutoarchive = hasAutoarchive
|
||||
@ -959,7 +960,9 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PrivacySettings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
|
||||
let isPremium = accountPeer?.isPremium ?? false
|
||||
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive, isPremium: isPremium), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
@ -103,16 +103,14 @@ final class StickerPackEmojisItem: GridItem {
|
||||
|
||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
||||
let node = StickerPackEmojisItemNode()
|
||||
node.setup(item: self)
|
||||
return node
|
||||
}
|
||||
|
||||
func update(node: GridItemNode) {
|
||||
guard let node = node as? StickerPackEmojisItemNode else {
|
||||
guard let _ = node as? StickerPackEmojisItemNode else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
node.setup(item: self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +171,7 @@ final class StickerPackEmojisItemNode: GridItemNode {
|
||||
|
||||
let shimmerHostView = PortalSourceView()
|
||||
shimmerHostView.alpha = 0.0
|
||||
shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.frame.size)
|
||||
shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.size)
|
||||
self.view.addSubview(shimmerHostView)
|
||||
self.shimmerHostView = shimmerHostView
|
||||
|
||||
@ -194,10 +192,14 @@ final class StickerPackEmojisItemNode: GridItemNode {
|
||||
}
|
||||
self.boundsChangeTrackerLayer = boundsChangeTrackerLayer
|
||||
}
|
||||
|
||||
private var setupTimestamp: Double?
|
||||
func setup(item: StickerPackEmojisItem) {
|
||||
|
||||
private var size = CGSize()
|
||||
override func updateLayout(item: GridItem, size: CGSize, isVisible: Bool, synchronousLoads: Bool) {
|
||||
guard let item = item as? StickerPackEmojisItem else {
|
||||
return
|
||||
}
|
||||
self.item = item
|
||||
self.size = size
|
||||
|
||||
if let title = item.title {
|
||||
let isInstalled = item.isInstalled ?? false
|
||||
@ -217,9 +219,9 @@ final class StickerPackEmojisItemNode: GridItemNode {
|
||||
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
|
||||
func updateVisibleItems(attemptSynchronousLoads: Bool, transition: ContainedViewLayoutTransition) {
|
||||
guard let item = self.item, !self.frame.width.isZero else {
|
||||
guard let item = self.item, !self.size.width.isZero else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -231,10 +233,10 @@ final class StickerPackEmojisItemNode: GridItemNode {
|
||||
var validIds = Set<EmojiPagerContentComponent.View.ItemLayer.Key>()
|
||||
|
||||
let itemLayout: ItemLayout
|
||||
if let current = self.itemLayout, current.width == self.frame.width && current.itemsCount == items.count && current.hasTitle == (item.title != nil) {
|
||||
if let current = self.itemLayout, current.width == self.size.width && current.itemsCount == items.count && current.hasTitle == (item.title != nil) {
|
||||
itemLayout = current
|
||||
} else {
|
||||
itemLayout = ItemLayout(width: self.frame.width, itemsCount: items.count, hasTitle: item.title != nil)
|
||||
itemLayout = ItemLayout(width: self.size.width, itemsCount: items.count, hasTitle: item.title != nil)
|
||||
self.itemLayout = itemLayout
|
||||
}
|
||||
|
||||
@ -368,20 +370,20 @@ final class StickerPackEmojisItemNode: GridItemNode {
|
||||
super.layout()
|
||||
|
||||
if let _ = self.item {
|
||||
var buttonSize = self.buttonNode.calculateSizeThatFits(self.frame.size)
|
||||
var buttonSize = self.buttonNode.calculateSizeThatFits(self.size)
|
||||
buttonSize.width += 24.0
|
||||
buttonSize.height = 28.0
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: self.frame.width - 60.0, height: self.frame.height))
|
||||
let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: self.frame.width - 60.0, height: self.frame.height))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: self.size.width - 60.0, height: self.size.height))
|
||||
let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: self.size.width - 60.0, height: self.size.height))
|
||||
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 10.0), size: titleSize)
|
||||
self.subtitleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 33.0), size: subtitleSize)
|
||||
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(x: self.frame.width - buttonSize.width - 16.0, y: 17.0), size: buttonSize)
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(x: self.size.width - buttonSize.width - 16.0, y: 17.0), size: buttonSize)
|
||||
}
|
||||
|
||||
self.shimmerHostView?.frame = CGRect(origin: CGPoint(), size: self.frame.size)
|
||||
self.shimmerHostView?.frame = CGRect(origin: CGPoint(), size: self.size)
|
||||
self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate)
|
||||
}
|
||||
|
||||
|
||||
@ -911,14 +911,6 @@ private final class StickerPackContainer: ASDisplayNode {
|
||||
}
|
||||
|
||||
if updateLayout, let (layout, _, _, _) = self.validLayout {
|
||||
let cancelSize = self.cancelButtonNode.measure(CGSize(width: layout.size.width, height: .greatestFiniteMagnitude))
|
||||
self.cancelButtonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left + 16.0, y: 18.0), size: cancelSize)
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - cancelSize.width * 2.0 - 40.0, height: .greatestFiniteMagnitude))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: floor((-titleSize.width) / 2.0), y: floor((-titleSize.height) / 2.0)), size: titleSize)
|
||||
|
||||
self.moreButtonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - 46.0, y: 5.0), size: CGSize(width: 44.0, height: 44.0))
|
||||
|
||||
self.updateLayout(layout: layout, transition: .immediate)
|
||||
}
|
||||
|
||||
@ -1050,6 +1042,14 @@ private final class StickerPackContainer: ASDisplayNode {
|
||||
titlePlaceholderNode.updateAbsoluteRect(titlePlaceholderNode.frame.offsetBy(dx: self.titleContainer.frame.minX, dy: self.titleContainer.frame.minY - gridInsets.top - gridFrame.minY), within: gridFrame.size)
|
||||
}
|
||||
|
||||
let cancelSize = self.cancelButtonNode.measure(CGSize(width: layout.size.width, height: .greatestFiniteMagnitude))
|
||||
self.cancelButtonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left + 16.0, y: 18.0), size: cancelSize)
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - cancelSize.width * 2.0 - 40.0, height: .greatestFiniteMagnitude))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: floor((-titleSize.width) / 2.0), y: floor((-titleSize.height) / 2.0)), size: titleSize)
|
||||
|
||||
self.moreButtonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - 46.0, y: 5.0), size: CGSize(width: 44.0, height: 44.0))
|
||||
|
||||
if firstTime {
|
||||
while !self.enqueuedTransactions.isEmpty {
|
||||
self.dequeueTransaction()
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -3617,7 +3617,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}, didDismiss: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let isFocused = strongSelf.chatDisplayNode.textInputPanelNode?.isFocused ?? false
|
||||
strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.historyNodeContainer)
|
||||
strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.inputContextPanelContainer)
|
||||
if isFocused {
|
||||
strongSelf.chatDisplayNode.textInputPanelNode?.ensureFocused()
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private var secondaryInputPanelNode: ChatInputPanelNode?
|
||||
private(set) var accessoryPanelNode: AccessoryPanelNode?
|
||||
private var inputContextPanelNode: ChatInputContextPanelNode?
|
||||
private let inputContextPanelContainer: ChatControllerTitlePanelNodeContainer
|
||||
let inputContextPanelContainer: ChatControllerTitlePanelNodeContainer
|
||||
private let inputContextOverTextPanelContainer: ChatControllerTitlePanelNodeContainer
|
||||
private var overlayContextPanelNode: ChatInputContextPanelNode?
|
||||
|
||||
|
||||
@ -1067,7 +1067,14 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
}
|
||||
|
||||
if isPremiumLocked {
|
||||
let controller = PremiumIntroScreen(context: context, source: .stickers)
|
||||
var replaceImpl: ((ViewController) -> Void)?
|
||||
let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: {
|
||||
let controller = PremiumIntroScreen(context: context, source: .animatedEmoji)
|
||||
replaceImpl?(controller)
|
||||
})
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
controllerInteraction.navigationController()?.pushViewController(controller)
|
||||
|
||||
return
|
||||
|
||||
@ -60,7 +60,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
||||
self.addSubnode(self.iconImageNode)
|
||||
|
||||
switch item {
|
||||
case .input, .botInput:
|
||||
case .input, .botInput, .silentPost:
|
||||
self.iconImageNode.isHidden = true
|
||||
self.animationView = ComponentView<Empty>()
|
||||
default:
|
||||
@ -175,105 +175,122 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
||||
self.iconImageNode.frame = imageFrame
|
||||
|
||||
if let animationView = self.animationView {
|
||||
let iconSize: CGSize = CGSize(width: 32.0, height: 32.0)
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0) - bottomInset), size: iconSize)
|
||||
let animationFrame = iconFrame.insetBy(dx: -4.0, dy: -4.0)
|
||||
let width = AccessoryItemIconButtonNode.calculateWidth(item: item, image: image, text: "", strings: self.strings)
|
||||
let iconSize = CGSize(width: width, height: width)
|
||||
|
||||
var previousInputMode: ChatTextInputAccessoryItem.InputMode?
|
||||
var inputMode: ChatTextInputAccessoryItem.InputMode?
|
||||
|
||||
switch previousItem {
|
||||
case let .input(_, itemInputMode), let .botInput(_, itemInputMode):
|
||||
previousInputMode = itemInputMode
|
||||
default:
|
||||
break
|
||||
}
|
||||
switch item {
|
||||
case let .input(_, itemInputMode), let .botInput(_, itemInputMode):
|
||||
inputMode = itemInputMode
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let emojiColorKeys = [
|
||||
"Ellipse 33.Ellipse 33.Stroke 1",
|
||||
"Ellipse 34.Ellipse 34.Stroke 1",
|
||||
"Oval.Oval.Fill 1",
|
||||
"Oval 2.Oval.Fill 1",
|
||||
"Path 85.Path 85.Stroke 1"
|
||||
]
|
||||
let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - width) / 2.0), y: floor((size.height - width) / 2.0) - bottomInset), size: CGSize(width: width, height: width))
|
||||
|
||||
var colorKeys: [String] = ["__allcolors__"]
|
||||
let animationName: String
|
||||
var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end)
|
||||
if let inputMode = inputMode {
|
||||
switch inputMode {
|
||||
case .keyboard:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .stickers = previousInputMode {
|
||||
animationName = "input_anim_stickerToKey"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .emoji = previousInputMode {
|
||||
animationName = "input_anim_smileToKey"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .bot = previousInputMode {
|
||||
animationName = "input_anim_botToKey"
|
||||
animationMode = .animating(loop: false)
|
||||
} else {
|
||||
animationName = "input_anim_stickerToKey"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_stickerToKey"
|
||||
}
|
||||
case .stickers:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .keyboard = previousInputMode {
|
||||
animationName = "input_anim_keyToSticker"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .emoji = previousInputMode {
|
||||
animationName = "input_anim_smileToSticker"
|
||||
animationMode = .animating(loop: false)
|
||||
colorKeys = emojiColorKeys
|
||||
} else {
|
||||
animationName = "input_anim_keyToSticker"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_keyToSticker"
|
||||
}
|
||||
case .emoji:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .keyboard = previousInputMode {
|
||||
animationName = "input_anim_keyToSmile"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .stickers = previousInputMode {
|
||||
animationName = "input_anim_stickerToSmile"
|
||||
animationMode = .animating(loop: false)
|
||||
colorKeys = emojiColorKeys
|
||||
} else {
|
||||
animationName = "input_anim_keyToSmile"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_keyToSmile"
|
||||
}
|
||||
case .bot:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .keyboard = previousInputMode {
|
||||
animationName = "input_anim_keyToBot"
|
||||
animationMode = .animating(loop: false)
|
||||
} else {
|
||||
animationName = "input_anim_keyToBot"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_keyToBot"
|
||||
}
|
||||
|
||||
if case let .silentPost(muted) = item {
|
||||
if case let .silentPost(previousMuted) = previousItem {
|
||||
if muted {
|
||||
animationName = "input_anim_channelMute"
|
||||
} else {
|
||||
animationName = "input_anim_channelUnmute"
|
||||
}
|
||||
if muted != previousMuted {
|
||||
animationMode = .animating(loop: false)
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_channelMute"
|
||||
}
|
||||
} else {
|
||||
animationName = ""
|
||||
var previousInputMode: ChatTextInputAccessoryItem.InputMode?
|
||||
var inputMode: ChatTextInputAccessoryItem.InputMode?
|
||||
|
||||
switch previousItem {
|
||||
case let .input(_, itemInputMode), let .botInput(_, itemInputMode):
|
||||
previousInputMode = itemInputMode
|
||||
default:
|
||||
break
|
||||
}
|
||||
switch item {
|
||||
case let .input(_, itemInputMode), let .botInput(_, itemInputMode):
|
||||
inputMode = itemInputMode
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let emojiColorKeys = [
|
||||
"Ellipse 33.Ellipse 33.Stroke 1",
|
||||
"Ellipse 34.Ellipse 34.Stroke 1",
|
||||
"Oval.Oval.Fill 1",
|
||||
"Oval 2.Oval.Fill 1",
|
||||
"Path 85.Path 85.Stroke 1"
|
||||
]
|
||||
|
||||
if let inputMode = inputMode {
|
||||
switch inputMode {
|
||||
case .keyboard:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .stickers = previousInputMode {
|
||||
animationName = "input_anim_stickerToKey"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .emoji = previousInputMode {
|
||||
animationName = "input_anim_smileToKey"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .bot = previousInputMode {
|
||||
animationName = "input_anim_botToKey"
|
||||
animationMode = .animating(loop: false)
|
||||
} else {
|
||||
animationName = "input_anim_stickerToKey"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_stickerToKey"
|
||||
}
|
||||
case .stickers:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .keyboard = previousInputMode {
|
||||
animationName = "input_anim_keyToSticker"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .emoji = previousInputMode {
|
||||
animationName = "input_anim_smileToSticker"
|
||||
animationMode = .animating(loop: false)
|
||||
colorKeys = emojiColorKeys
|
||||
} else {
|
||||
animationName = "input_anim_keyToSticker"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_keyToSticker"
|
||||
}
|
||||
case .emoji:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .keyboard = previousInputMode {
|
||||
animationName = "input_anim_keyToSmile"
|
||||
animationMode = .animating(loop: false)
|
||||
} else if case .stickers = previousInputMode {
|
||||
animationName = "input_anim_stickerToSmile"
|
||||
animationMode = .animating(loop: false)
|
||||
colorKeys = emojiColorKeys
|
||||
} else {
|
||||
animationName = "input_anim_keyToSmile"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_keyToSmile"
|
||||
}
|
||||
case .bot:
|
||||
if let previousInputMode = previousInputMode {
|
||||
if case .keyboard = previousInputMode {
|
||||
animationName = "input_anim_keyToBot"
|
||||
animationMode = .animating(loop: false)
|
||||
} else {
|
||||
animationName = "input_anim_keyToBot"
|
||||
}
|
||||
} else {
|
||||
animationName = "input_anim_keyToBot"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
animationName = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var colors: [String: UIColor] = [:]
|
||||
for colorKey in colorKeys {
|
||||
colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
||||
colors[colorKey] = self.theme.chat.inputPanel.inputControlColor
|
||||
}
|
||||
|
||||
let animationSize = animationView.update(
|
||||
@ -284,7 +301,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
||||
mode: animationMode
|
||||
),
|
||||
colors: colors,
|
||||
size: CGSize(width: 32.0, height: 32.0)
|
||||
size: iconSize
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: animationFrame.size
|
||||
|
||||
@ -74,11 +74,13 @@ public final class TelegramRootController: NavigationController {
|
||||
}
|
||||
})
|
||||
|
||||
self.applicationInFocusDisposable = (context.sharedContext.applicationBindings.applicationIsActive
|
||||
|> distinctUntilChanged
|
||||
|> deliverOn(Queue.mainQueue())).start(next: { value in
|
||||
context.sharedContext.mainWindow?.setForceBadgeHidden(!value)
|
||||
})
|
||||
if context.sharedContext.applicationBindings.isMainApp {
|
||||
self.applicationInFocusDisposable = (context.sharedContext.applicationBindings.applicationIsActive
|
||||
|> distinctUntilChanged
|
||||
|> deliverOn(Queue.mainQueue())).start(next: { value in
|
||||
context.sharedContext.mainWindow?.setForceBadgeHidden(!value)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
|
||||
@ -800,39 +800,40 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
||||
self.needDismissConfirmation = needConfirmation
|
||||
}
|
||||
case "web_app_request_phone":
|
||||
let _ = (self.context.account.postbox.loadedPeerWithId(self.context.account.peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] accountPeer in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let user = accountPeer as? TelegramUser, let phoneNumber = user.phone else {
|
||||
return
|
||||
}
|
||||
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumberConfirmation(formatPhoneNumber(phoneNumber), strongSelf.controller?.botName ?? "").string, parseMarkdown: true))
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumber, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.sendPhoneRequestedEvent(phone: phoneNumber)
|
||||
}))
|
||||
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.sendPhoneRequestedEvent(phone: nil)
|
||||
})
|
||||
])])
|
||||
strongSelf.controller?.present(actionSheet, in: .window(.root))
|
||||
})
|
||||
break
|
||||
// let _ = (self.context.account.postbox.loadedPeerWithId(self.context.account.peerId)
|
||||
// |> deliverOnMainQueue).start(next: { [weak self] accountPeer in
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
// guard let user = accountPeer as? TelegramUser, let phoneNumber = user.phone else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
// var items: [ActionSheetItem] = []
|
||||
// items.append(ActionSheetTextItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumberConfirmation(formatPhoneNumber(phoneNumber), strongSelf.controller?.botName ?? "").string, parseMarkdown: true))
|
||||
// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumber, action: { [weak actionSheet] in
|
||||
// actionSheet?.dismissAnimated()
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// strongSelf.sendPhoneRequestedEvent(phone: phoneNumber)
|
||||
// }))
|
||||
//
|
||||
// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
// actionSheet?.dismissAnimated()
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// strongSelf.sendPhoneRequestedEvent(phone: nil)
|
||||
// })
|
||||
// ])])
|
||||
// strongSelf.controller?.present(actionSheet, in: .window(.root))
|
||||
// })
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user