From 7174618a63d9816645b3eb94033c394f5a350cda Mon Sep 17 00:00:00 2001 From: Alexander Goodkind Date: Wed, 22 Jul 2026 20:12:10 -0700 Subject: [PATCH] Extract relay controller config actions Co-authored-by: Codex --- .../RelayController+ConfigLibrary.swift | 46 +++++++++++++++++++ Apps/iOS/Services/RelayController.swift | 41 +---------------- 2 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 Apps/iOS/Services/RelayController+ConfigLibrary.swift diff --git a/Apps/iOS/Services/RelayController+ConfigLibrary.swift b/Apps/iOS/Services/RelayController+ConfigLibrary.swift new file mode 100644 index 0000000..6fb126a --- /dev/null +++ b/Apps/iOS/Services/RelayController+ConfigLibrary.swift @@ -0,0 +1,46 @@ +// +// RelayController+ConfigLibrary.swift +// CellTunnelPhone +// +// Created by Alexander Goodkind on 2026-07-22. +// Copyright © 2026, all rights reserved. +// + +import CellTunnelLog +import Foundation + +private let configLibraryLogger = CellTunnelLog.logger(category: .relay) + +// MARK: - Config operations + +extension RelayController { + /// Deletes a stored configuration. + func deleteConfig(id: UUID) { + configLibraryLogger.notice("relay controller delete config requested") + Task { await backend.deleteConfig(id: id) } + } + + /// Renames a stored configuration without touching tunnel state. + func renameConfig(id: UUID, name: String) { + configLibraryLogger.notice("relay controller rename config requested") + Task { await backend.renameConfig(id: id, name: name) } + } + + /// Creates a stored configuration from raw text without leaving it active, for the + /// new-config flow. The agent activates a config on import, so the previously active + /// config is restored afterward to keep New from stealing the current selection. + func createConfig(name: String, text: String) { + configLibraryLogger.notice("relay controller create config requested") + let previousActiveID = activeConfigID + if previousActiveID != nil { + pinnedActiveConfigID = previousActiveID + } + Task { + await backend.importConfig(name: name, text: text) + if let previousActiveID { + await backend.activateConfig(id: previousActiveID) + } + pinnedActiveConfigID = nil + } + } +} diff --git a/Apps/iOS/Services/RelayController.swift b/Apps/iOS/Services/RelayController.swift index fdccb35..b29a735 100644 --- a/Apps/iOS/Services/RelayController.swift +++ b/Apps/iOS/Services/RelayController.swift @@ -140,7 +140,7 @@ struct RelayStatusSample: Sendable { @MainActor @Observable final class RelayController { - private let backend: any RelayControlBackend + let backend: any RelayControlBackend private let installState: InstallationState private let deviceProbe: DeviceEgressProbe? private var pollTask: Task? @@ -183,7 +183,7 @@ final class RelayController { /// cannot momentarily surface the agent's intermediate "new config is active" state /// between `importConfig` and the restoring `activateConfig`. Non-nil only while a /// create that preserves a prior active config is in flight. - private var pinnedActiveConfigID: UUID? + var pinnedActiveConfigID: UUID? /// Whether the background agent is installed, the gate to the install-agent setup /// tier. Always true on the iPhone, where there is no separate agent; on the Mac /// it tracks the install state. @@ -613,40 +613,3 @@ extension RelayController { } } } - -// MARK: - Config operations - -extension RelayController { - /// Deletes a stored configuration. - func deleteConfig(id: UUID) { - logger.notice("relay controller delete config requested") - Task { await backend.deleteConfig(id: id) } - } - - /// Renames a stored configuration without touching tunnel state. - func renameConfig(id: UUID, name: String) { - logger.notice("relay controller rename config requested") - Task { await backend.renameConfig(id: id, name: name) } - } - - /// Creates a stored configuration from raw text without leaving it active, for the - /// new-config flow. The agent activates a config on import, so the previously active - /// config is restored afterward to keep New from stealing the current selection. - func createConfig(name: String, text: String) { - logger.notice("relay controller create config requested") - let previousActiveID = activeConfigID - // Pin the prior active id only when there is one to preserve, so the poll holds - // the checkmark in place until the restore lands; with no prior active config the - // newly imported one stays active and no restore runs. - if previousActiveID != nil { - pinnedActiveConfigID = previousActiveID - } - Task { - await backend.importConfig(name: name, text: text) - if let previousActiveID { - await backend.activateConfig(id: previousActiveID) - } - pinnedActiveConfigID = nil - } - } -}