mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Use @Observable instead of ObservableObject for our NavigationCoordinators.
This commit is contained in:
@@ -10,27 +10,19 @@ import SwiftUI
|
|||||||
|
|
||||||
/// Class responsible for displaying 2 coordinators side by side and collapsing them
|
/// Class responsible for displaying 2 coordinators side by side and collapsing them
|
||||||
/// into a single navigation stack on compact layouts
|
/// into a single navigation stack on compact layouts
|
||||||
class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomStringConvertible {
|
@Observable class NavigationSplitCoordinator: CoordinatorProtocol, CustomStringConvertible {
|
||||||
fileprivate let placeholderModule: NavigationModule
|
fileprivate let placeholderModule: NavigationModule
|
||||||
|
|
||||||
var sidebarStackModuleCancellable: AnyCancellable?
|
|
||||||
|
|
||||||
@Published fileprivate var sidebarModule: NavigationModule? {
|
fileprivate var sidebarModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove sidebar", oldValue)
|
logPresentationChange("Remove sidebar", oldValue)
|
||||||
oldValue.tearDown()
|
oldValue.tearDown()
|
||||||
sidebarStackModuleCancellable = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let sidebarModule {
|
if let sidebarModule {
|
||||||
logPresentationChange("Set sidebar", sidebarModule)
|
logPresentationChange("Set sidebar", sidebarModule)
|
||||||
sidebarModule.coordinator?.start()
|
sidebarModule.coordinator?.start()
|
||||||
if let observableCoordinator = sidebarModule.coordinator as? NavigationStackCoordinator {
|
|
||||||
sidebarStackModuleCancellable = Publishers.CombineLatest(observableCoordinator.$rootModule, observableCoordinator.$stackModules).sink { [weak self] _ in
|
|
||||||
self?.objectWillChange.send()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,25 +31,17 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
var sidebarCoordinator: (any CoordinatorProtocol)? {
|
var sidebarCoordinator: (any CoordinatorProtocol)? {
|
||||||
sidebarModule?.coordinator
|
sidebarModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
var detailCoordinatorCancellable: AnyCancellable?
|
|
||||||
|
|
||||||
@Published fileprivate var detailModule: NavigationModule? {
|
fileprivate var detailModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove detail", oldValue)
|
logPresentationChange("Remove detail", oldValue)
|
||||||
oldValue.tearDown()
|
oldValue.tearDown()
|
||||||
detailCoordinatorCancellable = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let detailModule {
|
if let detailModule {
|
||||||
logPresentationChange("Set detail", detailModule)
|
logPresentationChange("Set detail", detailModule)
|
||||||
detailModule.coordinator?.start()
|
detailModule.coordinator?.start()
|
||||||
if let observableCoordinator = detailModule.coordinator as? NavigationStackCoordinator {
|
|
||||||
detailCoordinatorCancellable = Publishers.CombineLatest(observableCoordinator.$rootModule, observableCoordinator.$stackModules).sink { [weak self] _ in
|
|
||||||
self?.objectWillChange.send()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +51,7 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
detailModule?.coordinator
|
detailModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var sheetModule: NavigationModule? {
|
fileprivate var sheetModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove sheet", oldValue)
|
logPresentationChange("Remove sheet", oldValue)
|
||||||
@@ -86,7 +70,7 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
sheetModule?.coordinator
|
sheetModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var fullScreenCoverModule: NavigationModule? {
|
fileprivate var fullScreenCoverModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove fullscreen cover", oldValue)
|
logPresentationChange("Remove fullscreen cover", oldValue)
|
||||||
@@ -106,7 +90,7 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
fullScreenCoverModule?.coordinator
|
fullScreenCoverModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var overlayModule: NavigationModule? {
|
fileprivate var overlayModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove overlay", oldValue)
|
logPresentationChange("Remove overlay", oldValue)
|
||||||
@@ -126,7 +110,7 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum OverlayPresentationMode { case fullScreen, minimized }
|
enum OverlayPresentationMode { case fullScreen, minimized }
|
||||||
@Published fileprivate var overlayPresentationMode: OverlayPresentationMode = .minimized
|
fileprivate var overlayPresentationMode: OverlayPresentationMode = .minimized
|
||||||
|
|
||||||
fileprivate var compactLayoutRootModule: NavigationModule? {
|
fileprivate var compactLayoutRootModule: NavigationModule? {
|
||||||
if let sidebarNavigationStackCoordinator = sidebarModule?.coordinator as? NavigationStackCoordinator {
|
if let sidebarNavigationStackCoordinator = sidebarModule?.coordinator as? NavigationStackCoordinator {
|
||||||
@@ -145,19 +129,13 @@ class NavigationSplitCoordinator: CoordinatorProtocol, ObservableObject, CustomS
|
|||||||
|
|
||||||
var compactLayoutStackModules: [NavigationModule] {
|
var compactLayoutStackModules: [NavigationModule] {
|
||||||
get {
|
get {
|
||||||
compactLayoutStackModulesBinding.wrappedValue
|
getCompactStackModules()
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
compactLayoutStackModulesBinding.wrappedValue = newValue
|
setCompactStackModules(newValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate lazy var compactLayoutStackModulesBinding: Binding<[NavigationModule]> = Binding(get: { [weak self] in
|
|
||||||
self?.getCompactStackModules() ?? []
|
|
||||||
}, set: { [weak self] newValue in
|
|
||||||
self?.setCompactStackModules(newValue)
|
|
||||||
})
|
|
||||||
|
|
||||||
private func getCompactStackModules() -> [NavigationModule] {
|
private func getCompactStackModules() -> [NavigationModule] {
|
||||||
// Start building the new compact layout navigation stack
|
// Start building the new compact layout navigation stack
|
||||||
var stackModules: [NavigationModule] = []
|
var stackModules: [NavigationModule] = []
|
||||||
@@ -415,7 +393,7 @@ private struct NavigationSplitCoordinatorView: View {
|
|||||||
|
|
||||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
|
|
||||||
@ObservedObject var navigationSplitCoordinator: NavigationSplitCoordinator
|
@Bindable var navigationSplitCoordinator: NavigationSplitCoordinator
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
@@ -454,7 +432,7 @@ private struct NavigationSplitCoordinatorView: View {
|
|||||||
|
|
||||||
/// The NavigationStack that will be used in compact layouts
|
/// The NavigationStack that will be used in compact layouts
|
||||||
var navigationStack: some View {
|
var navigationStack: some View {
|
||||||
NavigationStack(path: navigationSplitCoordinator.compactLayoutStackModulesBinding) {
|
NavigationStack(path: $navigationSplitCoordinator.compactLayoutStackModules) {
|
||||||
navigationSplitCoordinator.compactLayoutRootModule?.coordinator?.toPresentable()
|
navigationSplitCoordinator.compactLayoutRootModule?.coordinator?.toPresentable()
|
||||||
.id(navigationSplitCoordinator.compactLayoutRootModule?.id) // Is a nil ID ok?
|
.id(navigationSplitCoordinator.compactLayoutRootModule?.id) // Is a nil ID ok?
|
||||||
.navigationDestination(for: NavigationModule.self) { module in
|
.navigationDestination(for: NavigationModule.self) { module in
|
||||||
@@ -496,10 +474,10 @@ private struct NavigationSplitCoordinatorView: View {
|
|||||||
// MARK: - NavigationStackCoordinator
|
// MARK: - NavigationStackCoordinator
|
||||||
|
|
||||||
/// Class responsible for displaying a normal "NavigationController" style hierarchy
|
/// Class responsible for displaying a normal "NavigationController" style hierarchy
|
||||||
class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomStringConvertible {
|
@Observable class NavigationStackCoordinator: CoordinatorProtocol, CustomStringConvertible {
|
||||||
private(set) weak var navigationSplitCoordinator: NavigationSplitCoordinator?
|
private(set) weak var navigationSplitCoordinator: NavigationSplitCoordinator?
|
||||||
|
|
||||||
@Published fileprivate var rootModule: NavigationModule? {
|
fileprivate var rootModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove root", oldValue)
|
logPresentationChange("Remove root", oldValue)
|
||||||
@@ -518,7 +496,7 @@ class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomS
|
|||||||
rootModule?.coordinator
|
rootModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var sheetModule: NavigationModule? {
|
fileprivate var sheetModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove sheet", oldValue)
|
logPresentationChange("Remove sheet", oldValue)
|
||||||
@@ -544,7 +522,7 @@ class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomS
|
|||||||
return sheetModule?.coordinator
|
return sheetModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var fullScreenCoverModule: NavigationModule? {
|
fileprivate var fullScreenCoverModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove fullscreen cover", oldValue)
|
logPresentationChange("Remove fullscreen cover", oldValue)
|
||||||
@@ -569,7 +547,7 @@ class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomS
|
|||||||
return fullScreenCoverModule?.coordinator
|
return fullScreenCoverModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var stackModules = [NavigationModule]() {
|
fileprivate var stackModules = [NavigationModule]() {
|
||||||
didSet {
|
didSet {
|
||||||
let diffs = stackModules.difference(from: oldValue)
|
let diffs = stackModules.difference(from: oldValue)
|
||||||
diffs.forEach { change in
|
diffs.forEach { change in
|
||||||
@@ -763,7 +741,7 @@ class NavigationStackCoordinator: ObservableObject, CoordinatorProtocol, CustomS
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct NavigationStackCoordinatorView: View {
|
private struct NavigationStackCoordinatorView: View {
|
||||||
@ObservedObject var navigationStackCoordinator: NavigationStackCoordinator
|
@Bindable var navigationStackCoordinator: NavigationStackCoordinator
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack(path: $navigationStackCoordinator.stackModules) {
|
NavigationStack(path: $navigationStackCoordinator.stackModules) {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomStringConvertible {
|
@Observable class NavigationRootCoordinator: CoordinatorProtocol, CustomStringConvertible {
|
||||||
@Published fileprivate var rootModule: NavigationModule? {
|
fileprivate var rootModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
oldValue.tearDown()
|
oldValue.tearDown()
|
||||||
@@ -26,7 +26,7 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt
|
|||||||
rootModule?.coordinator
|
rootModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var sheetModule: NavigationModule? {
|
fileprivate var sheetModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove sheet", oldValue)
|
logPresentationChange("Remove sheet", oldValue)
|
||||||
@@ -47,7 +47,7 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt
|
|||||||
sheetModule?.coordinator
|
sheetModule?.coordinator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published fileprivate var overlayModule: NavigationModule? {
|
fileprivate var overlayModule: NavigationModule? {
|
||||||
didSet {
|
didSet {
|
||||||
if let oldValue {
|
if let oldValue {
|
||||||
logPresentationChange("Remove overlay", oldValue)
|
logPresentationChange("Remove overlay", oldValue)
|
||||||
@@ -152,7 +152,7 @@ class NavigationRootCoordinator: ObservableObject, CoordinatorProtocol, CustomSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct NavigationRootCoordinatorView: View {
|
private struct NavigationRootCoordinatorView: View {
|
||||||
@ObservedObject var rootCoordinator: NavigationRootCoordinator
|
@Bindable var rootCoordinator: NavigationRootCoordinator
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
|
|||||||
Reference in New Issue
Block a user