Skip to content

Add Engine & Model parent and Apple Intelligence / Open Source sub-panes#365

Merged
FuJacob merged 2 commits into
mainfrom
feat/settings-redesign-engine-model
May 28, 2026
Merged

Add Engine & Model parent and Apple Intelligence / Open Source sub-panes#365
FuJacob merged 2 commits into
mainfrom
feat/settings-redesign-engine-model

Conversation

@FuJacob
Copy link
Copy Markdown
Owner

@FuJacob FuJacob commented May 28, 2026

Re-opened after base branch deletion. Rebased onto current main (includes tooltip removal #362), cotabbyHelp calls stripped. Build/lint clean locally.

Greptile Summary

This PR implements three new settings panes — EngineAndModelPaneView (parent overview with the engine picker), AppleIntelligencePaneView (on-device availability + one-tap switch), and OpenSourcePaneView (local llama model management lifted verbatim from the legacy view) — and wires them into SettingsContainerView, replacing the previous PlaceholderPaneView fallback.

  • EngineAndModelPaneView owns the sole engine picker and shows a live status summary for whichever engine is selected; sub-panes are linked via sidebar rows.
  • AppleIntelligencePaneView shows the FoundationModelAvailabilityService state with a warning callout when the selected engine is unavailable.
  • OpenSourcePaneView lifts the full model-management UI (download catalog, Hugging Face browser, folder controls, installed-model list with delete confirmation) from the legacy settings view with no behavioral changes.

Confidence Score: 4/5

Safe to merge; all new panes are additive UI-only changes with no new business logic or data mutations beyond what already existed in the legacy settings view.

The three new panes are straightforward view decompositions that wire correctly into the container. The only noteworthy gap is that EngineAndModelPaneView omits the .fixedSize and .multilineTextAlignment modifiers present in the sibling AppleIntelligencePaneView, which can cause unavailability messages to be truncated in the parent overview. Everything else — engine switching, model deletion flow, callout logic — is consistent and correct.

EngineAndModelPaneView.swift — the availability Text display could truncate on narrow windows; OpenSourcePaneView.swift — inline filesystem calls inside body are inherited from legacy code but worth cleaning up.

Important Files Changed

Filename Overview
Cotabby/UI/Settings/Panes/EngineAndModelPaneView.swift New parent overview pane for engine/model settings with engine picker and high-level status; availability Text is missing multiline/fixedSize modifiers that its sibling sub-pane applies.
Cotabby/UI/Settings/Panes/AppleIntelligencePaneView.swift New Apple Intelligence sub-pane showing availability callout and one-tap engine switch; logic and modifiers are consistent with the rest of the settings UI.
Cotabby/UI/Settings/Panes/OpenSourcePaneView.swift New Open Source sub-pane lifting model management controls verbatim from the legacy view; inline FileManager.fileExists call inside body is a minor main-thread I/O concern.
Cotabby/UI/Settings/SettingsContainerView.swift Wires the three new pane views into the switch and removes them from the PlaceholderPaneView fallback; straightforward routing change with no logic issues.
Cotabby.xcodeproj/project.pbxproj Adds build file and file reference entries for the three new Swift source files; project structure changes look correct.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    SCV[SettingsContainerView] -->|selection == .engineAndModel| EMP[EngineAndModelPaneView]
    SCV -->|selection == .appleIntelligence| AIP[AppleIntelligencePaneView]
    SCV -->|selection == .openSource| OSP[OpenSourcePaneView]

    EMP -->|reads/writes| SS[SuggestionSettingsModel\n.selectedEngine]
    EMP -->|reads| FMAS[FoundationModelAvailabilityService\n.userVisibleMessage / .isAvailable]
    EMP -->|reads| RBM[RuntimeBootstrapModel\n.state.summary]
    EMP -->|.onAppear| FMAS

    AIP -->|reads| SS
    AIP -->|selectEngine .appleIntelligence| SS
    AIP -->|reads| FMAS
    AIP -->|.onAppear| FMAS

    OSP -->|reads| SS
    OSP -->|selectEngine .llamaOpenSource| SS
    OSP -->|reads/calls| RBM
    OSP -->|reads/calls| MDM[ModelDownloadManager]
    OSP -->|reads/calls| HFS[HuggingFaceSearchService]
Loading

Fix All in Codex Fix All in Claude Code

Reviews (1): Last reviewed commit: "Address Greptile feedback: align engine ..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@FuJacob FuJacob merged commit 5b5f56c into main May 28, 2026
4 checks passed
@FuJacob FuJacob deleted the feat/settings-redesign-engine-model branch May 28, 2026 10:37
Comment on lines +29 to +32
Text(foundationModelAvailabilityService.userVisibleMessage)
.foregroundStyle(foundationModelAvailabilityService.isAvailable ? .green : .orange)
}
case .llamaOpenSource:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing text modifiers on availability label

The sibling AppleIntelligencePaneView applies .multilineTextAlignment(.trailing).fixedSize(horizontal: false, vertical: true) to the same userVisibleMessage text. Without those modifiers here, long unavailability strings (e.g. "Apple Intelligence requires macOS 26 or later. Use Open Source on this Mac.") can be truncated or misaligned in the parent overview pane — the first thing a user sees when switching engines.

Fix in Codex Fix in Claude Code

Comment on lines +80 to +85
HStack(spacing: 8) {
let lmStudioURL = FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent(".lmstudio/models")
let lmStudioAvailable = FileManager.default.fileExists(atPath: lmStudioURL.path)
let isUsingCustomPath = BundledRuntimeLocator.customModelDirectoryURL() != nil
Button("Use LM Studio") {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Calling FileManager.default.fileExists(atPath:) and BundledRuntimeLocator.customModelDirectoryURL() directly inside the view body means a synchronous filesystem syscall runs on the main thread on every SwiftUI re-render. Extracting these into computed properties (or @State populated in .onAppear/button actions) avoids the repeated I/O and makes the intent clearer.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code

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