2023-05-01 16:00:56 -04:00
|
|
|
import 'package:contacts_plus_plus/models/session.dart';
|
2023-05-01 13:13:40 -04:00
|
|
|
import 'package:contacts_plus_plus/models/user_profile.dart';
|
2023-05-05 10:39:40 -04:00
|
|
|
import 'package:flutter/material.dart';
|
2023-04-29 15:26:12 -04:00
|
|
|
|
2023-05-12 11:05:31 -04:00
|
|
|
class Friend implements Comparable {
|
2023-05-12 12:40:09 -04:00
|
|
|
static const _neosBotId = "U-Neos";
|
2023-04-29 13:18:46 -04:00
|
|
|
final String id;
|
|
|
|
final String username;
|
2023-05-04 14:57:16 -04:00
|
|
|
final String ownerId;
|
2023-04-29 13:18:46 -04:00
|
|
|
final UserStatus userStatus;
|
2023-04-30 07:39:09 -04:00
|
|
|
final UserProfile userProfile;
|
2023-04-30 17:14:29 -04:00
|
|
|
final FriendStatus friendStatus;
|
2023-05-06 13:01:15 -04:00
|
|
|
final DateTime latestMessageTime;
|
2023-04-29 13:18:46 -04:00
|
|
|
|
2023-05-04 14:57:16 -04:00
|
|
|
Friend({required this.id, required this.username, required this.ownerId, required this.userStatus, required this.userProfile,
|
2023-05-06 13:01:15 -04:00
|
|
|
required this.friendStatus, required this.latestMessageTime,
|
2023-04-30 17:14:29 -04:00
|
|
|
});
|
2023-04-29 15:26:12 -04:00
|
|
|
|
2023-05-12 13:29:23 -04:00
|
|
|
bool get isHeadless => userStatus.activeSessions.any((session) => session.headlessHost == true && session.hostUserId == id);
|
|
|
|
|
2023-04-29 15:26:12 -04:00
|
|
|
factory Friend.fromMap(Map map) {
|
2023-05-12 12:40:09 -04:00
|
|
|
final userStatus = UserStatus.fromMap(map["userStatus"]);
|
2023-04-30 07:39:09 -04:00
|
|
|
return Friend(
|
|
|
|
id: map["id"],
|
|
|
|
username: map["friendUsername"],
|
2023-05-04 14:57:16 -04:00
|
|
|
ownerId: map["ownerId"] ?? map["id"],
|
2023-05-12 12:40:09 -04:00
|
|
|
// Neos bot status is always offline but should be displayed as online
|
|
|
|
userStatus: map["id"] == _neosBotId ? userStatus.copyWith(onlineStatus: OnlineStatus.online) : userStatus,
|
2023-04-30 17:14:29 -04:00
|
|
|
userProfile: UserProfile.fromMap(map["profile"] ?? {}),
|
|
|
|
friendStatus: FriendStatus.fromString(map["friendStatus"]),
|
2023-05-06 13:01:15 -04:00
|
|
|
latestMessageTime: map["latestMessageTime"] == null
|
|
|
|
? DateTime.fromMillisecondsSinceEpoch(0) : DateTime.parse(map["latestMessageTime"]),
|
2023-04-30 07:39:09 -04:00
|
|
|
);
|
2023-04-29 15:26:12 -04:00
|
|
|
}
|
|
|
|
|
2023-05-16 07:01:42 -04:00
|
|
|
static Friend? fromMapOrNull(Map? map) {
|
|
|
|
if (map == null) return null;
|
|
|
|
return Friend.fromMap(map);
|
|
|
|
}
|
|
|
|
|
2023-05-06 13:45:54 -04:00
|
|
|
Friend copyWith({
|
|
|
|
String? id, String? username, String? ownerId, UserStatus? userStatus, UserProfile? userProfile,
|
|
|
|
FriendStatus? friendStatus, DateTime? latestMessageTime}) {
|
|
|
|
return Friend(
|
|
|
|
id: id ?? this.id,
|
|
|
|
username: username ?? this.username,
|
|
|
|
ownerId: ownerId ?? this.ownerId,
|
|
|
|
userStatus: userStatus ?? this.userStatus,
|
|
|
|
userProfile: userProfile ?? this.userProfile,
|
|
|
|
friendStatus: friendStatus ?? this.friendStatus,
|
|
|
|
latestMessageTime: latestMessageTime ?? this.latestMessageTime,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-05-04 14:57:16 -04:00
|
|
|
Map toMap({bool shallow=false}) {
|
|
|
|
return {
|
|
|
|
"id": id,
|
|
|
|
"username": username,
|
|
|
|
"ownerId": ownerId,
|
|
|
|
"userStatus": userStatus.toMap(shallow: shallow),
|
|
|
|
"profile": userProfile.toMap(),
|
|
|
|
"friendStatus": friendStatus.name,
|
2023-05-06 13:01:15 -04:00
|
|
|
"latestMessageTime": latestMessageTime.toIso8601String(),
|
2023-05-04 14:57:16 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-04-29 15:26:12 -04:00
|
|
|
@override
|
2023-05-03 14:03:46 -04:00
|
|
|
int compareTo(covariant Friend other) {
|
|
|
|
return username.compareTo(other.username);
|
2023-04-29 15:26:12 -04:00
|
|
|
}
|
2023-04-29 13:18:46 -04:00
|
|
|
}
|
|
|
|
|
2023-04-30 17:14:29 -04:00
|
|
|
enum FriendStatus {
|
|
|
|
none,
|
|
|
|
searchResult,
|
|
|
|
requested,
|
|
|
|
ignored,
|
|
|
|
blocked,
|
|
|
|
accepted;
|
|
|
|
|
|
|
|
factory FriendStatus.fromString(String text) {
|
|
|
|
return FriendStatus.values.firstWhere((element) => element.name.toLowerCase() == text.toLowerCase(),
|
|
|
|
orElse: () => FriendStatus.none,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-29 13:18:46 -04:00
|
|
|
enum OnlineStatus {
|
|
|
|
offline,
|
2023-05-05 10:39:40 -04:00
|
|
|
invisible,
|
2023-04-29 15:26:12 -04:00
|
|
|
away,
|
|
|
|
busy,
|
2023-04-30 17:14:29 -04:00
|
|
|
online;
|
|
|
|
|
2023-05-05 10:39:40 -04:00
|
|
|
static final List<Color> _colors = [
|
2023-05-25 13:30:15 -04:00
|
|
|
Colors.transparent,
|
|
|
|
Colors.transparent,
|
2023-05-05 10:39:40 -04:00
|
|
|
Colors.yellow,
|
|
|
|
Colors.red,
|
|
|
|
Colors.green,
|
|
|
|
];
|
|
|
|
|
2023-05-25 13:30:15 -04:00
|
|
|
Color color(BuildContext context) => this == OnlineStatus.offline || this == OnlineStatus.invisible ? Theme.of(context).colorScheme.onSurface : _colors[index];
|
2023-05-05 10:39:40 -04:00
|
|
|
|
2023-04-30 17:14:29 -04:00
|
|
|
factory OnlineStatus.fromString(String? text) {
|
|
|
|
return OnlineStatus.values.firstWhere((element) => element.name.toLowerCase() == text?.toLowerCase(),
|
2023-05-05 10:39:40 -04:00
|
|
|
orElse: () => OnlineStatus.offline,
|
2023-04-30 17:14:29 -04:00
|
|
|
);
|
|
|
|
}
|
2023-05-03 12:43:06 -04:00
|
|
|
|
|
|
|
int compareTo(OnlineStatus other) {
|
|
|
|
if (this == other) return 0;
|
|
|
|
if (this == OnlineStatus.online) return -1;
|
|
|
|
if (other == OnlineStatus.online) return 1;
|
|
|
|
if (this == OnlineStatus.away) return -1;
|
|
|
|
if (other == OnlineStatus.away) return 1;
|
|
|
|
if (this == OnlineStatus.busy) return -1;
|
|
|
|
if (other == OnlineStatus.busy) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2023-04-29 13:18:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
class UserStatus {
|
|
|
|
final OnlineStatus onlineStatus;
|
|
|
|
final DateTime lastStatusChange;
|
2023-05-15 05:47:57 -04:00
|
|
|
final int currentSessionAccessLevel;
|
|
|
|
final bool currentSessionHidden;
|
|
|
|
final bool currentHosting;
|
2023-05-12 13:29:23 -04:00
|
|
|
final Session currentSession;
|
2023-04-30 17:14:29 -04:00
|
|
|
final List<Session> activeSessions;
|
2023-05-06 05:18:00 -04:00
|
|
|
final String neosVersion;
|
2023-05-15 05:47:57 -04:00
|
|
|
final String outputDevice;
|
|
|
|
final bool isMobile;
|
|
|
|
final String compatibilityHash;
|
2023-04-29 13:18:46 -04:00
|
|
|
|
2023-05-12 13:29:23 -04:00
|
|
|
const UserStatus(
|
2023-05-15 05:47:57 -04:00
|
|
|
{required this.onlineStatus, required this.lastStatusChange, required this.currentSession,
|
|
|
|
required this.currentSessionAccessLevel, required this.currentSessionHidden, required this.currentHosting,
|
|
|
|
required this.activeSessions, required this.neosVersion, required this.outputDevice, required this.isMobile,
|
|
|
|
required this.compatibilityHash,
|
2023-05-12 13:29:23 -04:00
|
|
|
});
|
2023-04-29 15:26:12 -04:00
|
|
|
|
2023-05-12 13:29:23 -04:00
|
|
|
factory UserStatus.empty() =>
|
|
|
|
UserStatus(
|
|
|
|
onlineStatus: OnlineStatus.offline,
|
|
|
|
lastStatusChange: DateTime.now(),
|
2023-05-15 05:47:57 -04:00
|
|
|
currentSessionAccessLevel: 0,
|
|
|
|
currentSessionHidden: false,
|
|
|
|
currentHosting: false,
|
2023-05-12 13:29:23 -04:00
|
|
|
currentSession: Session.none(),
|
2023-05-15 05:47:57 -04:00
|
|
|
activeSessions: [],
|
2023-05-12 13:29:23 -04:00
|
|
|
neosVersion: "",
|
2023-05-15 05:47:57 -04:00
|
|
|
outputDevice: "Unknown",
|
|
|
|
isMobile: false,
|
|
|
|
compatibilityHash: "",
|
2023-05-12 13:29:23 -04:00
|
|
|
);
|
2023-05-04 14:57:16 -04:00
|
|
|
|
2023-04-29 15:26:12 -04:00
|
|
|
factory UserStatus.fromMap(Map map) {
|
|
|
|
final statusString = map["onlineStatus"] as String?;
|
2023-04-30 17:14:29 -04:00
|
|
|
final status = OnlineStatus.fromString(statusString);
|
2023-04-29 15:26:12 -04:00
|
|
|
return UserStatus(
|
|
|
|
onlineStatus: status,
|
|
|
|
lastStatusChange: DateTime.parse(map["lastStatusChange"]),
|
2023-05-15 05:47:57 -04:00
|
|
|
currentSessionAccessLevel: map["currentSessionAccessLevel"] ?? 0,
|
|
|
|
currentSessionHidden: map["currentSessionHidden"] ?? false,
|
|
|
|
currentHosting: map["currentHosting"] ?? false,
|
2023-05-12 13:29:23 -04:00
|
|
|
currentSession: Session.fromMap(map["currentSession"]),
|
2023-04-30 17:14:29 -04:00
|
|
|
activeSessions: (map["activeSessions"] as List? ?? []).map((e) => Session.fromMap(e)).toList(),
|
2023-05-06 05:18:00 -04:00
|
|
|
neosVersion: map["neosVersion"] ?? "",
|
2023-05-15 05:47:57 -04:00
|
|
|
outputDevice: map["outputDevice"] ?? "Unknown",
|
|
|
|
isMobile: map["isMobile"] ?? false,
|
|
|
|
compatibilityHash: map["compatabilityHash"] ?? ""
|
2023-04-29 15:26:12 -04:00
|
|
|
);
|
|
|
|
}
|
2023-05-04 14:57:16 -04:00
|
|
|
|
2023-05-12 13:29:23 -04:00
|
|
|
Map toMap({bool shallow = false}) {
|
2023-05-04 14:57:16 -04:00
|
|
|
return {
|
|
|
|
"onlineStatus": onlineStatus.index,
|
|
|
|
"lastStatusChange": lastStatusChange.toIso8601String(),
|
2023-05-15 05:47:57 -04:00
|
|
|
"currentSessionAccessLevel": currentSessionAccessLevel,
|
|
|
|
"currentSessionHidden": currentSessionHidden,
|
|
|
|
"currentHosting": currentHosting,
|
2023-05-12 13:29:23 -04:00
|
|
|
"currentSession": currentSession.isNone || shallow ? null : currentSession.toMap(),
|
2023-05-15 05:47:57 -04:00
|
|
|
"activeSessions": shallow ? [] : activeSessions.map((e) => e.toMap(),).toList(),
|
2023-05-06 05:18:00 -04:00
|
|
|
"neosVersion": neosVersion,
|
2023-05-15 05:47:57 -04:00
|
|
|
"outputDevice": outputDevice,
|
|
|
|
"isMobile": isMobile,
|
|
|
|
"compatibilityHash": compatibilityHash,
|
2023-05-04 14:57:16 -04:00
|
|
|
};
|
|
|
|
}
|
2023-05-05 10:39:40 -04:00
|
|
|
|
2023-05-12 13:29:23 -04:00
|
|
|
UserStatus copyWith({
|
|
|
|
OnlineStatus? onlineStatus,
|
|
|
|
DateTime? lastStatusChange,
|
2023-05-15 05:47:57 -04:00
|
|
|
int? currentSessionAccessLevel,
|
|
|
|
bool? currentSessionHidden,
|
|
|
|
bool? currentHosting,
|
2023-05-12 13:29:23 -04:00
|
|
|
Session? currentSession,
|
|
|
|
List<Session>? activeSessions,
|
2023-05-15 05:47:57 -04:00
|
|
|
String? neosVersion,
|
|
|
|
String? outputDevice,
|
|
|
|
bool? isMobile,
|
|
|
|
String? compatibilityHash,
|
2023-05-12 13:29:23 -04:00
|
|
|
}) =>
|
|
|
|
UserStatus(
|
|
|
|
onlineStatus: onlineStatus ?? this.onlineStatus,
|
|
|
|
lastStatusChange: lastStatusChange ?? this.lastStatusChange,
|
2023-05-15 05:47:57 -04:00
|
|
|
currentSessionAccessLevel: currentSessionAccessLevel ?? this.currentSessionAccessLevel,
|
|
|
|
currentSessionHidden: currentSessionHidden ?? this.currentSessionHidden,
|
|
|
|
currentHosting: currentHosting ?? this.currentHosting,
|
2023-05-12 13:29:23 -04:00
|
|
|
currentSession: currentSession ?? this.currentSession,
|
|
|
|
activeSessions: activeSessions ?? this.activeSessions,
|
|
|
|
neosVersion: neosVersion ?? this.neosVersion,
|
2023-05-15 05:47:57 -04:00
|
|
|
outputDevice: outputDevice ?? this.outputDevice,
|
|
|
|
isMobile: isMobile ?? this.isMobile,
|
|
|
|
compatibilityHash: compatibilityHash ?? this.compatibilityHash,
|
2023-05-12 13:29:23 -04:00
|
|
|
);
|
2023-04-29 13:18:46 -04:00
|
|
|
}
|