From fcd34d4fb1f1930f4bab8be2aa0ad26fb04fc016 Mon Sep 17 00:00:00 2001 From: Nutcake Date: Thu, 12 Oct 2023 18:01:15 +0200 Subject: [PATCH] Fix online status not getting set correctly Closes #6 --- lib/apis/record_api.dart | 7 +++++++ lib/clients/messaging_client.dart | 18 +++++++++++++----- lib/hub_manager.dart | 4 ++-- lib/models/authentication_data.dart | 1 - lib/models/users/user_status.dart | 18 +++++++++++++++--- lib/widgets/friends/friends_list_app_bar.dart | 3 ++- .../inventory/inventory_browser_app_bar.dart | 1 - pubspec.lock | 2 +- pubspec.yaml | 3 +-- 9 files changed, 41 insertions(+), 16 deletions(-) diff --git a/lib/apis/record_api.dart b/lib/apis/record_api.dart index 36fad6f..dbb1761 100644 --- a/lib/apis/record_api.dart +++ b/lib/apis/record_api.dart @@ -31,6 +31,13 @@ class RecordApi { return body.map((e) => Record.fromMap(e)).toList(); } + static Future> getGroupRecordsAt(ApiClient client, {required String path, required String groupId}) async { + final response = await client.get("/users/$groupId/records?path=$path"); + client.checkResponse(response); + final body = jsonDecode(response.body) as List; + return body.map((e) => Record.fromMap(e)).toList(); + } + static Future deleteRecord(ApiClient client, {required String recordId}) async { final response = await client.delete("/users/${client.userId}/records/$recordId"); client.checkResponse(response); diff --git a/lib/clients/messaging_client.dart b/lib/clients/messaging_client.dart index 19b6181..fc53a8d 100644 --- a/lib/clients/messaging_client.dart +++ b/lib/clients/messaging_client.dart @@ -24,6 +24,7 @@ import 'package:package_info_plus/package_info_plus.dart'; class MessagingClient extends ChangeNotifier { static const Duration _autoRefreshDuration = Duration(seconds: 10); static const Duration _unreadSafeguardDuration = Duration(seconds: 120); + static const Duration _statusHeartbeatDuration = Duration(seconds: 150); static const String _messageBoxKey = "message-box"; static const String _lastUpdateKey = "__last-update-time"; @@ -38,7 +39,7 @@ class MessagingClient extends ChangeNotifier { final Set _knownSessionKeys = {}; Friend? selectedFriend; - Timer? _notifyOnlineTimer; + Timer? _statusHeartbeat; Timer? _autoRefresh; Timer? _unreadSafeguard; String? _initStatus; @@ -62,7 +63,7 @@ class MessagingClient extends ChangeNotifier { void dispose() { debugPrint("mClient disposed: $hashCode"); _autoRefresh?.cancel(); - _notifyOnlineTimer?.cancel(); + _statusHeartbeat?.cancel(); _unreadSafeguard?.cancel(); _hubManager.dispose(); super.dispose(); @@ -117,6 +118,7 @@ class MessagingClient extends ChangeNotifier { } void markMessagesRead(MarkReadBatch batch) { + if (_userStatus.onlineStatus == OnlineStatus.invisible || _userStatus.onlineStatus == OnlineStatus.offline) return; final msgBody = batch.toMap(); _hubManager.send("MarkMessagesRead", arguments: [msgBody]); clearUnreadsForUser(batch.senderId); @@ -124,11 +126,14 @@ class MessagingClient extends ChangeNotifier { Future setOnlineStatus(OnlineStatus status) async { final pkginfo = await PackageInfo.fromPlatform(); - + final now = DateTime.now(); _userStatus = _userStatus.copyWith( + userId: _apiClient.userId, appVersion: "${pkginfo.version} of ${pkginfo.appName}", - lastStatusChange: DateTime.now(), + lastPresenceTimestamp: now, + lastStatusChange: now, onlineStatus: status, + isPresent: true, ); _hubManager.send( @@ -258,7 +263,6 @@ class MessagingClient extends ChangeNotifier { _hubManager.setHandler(EventTarget.removeSession, _onRemoveSession); await _hubManager.start(); - await setOnlineStatus(OnlineStatus.online); _hubManager.send( "InitializeStatus", responseHandler: (Map data) async { @@ -272,6 +276,10 @@ class MessagingClient extends ChangeNotifier { await _refreshUnreads(); _unreadSafeguard = Timer.periodic(_unreadSafeguardDuration, (timer) => _refreshUnreads()); _hubManager.send("RequestStatus", arguments: [null, false]); + await setOnlineStatus(OnlineStatus.online); + _statusHeartbeat = Timer.periodic(_statusHeartbeatDuration, (timer) { + setOnlineStatus(_userStatus.onlineStatus); + }); }, ); } diff --git a/lib/hub_manager.dart b/lib/hub_manager.dart index 7b2c0cc..0b8333c 100644 --- a/lib/hub_manager.dart +++ b/lib/hub_manager.dart @@ -107,10 +107,10 @@ class HubManager { void _handleInvocation(body) async { final target = EventTarget.parse(body["target"]); final args = body["arguments"] ?? []; - if (kDebugMode) _logger.info("Invocation target: ${target.name}, args:\n$args"); final handler = _handlers[target]; if (handler == null) { - _logger.info("Unhandled event received"); + _logger.warning("Unhandled event received"); + if (kDebugMode) _logger.warning("Invocation target: ${target.name}, args:\n$args"); return; } handler(args); diff --git a/lib/models/authentication_data.dart b/lib/models/authentication_data.dart index 76ca47d..8aa18a9 100644 --- a/lib/models/authentication_data.dart +++ b/lib/models/authentication_data.dart @@ -36,7 +36,6 @@ class AuthenticationData { Map get authorizationHeader => { "Authorization": "res $userId:$token", - "UID": uid, }; Map toMap() { diff --git a/lib/models/users/user_status.dart b/lib/models/users/user_status.dart index 94ac818..3f1f76d 100644 --- a/lib/models/users/user_status.dart +++ b/lib/models/users/user_status.dart @@ -1,3 +1,5 @@ +import 'package:intl/intl.dart'; +import 'package:recon/config.dart'; import 'package:recon/crypto_helper.dart'; import 'package:recon/models/session.dart'; import 'package:recon/models/session_metadata.dart'; @@ -10,7 +12,7 @@ enum UserSessionType graphicalClient, chatClient, headless, - not; + bot; factory UserSessionType.fromString(String? text) { return UserSessionType.values.firstWhere((element) => element.name.toLowerCase() == text?.toLowerCase(), @@ -20,6 +22,7 @@ enum UserSessionType } class UserStatus { + final String userId; final OnlineStatus onlineStatus; final DateTime lastStatusChange; final DateTime lastPresenceTimestamp; @@ -36,6 +39,7 @@ class UserStatus { final List decodedSessions; const UserStatus({ + required this.userId, required this.onlineStatus, required this.lastStatusChange, required this.lastPresenceTimestamp, @@ -54,15 +58,18 @@ class UserStatus { factory UserStatus.initial() => UserStatus.empty().copyWith( + compatibilityHash: Config.latestCompatHash, onlineStatus: OnlineStatus.online, hashSalt: CryptoHelper.cryptoToken(), - outputDevice: "Screen", + outputDevice: "Unknown", userSessionId: const Uuid().v4().toString(), sessionType: UserSessionType.chatClient, + isPresent: true, ); factory UserStatus.empty() => UserStatus( + userId: "", onlineStatus: OnlineStatus.offline, lastStatusChange: DateTime.now(), lastPresenceTimestamp: DateTime.now(), @@ -82,6 +89,7 @@ class UserStatus { final statusString = map["onlineStatus"].toString(); final status = OnlineStatus.fromString(statusString); return UserStatus( + userId: map["userId"] ?? "", onlineStatus: status, lastStatusChange: DateTime.tryParse(map["lastStatusChange"] ?? "") ?? DateTime.now(), lastPresenceTimestamp: DateTime.tryParse(map["lastPresenceTimestamp"] ?? "") ?? DateTime.now(), @@ -92,7 +100,7 @@ class UserStatus { appVersion: map["appVersion"] ?? "", outputDevice: map["outputDevice"] ?? "Unknown", isMobile: map["isMobile"] ?? false, - compatibilityHash: map["compatabilityHash"] ?? "", + compatibilityHash: map["compatibilityHash"] ?? "", hashSalt: map["hashSalt"] ?? "", sessionType: UserSessionType.fromString(map["sessionType"]) ); @@ -100,6 +108,7 @@ class UserStatus { Map toMap({bool shallow = false}) { return { + "userId": userId, "onlineStatus": onlineStatus.index, "lastStatusChange": lastStatusChange.toIso8601String(), "isPresent": isPresent, @@ -117,10 +126,12 @@ class UserStatus { "outputDevice": outputDevice, "isMobile": isMobile, "compatibilityHash": compatibilityHash, + "sessionType": toBeginningOfSentenceCase(sessionType.name) }; } UserStatus copyWith({ + String? userId, OnlineStatus? onlineStatus, DateTime? lastStatusChange, DateTime? lastPresenceTimestamp, @@ -137,6 +148,7 @@ class UserStatus { List? decodedSessions, }) => UserStatus( + userId: userId ?? this.userId, onlineStatus: onlineStatus ?? this.onlineStatus, lastStatusChange: lastStatusChange ?? this.lastStatusChange, lastPresenceTimestamp: lastPresenceTimestamp ?? this.lastPresenceTimestamp, diff --git a/lib/widgets/friends/friends_list_app_bar.dart b/lib/widgets/friends/friends_list_app_bar.dart index 91fc964..fbee120 100644 --- a/lib/widgets/friends/friends_list_app_bar.dart +++ b/lib/widgets/friends/friends_list_app_bar.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart'; import 'package:recon/client_holder.dart'; import 'package:recon/clients/messaging_client.dart'; import 'package:recon/models/users/online_status.dart'; @@ -52,7 +53,7 @@ class _FriendsListAppBarState extends State with AutomaticKee } }, itemBuilder: (BuildContext context) => OnlineStatus.values - .where((element) => element == OnlineStatus.online || element == OnlineStatus.invisible) + .where((element) => element == OnlineStatus.online || element == OnlineStatus.offline).sorted((a, b) => b.index.compareTo(a.index),) .map( (item) => PopupMenuItem( value: item, diff --git a/lib/widgets/inventory/inventory_browser_app_bar.dart b/lib/widgets/inventory/inventory_browser_app_bar.dart index 472181d..f98d55f 100644 --- a/lib/widgets/inventory/inventory_browser_app_bar.dart +++ b/lib/widgets/inventory/inventory_browser_app_bar.dart @@ -5,7 +5,6 @@ import 'package:recon/auxiliary.dart'; import 'package:recon/clients/inventory_client.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:path/path.dart'; import 'package:provider/provider.dart'; diff --git a/pubspec.lock b/pubspec.lock index 89ee28b..a869643 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -926,7 +926,7 @@ packages: source: hosted version: "3.0.7" vector_math: - dependency: "direct main" + dependency: transitive description: name: vector_math sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" diff --git a/pubspec.yaml b/pubspec.yaml index 8c362c5..4e2a09d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.9.0+1 +version: 0.9.1+1 environment: sdk: '>=3.0.1' @@ -63,7 +63,6 @@ dependencies: permission_handler: ^10.2.0 flutter_downloader: ^1.10.4 flutter_cube: ^0.1.1 - vector_math: ^2.1.4 dev_dependencies: flutter_test: