mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
[WIP] Stories
This commit is contained in:
@@ -245,8 +245,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
private var powerSavingMonitoringDisposable: Disposable?
|
||||
|
||||
public private(set) var storyListContext: StoryListContext?
|
||||
private var storyListState: StoryListContext.State?
|
||||
private var storyListStateDisposable: Disposable?
|
||||
private var storySubscriptions: EngineStorySubscriptions?
|
||||
|
||||
private var storySubscriptionsDisposable: Disposable?
|
||||
private var preloadStorySubscriptionsDisposable: Disposable?
|
||||
private var preloadStoryResourceDisposables: [MediaResourceId: Disposable] = [:]
|
||||
|
||||
private var storyListHeight: CGFloat
|
||||
|
||||
@@ -802,7 +805,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
self.joinForumDisposable.dispose()
|
||||
self.actionDisposables.dispose()
|
||||
self.powerSavingMonitoringDisposable?.dispose()
|
||||
self.storyListStateDisposable?.dispose()
|
||||
self.storySubscriptionsDisposable?.dispose()
|
||||
self.preloadStorySubscriptionsDisposable?.dispose()
|
||||
}
|
||||
|
||||
private func updateNavigationMetadata() {
|
||||
@@ -2123,30 +2127,59 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
})
|
||||
|
||||
let storyListContext = self.context.engine.messages.allStories()
|
||||
self.storyListContext = storyListContext
|
||||
self.storyListStateDisposable = (storyListContext.state
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
self.preloadStorySubscriptionsDisposable = (self.context.engine.messages.preloadStorySubscriptions()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] resources in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var validIds: [MediaResourceId] = []
|
||||
for (_, info) in resources.sorted(by: { $0.value.priority < $1.value.priority }) {
|
||||
let resource = info.resource
|
||||
validIds.append(resource.resource.id)
|
||||
if preloadStoryResourceDisposables[resource.resource.id] == nil {
|
||||
var fetchRange: (Range<Int64>, MediaBoxFetchPriority)?
|
||||
if let size = info.size {
|
||||
fetchRange = (0 ..< Int64(size), .default)
|
||||
}
|
||||
preloadStoryResourceDisposables[resource.resource.id] = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: resource, range: fetchRange).start()
|
||||
}
|
||||
}
|
||||
|
||||
var removeIds: [MediaResourceId] = []
|
||||
for (id, disposable) in self.preloadStoryResourceDisposables {
|
||||
if !validIds.contains(id) {
|
||||
removeIds.append(id)
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
for id in removeIds {
|
||||
self.preloadStoryResourceDisposables.removeValue(forKey: id)
|
||||
}
|
||||
})
|
||||
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var wasEmpty = true
|
||||
if let storyListState = self.storyListState, !storyListState.itemSets.isEmpty {
|
||||
if let storySubscriptions = self.storySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
wasEmpty = false
|
||||
}
|
||||
self.storyListState = state
|
||||
let isEmpty = state.itemSets.isEmpty
|
||||
self.storySubscriptions = storySubscriptions
|
||||
let isEmpty = storySubscriptions.items.isEmpty
|
||||
|
||||
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
|
||||
var chatListState = chatListState
|
||||
|
||||
var peersWithNewStories = Set<EnginePeer.Id>()
|
||||
for itemSet in state.itemSets {
|
||||
if itemSet.peerId == self.context.account.peerId {
|
||||
for item in storySubscriptions.items {
|
||||
if item.peer.id == self.context.account.peerId {
|
||||
continue
|
||||
}
|
||||
if itemSet.items.contains(where: { $0.id > itemSet.maxReadId }) {
|
||||
peersWithNewStories.insert(itemSet.peerId)
|
||||
if item.hasUnseen {
|
||||
peersWithNewStories.insert(item.peer.id)
|
||||
}
|
||||
}
|
||||
chatListState.peersWithNewStories = peersWithNewStories
|
||||
@@ -2156,14 +2189,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|
||||
self.storyListHeight = isEmpty ? 0.0 : 94.0
|
||||
|
||||
let tabsIsEmpty: Bool
|
||||
if let (resolvedItems, displayTabsAtBottom, _) = self.tabContainerData {
|
||||
tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom
|
||||
} else {
|
||||
tabsIsEmpty = true
|
||||
}
|
||||
|
||||
self.navigationBar?.secondaryContentHeight = (!tabsIsEmpty ? NavigationBar.defaultSecondaryContentHeight : 0.0)
|
||||
if case .chatList(.root) = self.location {
|
||||
self.searchContentNode?.additionalHeight = 94.0
|
||||
}
|
||||
@@ -2413,11 +2438,121 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
if let searchContentNode = self.searchContentNode, case .chatList(.root) = self.location {
|
||||
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
|
||||
componentView.storyPeerAction = { [weak self] peer in
|
||||
guard let self, let storyListContext = self.storyListContext else {
|
||||
guard let self, let peer else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (StoryChatContent.stories(
|
||||
let storyFocusContext = self.context.engine.messages.peerStoryFocusContext(id: peer.id, focusItemId: nil)
|
||||
|
||||
let _ = (storyFocusContext.state
|
||||
|> filter { state -> Bool in
|
||||
if state.isLoading {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] state in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = storyFocusContext
|
||||
let _ = self
|
||||
|
||||
if let item = state.item {
|
||||
let _ = item
|
||||
|
||||
let _ = (StoryChatContent.subscriptionsStories(
|
||||
context: self.context,
|
||||
peerId: peer.id
|
||||
)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] initialContent in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var transitionIn: StoryContainerScreen.TransitionIn?
|
||||
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
|
||||
if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: peer.id) {
|
||||
transitionIn = StoryContainerScreen.TransitionIn(
|
||||
sourceView: transitionView,
|
||||
sourceRect: transitionView.bounds,
|
||||
sourceCornerRadius: transitionView.bounds.height * 0.5
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var cameraTransitionIn: StoryCameraTransitionIn?
|
||||
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
|
||||
if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) {
|
||||
cameraTransitionIn = StoryCameraTransitionIn(
|
||||
sourceView: transitionView,
|
||||
sourceRect: transitionView.bounds,
|
||||
sourceCornerRadius: transitionView.bounds.height * 0.5
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var initialFocusedId: AnyHashable?
|
||||
//if let peer {
|
||||
initialFocusedId = AnyHashable(peer.id)
|
||||
//}
|
||||
|
||||
if initialFocusedId == AnyHashable(self.context.account.peerId), let firstItem = initialContent.first, firstItem.id == initialFocusedId && firstItem.items.isEmpty {
|
||||
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||
rootController.openStoryCamera(transitionIn: cameraTransitionIn, transitionOut: { [weak self] _ in
|
||||
guard let self else {
|
||||
return nil
|
||||
}
|
||||
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
|
||||
if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) {
|
||||
return StoryCameraTransitionOut(
|
||||
destinationView: transitionView,
|
||||
destinationRect: transitionView.bounds,
|
||||
destinationCornerRadius: transitionView.bounds.height * 0.5
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let storyContainerScreen = StoryContainerScreen(
|
||||
context: self.context,
|
||||
initialFocusedId: initialFocusedId,
|
||||
initialContent: initialContent,
|
||||
transitionIn: transitionIn,
|
||||
transitionOut: { [weak self] peerId, _ in
|
||||
guard let self else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
|
||||
if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) {
|
||||
return StoryContainerScreen.TransitionOut(
|
||||
destinationView: transitionView,
|
||||
destinationRect: transitionView.bounds,
|
||||
destinationCornerRadius: transitionView.bounds.height * 0.5,
|
||||
destinationIsAvatar: true,
|
||||
completed: {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
)
|
||||
self.push(storyContainerScreen)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
/*let _ = (StoryChatContent.stories(
|
||||
context: self.context,
|
||||
storyList: storyListContext,
|
||||
focusItem: nil
|
||||
@@ -2503,7 +2638,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
)
|
||||
self.push(storyContainerScreen)
|
||||
})
|
||||
})*/
|
||||
}
|
||||
|
||||
let fraction = 94.0 / (navigationBarSearchContentHeight + 94.0)
|
||||
@@ -2512,7 +2647,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
visibleProgress = (1.0 / fraction) * visibleProgress
|
||||
visibleProgress = max(0.0, min(1.0, visibleProgress))
|
||||
|
||||
componentView.updateStories(offset: visibleProgress, context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, storyListState: self.storyListState, transition: Transition(transition))
|
||||
componentView.updateStories(offset: visibleProgress, context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, storySubscriptions: self.storySubscriptions, transition: Transition(transition))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user