fix(#472): clear per-radio in-memory caches on reconnect
Switching radios showed the previous radio's channel history (including its outgoing messages) on the new radio. The in-memory caches _channelMessages, _conversations, and _loadedConversationKeys are keyed by channel index / contact key, not by radio, and were never cleared on a switch; a new radio's empty store could not overwrite them (_loadChannelMessages only writes on a non-empty read). On-disk stores are already per-radio (device+PSK since #277), so no re-keying or migration is needed. Clear the three caches in _resetConnectionHandshakeState (runs at the start of every connect). loadAllChannelMessages and _loadMessagesForContact repopulate from the new radio's store. Adds a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>pull/510/head
parent
7a2fca929a
commit
f84bcaa736
@ -0,0 +1,68 @@
|
||||
// #472: switching radios must not show the previous radio's history.
|
||||
//
|
||||
// The per-radio in-memory caches (_channelMessages, _conversations,
|
||||
// _loadedConversationKeys) are keyed by channel index / contact key, not by
|
||||
// radio. _resetConnectionHandshakeState() runs at the start of every
|
||||
// connection, so it must clear them; otherwise a new radio whose store is empty
|
||||
// for a channel cannot overwrite the stale entry and keeps rendering the prior
|
||||
// radio's history (including its outgoing messages). On-disk stores are already
|
||||
// per-radio (device+PSK), so this is purely the runtime cache.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meshcore_open/connector/meshcore_connector.dart';
|
||||
import 'package:meshcore_open/models/channel_message.dart';
|
||||
import 'package:meshcore_open/storage/prefs_manager.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
setUp(() async {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
PrefsManager.reset();
|
||||
await PrefsManager.initialize();
|
||||
});
|
||||
|
||||
test(
|
||||
'connection reset clears the previous radio in-memory caches (#472)',
|
||||
() {
|
||||
final connector = MeshCoreConnector();
|
||||
|
||||
// Seed the caches as if a prior radio's history had loaded.
|
||||
connector.channelMessagesForTest[0] = [
|
||||
ChannelMessage(
|
||||
senderName: 'PrevRadio',
|
||||
text: 'history from the other radio',
|
||||
timestamp: DateTime.fromMillisecondsSinceEpoch(1000),
|
||||
isOutgoing: true,
|
||||
status: ChannelMessageStatus.sent,
|
||||
),
|
||||
];
|
||||
connector.conversationsForTest['deadbeef00'] = [];
|
||||
connector.loadedConversationKeysForTest.add('deadbeef00');
|
||||
|
||||
expect(connector.channelMessagesForTest, isNotEmpty);
|
||||
expect(connector.conversationsForTest, isNotEmpty);
|
||||
expect(connector.loadedConversationKeysForTest, isNotEmpty);
|
||||
|
||||
// A new connection begins.
|
||||
connector.resetConnectionHandshakeStateForTest();
|
||||
|
||||
expect(
|
||||
connector.channelMessagesForTest,
|
||||
isEmpty,
|
||||
reason: 'channel history cache must be dropped on reconnect',
|
||||
);
|
||||
expect(
|
||||
connector.conversationsForTest,
|
||||
isEmpty,
|
||||
reason: 'DM conversation cache must be dropped on reconnect',
|
||||
);
|
||||
expect(
|
||||
connector.loadedConversationKeysForTest,
|
||||
isEmpty,
|
||||
reason: 'loaded-conversation markers must be dropped so DMs reload',
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
Loading…
Reference in new issue