Merge commit 'f2b219b3df9f38c223796e47c3d9463661ff4e07'

This commit is contained in:
Peter 2019-05-28 21:44:58 +02:00
commit a19bb79f90
10 changed files with 308 additions and 129 deletions

View File

@ -216,50 +216,50 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee
let chatPeer = peer
let contextBot = resolvePeerByName(account: context.account, name: addressName)
|> mapToSignal { peerId -> Signal<Peer?, NoError> in
if let peerId = peerId {
return context.account.postbox.loadedPeerWithId(peerId)
|> map { peer -> Peer? in
return peer
}
|> take(1)
} else {
return .single(nil)
|> mapToSignal { peerId -> Signal<Peer?, NoError> in
if let peerId = peerId {
return context.account.postbox.loadedPeerWithId(peerId)
|> map { peer -> Peer? in
return peer
}
|> take(1)
} else {
return .single(nil)
}
|> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError> in
if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder {
let contextResults = requestChatContextResults(account: context.account, botId: user.id, peerId: chatPeer.id, query: query, offset: "")
|> map { results -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in
return { _ in
return .contextRequestResult(user, results)
}
|> mapToSignal { peer -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError> in
if let user = peer as? TelegramUser, let botInfo = user.botInfo, let _ = botInfo.inlinePlaceholder {
let contextResults = requestChatContextResults(account: context.account, botId: user.id, peerId: chatPeer.id, query: query, offset: "")
|> map { results -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in
return { _ in
return .contextRequestResult(user, results)
}
}
let botResult: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError> = .single({ previousResult in
var passthroughPreviousResult: ChatContextResultCollection?
if let previousResult = previousResult {
if case let .contextRequestResult(previousUser, previousResults) = previousResult {
if previousUser?.id == user.id {
passthroughPreviousResult = previousResults
}
}
let botResult: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError> = .single({ previousResult in
var passthroughPreviousResult: ChatContextResultCollection?
if let previousResult = previousResult {
if case let .contextRequestResult(previousUser, previousResults) = previousResult {
if previousUser?.id == user.id {
passthroughPreviousResult = previousResults
}
}
}
return .contextRequestResult(user, passthroughPreviousResult)
})
let maybeDelayedContextResults: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError>
if delayRequest {
maybeDelayedContextResults = contextResults |> delay(0.4, queue: Queue.concurrentDefaultQueue())
} else {
maybeDelayedContextResults = contextResults
}
return .contextRequestResult(user, passthroughPreviousResult)
})
return botResult |> then(maybeDelayedContextResults)
let maybeDelayedContextResults: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, NoError>
if delayRequest {
maybeDelayedContextResults = contextResults |> delay(0.4, queue: Queue.concurrentDefaultQueue())
} else {
return .single({ _ in return nil })
maybeDelayedContextResults = contextResults
}
return botResult |> then(maybeDelayedContextResults)
} else {
return .single({ _ in return nil })
}
}
return signal |> then(contextBot)
case let .emojiSearch(query, languageCode):

View File

@ -29,7 +29,7 @@ kernel vec4 alphaFrame(__sample s, __sample m) {
}
}
private func createVideoComposition(for playerItem: AVPlayerItem) -> AVVideoComposition? {
private func createVideoComposition(for playerItem: AVPlayerItem, ready: @escaping () -> Void) -> AVVideoComposition? {
let videoSize = CGSize(width: playerItem.presentationSize.width, height: playerItem.presentationSize.height / 2.0)
if #available(iOSApplicationExtension 9.0, *) {
let composition = AVMutableVideoComposition(asset: playerItem.asset, applyingCIFiltersWithHandler: { request in
@ -39,7 +39,8 @@ private func createVideoComposition(for playerItem: AVPlayerItem) -> AVVideoComp
filter.inputImage = request.sourceImage.cropped(to: alphaRect)
.transformed(by: CGAffineTransform(translationX: 0, y: -sourceRect.height))
filter.maskImage = request.sourceImage.cropped(to: sourceRect)
return request.finish(with: filter.outputImage!, context: nil)
request.finish(with: filter.outputImage!, context: nil)
ready()
})
composition.renderSize = videoSize
return composition
@ -60,6 +61,19 @@ private final class StickerAnimationNode: ASDisplayNode {
var started: () -> Void = {}
var ready = false
var visibility = false {
didSet {
if self.visibility {
if self.ready {
self.player?.play()
}
} else{
self.player?.pause()
}
}
}
var player: AVPlayer? {
get {
if self.isNodeLoaded {
@ -69,13 +83,7 @@ private final class StickerAnimationNode: ASDisplayNode {
}
}
set {
if let player = self.playerLayer.player {
player.removeObserver(self, forKeyPath: #keyPath(AVPlayer.rate))
}
self.playerLayer.player = newValue
if let newValue = newValue {
newValue.addObserver(self, forKeyPath: #keyPath(AVPlayer.rate), options: [], context: nil)
}
}
}
@ -95,6 +103,7 @@ private final class StickerAnimationNode: ASDisplayNode {
self.setLayerBlock({
let layer = AVPlayerLayer()
layer.isHidden = true
layer.videoGravity = .resize
if #available(iOSApplicationExtension 9.0, *) {
layer.pixelBufferAttributes = [(kCVPixelBufferPixelFormatTypeKey as String): kCVPixelFormatType_32BGRA]
}
@ -149,31 +158,22 @@ private final class StickerAnimationNode: ASDisplayNode {
if let playerItem = object as? AVPlayerItem, playerItem === self.playerItem {
if case .readyToPlay = playerItem.status, playerItem.videoComposition == nil {
playerItem.seekingWaitsForVideoCompositionRendering = true
let composition = createVideoComposition(for: playerItem)
let composition = createVideoComposition(for: playerItem, ready: { [weak self] in
Queue.mainQueue().async {
self?.playerLayer.isHidden = false
self?.started()
}
})
playerItem.videoComposition = composition
//playerItem.videoComposition = nil
//playerItem.videoComposition = composition
self.player?.play()
}
} else if let player = object as? AVPlayer, player === self.player {
if self.playerLayer.isHidden && player.rate > 0.0 {
//Queue.mainQueue().after(0.2) {
self.playerLayer.isHidden = false
self.started()
//}
ready = true
if self.visibility {
self.player?.play()
}
}
} else {
return super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
func play() {
}
func reset() {
}
}
class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
@ -244,13 +244,25 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
self.view.addGestureRecognizer(replyRecognizer)
}
override var visibility: ListViewItemNodeVisibility {
didSet {
if self.visibility != oldValue {
switch self.visibility {
case .visible:
self.animationNode.visibility = true
case .none:
self.animationNode.visibility = false
}
}
}
}
override func setupItem(_ item: ChatMessageItem) {
super.setupItem(item)
for media in item.message.media {
if let telegramFile = media as? TelegramMediaFile {
if self.telegramFile != telegramFile {
if self.telegramFile?.id != telegramFile.id {
self.telegramFile = telegramFile
self.imageNode.setSignal(chatMessageSticker(account: item.context.account, file: telegramFile, small: false, thumbnail: true))
self.animationNode.setup(account: item.context.account, fileReference: .message(message: MessageReference(item.message), media: telegramFile))

View File

@ -89,18 +89,6 @@ func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize:
return result
}
private func textMentionRangesEqual(_ lhs: [(NSRange, ChatTextInputTextMentionAttribute)], _ rhs: [(NSRange, ChatTextInputTextMentionAttribute)]) -> Bool {
if lhs.count != rhs.count {
return false
}
for i in 0 ..< lhs.count {
if lhs[i].0 != rhs[i].0 || lhs[i].1.peerId != rhs[i].1.peerId {
return false
}
}
return true
}
final class ChatTextInputTextMentionAttribute: NSObject {
let peerId: PeerId
@ -119,6 +107,18 @@ final class ChatTextInputTextMentionAttribute: NSObject {
}
}
private func textMentionRangesEqual(_ lhs: [(NSRange, ChatTextInputTextMentionAttribute)], _ rhs: [(NSRange, ChatTextInputTextMentionAttribute)]) -> Bool {
if lhs.count != rhs.count {
return false
}
for i in 0 ..< lhs.count {
if lhs[i].0 != rhs[i].0 || lhs[i].1.peerId != rhs[i].1.peerId {
return false
}
}
return true
}
final class ChatTextInputTextUrlAttribute: NSObject {
let url: String
@ -137,16 +137,19 @@ final class ChatTextInputTextUrlAttribute: NSObject {
}
}
func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat) {
guard let initialAttributedText = textNode.attributedText, initialAttributedText.length != 0 else {
return
private func textUrlRangesEqual(_ lhs: [(NSRange, ChatTextInputTextUrlAttribute)], _ rhs: [(NSRange, ChatTextInputTextUrlAttribute)]) -> Bool {
if lhs.count != rhs.count {
return false
}
for i in 0 ..< lhs.count {
if lhs[i].0 != rhs[i].0 || lhs[i].1.url != rhs[i].1.url {
return false
}
}
return true
}
let text: NSString = initialAttributedText.string as NSString
let fullRange = NSRange(location: 0, length: initialAttributedText.length)
let attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(initialAttributedText))
private func refreshTextMentions(text: NSString, initialAttributedText: NSAttributedString, attributedText: NSMutableAttributedString, fullRange: NSRange) {
var textMentionRanges: [(NSRange, ChatTextInputTextMentionAttribute)] = []
initialAttributedText.enumerateAttribute(ChatTextInputAttributes.textMention, in: fullRange, options: [], using: { value, range, _ in
if let value = value as? ChatTextInputTextMentionAttribute {
@ -260,8 +263,142 @@ func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: Prese
attributedText.addAttribute(ChatTextInputAttributes.textMention, value: ChatTextInputTextMentionAttribute(peerId: attribute.peerId), range: range)
}
}
}
let resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor)
private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributedString, attributedText: NSMutableAttributedString, fullRange: NSRange) {
var textUrlRanges: [(NSRange, ChatTextInputTextUrlAttribute)] = []
initialAttributedText.enumerateAttribute(ChatTextInputAttributes.textUrl, in: fullRange, options: [], using: { value, range, _ in
if let value = value as? ChatTextInputTextUrlAttribute {
textUrlRanges.append((range, value))
}
})
textUrlRanges.sort(by: { $0.0.location < $1.0.location })
let initialTextUrlRanges = textUrlRanges
for i in 0 ..< textUrlRanges.count {
let range = textUrlRanges[i].0
var validLower = range.lowerBound
inner1: for i in range.lowerBound ..< range.upperBound {
if let c = UnicodeScalar(text.character(at: i)) {
if alphanumericCharacters.contains(c) || c == " " as UnicodeScalar {
validLower = i
break inner1
}
} else {
break inner1
}
}
var validUpper = range.upperBound
inner2: for i in (validLower ..< range.upperBound).reversed() {
if let c = UnicodeScalar(text.character(at: i)) {
if alphanumericCharacters.contains(c) || c == " " as UnicodeScalar {
validUpper = i + 1
break inner2
}
} else {
break inner2
}
}
let minLower = (i == 0) ? fullRange.lowerBound : textUrlRanges[i - 1].0.upperBound
inner3: for i in (minLower ..< validLower).reversed() {
if let c = UnicodeScalar(text.character(at: i)) {
if alphanumericCharacters.contains(c) {
validLower = i
} else {
break inner3
}
} else {
break inner3
}
}
let maxUpper = (i == textUrlRanges.count - 1) ? fullRange.upperBound : textUrlRanges[i + 1].0.lowerBound
inner3: for i in validUpper ..< maxUpper {
if let c = UnicodeScalar(text.character(at: i)) {
if alphanumericCharacters.contains(c) {
validUpper = i + 1
} else {
break inner3
}
} else {
break inner3
}
}
textUrlRanges[i] = (NSRange(location: validLower, length: validUpper - validLower), textUrlRanges[i].1)
}
textUrlRanges = textUrlRanges.filter({ $0.0.length > 0 })
while textUrlRanges.count > 1 {
var hadReductions = false
outer: for i in 0 ..< textUrlRanges.count - 1 {
if textUrlRanges[i].1 === textUrlRanges[i + 1].1 {
var combine = true
inner: for j in textUrlRanges[i].0.upperBound ..< textUrlRanges[i + 1].0.lowerBound {
if let c = UnicodeScalar(text.character(at: j)) {
if alphanumericCharacters.contains(c) || c == " " as UnicodeScalar {
} else {
combine = false
break inner
}
} else {
combine = false
break inner
}
}
if combine {
hadReductions = true
textUrlRanges[i] = (NSRange(location: textUrlRanges[i].0.lowerBound, length: textUrlRanges[i + 1].0.upperBound - textUrlRanges[i].0.lowerBound), textUrlRanges[i].1)
textUrlRanges.remove(at: i + 1)
break outer
}
}
}
if !hadReductions {
break
}
}
if textUrlRanges.count > 1 {
outer: for i in (1 ..< textUrlRanges.count).reversed() {
for j in 0 ..< i {
if textUrlRanges[j].1 === textUrlRanges[i].1 {
textUrlRanges.remove(at: i)
continue outer
}
}
}
}
if !textUrlRangesEqual(textUrlRanges, initialTextUrlRanges) {
attributedText.removeAttribute(ChatTextInputAttributes.textUrl, range: fullRange)
for (range, attribute) in textUrlRanges {
attributedText.addAttribute(ChatTextInputAttributes.textUrl, value: ChatTextInputTextUrlAttribute(url: attribute.url), range: range)
}
}
}
func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat) {
guard var initialAttributedText = textNode.attributedText, initialAttributedText.length != 0 else {
return
}
var text: NSString = initialAttributedText.string as NSString
var fullRange = NSRange(location: 0, length: initialAttributedText.length)
var attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(initialAttributedText))
refreshTextMentions(text: text, initialAttributedText: initialAttributedText, attributedText: attributedText, fullRange: fullRange)
var resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor)
text = resultAttributedText.string as NSString
fullRange = NSRange(location: 0, length: initialAttributedText.length)
attributedText = NSMutableAttributedString(attributedString: stateAttributedStringForText(resultAttributedText))
refreshTextUrls(text: text, initialAttributedText: resultAttributedText, attributedText: attributedText, fullRange: fullRange)
resultAttributedText = textAttributedStringForStateText(attributedText, fontSize: baseFontSize, textColor: theme.chat.inputPanel.primaryTextColor, accentTextColor: theme.chat.inputPanel.panelControlAccentColor)
if !resultAttributedText.isEqual(to: initialAttributedText) {
textNode.textView.textStorage.removeAttribute(NSAttributedStringKey.font, range: fullRange)
@ -299,13 +436,13 @@ func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: Prese
if !fontAttributes.isEmpty {
var font: UIFont?
if fontAttributes == [.bold, .italic, .monospace] {
font = Font.semiboldItalicMonospace(baseFontSize)
} else if fontAttributes == [.bold, .italic] {
font = Font.semiboldItalic(baseFontSize)
} else if fontAttributes == [.bold, .monospace] {
font = Font.semiboldMonospace(baseFontSize)
} else if fontAttributes == [.italic, .monospace] {
font = Font.italicMonospace(baseFontSize)
} else if fontAttributes == [.bold] {
font = Font.semibold(baseFontSize)
} else if fontAttributes == [.italic] {

View File

@ -6,13 +6,14 @@ import Postbox
import TelegramCore
private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegate {
private let theme: PresentationTheme
private var theme: PresentationTheme
private let backgroundNode: ASImageNode
private let textInputNode: EditableTextNode
private let placeholderNode: ASTextNode
var updateHeight: (() -> Void)?
var complete: (() -> Void)?
var textChanged: ((String) -> Void)?
private let backgroundInsets = UIEdgeInsets(top: 8.0, left: 16.0, bottom: 15.0, right: 16.0)
private let inputInsets = UIEdgeInsets(top: 5.0, left: 12.0, bottom: 5.0, right: 12.0)
@ -41,7 +42,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
self.backgroundNode.isLayerBacked = true
self.backgroundNode.displaysAsynchronously = false
self.backgroundNode.displayWithoutProcessing = true
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: theme.actionSheet.itemBackgroundColor.withAlphaComponent(1.0), strokeColor: theme.actionSheet.inputBackgroundColor, strokeWidth: 1.0)
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode = EditableTextNode()
self.textInputNode.typingAttributes = [NSAttributedStringKey.font.rawValue: Font.regular(17.0), NSAttributedStringKey.foregroundColor.rawValue: theme.actionSheet.inputTextColor]
@ -52,6 +53,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
self.textInputNode.keyboardType = .URL
self.textInputNode.autocapitalizationType = .none
self.textInputNode.returnKeyType = .done
self.textInputNode.autocorrectionType = .no
self.placeholderNode = ASTextNode()
self.placeholderNode.isUserInteractionEnabled = false
@ -67,6 +69,14 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
self.addSubnode(self.placeholderNode)
}
func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 33.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
}
func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
let backgroundInsets = self.backgroundInsets
let inputInsets = self.inputInsets
@ -79,7 +89,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
let placeholderSize = self.placeholderNode.measure(backgroundFrame.size)
transition.updateFrame(node: self.placeholderNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + floor((backgroundFrame.size.width - placeholderSize.width) / 2.0), y: backgroundFrame.minY + floor((backgroundFrame.size.height - placeholderSize.height) / 2.0)), size: placeholderSize))
transition.updateFrame(node: self.placeholderNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY + floor((backgroundFrame.size.height - placeholderSize.height) / 2.0)), size: placeholderSize))
transition.updateFrame(node: self.textInputNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY), size: CGSize(width: backgroundFrame.size.width - inputInsets.left - inputInsets.right - accessoryButtonsWidth, height: backgroundFrame.size.height)))
@ -96,13 +106,7 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
@objc func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) {
self.updateTextNodeText(animated: true)
}
func editableTextNodeDidBeginEditing(_ editableTextNode: ASEditableTextNode) {
self.placeholderNode.isHidden = true
}
func editableTextNodeDidFinishEditing(_ editableTextNode: ASEditableTextNode) {
self.textChanged?(editableTextNode.textView.text)
self.placeholderNode.isHidden = !(editableTextNode.textView.text ?? "").isEmpty
}
@ -143,17 +147,19 @@ private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTex
private final class ChatTextLinkEditContentActionNode: HighlightableButtonNode {
private let backgroundNode: ASDisplayNode
private var theme: AlertControllerTheme
let action: TextAlertAction
private let backgroundNode: ASDisplayNode
init(theme: AlertControllerTheme, action: TextAlertAction) {
self.theme = theme
self.action = action
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = true
self.backgroundNode.alpha = 0.0
self.action = action
super.init()
self.titleNode.maximumNumberOfLines = 2
@ -176,16 +182,27 @@ private final class ChatTextLinkEditContentActionNode: HighlightableButtonNode {
self.updateTheme(theme)
}
func updateTheme(_ theme: AlertControllerTheme) {
self.backgroundNode.backgroundColor = theme.highlightedItemColor
var actionEnabled: Bool = true {
didSet {
self.isUserInteractionEnabled = self.actionEnabled
self.updateTitle()
}
}
func updateTheme(_ theme: AlertControllerTheme) {
self.theme = theme
self.backgroundNode.backgroundColor = theme.highlightedItemColor
self.updateTitle()
}
private func updateTitle() {
var font = Font.regular(17.0)
var color = theme.accentColor
var color: UIColor
switch self.action.type {
case .defaultAction, .genericAction:
break
color = self.actionEnabled ? self.theme.accentColor : self.theme.disabledColor
case .destructiveAction:
color = theme.destructiveColor
color = self.actionEnabled ? self.theme.destructiveColor : self.theme.disabledColor
}
switch self.action.type {
case .defaultAction:
@ -219,7 +236,7 @@ private final class ChatTextLinkEditAlertContentNode: AlertContentNode {
private let titleNode: ASTextNode
private let textNode: ASTextNode
private let inputFieldNode: ChatTextLinkEditInputFieldNode
let inputFieldNode: ChatTextLinkEditInputFieldNode
private let actionNodesSeparator: ASDisplayNode
private let actionNodes: [ChatTextLinkEditContentActionNode]
@ -250,9 +267,8 @@ private final class ChatTextLinkEditAlertContentNode: AlertContentNode {
self.textNode = ASTextNode()
self.textNode.maximumNumberOfLines = 2
self.inputFieldNode = ChatTextLinkEditInputFieldNode(theme: ptheme, placeholder: "")
self.inputFieldNode = ChatTextLinkEditInputFieldNode(theme: ptheme, placeholder: strings.TextFormat_AddLinkPlaceholder)
self.inputFieldNode.text = link ?? ""
self.inputFieldNode.placeholder = strings.TextFormat_AddLinkPlaceholder
self.actionNodesSeparator = ASDisplayNode()
self.actionNodesSeparator.isLayerBacked = true
@ -283,6 +299,7 @@ private final class ChatTextLinkEditAlertContentNode: AlertContentNode {
for actionNode in self.actionNodes {
self.addSubnode(actionNode)
}
self.actionNodes.last?.actionEnabled = !(link ?? "").isEmpty
for separatorNode in self.actionVerticalSeparators {
self.addSubnode(separatorNode)
@ -296,6 +313,12 @@ private final class ChatTextLinkEditAlertContentNode: AlertContentNode {
}
}
self.inputFieldNode.textChanged = { [weak self] text in
if let strongSelf = self, let lastNode = strongSelf.actionNodes.last {
lastNode.actionEnabled = !text.isEmpty
}
}
self.updateTheme(theme)
}
@ -445,8 +468,6 @@ private final class ChatTextLinkEditAlertContentNode: AlertContentNode {
func chatTextLinkEditController(sharedContext: SharedAccountContext, account: Account, text: String, link: String?, apply: @escaping (String?) -> Void) -> AlertController {
let presentationData = sharedContext.currentPresentationData.with { $0 }
let theme = presentationData.theme
let strings = presentationData.strings
var dismissImpl: ((Bool) -> Void)?
var applyImpl: (() -> Void)?
@ -458,7 +479,7 @@ func chatTextLinkEditController(sharedContext: SharedAccountContext, account: Ac
applyImpl?()
})]
let contentNode = ChatTextLinkEditAlertContentNode(theme: AlertControllerTheme(presentationTheme: theme), ptheme: theme, strings: strings, actions: actions, text: text, link: link)
let contentNode = ChatTextLinkEditAlertContentNode(theme: AlertControllerTheme(presentationTheme: presentationData.theme), ptheme: presentationData.theme, strings: presentationData.strings, actions: actions, text: text, link: link)
contentNode.complete = {
applyImpl?()
}
@ -470,14 +491,7 @@ func chatTextLinkEditController(sharedContext: SharedAccountContext, account: Ac
if !updatedLink.hasPrefix("http") && !updatedLink.hasPrefix("https") {
updatedLink = "http://\(updatedLink)"
}
if updatedLink.isEmpty {
if let _ = link {
dismissImpl?(true)
apply(updatedLink)
} else {
contentNode.animateError()
}
} else if isValidUrl(updatedLink) {
if !updatedLink.isEmpty && isValidUrl(updatedLink) {
dismissImpl?(true)
apply(updatedLink)
} else {
@ -485,7 +499,14 @@ func chatTextLinkEditController(sharedContext: SharedAccountContext, account: Ac
}
}
let controller = AlertController(theme: AlertControllerTheme(presentationTheme: theme), contentNode: contentNode)
let controller = AlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), contentNode: contentNode)
let presentationDataDisposable = sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
controller?.theme = AlertControllerTheme(presentationTheme: presentationData.theme)
contentNode?.inputFieldNode.updateTheme(presentationData.theme)
})
controller.dismissed = {
presentationDataDisposable.dispose()
}
dismissImpl = { [weak controller] animated in
if animated {
controller?.dismissAnimated()

View File

@ -43,7 +43,7 @@ extension ActionSheetController {
public extension AlertControllerTheme {
convenience init(presentationTheme: PresentationTheme) {
let actionSheet = presentationTheme.actionSheet
self.init(backgroundColor: actionSheet.opaqueItemBackgroundColor, separatorColor: actionSheet.opaqueItemSeparatorColor, highlightedItemColor: actionSheet.opaqueItemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor)
self.init(backgroundColor: actionSheet.opaqueItemBackgroundColor, separatorColor: actionSheet.opaqueItemSeparatorColor, highlightedItemColor: actionSheet.opaqueItemHighlightedBackgroundColor, primaryColor: actionSheet.primaryTextColor, secondaryColor: actionSheet.secondaryTextColor, accentColor: actionSheet.controlAccentColor, destructiveColor: actionSheet.destructiveActionTextColor, disabledColor: actionSheet.disabledActionTextColor)
}
}

View File

@ -310,6 +310,8 @@ private let actionSheet = PresentationThemeActionSheet(
secondaryTextColor: UIColor(white: 1.0, alpha: 0.5), //!!!
controlAccentColor: accentColor,
inputBackgroundColor: UIColor(rgb: 0x182330), //!!!
inputHollowBackgroundColor: UIColor(rgb: 0x182330),
inputBorderColor: UIColor(rgb: 0x182330),
inputPlaceholderColor: UIColor(rgb: 0x8B9197), //!!!
inputTextColor: .white,
inputClearButtonColor: UIColor(rgb: 0x8B9197),

View File

@ -308,6 +308,8 @@ private let actionSheet = PresentationThemeActionSheet(
secondaryTextColor: UIColor(rgb: 0x5e5e5e), //!!!
controlAccentColor: accentColor,
inputBackgroundColor: UIColor(rgb: 0x545454), //!!!
inputHollowBackgroundColor: UIColor(rgb: 0x545454),
inputBorderColor: UIColor(rgb: 0x545454),
inputPlaceholderColor: UIColor(rgb: 0xaaaaaa), //!!!
inputTextColor: .white,
inputClearButtonColor: UIColor(rgb: 0xaaaaaa),

View File

@ -414,11 +414,13 @@ private func makeDefaultPresentationTheme(accentColor: UIColor, serviceBackgroun
standardActionTextColor: accentColor,
opaqueItemSeparatorColor: UIColor(white: 0.9, alpha: 1.0),
destructiveActionTextColor: destructiveColor,
disabledActionTextColor: UIColor(rgb: 0x4d4d4d),
disabledActionTextColor: UIColor(rgb: 0xb3b3b3),
primaryTextColor: .black,
secondaryTextColor: UIColor(rgb: 0x5e5e5e),
controlAccentColor: accentColor,
inputBackgroundColor: UIColor(rgb: 0xe9e9e9),
inputHollowBackgroundColor: .white,
inputBorderColor: UIColor(rgb: 0xe4e4e6),
inputPlaceholderColor: UIColor(rgb: 0x818086),
inputTextColor: .black,
inputClearButtonColor: UIColor(rgb: 0x7b7b81),

View File

@ -199,12 +199,14 @@ public final class PresentationThemeActionSheet {
public let secondaryTextColor: UIColor
public let controlAccentColor: UIColor
public let inputBackgroundColor: UIColor
public let inputHollowBackgroundColor: UIColor
public let inputBorderColor: UIColor
public let inputPlaceholderColor: UIColor
public let inputTextColor: UIColor
public let inputClearButtonColor: UIColor
public let checkContentColor: UIColor
init(dimColor: UIColor, backgroundType: PresentationThemeActionSheetBackgroundType, opaqueItemBackgroundColor: UIColor, itemBackgroundColor: UIColor, opaqueItemHighlightedBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, standardActionTextColor: UIColor, opaqueItemSeparatorColor: UIColor, destructiveActionTextColor: UIColor, disabledActionTextColor: UIColor, primaryTextColor: UIColor, secondaryTextColor: UIColor, controlAccentColor: UIColor, inputBackgroundColor: UIColor, inputPlaceholderColor: UIColor, inputTextColor: UIColor, inputClearButtonColor: UIColor, checkContentColor: UIColor) {
init(dimColor: UIColor, backgroundType: PresentationThemeActionSheetBackgroundType, opaqueItemBackgroundColor: UIColor, itemBackgroundColor: UIColor, opaqueItemHighlightedBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, standardActionTextColor: UIColor, opaqueItemSeparatorColor: UIColor, destructiveActionTextColor: UIColor, disabledActionTextColor: UIColor, primaryTextColor: UIColor, secondaryTextColor: UIColor, controlAccentColor: UIColor, inputBackgroundColor: UIColor, inputHollowBackgroundColor: UIColor, inputBorderColor: UIColor, inputPlaceholderColor: UIColor, inputTextColor: UIColor, inputClearButtonColor: UIColor, checkContentColor: UIColor) {
self.dimColor = dimColor
self.backgroundType = backgroundType
self.opaqueItemBackgroundColor = opaqueItemBackgroundColor
@ -219,6 +221,8 @@ public final class PresentationThemeActionSheet {
self.secondaryTextColor = secondaryTextColor
self.controlAccentColor = controlAccentColor
self.inputBackgroundColor = inputBackgroundColor
self.inputHollowBackgroundColor = inputHollowBackgroundColor
self.inputBorderColor = inputBorderColor
self.inputPlaceholderColor = inputPlaceholderColor
self.inputTextColor = inputTextColor
self.inputClearButtonColor = inputClearButtonColor

View File

@ -4,9 +4,8 @@ import TelegramCore
public func textAlertController(context: AccountContext, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal) -> AlertController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let theme = presentationData.theme
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: theme), title: title, text: text, actions: actions)
let controller = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: title, text: text, actions: actions)
let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller] presentationData in
controller?.theme = AlertControllerTheme(presentationTheme: presentationData.theme)
})