Add active session name and headless indicator to friend tile
This commit is contained in:
parent
801881cc07
commit
8a6a033cfd
5 changed files with 81 additions and 26 deletions
|
@ -16,6 +16,8 @@ class Friend implements Comparable {
|
|||
required this.friendStatus, required this.latestMessageTime,
|
||||
});
|
||||
|
||||
bool get isHeadless => userStatus.activeSessions.any((session) => session.headlessHost == true && session.hostUserId == id);
|
||||
|
||||
factory Friend.fromMap(Map map) {
|
||||
final userStatus = UserStatus.fromMap(map["userStatus"]);
|
||||
return Friend(
|
||||
|
@ -116,19 +118,23 @@ enum OnlineStatus {
|
|||
class UserStatus {
|
||||
final OnlineStatus onlineStatus;
|
||||
final DateTime lastStatusChange;
|
||||
final Session currentSession;
|
||||
final List<Session> activeSessions;
|
||||
final String neosVersion;
|
||||
|
||||
const UserStatus({required this.onlineStatus, required this.lastStatusChange, required this.activeSessions,
|
||||
required this.neosVersion,
|
||||
});
|
||||
const UserStatus(
|
||||
{required this.onlineStatus, required this.lastStatusChange, required this.currentSession, required this.activeSessions,
|
||||
required this.neosVersion,
|
||||
});
|
||||
|
||||
factory UserStatus.empty() => UserStatus(
|
||||
onlineStatus: OnlineStatus.offline,
|
||||
lastStatusChange: DateTime.now(),
|
||||
activeSessions: [],
|
||||
neosVersion: "",
|
||||
);
|
||||
factory UserStatus.empty() =>
|
||||
UserStatus(
|
||||
onlineStatus: OnlineStatus.offline,
|
||||
lastStatusChange: DateTime.now(),
|
||||
activeSessions: [],
|
||||
currentSession: Session.none(),
|
||||
neosVersion: "",
|
||||
);
|
||||
|
||||
factory UserStatus.fromMap(Map map) {
|
||||
final statusString = map["onlineStatus"] as String?;
|
||||
|
@ -136,27 +142,34 @@ class UserStatus {
|
|||
return UserStatus(
|
||||
onlineStatus: status,
|
||||
lastStatusChange: DateTime.parse(map["lastStatusChange"]),
|
||||
currentSession: Session.fromMap(map["currentSession"]),
|
||||
activeSessions: (map["activeSessions"] as List? ?? []).map((e) => Session.fromMap(e)).toList(),
|
||||
neosVersion: map["neosVersion"] ?? "",
|
||||
);
|
||||
}
|
||||
|
||||
Map toMap({bool shallow=false}) {
|
||||
Map toMap({bool shallow = false}) {
|
||||
return {
|
||||
"onlineStatus": onlineStatus.index,
|
||||
"lastStatusChange": lastStatusChange.toIso8601String(),
|
||||
"currentSession": currentSession.isNone || shallow ? null : currentSession.toMap(),
|
||||
"activeSessions": shallow ? [] : activeSessions.map((e) => e.toMap(),),
|
||||
"neosVersion": neosVersion,
|
||||
};
|
||||
}
|
||||
|
||||
UserStatus copyWith({OnlineStatus? onlineStatus, DateTime? lastStatusChange, List<Session>? activeSessions,
|
||||
UserStatus copyWith({
|
||||
OnlineStatus? onlineStatus,
|
||||
DateTime? lastStatusChange,
|
||||
Session? currentSession,
|
||||
List<Session>? activeSessions,
|
||||
String? neosVersion
|
||||
})
|
||||
=> UserStatus(
|
||||
onlineStatus: onlineStatus ?? this.onlineStatus,
|
||||
lastStatusChange: lastStatusChange ?? this.lastStatusChange,
|
||||
activeSessions: activeSessions ?? this.activeSessions,
|
||||
neosVersion: neosVersion ?? this.neosVersion,
|
||||
);
|
||||
}) =>
|
||||
UserStatus(
|
||||
onlineStatus: onlineStatus ?? this.onlineStatus,
|
||||
lastStatusChange: lastStatusChange ?? this.lastStatusChange,
|
||||
currentSession: currentSession ?? this.currentSession,
|
||||
activeSessions: activeSessions ?? this.activeSessions,
|
||||
neosVersion: neosVersion ?? this.neosVersion,
|
||||
);
|
||||
}
|
|
@ -13,15 +13,38 @@ class Session {
|
|||
final FormatNode formattedDescription;
|
||||
final List<String> tags;
|
||||
final bool headlessHost;
|
||||
final String hostUserId;
|
||||
final String hostUsername;
|
||||
final SessionAccessLevel accessLevel;
|
||||
|
||||
Session({required this.id, required this.name, required this.sessionUsers, required this.thumbnail,
|
||||
required this.maxUsers, required this.hasEnded, required this.isValid, required this.description,
|
||||
required this.tags, required this.headlessHost, required this.hostUsername, required this.accessLevel,
|
||||
required this.tags, required this.headlessHost, required this.hostUserId, required this.hostUsername,
|
||||
required this.accessLevel,
|
||||
}) : formattedName = FormatNode.fromText(name), formattedDescription = FormatNode.fromText(description);
|
||||
|
||||
factory Session.fromMap(Map map) {
|
||||
factory Session.none() {
|
||||
return Session(
|
||||
id: "",
|
||||
name: "",
|
||||
sessionUsers: const [],
|
||||
thumbnail: "",
|
||||
maxUsers: 0,
|
||||
hasEnded: true,
|
||||
isValid: false,
|
||||
description: "",
|
||||
tags: const [],
|
||||
headlessHost: false,
|
||||
hostUserId: "",
|
||||
hostUsername: "",
|
||||
accessLevel: SessionAccessLevel.unknown
|
||||
);
|
||||
}
|
||||
|
||||
bool get isNone => id.isEmpty && isValid == false;
|
||||
|
||||
factory Session.fromMap(Map? map) {
|
||||
if (map == null) return Session.none();
|
||||
return Session(
|
||||
id: map["sessionId"],
|
||||
name: map["name"],
|
||||
|
@ -33,6 +56,7 @@ class Session {
|
|||
description: map["description"] ?? "",
|
||||
tags: ((map["tags"] as List?) ?? []).map((e) => e.toString()).toList(),
|
||||
headlessHost: map["headlessHost"] ?? false,
|
||||
hostUserId: map["hostUserId"] ?? "",
|
||||
hostUsername: map["hostUsername"] ?? "",
|
||||
accessLevel: SessionAccessLevel.fromName(map["accessLevel"]),
|
||||
);
|
||||
|
@ -50,6 +74,7 @@ class Session {
|
|||
"description": description,
|
||||
"tags": shallow ? [] : throw UnimplementedError(),
|
||||
"headlessHost": headlessHost,
|
||||
"hostUserId": hostUserId,
|
||||
"hostUsername": hostUsername,
|
||||
"accessLevel": accessLevel.name, // This probably wont work, the API usually expects integers.
|
||||
};
|
||||
|
|
|
@ -2,19 +2,19 @@ import 'package:contacts_plus_plus/auxiliary.dart';
|
|||
import 'package:contacts_plus_plus/clients/messaging_client.dart';
|
||||
import 'package:contacts_plus_plus/models/friend.dart';
|
||||
import 'package:contacts_plus_plus/models/message.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/generic_avatar.dart';
|
||||
import 'package:contacts_plus_plus/widgets/messages/messages_list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class FriendListTile extends StatelessWidget {
|
||||
const FriendListTile({required this.friend, this.unreads, this.onTap, super.key});
|
||||
const FriendListTile({required this.friend, required this.unreads, this.onTap, super.key});
|
||||
|
||||
final Friend friend;
|
||||
final int? unreads;
|
||||
final int unreads;
|
||||
final Function? onTap;
|
||||
|
||||
@override
|
||||
|
@ -23,10 +23,18 @@ class FriendListTile extends StatelessWidget {
|
|||
final theme = Theme.of(context);
|
||||
return ListTile(
|
||||
leading: GenericAvatar(imageUri: imageUri,),
|
||||
trailing: unreads != null && unreads != 0
|
||||
trailing: unreads != 0
|
||||
? Text("+$unreads", style: theme.textTheme.bodyMedium?.copyWith(color: theme.colorScheme.primary),)
|
||||
: null,
|
||||
title: Text(friend.username),
|
||||
title: Row(
|
||||
children: [
|
||||
Text(friend.username),
|
||||
if (friend.isHeadless) Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Icon(Icons.dns, size: 12, color: theme.colorScheme.onSecondaryContainer.withAlpha(150),),
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
|
@ -34,6 +42,11 @@ class FriendListTile extends StatelessWidget {
|
|||
FriendOnlineStatusIndicator(userStatus: friend.userStatus),
|
||||
const SizedBox(width: 4,),
|
||||
Text(toBeginningOfSentenceCase(friend.userStatus.onlineStatus.name) ?? "Unknown"),
|
||||
if (!friend.userStatus.currentSession.isNone)
|
||||
...[
|
||||
const Text(" in "),
|
||||
Expanded(child: FormattedText(friend.userStatus.currentSession.formattedName, overflow: TextOverflow.ellipsis, maxLines: 1,))
|
||||
]
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:contacts_plus_plus/clients/messaging_client.dart';
|
|||
import 'package:contacts_plus_plus/models/friend.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/formatted_text.dart';
|
||||
import 'package:contacts_plus_plus/widgets/friends/expanding_input_fab.dart';
|
||||
import 'package:contacts_plus_plus/widgets/friends/friend_list_tile.dart';
|
||||
import 'package:contacts_plus_plus/widgets/my_profile_dialog.dart';
|
||||
|
|
|
@ -72,7 +72,10 @@ class _MessagesListState extends State<MessagesList> {
|
|||
FriendOnlineStatusIndicator(userStatus: widget.friend.userStatus),
|
||||
const SizedBox(width: 8,),
|
||||
Text(widget.friend.username),
|
||||
|
||||
if (widget.friend.isHeadless) Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Icon(Icons.dns, size: 18, color: Theme.of(context).colorScheme.onSecondaryContainer.withAlpha(150),),
|
||||
),
|
||||
],
|
||||
),
|
||||
scrolledUnderElevation: 0.0,
|
||||
|
|
Loading…
Reference in a new issue