Commit Graph

16 Commits

Author SHA1 Message Date
AskaEth e65a35a239 fix: remove AnimatedVisibility from chat bubbles to fix LazyColumn scroll limit
AnimatedVisibility with visible=false starts items at zero height. Inside a
reverseLayout LazyColumn, this causes the list to miscompute total content
height, preventing items beyond the visible viewport from being composed.
This was limiting the chat to ~9 visible messages that filled the screen.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 12:43:57 +08:00
AskaEth 7fcf562648 feat: markdown/code message renderers, collapsible non-chat content, dark mode fixes, and data persistence
- Add MarkdownBubble (headings, bold/italic, code blocks, lists, quotes, links)
- Add CodeBubble with dark background + language header
- Add CollapsibleBubble wrapper for long non-chat content with fold/expand button
- Update WSReviewMessage DTO: add type and metadata fields for review messages
- Fix message dedup: apply removeWrappingDuplicates before DB insert instead of on return value
- Fix dark mode: explicit text colors on StatusIndicator, icon tints, dynamicColor=false
- Add enter-to-send toggle and typing indicator style (bubble/text) in settings
- Overlay: transparent window background, pill-shaped semi-transparent input field
- Remove PullToRefreshBox (conflicted with reverseLayout scroll), use refresh button
- Add auto-refresh when connection transitions offline→online
- Fix session ID fallback for DB message loading after APK update

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 12:36:06 +08:00
AskaEth 64c7018729 fix: stream_end dedup, typing indicator position, and indicator style toggle
- Fix stream_end not suppressed: populate recentParsedContents in response handler
  instead of clearing it, so the dedup check can correctly suppress wrapping text
- Fix typing indicator appearing at top (oldest) in reverseLayout: place item
  before itemsIndexed so it gets index 0 (visual bottom)
- Add typing indicator style toggle in settings: bubble (default) vs text mode,
  persisted via PreferencesDataStore, applied in ChatScreen and OverlayContent

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 19:02:47 +08:00
AskaEth 86d196b857 fix: align OverlayViewModel message dedup with ChatViewModel
Removed the legacy isDup check (role+content+msgType) that could suppress
multi_message items already seen as review items. Now deduplicates by
message ID only and inserts at correct timestamp position, matching
the fixed ChatViewModel behavior.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 18:40:57 +08:00
AskaEth 91231834dc fix: prevent IME from hiding latest messages in chat
Changed chat layout from Box overlay to Column flow so imePadding()
applies to the whole container instead of just the input bar. Messages
area now shrinks with the keyboard, keeping latest messages visible.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 13:01:43 +08:00
AskaEth 5dad0cd39b fix: use backend msg_type instead of hardcoding in server message handlers
Backend now guarantees msg_type is always populated. Changed all server
message handlers (stream_chunk, stream_end, thinking, tool_progress, error,
voice_transcript, review) to use wsMsg.msgType with safe fallback defaults
instead of hardcoded values.

Also added missing ProGuard keep rules for UI screens/components/overlay to
prevent R8 from stripping composables called via navigation lambdas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 12:50:49 +08:00
AskaEth ce73f68bc8 fix: add ProGuard keep rules for UI screens and components
Navigation compose lambdas in NavGraph may not be traced by R8's call
graph, causing screen composables to be stripped in release builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 12:45:48 +08:00
AskaEth 3c90adae6a fix: use offset+clipToBounds instead of graphicsLayer alpha for tab keep-alive
Hidden tabs with graphicsLayer{alpha=0f} still intercepted touch events.
Replaced with offset(x=2000.dp) + parent clipToBounds() so hidden composables
are off-screen and cannot capture touches meant for the visible tab.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 12:04:33 +08:00
AskaEth 014437760d fix: IME layout, message dedup, animation order, and overlay input positioning
- ChatScreen: restructure to Box overlay layout so only input area
  rises with IME, messages stay fixed. Add opaque background to input
  area. Use reverseLayout with newest-first animation order.
- OverlayContent: remove all manual IME detection — system forces
  adjust=pan on VoiceInteractionSession windows, so manual padding
  caused double offset. Let system handle IME naturally.
- ChatRepositoryImpl: add messageRemovals flow to clean up wrapping
  stream_end/response when review/multi_message items arrive later.
  Track lastResponseId in both stream_end and response handlers.
- ChatViewModel/OverlayViewModel: fix dedup to check by message ID
  only. Sort descending (newest first). Observe messageRemovals.
- NavGraph: keep all tabs composed with graphicsLayer alpha toggle —
  prevents ChatScreen destruction and re-render on tab switch.
- CyreneVoiceInteractionSession: defer configureWindow via post()
  to override system softInputMode flags.
- AndroidManifest: set windowSoftInputMode=adjustNothing on main
  activity.
- Add WebSocketKeepAliveService for background connection persistence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 21:41:46 +08:00
AskaEth eb94142404 fix: add missing ProGuard keep rules to prevent release crash
R8 was stripping Android components (services, application),
Room entities, Koin modules, and ViewModels — causing crash
when VoiceInteractionService was invoked via power button.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 21:15:23 +08:00
AskaEth 1c96588d79 chore: add release signing config via keystore.properties
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 20:27:29 +08:00
AskaEth 9295fe8021 feat: dark mode background fixes, chat bubble long-press menu, notification dedup, biometric auth for clear
- Fix: dark mode white backgrounds via transparent windowBackground, decorView color, and explicit Surface backgrounds on IoT/Profile/MainScreen
- Fix: dark mode text colors in ProfileScreen (nickname, account info, assistant status)
- Feat: long-press chat bubble to copy message text via DropdownMenu
- Feat: notification deduplication — track notified message IDs, clear on foreground
- Feat: cancel all notifications when app enters foreground
- Feat: biometric/device-credential verification before clearing local messages

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 20:22:28 +08:00
AskaEth 5247eef0fc feat: auto screen context toggle + fix dark mode status bar
- Add auto_screen_context preference (boolean, default false) to DataStore
- Add Switch toggle in Settings > Voice section to control automatic screen
  content reading when assistant is invoked via power button
- CyreneVoiceInteractionSession onShow now checks the preference before
  calling AccessibilityService to read and send screen content
- Fix status bar white in dark mode: MainActivity now observes theme mode
  preference (light/dark/auto) and passes resolved boolean to CyreneTheme
- CyreneTheme sets statusBarColor, navigationBarColor, and
  isAppearanceLightStatusBars/isAppearanceLightNavigationBars explicitly

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 18:25:47 +08:00
AskaEth 2725fdd1d5 fix: overlay status bar coverage and IME input flying in portrait mode
- Restore FLAG_TRANSLUCENT_STATUS and FLAG_TRANSLUCENT_NAVIGATION on
  VoiceInteractionSession window to let content extend behind system bars
- Move window configuration from onCreateContentView to onShow (window
  is guaranteed available at this point)
- Replace statusBarsPadding/navigationBarsPadding with manual status bar
  height calculation — Compose WindowInsets may not receive proper values
  in VoiceInteractionSession overlay windows
- Keep SOFT_INPUT_ADJUST_NOTHING + imePadding on InputArea for correct
  IME behavior (full-screen IME pushes input, floating IME does not)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 18:01:58 +08:00
AskaEth 367ef7f2d6 feat: reconnection, overlay UI, profile caching, history loading, log viewer, and about page
- Reconnection: unlimited retries with capped backoff, forceReconnect on foreground
  and manual refresh when offline
- Overlay: fix status bar coverage, remove scrim, fix IME layout (messages fixed
  at top, only full-screen IME pushes input), handle process-kill by eager
  ViewModel resolution with try-catch
- Profile: cache-first rendering, cloud refresh on each visit, silent fallback
  to cache on failure
- Messages: fix message swallowing by tracking DB observer job and using atomic
  StateFlow.update(), add dedicated isAssistantStreaming state for reliable
  typing indicator
- History: history_response handler now emits to live message stream, HTTP
  fallback waits for WS connection before requesting history
- Foreground: always request history on foreground to catch cross-device messages
- Log viewer: enhanced with All tab, auto-scroll, new categories (HTTP, voice, general),
  added log points for app lifecycle and overlay events
- Settings: added About page with project link (https://git.yeij.top/AskaEth/Cyrene-For-Android)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 17:58:34 +08:00
AskaEth a57692353c Initial Android project setup with Compose, WebSocket, and VoiceInteractionService
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:58:59 +08:00