mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Memory management (#503)
* Correctly tear down the user session on signing out * Fix session verification <-> user session retain cycle, visible range debouncer leak * Manually clean up coordinators retained within SwiftUI's NavigationStacks * Slightly refactor the timeline content menu builder and prevent it from retaining the view model. Cleanup now unnecessarily optional RoomScreenCoordinator instance vars * Move coordinator dismissal logic to the navigation modules
This commit is contained in:
@@ -17,11 +17,17 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TimelineItemContextMenuActions {
|
||||
static var empty: TimelineItemContextMenuActions { .init(actions: [], debugActions: []) }
|
||||
|
||||
let actions: [TimelineItemContextMenuAction]
|
||||
let debugActions: [TimelineItemContextMenuAction]
|
||||
var isEmpty: Bool { actions.isEmpty && debugActions.isEmpty }
|
||||
|
||||
init?(actions: [TimelineItemContextMenuAction], debugActions: [TimelineItemContextMenuAction]) {
|
||||
if actions.isEmpty, debugActions.isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.actions = actions
|
||||
self.debugActions = debugActions
|
||||
}
|
||||
}
|
||||
|
||||
enum TimelineItemContextMenuAction: Identifiable, Hashable {
|
||||
@@ -52,16 +58,11 @@ public struct TimelineItemContextMenu: View {
|
||||
let callback: (TimelineItemContextMenuAction) -> Void
|
||||
|
||||
public var body: some View {
|
||||
if contextMenuActions.isEmpty {
|
||||
// When there are no actions make sure then menu isn't shown.
|
||||
EmptyView()
|
||||
} else {
|
||||
viewsForActions(contextMenuActions.actions)
|
||||
Menu {
|
||||
viewsForActions(contextMenuActions.debugActions)
|
||||
} label: {
|
||||
Label("Developer", systemImage: "hammer")
|
||||
}
|
||||
viewsForActions(contextMenuActions.actions)
|
||||
Menu {
|
||||
viewsForActions(contextMenuActions.debugActions)
|
||||
} label: {
|
||||
Label("Developer", systemImage: "hammer")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class TimelineTableViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
var contextMenuBuilder: (@MainActor (_ itemId: String) -> TimelineItemContextMenu)?
|
||||
var contextMenuActionProvider: (@MainActor (_ itemId: String) -> TimelineItemContextMenuActions?)?
|
||||
|
||||
@Binding private var scrollToBottomButtonVisible: Bool
|
||||
|
||||
@@ -189,7 +189,7 @@ class TimelineTableViewController: UIViewController {
|
||||
// A local reference to avoid capturing self in the cell configuration.
|
||||
let coordinator = self.coordinator
|
||||
let opacity = self.opacity(for: timelineItem)
|
||||
let contextMenuBuilder = self.contextMenuBuilder
|
||||
let contextMenuActionProvider = self.contextMenuActionProvider
|
||||
|
||||
cell.item = timelineItem
|
||||
cell.contentConfiguration = UIHostingConfiguration {
|
||||
@@ -198,7 +198,11 @@ class TimelineTableViewController: UIViewController {
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.opacity(opacity)
|
||||
.contextMenu {
|
||||
contextMenuBuilder?(timelineItem.id)
|
||||
contextMenuActionProvider?(timelineItem.id).map { actions in
|
||||
TimelineItemContextMenu(contextMenuActions: actions) { action in
|
||||
coordinator.send(viewAction: .contextMenuAction(itemID: timelineItem.id, action: action))
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
coordinator.send(viewAction: .itemAppeared(id: timelineItem.id))
|
||||
|
||||
@@ -70,7 +70,7 @@ struct TimelineView: UIViewControllerRepresentable {
|
||||
}
|
||||
|
||||
// Doesn't have an equatable conformance :(
|
||||
tableViewController.contextMenuBuilder = context.viewState.contextMenuBuilder
|
||||
tableViewController.contextMenuActionProvider = context.viewState.contextMenuActionProvider
|
||||
}
|
||||
|
||||
func send(viewAction: RoomScreenViewAction) {
|
||||
|
||||
Reference in New Issue
Block a user