Commit Graph
6 Commits
Author SHA1 Message Date
rune 2668555b98 Add nested (hierarchical) conversation folders
Folders can now contain other folders, arbitrarily deep — e.g. "Work"
containing "Project A"/"Project B". v10 migration adds a
self-referencing parentId column; tree ordering, depth, and cycle
detection are pure Swift (Folder.orderedTree/isDescendant/
visibleFolderIds), not SQL, so listFolders() stays a simple flat
query.

- Create nested folders via "New Subfolder…" (context menu, both
  list views) or by dragging a folder onto another to reparent it.
  Dragging onto an existing descendant is rejected (cycle guard).
- Deleting a folder reparents its children and any conversations
  filed directly in it up one level to the deleted folder's own
  parent — conversations are never deleted. This also fixes a real
  bug: the previous deleteFolder never persisted unfiling to the
  database, only patched in-memory state, so a conversation whose
  folder was deleted kept a dangling folderId and silently vanished
  from view after the next relaunch.
- All "Move to Folder" pickers (sidebar, advanced list, per-row
  context menus, the Save dialog's folder popup) show an indented
  flat list reflecting the tree.
- New DraggedItem enum disambiguates a dragged folder from dragged
  conversation(s) in the shared string-based drag payload, and
  unifies both list views on the same bundled-multi-selection format
  — closes a gap where dragging a multi-selection in the advanced
  list (⌘L) only moved the one row grabbed, unlike the sidebar.

Confirmed working live, including relaunch-survival of the
delete/reparent fix.
2026-08-02 17:52:10 +02:00
rune 76b58e6fdc Rename app from oAI to Confab
"oAI" reads as easily confused with OpenAI, both visually and in
casual conversation. Renamed to "Confab" throughout: Xcode
target/scheme/bundle ID (com.oai.Confab), Info.plist and Help Book
identity, all user-facing UI text, internal Log subsystem and color
identifiers, localization catalogs (6 languages, including a proper
reworded/retranslated Intel-deprecation notice), Help Book HTML
content, and docs (README/DEVELOPMENT/PRIVACY/SECURITY).

Deliberately cosmetic-only: the on-disk data folder
(~/Library/Application Support/oAI/), database/backup filenames,
Keychain service identifiers, and EncryptionService's key-derivation
inputs are all left untouched so existing conversations, settings,
and stored API keys survive the update with zero migration and no
re-entering credentials. Verified live: a real signed build
successfully decrypted a stored API key and loaded an existing
conversation database after the bundle ID change.

Also includes a small already-completed, previously uncommitted
model-release-date feature (ModelInfo/OpenRouterModels/
OpenRouterProvider/ModelInfoView) that happened to share several
files with this rename.

Gitignored on this branch and updated on disk but not part of this
commit: CLAUDE.md, RELEASE_NOTES.md, and the build*.sh scripts.
2026-08-02 14:58:14 +02:00
rune e898d4b6db Sort folders alphabetically; let users pick the merge model directly
Folders now list alphabetically (case-insensitive) everywhere they're
shown — sidebar, advanced conversation list, and the "Move to Folder"
menu — rather than creation order. listFolders() does the sort at the
DB layer; in-memory folder arrays are re-sorted after local
create/rename so newly added or renamed folders don't fall out of
order until the next reload.

Combine Conversations' AI-Assisted Merge no longer silently assumes
settings.defaultModel — added a model picker (reusing ModelSelectorView,
defaulting to the current default model/provider) so users can pick
which model performs the merge per-combine. ConversationMergeService.merge
takes optional mergeModelId/mergeProvider overrides.
2026-07-28 14:39:18 +02:00
rune 376fff4939 Add folders for organizing saved conversations
Conversations can now be filed into flat (non-nested) folders, shown
as collapsible sections in both the sidebar and the advanced
conversation list. New folders migration (v9) adds a folders table
and conversations.folderId with ON DELETE SET NULL, so deleting a
folder unfiles its conversations rather than losing them. Move/rename/
delete via context menu; conversation lists with no folders fall back
to the existing flat view unchanged.
2026-07-28 12:43:05 +02:00
rune 0642f3746f Add all-time usage statistics tab
Extends the existing Stats sheet (⌘⇧S) with a Session/All-Time segmented
picker. All-Time aggregates tokens, cost, and message counts across every
saved conversation, broken down by model and by conversation, using the
modelId already stored per message — no schema change needed.
2026-07-28 12:35:45 +02:00
rune f3c6271c9e Phase 4 tests: DatabaseService migrations + ContextSelectionService DB paths
17 tests against throwaway in-memory DatabaseService instances: all
v1-v8 tables/columns exist post-migration, settings CRUD, conversation
save/load round-trip, instance isolation between separate in-memory
queues, and ContextSelectionService's DB-coupled paths (starring,
excluded-range summaries, smartSelection end to end) that were
previously untestable.
2026-07-24 09:16:46 +02:00