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>
This commit is contained in:
2026-05-25 21:41:46 +08:00
parent eb94142404
commit 014437760d
18 changed files with 1063 additions and 311 deletions
+8
View File
@@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<!-- 推送 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
@@ -42,6 +43,7 @@
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustNothing"
android:theme="@style/Theme.Cyrene">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -83,6 +85,12 @@
android:resource="@xml/accessibility_config" />
</service>
<!-- WebSocket 后台保活 -->
<service
android:name=".service.WebSocketKeepAliveService"
android:exported="false"
android:foregroundServiceType="dataSync" />
<!-- FileProvider:日志分享 -->
<provider
android:name="androidx.core.content.FileProvider"