Files
ai-app/iris/src/lib.rs
T
irisandClaude Fable 5.1 64f64b54e5 iris: per-block markdown appearance, syntax-highlighted fences, tappable links
P1a (docs/RUST.md). A transcript row's blocks are drawn the way
Markdown.kt draws them rather than as one flat span list:

- transcript-ui/src/markdown.rs is a *block* renderer now.
  `BlockFrame` is the whole widget vocabulary -- Plain, Verbatim (a
  dark rounded panel that pans sideways) and Quote (a bar and an
  indent) -- so a new markdown feature costs spans, not widgets.
  `frame_of` is the one place the BlockKind -> appearance mapping is
  written.
- Fences take `client_core::highlight`'s spans by language, in the
  same Catppuccin palette Theme.kt's `catppuccinSyntax()` uses, with
  the char->byte offset conversion the two index spaces need.
- Lists get the bullet ladder and coloured markers MarkdownPieces.kt
  draws, ordered lists count from the number they were written with,
  headings take Material's own ladder (24/22/16/14/12/11).
- Tables are padded monospace columns measured from the cells, with
  the header bold and a rule under it -- see docs/DECISIONS.md for
  what that trades against a real grid.
- Links carry their URL through to a tap. `GestureOutcome::Tapped`
  is new: a press that never committed to a pan or a selection, so a
  finger that flung the list past a link does not also open it.
  `iris::platform::OpenUrl` is the capability, implemented by each
  backend (xdg-open/open/start on the desktop, an ACTION_VIEW intent
  deferred to `after_input` on Android, the same shape
  `pending_show_keyboard` uses).
- `DragArbiter`/`DragGesture` take an axis, so a code fence pans
  across its own long lines through the same machine a list pans
  down its rows -- and a vertical drag starting on a fence still
  reaches the list.
- `TextEditCtx::byte_at` answers which byte a tap landed on without
  exposing the parley layout; `Rect::radius` takes a `Len`, so a
  corner can be written in dp.

Tests: 31 in transcript-ui (11 new, covering the frame mapping,
highlighting including a multibyte fence and an unknown language,
list markers, table padding and wrapping, link hit-testing), 85 in
iris (4 new on the tap-vs-drag rule and the two axes).
cargo fmt clean, clippy warning-free.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 18:55:46 -04:00

60 lines
1.6 KiB
Rust

#![feature(unboxed_closures)]
#![feature(fn_traits)]
// Only `default::DefaultAppState::Event`'s default uses this; unused (and
// warned about) on the android target, which has no such default.
#![cfg_attr(not(target_os = "android"), feature(associated_type_defaults))]
#![feature(unsize)]
#![feature(option_into_flat_iter)]
#![feature(async_fn_traits)]
// Two windowing backends live side by side, chosen by target rather than by
// feature flag: winit everywhere but Android, android-view on it. They are
// mutually exclusive rather than both-compiled-in because winit's own
// Android support pulls in `android-activity`, which needs one of its
// `game-activity`/`native-activity` features selected -- exactly what
// `iris-core` was kept free of, and android-view is the framework's own
// answer to the same surface on that platform. See RUST.md's I2.
#[cfg(target_os = "android")]
pub mod android;
#[cfg(not(target_os = "android"))]
pub mod default;
pub mod attr;
pub mod event;
pub mod platform;
pub mod sense;
pub mod state;
pub mod task;
pub mod widget;
#[cfg(test)]
mod access_tests;
#[cfg(test)]
mod layout_tests;
#[cfg(test)]
mod sense_tests;
pub use iris_core as core;
pub use iris_macro as macros;
pub mod prelude {
use super::*;
#[cfg(target_os = "android")]
pub use android::*;
#[cfg(not(target_os = "android"))]
pub use default::*;
pub use attr::*;
pub use event::*;
pub use iris_core::*;
pub use iris_macro::*;
pub use platform::*;
pub use sense::*;
pub use state::*;
pub use task::*;
pub use widget::*;
pub use iris_core::util::Vec2;
pub use len_fns::*;
}