mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Web app improvements
This commit is contained in:
parent
5941becc33
commit
0f597d457e
@ -5,6 +5,13 @@ public struct AttachmentMainButtonState {
|
|||||||
public enum Background {
|
public enum Background {
|
||||||
case color(UIColor)
|
case color(UIColor)
|
||||||
case premium
|
case premium
|
||||||
|
|
||||||
|
public var colorValue: UIColor? {
|
||||||
|
if case let .color(color) = self {
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Progress: Equatable {
|
public enum Progress: Equatable {
|
||||||
@ -18,6 +25,13 @@ public struct AttachmentMainButtonState {
|
|||||||
case bold
|
case bold
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Position: String, Equatable {
|
||||||
|
case top
|
||||||
|
case bottom
|
||||||
|
case left
|
||||||
|
case right
|
||||||
|
}
|
||||||
|
|
||||||
public let text: String?
|
public let text: String?
|
||||||
public let font: Font
|
public let font: Font
|
||||||
public let background: Background
|
public let background: Background
|
||||||
@ -25,6 +39,8 @@ public struct AttachmentMainButtonState {
|
|||||||
public let isVisible: Bool
|
public let isVisible: Bool
|
||||||
public let progress: Progress
|
public let progress: Progress
|
||||||
public let isEnabled: Bool
|
public let isEnabled: Bool
|
||||||
|
public let hasShimmer: Bool
|
||||||
|
public let position: Position?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
text: String?,
|
text: String?,
|
||||||
@ -33,7 +49,9 @@ public struct AttachmentMainButtonState {
|
|||||||
textColor: UIColor,
|
textColor: UIColor,
|
||||||
isVisible: Bool,
|
isVisible: Bool,
|
||||||
progress: Progress,
|
progress: Progress,
|
||||||
isEnabled: Bool
|
isEnabled: Bool,
|
||||||
|
hasShimmer: Bool,
|
||||||
|
position: Position? = nil
|
||||||
) {
|
) {
|
||||||
self.text = text
|
self.text = text
|
||||||
self.font = font
|
self.font = font
|
||||||
@ -42,9 +60,11 @@ public struct AttachmentMainButtonState {
|
|||||||
self.isVisible = isVisible
|
self.isVisible = isVisible
|
||||||
self.progress = progress
|
self.progress = progress
|
||||||
self.isEnabled = isEnabled
|
self.isEnabled = isEnabled
|
||||||
|
self.hasShimmer = hasShimmer
|
||||||
|
self.position = position
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var initial: AttachmentMainButtonState {
|
public static var initial: AttachmentMainButtonState {
|
||||||
return AttachmentMainButtonState(text: nil, font: .bold, background: .color(.clear), textColor: .clear, isVisible: false, progress: .none, isEnabled: false)
|
return AttachmentMainButtonState(text: nil, font: .bold, background: .color(.clear), textColor: .clear, isVisible: false, progress: .none, isEnabled: false, hasShimmer: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,8 +215,11 @@ public protocol AttachmentMediaPickerContext {
|
|||||||
|
|
||||||
var loadingProgress: Signal<CGFloat?, NoError> { get }
|
var loadingProgress: Signal<CGFloat?, NoError> { get }
|
||||||
var mainButtonState: Signal<AttachmentMainButtonState?, NoError> { get }
|
var mainButtonState: Signal<AttachmentMainButtonState?, NoError> { get }
|
||||||
|
var secondaryButtonState: Signal<AttachmentMainButtonState?, NoError> { get }
|
||||||
|
var bottomPanelBackgroundColor: Signal<UIColor?, NoError> { get }
|
||||||
|
|
||||||
func mainButtonAction()
|
func mainButtonAction()
|
||||||
|
func secondaryButtonAction()
|
||||||
|
|
||||||
func setCaption(_ caption: NSAttributedString)
|
func setCaption(_ caption: NSAttributedString)
|
||||||
func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode, parameters: ChatSendMessageActionSheetController.SendParameters?)
|
func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode, parameters: ChatSendMessageActionSheetController.SendParameters?)
|
||||||
@ -262,6 +265,14 @@ public extension AttachmentMediaPickerContext {
|
|||||||
return .single(nil)
|
return .single(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var secondaryButtonState: Signal<AttachmentMainButtonState?, NoError> {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var bottomPanelBackgroundColor: Signal<UIColor?, NoError> {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
func setCaption(_ caption: NSAttributedString) {
|
func setCaption(_ caption: NSAttributedString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +284,9 @@ public extension AttachmentMediaPickerContext {
|
|||||||
|
|
||||||
func mainButtonAction() {
|
func mainButtonAction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func secondaryButtonAction() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func generateShadowImage() -> UIImage? {
|
private func generateShadowImage() -> UIImage? {
|
||||||
@ -364,6 +378,8 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
|
|
||||||
private let loadingProgressDisposable = MetaDisposable()
|
private let loadingProgressDisposable = MetaDisposable()
|
||||||
private let mainButtonStateDisposable = MetaDisposable()
|
private let mainButtonStateDisposable = MetaDisposable()
|
||||||
|
private let secondaryButtonStateDisposable = MetaDisposable()
|
||||||
|
private let bottomPanelBackgroundColorDisposable = MetaDisposable()
|
||||||
|
|
||||||
private var selectionCount: Int = 0
|
private var selectionCount: Int = 0
|
||||||
|
|
||||||
@ -408,11 +424,44 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
self.secondaryButtonStateDisposable.set((mediaPickerContext.secondaryButtonState
|
||||||
|
|> deliverOnMainQueue).startStrict(next: { [weak self] mainButtonState in
|
||||||
|
if let strongSelf = self {
|
||||||
|
let _ = (strongSelf.panel.animatingTransitionPromise.get()
|
||||||
|
|> filter { value in
|
||||||
|
return !value
|
||||||
|
}
|
||||||
|
|> take(1)).startStandalone(next: { [weak self] _ in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.panel.updateSecondaryButtonState(mainButtonState)
|
||||||
|
if let layout = strongSelf.validLayout {
|
||||||
|
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .spring))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
self.bottomPanelBackgroundColorDisposable.set((mediaPickerContext.bottomPanelBackgroundColor
|
||||||
|
|> deliverOnMainQueue).startStrict(next: { [weak self] color in
|
||||||
|
if let strongSelf = self {
|
||||||
|
let _ = (strongSelf.panel.animatingTransitionPromise.get()
|
||||||
|
|> filter { value in
|
||||||
|
return !value
|
||||||
|
}
|
||||||
|
|> take(1)).startStandalone(next: { [weak self] _ in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.panel.updateCustomBottomPanelBackgroundColor(color)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
self.updateSelectionCount(0)
|
self.updateSelectionCount(0)
|
||||||
self.mediaSelectionCountDisposable.set(nil)
|
self.mediaSelectionCountDisposable.set(nil)
|
||||||
self.loadingProgressDisposable.set(nil)
|
self.loadingProgressDisposable.set(nil)
|
||||||
self.mainButtonStateDisposable.set(nil)
|
self.mainButtonStateDisposable.set(nil)
|
||||||
|
self.secondaryButtonStateDisposable.set(nil)
|
||||||
|
self.bottomPanelBackgroundColorDisposable.set(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,12 +639,18 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.panel.mainButtonPressed = { [weak self] in
|
self.panel.onMainButtonPressed = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.mediaPickerContext?.mainButtonAction()
|
strongSelf.mediaPickerContext?.mainButtonAction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.panel.onSecondaryButtonPressed = { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.mediaPickerContext?.secondaryButtonAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.panel.requestLayout = { [weak self] in
|
self.panel.requestLayout = { [weak self] in
|
||||||
if let strongSelf = self, let layout = strongSelf.validLayout {
|
if let strongSelf = self, let layout = strongSelf.validLayout {
|
||||||
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.2, curve: .easeInOut))
|
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.2, curve: .easeInOut))
|
||||||
@ -628,6 +683,8 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
self.mediaSelectionCountDisposable.dispose()
|
self.mediaSelectionCountDisposable.dispose()
|
||||||
self.loadingProgressDisposable.dispose()
|
self.loadingProgressDisposable.dispose()
|
||||||
self.mainButtonStateDisposable.dispose()
|
self.mainButtonStateDisposable.dispose()
|
||||||
|
self.secondaryButtonStateDisposable.dispose()
|
||||||
|
self.bottomPanelBackgroundColorDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var inputContainerHeight: CGFloat?
|
private var inputContainerHeight: CGFloat?
|
||||||
@ -985,10 +1042,7 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
|
|
||||||
var containerLayout = layout
|
var containerLayout = layout
|
||||||
let containerRect: CGRect
|
let containerRect: CGRect
|
||||||
var isCompact = true
|
|
||||||
if case .regular = layout.metrics.widthClass {
|
if case .regular = layout.metrics.widthClass {
|
||||||
isCompact = false
|
|
||||||
|
|
||||||
let availableHeight = layout.size.height - (layout.inputHeight ?? 0.0) - 60.0
|
let availableHeight = layout.size.height - (layout.inputHeight ?? 0.0) - 60.0
|
||||||
|
|
||||||
let size = CGSize(width: 390.0, height: min(620.0, availableHeight))
|
let size = CGSize(width: 390.0, height: min(620.0, availableHeight))
|
||||||
@ -1055,7 +1109,7 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
|
|
||||||
var containerInsets = containerLayout.intrinsicInsets
|
var containerInsets = containerLayout.intrinsicInsets
|
||||||
var hasPanel = false
|
var hasPanel = false
|
||||||
let previousHasButton = self.hasButton
|
// let previousHasButton = self.hasButton
|
||||||
let hasButton = self.panel.isButtonVisible && !self.isDismissing
|
let hasButton = self.panel.isButtonVisible && !self.isDismissing
|
||||||
self.hasButton = hasButton
|
self.hasButton = hasButton
|
||||||
if let controller = self.controller, controller.buttons.count > 1 || controller.hasTextInput {
|
if let controller = self.controller, controller.buttons.count > 1 || controller.hasTextInput {
|
||||||
@ -1066,53 +1120,21 @@ public class AttachmentController: ViewController, MinimizableController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isEffecitvelyCollapsedUpdated = (self.selectionCount > 0) != (self.panel.isSelecting)
|
let isEffecitvelyCollapsedUpdated = (self.selectionCount > 0) != (self.panel.isSelecting)
|
||||||
var panelHeight = self.panel.update(layout: containerLayout, buttons: self.controller?.buttons ?? [], isSelecting: self.selectionCount > 0, elevateProgress: !hasPanel && !hasButton, transition: transition)
|
let panelHeight = self.panel.update(layout: containerLayout, buttons: self.controller?.buttons ?? [], isSelecting: self.selectionCount > 0, elevateProgress: !hasPanel && !hasButton, transition: transition)
|
||||||
if fromMenu && !hasButton, let inputContainerHeight = self.inputContainerHeight {
|
|
||||||
panelHeight = inputContainerHeight
|
|
||||||
}
|
|
||||||
if hasPanel || hasButton {
|
if hasPanel || hasButton {
|
||||||
containerInsets.bottom = panelHeight
|
containerInsets.bottom = panelHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
var transitioning = false
|
|
||||||
if fromMenu && previousHasButton != hasButton, let (_, _, getTransition) = controller.getInputContainerNode(), let inputTransition = getTransition() {
|
|
||||||
if hasButton {
|
|
||||||
self.panel.animateTransitionIn(inputTransition: inputTransition, transition: transition)
|
|
||||||
} else {
|
|
||||||
self.panel.animateTransitionOut(inputTransition: inputTransition, dismissed: false, transition: transition)
|
|
||||||
}
|
|
||||||
transitioning = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var panelTransition = transition
|
var panelTransition = transition
|
||||||
if isEffecitvelyCollapsedUpdated {
|
if isEffecitvelyCollapsedUpdated {
|
||||||
panelTransition = .animated(duration: 0.25, curve: .easeInOut)
|
panelTransition = .animated(duration: 0.25, curve: .easeInOut)
|
||||||
}
|
}
|
||||||
var panelY = containerRect.height - panelHeight
|
var panelY = containerRect.height - panelHeight
|
||||||
if fromMenu && isCompact {
|
if !hasPanel && !hasButton {
|
||||||
panelY = layout.size.height - panelHeight
|
|
||||||
} else if !hasPanel && !hasButton {
|
|
||||||
panelY = containerRect.height
|
panelY = containerRect.height
|
||||||
}
|
}
|
||||||
|
|
||||||
if fromMenu && isCompact {
|
panelTransition.updateFrame(node: self.panel, frame: CGRect(origin: CGPoint(x: 0.0, y: panelY), size: CGSize(width: containerRect.width, height: panelHeight)))
|
||||||
if hasButton {
|
|
||||||
self.panel.isHidden = false
|
|
||||||
self.inputContainerNode?.isHidden = true
|
|
||||||
} else if !transitioning {
|
|
||||||
if !self.panel.animatingTransition {
|
|
||||||
self.panel.isHidden = true
|
|
||||||
self.inputContainerNode?.isHidden = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panelTransition.updateFrame(node: self.panel, frame: CGRect(origin: CGPoint(x: 0.0, y: panelY), size: CGSize(width: containerRect.width, height: panelHeight)), completion: { [weak self] finished in
|
|
||||||
if transitioning && finished, isCompact {
|
|
||||||
self?.panel.isHidden = !hasButton
|
|
||||||
self?.inputContainerNode?.isHidden = hasButton
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var shadowFrame = containerRect.insetBy(dx: -60.0, dy: -60.0)
|
var shadowFrame = containerRect.insetBy(dx: -60.0, dy: -60.0)
|
||||||
shadowFrame.size.height -= 12.0
|
shadowFrame.size.height -= 12.0
|
||||||
|
@ -463,7 +463,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
|
|||||||
let diameter: CGFloat = size.height - 22.0
|
let diameter: CGFloat = size.height - 22.0
|
||||||
let progressFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(buttonOffset + (buttonWidth - diameter) / 2.0), y: floorToScreenPixels((size.height - diameter) / 2.0)), size: CGSize(width: diameter, height: diameter))
|
let progressFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(buttonOffset + (buttonWidth - diameter) / 2.0), y: floorToScreenPixels((size.height - diameter) / 2.0)), size: CGSize(width: diameter, height: diameter))
|
||||||
progressNode.frame = progressFrame
|
progressNode.frame = progressFrame
|
||||||
progressNode.image = generateIndefiniteActivityIndicatorImage(color: .white, diameter: diameter, lineWidth: 3.0)
|
progressNode.image = generateIndefiniteActivityIndicatorImage(color: self.state.textColor, diameter: diameter, lineWidth: 3.0)
|
||||||
|
|
||||||
self.addSubnode(progressNode)
|
self.addSubnode(progressNode)
|
||||||
|
|
||||||
@ -499,7 +499,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func setupShimmering() {
|
private func setupShimmering() {
|
||||||
if case .premium = self.state.background {
|
if self.state.hasShimmer {
|
||||||
if self.shimmerView == nil {
|
if self.shimmerView == nil {
|
||||||
let shimmerView = ShimmerEffectForegroundView()
|
let shimmerView = ShimmerEffectForegroundView()
|
||||||
shimmerView.isUserInteractionEnabled = false
|
shimmerView.isUserInteractionEnabled = false
|
||||||
@ -601,7 +601,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(size: CGSize, state: AttachmentMainButtonState, transition: ContainedViewLayoutTransition) {
|
func updateLayout(size: CGSize, state: AttachmentMainButtonState, animateBackground: Bool = false, transition: ContainedViewLayoutTransition) {
|
||||||
let previousState = self.state
|
let previousState = self.state
|
||||||
self.state = state
|
self.state = state
|
||||||
self.size = size
|
self.size = size
|
||||||
@ -621,13 +621,23 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
|
|||||||
self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: state.textColor)
|
self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: state.textColor)
|
||||||
|
|
||||||
let textSize = self.textNode.updateLayout(size)
|
let textSize = self.textNode.updateLayout(size)
|
||||||
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
|
let textFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
|
||||||
|
if self.textNode.frame.width.isZero {
|
||||||
|
self.textNode.frame = textFrame
|
||||||
|
} else {
|
||||||
|
self.textNode.bounds = CGRect(origin: .zero, size: textSize)
|
||||||
|
transition.updatePosition(node: self.textNode, position: textFrame.center)
|
||||||
|
}
|
||||||
|
|
||||||
switch state.background {
|
switch state.background {
|
||||||
case let .color(backgroundColor):
|
case let .color(backgroundColor):
|
||||||
self.backgroundAnimationNode.image = nil
|
self.backgroundAnimationNode.image = nil
|
||||||
self.backgroundAnimationNode.layer.removeAllAnimations()
|
self.backgroundAnimationNode.layer.removeAllAnimations()
|
||||||
|
if animateBackground {
|
||||||
|
ContainedViewLayoutTransition.animated(duration: 0.2, curve: .linear).updateBackgroundColor(node: self, color: backgroundColor)
|
||||||
|
} else {
|
||||||
self.backgroundColor = backgroundColor
|
self.backgroundColor = backgroundColor
|
||||||
|
}
|
||||||
case .premium:
|
case .premium:
|
||||||
if self.backgroundAnimationNode.image == nil {
|
if self.backgroundAnimationNode.image == nil {
|
||||||
let backgroundColors = [
|
let backgroundColors = [
|
||||||
@ -706,9 +716,12 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
private var textInputPanelNode: AttachmentTextInputPanelNode?
|
private var textInputPanelNode: AttachmentTextInputPanelNode?
|
||||||
private var progressNode: LoadingProgressNode?
|
private var progressNode: LoadingProgressNode?
|
||||||
private var mainButtonNode: MainButtonNode
|
private var mainButtonNode: MainButtonNode
|
||||||
|
private var secondaryButtonNode: MainButtonNode
|
||||||
|
|
||||||
private var loadingProgress: CGFloat?
|
private var loadingProgress: CGFloat?
|
||||||
private var mainButtonState: AttachmentMainButtonState = .initial
|
private var mainButtonState: AttachmentMainButtonState = .initial
|
||||||
|
private var secondaryButtonState: AttachmentMainButtonState = .initial
|
||||||
|
private var customBottomPanelBackgroundColor: UIColor?
|
||||||
|
|
||||||
private var elevateProgress: Bool = false
|
private var elevateProgress: Bool = false
|
||||||
private var buttons: [AttachmentButtonType] = []
|
private var buttons: [AttachmentButtonType] = []
|
||||||
@ -716,7 +729,7 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
private(set) var isSelecting: Bool = false
|
private(set) var isSelecting: Bool = false
|
||||||
private var _isButtonVisible: Bool = false
|
private var _isButtonVisible: Bool = false
|
||||||
var isButtonVisible: Bool {
|
var isButtonVisible: Bool {
|
||||||
return self.mainButtonState.isVisible
|
return self.mainButtonState.isVisible || self.secondaryButtonState.isVisible
|
||||||
}
|
}
|
||||||
|
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
@ -737,7 +750,8 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
|
|
||||||
var getCurrentSendMessageContextMediaPreview: (() -> ChatSendMessageContextScreenMediaPreview?)?
|
var getCurrentSendMessageContextMediaPreview: (() -> ChatSendMessageContextScreenMediaPreview?)?
|
||||||
|
|
||||||
var mainButtonPressed: () -> Void = { }
|
var onMainButtonPressed: () -> Void = { }
|
||||||
|
var onSecondaryButtonPressed: () -> Void = { }
|
||||||
|
|
||||||
init(controller: AttachmentController, context: AccountContext, chatLocation: ChatLocation?, isScheduledMessages: Bool, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) {
|
init(controller: AttachmentController, context: AccountContext, chatLocation: ChatLocation?, isScheduledMessages: Bool, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) {
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
@ -760,6 +774,7 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
self.separatorNode.backgroundColor = self.presentationData.theme.rootController.tabBar.separatorColor
|
self.separatorNode.backgroundColor = self.presentationData.theme.rootController.tabBar.separatorColor
|
||||||
|
|
||||||
self.mainButtonNode = MainButtonNode()
|
self.mainButtonNode = MainButtonNode()
|
||||||
|
self.secondaryButtonNode = MainButtonNode()
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -768,9 +783,11 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
self.containerNode.addSubnode(self.separatorNode)
|
self.containerNode.addSubnode(self.separatorNode)
|
||||||
self.containerNode.addSubnode(self.scrollNode)
|
self.containerNode.addSubnode(self.scrollNode)
|
||||||
|
|
||||||
|
self.addSubnode(self.secondaryButtonNode)
|
||||||
self.addSubnode(self.mainButtonNode)
|
self.addSubnode(self.mainButtonNode)
|
||||||
|
|
||||||
self.mainButtonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
self.mainButtonNode.addTarget(self, action: #selector(self.mainButtonPressed), forControlEvents: .touchUpInside)
|
||||||
|
self.secondaryButtonNode.addTarget(self, action: #selector(self.secondaryButtonPressed), forControlEvents: .touchUpInside)
|
||||||
|
|
||||||
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
||||||
}, setupEditMessage: { _, _ in
|
}, setupEditMessage: { _, _ in
|
||||||
@ -1105,7 +1122,7 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
|
|
||||||
strongSelf.backgroundNode.updateColor(color: presentationData.theme.rootController.tabBar.backgroundColor, transition: .immediate)
|
strongSelf.backgroundNode.updateColor(color: strongSelf.customBottomPanelBackgroundColor ?? presentationData.theme.rootController.tabBar.backgroundColor, transition: .immediate)
|
||||||
strongSelf.separatorNode.backgroundColor = presentationData.theme.rootController.tabBar.separatorColor
|
strongSelf.separatorNode.backgroundColor = presentationData.theme.rootController.tabBar.separatorColor
|
||||||
|
|
||||||
strongSelf.updateChatPresentationInterfaceState({ $0.updatedTheme(presentationData.theme) })
|
strongSelf.updateChatPresentationInterfaceState({ $0.updatedTheme(presentationData.theme) })
|
||||||
@ -1137,8 +1154,12 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
self.view.accessibilityTraits = .tabBar
|
self.view.accessibilityTraits = .tabBar
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func buttonPressed() {
|
@objc private func mainButtonPressed() {
|
||||||
self.mainButtonPressed()
|
self.onMainButtonPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func secondaryButtonPressed() {
|
||||||
|
self.onSecondaryButtonPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateBackgroundAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) {
|
func updateBackgroundAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
@ -1372,11 +1393,24 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
func updateMainButtonState(_ mainButtonState: AttachmentMainButtonState?) {
|
func updateMainButtonState(_ mainButtonState: AttachmentMainButtonState?) {
|
||||||
var currentButtonState = self.mainButtonState
|
var currentButtonState = self.mainButtonState
|
||||||
if mainButtonState == nil {
|
if mainButtonState == nil {
|
||||||
currentButtonState = AttachmentMainButtonState(text: currentButtonState.text, font: currentButtonState.font, background: currentButtonState.background, textColor: currentButtonState.textColor, isVisible: false, progress: .none, isEnabled: currentButtonState.isEnabled)
|
currentButtonState = AttachmentMainButtonState(text: currentButtonState.text, font: currentButtonState.font, background: currentButtonState.background, textColor: currentButtonState.textColor, isVisible: false, progress: .none, isEnabled: currentButtonState.isEnabled, hasShimmer: currentButtonState.hasShimmer)
|
||||||
}
|
}
|
||||||
self.mainButtonState = mainButtonState ?? currentButtonState
|
self.mainButtonState = mainButtonState ?? currentButtonState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateSecondaryButtonState(_ secondaryButtonState: AttachmentMainButtonState?) {
|
||||||
|
var currentButtonState = self.secondaryButtonState
|
||||||
|
if secondaryButtonState == nil {
|
||||||
|
currentButtonState = AttachmentMainButtonState(text: currentButtonState.text, font: currentButtonState.font, background: currentButtonState.background, textColor: currentButtonState.textColor, isVisible: false, progress: .none, isEnabled: currentButtonState.isEnabled, hasShimmer: currentButtonState.hasShimmer)
|
||||||
|
}
|
||||||
|
self.secondaryButtonState = secondaryButtonState ?? currentButtonState
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCustomBottomPanelBackgroundColor(_ color: UIColor?) {
|
||||||
|
self.customBottomPanelBackgroundColor = color
|
||||||
|
self.backgroundNode.updateColor(color: self.customBottomPanelBackgroundColor ?? presentationData.theme.rootController.tabBar.backgroundColor, transition: .animated(duration: 0.2, curve: .linear))
|
||||||
|
}
|
||||||
|
|
||||||
let animatingTransitionPromise = ValuePromise<Bool>(false)
|
let animatingTransitionPromise = ValuePromise<Bool>(false)
|
||||||
private(set) var animatingTransition = false {
|
private(set) var animatingTransition = false {
|
||||||
didSet {
|
didSet {
|
||||||
@ -1521,11 +1555,14 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
|
|
||||||
self.scrollNode.isUserInteractionEnabled = !isSelecting
|
self.scrollNode.isUserInteractionEnabled = !isSelecting
|
||||||
|
|
||||||
let isButtonVisible = self.mainButtonState.isVisible
|
let isAnyButtonVisible = self.mainButtonState.isVisible || self.secondaryButtonState.isVisible
|
||||||
let isNarrowButton = isButtonVisible && self.mainButtonState.font == .regular
|
let isNarrowButton = isAnyButtonVisible && self.mainButtonState.font == .regular
|
||||||
|
|
||||||
|
let isTwoVerticalButtons = self.mainButtonState.isVisible && self.secondaryButtonState.isVisible && [.top, .bottom].contains(self.secondaryButtonState.position)
|
||||||
|
let isTwoHorizontalButtons = self.mainButtonState.isVisible && self.secondaryButtonState.isVisible && [.left, .right].contains(self.secondaryButtonState.position)
|
||||||
|
|
||||||
var insets = layout.insets(options: [])
|
var insets = layout.insets(options: [])
|
||||||
if let inputHeight = layout.inputHeight, inputHeight > 0.0 && (isSelecting || isButtonVisible) {
|
if let inputHeight = layout.inputHeight, inputHeight > 0.0 && (isSelecting || isAnyButtonVisible) {
|
||||||
insets.bottom = inputHeight
|
insets.bottom = inputHeight
|
||||||
} else if layout.intrinsicInsets.bottom > 0.0 {
|
} else if layout.intrinsicInsets.bottom > 0.0 {
|
||||||
insets.bottom = layout.intrinsicInsets.bottom
|
insets.bottom = layout.intrinsicInsets.bottom
|
||||||
@ -1560,7 +1597,11 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
let bounds = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: buttonSize.height + insets.bottom))
|
let bounds = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: buttonSize.height + insets.bottom))
|
||||||
var containerTransition: ContainedViewLayoutTransition
|
var containerTransition: ContainedViewLayoutTransition
|
||||||
let containerFrame: CGRect
|
let containerFrame: CGRect
|
||||||
if isButtonVisible {
|
|
||||||
|
let sideInset: CGFloat = 16.0
|
||||||
|
let buttonHeight: CGFloat = 50.0
|
||||||
|
|
||||||
|
if isAnyButtonVisible {
|
||||||
var height: CGFloat
|
var height: CGFloat
|
||||||
if layout.intrinsicInsets.bottom > 0.0 && (layout.inputHeight ?? 0.0).isZero {
|
if layout.intrinsicInsets.bottom > 0.0 && (layout.inputHeight ?? 0.0).isZero {
|
||||||
height = bounds.height
|
height = bounds.height
|
||||||
@ -1577,6 +1618,9 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
if !isNarrowButton {
|
if !isNarrowButton {
|
||||||
height += 9.0
|
height += 9.0
|
||||||
}
|
}
|
||||||
|
if isTwoVerticalButtons {
|
||||||
|
height += buttonHeight + sideInset
|
||||||
|
}
|
||||||
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: height))
|
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: height))
|
||||||
} else if isSelecting {
|
} else if isSelecting {
|
||||||
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: textPanelHeight + insets.bottom))
|
containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: textPanelHeight + insets.bottom))
|
||||||
@ -1589,8 +1633,8 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
} else {
|
} else {
|
||||||
containerTransition = transition
|
containerTransition = transition
|
||||||
}
|
}
|
||||||
containerTransition.updateAlpha(node: self.scrollNode, alpha: isSelecting || isButtonVisible ? 0.0 : 1.0)
|
containerTransition.updateAlpha(node: self.scrollNode, alpha: isSelecting || isAnyButtonVisible ? 0.0 : 1.0)
|
||||||
containerTransition.updateTransformScale(node: self.scrollNode, scale: isSelecting || isButtonVisible ? 0.85 : 1.0)
|
containerTransition.updateTransformScale(node: self.scrollNode, scale: isSelecting || isAnyButtonVisible ? 0.85 : 1.0)
|
||||||
|
|
||||||
if isSelectingUpdated {
|
if isSelectingUpdated {
|
||||||
if isSelecting {
|
if isSelecting {
|
||||||
@ -1643,15 +1687,67 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let sideInset: CGFloat = 16.0
|
var buttonSize = CGSize(width: layout.size.width - (sideInset + layout.safeInsets.left) * 2.0, height: buttonHeight)
|
||||||
let buttonSize = CGSize(width: layout.size.width - (sideInset + layout.safeInsets.left) * 2.0, height: 50.0)
|
if isTwoHorizontalButtons {
|
||||||
|
buttonSize = CGSize(width: (buttonSize.width - sideInset) / 2.0, height: buttonSize.height)
|
||||||
|
}
|
||||||
let buttonTopInset: CGFloat = isNarrowButton ? 2.0 : 8.0
|
let buttonTopInset: CGFloat = isNarrowButton ? 2.0 : 8.0
|
||||||
|
|
||||||
if !self.dismissed {
|
|
||||||
self.mainButtonNode.updateLayout(size: buttonSize, state: self.mainButtonState, transition: transition)
|
|
||||||
}
|
|
||||||
if !self.animatingTransition {
|
if !self.animatingTransition {
|
||||||
transition.updateFrame(node: self.mainButtonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + sideInset, y: isButtonVisible || self.fromMenu ? buttonTopInset : containerFrame.height), size: buttonSize))
|
let buttonOriginX = layout.safeInsets.left + sideInset
|
||||||
|
let buttonOriginY = isAnyButtonVisible || self.fromMenu ? buttonTopInset : containerFrame.height
|
||||||
|
var mainButtonFrame: CGRect?
|
||||||
|
var secondaryButtonFrame: CGRect?
|
||||||
|
if self.secondaryButtonState.isVisible && self.mainButtonState.isVisible, let position = self.secondaryButtonState.position {
|
||||||
|
switch position {
|
||||||
|
case .top:
|
||||||
|
secondaryButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY), size: buttonSize)
|
||||||
|
mainButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY + sideInset + buttonSize.height), size: buttonSize)
|
||||||
|
case .bottom:
|
||||||
|
mainButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY), size: buttonSize)
|
||||||
|
secondaryButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY + sideInset + buttonSize.height), size: buttonSize)
|
||||||
|
case .left:
|
||||||
|
secondaryButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY), size: buttonSize)
|
||||||
|
mainButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX + buttonSize.width + sideInset, y: buttonOriginY), size: buttonSize)
|
||||||
|
case .right:
|
||||||
|
mainButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY), size: buttonSize)
|
||||||
|
secondaryButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX + buttonSize.width + sideInset, y: buttonOriginY), size: buttonSize)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.mainButtonState.isVisible {
|
||||||
|
mainButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY), size: buttonSize)
|
||||||
|
}
|
||||||
|
if self.secondaryButtonState.isVisible {
|
||||||
|
secondaryButtonFrame = CGRect(origin: CGPoint(x: buttonOriginX, y: buttonOriginY), size: buttonSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let mainButtonFrame {
|
||||||
|
if !self.dismissed {
|
||||||
|
self.mainButtonNode.updateLayout(size: buttonSize, state: self.mainButtonState, animateBackground: self.mainButtonState.background.colorValue == self.backgroundNode.color && transition.isAnimated, transition: transition)
|
||||||
|
}
|
||||||
|
if self.mainButtonNode.frame.width.isZero {
|
||||||
|
self.mainButtonNode.frame = mainButtonFrame
|
||||||
|
} else {
|
||||||
|
transition.updateFrame(node: self.mainButtonNode, frame: mainButtonFrame)
|
||||||
|
}
|
||||||
|
transition.updateAlpha(node: self.mainButtonNode, alpha: 1.0)
|
||||||
|
} else {
|
||||||
|
transition.updateAlpha(node: self.mainButtonNode, alpha: 0.0)
|
||||||
|
}
|
||||||
|
if let secondaryButtonFrame {
|
||||||
|
if !self.dismissed {
|
||||||
|
self.secondaryButtonNode.updateLayout(size: buttonSize, state: self.secondaryButtonState, animateBackground: self.secondaryButtonState.background.colorValue == self.backgroundNode.color && transition.isAnimated, transition: transition)
|
||||||
|
}
|
||||||
|
if self.secondaryButtonNode.frame.width.isZero {
|
||||||
|
self.secondaryButtonNode.frame = secondaryButtonFrame
|
||||||
|
} else {
|
||||||
|
transition.updateFrame(node: self.secondaryButtonNode, frame: secondaryButtonFrame)
|
||||||
|
}
|
||||||
|
transition.updateAlpha(node: self.secondaryButtonNode, alpha: 1.0)
|
||||||
|
} else {
|
||||||
|
transition.updateAlpha(node: self.secondaryButtonNode, alpha: 0.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return containerFrame.height
|
return containerFrame.height
|
||||||
|
@ -140,6 +140,10 @@ private var sharedIsReduceTransparencyEnabled = UIAccessibility.isReduceTranspar
|
|||||||
public final class NavigationBackgroundNode: ASDisplayNode {
|
public final class NavigationBackgroundNode: ASDisplayNode {
|
||||||
private var _color: UIColor
|
private var _color: UIColor
|
||||||
|
|
||||||
|
public var color: UIColor {
|
||||||
|
return self._color
|
||||||
|
}
|
||||||
|
|
||||||
private var enableBlur: Bool
|
private var enableBlur: Bool
|
||||||
private var enableSaturation: Bool
|
private var enableSaturation: Bool
|
||||||
|
|
||||||
|
@ -2949,7 +2949,7 @@ public func wallpaperMediaPickerController(
|
|||||||
controller.animateAppearance = animateAppearance
|
controller.animateAppearance = animateAppearance
|
||||||
controller.requestController = { [weak controller] _, present in
|
controller.requestController = { [weak controller] _, present in
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_SetColorWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true), mainButtonAction: {
|
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_SetColorWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false), mainButtonAction: {
|
||||||
controller?.dismiss(animated: true)
|
controller?.dismiss(animated: true)
|
||||||
openColors()
|
openColors()
|
||||||
})
|
})
|
||||||
|
@ -879,7 +879,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
price = nil
|
price = nil
|
||||||
}
|
}
|
||||||
let buttonText = presentationData.strings.Premium_Gift_GiftSubscription(price ?? "—").string
|
let buttonText = presentationData.strings.Premium_Gift_GiftSubscription(price ?? "—").string
|
||||||
self.buttonStatePromise.set(.single(AttachmentMainButtonState(text: buttonText, font: .bold, background: .premium, textColor: .white, isVisible: true, progress: self.inProgress ? .center : .none, isEnabled: true, hasShimmer: false)))
|
self.buttonStatePromise.set(.single(AttachmentMainButtonState(text: buttonText, font: .bold, background: .premium, textColor: .white, isVisible: true, progress: self.inProgress ? .center : .none, isEnabled: true, hasShimmer: true)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func buy() {
|
func buy() {
|
||||||
|
@ -194,7 +194,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
|||||||
self?.push(controller)
|
self?.push(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mainButtonState = AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true)
|
self.mainButtonState = AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
|
@ -645,8 +645,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
if let giveawayMessageId {
|
if let giveawayMessageId {
|
||||||
tableItems.append(.init(
|
tableItems.append(.init(
|
||||||
id: "gift",
|
id: "prize",
|
||||||
title: "Gift",
|
title: "Prize",
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
MultilineTextComponent(text: .plain(NSAttributedString(string: "\(count) Stars", font: tableFont, textColor: tableTextColor)))
|
MultilineTextComponent(text: .plain(NSAttributedString(string: "\(count) Stars", font: tableFont, textColor: tableTextColor)))
|
||||||
)
|
)
|
||||||
|
@ -104,6 +104,7 @@ public func generateWebAppThemeParams(_ theme: PresentationTheme) -> [String: An
|
|||||||
"button_color": Int32(bitPattern: theme.list.itemCheckColors.fillColor.rgb),
|
"button_color": Int32(bitPattern: theme.list.itemCheckColors.fillColor.rgb),
|
||||||
"button_text_color": Int32(bitPattern: theme.list.itemCheckColors.foregroundColor.rgb),
|
"button_text_color": Int32(bitPattern: theme.list.itemCheckColors.foregroundColor.rgb),
|
||||||
"header_bg_color": Int32(bitPattern: theme.rootController.navigationBar.opaqueBackgroundColor.rgb),
|
"header_bg_color": Int32(bitPattern: theme.rootController.navigationBar.opaqueBackgroundColor.rgb),
|
||||||
|
"bottom_bar_bg_color": Int32(bitPattern: theme.rootController.tabBar.backgroundColor.rgb),
|
||||||
"accent_text_color": Int32(bitPattern: theme.list.itemAccentColor.rgb),
|
"accent_text_color": Int32(bitPattern: theme.list.itemAccentColor.rgb),
|
||||||
"section_bg_color": Int32(bitPattern: theme.list.itemBlocksBackgroundColor.rgb),
|
"section_bg_color": Int32(bitPattern: theme.list.itemBlocksBackgroundColor.rgb),
|
||||||
"section_header_text_color": Int32(bitPattern: theme.list.freeTextColor.rgb),
|
"section_header_text_color": Int32(bitPattern: theme.list.freeTextColor.rgb),
|
||||||
@ -145,6 +146,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
fileprivate let mainButtonStatePromise = Promise<AttachmentMainButtonState?>(nil)
|
fileprivate let mainButtonStatePromise = Promise<AttachmentMainButtonState?>(nil)
|
||||||
|
|
||||||
|
fileprivate var secondaryButtonState: AttachmentMainButtonState? {
|
||||||
|
didSet {
|
||||||
|
self.secondaryButtonStatePromise.set(.single(self.secondaryButtonState))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileprivate let secondaryButtonStatePromise = Promise<AttachmentMainButtonState?>(nil)
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
var presentationData: PresentationData
|
var presentationData: PresentationData
|
||||||
private var queryId: Int64?
|
private var queryId: Int64?
|
||||||
@ -192,9 +200,12 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self?.handleScriptMessage(message)
|
self?.handleScriptMessage(message)
|
||||||
}
|
}
|
||||||
webView.onFirstTouch = { [weak self] in
|
webView.onFirstTouch = { [weak self] in
|
||||||
if let strongSelf = self, let delayedScriptMessage = strongSelf.delayedScriptMessage {
|
if let self, !self.delayedScriptMessages.isEmpty {
|
||||||
strongSelf.delayedScriptMessage = nil
|
let delayedScriptMessages = self.delayedScriptMessages
|
||||||
strongSelf.handleScriptMessage(delayedScriptMessage)
|
self.delayedScriptMessages.removeAll()
|
||||||
|
for message in delayedScriptMessages {
|
||||||
|
self.handleScriptMessage(message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
@ -414,6 +425,14 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.webView?.sendEvent(name: "main_button_pressed", data: nil)
|
self.webView?.sendEvent(name: "main_button_pressed", data: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc fileprivate func secondaryButtonPressed() {
|
||||||
|
if let secondaryButtonState = self.secondaryButtonState, !secondaryButtonState.isVisible || !secondaryButtonState.isEnabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.webView?.lastTouchTimestamp = CACurrentMediaTime()
|
||||||
|
self.webView?.sendEvent(name: "secondary_button_pressed", data: nil)
|
||||||
|
}
|
||||||
|
|
||||||
private func updatePlaceholder(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize {
|
private func updatePlaceholder(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||||
var shapes: [ShimmerEffect.ShimmerEffectNode.Shape] = []
|
var shapes: [ShimmerEffect.ShimmerEffectNode.Shape] = []
|
||||||
var placeholderSize: CGSize = CGSize()
|
var placeholderSize: CGSize = CGSize()
|
||||||
@ -656,7 +675,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
private weak var currentQrCodeScannerScreen: QrCodeScanScreen?
|
private weak var currentQrCodeScannerScreen: QrCodeScanScreen?
|
||||||
|
|
||||||
private var delayedScriptMessage: WKScriptMessage?
|
private var delayedScriptMessages: [WKScriptMessage] = []
|
||||||
private func handleScriptMessage(_ message: WKScriptMessage) {
|
private func handleScriptMessage(_ message: WKScriptMessage) {
|
||||||
guard let controller = self.controller else {
|
guard let controller = self.controller else {
|
||||||
return
|
return
|
||||||
@ -706,7 +725,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
case "web_app_setup_main_button":
|
case "web_app_setup_main_button":
|
||||||
if let webView = self.webView, !webView.didTouchOnce && controller.url == nil && controller.source == .attachMenu {
|
if let webView = self.webView, !webView.didTouchOnce && controller.url == nil && controller.source == .attachMenu {
|
||||||
self.delayedScriptMessage = message
|
self.delayedScriptMessages.append(message)
|
||||||
} else if let json = json {
|
} else if let json = json {
|
||||||
if var isVisible = json["is_visible"] as? Bool {
|
if var isVisible = json["is_visible"] as? Bool {
|
||||||
let text = json["text"] as? String
|
let text = json["text"] as? String
|
||||||
@ -721,10 +740,35 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
let isLoading = json["is_progress_visible"] as? Bool
|
let isLoading = json["is_progress_visible"] as? Bool
|
||||||
let isEnabled = json["is_active"] as? Bool
|
let isEnabled = json["is_active"] as? Bool
|
||||||
let state = AttachmentMainButtonState(text: text, font: .bold, background: .color(backgroundColor), textColor: textColor, isVisible: isVisible, progress: (isLoading ?? false) ? .side : .none, isEnabled: isEnabled ?? true)
|
let hasShimmer = json["has_shine_effect"] as? Bool
|
||||||
|
let state = AttachmentMainButtonState(text: text, font: .bold, background: .color(backgroundColor), textColor: textColor, isVisible: isVisible, progress: (isLoading ?? false) ? .center : .none, isEnabled: isEnabled ?? true, hasShimmer: hasShimmer ?? false)
|
||||||
self.mainButtonState = state
|
self.mainButtonState = state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "web_app_setup_secondary_button":
|
||||||
|
if let webView = self.webView, !webView.didTouchOnce && controller.url == nil && controller.source == .attachMenu {
|
||||||
|
self.delayedScriptMessages.append(message)
|
||||||
|
} else if let json = json {
|
||||||
|
if var isVisible = json["is_visible"] as? Bool {
|
||||||
|
let text = json["text"] as? String
|
||||||
|
if (text ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let backgroundColorString = json["color"] as? String
|
||||||
|
let backgroundColor = backgroundColorString.flatMap({ UIColor(hexString: $0) }) ?? self.presentationData.theme.list.itemCheckColors.fillColor
|
||||||
|
let textColorString = json["text_color"] as? String
|
||||||
|
let textColor = textColorString.flatMap({ UIColor(hexString: $0) }) ?? self.presentationData.theme.list.itemCheckColors.foregroundColor
|
||||||
|
|
||||||
|
let isLoading = json["is_progress_visible"] as? Bool
|
||||||
|
let isEnabled = json["is_active"] as? Bool
|
||||||
|
let hasShimmer = json["has_shine_effect"] as? Bool
|
||||||
|
let position = json["position"] as? String
|
||||||
|
|
||||||
|
let state = AttachmentMainButtonState(text: text, font: .bold, background: .color(backgroundColor), textColor: textColor, isVisible: isVisible, progress: (isLoading ?? false) ? .center : .none, isEnabled: isEnabled ?? true, hasShimmer: hasShimmer ?? false, position: position.flatMap { AttachmentMainButtonState.Position(rawValue: $0) })
|
||||||
|
self.secondaryButtonState = state
|
||||||
|
}
|
||||||
|
}
|
||||||
case "web_app_request_viewport":
|
case "web_app_request_viewport":
|
||||||
if let (layout, navigationBarHeight) = self.validLayout {
|
if let (layout, navigationBarHeight) = self.validLayout {
|
||||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||||
@ -935,6 +979,12 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
self.updateHeaderBackgroundColor(transition: .animated(duration: 0.2, curve: .linear))
|
self.updateHeaderBackgroundColor(transition: .animated(duration: 0.2, curve: .linear))
|
||||||
}
|
}
|
||||||
|
case "web_app_set_bottom_bar_color":
|
||||||
|
if let json = json {
|
||||||
|
if let hexColor = json["color"] as? String, let color = UIColor(hexString: hexColor) {
|
||||||
|
self.bottomPanelColor = color
|
||||||
|
}
|
||||||
|
}
|
||||||
case "web_app_open_popup":
|
case "web_app_open_popup":
|
||||||
if let json = json, let message = json["message"] as? String, let buttons = json["buttons"] as? [Any] {
|
if let json = json, let message = json["message"] as? String, let buttons = json["buttons"] as? [Any] {
|
||||||
let presentationData = self.presentationData
|
let presentationData = self.presentationData
|
||||||
@ -1177,6 +1227,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
fileprivate var headerPrimaryTextColor: UIColor?
|
fileprivate var headerPrimaryTextColor: UIColor?
|
||||||
private var headerColorKey: String?
|
private var headerColorKey: String?
|
||||||
|
|
||||||
|
fileprivate var bottomPanelColor: UIColor? {
|
||||||
|
didSet {
|
||||||
|
self.bottomPanelColorPromise.set(.single(self.bottomPanelColor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileprivate let bottomPanelColorPromise = Promise<UIColor?>(nil)
|
||||||
|
|
||||||
private func updateHeaderBackgroundColor(transition: ContainedViewLayoutTransition) {
|
private func updateHeaderBackgroundColor(transition: ContainedViewLayoutTransition) {
|
||||||
guard let controller = self.controller else {
|
guard let controller = self.controller else {
|
||||||
return
|
return
|
||||||
@ -2254,6 +2311,14 @@ final class WebAppPickerContext: AttachmentMediaPickerContext {
|
|||||||
return self.controller?.controllerNode.mainButtonStatePromise.get() ?? .single(nil)
|
return self.controller?.controllerNode.mainButtonStatePromise.get() ?? .single(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var secondaryButtonState: Signal<AttachmentMainButtonState?, NoError> {
|
||||||
|
return self.controller?.controllerNode.secondaryButtonStatePromise.get() ?? .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var bottomPanelBackgroundColor: Signal<UIColor?, NoError> {
|
||||||
|
return self.controller?.controllerNode.bottomPanelColorPromise.get() ?? .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
init(controller: WebAppController) {
|
init(controller: WebAppController) {
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
}
|
}
|
||||||
@ -2261,6 +2326,10 @@ final class WebAppPickerContext: AttachmentMediaPickerContext {
|
|||||||
func mainButtonAction() {
|
func mainButtonAction() {
|
||||||
self.controller?.controllerNode.mainButtonPressed()
|
self.controller?.controllerNode.mainButtonPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func secondaryButtonAction() {
|
||||||
|
self.controller?.controllerNode.secondaryButtonPressed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user