feat: Store timestamp in the presence events
This fixes the presence never being accurate in the app.
This commit is contained in:
parent
2f232fefba
commit
907a0d2317
|
|
@ -26,6 +26,7 @@ export 'src/database/database_api.dart';
|
||||||
export 'src/database/hive_database.dart';
|
export 'src/database/hive_database.dart';
|
||||||
export 'src/database/fluffybox_database.dart';
|
export 'src/database/fluffybox_database.dart';
|
||||||
export 'src/event.dart';
|
export 'src/event.dart';
|
||||||
|
export 'src/presence.dart';
|
||||||
export 'src/event_status.dart';
|
export 'src/event_status.dart';
|
||||||
export 'src/voip.dart';
|
export 'src/voip.dart';
|
||||||
export 'src/voip_content.dart';
|
export 'src/voip_content.dart';
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ class Client extends MatrixApi {
|
||||||
Map<String, BasicEvent> get accountData => _accountData;
|
Map<String, BasicEvent> get accountData => _accountData;
|
||||||
|
|
||||||
/// Presences of users by a given matrix ID
|
/// Presences of users by a given matrix ID
|
||||||
Map<String, Presence> presences = {};
|
Map<String, CachedPresence> presences = {};
|
||||||
|
|
||||||
int _transactionCounter = 0;
|
int _transactionCounter = 0;
|
||||||
|
|
||||||
|
|
@ -889,8 +889,14 @@ class Client extends MatrixApi {
|
||||||
StreamController.broadcast();
|
StreamController.broadcast();
|
||||||
|
|
||||||
/// Callback will be called on presences.
|
/// Callback will be called on presences.
|
||||||
|
@Deprecated(
|
||||||
|
'Deprecated, use onPresenceChanged instead which has a timestamp.')
|
||||||
final StreamController<Presence> onPresence = StreamController.broadcast();
|
final StreamController<Presence> onPresence = StreamController.broadcast();
|
||||||
|
|
||||||
|
/// Callback will be called on presence updates.
|
||||||
|
final StreamController<CachedPresence> onPresenceChanged =
|
||||||
|
StreamController.broadcast();
|
||||||
|
|
||||||
/// Callback will be called on account data updates.
|
/// Callback will be called on account data updates.
|
||||||
final StreamController<BasicEvent> onAccountData =
|
final StreamController<BasicEvent> onAccountData =
|
||||||
StreamController.broadcast();
|
StreamController.broadcast();
|
||||||
|
|
@ -1467,8 +1473,11 @@ class Client extends MatrixApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (final newPresence in sync.presence ?? []) {
|
for (final newPresence in sync.presence ?? []) {
|
||||||
presences[newPresence.senderId] = newPresence;
|
final cachedPresence = CachedPresence.fromMatrixEvent(newPresence);
|
||||||
|
presences[newPresence.senderId] = cachedPresence;
|
||||||
|
// ignore: deprecated_member_use_from_same_package
|
||||||
onPresence.add(newPresence);
|
onPresence.add(newPresence);
|
||||||
|
onPresenceChanged.add(cachedPresence);
|
||||||
}
|
}
|
||||||
for (final newAccountData in sync.accountData ?? []) {
|
for (final newAccountData in sync.accountData ?? []) {
|
||||||
await database?.storeAccountData(
|
await database?.storeAccountData(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Famedly Matrix SDK
|
||||||
|
* Copyright (C) 2019, 2020, 2021 Famedly GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import '../matrix.dart';
|
||||||
|
|
||||||
|
class CachedPresence {
|
||||||
|
PresenceType presence;
|
||||||
|
DateTime? lastActiveTimestamp;
|
||||||
|
String? statusMsg;
|
||||||
|
bool? currentlyActive;
|
||||||
|
String userid;
|
||||||
|
|
||||||
|
CachedPresence(this.presence, int? lastActiveAgo, this.statusMsg,
|
||||||
|
this.currentlyActive, this.userid) {
|
||||||
|
if (lastActiveAgo != null) {
|
||||||
|
lastActiveTimestamp =
|
||||||
|
DateTime.now().subtract(Duration(milliseconds: lastActiveAgo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedPresence.fromMatrixEvent(Presence event)
|
||||||
|
: this(
|
||||||
|
event.presence.presence,
|
||||||
|
event.presence.lastActiveAgo,
|
||||||
|
event.presence.statusMsg,
|
||||||
|
event.presence.currentlyActive,
|
||||||
|
event.senderId);
|
||||||
|
|
||||||
|
CachedPresence.fromPresenceResponse(GetPresenceResponse event, String userid)
|
||||||
|
: this(event.presence, event.lastActiveAgo, event.statusMsg,
|
||||||
|
event.currentlyActive, userid);
|
||||||
|
|
||||||
|
CachedPresence.neverSeen(String userid)
|
||||||
|
: presence = PresenceType.offline,
|
||||||
|
userid = userid;
|
||||||
|
|
||||||
|
Presence toPresence() {
|
||||||
|
final content = <String, dynamic>{
|
||||||
|
'presence': presence.toString(),
|
||||||
|
};
|
||||||
|
if (currentlyActive != null) content['currently_active'] = currentlyActive!;
|
||||||
|
if (lastActiveTimestamp != null) {
|
||||||
|
content['last_active_ago'] =
|
||||||
|
DateTime.now().difference(lastActiveTimestamp!).inMilliseconds;
|
||||||
|
}
|
||||||
|
if (statusMsg != null) content['status_msg'] = statusMsg!;
|
||||||
|
|
||||||
|
final json = {
|
||||||
|
'content': content,
|
||||||
|
'sender': '@example:localhost',
|
||||||
|
'type': 'm.presence'
|
||||||
|
};
|
||||||
|
|
||||||
|
return Presence.fromJson(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -158,7 +158,23 @@ class User extends Event {
|
||||||
);
|
);
|
||||||
|
|
||||||
/// The newest presence of this user if there is any and null if not.
|
/// The newest presence of this user if there is any and null if not.
|
||||||
Presence? get presence => room.client.presences[id];
|
@Deprecated('Deprecated in favour of currentPresence.')
|
||||||
|
Presence? get presence => room.client.presences[id]?.toPresence();
|
||||||
|
|
||||||
|
/// The newest presence of this user if there is any. Fetches it from the server if necessary or returns offline.
|
||||||
|
Future<CachedPresence> get currentPresence async {
|
||||||
|
final cachedPresence = room.client.presences[id];
|
||||||
|
if (cachedPresence != null) {
|
||||||
|
return cachedPresence;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final newPresence = await room.client.getPresence(id);
|
||||||
|
return CachedPresence.fromPresenceResponse(newPresence, id);
|
||||||
|
} catch (e) {
|
||||||
|
return CachedPresence.neverSeen(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the client is able to ban/unban this user.
|
/// Whether the client is able to ban/unban this user.
|
||||||
bool get canBan => room.canBan && powerLevel < room.ownPowerLevel;
|
bool get canBan => room.canBan && powerLevel < room.ownPowerLevel;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ void main() {
|
||||||
|
|
||||||
var presenceCounter = 0;
|
var presenceCounter = 0;
|
||||||
var accountDataCounter = 0;
|
var accountDataCounter = 0;
|
||||||
matrix.onPresence.stream.listen((Presence data) {
|
matrix.onPresenceChanged.stream.listen((CachedPresence data) {
|
||||||
presenceCounter++;
|
presenceCounter++;
|
||||||
});
|
});
|
||||||
matrix.onAccountData.stream.listen((BasicEvent data) {
|
matrix.onAccountData.stream.listen((BasicEvent data) {
|
||||||
|
|
@ -150,7 +150,7 @@ void main() {
|
||||||
expect(matrix.rooms.length, 2);
|
expect(matrix.rooms.length, 2);
|
||||||
expect(matrix.rooms[1].canonicalAlias,
|
expect(matrix.rooms[1].canonicalAlias,
|
||||||
"#famedlyContactDiscovery:${matrix.userID!.split(":")[1]}");
|
"#famedlyContactDiscovery:${matrix.userID!.split(":")[1]}");
|
||||||
expect(matrix.presences['@alice:example.com']?.presence.presence,
|
expect(matrix.presences['@alice:example.com']?.presence,
|
||||||
PresenceType.online);
|
PresenceType.online);
|
||||||
expect(presenceCounter, 1);
|
expect(presenceCounter, 1);
|
||||||
expect(accountDataCounter, 9);
|
expect(accountDataCounter, 9);
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ void main() {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
expect(user1.presence?.presence.presence, PresenceType.online);
|
expect((await user1.currentPresence).presence, PresenceType.online);
|
||||||
});
|
});
|
||||||
test('canBan', () async {
|
test('canBan', () async {
|
||||||
expect(user1.canBan, false);
|
expect(user1.canBan, false);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue