Skip to content

refactor(services): inject dependencies into AppSettingsManager and add four singletons to AppServices#1157

Merged
datlechin merged 1 commit into
mainfrom
refactor/inject-services-into-app-settings-manager
May 9, 2026
Merged

refactor(services): inject dependencies into AppSettingsManager and add four singletons to AppServices#1157
datlechin merged 1 commit into
mainfrom
refactor/inject-services-into-app-settings-manager

Conversation

@datlechin

Copy link
Copy Markdown
Member

Summary

AppSettingsManager now takes its eight cross-singleton dependencies via init, matching the pattern PR #1153 established for storage classes. The 32 raw .shared reads inside the class are converted to instance properties, including the four Task { ... } capture closures in didSet blocks that previously dialed CopilotService.shared / MCPServerManager.shared mid-write.

AppServices gains four fields: queryHistoryManager, dateFormattingService, copilotService, mcpServerManager. The live initializer threads .shared defaults.

AppSettingsManager init signature:

init(
    storage: AppSettingsStorage = .shared,
    themeEngine: ThemeEngine = .shared,
    syncTracker: SyncChangeTracker = .shared,
    appEvents: AppEvents = .shared,
    dateFormattingService: DateFormattingService = .shared,
    queryHistoryManager: QueryHistoryManager = .shared,
    mcpServerManager: MCPServerManager = .shared,
    copilotService: CopilotService = .shared
)

private init() is dropped and the parameters all default to .shared, so AppSettingsManager.shared = AppSettingsManager() (and any test harness that wants to substitute) both compile.

Why individual params, not services: AppServices: AppServices.live initializes appSettings: .shared. Defaulting AppSettingsManager.init to services: AppServices = .live would recursively read .live mid-construction. Individual params avoid the cycle.

The 49 caller-side AppSettingsManager.shared reads are out of scope here; they ride along when their owners adopt services in subsequent DI waves.

Why this matters

Audit findings 3.1 + arch 5.1 ("complete the AppServices threading"). After PRs #1151, #1152, #1153, #1155, this is the next-biggest concentration: the central settings hub. Resolving it removes 32 raw .shared reads from a singleton that fires on every settings change, and keeps the door open for tests that want to drive AppSettingsManager against fakes (e.g. a no-op MCPServerManager so mcp.didSet doesn't actually start a server).

Test plan

  • Change a setting in Settings (theme, font, page size, MCP toggle) and confirm the side-effect runs (theme reapplied, MCP server starts/stops, sync tracker marked dirty).
  • Toggle Copilot in AI providers; confirm it starts/stops (verify Console logs).
  • Edit history retention; confirm applyHistorySettingsImmediately still fires.
  • App launches with default settings.
  • swiftlint --strict clean.

@datlechin datlechin merged commit 719f005 into main May 9, 2026
2 checks passed
@datlechin datlechin deleted the refactor/inject-services-into-app-settings-manager branch May 9, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant