Merge branch 'spike/block2-derisking'
This commit is contained in:
commit
0cecb943f0
12 changed files with 211 additions and 3 deletions
|
|
@ -8,12 +8,29 @@ import '../security/secret_store.dart';
|
|||
/// capped, per-peer JSON list — recent history survives leaving the chat. Small
|
||||
/// and simple on purpose; the encrypted Drift DB is the eventual home if chats
|
||||
/// grow large.
|
||||
/// A conversation preview for the messages inbox.
|
||||
class ChatSummary {
|
||||
const ChatSummary({
|
||||
required this.peerPubkey,
|
||||
required this.lastText,
|
||||
required this.lastAt,
|
||||
});
|
||||
|
||||
final String peerPubkey;
|
||||
final String lastText;
|
||||
final DateTime lastAt;
|
||||
}
|
||||
|
||||
class MessageStore {
|
||||
MessageStore(this._store);
|
||||
|
||||
final SecretStore _store;
|
||||
static const _prefix = 'tane.social.chat.';
|
||||
|
||||
/// Index of peers we have a conversation with (the keystore is key/value with
|
||||
/// no key enumeration, so we track the list ourselves).
|
||||
static const _indexKey = 'tane.social.chats';
|
||||
|
||||
/// Keep only the most recent [_cap] messages per conversation, to bound the
|
||||
/// keystore entry size.
|
||||
static const _cap = 200;
|
||||
|
|
@ -36,7 +53,7 @@ class MessageStore {
|
|||
}
|
||||
|
||||
/// Appends [message] to the conversation with [peerPubkey] (trimming to the
|
||||
/// cap).
|
||||
/// cap) and records the peer in the conversation index.
|
||||
Future<void> append(String peerPubkey, PrivateMessage message) async {
|
||||
final next = [...await history(peerPubkey), message];
|
||||
final capped =
|
||||
|
|
@ -52,5 +69,35 @@ class MessageStore {
|
|||
},
|
||||
]),
|
||||
);
|
||||
await _rememberPeer(peerPubkey);
|
||||
}
|
||||
|
||||
/// Conversations, most-recently-active first (for the messages inbox).
|
||||
Future<List<ChatSummary>> conversations() async {
|
||||
final summaries = <ChatSummary>[];
|
||||
for (final peer in await _peers()) {
|
||||
final history = await this.history(peer);
|
||||
if (history.isEmpty) continue;
|
||||
final last = history.last;
|
||||
summaries.add(ChatSummary(
|
||||
peerPubkey: peer,
|
||||
lastText: last.text,
|
||||
lastAt: last.at,
|
||||
));
|
||||
}
|
||||
summaries.sort((a, b) => b.lastAt.compareTo(a.lastAt));
|
||||
return summaries;
|
||||
}
|
||||
|
||||
Future<List<String>> _peers() async {
|
||||
final raw = await _store.read(_indexKey);
|
||||
if (raw == null || raw.isEmpty) return const [];
|
||||
return raw.split('\n').where((s) => s.isNotEmpty).toList();
|
||||
}
|
||||
|
||||
Future<void> _rememberPeer(String peer) async {
|
||||
final peers = await _peers();
|
||||
if (peers.contains(peer)) return;
|
||||
await _store.write(_indexKey, [...peers, peer].join('\n'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue