Skip to content

feat: built-in markdown with streaming polish and chat view API changes - #18

Merged
divyanshub024 merged 21 commits into
mainfrom
dv/chat-view-api
Aug 22, 2026
Merged

feat: built-in markdown with streaming polish and chat view API changes#18
divyanshub024 merged 21 commits into
mainfrom
dv/chat-view-api

Conversation

@divyanshub024

@divyanshub024 divyanshub024 commented Aug 22, 2026

Copy link
Copy Markdown
Member

Summary

Roadmap row 25 plus the chat view API decisions that fell out of dogfooding the live example. Five commits, reviewable in order.

MarkdownFlowMarkdown, assistant prose typeset by a built-in parser (no new dependency). The dialect is what assistants emit: ATX headings on the existing type ramp, emphasis, inline code, fenced code rendered by FlowCodeBlock (sharing the FlowCodePart copy contract), [label](href) links plus bare-URL autolinks with GFM's trimming rules (balance-aware parens, trailing punctuation, www. prepending), nested lists, quotes, rules, and pipe tables with alignment and overflow scroll. Inline code paints as a rounded chip under the glyphs, so a wrapped chip keeps only its outer corners rounded and the streaming reveal runs straight through it. Links report intent via onLinkTap and render as plain prose when no handler is wired. Assistant text parts render markdown by default (markdown: false opts out); user and system turns stay plain.

Streaming motion — the reveal runs through one sequenced frontier: nothing renders below the animating block, fences and tables ease in with height and opacity, line growth is eased in layout, and pacing keeps the frontier inside the reveal's lag bound on fast streams. The parser tolerates input that ends mid-construct, and restyles ride source-offset fade stamps so nothing re-fades. Also fixes a first-reply flicker loop (the fit-mode flip is frozen while streaming) and debounces the jump-to-latest button.

Breaking (pre-1.0), each called out in the CHANGELOG: assistant text parts render markdown by default; FlowChatView.composer is now required (still nullable, and an all-null construction asserts instead of rendering a blank surface); FlowComposer.placeholder defaults to 'How can I help you today?'; a conversation that fits its viewport reads from the top.

Also: tap-to-dismiss and scroll-to-dismiss for the keyboard; the example is now a runnable streaming Gemini chat (platform runners checked in, key via a gitignored env.g.dart, link taps surfaced in a snackbar).

Notes for review:

  • The parser and chip painter follow the syntax highlighter's precedent: from-scratch, synchronous, string in and spans out, theme passed as arguments. The GFM autolink trimming rules and the painted-chip technique were adapted from studying gpt_markdown's source; no dependency was taken.
  • While streaming, the whole markdown document is one quiet semantics block (a single label of the text so far) and the real semantics tree mounts once at settle. Links are inert during the reveal by design, so nothing interactive is hidden.
  • A known upstream issue is documented but not in this diff: Flutter 3.47.0 asserts in the reworked semantics pipeline on hot restart when the platform accessibility bridge is attached. Extensive on-device and widget-test evidence shows it is not triggered by this tree; a minimal repro and issue draft are prepared separately.

Screenshots

Before After
Assistant replies rendered raw markdown as plain text (captures being attached)

How this was verified

flutter analyze clean in the package root, example/, and playground/; dart format . applied; docs site builds with the new markdown page. A scratch widget-test harness (kept outside the repo per the no-tests policy) replays a Gemini-shaped stream with semantics enabled, irregular delta bursts, a mid-stream drag, and a regenerate, asserting the reveal never collapses. Headless-Chrome captures of the playground web build verify: the typeset document in both themes, the frontier never rendering below the animating block, fences fading in at their turn, every autolink trimming rule (including the parenthesized Wikipedia URL), and a wrapped chip keeping only its outer corners rounded. The live example was exercised end to end against Gemini on the iOS simulator, including the first-reply flicker scenario this PR fixes.

Checklist

  • flutter analyze lib and flutter analyze in example/ and playground/ are clean
  • dart format . applied
  • Exercised in the playground — with a stage demo added or updated if this is a new component or variant
  • No new entries under dependencies: in pubspec.yaml (Flutter SDK and flutter.dev packages only)
  • Nothing model-facing — no prompts, schemas, or provider/network calls
  • New public API is exported from lib/flow_ui.dart and documented in docs/ and the README table
  • CHANGELOG.md updated for user-facing changes, with breaking changes called out
  • PR title follows conventional commits (feat:, fix:, refactor:, docs:, chore:)

Note

Medium Risk
Large new parser/renderer and several breaking chat APIs (markdown-by-default, required composer, placeholder default, top-aligned short threads) can change host rendering and call sites. The example now talks to Gemini over HTTP with a gitignored key.

Overview
Ships FlowMarkdown: a built-in, no-dependency parser/renderer for assistant prose (headings, emphasis, lists, quotes, tables, GFM autolinks, fences via FlowCodeBlock). Assistant text parts render markdown by default; hosts pass markdown: false for literal text. Streaming uses a sequenced frontier (eased line growth, fences/tables fade in, mid-construct input tolerated, reduced-motion static).

Chat surface: short threads read from the top until they overflow; keyboard dismisses on surface tap and thread drag; messageFooter fills the default message footer without replacing the whole turn. Breaking: FlowChatView.composer is required (still nullable), FlowComposer.placeholder defaults to 'How can I help you today?'.

The example is now a live Gemini host (stop/retry/copy/feedback, gitignored env.g.dart, checked-in platform runners). CI stubs the missing key file so analyze still runs.

Reviewed by Cursor Bugbot for commit 08cf414. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread example/macos/Runner/DebugProfile.entitlements
Comment thread example/android/app/src/main/AndroidManifest.xml
Comment thread example/test/widget_test.dart Outdated
Comment thread example/ios/Runner.xcodeproj/project.pbxproj Outdated
Comment thread lib/src/widgets/flow_markdown.dart
Comment thread example/lib/main.dart
Comment thread lib/src/utils/flow_markdown_parser.dart

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit add5fea. Configure here.

Comment thread example/lib/gemini_api.dart
@divyanshub024
divyanshub024 merged commit d867df2 into main Aug 22, 2026
5 checks passed
@divyanshub024
divyanshub024 deleted the dv/chat-view-api branch August 22, 2026 14:09
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