Skip to content

Commit eaa5ec8

Browse files
Zaf4claude
andcommitted
Add inline collection rename, reorder Reading, restructure AI Settings
- Collections: rename a collection in-place (Finder-style) via the context menu; Enter/click-away commits, Esc cancels. - Sidebar: show Currently Reading above Recently Opened. - AI Settings: surface Model Provider/model at the top and tuck the custom-agent picker behind a "Use a custom agent" toggle (auto-shown when a custom agent is already set). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent bcf2521 commit eaa5ec8

3 files changed

Lines changed: 79 additions & 21 deletions

File tree

Sources/Refman/AISettingsView.swift

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,10 @@ struct AISettingsView: View {
1515
@StateObject private var codexList = CodexModelList()
1616
@StateObject private var providerSetup = ProviderSetupModel()
1717

18+
@State private var showAdvanced = false
19+
1820
var body: some View {
1921
Form {
20-
Section("Assistant Agent") {
21-
LabeledContent("Agent") {
22-
AgentPicker(
23-
stackAlignment: .trailing,
24-
pathAlignment: .trailing,
25-
pathMaxWidth: 280)
26-
}
27-
Text(
28-
"Any executable speaking the Agent Client Protocol on stdio works here. "
29-
+ "The bundled refman-agent bridges to a local Ollama."
30-
)
31-
.font(.caption)
32-
.foregroundStyle(.secondary)
33-
}
34-
3522
// Provider and model choice only apply to the bundled agent.
3623
if agentPath.isEmpty {
3724
Section("Model Provider") {
@@ -106,14 +93,36 @@ struct AISettingsView: View {
10693
}
10794

10895
Section {
109-
Text("Agent executable changes apply to newly opened assistant panels.")
96+
Toggle("Use a custom agent", isOn: $showAdvanced)
97+
}
98+
99+
if showAdvanced {
100+
Section("Assistant Agent") {
101+
LabeledContent("Agent") {
102+
AgentPicker(
103+
stackAlignment: .trailing,
104+
pathAlignment: .trailing,
105+
pathMaxWidth: 280)
106+
}
107+
Text(
108+
"Any executable speaking the Agent Client Protocol on stdio works here. "
109+
+ "The bundled refman-agent bridges to a local Ollama."
110+
)
110111
.font(.caption)
111112
.foregroundStyle(.secondary)
113+
}
114+
115+
Section {
116+
Text("Agent executable changes apply to newly opened assistant panels.")
117+
.font(.caption)
118+
.foregroundStyle(.secondary)
119+
}
112120
}
113121
}
114122
.formStyle(.grouped)
115123
.frame(width: 480, height: 600)
116124
.onAppear {
125+
if !agentPath.isEmpty { showAdvanced = true }
117126
modelList.load()
118127
codexList.load()
119128
providerSetup.refresh()

Sources/Refman/AppModel.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,15 @@ final class AppModel: ObservableObject {
634634
}
635635
}
636636

637+
func renameCollection(id: Int64, to name: String) {
638+
do {
639+
try repository.renameCollection(id: id, to: name)
640+
reload()
641+
} catch {
642+
statusMessage = "Could not rename collection: \(error.localizedDescription)"
643+
}
644+
}
645+
637646
/// Reorders the siblings under `parentId` after a drag in the sidebar.
638647
func moveCollections(parentId: Int64?, from source: IndexSet, to destination: Int) {
639648
var siblings = collections.filter { $0.parentId == parentId }

Sources/Refman/LibraryView.swift

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ struct LibraryView: View {
1616
@State private var collectionToDelete: RefmanCore.Collection?
1717
@State private var subcollectionParent: RefmanCore.Collection?
1818
@State private var subcollectionName = ""
19+
@State private var renamingCollectionId: Int64?
20+
@State private var renameText = ""
1921
@State private var previewURL: URL?
2022
@State private var showingAddPopover = false
2123
@State private var identifierText = ""
@@ -215,16 +217,18 @@ struct LibraryView: View {
215217
.tag(SidebarItem.trash)
216218
}
217219
Section("Reading") {
218-
Label("Recently Opened", systemImage: "clock.arrow.circlepath")
219-
.tag(SidebarItem.recentlyOpened)
220220
Label("Currently Reading", systemImage: "book")
221221
.tag(SidebarItem.reading)
222+
Label("Recently Opened", systemImage: "clock.arrow.circlepath")
223+
.tag(SidebarItem.recentlyOpened)
222224
}
223225
Section("Collections") {
224226
CollectionTree(
225227
parentId: nil,
226228
collectionToDelete: $collectionToDelete,
227-
subcollectionParent: $subcollectionParent)
229+
subcollectionParent: $subcollectionParent,
230+
renamingCollectionId: $renamingCollectionId,
231+
renameText: $renameText)
228232
if showingNewCollection {
229233
TextField("Collection name", text: $newCollectionName)
230234
.onSubmit {
@@ -811,6 +815,9 @@ private struct CollectionTree: View {
811815
let parentId: Int64?
812816
@Binding var collectionToDelete: RefmanCore.Collection?
813817
@Binding var subcollectionParent: RefmanCore.Collection?
818+
@Binding var renamingCollectionId: Int64?
819+
@Binding var renameText: String
820+
@FocusState private var renameFieldFocused: Bool
814821

815822
var body: some View {
816823
ForEach(model.collections.filter { $0.parentId == parentId }, id: \.id) { collection in
@@ -819,7 +826,9 @@ private struct CollectionTree: View {
819826
CollectionTree(
820827
parentId: collection.id,
821828
collectionToDelete: $collectionToDelete,
822-
subcollectionParent: $subcollectionParent)
829+
subcollectionParent: $subcollectionParent,
830+
renamingCollectionId: $renamingCollectionId,
831+
renameText: $renameText)
823832
} label: {
824833
row(for: collection)
825834
}
@@ -834,8 +843,26 @@ private struct CollectionTree: View {
834843
}
835844
}
836845

846+
@ViewBuilder
837847
private func row(for collection: RefmanCore.Collection) -> some View {
838-
Label(collection.name, systemImage: collection.icon ?? "folder")
848+
if renamingCollectionId == collection.id {
849+
Label {
850+
TextField("Name", text: $renameText)
851+
.textFieldStyle(.plain)
852+
.focused($renameFieldFocused)
853+
.onAppear { renameFieldFocused = true }
854+
.onSubmit { commitRename(collection) }
855+
.onExitCommand { renamingCollectionId = nil }
856+
.onChange(of: renameFieldFocused) { _, focused in
857+
if !focused, renamingCollectionId == collection.id {
858+
commitRename(collection)
859+
}
860+
}
861+
} icon: {
862+
Image(systemName: collection.icon ?? "folder")
863+
}
864+
} else {
865+
Label(collection.name, systemImage: collection.icon ?? "folder")
839866
.contextMenu {
840867
Menu("Icon") {
841868
ForEach(LibraryView.collectionIcons, id: \.group) { group in
@@ -850,6 +877,10 @@ private struct CollectionTree: View {
850877
}
851878
}
852879
}
880+
Button("Rename") {
881+
renameText = collection.name
882+
renamingCollectionId = collection.id
883+
}
853884
Button("New Subcollection") {
854885
subcollectionParent = collection
855886
}
@@ -884,6 +915,15 @@ private struct CollectionTree: View {
884915
model.add(documentIds: ids, toCollection: collection.id!)
885916
return true
886917
}
918+
}
919+
}
920+
921+
private func commitRename(_ collection: RefmanCore.Collection) {
922+
let name = renameText.trimmingCharacters(in: .whitespacesAndNewlines)
923+
if !name.isEmpty, name != collection.name {
924+
model.renameCollection(id: collection.id!, to: name)
925+
}
926+
renamingCollectionId = nil
887927
}
888928
}
889929

0 commit comments

Comments
 (0)