mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Stories
This commit is contained in:
parent
4e06ed8bdd
commit
fbea3fccc0
@ -118,6 +118,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|
|
||||||
private var didAppear = false
|
private var didAppear = false
|
||||||
private var dismissSearchOnDisappear = false
|
private var dismissSearchOnDisappear = false
|
||||||
|
public var onDidAppear: (() -> Void)?
|
||||||
|
|
||||||
private var passcodeLockTooltipDisposable = MetaDisposable()
|
private var passcodeLockTooltipDisposable = MetaDisposable()
|
||||||
private var didShowPasscodeLockTooltipController = false
|
private var didShowPasscodeLockTooltipController = false
|
||||||
@ -187,6 +188,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
private(set) var orderedStorySubscriptions: EngineStorySubscriptions?
|
private(set) var orderedStorySubscriptions: EngineStorySubscriptions?
|
||||||
private var displayedStoriesTooltip: Bool = false
|
private var displayedStoriesTooltip: Bool = false
|
||||||
|
|
||||||
|
public var hasStorySubscriptions: Bool {
|
||||||
|
if let rawStorySubscriptions = self.rawStorySubscriptions, !rawStorySubscriptions.items.isEmpty {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var storyProgressDisposable: Disposable?
|
private var storyProgressDisposable: Disposable?
|
||||||
private var storySubscriptionsDisposable: Disposable?
|
private var storySubscriptionsDisposable: Disposable?
|
||||||
private var preloadStorySubscriptionsDisposable: Disposable?
|
private var preloadStorySubscriptionsDisposable: Disposable?
|
||||||
@ -1059,7 +1068,21 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .chatList(groupId: groupId), controlsHistoryPreload: false, enableDebugActions: false)
|
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .chatList(groupId: groupId), controlsHistoryPreload: false, enableDebugActions: false)
|
||||||
chatListController.navigationPresentation = .master
|
chatListController.navigationPresentation = .master
|
||||||
|
#if DEBUG && false
|
||||||
|
navigationController.pushViewController(chatListController, animated: false, completion: {})
|
||||||
|
chatListController.onDidAppear = { [weak chatListController] in
|
||||||
|
Queue.mainQueue().after(0.1, {
|
||||||
|
guard let chatListController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if chatListController.hasStorySubscriptions {
|
||||||
|
chatListController.scrollToStoriesAnimated()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#else
|
||||||
navigationController.pushViewController(chatListController)
|
navigationController.pushViewController(chatListController)
|
||||||
|
#endif
|
||||||
strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.clearHighlightAnimated(true)
|
strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.clearHighlightAnimated(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1813,12 +1836,18 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|> filter { $0 }
|
|> filter { $0 }
|
||||||
|> take(1))
|
|> take(1))
|
||||||
} else {
|
} else {
|
||||||
self.storiesReady.set(.single(true))
|
let signals: [Signal<Bool, NoError>] = [
|
||||||
|
self.primaryInfoReady.get(),
|
||||||
|
self.storiesReady.get()
|
||||||
|
]
|
||||||
|
|
||||||
self.ready.set(combineLatest([
|
if case .chatList(.archive) = self.location {
|
||||||
self.chatListDisplayNode.mainContainerNode.ready,
|
//signals.append(self.mainReady.get())
|
||||||
self.primaryInfoReady.get()
|
} else {
|
||||||
])
|
self.storiesReady.set(.single(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ready.set(combineLatest(signals)
|
||||||
|> map { values -> Bool in
|
|> map { values -> Bool in
|
||||||
return !values.contains(where: { !$0 })
|
return !values.contains(where: { !$0 })
|
||||||
}
|
}
|
||||||
@ -1919,7 +1948,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.requestLayout(transition: transition)
|
self.requestLayout(transition: transition)
|
||||||
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
|
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
|
||||||
|
|
||||||
if rawStorySubscriptions.items.isEmpty {
|
if !shouldDisplayStoriesInChatListHeader(storySubscriptions: rawStorySubscriptions, isHidden: self.location == .chatList(groupId: .archive)) {
|
||||||
self.chatListDisplayNode.scrollToTopIfStoriesAreExpanded()
|
self.chatListDisplayNode.scrollToTopIfStoriesAreExpanded()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2162,6 +2191,20 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard case .chatList(.root) = self.location else {
|
guard case .chatList(.root) = self.location else {
|
||||||
|
if !self.didSuggestLocalization {
|
||||||
|
self.didSuggestLocalization = true
|
||||||
|
|
||||||
|
let _ = (self.chatListDisplayNode.mainContainerNode.ready
|
||||||
|
|> filter { $0 }
|
||||||
|
|> take(1)
|
||||||
|
|> timeout(0.5, queue: .mainQueue(), alternate: .single(true))).start(next: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.onDidAppear?()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2362,6 +2405,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.onDidAppear?()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.chatListDisplayNode.mainContainerNode.addedVisibleChatsWithPeerIds = { [weak self] peerIds in
|
self.chatListDisplayNode.mainContainerNode.addedVisibleChatsWithPeerIds = { [weak self] peerIds in
|
||||||
@ -2916,6 +2961,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.chatListDisplayNode.scrollToStories(animated: false)
|
self.chatListDisplayNode.scrollToStories(animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func scrollToStoriesAnimated() {
|
||||||
|
self.chatListDisplayNode.scrollToStories(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
private func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
private func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||||
var tabContainerOffset: CGFloat = 0.0
|
var tabContainerOffset: CGFloat = 0.0
|
||||||
if !self.displayNavigationBar {
|
if !self.displayNavigationBar {
|
||||||
|
@ -13,6 +13,7 @@ import ContextUI
|
|||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
import StoryContainerScreen
|
import StoryContainerScreen
|
||||||
import MultilineTextComponent
|
import MultilineTextComponent
|
||||||
|
import HierarchyTrackingLayer
|
||||||
|
|
||||||
private func calculateCircleIntersection(center: CGPoint, otherCenter: CGPoint, radius: CGFloat) -> (point1Angle: CGFloat, point2Angle: CGFloat)? {
|
private func calculateCircleIntersection(center: CGPoint, otherCenter: CGPoint, radius: CGFloat) -> (point1Angle: CGFloat, point2Angle: CGFloat)? {
|
||||||
let distanceVector = CGPoint(x: otherCenter.x - center.x, y: otherCenter.y - center.y)
|
let distanceVector = CGPoint(x: otherCenter.x - center.x, y: otherCenter.y - center.y)
|
||||||
@ -124,7 +125,7 @@ private func calculateMergingCircleShape(center: CGPoint, leftCenter: CGPoint?,
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class StoryProgressLayer: SimpleLayer {
|
private final class StoryProgressLayer: HierarchyTrackingLayer {
|
||||||
enum Value: Equatable {
|
enum Value: Equatable {
|
||||||
case indefinite
|
case indefinite
|
||||||
case progress(Float)
|
case progress(Float)
|
||||||
@ -164,6 +165,13 @@ private final class StoryProgressLayer: SimpleLayer {
|
|||||||
self.indefiniteReplicatorLayer.instanceTransform = CATransform3DMakeRotation(CGFloat(angle), 0.0, 0.0, 1.0)
|
self.indefiniteReplicatorLayer.instanceTransform = CATransform3DMakeRotation(CGFloat(angle), 0.0, 0.0, 1.0)
|
||||||
self.indefiniteReplicatorLayer.transform = CATransform3DMakeRotation(-.pi / 2.0, 0.0, 0.0, 1.0)
|
self.indefiniteReplicatorLayer.transform = CATransform3DMakeRotation(-.pi / 2.0, 0.0, 0.0, 1.0)
|
||||||
self.indefiniteReplicatorLayer.instanceDelay = 0.025
|
self.indefiniteReplicatorLayer.instanceDelay = 0.025
|
||||||
|
|
||||||
|
self.didEnterHierarchy = { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.updateAnimations(transition: .immediate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override init(layer: Any) {
|
override init(layer: Any) {
|
||||||
@ -180,35 +188,12 @@ private final class StoryProgressLayer: SimpleLayer {
|
|||||||
self.uploadProgressLayer.path = nil
|
self.uploadProgressLayer.path = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(size: CGSize, lineWidth: CGFloat, value: Value, transition: Transition) {
|
func updateAnimations(transition: Transition) {
|
||||||
let params = Params(
|
guard let params = self.currentParams else {
|
||||||
size: size,
|
|
||||||
lineWidth: lineWidth,
|
|
||||||
value: value
|
|
||||||
)
|
|
||||||
if self.currentParams == params {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.currentParams = params
|
|
||||||
|
|
||||||
let lineWidth: CGFloat = 2.0
|
switch params.value {
|
||||||
let bounds = CGRect(origin: .zero, size: size)
|
|
||||||
if self.uploadProgressLayer.path == nil {
|
|
||||||
let path = CGMutablePath()
|
|
||||||
path.addEllipse(in: CGRect(origin: CGPoint(x: lineWidth * 0.5, y: lineWidth * 0.5), size: CGSize(width: size.width - lineWidth, height: size.height - lineWidth)))
|
|
||||||
self.uploadProgressLayer.path = path
|
|
||||||
self.uploadProgressLayer.frame = bounds
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.indefiniteDashLayer.path == nil {
|
|
||||||
let path = CGMutablePath()
|
|
||||||
path.addEllipse(in: CGRect(origin: CGPoint(x: lineWidth * 0.5, y: lineWidth * 0.5), size: CGSize(width: size.width - lineWidth, height: size.height - lineWidth)))
|
|
||||||
self.indefiniteDashLayer.path = path
|
|
||||||
self.indefiniteReplicatorLayer.frame = bounds
|
|
||||||
self.indefiniteDashLayer.frame = bounds
|
|
||||||
}
|
|
||||||
|
|
||||||
switch value {
|
|
||||||
case let .progress(progress):
|
case let .progress(progress):
|
||||||
if self.indefiniteReplicatorLayer.superlayer != nil {
|
if self.indefiniteReplicatorLayer.superlayer != nil {
|
||||||
self.indefiniteReplicatorLayer.removeFromSuperlayer()
|
self.indefiniteReplicatorLayer.removeFromSuperlayer()
|
||||||
@ -258,6 +243,37 @@ private final class StoryProgressLayer: SimpleLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func update(size: CGSize, lineWidth: CGFloat, value: Value, transition: Transition) {
|
||||||
|
let params = Params(
|
||||||
|
size: size,
|
||||||
|
lineWidth: lineWidth,
|
||||||
|
value: value
|
||||||
|
)
|
||||||
|
if self.currentParams == params {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.currentParams = params
|
||||||
|
|
||||||
|
let lineWidth: CGFloat = 2.0
|
||||||
|
let bounds = CGRect(origin: .zero, size: size)
|
||||||
|
if self.uploadProgressLayer.path == nil {
|
||||||
|
let path = CGMutablePath()
|
||||||
|
path.addEllipse(in: CGRect(origin: CGPoint(x: lineWidth * 0.5, y: lineWidth * 0.5), size: CGSize(width: size.width - lineWidth, height: size.height - lineWidth)))
|
||||||
|
self.uploadProgressLayer.path = path
|
||||||
|
self.uploadProgressLayer.frame = bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.indefiniteDashLayer.path == nil {
|
||||||
|
let path = CGMutablePath()
|
||||||
|
path.addEllipse(in: CGRect(origin: CGPoint(x: lineWidth * 0.5, y: lineWidth * 0.5), size: CGSize(width: size.width - lineWidth, height: size.height - lineWidth)))
|
||||||
|
self.indefiniteDashLayer.path = path
|
||||||
|
self.indefiniteReplicatorLayer.frame = bounds
|
||||||
|
self.indefiniteDashLayer.frame = bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updateAnimations(transition: transition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var sharedAvatarBackgroundImage: UIImage?
|
private var sharedAvatarBackgroundImage: UIImage?
|
||||||
|
@ -26,6 +26,7 @@ import AccountUtils
|
|||||||
import ContextUI
|
import ContextUI
|
||||||
import TelegramCallsUI
|
import TelegramCallsUI
|
||||||
import AuthorizationUI
|
import AuthorizationUI
|
||||||
|
import ChatListUI
|
||||||
|
|
||||||
final class UnauthorizedApplicationContext {
|
final class UnauthorizedApplicationContext {
|
||||||
let sharedContext: SharedAccountContextImpl
|
let sharedContext: SharedAccountContextImpl
|
||||||
@ -852,8 +853,56 @@ final class AuthorizedApplicationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func openChatWithPeerId(peerId: PeerId, threadId: Int64?, messageId: MessageId? = nil, activateInput: Bool = false, storyId: StoryId?) {
|
func openChatWithPeerId(peerId: PeerId, threadId: Int64?, messageId: MessageId? = nil, activateInput: Bool = false, storyId: StoryId?) {
|
||||||
if let _ = storyId {
|
if let storyId {
|
||||||
self.rootController.chatListController?.openStories(peerId: peerId)
|
if let chatListController = self.rootController.chatListController as? ChatListControllerImpl {
|
||||||
|
let _ = (chatListController.context.account.postbox.transaction { transaction -> Bool in
|
||||||
|
if let peer = transaction.getPeer(storyId.peerId) as? TelegramUser, let storiesHidden = peer.storiesHidden, storiesHidden {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] isArchived in
|
||||||
|
guard let self, let chatListController = self.rootController.chatListController as? ChatListControllerImpl else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if isArchived {
|
||||||
|
if let navigationController = (chatListController.navigationController as? NavigationController) {
|
||||||
|
var viewControllers = navigationController.viewControllers
|
||||||
|
if let index = viewControllers.firstIndex(where: { c in
|
||||||
|
if let c = c as? ChatListControllerImpl {
|
||||||
|
if case .chatList(groupId: .archive) = c.location {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) {
|
||||||
|
(viewControllers[index] as? ChatListControllerImpl)?.scrollToStories()
|
||||||
|
viewControllers.removeSubrange((index + 1) ..< viewControllers.count)
|
||||||
|
navigationController.setViewControllers(viewControllers, animated: false)
|
||||||
|
} else {
|
||||||
|
let archive = ChatListControllerImpl(context: chatListController.context, location: .chatList(groupId: .archive), controlsHistoryPreload: false, hideNetworkActivityStatus: false, previewing: false, enableDebugActions: false)
|
||||||
|
archive.onDidAppear = { [weak archive] in
|
||||||
|
Queue.mainQueue().after(0.1, {
|
||||||
|
guard let archive else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if archive.hasStorySubscriptions {
|
||||||
|
archive.scrollToStoriesAnimated()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
navigationController.pushViewController(archive, animated: false, completion: {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chatListController.scrollToStories()
|
||||||
|
if let navigationController = (chatListController.navigationController as? NavigationController) {
|
||||||
|
navigationController.popToRoot(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var visiblePeerId: PeerId?
|
var visiblePeerId: PeerId?
|
||||||
if let controller = self.rootController.topViewController as? ChatControllerImpl, controller.chatLocation.peerId == peerId, controller.chatLocation.threadId == threadId {
|
if let controller = self.rootController.topViewController as? ChatControllerImpl, controller.chatLocation.peerId == peerId, controller.chatLocation.threadId == threadId {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user