Implement online-status keep-alive
This commit is contained in:
parent
ab21717829
commit
59cd6bc07f
5 changed files with 32 additions and 18 deletions
|
@ -28,6 +28,11 @@ class UserApi {
|
||||||
final data = jsonDecode(response.body);
|
final data = jsonDecode(response.body);
|
||||||
return UserStatus.fromMap(data);
|
return UserStatus.fromMap(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> notifyOnlineInstance(ApiClient client) async {
|
||||||
|
final response = await client.post("/stats/instanceOnline/${client.authenticationData.secretMachineId.hashCode}");
|
||||||
|
ApiClient.checkResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
static Future<void> setStatus(ApiClient client, {required UserStatus status}) async {
|
static Future<void> setStatus(ApiClient client, {required UserStatus status}) async {
|
||||||
final pkginfo = await PackageInfo.fromPlatform();
|
final pkginfo = await PackageInfo.fromPlatform();
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:contacts_plus_plus/clients/messaging_client.dart';
|
|
||||||
import 'package:contacts_plus_plus/clients/notification_client.dart';
|
|
||||||
import 'package:contacts_plus_plus/clients/settings_client.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_phoenix/flutter_phoenix.dart';
|
import 'package:flutter_phoenix/flutter_phoenix.dart';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:contacts_plus_plus/apis/friend_api.dart';
|
import 'package:contacts_plus_plus/apis/friend_api.dart';
|
||||||
import 'package:contacts_plus_plus/apis/message_api.dart';
|
import 'package:contacts_plus_plus/apis/message_api.dart';
|
||||||
|
import 'package:contacts_plus_plus/apis/user_api.dart';
|
||||||
import 'package:contacts_plus_plus/clients/notification_client.dart';
|
import 'package:contacts_plus_plus/clients/notification_client.dart';
|
||||||
import 'package:contacts_plus_plus/models/authentication_data.dart';
|
import 'package:contacts_plus_plus/models/authentication_data.dart';
|
||||||
import 'package:contacts_plus_plus/models/friend.dart';
|
import 'package:contacts_plus_plus/models/friend.dart';
|
||||||
|
@ -57,6 +57,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
final Workmanager _workmanager = Workmanager();
|
final Workmanager _workmanager = Workmanager();
|
||||||
final NotificationClient _notificationClient;
|
final NotificationClient _notificationClient;
|
||||||
Friend? selectedFriend;
|
Friend? selectedFriend;
|
||||||
|
Timer? _notifyOnlineTimer;
|
||||||
Timer? _autoRefresh;
|
Timer? _autoRefresh;
|
||||||
Timer? _refreshTimeout;
|
Timer? _refreshTimeout;
|
||||||
int _attempts = 0;
|
int _attempts = 0;
|
||||||
|
@ -66,16 +67,24 @@ class MessagingClient extends ChangeNotifier {
|
||||||
|
|
||||||
String? get initStatus => _initStatus;
|
String? get initStatus => _initStatus;
|
||||||
|
|
||||||
|
bool get websocketConnected => _wsChannel != null;
|
||||||
|
|
||||||
MessagingClient({required ApiClient apiClient, required NotificationClient notificationClient})
|
MessagingClient({required ApiClient apiClient, required NotificationClient notificationClient})
|
||||||
: _apiClient = apiClient, _notificationClient = notificationClient {
|
: _apiClient = apiClient, _notificationClient = notificationClient {
|
||||||
refreshFriendsListWithErrorHandler();
|
refreshFriendsListWithErrorHandler();
|
||||||
start();
|
startWebsocket();
|
||||||
|
_notifyOnlineTimer = Timer.periodic(const Duration(seconds: 60), (timer) async {
|
||||||
|
// We should probably let the MessagingClient handle the entire state of USerStatus instead of mirroring like this
|
||||||
|
// but I don't feel like implementing that right now.
|
||||||
|
UserApi.setStatus(apiClient, status: await UserApi.getUserStatus(apiClient, userId: apiClient.userId));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_autoRefresh?.cancel();
|
_autoRefresh?.cancel();
|
||||||
_refreshTimeout?.cancel();
|
_refreshTimeout?.cancel();
|
||||||
|
_notifyOnlineTimer?.cancel();
|
||||||
_wsChannel?.close();
|
_wsChannel?.close();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
@ -116,16 +125,21 @@ class MessagingClient extends ChangeNotifier {
|
||||||
_friendsCache[friend.id] = friend;
|
_friendsCache[friend.id] = friend;
|
||||||
}
|
}
|
||||||
_sortedFriendsCache.clear();
|
_sortedFriendsCache.clear();
|
||||||
_sortedFriendsCache.addAll(friends.sorted((a, b) {
|
_sortedFriendsCache.addAll(friends);
|
||||||
|
_sortFriendsCache();
|
||||||
|
_initStatus = "";
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sortFriendsCache() {
|
||||||
|
_sortedFriendsCache.sort((a, b) {
|
||||||
var aVal = friendHasUnreads(a) ? -3 : 0;
|
var aVal = friendHasUnreads(a) ? -3 : 0;
|
||||||
var bVal = friendHasUnreads(b) ? -3 : 0;
|
var bVal = friendHasUnreads(b) ? -3 : 0;
|
||||||
|
|
||||||
aVal -= a.userStatus.lastStatusChange.compareTo(b.userStatus.lastStatusChange);
|
aVal -= a.userStatus.lastStatusChange.compareTo(b.userStatus.lastStatusChange);
|
||||||
aVal += a.userStatus.onlineStatus.compareTo(b.userStatus.onlineStatus) * 2;
|
aVal += a.userStatus.onlineStatus.compareTo(b.userStatus.onlineStatus) * 2;
|
||||||
return aVal.compareTo(bVal);
|
return aVal.compareTo(bVal);
|
||||||
}));
|
});
|
||||||
_initStatus = "";
|
|
||||||
notifyListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateAllUnreads(List<Message> messages) {
|
void updateAllUnreads(List<Message> messages) {
|
||||||
|
@ -151,6 +165,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
messages.add(message);
|
messages.add(message);
|
||||||
}
|
}
|
||||||
messages.sort();
|
messages.sort();
|
||||||
|
_sortFriendsCache();
|
||||||
_notificationClient.showUnreadMessagesNotification(messages.reversed);
|
_notificationClient.showUnreadMessagesNotification(messages.reversed);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -205,11 +220,12 @@ class MessagingClient extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onDisconnected(error) async {
|
void _onDisconnected(error) async {
|
||||||
|
_wsChannel = null;
|
||||||
_logger.warning("Neos Hub connection died with error '$error', reconnecting...");
|
_logger.warning("Neos Hub connection died with error '$error', reconnecting...");
|
||||||
await start();
|
await startWebsocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> start() async {
|
Future<void> startWebsocket() async {
|
||||||
if (!_apiClient.isAuthenticated) {
|
if (!_apiClient.isAuthenticated) {
|
||||||
_logger.info("Tried to connect to Neos Hub without authentication, this is probably fine for now.");
|
_logger.info("Tried to connect to Neos Hub without authentication, this is probably fine for now.");
|
||||||
return;
|
return;
|
||||||
|
@ -352,9 +368,4 @@ class MessagingClient extends ChangeNotifier {
|
||||||
};
|
};
|
||||||
_sendData(data);
|
_sendData(data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MessagesProvider extends ChangeNotifier {
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -72,7 +72,9 @@ class _ContactsPlusPlusState extends State<ContactsPlusPlus> {
|
||||||
ChangeNotifierProvider( // This doesn't need to be a proxy provider since the arguments should never change during it's lifetime.
|
ChangeNotifierProvider( // This doesn't need to be a proxy provider since the arguments should never change during it's lifetime.
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
MessagingClient(
|
MessagingClient(
|
||||||
apiClient: clientHolder.apiClient, notificationClient: clientHolder.notificationClient),
|
apiClient: clientHolder.apiClient,
|
||||||
|
notificationClient: clientHolder.notificationClient,
|
||||||
|
),
|
||||||
child: const FriendsList(),
|
child: const FriendsList(),
|
||||||
) :
|
) :
|
||||||
LoginScreen(
|
LoginScreen(
|
||||||
|
|
|
@ -4,7 +4,6 @@ import 'package:contacts_plus_plus/apis/user_api.dart';
|
||||||
import 'package:contacts_plus_plus/client_holder.dart';
|
import 'package:contacts_plus_plus/client_holder.dart';
|
||||||
import 'package:contacts_plus_plus/clients/messaging_client.dart';
|
import 'package:contacts_plus_plus/clients/messaging_client.dart';
|
||||||
import 'package:contacts_plus_plus/models/friend.dart';
|
import 'package:contacts_plus_plus/models/friend.dart';
|
||||||
import 'package:contacts_plus_plus/models/message.dart';
|
|
||||||
import 'package:contacts_plus_plus/models/personal_profile.dart';
|
import 'package:contacts_plus_plus/models/personal_profile.dart';
|
||||||
import 'package:contacts_plus_plus/widgets/default_error_widget.dart';
|
import 'package:contacts_plus_plus/widgets/default_error_widget.dart';
|
||||||
import 'package:contacts_plus_plus/widgets/expanding_input_fab.dart';
|
import 'package:contacts_plus_plus/widgets/expanding_input_fab.dart';
|
||||||
|
|
Loading…
Reference in a new issue