Resizable single-project stats widget (4x1 / 2x2 / 3x2 / 3x3+) showing
total word count, cadence-goal progress, today/streak, a 7-day sparkline,
and Open/Note actions. Adds a config activity for project selection.
Bumps Glance to 1.2.0-rc01 and wires up providePreview + setWidgetPreviews
so all three widgets render previews on Android 15+ pickers. Adds the
project name to the Add Note widget header. Extracts parseDailyWordTotals
and formatWidgetWords as shared helpers.
- Wrap suggestion derivation in remember(...) so HdHairlineTagField
and the encyclopedia tag-add dialog only recompute when the draft
or existing-tag set changes.
- Replace HdHairlineTagField's nullable suggestTags param with an
empty-default lambda, removing the inline null check.
- Extract the FlowRow-of-chips suggestion strip into a shared
HdTagSuggestionStrip composable; the design-system field and the
encyclopedia dialog now use it.
- Guard rankedTags updates in BrowseNotes and TimeLineOverview
components so identical lists don't propagate downstream.
HdHairlineTagField now accepts an optional suggestTags callback and
renders a row of suggestion chips below the input as the user types.
Project components inherit a suggestTags implementation from
ProjectComponentBase that delegates to TagIndexService.suggest, scoped
to the top 5 results across all entity types.
BrowseNotes and TimeLineOverview now expose a rankedTags Value sourced
from TagIndexService. UIs subscribe to it instead of recomputing
buildTagIndex from the in-memory list on every frame.
Removes identical private cleanTags from EncyclopediaRepository,
NotesRepository, and TimeLineRepository in favor of one top-level
function in the tagindex package.
Aggregates tags from encyclopedia, notes, and timeline events into a
project-scoped reactive index for ranking and lookup. Each repository
gains a contentChangedFlow signal that drives a debounced rebuild.
Brings Account Settings in line with the Hammer design system: breadcrumb,
§ 0 Hero with version greeble, six numbered sections at 64dp spacing, and
a folio caption footer. Drops every M3 Surface/card/button on the screen.
§ III Sync gets a new HdCatalogueCard affordance — a doubled-hairline
library-index-card with four corner greeble slots — to highlight
connection state above the rest of the page.
Lifts three helpers from Project Settings into the design system so both
screens share them: HdHairlineCheckbox, HdHairlineToggleRow, and a
generic HdHairlineSegmentedPicker (replaces the per-screen CadencePicker).
Adds a danger tone to HdHairlineButton and an inline error to
HdHairlineField. Per-platform PlatformSettingsUi (Android + Desktop)
also moves to Hd* primitives.
- View Note now reads as a hairline-framed modal with a CrumbRow
(back to Notes + delete-via-menu) over a StampRow (section label,
meta, Edit/Save), matching the encyclopedia entry vocabulary. Folio
footer flips to a status row in edit mode.
- Add HdEntityId design-system primitive: zero-padded type-prefixed
identifier (NOTE-007, ENT-034, SCN-12). Used in the notes folio
footer and the scene metadata panel masthead.
Replace the emoji header and Surface/elevation scene cards with the
hairline + mono-label vocabulary used by the rest of the redesigned
editor. Top-level group rows now lead with a chevron and display title;
nested groups keep the folder icon. The two floating FABs become a
footer row with the Outline Overview button and a + dropdown for new
scene/group; the footer hides on scroll-down and reveals on scroll-up
to reclaim vertical space on narrow layouts. The list uses
surfaceContainerLow only when in a split pane (sidebar context); on
mobile single-pane it sits on plain surface so it doesn't read as
phantom panel chrome. The list/editor split divider drops from 1dp
outline to Dp.Hairline outlineVariant.
- Add change-detection guard to the SceneEditor settings observer so
unrelated GlobalSettings emissions (font size, dnd, locale, ...) don't
rebuild the SceneEditor.State on every emit.
- Memoize isWide and the onToggleMetadata callback in SceneEditorUi so
EditorTopBar's parameter identity is stable across recompositions and
Compose can skip when nothing changed.
- Wrap the EntryDef groupBy in remember(refs) for both ReferencesBody
and DismissedBody so partition only runs when the lists actually
change.
- Drop the redundant derivedStateOf around the dialog suggestions list
(no observable Snapshot reads inside; plain remember is enough).
- Migrate AddReferenceDialog from raw Dialog to the new AnimatedDialog
wrapper so it gets fade+scale animation and predictive-back support
for free, matching the panel modal.
- Colocate per-bucket search placeholder strings on RefBucket via a new
searchPlaceholder() extension instead of an inline when expression at
the call site.
- Strip narration comments throughout SceneMetadataPanelUi.kt (// Header,
// Outline, // Notes, // Type tabs, // Search, // Footer, etc.).
- Drop two now-unused string resources (add_placeholder, add_no_matches)
superseded by the add_dialog_* family.
The hint read button-like even though it was just a label. Drops it
entirely; the dialog's empty state is now just the 'No matching
entries.' line. Removes the now-unused string resource.
Splits the panel-visibility concern into two paths:
- Wide layouts (in-line aside) read GlobalSettings.metadataPanelVisible.
Tapping the info icon flips the persisted setting via
toggleMetadataPanelVisible(), so the panel state survives across
sessions. Default true.
- Narrow layouts (Dialog) keep the existing transient behavior via
toggleMetadataModal() and the State.showMetadataModal flag.
The breakpoint decision still lives in SceneEditorUi (the component
intentionally doesn't know about screen width); SceneEditorUi derives
isWide once and dispatches the right toggle into EditorTopBar via a new
onToggleMetadata callback parameter on the expect/actual function.
Renames State.showMetadata -> showMetadataModal so future readers don't
conflate the persistent and transient flags. The new
GlobalSettings.metadataPanelVisible field carries a KDoc noting it's UI
state living in settings until we have a dedicated window-state store.
Adds HdUnsavedBadge and HdReferenceChip primitives, extends
HdMetadataItem with selectable and CollapsableSection with a trailing
action slot. Rewrites SceneMetadataPanelUi: hairline-underline fields
for outline / notes / draft name, references partitioned into
Characters / Locations / Other, dismissed promoted to a peer
collapsable, advanced rendered with HdMetadataItem, and a new modal
AddReferenceDialog with type tabs and live autocomplete. EditorTopBar
swaps M3 Badge for the square-corner HdUnsavedBadge, and the desktop
metadata sidebar drops its outer padding wrapper to sit flush.
Recasts the View Entry screen in the same hairline-and-mono editorial
voice as the rest of the redesigned encyclopedia: type stamp + folio
meta, massive 200-weight name, an inset figure (240x320 wide, full-width
on compact), a Particulars ledger of type/tags/aliases/scenes, paired
Tags and Aliases sections, an Appears-in-scenes list, and a colophon
footer. The folio meta swaps out for Save/Cancel during edit mode so
the row never overflows on narrow screens.
Adds a matching shared-element on the entry image so it animates from
the browse-card hero bounds straight to the inset bounds, instead of
being dragged along with the much larger card-bounds animation.
All user-facing copy lives in strings_encyclopedia.xml.
Adds a 12-week activity heatmap, writing streaks, this-week summary, and
goal-progress card to the project home screen. Surfaces per-device word
totals, reading-time and page estimates derived from total words, and
chapter spread (min/max/std-dev) alongside scene length stats. Replaces
the chapter words bar chart with a line chart.
Renames ProjectTheme.color1/color2 to primary/secondary and pipes them
into a Material 3 ColorScheme via material-kolor's dynamicColorScheme.
The user's secondary seeds both the Material 3 secondary and tertiary
palettes, the Rainbow palette style keeps them in distinct hue lanes
instead of collapsing toward the primary, and surfaceTint is redirected
to secondary so elevated surfaces (cards, dialogs, top bars) pick up
the accent.
The override is hoisted to the platform entry points
(ProjectEditorWindow.AppContent on desktop, ProjectRootActivity.Content
on Android) so a single ProjectThemeOverride wraps the NavigationRail,
ProjectRootUi, FAB stack, and confirm-close dialogs. ProjectRootUi and
ProjectRootFab no longer self-wrap.
All five project FABs (notes, encyclopedia, timeline, scene group,
scene) explicitly draw containerColor/contentColor from
secondaryContainer so the second color is the obvious accent on the
heaviest visible chrome.
New project-data sync phase runs before entity transfer. The blob is a
single per-project row on the server, hash-checked for conflicts; the
client surfaces a per-field pick-a-side resolver UI when both sides
edited concurrently. Author name is a text field, custom theme uses a
clickable color swatch backed by skydoves/colorpicker-compose, and the
word-count goal is cadence + count. Each opt-in section nulls out its
data when unchecked so the wire signal is unambiguous.