mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Tooltip
This commit is contained in:
parent
a7c7608d21
commit
ff0e21e412
@ -181,7 +181,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
private var rawStorySubscriptions: EngineStorySubscriptions?
|
private var rawStorySubscriptions: EngineStorySubscriptions?
|
||||||
private var shouldFixStorySubscriptionOrder: Bool = false
|
private var shouldFixStorySubscriptionOrder: Bool = false
|
||||||
private var fixedStorySubscriptionOrder: [EnginePeer.Id] = []
|
private var fixedStorySubscriptionOrder: [EnginePeer.Id] = []
|
||||||
var orderedStorySubscriptions: EngineStorySubscriptions?
|
private(set) var orderedStorySubscriptions: EngineStorySubscriptions?
|
||||||
|
private var displayedStoriesTooltip: Bool = false
|
||||||
|
|
||||||
private var storyProgressDisposable: Disposable?
|
private var storyProgressDisposable: Disposable?
|
||||||
private var storySubscriptionsDisposable: Disposable?
|
private var storySubscriptionsDisposable: Disposable?
|
||||||
@ -1853,11 +1854,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var wasEmpty = true
|
|
||||||
if let rawStorySubscriptions = self.rawStorySubscriptions, !rawStorySubscriptions.items.isEmpty {
|
|
||||||
wasEmpty = false
|
|
||||||
}
|
|
||||||
|
|
||||||
self.rawStorySubscriptions = rawStorySubscriptions
|
self.rawStorySubscriptions = rawStorySubscriptions
|
||||||
var items: [EngineStorySubscriptions.Item] = []
|
var items: [EngineStorySubscriptions.Item] = []
|
||||||
if self.shouldFixStorySubscriptionOrder {
|
if self.shouldFixStorySubscriptionOrder {
|
||||||
@ -1879,8 +1875,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
)
|
)
|
||||||
self.fixedStorySubscriptionOrder = items.map(\.peer.id)
|
self.fixedStorySubscriptionOrder = items.map(\.peer.id)
|
||||||
|
|
||||||
let isEmpty = rawStorySubscriptions.items.isEmpty
|
|
||||||
|
|
||||||
let transition: ContainedViewLayoutTransition
|
let transition: ContainedViewLayoutTransition
|
||||||
if self.didAppear {
|
if self.didAppear {
|
||||||
transition = .animated(duration: 0.4, curve: .spring)
|
transition = .animated(duration: 0.4, curve: .spring)
|
||||||
@ -1888,9 +1882,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
transition = .immediate
|
transition = .immediate
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = wasEmpty
|
|
||||||
let _ = isEmpty
|
|
||||||
|
|
||||||
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = transition
|
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = transition
|
||||||
self.requestLayout(transition: transition)
|
self.requestLayout(transition: transition)
|
||||||
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
|
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
|
||||||
@ -1911,6 +1902,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.storiesReady.set(.single(true))
|
self.storiesReady.set(.single(true))
|
||||||
|
|
||||||
|
Queue.mainQueue().after(1.0, { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.maybeDisplayStoryTooltip()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
self.storyProgressDisposable = (self.context.engine.messages.allStoriesUploadProgress()
|
self.storyProgressDisposable = (self.context.engine.messages.allStoriesUploadProgress()
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] progress in
|
|> deliverOnMainQueue).start(next: { [weak self] progress in
|
||||||
@ -1922,6 +1920,67 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate func maybeDisplayStoryTooltip() {
|
||||||
|
let content = self.updateHeaderContent()
|
||||||
|
if content.secondaryContent != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let chatListTitle = content.primaryContent?.chatListTitle else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if chatListTitle.activity {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.displayedStoriesTooltip {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let orderedStorySubscriptions = self.orderedStorySubscriptions, !orderedStorySubscriptions.items.isEmpty {
|
||||||
|
let _ = (ApplicationSpecificNotice.displayChatListStoriesTooltip(accountManager: self.context.sharedContext.accountManager)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] didDisplay in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if didDisplay {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View, !navigationBarView.storiesUnlocked, !self.displayedStoriesTooltip {
|
||||||
|
if let storyPeerListView = self.chatListHeaderView()?.storyPeerListView(), let (anchorView, anchorRect) = storyPeerListView.anchorForTooltip() {
|
||||||
|
self.displayedStoriesTooltip = true
|
||||||
|
|
||||||
|
let absoluteFrame = anchorView.convert(anchorRect, to: self.view)
|
||||||
|
//TODO:localize
|
||||||
|
|
||||||
|
let itemList = orderedStorySubscriptions.items.prefix(3).map(\.peer.compactDisplayTitle)
|
||||||
|
var itemListString: String = itemList.joined(separator: ", ")
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
let listFormatter = ListFormatter()
|
||||||
|
listFormatter.locale = localeWithStrings(self.presentationData.strings)
|
||||||
|
if let value = listFormatter.string(from: itemList) {
|
||||||
|
itemListString = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let text: String = "Tap above to view updates\nfrom \(itemListString)"
|
||||||
|
|
||||||
|
let tooltipController = TooltipController(content: .text(text), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, timeout: 30.0, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true, padding: 6.0, innerPadding: UIEdgeInsets(top: 2.0, left: 3.0, bottom: 2.0, right: 3.0))
|
||||||
|
self.present(tooltipController, in: .current, with: TooltipControllerPresentationArguments(sourceNodeAndRect: { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return (self.displayNode, absoluteFrame.insetBy(dx: 0.0, dy: 0.0).offsetBy(dx: 0.0, dy: 0.0))
|
||||||
|
}))
|
||||||
|
|
||||||
|
#if !DEBUG
|
||||||
|
let _ = ApplicationSpecificNotice.setDisplayChatListStoriesTooltip(accountManager: self.context.sharedContext.accountManager).start()
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override func displayNodeDidLoad() {
|
public override func displayNodeDidLoad() {
|
||||||
super.displayNodeDidLoad()
|
super.displayNodeDidLoad()
|
||||||
|
|
||||||
@ -2351,7 +2410,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateHeaderContent(layout: ContainerViewLayout) -> (primaryContent: ChatListHeaderComponent.Content?, secondaryContent: ChatListHeaderComponent.Content?) {
|
func updateHeaderContent() -> (primaryContent: ChatListHeaderComponent.Content?, secondaryContent: ChatListHeaderComponent.Content?) {
|
||||||
var primaryContent: ChatListHeaderComponent.Content?
|
var primaryContent: ChatListHeaderComponent.Content?
|
||||||
if let primaryContext = self.primaryContext {
|
if let primaryContext = self.primaryContext {
|
||||||
var backTitle: String?
|
var backTitle: String?
|
||||||
@ -5684,6 +5743,8 @@ private final class ChatListLocationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.parentController?.requestLayout(transition: .animated(duration: 0.45, curve: .spring))
|
self.parentController?.requestLayout(transition: .animated(duration: 0.45, curve: .spring))
|
||||||
|
|
||||||
|
self.parentController?.maybeDisplayStoryTooltip()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateForum(
|
private func updateForum(
|
||||||
|
|||||||
@ -1915,7 +1915,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateNavigationBar(layout: ContainerViewLayout, deferScrollApplication: Bool, transition: Transition) -> (navigationHeight: CGFloat, storiesInset: CGFloat) {
|
private func updateNavigationBar(layout: ContainerViewLayout, deferScrollApplication: Bool, transition: Transition) -> (navigationHeight: CGFloat, storiesInset: CGFloat) {
|
||||||
let headerContent = self.controller?.updateHeaderContent(layout: layout)
|
let headerContent = self.controller?.updateHeaderContent()
|
||||||
|
|
||||||
var tabsNode: ASDisplayNode?
|
var tabsNode: ASDisplayNode?
|
||||||
var tabsNodeIsSearch = false
|
var tabsNodeIsSearch = false
|
||||||
@ -2355,7 +2355,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func shouldStopScrolling(listView: ListView, velocity: CGFloat, isPrimary: Bool) -> Bool {
|
private func shouldStopScrolling(listView: ListView, velocity: CGFloat, isPrimary: Bool) -> Bool {
|
||||||
if abs(velocity) > 1.0 {
|
if abs(velocity) > 0.8 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -173,6 +173,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
|||||||
case chatWallpaperLightPreviewTip = 39
|
case chatWallpaperLightPreviewTip = 39
|
||||||
case chatWallpaperDarkPreviewTip = 40
|
case chatWallpaperDarkPreviewTip = 40
|
||||||
case displayChatListContacts = 41
|
case displayChatListContacts = 41
|
||||||
|
case displayChatListStoriesTooltip = 42
|
||||||
|
|
||||||
var key: ValueBoxKey {
|
var key: ValueBoxKey {
|
||||||
let v = ValueBoxKey(length: 4)
|
let v = ValueBoxKey(length: 4)
|
||||||
@ -394,6 +395,10 @@ private struct ApplicationSpecificNoticeKeys {
|
|||||||
static func displayChatListContacts() -> NoticeEntryKey {
|
static func displayChatListContacts() -> NoticeEntryKey {
|
||||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.displayChatListContacts.key)
|
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.displayChatListContacts.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func displayChatListStoriesTooltip() -> NoticeEntryKey {
|
||||||
|
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.displayChatListStoriesTooltip.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ApplicationSpecificNotice {
|
public struct ApplicationSpecificNotice {
|
||||||
@ -1445,6 +1450,26 @@ public struct ApplicationSpecificNotice {
|
|||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func displayChatListStoriesTooltip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Bool, NoError> {
|
||||||
|
return accountManager.noticeEntry(key: ApplicationSpecificNoticeKeys.displayChatListStoriesTooltip())
|
||||||
|
|> map { view -> Bool in
|
||||||
|
if let _ = view.value?.get(ApplicationSpecificBoolNotice.self) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func setDisplayChatListStoriesTooltip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Never, NoError> {
|
||||||
|
return accountManager.transaction { transaction -> Void in
|
||||||
|
if let entry = CodableEntry(ApplicationSpecificBoolNotice()) {
|
||||||
|
transaction.setNotice(ApplicationSpecificNoticeKeys.displayChatListStoriesTooltip(), entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
|
||||||
public static func reset(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Void, NoError> {
|
public static func reset(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Void, NoError> {
|
||||||
return accountManager.transaction { transaction -> Void in
|
return accountManager.transaction { transaction -> Void in
|
||||||
}
|
}
|
||||||
|
|||||||
@ -323,6 +323,10 @@ public final class StoryPeerListComponent: Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func anchorForTooltip() -> (UIView, CGRect)? {
|
||||||
|
return (self.collapsedButton, self.collapsedButton.bounds)
|
||||||
|
}
|
||||||
|
|
||||||
public func transitionViewForItem(peerId: EnginePeer.Id) -> (UIView, StoryContainerScreen.TransitionView)? {
|
public func transitionViewForItem(peerId: EnginePeer.Id) -> (UIView, StoryContainerScreen.TransitionView)? {
|
||||||
if self.collapsedButton.isUserInteractionEnabled {
|
if self.collapsedButton.isUserInteractionEnabled {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user