mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Update next channel navigation UI
This commit is contained in:
parent
321f4002ab
commit
0a0517122c
@ -289,9 +289,10 @@ public final class NavigateToChatControllerParams {
|
|||||||
public let animated: Bool
|
public let animated: Bool
|
||||||
public let options: NavigationAnimationOptions
|
public let options: NavigationAnimationOptions
|
||||||
public let parentGroupId: PeerGroupId?
|
public let parentGroupId: PeerGroupId?
|
||||||
|
public let chatListFilter: ChatListFilterData?
|
||||||
public let completion: (ChatController) -> Void
|
public let completion: (ChatController) -> Void
|
||||||
|
|
||||||
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
|
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: ChatListFilterData? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
|
||||||
self.navigationController = navigationController
|
self.navigationController = navigationController
|
||||||
self.chatController = chatController
|
self.chatController = chatController
|
||||||
self.chatLocationContextHolder = chatLocationContextHolder
|
self.chatLocationContextHolder = chatLocationContextHolder
|
||||||
@ -312,6 +313,7 @@ public final class NavigateToChatControllerParams {
|
|||||||
self.animated = animated
|
self.animated = animated
|
||||||
self.options = options
|
self.options = options
|
||||||
self.parentGroupId = parentGroupId
|
self.parentGroupId = parentGroupId
|
||||||
|
self.chatListFilter = chatListFilter
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -611,8 +611,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
||||||
scrollToEndIfExists = true
|
scrollToEndIfExists = true
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), activateInput: activateInput && !peer.isDeleted, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, completion: { [weak self] controller in
|
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), activateInput: activateInput && !peer.isDeleted, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, chatListFilter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.data, completion: { [weak self] controller in
|
||||||
self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true)
|
self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true)
|
||||||
if let promoInfo = promoInfo {
|
if let promoInfo = promoInfo {
|
||||||
switch promoInfo {
|
switch promoInfo {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ struct ChatListNodeViewUpdate {
|
|||||||
let scrollPosition: ChatListNodeViewScrollPosition?
|
let scrollPosition: ChatListNodeViewScrollPosition?
|
||||||
}
|
}
|
||||||
|
|
||||||
func chatListFilterPredicate(filter: ChatListFilterData) -> ChatListFilterPredicate {
|
public func chatListFilterPredicate(filter: ChatListFilterData) -> ChatListFilterPredicate {
|
||||||
var includePeers = Set(filter.includePeers.peers)
|
var includePeers = Set(filter.includePeers.peers)
|
||||||
var excludePeers = Set(filter.excludePeers)
|
var excludePeers = Set(filter.excludePeers)
|
||||||
|
|
||||||
|
|||||||
@ -495,16 +495,19 @@ public extension TelegramEngine {
|
|||||||
return _internal_updatePeerDescription(account: self.account, peerId: peerId, description: description)
|
return _internal_updatePeerDescription(account: self.account, peerId: peerId, description: description)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getNextUnreadChannel(peerId: PeerId) -> Signal<EnginePeer?, NoError> {
|
public func getNextUnreadChannel(peerId: PeerId, filter: ChatListFilterPredicate?) -> Signal<EnginePeer?, NoError> {
|
||||||
return self.account.postbox.transaction { transaction -> EnginePeer? in
|
return self.account.postbox.transaction { transaction -> EnginePeer? in
|
||||||
var peers: [RenderedPeer] = []
|
|
||||||
peers.append(contentsOf: transaction.getTopChatListEntries(groupId: .root, count: 100))
|
|
||||||
peers.append(contentsOf: transaction.getTopChatListEntries(groupId: Namespaces.PeerGroup.archive, count: 100))
|
|
||||||
|
|
||||||
var results: [(EnginePeer, Int32)] = []
|
var results: [(EnginePeer, Int32)] = []
|
||||||
|
|
||||||
for peer in peers {
|
var peerIds: [PeerId] = []
|
||||||
guard let channel = peer.chatMainPeer as? TelegramChannel, case .broadcast = channel.info else {
|
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: filter))
|
||||||
|
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: filter))
|
||||||
|
|
||||||
|
for listId in peerIds {
|
||||||
|
guard let peer = transaction.getPeer(listId) else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
guard let channel = peer as? TelegramChannel, case .broadcast = channel.info else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if channel.id == peerId {
|
if channel.id == peerId {
|
||||||
@ -516,6 +519,7 @@ public extension TelegramEngine {
|
|||||||
guard let topMessageIndex = transaction.getTopPeerMessageIndex(peerId: channel.id) else {
|
guard let topMessageIndex = transaction.getTopPeerMessageIndex(peerId: channel.id) else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
results.append((EnginePeer(channel), topMessageIndex.timestamp))
|
results.append((EnginePeer(channel), topMessageIndex.timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -137,6 +137,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
|||||||
case callsTabTip = 18
|
case callsTabTip = 18
|
||||||
case chatFolderTips = 19
|
case chatFolderTips = 19
|
||||||
case locationProximityAlertTip = 20
|
case locationProximityAlertTip = 20
|
||||||
|
case nextChatSuggestionTip = 21
|
||||||
|
|
||||||
var key: ValueBoxKey {
|
var key: ValueBoxKey {
|
||||||
let v = ValueBoxKey(length: 4)
|
let v = ValueBoxKey(length: 4)
|
||||||
@ -268,6 +269,10 @@ private struct ApplicationSpecificNoticeKeys {
|
|||||||
static func locationProximityAlertTip() -> NoticeEntryKey {
|
static func locationProximityAlertTip() -> NoticeEntryKey {
|
||||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.locationProximityAlertTip.key)
|
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.locationProximityAlertTip.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func nextChatSuggestionTip() -> NoticeEntryKey {
|
||||||
|
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.nextChatSuggestionTip.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ApplicationSpecificNotice {
|
public struct ApplicationSpecificNotice {
|
||||||
@ -735,6 +740,28 @@ public struct ApplicationSpecificNotice {
|
|||||||
transaction.setNotice(ApplicationSpecificNoticeKeys.chatMessageOptionsTip(), ApplicationSpecificCounterNotice(value: currentValue))
|
transaction.setNotice(ApplicationSpecificNoticeKeys.chatMessageOptionsTip(), ApplicationSpecificCounterNotice(value: currentValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func getNextChatSuggestionTip(accountManager: AccountManager) -> Signal<Int32, NoError> {
|
||||||
|
return accountManager.transaction { transaction -> Int32 in
|
||||||
|
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.nextChatSuggestionTip()) as? ApplicationSpecificCounterNotice {
|
||||||
|
return value.value
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func incrementNextChatSuggestionTip(accountManager: AccountManager, count: Int32 = 1) -> Signal<Void, NoError> {
|
||||||
|
return accountManager.transaction { transaction -> Void in
|
||||||
|
var currentValue: Int32 = 0
|
||||||
|
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.nextChatSuggestionTip()) as? ApplicationSpecificCounterNotice {
|
||||||
|
currentValue = value.value
|
||||||
|
}
|
||||||
|
currentValue += count
|
||||||
|
|
||||||
|
transaction.setNotice(ApplicationSpecificNoticeKeys.nextChatSuggestionTip(), ApplicationSpecificCounterNotice(value: currentValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static func reset(accountManager: AccountManager) -> Signal<Void, NoError> {
|
public static func reset(accountManager: AccountManager) -> Signal<Void, NoError> {
|
||||||
return accountManager.transaction { transaction -> Void in
|
return accountManager.transaction { transaction -> Void in
|
||||||
|
|||||||
@ -64,6 +64,7 @@ import TelegramPermissionsUI
|
|||||||
import Speak
|
import Speak
|
||||||
import UniversalMediaPlayer
|
import UniversalMediaPlayer
|
||||||
import WallpaperBackgroundNode
|
import WallpaperBackgroundNode
|
||||||
|
import ChatListUI
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
import os.signpost
|
import os.signpost
|
||||||
@ -212,6 +213,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
public weak var parentController: ViewController?
|
public weak var parentController: ViewController?
|
||||||
|
|
||||||
|
private let currentChatListFilter: ChatListFilterData?
|
||||||
|
|
||||||
public var peekActions: ChatControllerPeekActions = .standard
|
public var peekActions: ChatControllerPeekActions = .standard
|
||||||
private var didSetup3dTouch: Bool = false
|
private var didSetup3dTouch: Bool = false
|
||||||
@ -282,6 +285,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
private var preloadHistoryPeerId: PeerId?
|
private var preloadHistoryPeerId: PeerId?
|
||||||
private let preloadHistoryPeerIdDisposable = MetaDisposable()
|
private let preloadHistoryPeerIdDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
private var preloadNextChatPeerId: PeerId?
|
||||||
|
private let preloadNextChatPeerIdDisposable = MetaDisposable()
|
||||||
|
|
||||||
private let botCallbackAlertMessage = Promise<String?>(nil)
|
private let botCallbackAlertMessage = Promise<String?>(nil)
|
||||||
private var botCallbackAlertMessageDisposable: Disposable?
|
private var botCallbackAlertMessageDisposable: Disposable?
|
||||||
@ -459,7 +465,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
private var nextChannelToReadDisposable: Disposable?
|
private var nextChannelToReadDisposable: Disposable?
|
||||||
|
|
||||||
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil) {
|
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: ChatListFilterData? = nil) {
|
||||||
let _ = ChatControllerCount.modify { value in
|
let _ = ChatControllerCount.modify { value in
|
||||||
return value + 1
|
return value + 1
|
||||||
}
|
}
|
||||||
@ -470,6 +476,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.subject = subject
|
self.subject = subject
|
||||||
self.botStart = botStart
|
self.botStart = botStart
|
||||||
self.peekData = peekData
|
self.peekData = peekData
|
||||||
|
self.currentChatListFilter = chatListFilter
|
||||||
|
|
||||||
var useSharedAnimationPhase = false
|
var useSharedAnimationPhase = false
|
||||||
switch mode {
|
switch mode {
|
||||||
@ -3306,16 +3313,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
if let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
|
if let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
|
||||||
if strongSelf.nextChannelToReadDisposable == nil {
|
if strongSelf.nextChannelToReadDisposable == nil {
|
||||||
strongSelf.nextChannelToReadDisposable = (strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id)
|
strongSelf.nextChannelToReadDisposable = (combineLatest(queue: .mainQueue(),
|
||||||
|> deliverOnMainQueue
|
strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id, filter: strongSelf.currentChatListFilter.flatMap(chatListFilterPredicate)),
|
||||||
|
ApplicationSpecificNotice.getNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager)
|
||||||
|
)
|
||||||
|> then(.complete() |> delay(1.0, queue: .mainQueue()))
|
|> then(.complete() |> delay(1.0, queue: .mainQueue()))
|
||||||
|> restart).start(next: { nextPeer in
|
|> restart).start(next: { nextPeer, nextChatSuggestionTip in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.chatDisplayNode.historyNode.offerNextChannelToRead = true
|
strongSelf.chatDisplayNode.historyNode.offerNextChannelToRead = true
|
||||||
strongSelf.chatDisplayNode.historyNode.nextChannelToRead = nextPeer
|
strongSelf.chatDisplayNode.historyNode.nextChannelToRead = nextPeer
|
||||||
|
strongSelf.chatDisplayNode.historyNode.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3
|
||||||
|
|
||||||
|
let nextPeerId = nextPeer?.id
|
||||||
|
|
||||||
|
if strongSelf.preloadNextChatPeerId != nextPeerId {
|
||||||
|
strongSelf.preloadNextChatPeerId = nextPeerId
|
||||||
|
if let nextPeerId = nextPeerId {
|
||||||
|
let combinedDisposable = DisposableSet()
|
||||||
|
strongSelf.preloadNextChatPeerIdDisposable.set(combinedDisposable)
|
||||||
|
combinedDisposable.add(strongSelf.context.account.viewTracker.polledChannel(peerId: nextPeerId).start())
|
||||||
|
combinedDisposable.add(strongSelf.context.account.addAdditionalPreloadHistoryPeerId(peerId: nextPeerId))
|
||||||
|
} else {
|
||||||
|
strongSelf.preloadNextChatPeerIdDisposable.set(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3878,6 +3902,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.shareStatusDisposable?.dispose()
|
self.shareStatusDisposable?.dispose()
|
||||||
self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeTarget(self)
|
self.context.sharedContext.mediaManager.galleryHiddenMediaManager.removeTarget(self)
|
||||||
self.preloadHistoryPeerIdDisposable.dispose()
|
self.preloadHistoryPeerIdDisposable.dispose()
|
||||||
|
self.preloadNextChatPeerIdDisposable.dispose()
|
||||||
self.reportIrrelvantGeoDisposable?.dispose()
|
self.reportIrrelvantGeoDisposable?.dispose()
|
||||||
self.reminderActivity?.invalidate()
|
self.reminderActivity?.invalidate()
|
||||||
self.updateSlowmodeStatusDisposable.dispose()
|
self.updateSlowmodeStatusDisposable.dispose()
|
||||||
@ -7053,11 +7078,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let navigationController = strongSelf.effectiveNavigationController {
|
if let navigationController = strongSelf.effectiveNavigationController {
|
||||||
|
ApplicationSpecificNotice.incrementNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager).start()
|
||||||
|
|
||||||
let snapshotState = strongSelf.chatDisplayNode.prepareSnapshotState(
|
let snapshotState = strongSelf.chatDisplayNode.prepareSnapshotState(
|
||||||
titleViewSnapshotState: strongSelf.chatTitleView?.prepareSnapshotState(),
|
titleViewSnapshotState: strongSelf.chatTitleView?.prepareSnapshotState(),
|
||||||
avatarSnapshotState: (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState()
|
avatarSnapshotState: (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState()
|
||||||
)
|
)
|
||||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, completion: { nextController in
|
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: strongSelf.currentChatListFilter, completion: { nextController in
|
||||||
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
|
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -551,6 +551,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
private var overscrollView: ComponentHostView<Empty>?
|
private var overscrollView: ComponentHostView<Empty>?
|
||||||
var nextChannelToRead: EnginePeer?
|
var nextChannelToRead: EnginePeer?
|
||||||
var offerNextChannelToRead: Bool = false
|
var offerNextChannelToRead: Bool = false
|
||||||
|
var nextChannelToReadDisplayName: Bool = false
|
||||||
private var currentOverscrollExpandProgress: CGFloat = 0.0
|
private var currentOverscrollExpandProgress: CGFloat = 0.0
|
||||||
private var feedback: HapticFeedback?
|
private var feedback: HapticFeedback?
|
||||||
var openNextChannelToRead: ((EnginePeer) -> Void)?
|
var openNextChannelToRead: ((EnginePeer) -> Void)?
|
||||||
@ -1217,15 +1218,25 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
self.view.addSubview(overscrollView)
|
self.view.addSubview(overscrollView)
|
||||||
}
|
}
|
||||||
|
|
||||||
let expandProgress: CGFloat = min(1.0, max(-offset, 0.0) / 110.0)
|
let expandDistance = max(-offset - 12.0, 0.0)
|
||||||
|
let expandProgress: CGFloat = min(1.0, expandDistance / 90.0)
|
||||||
|
|
||||||
let text: String
|
let text: String
|
||||||
if self.nextChannelToRead != nil {
|
if let nextChannelToRead = nextChannelToRead {
|
||||||
if expandProgress >= 0.99 {
|
if self.nextChannelToReadDisplayName {
|
||||||
//TODO:localize
|
if expandProgress >= 0.99 {
|
||||||
text = "Release to go to the next unread channel"
|
//TODO:localize
|
||||||
|
text = "Release to go to \(nextChannelToRead.compactDisplayTitle)"
|
||||||
|
} else {
|
||||||
|
text = "Swipe up to go to \(nextChannelToRead.compactDisplayTitle)"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
text = "Swipe up to go to the next unread channel"
|
if expandProgress >= 0.99 {
|
||||||
|
//TODO:localize
|
||||||
|
text = "Release to go to the next unread channel"
|
||||||
|
} else {
|
||||||
|
text = "Swipe up to go to the next unread channel"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let previousType = self.currentOverscrollExpandProgress >= 0.99
|
let previousType = self.currentOverscrollExpandProgress >= 0.99
|
||||||
@ -1251,7 +1262,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
foregroundColor: bubbleVariableColor(variableColor: self.currentPresentationData.theme.theme.chat.serviceMessage.dateTextColor, wallpaper: self.currentPresentationData.theme.wallpaper),
|
foregroundColor: bubbleVariableColor(variableColor: self.currentPresentationData.theme.theme.chat.serviceMessage.dateTextColor, wallpaper: self.currentPresentationData.theme.wallpaper),
|
||||||
peer: self.nextChannelToRead,
|
peer: self.nextChannelToRead,
|
||||||
context: self.context,
|
context: self.context,
|
||||||
expandProgress: expandProgress
|
expandDistance: expandDistance
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: self.bounds.width, height: 200.0)
|
containerSize: CGSize(width: self.bounds.width, height: 200.0)
|
||||||
|
|||||||
@ -341,7 +341,7 @@ final class ChatOverscrollControl: CombinedComponent {
|
|||||||
let foregroundColor: UIColor
|
let foregroundColor: UIColor
|
||||||
let peer: EnginePeer?
|
let peer: EnginePeer?
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let expandProgress: CGFloat
|
let expandDistance: CGFloat
|
||||||
|
|
||||||
init(
|
init(
|
||||||
text: String,
|
text: String,
|
||||||
@ -349,14 +349,14 @@ final class ChatOverscrollControl: CombinedComponent {
|
|||||||
foregroundColor: UIColor,
|
foregroundColor: UIColor,
|
||||||
peer: EnginePeer?,
|
peer: EnginePeer?,
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
expandProgress: CGFloat
|
expandDistance: CGFloat
|
||||||
) {
|
) {
|
||||||
self.text = text
|
self.text = text
|
||||||
self.backgroundColor = backgroundColor
|
self.backgroundColor = backgroundColor
|
||||||
self.foregroundColor = foregroundColor
|
self.foregroundColor = foregroundColor
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.context = context
|
self.context = context
|
||||||
self.expandProgress = expandProgress
|
self.expandDistance = expandDistance
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: ChatOverscrollControl, rhs: ChatOverscrollControl) -> Bool {
|
static func ==(lhs: ChatOverscrollControl, rhs: ChatOverscrollControl) -> Bool {
|
||||||
@ -375,7 +375,7 @@ final class ChatOverscrollControl: CombinedComponent {
|
|||||||
if lhs.context !== rhs.context {
|
if lhs.context !== rhs.context {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.expandProgress != rhs.expandProgress {
|
if lhs.expandDistance != rhs.expandDistance {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -431,13 +431,32 @@ final class ChatOverscrollControl: CombinedComponent {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let progressSize = avatarBackground.size.width - avatarProgressPadding * 2.0
|
||||||
|
|
||||||
|
let halfDistance = progressSize
|
||||||
|
let quarterDistance = halfDistance / 2.0
|
||||||
|
|
||||||
|
let clippedDistance = max(0.0, min(halfDistance * 2.0, context.component.expandDistance))
|
||||||
|
|
||||||
|
var mappedProgress: CGFloat
|
||||||
|
if clippedDistance <= quarterDistance {
|
||||||
|
mappedProgress = acos(1.0 - clippedDistance / quarterDistance) / (CGFloat.pi * 2.0)
|
||||||
|
} else if clippedDistance <= halfDistance {
|
||||||
|
let sectionDistance = halfDistance - clippedDistance
|
||||||
|
mappedProgress = 0.25 + asin(1.0 - sectionDistance / quarterDistance) / (CGFloat.pi * 2.0)
|
||||||
|
} else {
|
||||||
|
let restDistance = clippedDistance - halfDistance
|
||||||
|
mappedProgress = min(1.0, 0.5 + restDistance / 60.0)
|
||||||
|
}
|
||||||
|
mappedProgress = max(0.01, mappedProgress)
|
||||||
|
|
||||||
let avatarExpandProgress = avatarExpandProgress.update(
|
let avatarExpandProgress = avatarExpandProgress.update(
|
||||||
component: RadialProgressComponent(
|
component: RadialProgressComponent(
|
||||||
color: context.component.foregroundColor,
|
color: context.component.foregroundColor,
|
||||||
lineWidth: 2.5,
|
lineWidth: 2.5,
|
||||||
value: context.component.peer == nil ? 0.0 : context.component.expandProgress
|
value: context.component.peer == nil ? 0.0 : mappedProgress
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: avatarBackground.size.width - avatarProgressPadding * 2.0, height: avatarBackground.size.height - avatarProgressPadding * 2.0),
|
availableSize: CGSize(width: progressSize, height: progressSize),
|
||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData)
|
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter)
|
||||||
}
|
}
|
||||||
controller.purposefulAction = params.purposefulAction
|
controller.purposefulAction = params.purposefulAction
|
||||||
if let search = params.activateMessageSearch {
|
if let search = params.activateMessageSearch {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user