feat(chat): usable 1:1 chat — bottom-anchored, Drift-backed, dated
- Anchor the message list to the bottom (`reverse: true`) so new messages stay in view instead of landing below the fold. - Move chat history from the OS keystore (O(n²) JSON blob, silent 200-msg cap) to a separate encrypted Drift/SQLCipher DB (`ChatDatabase`): indexed append, uncapped history, dedup as a unique-key invariant. It's an ephemeral per-device cache, isolated from the inventory schema, its migrations, and its sync. No data migration (pre-release). - Add day separators (Today/Yesterday/locale date) and a per-bubble time, all via ICU (12/24h per locale; Localizations locale maps Asturian → Spanish for intl date symbols). - Add peer avatars (deterministic colour from the pubkey + name initial), surface send failures that were previously silent, and make bubble text selectable (addresses, links). - New i18n keys in en/es/pt/ast; tests for grouping, formatting, avatars, scroll anchoring, storage and send errors. Docs: docs/design/chat-storage.md + open-decisions.md.
This commit is contained in:
parent
171daabce3
commit
6cff0d0b11
27 changed files with 1793 additions and 264 deletions
|
|
@ -6,6 +6,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tane/data/species_repository.dart';
|
||||
import 'package:tane/data/variety_repository.dart';
|
||||
import 'package:tane/db/chat_database.dart';
|
||||
import 'package:tane/db/database.dart';
|
||||
import 'package:tane/i18n/strings.g.dart';
|
||||
import 'package:tane/security/secret_store.dart';
|
||||
|
|
@ -19,6 +20,9 @@ import 'package:tane/ui/variety_detail_screen.dart';
|
|||
/// verified separately in the SQLCipher-only security test).
|
||||
AppDatabase newTestDatabase() => AppDatabase(NativeDatabase.memory());
|
||||
|
||||
/// A fresh in-memory chat cache for host tests (unencrypted; see above).
|
||||
ChatDatabase newTestChatDatabase() => ChatDatabase(NativeDatabase.memory());
|
||||
|
||||
/// Unmounts the widget tree *inside* the test and drains the zero-duration
|
||||
/// timer Drift schedules when its stream subscription is cancelled. Without
|
||||
/// this, flutter_test reports "a Timer is still pending after disposal". Call
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue