Cleanup page view controller's access to multiple contexts

This commit is contained in:
Nora Trapp 2022-08-11 13:06:46 -07:00 committed by Nora Trapp
parent d12af96dde
commit 02cd514370
3 changed files with 31 additions and 19 deletions

View File

@ -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

View File

@ -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)
}

View File

@ -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()
}
}