Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2022-11-28 19:10:54 +04:00
commit a8a3854950
19 changed files with 417 additions and 109 deletions

View File

@ -413,8 +413,8 @@ official_apple_pay_merchants = [
"merchant.org.telegram.Best2pay.test",
"merchant.psbank.test.telegramios",
"merchant.psbank.prod.telegramios",
"merchant.org.telegram.billinenet.test",
"merchant.org.telegram.portmone.test",
#"merchant.org.telegram.billinenet.test",
#"merchant.org.telegram.portmone.test",
]
official_bundle_ids = [

View File

@ -8405,3 +8405,37 @@ Sorry for the inconvenience.";
"GlobalAutodeleteSettings.AttemptDisabledGenericSelection" = "You can't enable auto-delete in this chat.";
"EmojiSearch.SearchEmojiPlaceholder" = "Search Emoji";
"MessageTimer.LargeShortSeconds_1" = "%@s";
"MessageTimer.LargeShortSeconds_2" = "%@s";
"MessageTimer.LargeShortSeconds_3_10" = "%@s";
"MessageTimer.LargeShortSeconds_any" = "%@s";
"MessageTimer.LargeShortSeconds_many" = "%@s";
"MessageTimer.LargeShortSeconds_0" = "%@s";
"MessageTimer.LargeShortMinutes_1" = "%@m";
"MessageTimer.LargeShortMinutes_2" = "%@m";
"MessageTimer.LargeShortMinutes_3_10" = "%@m";
"MessageTimer.LargeShortMinutes_any" = "%@m";
"MessageTimer.LargeShortMinutes_many" = "%@m";
"MessageTimer.LargeShortMinutes_0" = "%@m";
"MessageTimer.LargeShortHours_1" = "%@h";
"MessageTimer.LargeShortHours_2" = "%@h";
"MessageTimer.LargeShortHours_3_10" = "%@h";
"MessageTimer.LargeShortHours_any" = "%@h";
"MessageTimer.LargeShortHours_many" = "%@h";
"MessageTimer.LargeShortHours_0" = "%@h";
"MessageTimer.LargeShortDays_1" = "%@d";
"MessageTimer.LargeShortDays_2" = "%@d";
"MessageTimer.LargeShortDays_3_10" = "%@d";
"MessageTimer.LargeShortDays_any" = "%@d";
"MessageTimer.LargeShortDays_many" = "%@d";
"MessageTimer.LargeShortDays_0" = "%@d";
"MessageTimer.LargeShortWeeks_1" = "%@w";
"MessageTimer.LargeShortWeeks_2" = "%@w";
"MessageTimer.LargeShortWeeks_3_10" = "%@w";
"MessageTimer.LargeShortWeeks_any" = "%@w";
"MessageTimer.LargeShortWeeks_many" = "%@w";
"MessageTimer.LargeShortMonths_1" = "%@m";
"MessageTimer.LargeShortMonths_any" = "%@m";
"MessageTimer.LargeShortYears_1" = "%@y";
"MessageTimer.LargeShortYears_any" = "%@y";

View File

@ -140,7 +140,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
private let primaryInfoReady = Promise<Bool>()
private var pendingSecondaryContext: ChatListLocationContext?
private var secondaryContext: ChatListLocationContext?
fileprivate private(set) var secondaryContext: ChatListLocationContext?
fileprivate var effectiveContext: ChatListLocationContext? {
return self.secondaryContext ?? self.primaryContext
@ -250,34 +250,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
case let .forum(peerId):
title = ""
self.forumChannelTracker = ForumChannelTopics(account: self.context.account, peerId: peerId)
self.navigationBar?.userInfo = PeerInfoNavigationSourceTag(peerId: peerId)
self.navigationBar?.allowsCustomTransition = { [weak self] in
guard let strongSelf = self else {
return false
}
if strongSelf.navigationBar?.userInfo == nil {
return false
}
//TODO:loc
if "".isEmpty {
return false
}
return true
}
}
switch self.location {
case .chatList:
/*if let titleView = self.titleView {
titleView.title = NetworkStatusTitle(text: title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false, peerStatus: nil)
//self.navigationItem.titleView = titleView
}*/
//self.primaryInfoReady.set(.single(true))
break
case .forum:
break
}
let primaryContext = ChatListLocationContext(
@ -736,6 +708,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
self.reloadFilters()
}
self.updateNavigationMetadata()
}
required public init(coder aDecoder: NSCoder) {
@ -761,6 +735,31 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.actionDisposables.dispose()
}
private func updateNavigationMetadata() {
guard let currentContext = self.secondaryContext ?? self.primaryContext else {
return
}
switch currentContext.location {
case .chatList:
self.navigationBar?.userInfo = nil
self.navigationBar?.allowsCustomTransition = {
return false
}
case let .forum(peerId):
self.navigationBar?.userInfo = PeerInfoNavigationSourceTag(peerId: peerId)
self.navigationBar?.allowsCustomTransition = { [weak self] in
guard let strongSelf = self else {
return false
}
if strongSelf.navigationBar?.userInfo == nil {
return false
}
return true
}
}
}
func findTitleView() -> ChatListTitleView? {
guard let componentView = self.headerContentView.view as? ChatListHeaderComponent.View else {
return nil
@ -2178,7 +2177,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
func setInlineChatList(location: ChatListControllerLocation?) {
public func setInlineChatList(location: ChatListControllerLocation?) {
if let location {
let inlineNode = self.chatListDisplayNode.makeInlineChatList(location: location)
let pendingSecondaryContext = ChatListLocationContext(
@ -2205,6 +2204,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.secondaryContext = pendingSecondaryContext
self.setToolbar(pendingSecondaryContext.toolbar, transition: .animated(duration: 0.5, curve: .spring))
self.chatListDisplayNode.setInlineChatList(inlineStackContainerNode: inlineNode)
self.updateNavigationMetadata()
})
} else {
if self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing {
@ -2214,6 +2214,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.secondaryContext = nil
self.setToolbar(self.primaryContext?.toolbar, transition: .animated(duration: 0.5, curve: .spring))
self.chatListDisplayNode.setInlineChatList(inlineStackContainerNode: nil)
self.updateNavigationMetadata()
}
}
@ -4739,13 +4740,14 @@ private final class ChatListLocationContext {
}
)))
} else {
let parentController = self.parentController
self.rightButton = AnyComponentWithIdentity(id: "more", component: AnyComponent(NavigationButtonComponent(
content: .more,
pressed: { [weak self] sourceView in
guard let self, let parentController = self.parentController else {
pressed: { [weak parentController] sourceView in
guard let secondaryContext = parentController?.secondaryContext else {
return
}
ChatListControllerImpl.openMoreMenu(context: self.context, peerId: peerId, sourceController: parentController, isViewingAsTopics: true, sourceView: sourceView, gesture: nil)
secondaryContext.performMoreAction(sourceView: sourceView)
},
contextAction: { [weak self] sourceView, gesture in
guard let self, let parentController = self.parentController else {
@ -4770,4 +4772,16 @@ private final class ChatListLocationContext {
self.parentController?.requestUpdateHeaderContent(transition: .immediate)
}
}
private func performMoreAction(sourceView: UIView) {
guard let parentController = self.parentController else {
return
}
switch self.location {
case .chatList:
break
case let .forum(peerId):
ChatListControllerImpl.openMoreMenu(context: self.context, peerId: peerId, sourceController: parentController, isViewingAsTopics: true, sourceView: sourceView, gesture: nil)
}
}
}

View File

@ -2782,7 +2782,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
strongSelf.contextContainer.view.addSubview(avatarTimerBadge)
}
let avatarBadgeSize = CGSize(width: avatarTimerBadgeDiameter, height: avatarTimerBadgeDiameter)
avatarTimerBadge.update(size: avatarBadgeSize, text: shortTimeIntervalString(strings: item.presentationData.strings, value: autoremoveTimeout))
avatarTimerBadge.update(size: avatarBadgeSize, text: shortTimeIntervalString(strings: item.presentationData.strings, value: autoremoveTimeout, useLargeFormat: true))
let avatarBadgeFrame = CGRect(origin: CGPoint(x: avatarFrame.maxX - avatarBadgeSize.width, y: avatarFrame.maxY - avatarBadgeSize.height), size: avatarBadgeSize)
avatarTimerTransition.updatePosition(layer: avatarTimerBadge.layer, position: avatarBadgeFrame.center)
avatarTimerTransition.updateBounds(layer: avatarTimerBadge.layer, bounds: CGRect(origin: CGPoint(), size: avatarBadgeFrame.size))

View File

@ -882,12 +882,15 @@ public final class ContactListNode: ASDisplayNode {
public var multipleSelection = false
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, presentation: Signal<ContactListPresentation, NoError>, filters: [ContactListFilter] = [.excludeSelf], selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, isSearch: Bool = false, multipleSelection: Bool = false) {
private let isPeerEnabled: ((EnginePeer) -> Bool)?
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, presentation: Signal<ContactListPresentation, NoError>, filters: [ContactListFilter] = [.excludeSelf], isPeerEnabled: ((EnginePeer) -> Bool)? = nil, selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, isSearch: Bool = false, multipleSelection: Bool = false) {
self.context = context
self.filters = filters
self.displayPermissionPlaceholder = displayPermissionPlaceholder
self.contextAction = contextAction
self.multipleSelection = multipleSelection
self.isPeerEnabled = isPeerEnabled
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
self.presentationData = presentationData
@ -1069,7 +1072,13 @@ public final class ContactListNode: ASDisplayNode {
}
}
if let mainPeer = peer.chatMainPeer {
resultPeers.append(FoundPeer(peer: mainPeer, subscribers: nil))
var matches = true
if let isPeerEnabled = isPeerEnabled {
matches = isPeerEnabled(EnginePeer(mainPeer))
}
if matches {
resultPeers.append(FoundPeer(peer: mainPeer, subscribers: nil))
}
}
}

View File

@ -219,12 +219,14 @@ private func generateRectsImage(color: UIColor, rects: [CGRect], inset: CGFloat,
} else {
drawFullCorner(context: context, color: color, at: rect.topLeft, type: .topLeft, radius: outerRadius)
}
if previous.maxY >= rect.minY && (rect.topRight.x >= previous.minX && rect.topRight.x <= previous.maxX) {
let radius = min(innerRadius, max(0.0, floor((previous.maxX - rect.topRight.x) / 2.0)))
drawConnectingCorner(context: context, color: color, at: CGPoint(x: rect.topRight.x, y: previous.maxY), type: .topRight, radius: radius)
} else if previous.maxY >= rect.minY && rect.topRight.x - previous.maxX < outerRadius * 2.0 {
let radius = max(0.0, floor((rect.bottomRight.x - previous.maxX) * 0.5))
drawFullCorner(context: context, color: color, at: rect.topRight, type: .topRight, radius: radius)
if previous.contains(rect.topRight.offsetBy(dx: -1.0, dy: 0.0)) {
if abs(rect.topRight.x - previous.maxX) >= innerRadius {
var radius = innerRadius
if let next = next {
radius = min(radius, floor((next.minY - previous.maxY) / 2.0))
}
drawConnectingCorner(context: context, color: color, at: CGPoint(x: rect.topRight.x, y: previous.maxY), type: .topRight, radius: radius)
}
} else {
drawFullCorner(context: context, color: color, at: rect.topRight, type: .topRight, radius: outerRadius)
}
@ -245,19 +247,14 @@ private func generateRectsImage(color: UIColor, rects: [CGRect], inset: CGFloat,
} else {
drawFullCorner(context: context, color: color, at: rect.bottomLeft, type: .bottomLeft, radius: outerRadius)
}
if next.minY <= rect.maxY && (rect.bottomRight.x >= next.minX && rect.bottomRight.x <= next.maxX) {
if next.contains(rect.bottomRight.offsetBy(dx: -1.0, dy: 0.0)) {
if abs(rect.bottomRight.x - next.maxX) >= innerRadius {
var radius = innerRadius
if let previous = previous {
radius = min(radius, floor((next.minY - previous.maxY) / 2.0))
}
drawFullCorner(context: context, color: color, at: rect.bottomRight, type: .bottomRight, radius: radius)
} else {
drawFullCorner(context: context, color: color, at: rect.bottomRight, type: .bottomRight, radius: outerRadius)
drawConnectingCorner(context: context, color: color, at: CGPoint(x: rect.bottomRight.x, y: next.minY), type: .bottomRight, radius: radius)
}
} else if next.minY <= rect.maxY && rect.bottomRight.x - next.maxX < outerRadius * 2.0 {
let radius = max(0.0, floor((rect.bottomRight.x - next.maxX) * 0.5))
drawFullCorner(context: context, color: color, at: rect.bottomRight, type: .bottomRight, radius: radius)
} else {
drawFullCorner(context: context, color: color, at: rect.bottomRight, type: .bottomRight, radius: outerRadius)
}
@ -267,7 +264,6 @@ private func generateRectsImage(color: UIColor, rects: [CGRect], inset: CGFloat,
}
}
}))
}
public final class LinkHighlightingNode: ASDisplayNode {

View File

@ -226,7 +226,7 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
bottomController.viewWillAppear(true)
let bottomNode = bottomController.displayNode
let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, isInteractive: true, isFlat: self.isFlat, container: self, topNode: topNode, topNavigationBar: topController.navigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self, weak bottomController] progress, transition, topFrame, bottomFrame in
let navigationTransitionCoordinator = NavigationTransitionCoordinator(transition: .Pop, isInteractive: true, isFlat: self.isFlat, container: self, topNode: topNode, topNavigationBar: topController.transitionNavigationBar, bottomNode: bottomNode, bottomNavigationBar: bottomController.transitionNavigationBar, didUpdateProgress: { [weak self, weak bottomController] progress, transition, topFrame, bottomFrame in
if let strongSelf = self {
if let top = strongSelf.state.top {
strongSelf.syncKeyboard(leftEdge: top.value.displayNode.frame.minX, transition: transition)
@ -315,12 +315,12 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
for i in 0 ..< controllers.count {
if i == 0 {
if canBeClosed {
controllers[i].navigationBar?.previousItem = .close
controllers[i].transitionNavigationBar?.previousItem = .close
} else {
controllers[i].navigationBar?.previousItem = nil
controllers[i].transitionNavigationBar?.previousItem = nil
}
} else {
controllers[i].navigationBar?.previousItem = .item(controllers[i - 1].navigationItem)
controllers[i].transitionNavigationBar?.previousItem = .item(controllers[i - 1].navigationItem)
}
}
@ -461,7 +461,7 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega
}
toValue.value.setIgnoreAppearanceMethodInvocations(false)
let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, isInteractive: false, isFlat: self.isFlat, container: self, topNode: topController.displayNode, topNavigationBar: topController.navigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.navigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in
let topTransition = TopTransition(type: transitionType, previous: fromValue, coordinator: NavigationTransitionCoordinator(transition: mappedTransitionType, isInteractive: false, isFlat: self.isFlat, container: self, topNode: topController.displayNode, topNavigationBar: topController.transitionNavigationBar, bottomNode: bottomController.displayNode, bottomNavigationBar: bottomController.transitionNavigationBar, didUpdateProgress: { [weak self] _, transition, topFrame, bottomFrame in
guard let strongSelf = self else {
return
}

View File

@ -446,7 +446,7 @@ open class NavigationBar: ASDisplayNode {
return 38.0
}
static func backArrowImage(color: UIColor) -> UIImage? {
public static func backArrowImage(color: UIColor) -> UIImage? {
var red: CGFloat = 0.0
var green: CGFloat = 0.0
var blue: CGFloat = 0.0
@ -487,7 +487,7 @@ open class NavigationBar: ASDisplayNode {
}
public let stripeNode: ASDisplayNode
private let clippingNode: SparseNode
public let clippingNode: SparseNode
private let buttonsContainerNode: ASDisplayNode
public private(set) var contentNode: NavigationBarContentNode?
@ -1498,6 +1498,22 @@ open class NavigationBar: ASDisplayNode {
}
}
public func makeTransitionBackButtonView(accentColor: UIColor) -> UIView? {
if self.backButtonNode.supernode != nil {
let node = NavigationButtonNode()
node.manualAlpha = self.backButtonNode.manualAlpha
node.updateManualText(self.backButtonNode.manualText)
node.color = accentColor
if let validLayout = self.validLayout {
let _ = node.updateLayout(constrainedSize: CGSize(width: validLayout.size.width, height: validLayout.defaultHeight), isLandscape: validLayout.isLandscape)
node.frame = self.backButtonNode.frame
}
return node.view
} else {
return nil
}
}
public func makeTransitionRightButtonNode(accentColor: UIColor) -> NavigationButtonNode? {
if self.rightButtonNode.supernode != nil {
let node = NavigationButtonNode()
@ -1534,6 +1550,17 @@ open class NavigationBar: ASDisplayNode {
}
}
public func makeTransitionBackArrowView(accentColor: UIColor) -> UIView? {
if self.backButtonArrow.supernode != nil {
let view = UIImageView()
view.image = NavigationBar.backArrowImage(color: accentColor)
view.frame = self.backButtonArrow.frame
return view
} else {
return nil
}
}
public func makeTransitionBadgeNode() -> ASDisplayNode? {
if self.badgeNode.supernode != nil && !self.badgeNode.isHidden {
let node = NavigationBarBadgeNode(fillColor: self.presentationData.theme.buttonColor, strokeColor: self.presentationData.theme.buttonColor, textColor: self.presentationData.theme.badgeTextColor)
@ -1547,6 +1574,7 @@ open class NavigationBar: ASDisplayNode {
}
public var intrinsicCanTransitionInline: Bool = true
public var shouldTransitionInline: (() -> Bool)?
public var passthroughTouches = true
@ -1554,6 +1582,11 @@ open class NavigationBar: ASDisplayNode {
if let contentNode = self.contentNode, case .replacement = contentNode.mode {
return false
} else {
if let shouldTransitionInline = self.shouldTransitionInline {
if !shouldTransitionInline() {
return false
}
}
return self.intrinsicCanTransitionInline
}
}

View File

@ -198,6 +198,9 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
public let statusBar: StatusBar
public let navigationBar: NavigationBar?
open var transitionNavigationBar: NavigationBar? {
return self.navigationBar
}
public private(set) var toolbar: Toolbar?
public var displayNavigationBar = true

View File

@ -202,6 +202,7 @@ public func globalAutoremoveScreen(context: AccountContext, initialValue: Int32,
}
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
var presentInCurrentControllerImpl: ((ViewController) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var dismissImpl: (() -> Void)?
var getController: (() -> ViewController?)?
@ -248,7 +249,16 @@ public func globalAutoremoveScreen(context: AccountContext, initialValue: Int32,
}
}
}
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, animateInAsReplacement: animateAsReplacement, action: { _ in return false }), nil)
if let current = getController?() {
current.forEachController { other in
if let other = other as? UndoOverlayController {
animateAsReplacement = true
other.dismiss()
}
return true
}
}
presentInCurrentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, animateInAsReplacement: animateAsReplacement, action: { _ in return false }))
}
updateTimeoutDisposable.set((context.engine.privacy.updateGlobalMessageRemovalTimeout(timeout: timeout == 0 ? nil : timeout)
@ -391,7 +401,16 @@ public func globalAutoremoveScreen(context: AccountContext, initialValue: Int32,
}
}
}
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, animateInAsReplacement: animateAsReplacement, action: { _ in return false }), nil)
if let current = getController?() {
current.forEachController { other in
if let other = other as? UndoOverlayController {
animateAsReplacement = true
other.dismiss()
}
return true
}
}
presentInCurrentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, animateInAsReplacement: animateAsReplacement, action: { _ in return false }))
})
}
})
@ -432,6 +451,12 @@ public func globalAutoremoveScreen(context: AccountContext, initialValue: Int32,
}
controller.present(c, in: .window(.root), with: p)
}
presentInCurrentControllerImpl = { [weak controller] c in
guard let controller else {
return
}
controller.present(c, in: .current, with: nil)
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}

View File

@ -121,6 +121,10 @@ open class TabBarControllerImpl: ViewController, TabBarController {
public var currentController: ViewController?
override public var transitionNavigationBar: NavigationBar? {
return self.currentController?.navigationBar
}
private let pendingControllerDisposable = MetaDisposable()
private var theme: TabBarControllerTheme

View File

@ -183,6 +183,14 @@ func _internal_updateAccountRemovalTimeout(account: Account, timeout: Int32) ->
}
func _internal_updateMessageRemovalTimeout(account: Account, timeout: Int32?) -> Signal<Void, NoError> {
let _ = account.postbox.transaction({ transaction -> Void in
updateGlobalMessageAutoremoveTimeoutSettings(transaction: transaction, { settings in
var settings = settings
settings.messageAutoremoveTimeout = timeout
return settings
})
}).start()
return account.network.request(Api.functions.messages.setDefaultHistoryTTL(period: timeout ?? 0))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)

View File

@ -195,21 +195,39 @@ public func scheduledTimeIntervalString(strings: PresentationStrings, value: Int
}
}
public func shortTimeIntervalString(strings: PresentationStrings, value: Int32) -> String {
if value < 60 {
return strings.MessageTimer_ShortSeconds(max(1, value))
} else if value < 60 * 60 {
return strings.MessageTimer_ShortMinutes(max(1, value / 60))
} else if value < 60 * 60 * 24 {
return strings.MessageTimer_ShortHours(max(1, value / (60 * 60)))
} else if value < 60 * 60 * 24 * 7 {
return strings.MessageTimer_ShortDays(max(1, value / (60 * 60 * 24)))
} else if value < 60 * 60 * 24 * 31 {
return strings.MessageTimer_ShortWeeks(max(1, value / (60 * 60 * 24 * 7)))
} else if value < 60 * 60 * 24 * 365 {
return strings.MessageTimer_ShortMonths(max(1, value / (60 * 60 * 24 * 30)))
public func shortTimeIntervalString(strings: PresentationStrings, value: Int32, useLargeFormat: Bool = false) -> String {
if useLargeFormat {
if value < 60 {
return strings.MessageTimer_LargeShortSeconds(max(1, value))
} else if value < 60 * 60 {
return strings.MessageTimer_LargeShortMinutes(max(1, value / 60))
} else if value < 60 * 60 * 24 {
return strings.MessageTimer_LargeShortHours(max(1, value / (60 * 60)))
} else if value < 60 * 60 * 24 * 7 {
return strings.MessageTimer_LargeShortDays(max(1, value / (60 * 60 * 24)))
} else if value < 60 * 60 * 24 * 31 {
return strings.MessageTimer_LargeShortWeeks(max(1, value / (60 * 60 * 24 * 7)))
} else if value < 60 * 60 * 24 * 365 {
return strings.MessageTimer_LargeShortMonths(max(1, value / (60 * 60 * 24 * 30)))
} else {
return strings.MessageTimer_LargeShortYears(max(1, value / (60 * 60 * 24 * 365)))
}
} else {
return strings.MessageTimer_ShortYears(max(1, value / (60 * 60 * 24 * 365)))
if value < 60 {
return strings.MessageTimer_ShortSeconds(max(1, value))
} else if value < 60 * 60 {
return strings.MessageTimer_ShortMinutes(max(1, value / 60))
} else if value < 60 * 60 * 24 {
return strings.MessageTimer_ShortHours(max(1, value / (60 * 60)))
} else if value < 60 * 60 * 24 * 7 {
return strings.MessageTimer_ShortDays(max(1, value / (60 * 60 * 24)))
} else if value < 60 * 60 * 24 * 31 {
return strings.MessageTimer_ShortWeeks(max(1, value / (60 * 60 * 24 * 7)))
} else if value < 60 * 60 * 24 * 365 {
return strings.MessageTimer_ShortMonths(max(1, value / (60 * 60 * 24 * 30)))
} else {
return strings.MessageTimer_ShortYears(max(1, value / (60 * 60 * 24 * 365)))
}
}
}

View File

@ -247,11 +247,11 @@ public final class ChatListHeaderComponent: Component {
let arrowSize = self.arrowView.image?.size ?? CGSize(width: 13.0, height: 22.0)
let arrowFrame = CGRect(origin: CGPoint(x: iconOffset, y: floor((availableSize.height - arrowSize.height) / 2.0)), size: arrowSize)
let arrowFrame = CGRect(origin: CGPoint(x: iconOffset - 1.0, y: floor((availableSize.height - arrowSize.height) / 2.0)), size: arrowSize)
transition.setPosition(view: self.arrowView, position: arrowFrame.center)
transition.setBounds(view: self.arrowView, bounds: CGRect(origin: CGPoint(), size: arrowFrame.size))
transition.setFrame(view: self.titleView, frame: CGRect(origin: CGPoint(x: iconOffset + arrowSize.width + iconSpacing, y: floor((availableSize.height - titleSize.height) / 2.0)), size: titleSize))
transition.setFrame(view: self.titleView, frame: CGRect(origin: CGPoint(x: iconOffset - 3.0 + arrowSize.width + iconSpacing, y: floor((availableSize.height - titleSize.height) / 2.0)), size: titleSize))
return CGSize(width: iconOffset + arrowSize.width + iconSpacing + titleSize.width, height: availableSize.height)
}
@ -589,6 +589,10 @@ public final class ChatListHeaderComponent: Component {
private var primaryContentView: ContentView?
private var secondaryContentView: ContentView?
private var effectiveContentView: ContentView? {
return self.secondaryContentView ?? self.primaryContentView
}
override init(frame: CGRect) {
super.init(frame: frame)
}
@ -597,6 +601,45 @@ public final class ChatListHeaderComponent: Component {
fatalError("init(coder:) has not been implemented")
}
public var backArrowView: UIView? {
return self.effectiveContentView?.backButtonView?.arrowView
}
public var backButtonTitleView: UIView? {
return self.effectiveContentView?.backButtonView?.titleView
}
public var rightButtonView: UIView? {
return self.effectiveContentView?.rightButtonViews.first?.value.view
}
public var titleContentView: UIView? {
return self.effectiveContentView?.titleContentView?.view
}
public func makeTransitionBackArrowView(accentColor: UIColor) -> UIView? {
if let backArrowView = self.backArrowView {
let view = UIImageView()
view.image = NavigationBar.backArrowImage(color: accentColor)
view.frame = backArrowView.convert(backArrowView.bounds, to: self)
return view
} else {
return nil
}
}
public func makeTransitionBackButtonView(accentColor: UIColor) -> UIView? {
if let backButtonTitleView = self.backButtonTitleView as? ImmediateTextView {
let view = ImmediateTextView()
view.attributedText = NSAttributedString(string: backButtonTitleView.attributedText?.string ?? "", font: Font.regular(17.0), textColor: accentColor)
let _ = view.updateLayout(CGSize(width: 100.0, height: 100.0))
view.frame = backButtonTitleView.convert(backButtonTitleView.bounds, to: self)
return view
} else {
return nil
}
}
func update(component: ChatListHeaderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
self.state = state

View File

@ -963,7 +963,7 @@ public final class ChatTitleComponent: Component {
}
public final class View: UIView {
private var contentView: ChatTitleView?
public private(set) var contentView: ChatTitleView?
private var component: ChatTitleComponent?

View File

@ -2371,7 +2371,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}, openUrl: { [weak self] url, concealed, _, message in
if let strongSelf = self {
strongSelf.openUrl(url, concealed: concealed, message: message)
var skipConcealedAlert = false
if let author = message?.author, author.isVerified {
skipConcealedAlert = true
}
strongSelf.openUrl(url, concealed: concealed, skipConcealedAlert: skipConcealedAlert, message: message)
}
}, shareCurrentLocation: { [weak self] in
if let strongSelf = self {

View File

@ -208,7 +208,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
if let (currentOffset, currentImage, currentRects) = cachedMaskBackgroundImage, currentRects == labelRects {
backgroundMaskImage = (currentOffset, currentImage)
} else {
backgroundMaskImage = LinkHighlightingNode.generateImage(color: .black, inset: 0.0, innerRadius: 10.0, outerRadius: 10.0, rects: labelRects, useModernPathCalculation: true)
backgroundMaskImage = LinkHighlightingNode.generateImage(color: .black, inset: 0.0, innerRadius: 10.0, outerRadius: 10.0, rects: labelRects, useModernPathCalculation: false)
backgroundMaskUpdated = true
}
@ -449,7 +449,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
} else {
let serviceColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper)
linkHighlightingNode = LinkHighlightingNode(color: serviceColor.linkHighlight)
linkHighlightingNode.useModernPathCalculation = true
linkHighlightingNode.useModernPathCalculation = false
linkHighlightingNode.inset = 2.5
self.linkHighlightingNode = linkHighlightingNode
self.insertSubnode(linkHighlightingNode, belowSubnode: self.labelNode.textNode)

View File

@ -71,6 +71,8 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
private let animationCache: AnimationCache
private let animationRenderer: MultiAnimationRenderer
private let isPeerEnabled: ((EnginePeer) -> Bool)?
init(navigationBar: NavigationBar?, context: AccountContext, presentationData: PresentationData, mode: ContactMultiselectionControllerMode, isPeerEnabled: ((EnginePeer) -> Bool)?, attemptDisabledItemSelection: ((EnginePeer) -> Void)?, options: [ContactListAdditionalOption], filters: [ContactListFilter], limit: Int32?, reachedSelectionLimit: ((Int32) -> Void)?) {
self.navigationBar = navigationBar
@ -80,6 +82,8 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
self.animationCache = context.animationCache
self.animationRenderer = context.animationRenderer
self.isPeerEnabled = isPeerEnabled
var placeholder: String
var includeChatList = false
switch mode {
@ -210,7 +214,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
searchChannels = true
globalSearch = false
}
let searchResultsNode = ContactListNode(context: context, presentation: .single(.search(signal: searchText.get(), searchChatList: searchChatList, searchDeviceContacts: false, searchGroups: searchGroups, searchChannels: searchChannels, globalSearch: globalSearch)), filters: filters, selectionState: selectionState, isSearch: true)
let searchResultsNode = ContactListNode(context: context, presentation: .single(.search(signal: searchText.get(), searchChatList: searchChatList, searchDeviceContacts: false, searchGroups: searchGroups, searchChannels: searchChannels, globalSearch: globalSearch)), filters: filters, isPeerEnabled: strongSelf.isPeerEnabled, selectionState: selectionState, isSearch: true)
searchResultsNode.openPeer = { peer, _ in
self?.tokenListNode.setText("")
self?.openPeer?(peer)

View File

@ -82,6 +82,7 @@ import NotificationExceptionsScreen
import ChatTimerScreen
import NotificationPeerExceptionController
import StickerPackPreviewUI
import ChatListHeaderComponent
protocol PeerInfoScreenItem: AnyObject {
var id: AnyHashable { get }
@ -8949,6 +8950,21 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
}
if self.chatLocation.peerId != nil {
/*self.navigationBar?.shouldTransitionInline = { [weak self] in
guard let strongSelf = self else {
return false
}
if strongSelf.navigationItem.leftBarButtonItem != nil {
return false
}
if strongSelf.controllerNode.scrollNode.view.contentOffset.y > .ulpOfOne {
return false
}
if strongSelf.controllerNode.headerNode.isAvatarExpanded {
return false
}
return false
}*/
self.navigationBar?.makeCustomTransitionNode = { [weak self] other, isInteractive in
guard let strongSelf = self else {
return nil
@ -9136,6 +9152,9 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
}, action: { _, f in
f(.default)
if let controller = navigationController?.viewControllers.first as? TabBarController, let chatListController = controller.currentController as? ChatListControllerImpl {
chatListController.setInlineChatList(location: nil)
}
navigationController?.popToRoot(animated: true)
})))
@ -9372,15 +9391,21 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
private let headerNode: PeerInfoHeaderNode
private var previousBackButtonArrow: ASDisplayNode?
private var previousBackButton: ASDisplayNode?
private var previousBackButtonArrow: UIView?
private var previousBackButton: UIView?
private var currentBackButtonArrow: ASDisplayNode?
private var previousBackButtonBadge: ASDisplayNode?
private var currentBackButton: ASDisplayNode?
private var previousRightButton: CALayer?
private var previousContentNode: ASDisplayNode?
private var previousContentNodeFrame: CGRect?
private var previousContentNodeAlpha: CGFloat = 1.0
private var previousSecondaryContentNode: ASDisplayNode?
private var previousSecondaryContentNodeFrame: CGRect?
private var previousSecondaryContentNodeAlpha: CGFloat = 1.0
private var previousTitleNode: (ASDisplayNode, PortalView)?
private var previousStatusNode: (ASDisplayNode, ASDisplayNode)?
@ -9413,40 +9438,82 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
if let topNavigationBar = self.topNavigationBar, let bottomNavigationBar = self.bottomNavigationBar {
self.addSubnode(bottomNavigationBar.additionalContentNode)
if let previousBackButtonArrow = bottomNavigationBar.makeTransitionBackArrowNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButtonArrow = previousBackButtonArrow
self.addSubnode(previousBackButtonArrow)
}
if let previousBackButton = bottomNavigationBar.makeTransitionBackButtonNode(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButton = previousBackButton
self.addSubnode(previousBackButton)
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let previousBackButtonArrow = headerView.makeTransitionBackArrowView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButtonArrow = previousBackButtonArrow
self.view.addSubview(previousBackButtonArrow)
}
if let previousBackButton = headerView.makeTransitionBackButtonView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButton = previousBackButton
self.view.addSubview(previousBackButton)
}
} else {
if let previousBackButtonArrow = bottomNavigationBar.makeTransitionBackArrowView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButtonArrow = previousBackButtonArrow
self.view.addSubview(previousBackButtonArrow)
}
if let previousBackButton = bottomNavigationBar.makeTransitionBackButtonView(accentColor: self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.previousBackButton = previousBackButton
self.view.addSubview(previousBackButton)
}
}
if self.screenNode.headerNode.isAvatarExpanded, let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.currentBackButtonArrow = currentBackButtonArrow
self.addSubnode(currentBackButtonArrow)
}
if let previousBackButtonBadge = bottomNavigationBar.makeTransitionBadgeNode() {
self.previousBackButtonBadge = previousBackButtonBadge
self.addSubnode(previousBackButtonBadge)
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
let _ = headerView
} else {
if let previousBackButtonBadge = bottomNavigationBar.makeTransitionBadgeNode() {
self.previousBackButtonBadge = previousBackButtonBadge
self.addSubnode(previousBackButtonBadge)
}
}
if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: self.screenNode.headerNode.isAvatarExpanded ? .white : self.presentationData.theme.rootController.navigationBar.accentTextColor) {
self.currentBackButton = currentBackButton
self.addSubnode(currentBackButton)
}
if let _ = bottomNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode {
} else if let previousRightButton = bottomNavigationBar.rightButtonNode.view.layer.snapshotContentTree() {
self.previousRightButton = previousRightButton
self.view.layer.addSublayer(previousRightButton)
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let previousRightButton = headerView.rightButtonView?.layer.snapshotContentTree() {
self.previousRightButton = previousRightButton
self.view.layer.addSublayer(previousRightButton)
}
} else {
if let _ = bottomNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode {
} else if let previousRightButton = bottomNavigationBar.rightButtonNode.view.layer.snapshotContentTree() {
self.previousRightButton = previousRightButton
self.view.layer.addSublayer(previousRightButton)
}
}
if let contentNode = bottomNavigationBar.contentNode {
self.previousContentNode = contentNode
self.previousContentNodeFrame = contentNode.view.convert(contentNode.view.bounds, to: bottomNavigationBar.view)
self.previousContentNodeAlpha = contentNode.alpha
self.addSubnode(contentNode)
}
if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView, let previousTitleNode = PortalView(matchPosition: false) {
if let secondaryContentNode = bottomNavigationBar.secondaryContentNode {
self.previousSecondaryContentNode = secondaryContentNode
self.previousSecondaryContentNodeFrame = secondaryContentNode.view.convert(secondaryContentNode.view.bounds, to: bottomNavigationBar.view)
self.previousSecondaryContentNodeAlpha = secondaryContentNode.alpha
self.addSubnode(secondaryContentNode)
}
var previousTitleView: UIView?
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let componentView = headerView.titleContentView as? ChatTitleComponent.View {
previousTitleView = componentView.contentView
}
} else {
previousTitleView = bottomNavigationBar.titleView
}
if let previousTitleView = previousTitleView as? ChatTitleView, let previousTitleNode = PortalView(matchPosition: false) {
previousTitleNode.view.frame = previousTitleView.titleContainerView.frame
previousTitleView.titleContainerView.addPortal(view: previousTitleNode)
let previousTitleContainerNode = ASDisplayNode()
@ -9473,20 +9540,43 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
let fraction = self.reverseFraction ? (1.0 - fraction) : fraction
if let previousBackButtonArrow = self.previousBackButtonArrow {
let previousBackButtonArrowFrame = bottomNavigationBar.backButtonArrow.view.convert(bottomNavigationBar.backButtonArrow.view.bounds, to: bottomNavigationBar.view)
previousBackButtonArrow.frame = previousBackButtonArrowFrame
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let backArrowView = headerView.backArrowView {
let previousBackButtonArrowFrame = backArrowView.convert(backArrowView.bounds, to: bottomNavigationBar.view)
previousBackButtonArrow.frame = previousBackButtonArrowFrame
}
} else {
let previousBackButtonArrowFrame = bottomNavigationBar.backButtonArrow.view.convert(bottomNavigationBar.backButtonArrow.view.bounds, to: bottomNavigationBar.view)
previousBackButtonArrow.frame = previousBackButtonArrowFrame
}
}
if let previousBackButton = self.previousBackButton {
let previousBackButtonFrame = bottomNavigationBar.backButtonNode.view.convert(bottomNavigationBar.backButtonNode.view.bounds, to: bottomNavigationBar.view)
previousBackButton.frame = previousBackButtonFrame
transition.updateAlpha(node: previousBackButton, alpha: fraction)
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let backButtonTitleView = headerView.backButtonTitleView {
let previousBackButtonFrame = backButtonTitleView.convert(backButtonTitleView.bounds, to: bottomNavigationBar.view)
previousBackButton.frame = previousBackButtonFrame
transition.updateAlpha(layer: previousBackButton.layer, alpha: fraction)
}
} else {
let previousBackButtonFrame = bottomNavigationBar.backButtonNode.view.convert(bottomNavigationBar.backButtonNode.view.bounds, to: bottomNavigationBar.view)
previousBackButton.frame = previousBackButtonFrame
transition.updateAlpha(layer: previousBackButton.layer, alpha: fraction)
}
}
if let previousRightButton = self.previousRightButton {
let previousRightButtonFrame = bottomNavigationBar.rightButtonNode.view.convert(bottomNavigationBar.rightButtonNode.view.bounds, to: bottomNavigationBar.view)
previousRightButton.frame = previousRightButtonFrame
transition.updateAlpha(layer: previousRightButton, alpha: fraction)
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let rightButtonView = headerView.rightButtonView {
let previousRightButtonFrame = rightButtonView.convert(rightButtonView.bounds, to: bottomNavigationBar.view)
previousRightButton.frame = previousRightButtonFrame
transition.updateAlpha(layer: previousRightButton, alpha: fraction)
}
} else {
let previousRightButtonFrame = bottomNavigationBar.rightButtonNode.view.convert(bottomNavigationBar.rightButtonNode.view.bounds, to: bottomNavigationBar.view)
previousRightButton.frame = previousRightButtonFrame
transition.updateAlpha(layer: previousRightButton, alpha: fraction)
}
}
if let currentBackButtonArrow = self.currentBackButtonArrow {
@ -9495,7 +9585,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
transition.updateAlpha(node: currentBackButtonArrow, alpha: 1.0 - fraction)
if let previousBackButtonArrow = self.previousBackButtonArrow {
transition.updateAlpha(node: previousBackButtonArrow, alpha: fraction)
transition.updateAlpha(layer: previousBackButtonArrow.layer, alpha: fraction)
}
}
@ -9510,7 +9600,16 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
transition.updateAlpha(node: currentBackButton, alpha: (1.0 - fraction))
}
if let previousTitleView = bottomNavigationBar.titleView as? ChatTitleView, let (previousTitleContainerNode, previousTitleNode) = self.previousTitleNode, let (previousStatusContainerNode, previousStatusNode) = self.previousStatusNode {
var previousTitleView: UIView?
if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View {
if let componentView = headerView.titleContentView as? ChatTitleComponent.View {
previousTitleView = componentView.contentView
}
} else {
previousTitleView = bottomNavigationBar.titleView
}
if let previousTitleView = previousTitleView as? ChatTitleView, let (previousTitleContainerNode, previousTitleNode) = self.previousTitleNode, let (previousStatusContainerNode, previousStatusNode) = self.previousStatusNode {
let previousTitleFrame = previousTitleView.titleContainerView.convert(previousTitleView.titleContainerView.bounds, to: bottomNavigationBar.view)
let previousStatusFrame = previousTitleView.activityNode.view.convert(previousTitleView.activityNode.bounds, to: bottomNavigationBar.view)
@ -9572,6 +9671,13 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
transition.updateFrame(node: previousContentNode, frame: updatedPreviousContentNodeFrame)
transition.updateAlpha(node: previousContentNode, alpha: fraction)
}
if let previousSecondaryContentNode = self.previousSecondaryContentNode, let previousSecondaryContentNodeFrame = self.previousSecondaryContentNodeFrame {
var updatedPreviousSecondaryContentNodeFrame = bottomNavigationBar.view.convert(previousSecondaryContentNodeFrame, to: bottomNavigationBar.view)
updatedPreviousSecondaryContentNodeFrame.origin.y += (1.0 - fraction) * (topHeight - bottomHeight)
transition.updateFrame(node: previousSecondaryContentNode, frame: updatedPreviousSecondaryContentNodeFrame)
transition.updateAlpha(node: previousSecondaryContentNode, alpha: fraction)
}
}
}
@ -9595,8 +9701,15 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
if let previousContentNode = self.previousContentNode, let previousContentNodeFrame = self.previousContentNodeFrame {
previousContentNode.frame = previousContentNodeFrame
previousContentNode.alpha = self.previousContentNodeAlpha
bottomNavigationBar.insertSubnode(previousContentNode, belowSubnode: bottomNavigationBar.stripeNode)
}
if let previousSecondaryContentNode = self.previousSecondaryContentNode, let previousSecondaryContentNodeFrame = self.previousSecondaryContentNodeFrame {
previousSecondaryContentNode.frame = previousSecondaryContentNodeFrame
previousSecondaryContentNode.alpha = self.previousSecondaryContentNodeAlpha
bottomNavigationBar.clippingNode.addSubnode(previousSecondaryContentNode)
}
}
}