Merge commit '8007e25fc4c1f5646a39de54a6d3d9532384e4f3' into beta

This commit is contained in:
Isaac 2024-03-05 15:33:02 +04:00
commit 85c81a107d
12 changed files with 122 additions and 43 deletions

View File

@ -11336,12 +11336,10 @@ Sorry for the inconvenience.";
"Premium.Business.Location.Text" = "Display the location of your business on your account."; "Premium.Business.Location.Text" = "Display the location of your business on your account.";
"Premium.Business.Hours.Title" = "Opening Hours"; "Premium.Business.Hours.Title" = "Opening Hours";
"Premium.Business.Hours.Text" = "Show to your customers when you are "Premium.Business.Hours.Text" = "Show to your customers when you are open for business.";
open for business.";
"Premium.Business.Replies.Title" = "Quick Replies"; "Premium.Business.Replies.Title" = "Quick Replies";
"Premium.Business.Replies.Text" = "Set up shortcuts with rich text and media "Premium.Business.Replies.Text" = "Set up shortcuts with rich text and media to respond to messages faster.";
to respond to messages faster.";
"Premium.Business.Greetings.Title" = "Greeting Messages"; "Premium.Business.Greetings.Title" = "Greeting Messages";
"Premium.Business.Greetings.Text" = "Create greetings that will be automatically sent to new customers."; "Premium.Business.Greetings.Text" = "Create greetings that will be automatically sent to new customers.";

View File

@ -519,7 +519,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
var clipDelta = delta var clipDelta = delta
if inputHeight.isZero || layout.isNonExclusive { if inputHeight < 70.0 || layout.isNonExclusive {
clipDelta -= self.contentContainerNode.frame.height + 16.0 clipDelta -= self.contentContainerNode.frame.height + 16.0
} }
@ -642,7 +642,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
var clipDelta = delta var clipDelta = delta
if inputHeight.isZero || layout.isNonExclusive { if inputHeight < 70.0 || layout.isNonExclusive {
clipDelta -= self.contentContainerNode.frame.height + 16.0 clipDelta -= self.contentContainerNode.frame.height + 16.0
} }
@ -714,7 +714,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} else { } else {
contentOrigin = CGPoint(x: layout.size.width - sideInset - contentSize.width - layout.safeInsets.right, y: layout.size.height - 6.0 - insets.bottom - contentSize.height) contentOrigin = CGPoint(x: layout.size.width - sideInset - contentSize.width - layout.safeInsets.right, y: layout.size.height - 6.0 - insets.bottom - contentSize.height)
} }
if inputHeight > 0.0 && !layout.isNonExclusive && self.animateInputField { if inputHeight > 70.0 && !layout.isNonExclusive && self.animateInputField {
contentOrigin.y += menuHeightWithInset contentOrigin.y += menuHeightWithInset
} }
contentOrigin.y = min(contentOrigin.y + contentOffset, layout.size.height - 6.0 - layout.intrinsicInsets.bottom - contentSize.height) contentOrigin.y = min(contentOrigin.y + contentOffset, layout.size.height - 6.0 - layout.intrinsicInsets.bottom - contentSize.height)
@ -728,7 +728,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
var sendButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - initialSendButtonFrame.width + 1.0 - UIScreenPixel - layout.safeInsets.right, y: layout.size.height - insets.bottom - initialSendButtonFrame.height), size: initialSendButtonFrame.size) var sendButtonFrame = CGRect(origin: CGPoint(x: layout.size.width - initialSendButtonFrame.width + 1.0 - UIScreenPixel - layout.safeInsets.right, y: layout.size.height - insets.bottom - initialSendButtonFrame.height), size: initialSendButtonFrame.size)
if (inputHeight.isZero || layout.isNonExclusive) && self.animateInputField { if (inputHeight < 70.0 || layout.isNonExclusive) && self.animateInputField {
sendButtonFrame.origin.y -= menuHeightWithInset sendButtonFrame.origin.y -= menuHeightWithInset
} }
sendButtonFrame.origin.y = min(sendButtonFrame.origin.y + contentOffset, layout.size.height - layout.intrinsicInsets.bottom - initialSendButtonFrame.height) sendButtonFrame.origin.y = min(sendButtonFrame.origin.y + contentOffset, layout.size.height - layout.intrinsicInsets.bottom - initialSendButtonFrame.height)
@ -741,7 +741,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
let messageHeightAddition: CGFloat = max(0.0, 35.0 - messageFrame.size.height) let messageHeightAddition: CGFloat = max(0.0, 35.0 - messageFrame.size.height)
if inputHeight.isZero || layout.isNonExclusive { if inputHeight < 70.0 || layout.isNonExclusive {
messageFrame.origin.y += menuHeightWithInset messageFrame.origin.y += menuHeightWithInset
} }

View File

@ -243,7 +243,6 @@ public final class WindowKeyboardGestureRecognizerDelegate: NSObject, UIGestureR
public class Window1 { public class Window1 {
public let hostView: WindowHostView public let hostView: WindowHostView
public let badgeView: UIImageView public let badgeView: UIImageView
private let customProximityDimView: UIView
private var deviceMetrics: DeviceMetrics private var deviceMetrics: DeviceMetrics
@ -331,10 +330,6 @@ public class Window1 {
self.badgeView.image = UIImage(bundleImageName: "Components/AppBadge") self.badgeView.image = UIImage(bundleImageName: "Components/AppBadge")
self.badgeView.isHidden = true self.badgeView.isHidden = true
self.customProximityDimView = UIView()
self.customProximityDimView.backgroundColor = .black
self.customProximityDimView.isHidden = true
self.systemUserInterfaceStyle = hostView.systemUserInterfaceStyle self.systemUserInterfaceStyle = hostView.systemUserInterfaceStyle
let boundsSize = self.hostView.eventView.bounds.size let boundsSize = self.hostView.eventView.bounds.size
@ -673,7 +668,6 @@ public class Window1 {
self.windowPanRecognizer = recognizer self.windowPanRecognizer = recognizer
self.hostView.containerView.addGestureRecognizer(recognizer) self.hostView.containerView.addGestureRecognizer(recognizer)
self.hostView.containerView.addSubview(self.badgeView) self.hostView.containerView.addSubview(self.badgeView)
self.hostView.containerView.addSubview(self.customProximityDimView)
} }
public required init(coder aDecoder: NSCoder) { public required init(coder aDecoder: NSCoder) {
@ -707,11 +701,18 @@ public class Window1 {
self.updateBadgeVisibility() self.updateBadgeVisibility()
} }
private var proximityDimController: CustomDimController?
public func setProximityDimHidden(_ hidden: Bool) { public func setProximityDimHidden(_ hidden: Bool) {
guard hidden != self.customProximityDimView.isHidden else { if !hidden {
return if self.proximityDimController == nil {
let proximityDimController = CustomDimController(navigationBarPresentationData: nil)
self.proximityDimController = proximityDimController
(self.viewController as? NavigationController)?.presentOverlay(controller: proximityDimController, inGlobal: true, blockInteraction: false)
}
} else if let proximityDimController = self.proximityDimController {
self.proximityDimController = nil
proximityDimController.dismiss()
} }
self.customProximityDimView.isHidden = hidden
} }
private func updateBadgeVisibility() { private func updateBadgeVisibility() {
@ -1170,8 +1171,6 @@ public class Window1 {
self.updateBadgeVisibility() self.updateBadgeVisibility()
self.badgeView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.windowLayout.size.width - image.size.width) / 2.0), y: 5.0), size: image.size) self.badgeView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.windowLayout.size.width - image.size.width) / 2.0), y: 5.0), size: image.size)
} }
self.customProximityDimView.frame = CGRect(origin: .zero, size: self.windowLayout.size)
} }
} }
} }
@ -1383,3 +1382,25 @@ public class Window1 {
} }
} }
} }
private class CustomDimController: ViewController {
class Node: ASDisplayNode {
override init() {
super.init()
self.backgroundColor = .black
}
}
override init(navigationBarPresentationData: NavigationBarPresentationData?) {
super.init(navigationBarPresentationData: nil)
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadDisplayNode() {
let node = Node()
self.displayNode = node
}
}

View File

@ -70,7 +70,7 @@ private final class HeaderComponent: Component {
transition: .immediate, transition: .immediate,
component: AnyComponent( component: AnyComponent(
MultilineTextComponent( MultilineTextComponent(
text: .plain(NSAttributedString(string: component.strings.Premium_Business_Description, font: Font.regular(15.0), textColor: .black)), text: .plain(NSAttributedString(string: component.strings.Premium_Business_Description, font: Font.regular(15.0), textColor: component.theme.list.itemPrimaryTextColor)),
horizontalAlignment: .center, horizontalAlignment: .center,
maximumNumberOfLines: 0, maximumNumberOfLines: 0,
lineSpacing: 0.2 lineSpacing: 0.2

View File

@ -3141,10 +3141,14 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
let secondaryTitleText: String let secondaryTitleText: String
var isAnonymous = false var isAnonymous = false
if var otherPeerName = state.otherPeerName { if var otherPeerName = state.otherPeerName {
if case let .emojiStatus(_, _, file, maybeEmojiPack) = context.component.source, let emojiPack = maybeEmojiPack, case let .result(info, _, _) = emojiPack { if case let .emojiStatus(peerId, _, file, maybeEmojiPack) = context.component.source, let emojiPack = maybeEmojiPack, case let .result(info, _, _) = emojiPack {
loadedEmojiPack = maybeEmojiPack loadedEmojiPack = maybeEmojiPack
highlightableLinks = true highlightableLinks = true
if peerId.isGroupOrChannel, otherPeerName.count > 20 {
otherPeerName = otherPeerName.prefix(20).trimmingCharacters(in: .whitespacesAndNewlines) + "\u{2026}"
}
var packReference: StickerPackReference? var packReference: StickerPackReference?
if let file = file { if let file = file {
for attribute in file.attributes { for attribute in file.attributes {

View File

@ -228,6 +228,8 @@ public class PremiumLimitsListScreen: ViewController {
if scrollView.contentSize.width > scrollView.contentSize.height || scrollView.contentSize.height > 1500.0 { if scrollView.contentSize.width > scrollView.contentSize.height || scrollView.contentSize.height > 1500.0 {
return false return false
} }
} else if otherGestureRecognizer.view is PremiumCoinComponent.View {
return false
} }
return true return true
} }

View File

@ -17,6 +17,12 @@ public final class AudioTranscriptionButtonComponent: Component {
} else { } else {
return false return false
} }
case let .custom(lhsBackgroundColor, lhsForegroundColor):
if case let .custom(rhsBackgroundColor, rhsForegroundColor) = rhs {
return lhsBackgroundColor == rhsBackgroundColor && lhsForegroundColor == rhsForegroundColor
} else {
return false
}
case let .freeform(lhsFreeform, lhsForeground): case let .freeform(lhsFreeform, lhsForeground):
if case let .freeform(rhsFreeform, rhsForeground) = rhs, lhsFreeform == rhsFreeform, lhsForeground == rhsForeground { if case let .freeform(rhsFreeform, rhsForeground) = rhs, lhsFreeform == rhsFreeform, lhsForeground == rhsForeground {
return true return true
@ -27,6 +33,7 @@ public final class AudioTranscriptionButtonComponent: Component {
} }
case bubble(PresentationThemePartedColors) case bubble(PresentationThemePartedColors)
case custom(UIColor, UIColor)
case freeform((UIColor, Bool), UIColor) case freeform((UIColor, Bool), UIColor)
} }
@ -101,6 +108,9 @@ public final class AudioTranscriptionButtonComponent: Component {
case let .bubble(theme): case let .bubble(theme):
foregroundColor = theme.bubble.withWallpaper.reactionActiveBackground foregroundColor = theme.bubble.withWallpaper.reactionActiveBackground
backgroundColor = theme.bubble.withWallpaper.reactionInactiveBackground backgroundColor = theme.bubble.withWallpaper.reactionInactiveBackground
case let .custom(backgroundColorValue, foregroundColorValue):
foregroundColor = foregroundColorValue
backgroundColor = backgroundColorValue
case let .freeform(colorAndBlur, color): case let .freeform(colorAndBlur, color):
foregroundColor = color foregroundColor = color
backgroundColor = .clear backgroundColor = .clear

View File

@ -728,7 +728,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
let contentFileSizeAndApply: (CGSize, ChatMessageInteractiveFileNode.Apply)? let contentFileSizeAndApply: (CGSize, ChatMessageInteractiveFileNode.Apply)?
if let contentFileFinalizeLayout { if let contentFileFinalizeLayout {
let (size, apply) = contentFileFinalizeLayout(resultingWidth - insets.left - insets.right) let (size, apply) = contentFileFinalizeLayout(resultingWidth - insets.left - insets.right - 6.0)
contentFileSizeAndApply = (size, apply) contentFileSizeAndApply = (size, apply)
} else { } else {
contentFileSizeAndApply = nil contentFileSizeAndApply = nil
@ -846,7 +846,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
offsetY: actualSize.height offsetY: actualSize.height
)) ))
actualSize.height += contentFileSize.height actualSize.height += contentFileSize.height + 9.0
} }
case .actionButton: case .actionButton:
if let (actionButtonSize, _) = actionButtonSizeAndApply { if let (actionButtonSize, _) = actionButtonSizeAndApply {

View File

@ -1329,10 +1329,16 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
strongSelf.view.addSubview(audioTranscriptionButton) strongSelf.view.addSubview(audioTranscriptionButton)
added = true added = true
} }
let buttonTheme: AudioTranscriptionButtonComponent.Theme
if let customTintColor = arguments.customTintColor {
buttonTheme = .custom(customTintColor.withMultipliedAlpha(0.1), customTintColor)
} else {
buttonTheme = .bubble(arguments.incoming ? arguments.presentationData.theme.theme.chat.message.incoming : arguments.presentationData.theme.theme.chat.message.outgoing)
}
let audioTranscriptionButtonSize = audioTranscriptionButton.update( let audioTranscriptionButtonSize = audioTranscriptionButton.update(
transition: animation.isAnimated ? .easeInOut(duration: 0.3) : .immediate, transition: animation.isAnimated ? .easeInOut(duration: 0.3) : .immediate,
component: AnyComponent(AudioTranscriptionButtonComponent( component: AnyComponent(AudioTranscriptionButtonComponent(
theme: .bubble(arguments.incoming ? arguments.presentationData.theme.theme.chat.message.incoming : arguments.presentationData.theme.theme.chat.message.outgoing), theme: buttonTheme,
transcriptionState: effectiveAudioTranscriptionState, transcriptionState: effectiveAudioTranscriptionState,
pressed: { pressed: {
guard let strongSelf = self else { guard let strongSelf = self else {

View File

@ -427,6 +427,10 @@ final class ShareWithPeersScreenComponent: Component {
} }
} }
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.endEditing(true)
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
guard let itemLayout = self.itemLayout, let topOffsetDistance = self.topOffsetDistance else { guard let itemLayout = self.itemLayout, let topOffsetDistance = self.topOffsetDistance else {
return return
@ -801,7 +805,7 @@ final class ShareWithPeersScreenComponent: Component {
} }
private func updateModalOverlayTransition(transition: Transition) { private func updateModalOverlayTransition(transition: Transition) {
guard let component = self.component, let environment = self.environment, let itemLayout = self.itemLayout else { guard let component = self.component, let environment = self.environment, let itemLayout = self.itemLayout, !self.isDismissed else {
return return
} }
@ -2071,6 +2075,14 @@ final class ShareWithPeersScreenComponent: Component {
self.selectedCategories.insert(.everyone) self.selectedCategories.insert(.everyone)
} }
self.state?.updated(transition: Transition(animation: .curve(duration: 0.35, curve: .spring))) self.state?.updated(transition: Transition(animation: .curve(duration: 0.35, curve: .spring)))
},
isFocusedUpdated: { [weak self] isFocused in
guard let self else {
return
}
if isFocused {
self.scrollView.setContentOffset(CGPoint(x: 0.0, y: -self.scrollView.contentInset.top), animated: true)
}
} }
)), )),
environment: {}, environment: {},
@ -2122,11 +2134,11 @@ final class ShareWithPeersScreenComponent: Component {
transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize)) transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize))
if case .members = component.stateContext.subject { if case .members = component.stateContext.subject {
self.dimView .isHidden = true self.dimView.isHidden = true
} else if case .channels = component.stateContext.subject { } else if case .channels = component.stateContext.subject {
self.dimView .isHidden = true self.dimView.isHidden = true
} else { } else {
self.dimView .isHidden = false self.dimView.isHidden = false
} }
let categoryItemSize = self.categoryTemplateItem.update( let categoryItemSize = self.categoryTemplateItem.update(

View File

@ -88,6 +88,7 @@ public final class TokenListTextField: Component {
public let tokens: [Token] public let tokens: [Token]
public let sideInset: CGFloat public let sideInset: CGFloat
public let deleteToken: (AnyHashable) -> Void public let deleteToken: (AnyHashable) -> Void
public let isFocusedUpdated: (Bool) -> Void
public init( public init(
externalState: ExternalState, externalState: ExternalState,
@ -96,7 +97,8 @@ public final class TokenListTextField: Component {
placeholder: String, placeholder: String,
tokens: [Token], tokens: [Token],
sideInset: CGFloat, sideInset: CGFloat,
deleteToken: @escaping (AnyHashable) -> Void deleteToken: @escaping (AnyHashable) -> Void,
isFocusedUpdated: @escaping (Bool) -> Void = { _ in }
) { ) {
self.externalState = externalState self.externalState = externalState
self.context = context self.context = context
@ -105,6 +107,7 @@ public final class TokenListTextField: Component {
self.tokens = tokens self.tokens = tokens
self.sideInset = sideInset self.sideInset = sideInset
self.deleteToken = deleteToken self.deleteToken = deleteToken
self.isFocusedUpdated = isFocusedUpdated
} }
public static func ==(lhs: TokenListTextField, rhs: TokenListTextField) -> Bool { public static func ==(lhs: TokenListTextField, rhs: TokenListTextField) -> Bool {
@ -191,6 +194,7 @@ public final class TokenListTextField: Component {
guard let self else { guard let self else {
return return
} }
self.component?.isFocusedUpdated(self.tokenListNode?.isFocused ?? false)
self.componentState?.updated(transition: Transition(animation: .curve(duration: 0.35, curve: .spring))) self.componentState?.updated(transition: Transition(animation: .curve(duration: 0.35, curve: .spring)))
} }

View File

@ -302,7 +302,7 @@ func openResolvedUrlImpl(
}) })
dismissInput() dismissInput()
case let .share(url, text, to): case let .share(url, text, to):
let continueWithPeer: (PeerId) -> Void = { peerId in let continueWithPeer: (PeerId, Int64?) -> Void = { peerId, threadId in
let textInputState: ChatTextInputState? let textInputState: ChatTextInputState?
if let text = text, !text.isEmpty { if let text = text, !text.isEmpty {
if let url = url, !url.isEmpty { if let url = url, !url.isEmpty {
@ -320,15 +320,42 @@ func openResolvedUrlImpl(
textInputState = nil textInputState = nil
} }
let updateControllers = { [weak navigationController] in
guard let navigationController else {
return
}
let chatController: Signal<ChatController, NoError>
if let threadId {
chatController = chatControllerForForumThreadImpl(context: context, peerId: peerId, threadId: threadId)
} else {
chatController = .single(ChatControllerImpl(context: context, chatLocation: .peer(id: peerId)))
}
let _ = (chatController
|> deliverOnMainQueue).start(next: { [weak navigationController] chatController in
guard let navigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is PeerSelectionController {
return false
}
return true
}
controllers.append(chatController)
navigationController.setViewControllers(controllers, animated: true)
})
}
if let textInputState = textInputState { if let textInputState = textInputState {
let _ = (ChatInterfaceState.update(engine: context.engine, peerId: peerId, threadId: nil, { currentState in let _ = (ChatInterfaceState.update(engine: context.engine, peerId: peerId, threadId: threadId, { currentState in
return currentState.withUpdatedComposeInputState(textInputState) return currentState.withUpdatedComposeInputState(textInputState)
}) })
|> deliverOnMainQueue).startStandalone(completed: { |> deliverOnMainQueue).startStandalone(completed: {
navigationController?.pushViewController(ChatControllerImpl(context: context, chatLocation: .peer(id: peerId))) updateControllers()
}) })
} else { } else {
navigationController?.pushViewController(ChatControllerImpl(context: context, chatLocation: .peer(id: peerId))) updateControllers()
} }
} }
@ -344,7 +371,7 @@ func openResolvedUrlImpl(
|> deliverOnMainQueue).startStandalone(next: { peer in |> deliverOnMainQueue).startStandalone(next: { peer in
if let peer = peer { if let peer = peer {
context.sharedContext.applicationBindings.dismissNativeController() context.sharedContext.applicationBindings.dismissNativeController()
continueWithPeer(peer.id) continueWithPeer(peer.id, nil)
} }
}) })
} else { } else {
@ -352,7 +379,7 @@ func openResolvedUrlImpl(
|> deliverOnMainQueue).startStandalone(next: { peer in |> deliverOnMainQueue).startStandalone(next: { peer in
if let peer = peer { if let peer = peer {
context.sharedContext.applicationBindings.dismissNativeController() context.sharedContext.applicationBindings.dismissNativeController()
continueWithPeer(peer.id) continueWithPeer(peer.id, nil)
} }
}) })
/*let query = to.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789").inverted) /*let query = to.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789").inverted)
@ -377,13 +404,8 @@ func openResolvedUrlImpl(
context.sharedContext.applicationBindings.dismissNativeController() context.sharedContext.applicationBindings.dismissNativeController()
} else { } else {
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyWriteable, .excludeDisabled], selectForumThreads: true)) let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyWriteable, .excludeDisabled], selectForumThreads: true))
controller.peerSelected = { [weak controller] peer, _ in controller.peerSelected = { peer, threadId in
let peerId = peer.id continueWithPeer(peer.id, threadId)
if let strongController = controller {
strongController.dismiss()
continueWithPeer(peerId)
}
} }
context.sharedContext.applicationBindings.dismissNativeController() context.sharedContext.applicationBindings.dismissNativeController()
navigationController?.pushViewController(controller) navigationController?.pushViewController(controller)