Various fixes

This commit is contained in:
Ilya Laktyushin 2023-08-08 15:20:07 +02:00
parent 67c07d35ed
commit 29707a7264
5 changed files with 105 additions and 36 deletions

View File

@ -163,10 +163,22 @@ private final class StickerSelectionComponent: Component {
}, },
sendEmoji: { _, _, _ in sendEmoji: { _, _, _ in
}, },
sendGif: { _, _, _, _, _ in sendGif: { [weak self] file, _, _, _, _ in
if let self, let controller = self.component?.getController() {
controller.completion(.video(file.media))
controller.dismiss(animated: true)
}
return false return false
}, },
sendBotContextResultAsGif: { _, _, _, _, _, _ in sendBotContextResultAsGif: { [weak self] collection, result, _, _, _, _ in
if let self, let controller = self.component?.getController() {
if case let .internalReference(reference) = result {
if let file = reference.file {
controller.completion(.video(file))
controller.dismiss(animated: true)
}
}
}
return false return false
}, },
updateChoosingSticker: { _ in }, updateChoosingSticker: { _ in },
@ -320,7 +332,7 @@ private final class StickerSelectionComponent: Component {
inputNodeInteraction: inputNodeInteraction, inputNodeInteraction: inputNodeInteraction,
mode: mappedMode, mode: mappedMode,
stickerActionTitle: presentationData.strings.StickerPack_AddSticker, stickerActionTitle: presentationData.strings.StickerPack_AddSticker,
trendingGifsPromise: Promise(nil), trendingGifsPromise: self.component?.getController()?.node.trendingGifsPromise ?? Promise(nil),
cancel: { cancel: {
}, },
peekBehavior: stickerPeekBehavior peekBehavior: stickerPeekBehavior
@ -416,7 +428,7 @@ public class StickerPickerScreen: ViewController {
private var content: StickerPickerInputData? private var content: StickerPickerInputData?
private let contentDisposable = MetaDisposable() private let contentDisposable = MetaDisposable()
private var hasRecentGifsDisposable: Disposable? private var hasRecentGifsDisposable: Disposable?
private let trendingGifsPromise = Promise<ChatMediaInputGifPaneTrendingState?>(nil) fileprivate let trendingGifsPromise = Promise<ChatMediaInputGifPaneTrendingState?>(nil)
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation? private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
private(set) var isExpanded = false private(set) var isExpanded = false
@ -584,6 +596,16 @@ public class StickerPickerScreen: ViewController {
}) })
} }
self.trendingGifsPromise.set(.single(nil))
self.trendingGifsPromise.set(paneGifSearchForQuery(context: context, query: "", offset: nil, incompleteResults: true, delayRequest: false, updateActivity: nil)
|> map { items -> ChatMediaInputGifPaneTrendingState? in
if let items = items {
return ChatMediaInputGifPaneTrendingState(files: items.files, nextOffset: items.nextOffset)
} else {
return nil
}
})
self.gifInputInteraction = GifPagerContentComponent.InputInteraction( self.gifInputInteraction = GifPagerContentComponent.InputInteraction(
performItemAction: { [weak self] item, view, rect in performItemAction: { [weak self] item, view, rect in
guard let self else { guard let self else {

View File

@ -100,7 +100,7 @@ public final class TwoFactorDataInputScreen: ViewController {
super.viewWillAppear(animated) super.viewWillAppear(animated)
switch self.mode { switch self.mode {
case .rememberPassword, .password: case .rememberPassword, .password, .passwordHint, .emailAddress:
(self.displayNode as? TwoFactorDataInputScreenNode)?.focus() (self.displayNode as? TwoFactorDataInputScreenNode)?.focus()
default: default:
break break
@ -210,6 +210,7 @@ public final class TwoFactorDataInputScreen: ViewController {
navigationController.replaceController(strongSelf, with: TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .passwordHint(recovery: recovery, password: values[0], doneText: doneText), stateUpdated: strongSelf.stateUpdated, presentation: strongSelf.navigationPresentation), animated: true) navigationController.replaceController(strongSelf, with: TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .passwordHint(recovery: recovery, password: values[0], doneText: doneText), stateUpdated: strongSelf.stateUpdated, presentation: strongSelf.navigationPresentation), animated: true)
case let .emailAddress(password, hint, doneText): case let .emailAddress(password, hint, doneText):
guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else { guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else {
(strongSelf.displayNode as? TwoFactorDataInputScreenNode)?.onAction(success: false)
return return
} }
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil)) let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
@ -1303,6 +1304,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
} }
} }
private var skipIsHiddenUntilError = false
init(sharedContext: SharedAccountContext, presentationData: PresentationData, mode: TwoFactorDataInputMode, action: @escaping () -> Void, skipAction: @escaping () -> Void, changeEmailAction: @escaping () -> Void, resendCodeAction: @escaping () -> Void) { init(sharedContext: SharedAccountContext, presentationData: PresentationData, mode: TwoFactorDataInputMode, action: @escaping () -> Void, skipAction: @escaping () -> Void, changeEmailAction: @escaping () -> Void, resendCodeAction: @escaping () -> Void) {
self.presentationData = presentationData self.presentationData = presentationData
self.mode = mode self.mode = mode
@ -1413,6 +1416,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Email_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor) text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Email_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
buttonText = presentationData.strings.TwoFactorSetup_Email_Action buttonText = presentationData.strings.TwoFactorSetup_Email_Action
skipActionText = presentationData.strings.TwoFactorSetup_Email_SkipAction skipActionText = presentationData.strings.TwoFactorSetup_Email_SkipAction
self.skipIsHiddenUntilError = true
changeEmailActionText = "" changeEmailActionText = ""
resendCodeActionText = "" resendCodeActionText = ""
inputNodes = [ inputNodes = [
@ -1538,8 +1542,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
self.skipActionTitleNode.displaysAsynchronously = false self.skipActionTitleNode.displaysAsynchronously = false
self.skipActionTitleNode.attributedText = NSAttributedString(string: skipActionText, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemAccentColor) self.skipActionTitleNode.attributedText = NSAttributedString(string: skipActionText, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemAccentColor)
self.skipActionButtonNode = HighlightTrackingButtonNode() self.skipActionButtonNode = HighlightTrackingButtonNode()
self.skipActionTitleNode.isHidden = skipActionText.isEmpty self.skipActionTitleNode.isHidden = skipActionText.isEmpty || self.skipIsHiddenUntilError
self.skipActionButtonNode.isHidden = skipActionText.isEmpty self.skipActionButtonNode.isHidden = skipActionText.isEmpty || self.skipIsHiddenUntilError
self.changeEmailActionTitleNode = ImmediateTextNode() self.changeEmailActionTitleNode = ImmediateTextNode()
self.changeEmailActionTitleNode.isUserInteractionEnabled = false self.changeEmailActionTitleNode.isUserInteractionEnabled = false
@ -1707,8 +1711,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
case .emailAddress, .updateEmailAddress, .passwordRecovery: case .emailAddress, .updateEmailAddress, .passwordRecovery:
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty }) let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
strongSelf.buttonNode.isHidden = !hasText strongSelf.buttonNode.isHidden = !hasText
strongSelf.skipActionTitleNode.isHidden = hasText strongSelf.skipActionTitleNode.isHidden = hasText || strongSelf.skipIsHiddenUntilError
strongSelf.skipActionButtonNode.isHidden = hasText strongSelf.skipActionButtonNode.isHidden = hasText || strongSelf.skipIsHiddenUntilError
case let .emailConfirmation(_, _, codeLength, _): case let .emailConfirmation(_, _, codeLength, _):
let text = strongSelf.inputNodes[0].text let text = strongSelf.inputNodes[0].text
let hasText = !text.isEmpty let hasText = !text.isEmpty
@ -1822,6 +1826,19 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
func onAction(success: Bool) { func onAction(success: Bool) {
switch self.mode { switch self.mode {
case .emailAddress:
if !success {
self.inputNodes.first?.layer.addShakeAnimation()
HapticFeedback().error()
if self.skipIsHiddenUntilError {
self.skipIsHiddenUntilError = false
self.skipActionTitleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.skipActionTitleNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.2)
self.skipActionTitleNode.isHidden = false
self.skipActionButtonNode.isHidden = false
}
}
case .rememberPassword: case .rememberPassword:
if !success { if !success {
self.skipActionTitleNode.isHidden = false self.skipActionTitleNode.isHidden = false

View File

@ -401,7 +401,8 @@ public final class PeerListItemComponent: Component {
let labelData: (String, Bool) let labelData: (String, Bool)
if let presence = component.presence { if let presence = component.presence {
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
labelData = stringAndActivityForUserPresence(strings: component.strings, dateTimeFormat: PresentationDateTimeFormat(), presence: presence, relativeTo: Int32(timestamp)) let dateTimeFormat = component.context.sharedContext.currentPresentationData.with { $0 }.dateTimeFormat
labelData = stringAndActivityForUserPresence(strings: component.strings, dateTimeFormat: dateTimeFormat, presence: presence, relativeTo: Int32(timestamp))
} else if let subtitle = component.subtitle { } else if let subtitle = component.subtitle {
labelData = (subtitle, false) labelData = (subtitle, false)
} else { } else {

View File

@ -32,6 +32,7 @@ swift_library(
"//submodules/AppBundle:AppBundle", "//submodules/AppBundle:AppBundle",
"//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/AttachmentUI:AttachmentUI", "//submodules/AttachmentUI:AttachmentUI",
"//submodules/RadialStatusNode:RadialStatusNode",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -7,6 +7,7 @@ import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
import CheckNode import CheckNode
import PhotoResources import PhotoResources
import RadialStatusNode
final class WebSearchItem: GridItem { final class WebSearchItem: GridItem {
var section: GridSection? var section: GridSection?
@ -44,6 +45,7 @@ final class WebSearchItemNode: GridItemNode {
private let imageNodeBackground: ASDisplayNode private let imageNodeBackground: ASDisplayNode
private let imageNode: TransformImageNode private let imageNode: TransformImageNode
private var checkNode: CheckNode? private var checkNode: CheckNode?
private var statusNode: RadialStatusNode?
private(set) var item: WebSearchItem? private(set) var item: WebSearchItem?
private var currentDimensions: CGSize? private var currentDimensions: CGSize?
@ -81,6 +83,32 @@ final class WebSearchItemNode: GridItemNode {
self.imageNode.view.addGestureRecognizer(recognizer) self.imageNode.view.addGestureRecognizer(recognizer)
} }
func updateProgress(_ value: Float?, animated: Bool) {
if let value {
let statusNode: RadialStatusNode
if let current = self.statusNode {
statusNode = current
} else {
statusNode = RadialStatusNode(backgroundNodeColor: UIColor(rgb: 0x000000, alpha: 0.6))
statusNode.isUserInteractionEnabled = false
self.addSubnode(statusNode)
self.statusNode = statusNode
}
let adjustedProgress = max(0.027, CGFloat(value))
let state: RadialStatusNodeState = .progress(color: .white, lineWidth: nil, value: adjustedProgress, cancelEnabled: true, animateRotation: true)
statusNode.transitionToState(state)
} else if let statusNode = self.statusNode {
self.statusNode = nil
if animated {
statusNode.transitionToState(.none, animated: true, completion: { [weak statusNode] in
statusNode?.removeFromSupernode()
})
} else {
statusNode.removeFromSupernode()
}
}
}
func setup(item: WebSearchItem, synchronousLoad: Bool) { func setup(item: WebSearchItem, synchronousLoad: Bool) {
if self.item !== item { if self.item !== item {
var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?