feat(ui,service): Handle the "self-participant"
This commit is contained in:
@@ -15,6 +15,7 @@ Future<void> upgradeFromV48ToV49(DatabaseMigrationData data) async {
|
|||||||
avatarPath TEXT,
|
avatarPath TEXT,
|
||||||
avatarHash TEXT,
|
avatarHash TEXT,
|
||||||
realJid TEXT,
|
realJid TEXT,
|
||||||
|
isSelf INTEGER NOT NULL,
|
||||||
PRIMARY KEY (roomJid, accountJid, nick),
|
PRIMARY KEY (roomJid, accountJid, nick),
|
||||||
CONSTRAINT fk_muc
|
CONSTRAINT fk_muc
|
||||||
FOREIGN KEY (roomJid, accountJid)
|
FOREIGN KEY (roomJid, accountJid)
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class GroupchatService {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
await db.insert(
|
await db.insert(
|
||||||
groupchatMembersTable,
|
groupchatMembersTable,
|
||||||
@@ -91,7 +92,23 @@ class GroupchatService {
|
|||||||
);
|
);
|
||||||
members.add(member);
|
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(
|
return Result(
|
||||||
GroupchatDetails(
|
GroupchatDetails(
|
||||||
|
|||||||
@@ -1,9 +1,25 @@
|
|||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:moxxmpp/moxxmpp.dart';
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
|
import 'package:moxxyv2/service/database/helpers.dart';
|
||||||
|
|
||||||
part 'groupchat_member.freezed.dart';
|
part 'groupchat_member.freezed.dart';
|
||||||
part 'groupchat_member.g.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> {
|
class RoleTypeConverter extends JsonConverter<Role, String> {
|
||||||
const RoleTypeConverter();
|
const RoleTypeConverter();
|
||||||
|
|
||||||
@@ -43,6 +59,7 @@ class GroupchatMember with _$GroupchatMember {
|
|||||||
String? avatarPath,
|
String? avatarPath,
|
||||||
String? avatarHash,
|
String? avatarHash,
|
||||||
String? realJid,
|
String? realJid,
|
||||||
|
@BooleanTypeConverter() bool isSelf,
|
||||||
) = _GroupchatMember;
|
) = _GroupchatMember;
|
||||||
|
|
||||||
/// JSON
|
/// JSON
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:moxxyv2/shared/events.dart';
|
|||||||
import 'package:moxxyv2/shared/models/conversation.dart';
|
import 'package:moxxyv2/shared/models/conversation.dart';
|
||||||
import 'package:moxxyv2/shared/models/groupchat_member.dart';
|
import 'package:moxxyv2/shared/models/groupchat_member.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/server_info_bloc.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/conversationheader.dart';
|
||||||
import 'package:moxxyv2/ui/pages/profile/profile.dart';
|
import 'package:moxxyv2/ui/pages/profile/profile.dart';
|
||||||
import 'package:moxxyv2/ui/pages/profile/selfheader.dart';
|
import 'package:moxxyv2/ui/pages/profile/selfheader.dart';
|
||||||
@@ -55,24 +56,9 @@ class ProfileViewState extends State<ProfileView> {
|
|||||||
),
|
),
|
||||||
))! as GroupchatMembersResult;
|
))! 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
|
// 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.
|
// the avatar data and just pull it from one of the BLoCs.
|
||||||
final members = List.of(result.members)
|
final members = List.of(result.members)
|
||||||
..add(
|
|
||||||
GroupchatMember(
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
t.messages.you,
|
|
||||||
Role.none,
|
|
||||||
Affiliation.none,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
..sort(groupchatMemberSortingFunction);
|
..sort(groupchatMemberSortingFunction);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -86,6 +72,55 @@ class ProfileViewState extends State<ProfileView> {
|
|||||||
_initStateAsync();
|
_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() {
|
Widget _buildMemberList() {
|
||||||
if (_members == null) {
|
if (_members == null) {
|
||||||
return const SliverToBoxAdapter(
|
return const SliverToBoxAdapter(
|
||||||
@@ -96,30 +131,8 @@ class ProfileViewState extends State<ProfileView> {
|
|||||||
return SliverList.builder(
|
return SliverList.builder(
|
||||||
itemCount: _members!.length,
|
itemCount: _members!.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
final member = _members![index];
|
||||||
leading: CachingXMPPAvatar(
|
return _buildMemberTile(member);
|
||||||
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,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user