Cleanup page view controller's access to multiple contexts
This commit is contained in:
parent
d12af96dde
commit
02cd514370
@ -22,10 +22,8 @@ class StoryPageViewController: UIPageViewController {
|
||||
}
|
||||
let onlyRenderMyStories: Bool
|
||||
|
||||
weak var contextDataSource: StoryPageViewControllerDataSource? {
|
||||
didSet { initiallyAvailableContexts = contextDataSource?.storyPageViewControllerAvailableContexts(self) ?? [currentContext] }
|
||||
}
|
||||
lazy var initiallyAvailableContexts: [StoryContext] = [currentContext]
|
||||
weak var contextDataSource: StoryPageViewControllerDataSource?
|
||||
let viewableContexts: [StoryContext]
|
||||
private var interactiveDismissCoordinator: StoryInteractiveTransitionCoordinator?
|
||||
|
||||
private let audioActivity = AudioActivity(audioDescription: "StoriesViewer", behavior: .playbackMixWithOthers)
|
||||
@ -40,8 +38,9 @@ class StoryPageViewController: UIPageViewController {
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
required init(context: StoryContext, loadMessage: StoryMessage? = nil, onlyRenderMyStories: Bool = false) {
|
||||
required init(context: StoryContext, viewableContexts: [StoryContext]? = nil, loadMessage: StoryMessage? = nil, onlyRenderMyStories: Bool = false) {
|
||||
self.onlyRenderMyStories = onlyRenderMyStories
|
||||
self.viewableContexts = viewableContexts ?? [context]
|
||||
super.init(transitionStyle: .scroll, navigationOrientation: .vertical, options: nil)
|
||||
self.currentContext = context
|
||||
currentContextViewController.loadMessage = loadMessage
|
||||
@ -283,22 +282,22 @@ extension StoryPageViewController: UIPageViewControllerDataSource {
|
||||
|
||||
extension StoryPageViewController: StoryContextViewControllerDelegate {
|
||||
var availableContexts: [StoryContext] {
|
||||
guard let contextDataSource = contextDataSource else { return initiallyAvailableContexts }
|
||||
guard let contextDataSource = contextDataSource else { return viewableContexts }
|
||||
let availableContexts = contextDataSource.storyPageViewControllerAvailableContexts(self)
|
||||
return initiallyAvailableContexts.filter { availableContexts.contains($0) }
|
||||
return viewableContexts.filter { availableContexts.contains($0) }
|
||||
}
|
||||
|
||||
var previousStoryContext: StoryContext? {
|
||||
guard let contextIndex = availableContexts.firstIndex(of: currentContext),
|
||||
let contextBefore = availableContexts[safe: contextIndex.advanced(by: -1)] else {
|
||||
guard let contextIndex = viewableContexts.firstIndex(of: currentContext),
|
||||
let contextBefore = viewableContexts[safe: contextIndex.advanced(by: -1)] else {
|
||||
return nil
|
||||
}
|
||||
return contextBefore
|
||||
}
|
||||
|
||||
var nextStoryContext: StoryContext? {
|
||||
guard let contextIndex = availableContexts.firstIndex(of: currentContext),
|
||||
let contextAfter = availableContexts[safe: contextIndex.advanced(by: 1)] else {
|
||||
guard let contextIndex = viewableContexts.firstIndex(of: currentContext),
|
||||
let contextAfter = viewableContexts[safe: contextIndex.advanced(by: 1)] else {
|
||||
return nil
|
||||
}
|
||||
return contextAfter
|
||||
@ -335,8 +334,8 @@ extension StoryPageViewController: StoryContextViewControllerDelegate {
|
||||
}
|
||||
|
||||
func storyContextViewController(_ storyContextViewController: StoryContextViewController, contextAfter context: StoryContext) -> StoryContext? {
|
||||
guard let contextIndex = availableContexts.firstIndex(of: context),
|
||||
let contextAfter = availableContexts[safe: contextIndex.advanced(by: 1)] else {
|
||||
guard let contextIndex = viewableContexts.firstIndex(of: context),
|
||||
let contextAfter = viewableContexts[safe: contextIndex.advanced(by: 1)] else {
|
||||
return nil
|
||||
}
|
||||
return contextAfter
|
||||
|
||||
@ -125,7 +125,12 @@ extension MyStoriesViewController: UITableViewDelegate {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
|
||||
guard let thread = thread(for: indexPath.section), let item = item(for: indexPath) else { return }
|
||||
let vc = StoryPageViewController(context: thread.storyContext, loadMessage: item.message, onlyRenderMyStories: true)
|
||||
let vc = StoryPageViewController(
|
||||
context: thread.storyContext,
|
||||
viewableContexts: items.orderedKeys.map { $0.storyContext },
|
||||
loadMessage: item.message,
|
||||
onlyRenderMyStories: true
|
||||
)
|
||||
vc.contextDataSource = self
|
||||
present(vc, animated: true)
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@ class StoriesViewController: OWSViewController {
|
||||
let tableView = UITableView()
|
||||
private let syncingModels = SyncingStoryViewModelArray()
|
||||
private var myStoryModel = AtomicOptional<MyStoryViewModel>(nil)
|
||||
private var viewerContexts: [StoryContext]?
|
||||
|
||||
private lazy var emptyStateLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
@ -403,13 +402,14 @@ extension StoriesViewController: UITableViewDelegate {
|
||||
|
||||
// If we tap on a story with unviewed stories, we only want the viewer
|
||||
// to page through unviewed contexts.
|
||||
let viewableContexts: [StoryContext]
|
||||
if model.hasUnviewedMessages {
|
||||
viewerContexts = syncingModels.get().lazy.filter { $0.hasUnviewedMessages }.map { $0.context }
|
||||
viewableContexts = syncingModels.get().lazy.filter { $0.hasUnviewedMessages }.map { $0.context }
|
||||
} else {
|
||||
viewerContexts = syncingModels.get().map { $0.context }
|
||||
viewableContexts = syncingModels.allContexts
|
||||
}
|
||||
|
||||
let vc = StoryPageViewController(context: model.context)
|
||||
let vc = StoryPageViewController(context: model.context, viewableContexts: viewableContexts)
|
||||
vc.contextDataSource = self
|
||||
presentFullScreen(vc, animated: true)
|
||||
case .hiddenStories:
|
||||
@ -494,7 +494,7 @@ extension StoriesViewController: UITableViewDataSource {
|
||||
|
||||
extension StoriesViewController: StoryPageViewControllerDataSource {
|
||||
func storyPageViewControllerAvailableContexts(_ storyPageViewController: StoryPageViewController) -> [StoryContext] {
|
||||
viewerContexts ?? []
|
||||
syncingModels.allContexts
|
||||
}
|
||||
}
|
||||
|
||||
@ -688,6 +688,8 @@ private class SyncingStoryViewModelArray {
|
||||
// This may lag behind `trueModels` and is eventually consistent. It is exposed to UITableView.
|
||||
@ThreadBoundValue(wrappedValue: [], queue: .main) private var exposedModels: [StoryViewModel]
|
||||
|
||||
private var contexts = AtomicArray<StoryContext>()
|
||||
|
||||
/// Safely modify the list of models. This method must be called on the loading queue.
|
||||
///
|
||||
/// - Parameters
|
||||
@ -708,6 +710,7 @@ private class SyncingStoryViewModelArray {
|
||||
}
|
||||
trueModels = newModels
|
||||
DispatchQueue.main.async {
|
||||
self.contexts.set(newModels.map { $0.context })
|
||||
self.exposedModels = newModels
|
||||
sync(newModels, userInfo)
|
||||
}
|
||||
@ -717,4 +720,9 @@ private class SyncingStoryViewModelArray {
|
||||
func get() -> [StoryViewModel] {
|
||||
return exposedModels
|
||||
}
|
||||
|
||||
/// Thread safe list of all contexts currently exposed
|
||||
var allContexts: [StoryContext] {
|
||||
contexts.get()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user