From 659fdd7817d73e5672502eab345e18dc8c5b23ef Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Wed, 18 Feb 2026 13:56:29 +0100 Subject: [PATCH] Reimplement proper window state restoration --- Mactrix/MainView.swift | 6 ++-- Mactrix/Models/WindowState.swift | 52 +++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Mactrix/MainView.swift b/Mactrix/MainView.swift index c085621..5bd3f3d 100644 --- a/Mactrix/MainView.swift +++ b/Mactrix/MainView.swift @@ -7,7 +7,8 @@ import Utils struct MainView: View { @Environment(AppState.self) var appState - @State private var windowState = WindowState() + @SceneStorage("MainView.windowState") + private var windowState: WindowState = .init() @State private var showWelcomeSheet: Bool = false @@ -35,7 +36,8 @@ struct MainView: View { isUserIgnored: appState.matrixClient?.isUserIgnored(profile.userId) ?? false, actions: appState.matrixClient?.userProfileActions(forUserId: profile.userId, windowState: windowState), timelineActions: nil, - imageLoader: appState.matrixClient) + imageLoader: appState.matrixClient + ) case .none: ContentUnavailableView("Select a room", systemImage: "message.fill") } diff --git a/Mactrix/Models/WindowState.swift b/Mactrix/Models/WindowState.swift index 1b10dbd..c6ac37c 100644 --- a/Mactrix/Models/WindowState.swift +++ b/Mactrix/Models/WindowState.swift @@ -24,16 +24,13 @@ enum SearchDirectResult { final class WindowState { var selectedScreen: SelectedScreen = .none - // @SceneStorage("MainView.selectedRoomId") var selectedRoomId: String? - - // @SceneStorage("MainView.inspectorVisible") var inspectorVisible: Bool = false var inspectorContent: InspectorContent = .roomInfo var requestedVerification = false - + var searchQuery: String = "" var searchTokens: [SearchToken] = [] var searchDirectResult: SearchDirectResult? @@ -122,6 +119,53 @@ final class WindowState { } } +extension WindowState: @MainActor RawRepresentable { + struct SceneStorageRepresentation: Codable { + let selectedRoomId: String? + let inspectorVisible: Bool + let sidebarSections: SidebarSectionCollapsibility + + @MainActor init(windowState: WindowState) { + self.selectedRoomId = windowState.selectedRoomId + self.inspectorVisible = windowState.inspectorVisible + self.sidebarSections = windowState.sidebarSections + } + + @MainActor func restore(windowState: WindowState) { + windowState.selectedRoomId = selectedRoomId + windowState.inspectorVisible = inspectorVisible + windowState.sidebarSections = sidebarSections + } + } + + convenience init?(rawValue: String) { + guard + let data = rawValue.data(using: .utf8), + let decoded = try? JSONDecoder().decode(SceneStorageRepresentation.self, from: data) + else { + Logger.windowState.warning("Failed to recover WindowState from storage: \(rawValue)") + return nil + } + + self.init() + decoded.restore(windowState: self) + Logger.windowState.info("WindowState recovered from storage: \(rawValue)") + } + + var rawValue: String { + guard + let data = try? JSONEncoder().encode(SceneStorageRepresentation(windowState: self)), + let result = String(data: data, encoding: .utf8) + else { + return "" + } + + return result + } + + typealias RawValue = String +} + enum SearchToken: Hashable, Identifiable { case users, rooms, spaces, messages case resolvedRoomAlias(alias: String, resolvedRoom: ResolvedRoomAlias)