Fix user session status not showing
This commit is contained in:
parent
56ed403d79
commit
bace94b6d2
9 changed files with 130 additions and 100 deletions
|
@ -1,51 +1,23 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:contacts_plus_plus/apis/session_api.dart';
|
|
||||||
|
import 'package:contacts_plus_plus/apis/contact_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/api_client.dart';
|
||||||
|
import 'package:contacts_plus_plus/clients/notification_client.dart';
|
||||||
import 'package:contacts_plus_plus/crypto_helper.dart';
|
import 'package:contacts_plus_plus/crypto_helper.dart';
|
||||||
import 'package:contacts_plus_plus/hub_manager.dart';
|
import 'package:contacts_plus_plus/hub_manager.dart';
|
||||||
|
import 'package:contacts_plus_plus/models/hub_events.dart';
|
||||||
|
import 'package:contacts_plus_plus/models/message.dart';
|
||||||
import 'package:contacts_plus_plus/models/session.dart';
|
import 'package:contacts_plus_plus/models/session.dart';
|
||||||
|
import 'package:contacts_plus_plus/models/users/friend.dart';
|
||||||
import 'package:contacts_plus_plus/models/users/user_status.dart';
|
import 'package:contacts_plus_plus/models/users/user_status.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import 'package:contacts_plus_plus/apis/contact_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/models/users/friend.dart';
|
|
||||||
import 'package:contacts_plus_plus/clients/api_client.dart';
|
|
||||||
import 'package:contacts_plus_plus/models/message.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
enum EventType {
|
|
||||||
undefined,
|
|
||||||
invocation,
|
|
||||||
streamItem,
|
|
||||||
completion,
|
|
||||||
streamInvocation,
|
|
||||||
cancelInvocation,
|
|
||||||
ping,
|
|
||||||
close;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EventTarget {
|
|
||||||
unknown,
|
|
||||||
messageSent,
|
|
||||||
receiveMessage,
|
|
||||||
messagesRead,
|
|
||||||
receiveSessionUpdate,
|
|
||||||
removeSession,
|
|
||||||
receiveStatusUpdate;
|
|
||||||
|
|
||||||
factory EventTarget.parse(String? text) {
|
|
||||||
if (text == null) return EventTarget.unknown;
|
|
||||||
return EventTarget.values.firstWhere(
|
|
||||||
(element) => element.name.toLowerCase() == text.toLowerCase(),
|
|
||||||
orElse: () => EventTarget.unknown,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessagingClient extends ChangeNotifier {
|
class MessagingClient extends ChangeNotifier {
|
||||||
static const Duration _autoRefreshDuration = Duration(seconds: 10);
|
static const Duration _autoRefreshDuration = Duration(seconds: 10);
|
||||||
|
@ -77,11 +49,6 @@ class MessagingClient extends ChangeNotifier {
|
||||||
debugPrint("mClient created: $hashCode");
|
debugPrint("mClient created: $hashCode");
|
||||||
Hive.openBox(_messageBoxKey).then((box) async {
|
Hive.openBox(_messageBoxKey).then((box) async {
|
||||||
await box.delete(_lastUpdateKey);
|
await box.delete(_lastUpdateKey);
|
||||||
final activeSessions = await SessionApi.getSessions(apiClient);
|
|
||||||
for (final session in activeSessions) {
|
|
||||||
final idHash = CryptoHelper.idHash(session.id + _userStatus.hashSalt);
|
|
||||||
_sessionMap[idHash] = session;
|
|
||||||
}
|
|
||||||
_setupHub();
|
_setupHub();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -113,8 +80,6 @@ class MessagingClient extends ChangeNotifier {
|
||||||
|
|
||||||
MessageCache _createUserMessageCache(String userId) => MessageCache(apiClient: _apiClient, userId: userId);
|
MessageCache _createUserMessageCache(String userId) => MessageCache(apiClient: _apiClient, userId: userId);
|
||||||
|
|
||||||
Session? getSessionInfo(String idHash) => _sessionMap[idHash];
|
|
||||||
|
|
||||||
Future<void> refreshFriendsListWithErrorHandler() async {
|
Future<void> refreshFriendsListWithErrorHandler() async {
|
||||||
try {
|
try {
|
||||||
await refreshFriendsList();
|
await refreshFriendsList();
|
||||||
|
@ -155,9 +120,10 @@ class MessagingClient extends ChangeNotifier {
|
||||||
Future<void> setUserStatus(UserStatus status) async {
|
Future<void> setUserStatus(UserStatus status) async {
|
||||||
final pkginfo = await PackageInfo.fromPlatform();
|
final pkginfo = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
_userStatus = status.copyWith(
|
_userStatus = _userStatus.copyWith(
|
||||||
appVersion: "${pkginfo.version} of ${pkginfo.appName}",
|
appVersion: "${pkginfo.version} of ${pkginfo.appName}",
|
||||||
lastStatusChange: DateTime.now(),
|
lastStatusChange: DateTime.now(),
|
||||||
|
onlineStatus: status.onlineStatus,
|
||||||
);
|
);
|
||||||
|
|
||||||
_hubManager.send(
|
_hubManager.send(
|
||||||
|
@ -165,14 +131,16 @@ class MessagingClient extends ChangeNotifier {
|
||||||
arguments: [
|
arguments: [
|
||||||
_userStatus.toMap(),
|
_userStatus.toMap(),
|
||||||
{
|
{
|
||||||
"group": 0,
|
"group": 1,
|
||||||
"targetIds": [],
|
"targetIds": null,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final self = getAsFriend(_apiClient.userId);
|
final self = getAsFriend(_apiClient.userId);
|
||||||
await _updateContact(self!.copyWith(userStatus: _userStatus));
|
if (self != null) {
|
||||||
|
await _updateContact(self.copyWith(userStatus: _userStatus));
|
||||||
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +252,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
_hubManager.setHandler(EventTarget.receiveSessionUpdate, _onReceiveSessionUpdate);
|
_hubManager.setHandler(EventTarget.receiveSessionUpdate, _onReceiveSessionUpdate);
|
||||||
|
|
||||||
await _hubManager.start();
|
await _hubManager.start();
|
||||||
setUserStatus(userStatus);
|
await setUserStatus(userStatus);
|
||||||
_hubManager.send(
|
_hubManager.send(
|
||||||
"InitializeStatus",
|
"InitializeStatus",
|
||||||
responseHandler: (Map data) async {
|
responseHandler: (Map data) async {
|
||||||
|
@ -302,6 +270,10 @@ class MessagingClient extends ChangeNotifier {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, Session> createSessionMap(String salt) {
|
||||||
|
return _sessionMap.map((key, value) => MapEntry(CryptoHelper.idHash(value.id + salt), value));
|
||||||
|
}
|
||||||
|
|
||||||
void _onMessageSent(List args) {
|
void _onMessageSent(List args) {
|
||||||
final msg = args[0];
|
final msg = args[0];
|
||||||
final message = Message.fromMap(msg, withState: MessageState.sent);
|
final message = Message.fromMap(msg, withState: MessageState.sent);
|
||||||
|
@ -338,9 +310,11 @@ class MessagingClient extends ChangeNotifier {
|
||||||
|
|
||||||
void _onReceiveStatusUpdate(List args) {
|
void _onReceiveStatusUpdate(List args) {
|
||||||
for (final statusUpdate in args) {
|
for (final statusUpdate in args) {
|
||||||
final status = UserStatus.fromMap(statusUpdate);
|
var status = UserStatus.fromMap(statusUpdate);
|
||||||
var friend = getAsFriend(statusUpdate["userId"]);
|
final sessionMap = createSessionMap(status.hashSalt);
|
||||||
friend = friend?.copyWith(userStatus: status);
|
status = status.copyWith(
|
||||||
|
sessionData: status.sessions.map((e) => sessionMap[e.sessionHash] ?? Session.none()).toList());
|
||||||
|
final friend = getAsFriend(statusUpdate["userId"])?.copyWith(userStatus: status);
|
||||||
if (friend != null) {
|
if (friend != null) {
|
||||||
_updateContact(friend);
|
_updateContact(friend);
|
||||||
}
|
}
|
||||||
|
@ -351,8 +325,7 @@ class MessagingClient extends ChangeNotifier {
|
||||||
void _onReceiveSessionUpdate(List args) {
|
void _onReceiveSessionUpdate(List args) {
|
||||||
for (final sessionUpdate in args) {
|
for (final sessionUpdate in args) {
|
||||||
final session = Session.fromMap(sessionUpdate);
|
final session = Session.fromMap(sessionUpdate);
|
||||||
final idHash = CryptoHelper.idHash(session.id + _userStatus.hashSalt);
|
_sessionMap[session.id] = session;
|
||||||
_sessionMap[idHash] = session;
|
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ class Config {
|
||||||
|
|
||||||
static const int messageCacheValiditySeconds = 90;
|
static const int messageCacheValiditySeconds = 90;
|
||||||
|
|
||||||
static const String latestCompatHash = "jnnkdwkBqGv5+jlf1u/k7A==";
|
static const String latestCompatHash = "YPDxN4N9fu7ZgV+Nr/AHQw==";
|
||||||
}
|
}
|
|
@ -2,8 +2,8 @@ import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:contacts_plus_plus/clients/messaging_client.dart';
|
|
||||||
import 'package:contacts_plus_plus/config.dart';
|
import 'package:contacts_plus_plus/config.dart';
|
||||||
|
import 'package:contacts_plus_plus/models/hub_events.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ class HubManager {
|
||||||
case EventType.completion:
|
case EventType.completion:
|
||||||
final handler = _responseHandlers[body["invocationId"]];
|
final handler = _responseHandlers[body["invocationId"]];
|
||||||
handler?.call(body["result"] ?? {});
|
handler?.call(body["result"] ?? {});
|
||||||
|
_logger.info("Received completion event: $rawType: $body");
|
||||||
break;
|
break;
|
||||||
case EventType.cancelInvocation:
|
case EventType.cancelInvocation:
|
||||||
case EventType.undefined:
|
case EventType.undefined:
|
||||||
|
|
28
lib/models/hub_events.dart
Normal file
28
lib/models/hub_events.dart
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
enum EventType {
|
||||||
|
undefined,
|
||||||
|
invocation,
|
||||||
|
streamItem,
|
||||||
|
completion,
|
||||||
|
streamInvocation,
|
||||||
|
cancelInvocation,
|
||||||
|
ping,
|
||||||
|
close;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EventTarget {
|
||||||
|
unknown,
|
||||||
|
messageSent,
|
||||||
|
receiveMessage,
|
||||||
|
messagesRead,
|
||||||
|
receiveSessionUpdate,
|
||||||
|
removeSession,
|
||||||
|
receiveStatusUpdate;
|
||||||
|
|
||||||
|
factory EventTarget.parse(String? text) {
|
||||||
|
if (text == null) return EventTarget.unknown;
|
||||||
|
return EventTarget.values.firstWhere(
|
||||||
|
(element) => element.name.toLowerCase() == text.toLowerCase(),
|
||||||
|
orElse: () => EventTarget.unknown,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -101,6 +101,7 @@ enum SessionAccessLevel {
|
||||||
private,
|
private,
|
||||||
contacts,
|
contacts,
|
||||||
contactsPlus,
|
contactsPlus,
|
||||||
|
registeredUsers,
|
||||||
anyone;
|
anyone;
|
||||||
|
|
||||||
static const _readableNamesMap = {
|
static const _readableNamesMap = {
|
||||||
|
@ -108,6 +109,7 @@ enum SessionAccessLevel {
|
||||||
SessionAccessLevel.private: "Private",
|
SessionAccessLevel.private: "Private",
|
||||||
SessionAccessLevel.contacts: "Contacts",
|
SessionAccessLevel.contacts: "Contacts",
|
||||||
SessionAccessLevel.contactsPlus: "Contacts+",
|
SessionAccessLevel.contactsPlus: "Contacts+",
|
||||||
|
SessionAccessLevel.registeredUsers: "Registered users",
|
||||||
SessionAccessLevel.anyone: "Anyone",
|
SessionAccessLevel.anyone: "Anyone",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +121,7 @@ enum SessionAccessLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
String toReadableString() {
|
String toReadableString() {
|
||||||
return SessionAccessLevel._readableNamesMap[this] ?? "Unknown";
|
return SessionAccessLevel._readableNamesMap[this] ?? SessionAccessLevel.unknown.toReadableString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,81 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:contacts_plus_plus/crypto_helper.dart';
|
import 'package:contacts_plus_plus/crypto_helper.dart';
|
||||||
|
import 'package:contacts_plus_plus/models/session.dart';
|
||||||
import 'package:contacts_plus_plus/models/session_metadata.dart';
|
import 'package:contacts_plus_plus/models/session_metadata.dart';
|
||||||
import 'package:contacts_plus_plus/models/users/online_status.dart';
|
import 'package:contacts_plus_plus/models/users/online_status.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
|
enum UserSessionType
|
||||||
|
{
|
||||||
|
unknown,
|
||||||
|
graphicalClient,
|
||||||
|
chatClient,
|
||||||
|
headless,
|
||||||
|
not;
|
||||||
|
|
||||||
|
factory UserSessionType.fromString(String? text) {
|
||||||
|
return UserSessionType.values.firstWhere((element) => element.name.toLowerCase() == text?.toLowerCase(),
|
||||||
|
orElse: () => UserSessionType.unknown,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class UserStatus {
|
class UserStatus {
|
||||||
final OnlineStatus onlineStatus;
|
final OnlineStatus onlineStatus;
|
||||||
final DateTime lastStatusChange;
|
final DateTime lastStatusChange;
|
||||||
final int currentSessionAccessLevel;
|
final DateTime lastPresenceTimestamp;
|
||||||
final bool currentSessionHidden;
|
final String userSessionId;
|
||||||
final bool currentHosting;
|
|
||||||
final int currentSessionIndex;
|
final int currentSessionIndex;
|
||||||
final List<SessionMetadata> sessions;
|
final List<SessionMetadata> sessions;
|
||||||
final String appVersion;
|
final String appVersion;
|
||||||
final String outputDevice;
|
final String outputDevice;
|
||||||
final bool isMobile;
|
final bool isMobile;
|
||||||
|
final bool isPresent;
|
||||||
final String compatibilityHash;
|
final String compatibilityHash;
|
||||||
final String hashSalt;
|
final String hashSalt;
|
||||||
|
final UserSessionType sessionType;
|
||||||
|
final List<Session> decodedSessions;
|
||||||
|
|
||||||
const UserStatus({
|
const UserStatus({
|
||||||
required this.onlineStatus,
|
required this.onlineStatus,
|
||||||
required this.lastStatusChange,
|
required this.lastStatusChange,
|
||||||
|
required this.lastPresenceTimestamp,
|
||||||
|
required this.userSessionId,
|
||||||
required this.currentSessionIndex,
|
required this.currentSessionIndex,
|
||||||
required this.currentSessionAccessLevel,
|
|
||||||
required this.currentSessionHidden,
|
|
||||||
required this.currentHosting,
|
|
||||||
required this.sessions,
|
required this.sessions,
|
||||||
required this.appVersion,
|
required this.appVersion,
|
||||||
required this.outputDevice,
|
required this.outputDevice,
|
||||||
required this.isMobile,
|
required this.isMobile,
|
||||||
|
required this.isPresent,
|
||||||
required this.compatibilityHash,
|
required this.compatibilityHash,
|
||||||
required this.hashSalt,
|
required this.hashSalt,
|
||||||
|
required this.sessionType,
|
||||||
|
this.decodedSessions = const []
|
||||||
});
|
});
|
||||||
|
|
||||||
factory UserStatus.initial() => UserStatus.empty().copyWith(
|
factory UserStatus.initial() =>
|
||||||
|
UserStatus.empty().copyWith(
|
||||||
onlineStatus: OnlineStatus.online,
|
onlineStatus: OnlineStatus.online,
|
||||||
hashSalt: CryptoHelper.cryptoToken(),
|
hashSalt: CryptoHelper.cryptoToken(),
|
||||||
outputDevice: "Mobile",
|
outputDevice: "Mobile",
|
||||||
|
userSessionId: const Uuid().v4().toString(),
|
||||||
|
sessionType: UserSessionType.chatClient,
|
||||||
);
|
);
|
||||||
|
|
||||||
factory UserStatus.empty() => UserStatus(
|
factory UserStatus.empty() =>
|
||||||
|
UserStatus(
|
||||||
onlineStatus: OnlineStatus.offline,
|
onlineStatus: OnlineStatus.offline,
|
||||||
lastStatusChange: DateTime.now(),
|
lastStatusChange: DateTime.now(),
|
||||||
currentSessionAccessLevel: 0,
|
lastPresenceTimestamp: DateTime.now(),
|
||||||
currentSessionHidden: false,
|
userSessionId: "",
|
||||||
currentHosting: false,
|
|
||||||
currentSessionIndex: -1,
|
currentSessionIndex: -1,
|
||||||
sessions: [],
|
sessions: [],
|
||||||
appVersion: "",
|
appVersion: "",
|
||||||
outputDevice: "Unknown",
|
outputDevice: "Unknown",
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
|
isPresent: false,
|
||||||
compatibilityHash: "",
|
compatibilityHash: "",
|
||||||
hashSalt: "",
|
hashSalt: "",
|
||||||
|
sessionType: UserSessionType.unknown
|
||||||
);
|
);
|
||||||
|
|
||||||
factory UserStatus.fromMap(Map map) {
|
factory UserStatus.fromMap(Map map) {
|
||||||
|
@ -60,10 +83,10 @@ class UserStatus {
|
||||||
final status = OnlineStatus.fromString(statusString);
|
final status = OnlineStatus.fromString(statusString);
|
||||||
return UserStatus(
|
return UserStatus(
|
||||||
onlineStatus: status,
|
onlineStatus: status,
|
||||||
lastStatusChange: DateTime.parse(map["lastStatusChange"]),
|
lastStatusChange: DateTime.tryParse(map["lastStatusChange"] ?? "") ?? DateTime.now(),
|
||||||
currentSessionAccessLevel: map["currentSessionAccessLevel"] ?? 0,
|
lastPresenceTimestamp: DateTime.tryParse(map["lastPresenceTimestamp"] ?? "") ?? DateTime.now(),
|
||||||
currentSessionHidden: map["currentSessionHidden"] ?? false,
|
userSessionId: map["userSessionId"] ?? "",
|
||||||
currentHosting: map["currentHosting"] ?? false,
|
isPresent: map["isPresent"] ?? false,
|
||||||
currentSessionIndex: map["currentSessionIndex"] ?? -1,
|
currentSessionIndex: map["currentSessionIndex"] ?? -1,
|
||||||
sessions: (map["sessions"] as List? ?? []).map((e) => SessionMetadata.fromMap(e)).toList(),
|
sessions: (map["sessions"] as List? ?? []).map((e) => SessionMetadata.fromMap(e)).toList(),
|
||||||
appVersion: map["appVersion"] ?? "",
|
appVersion: map["appVersion"] ?? "",
|
||||||
|
@ -71,6 +94,7 @@ class UserStatus {
|
||||||
isMobile: map["isMobile"] ?? false,
|
isMobile: map["isMobile"] ?? false,
|
||||||
compatibilityHash: map["compatabilityHash"] ?? "",
|
compatibilityHash: map["compatabilityHash"] ?? "",
|
||||||
hashSalt: map["hashSalt"] ?? "",
|
hashSalt: map["hashSalt"] ?? "",
|
||||||
|
sessionType: UserSessionType.fromString(map["sessionType"])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +102,9 @@ class UserStatus {
|
||||||
return {
|
return {
|
||||||
"onlineStatus": onlineStatus.index,
|
"onlineStatus": onlineStatus.index,
|
||||||
"lastStatusChange": lastStatusChange.toIso8601String(),
|
"lastStatusChange": lastStatusChange.toIso8601String(),
|
||||||
"currentSessionAccessLevel": currentSessionAccessLevel,
|
"isPresent": isPresent,
|
||||||
"currentSessionHidden": currentSessionHidden,
|
"lastPresenceTimestamp": lastPresenceTimestamp.toIso8601String(),
|
||||||
"currentHosting": currentHosting,
|
"userSessionId": userSessionId,
|
||||||
"currentSessionIndex": currentSessionIndex,
|
"currentSessionIndex": currentSessionIndex,
|
||||||
"sessions": shallow
|
"sessions": shallow
|
||||||
? []
|
? []
|
||||||
|
@ -99,9 +123,9 @@ class UserStatus {
|
||||||
UserStatus copyWith({
|
UserStatus copyWith({
|
||||||
OnlineStatus? onlineStatus,
|
OnlineStatus? onlineStatus,
|
||||||
DateTime? lastStatusChange,
|
DateTime? lastStatusChange,
|
||||||
int? currentSessionAccessLevel,
|
DateTime? lastPresenceTimestamp,
|
||||||
bool? currentSessionHidden,
|
bool? isPresent,
|
||||||
bool? currentHosting,
|
String? userSessionId,
|
||||||
int? currentSessionIndex,
|
int? currentSessionIndex,
|
||||||
List<SessionMetadata>? sessions,
|
List<SessionMetadata>? sessions,
|
||||||
String? appVersion,
|
String? appVersion,
|
||||||
|
@ -109,13 +133,15 @@ class UserStatus {
|
||||||
bool? isMobile,
|
bool? isMobile,
|
||||||
String? compatibilityHash,
|
String? compatibilityHash,
|
||||||
String? hashSalt,
|
String? hashSalt,
|
||||||
|
UserSessionType? sessionType,
|
||||||
|
List<Session>? sessionData,
|
||||||
}) =>
|
}) =>
|
||||||
UserStatus(
|
UserStatus(
|
||||||
onlineStatus: onlineStatus ?? this.onlineStatus,
|
onlineStatus: onlineStatus ?? this.onlineStatus,
|
||||||
lastStatusChange: lastStatusChange ?? this.lastStatusChange,
|
lastStatusChange: lastStatusChange ?? this.lastStatusChange,
|
||||||
currentSessionAccessLevel: currentSessionAccessLevel ?? this.currentSessionAccessLevel,
|
lastPresenceTimestamp: lastPresenceTimestamp ?? this.lastPresenceTimestamp,
|
||||||
currentSessionHidden: currentSessionHidden ?? this.currentSessionHidden,
|
isPresent: isPresent ?? this.isPresent,
|
||||||
currentHosting: currentHosting ?? this.currentHosting,
|
userSessionId: userSessionId ?? this.userSessionId,
|
||||||
currentSessionIndex: currentSessionIndex ?? this.currentSessionIndex,
|
currentSessionIndex: currentSessionIndex ?? this.currentSessionIndex,
|
||||||
sessions: sessions ?? this.sessions,
|
sessions: sessions ?? this.sessions,
|
||||||
appVersion: appVersion ?? this.appVersion,
|
appVersion: appVersion ?? this.appVersion,
|
||||||
|
@ -123,5 +149,7 @@ class UserStatus {
|
||||||
isMobile: isMobile ?? this.isMobile,
|
isMobile: isMobile ?? this.isMobile,
|
||||||
compatibilityHash: compatibilityHash ?? this.compatibilityHash,
|
compatibilityHash: compatibilityHash ?? this.compatibilityHash,
|
||||||
hashSalt: hashSalt ?? this.hashSalt,
|
hashSalt: hashSalt ?? this.hashSalt,
|
||||||
|
sessionType: sessionType ?? this.sessionType,
|
||||||
|
decodedSessions: sessionData ?? this.decodedSessions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:contacts_plus_plus/auxiliary.dart';
|
import 'package:contacts_plus_plus/auxiliary.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/users/friend.dart';
|
|
||||||
import 'package:contacts_plus_plus/models/message.dart';
|
import 'package:contacts_plus_plus/models/message.dart';
|
||||||
|
import 'package:contacts_plus_plus/models/users/friend.dart';
|
||||||
import 'package:contacts_plus_plus/widgets/formatted_text.dart';
|
import 'package:contacts_plus_plus/widgets/formatted_text.dart';
|
||||||
import 'package:contacts_plus_plus/widgets/friends/friend_online_status_indicator.dart';
|
import 'package:contacts_plus_plus/widgets/friends/friend_online_status_indicator.dart';
|
||||||
import 'package:contacts_plus_plus/widgets/generic_avatar.dart';
|
import 'package:contacts_plus_plus/widgets/generic_avatar.dart';
|
||||||
|
@ -24,8 +22,9 @@ class FriendListTile extends StatelessWidget {
|
||||||
final imageUri = Aux.resdbToHttp(friend.userProfile.iconUrl);
|
final imageUri = Aux.resdbToHttp(friend.userProfile.iconUrl);
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final mClient = Provider.of<MessagingClient>(context, listen: false);
|
final mClient = Provider.of<MessagingClient>(context, listen: false);
|
||||||
final currentSessionMetadata = friend.userStatus.sessions.elementAtOrNull(max(0, friend.userStatus.currentSessionIndex));
|
final currentSession = friend.userStatus.currentSessionIndex == -1
|
||||||
final currentSession = mClient.getSessionInfo(currentSessionMetadata?.sessionHash ?? "");
|
? null
|
||||||
|
: friend.userStatus.decodedSessions.elementAtOrNull(friend.userStatus.currentSessionIndex);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: GenericAvatar(
|
leading: GenericAvatar(
|
||||||
imageUri: imageUri,
|
imageUri: imageUri,
|
||||||
|
@ -59,7 +58,7 @@ class FriendListTile extends StatelessWidget {
|
||||||
width: 4,
|
width: 4,
|
||||||
),
|
),
|
||||||
Text(toBeginningOfSentenceCase(friend.userStatus.onlineStatus.name) ?? "Unknown"),
|
Text(toBeginningOfSentenceCase(friend.userStatus.onlineStatus.name) ?? "Unknown"),
|
||||||
if (currentSession != null) ...[
|
if (currentSession != null && !currentSession.isNone) ...[
|
||||||
const Text(" in "),
|
const Text(" in "),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FormattedText(
|
child: FormattedText(
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:contacts_plus_plus/clients/audio_cache_client.dart';
|
import 'package:contacts_plus_plus/clients/audio_cache_client.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/users/friend.dart';
|
import 'package:contacts_plus_plus/models/users/friend.dart';
|
||||||
|
@ -56,7 +57,7 @@ class _MessagesListState extends State<MessagesList> with SingleTickerProviderSt
|
||||||
return Consumer<MessagingClient>(builder: (context, mClient, _) {
|
return Consumer<MessagingClient>(builder: (context, mClient, _) {
|
||||||
final friend = mClient.selectedFriend ?? Friend.empty();
|
final friend = mClient.selectedFriend ?? Friend.empty();
|
||||||
final cache = mClient.getUserMessageCache(friend.id);
|
final cache = mClient.getUserMessageCache(friend.id);
|
||||||
final sessions = friend.userStatus.sessions;
|
final sessions = friend.userStatus.decodedSessions.whereNot((element) => element.isNone).toList();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
|
@ -121,9 +122,7 @@ class _MessagesListState extends State<MessagesList> with SingleTickerProviderSt
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemCount: sessions.length,
|
itemCount: sessions.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final currentSessionMetadata = sessions[index];
|
final currentSession = sessions[index];
|
||||||
final currentSession = mClient.getSessionInfo(currentSessionMetadata.sessionHash);
|
|
||||||
if (currentSession == null) return null;
|
|
||||||
return SessionTile(session: currentSession);
|
return SessionTile(session: currentSession);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -181,10 +181,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: ffi
|
name: ffi
|
||||||
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
|
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.1.0"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
Loading…
Reference in a new issue