Replaced the generic file picker with a dropdown menu offering three
options: take photo (camera preview), pick from gallery (image/*), or
choose any file (*/*). Camera captures are compressed as JPEG and
uploaded like any other file. Upload logic extracted into shared
uploadPickedFile helper.
Parse tool events into thinking/analyzing/inProgress/completed states
instead of showing all as generic "Tool" rows. Handles type "thinking"
(shows "Verarbeitet…"), "analyzing" (shows filename), "start"/"end"/
"error" with proper icons and elapsed time. Empty/thinking-only events
no longer show a confusing wrench icon.
StreamConsumer.Incremental now returns StreamState (content, reasoning,
tools, query, sources) instead of just visible text. All sentinel sections
are parsed and structured:
- \x01 REASONING: captured as separate string
- \x02 SOURCES: parsed as List<SearchSource> (title, url, snippet)
- \x03 TOOL: parsed as List<ToolEvent> (type, name, args, result, elapsed)
- \x04 QUERY: captured as search query string
UI components:
- ReasoningBlock: collapsible "Gedankengang" with expand/collapse animation
- ToolEventsBlock: shows tool-call steps with status icons (start/end/error)
- SourcesBlock: web search sources as compact cards with domain extraction
Message model extended with reasoning, tools, query, sources fields.
KaizenApi.chat() returns Flow<StreamState> instead of Flow<String>.
ChatScreen wires all fields to Message during streaming.
Fixed: empty append() on Incremental no longer prematurely ends tool phase.
StreamConsumerTest rewritten to verify all parsed sections.
Settings now persist across app restarts via SecureStore:
- Theme (KaizenThemeId), appearance (Light/Dark/System), username, locale
- All loaded on SettingsViewModel init, saved on every change
Server sync: fetchMe() returns name + email from /api/v1/me,
populates SettingsViewModel on login and each foreground resume.
Language selector: System / Deutsch / English pill toggle in Settings.
Locale preference stored; runtime switching deferred to next iteration.
MeResponse expanded to parse name + email (was defaultModel only).
SettingsViewModel tests updated for store-less default state.
German (default) in values/strings.xml, English in values-en/strings.xml.
Matches web app's next-intl de/en setup.
Migrated: greeting, hero headline, chat input, error messages, mode pills,
suggestion pills, sidebar (brand, search, dates, logout, settings),
model sheet, login screen (welcome, fields, errors, submit button),
conversation labels (locked, pinned).
ChatModels: Suggestion/ChatMode now use resource IDs instead of hardcoded strings.
greeting() is now @Composable (uses stringResource).
ModePillsRow: selected state uses resource ID (Int) instead of String.
Date labels (HEUTE/GESTERN/FRÜHER) localized via DateLabels data class.