feat(ui,service): Handle the "self-participant"
This commit is contained in:
@@ -15,6 +15,7 @@ Future<void> upgradeFromV48ToV49(DatabaseMigrationData data) async {
|
||||
avatarPath TEXT,
|
||||
avatarHash TEXT,
|
||||
realJid TEXT,
|
||||
isSelf INTEGER NOT NULL,
|
||||
PRIMARY KEY (roomJid, accountJid, nick),
|
||||
CONSTRAINT fk_muc
|
||||
FOREIGN KEY (roomJid, accountJid)
|
||||
|
||||
@@ -84,6 +84,7 @@ class GroupchatService {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
);
|
||||
await db.insert(
|
||||
groupchatMembersTable,
|
||||
@@ -91,7 +92,23 @@ class GroupchatService {
|
||||
);
|
||||
members.add(member);
|
||||
}
|
||||
members.sort((a, b) => a.nick.compareTo(b.nick));
|
||||
// Add the self-participant
|
||||
await db.insert(
|
||||
groupchatMembersTable,
|
||||
GroupchatMember(
|
||||
accountJid,
|
||||
muc.toString(),
|
||||
state.nick!,
|
||||
state.role!,
|
||||
state.affiliation!,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
).toJson(),
|
||||
);
|
||||
|
||||
// TODO(Unknown): In case the MUC changed our nick, update the groupchat details to reflect this.
|
||||
|
||||
return Result(
|
||||
GroupchatDetails(
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:moxxmpp/moxxmpp.dart';
|
||||
import 'package:moxxyv2/service/database/helpers.dart';
|
||||
|
||||
part 'groupchat_member.freezed.dart';
|
||||
part 'groupchat_member.g.dart';
|
||||
|
||||
// TODO: Move somewhere else so that we can reuse it.
|
||||
class BooleanTypeConverter extends JsonConverter<bool, int> {
|
||||
const BooleanTypeConverter();
|
||||
|
||||
@override
|
||||
bool fromJson(int json) {
|
||||
return intToBool(json);
|
||||
}
|
||||
|
||||
@override
|
||||
int toJson(bool object) {
|
||||
return boolToInt(object);
|
||||
}
|
||||
}
|
||||
|
||||
class RoleTypeConverter extends JsonConverter<Role, String> {
|
||||
const RoleTypeConverter();
|
||||
|
||||
@@ -43,6 +59,7 @@ class GroupchatMember with _$GroupchatMember {
|
||||
String? avatarPath,
|
||||
String? avatarHash,
|
||||
String? realJid,
|
||||
@BooleanTypeConverter() bool isSelf,
|
||||
) = _GroupchatMember;
|
||||
|
||||
/// JSON
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:moxxyv2/shared/events.dart';
|
||||
import 'package:moxxyv2/shared/models/conversation.dart';
|
||||
import 'package:moxxyv2/shared/models/groupchat_member.dart';
|
||||
import 'package:moxxyv2/ui/bloc/server_info_bloc.dart';
|
||||
import 'package:moxxyv2/ui/constants.dart';
|
||||
import 'package:moxxyv2/ui/pages/profile/conversationheader.dart';
|
||||
import 'package:moxxyv2/ui/pages/profile/profile.dart';
|
||||
import 'package:moxxyv2/ui/pages/profile/selfheader.dart';
|
||||
@@ -55,24 +56,9 @@ class ProfileViewState extends State<ProfileView> {
|
||||
),
|
||||
))! as GroupchatMembersResult;
|
||||
|
||||
// TODO: Handle the display of our own data more gracefully. Maybe keep a special
|
||||
// GroupchatMember that also stores our own affiliation and role so that we can
|
||||
// cache it.
|
||||
// TODO: That also requires that we render that element separately so that we can just bypass
|
||||
// the avatar data and just pull it from one of the BLoCs.
|
||||
final members = List.of(result.members)
|
||||
..add(
|
||||
GroupchatMember(
|
||||
'',
|
||||
'',
|
||||
t.messages.you,
|
||||
Role.none,
|
||||
Affiliation.none,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
),
|
||||
)
|
||||
..sort(groupchatMemberSortingFunction);
|
||||
|
||||
setState(() {
|
||||
@@ -86,6 +72,55 @@ class ProfileViewState extends State<ProfileView> {
|
||||
_initStateAsync();
|
||||
}
|
||||
|
||||
Widget _buildMemberTile(GroupchatMember member) {
|
||||
if (member.isSelf) {
|
||||
return ListTile(
|
||||
leading: CachingXMPPAvatar.self(radius: 20),
|
||||
title: Text(
|
||||
t.messages.you,
|
||||
style: const TextStyle(
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
member.nick,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: CachingXMPPAvatar(
|
||||
jid: '${widget.arguments.jid}/${member.nick}',
|
||||
radius: 20,
|
||||
hasContactId: false,
|
||||
isGroupchat: true,
|
||||
// TODO(Unknown): Request avatars at some point
|
||||
shouldRequest: false,
|
||||
),
|
||||
title: Text(
|
||||
member.nick,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
subtitle: switch (member.affiliation) {
|
||||
// TODO: i18n
|
||||
Affiliation.owner => const Text(
|
||||
'Owner',
|
||||
style: TextStyle(color: Colors.red),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Affiliation.admin => const Text(
|
||||
'Admin',
|
||||
style: TextStyle(color: Colors.green),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Affiliation.member => null,
|
||||
Affiliation.none => null,
|
||||
Affiliation.outcast => null,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildMemberList() {
|
||||
if (_members == null) {
|
||||
return const SliverToBoxAdapter(
|
||||
@@ -96,30 +131,8 @@ class ProfileViewState extends State<ProfileView> {
|
||||
return SliverList.builder(
|
||||
itemCount: _members!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
leading: CachingXMPPAvatar(
|
||||
jid: '${widget.arguments.jid}/${_members![index].nick}',
|
||||
radius: 20,
|
||||
hasContactId: false,
|
||||
isGroupchat: true,
|
||||
shouldRequest: false,
|
||||
),
|
||||
title: Text(_members![index].nick),
|
||||
subtitle: switch (_members![index].affiliation) {
|
||||
// TODO: i18n
|
||||
Affiliation.owner => const Text(
|
||||
'Owner',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
Affiliation.admin => const Text(
|
||||
'Admin',
|
||||
style: TextStyle(color: Colors.green),
|
||||
),
|
||||
Affiliation.member => null,
|
||||
Affiliation.none => null,
|
||||
Affiliation.outcast => null,
|
||||
},
|
||||
);
|
||||
final member = _members![index];
|
||||
return _buildMemberTile(member);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user