Commit Graph
9 Commits
Author SHA1 Message Date
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 b0f3049d6b Make PDF export actually dark
Two things were fighting the previous dark-PDF attempt, both
confirmed by direct experimentation:

- prefers-color-scheme is ignored entirely by the print pipeline —
  identical CSS printed light even with the webview's appearance
  forced to dark. Screen dark-mode media queries just don't apply to
  NSPrintOperation rendering.
- Even with dark colors set unconditionally (no media query), the
  print pipeline still dropped every background color and printed
  white — browsers/WebKit strip background-color/background-image by
  default when printing, to save ink, unless told otherwise via
  print-color-adjust: exact.

PDF now has its own always-dark stylesheet (pdfCss) instead of the
prefers-color-scheme-driven one HTML export still uses, plus
`* { print-color-adjust: exact }` so the dark backgrounds actually
survive the print pass. html(name:messages:) takes a new
forceDarkCSS parameter (default false, unchanged for HTML/other
callers); pdfData passes true. Dropped the now-pointless
webView.appearance forcing, since dark is unconditional now.

Verified with the same standalone repro-script + Read-the-PDF method:
dark page background, colored message boxes, dark code block, all
correctly surviving the real A4 print pipeline.
2026-07-29 12:37:18 +02:00
rune 879739b32c Switch PDF export page size from US Letter to A4 2026-07-29 12:08:22 +02:00
rune 7f5374dce0 Switch PDF export from createPDF() to real print pagination
Rune compared our PDF against a normal reference PDF and the
difference was structural, not just a font-size tweak: the reference
was 6 standard A4 pages (595x842pt); ours was ONE continuous page
850x6886pt — nearly 8 feet tall. That's what createPDF() actually
does when content overflows its frame (confirmed in the prior commit)
— it auto-grows to fit everything as a single non-standard-sized
page, never paginating. There was no page of a familiar size to judge
the "normal" font size against, which is what actually read as "huge"
even after the sizing fixes.

Replaced with WKWebView's real print pipeline: build an NSPrintInfo
for US Letter (612x792pt) with normal margins, get a print operation
via webView.printOperation(with:), and run it silently (no panel) to
a temp file, dispatched off the main actor since NSPrintOperation.run()
blocks synchronously. This is genuine multi-page pagination — same
mechanism any app's real print-to-PDF uses.

Also added break-inside/page-break-inside: avoid on .message so a
single message doesn't get split awkwardly across a page boundary.

Verified with a standalone reproduction script (same method as the
prior fix) using the actual exported CSS and realistic multi-message
content: clean 2-page US Letter output, message boundaries respected
across the page break, normal-looking document proportions.
2026-07-29 12:05:36 +02:00
rune 2219aceda6 Fix oversized nested headers in exported HTML/PDF
The remaining "text still looks large" complaint after the page-
geometry fix was real: .message h1-h6 only ever set margin, never
font-size, so any markdown header inside an AI response (very common
in formatted answers — "## Reality Check on Capacity" etc) fell back
to the browser's default heading sizes (h2 ≈ 22px+ against a 15px
body). Gave headers an explicit, compact scale (19/17/15.5/14px) and
trimmed the base body size from 15px to 14px and the outer title from
24px to 22px for a tighter, more document-like feel overall.

Verified by reproducing the exact content from the reported screenshot
(the M1 AI Setup conversation with its "Reality Check on Capacity"
h2 and bolded list items) through the same standalone WKWebView/
createPDF harness used for the previous fix, and visually confirming
the heading now renders proportionately instead of oversized.
2026-07-29 11:51:53 +02:00
rune 3a30db1d15 Actually fix oversized PDF text — root cause was the previous fix
Empirically reproduced this outside the app (standalone WKWebView +
createPDF script, inspecting real PDF page bounds via PDFKit) instead
of guessing again. Findings:

- WKPDFConfiguration.rect left at default captures the webview's
  frame size verbatim when content fits within it, and auto-grows to
  a single tall page matching full scrollable content when it
  overflows. It does not paginate, and setting rect explicitly just
  clips to that one rect instead.
- The scrollHeight-based frame resize added last round (to "fix" this
  same bug) was itself the problem: resizing the frame before calling
  createPDF produced a page that didn't match the resized frame at
  all (e.g. resized to 816x295, captured page came out 799x375) — a
  small, badly-proportioned page that made ordinarily-sized text look
  enormous relative to it. Removed entirely.
- A visible scrollbar during capture shaves ~17pt off the captured
  page width. Added ::-webkit-scrollbar { display: none } to prevent
  that.

Verified against a 12-message realistic conversation: clean single
page, correct proportions, readable text, matches the intended CSS
layout. The text-size-adjust/viewport-meta fix from last round turned
out to be unnecessary (computed font-size was correct all along) but
is harmless, so left in place.
2026-07-29 09:13:10 +02:00
rune a3fd2c0eab Fix extremely oversized text in PDF export
Three defensive fixes for WKWebView.createPDF() rendering text far
larger than the source HTML's actual font sizes specify:

- Added a viewport meta tag and explicit -webkit-text-size-adjust:
  100% — WebKit's shared engine has a text-autosizing heuristic
  (normally associated with mobile Safari, but can trigger in WKWebView
  contexts too, especially for content loaded via loadHTMLString with
  no base URL) that boosts font sizes for perceived readability; this
  disables it explicitly rather than relying on it not firing.
- Explicit body font-size (was previously unset, relying on WebKit's
  default) and webView.pageZoom = 1.0.
- Resize the webview to the actual rendered content height
  (via document.body.scrollHeight) before calling createPDF, instead
  of relying on its undocumented auto-sizing against the arbitrary
  initial frame — a bounds mismatch here is a known cause of
  blown-up/rescaled PDF output.
2026-07-29 09:01:12 +02:00
rune 53736d4c42 Add dark mode and GFM table support to HTML/PDF export
Dark: added a prefers-color-scheme: dark CSS block, so HTML export
adapts to the browser/OS theme it's later viewed in. PDF is baked at
export time so it can't respond live — instead the offscreen WKWebView
used for PDF rendering has its appearance explicitly set to
NSApp.effectiveAppearance, matching whatever mode the app is in right
now at export time.

Tables: the renderer had no table support at all (previously
documented as an intentional scope cut), so GFM pipe tables were
falling through to the plain-paragraph path and showing up as literal
"| --- | --- |" text. Added detection (a row line immediately followed
by a valid dashes/colons separator row) plus alignment parsing from
the separator's colons.
2026-07-29 08:08:16 +02:00
rune 634b83f284 Add HTML and PDF conversation export
Top item on the roadmap ranking from 2026-07-27 — multi-modal export
alongside the existing Markdown/JSON. New ConversationExportService
consolidates the two previously-duplicated Markdown builders
(ChatViewModel and ConversationListView had separate copies of the
same **User**/**Assistant** + --- format) and adds:

- A hand-rolled Markdown->HTML renderer scoped to what actually shows
  up in chat messages (headers, bold/italic, inline code, fenced code
  blocks, lists, blockquotes, links, horizontal rules) rather than
  full CommonMark/GFM — no existing markdown-to-HTML utility existed
  in the codebase, and swift-markdown-ui is SwiftUI-view-only with no
  HTML-string export API. Content is HTML-escaped before any markdown
  substitution so example code containing "<div>" etc renders as
  visible text, not live markup.
- PDF via an offscreen WKWebView loading that same HTML and calling
  the official createPDF(configuration:) API (macOS 11+) — no new
  project/framework linkage needed, WebKit is a system framework.

Wired into every place Markdown export already existed: File menu
(Export as HTML.../PDF...), /export slash command (now md|html|pdf|json),
and a new Export submenu (Markdown/HTML/PDF) on each conversation row's
context menu in the advanced conversation list, replacing the old
single-format swipe-only export. Help docs and InputBar autocomplete
updated to match.
2026-07-29 07:47:57 +02:00