fluffychat/lib/pangea/join_codes/knock_tracker.dart
wcjord 7f1e8f5ea0
feat: client-side knock auto-accept via KnockTracker (#5794)
* feat: client-side knock auto-accept via KnockTracker

Replace server-side AutoAcceptInviteIfKnocked (removed in
synapse-pangea-chat PR #21) with client-side KnockTracker.

- Record knocked room IDs in Matrix account data (org.pangea.knocked_rooms)
- Auto-join when invite arrives for a previously knocked room
- Migrate storage from GetStorage to Matrix account data for
  cross-device sync and reinstall persistence
- Add joining-courses.instructions.md design doc

* formatting

* centralizes calls to knock-storage related functions

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>
2026-02-24 14:44:36 -05:00

45 lines
1.4 KiB
Dart

import 'package:matrix/matrix.dart';
/// Tracks room IDs the user has knocked on so the client can auto-accept
/// invites for previously knocked rooms.
///
/// Stored in Matrix account data under [_accountDataKey] so the state
/// survives reinstall, logout, and syncs across devices.
class KnockTracker {
static const String _accountDataKey = 'org.pangea.knocked_rooms';
static const String _roomIdsField = 'room_ids';
static Future<void> recordKnock(Client client, String roomId) async {
final ids = _getKnockedRoomIds(client);
if (!ids.contains(roomId)) {
ids.add(roomId);
await _writeIds(client, ids);
}
}
static bool hasKnocked(Client client, String roomId) {
return _getKnockedRoomIds(client).contains(roomId);
}
static Future<void> clearKnock(Client client, String roomId) async {
final ids = _getKnockedRoomIds(client);
if (ids.remove(roomId)) {
await _writeIds(client, ids);
}
}
static List<String> _getKnockedRoomIds(Client client) {
final data = client.accountData[_accountDataKey];
final list = data?.content[_roomIdsField];
if (list is List) {
return list.cast<String>().toList();
}
return [];
}
static Future<void> _writeIds(Client client, List<String> ids) async {
await client.setAccountData(client.userID!, _accountDataKey, {
_roomIdsField: ids,
});
}
}