feat(ui,service): Get a basic participant list going
This commit is contained in:
@@ -355,6 +355,14 @@ files:
|
|||||||
items:
|
items:
|
||||||
type: List<SendFilesRecipient>
|
type: List<SendFilesRecipient>
|
||||||
deserialise: true
|
deserialise: true
|
||||||
|
- name: GroupchatMembersResult
|
||||||
|
extends: BackgroundEvent
|
||||||
|
implements:
|
||||||
|
- JsonImplementation
|
||||||
|
attributes:
|
||||||
|
members:
|
||||||
|
type: List<GroupchatMember>
|
||||||
|
deserialise: true
|
||||||
generate_builder: true
|
generate_builder: true
|
||||||
builder_name: "Event"
|
builder_name: "Event"
|
||||||
builder_baseclass: "BackgroundEvent"
|
builder_baseclass: "BackgroundEvent"
|
||||||
@@ -714,6 +722,12 @@ files:
|
|||||||
- JsonImplementation
|
- JsonImplementation
|
||||||
attributes:
|
attributes:
|
||||||
jids: List<String>
|
jids: List<String>
|
||||||
|
- name: GetMembersForGroupchatCommand
|
||||||
|
extends: BackgroundCommand
|
||||||
|
implements:
|
||||||
|
- JsonImplementation
|
||||||
|
attributes:
|
||||||
|
jid: String
|
||||||
generate_builder: true
|
generate_builder: true
|
||||||
# get${builder_Name}FromJson
|
# get${builder_Name}FromJson
|
||||||
builder_name: "Command"
|
builder_name: "Command"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const omemoRatchetsTable = 'OmemoRatchets';
|
|||||||
const omemoTrustTable = 'OmemoTrustTable';
|
const omemoTrustTable = 'OmemoTrustTable';
|
||||||
const notificationsTable = 'Notifications';
|
const notificationsTable = 'Notifications';
|
||||||
const groupchatTable = 'Groupchat';
|
const groupchatTable = 'Groupchat';
|
||||||
|
const groupchatMembersTable = 'GroupchatMembers';
|
||||||
|
|
||||||
const typeString = 0;
|
const typeString = 0;
|
||||||
const typeInt = 1;
|
const typeInt = 1;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import 'package:moxxyv2/service/database/migrations/0003_notifications.dart';
|
|||||||
import 'package:moxxyv2/service/database/migrations/0003_occupant_id.dart';
|
import 'package:moxxyv2/service/database/migrations/0003_occupant_id.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0003_remove_subscriptions.dart';
|
import 'package:moxxyv2/service/database/migrations/0003_remove_subscriptions.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0003_sticker_pack_timestamp.dart';
|
import 'package:moxxyv2/service/database/migrations/0003_sticker_pack_timestamp.dart';
|
||||||
|
import 'package:moxxyv2/service/database/migrations/0004_groupchat_members.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0004_new_avatar_cache.dart';
|
import 'package:moxxyv2/service/database/migrations/0004_new_avatar_cache.dart';
|
||||||
import 'package:moxxyv2/service/xmpp_state.dart';
|
import 'package:moxxyv2/service/xmpp_state.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
@@ -109,6 +110,7 @@ const List<Migration<DatabaseMigrationData>> migrations = [
|
|||||||
Migration(46, upgradeFromV45ToV46),
|
Migration(46, upgradeFromV45ToV46),
|
||||||
Migration(47, upgradeFromV46ToV47),
|
Migration(47, upgradeFromV46ToV47),
|
||||||
Migration(48, upgradeFromV47ToV48),
|
Migration(48, upgradeFromV47ToV48),
|
||||||
|
Migration(49, upgradeFromV48ToV49),
|
||||||
];
|
];
|
||||||
|
|
||||||
class DatabaseService {
|
class DatabaseService {
|
||||||
|
|||||||
28
lib/service/database/migrations/0004_groupchat_members.dart
Normal file
28
lib/service/database/migrations/0004_groupchat_members.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'package:moxxyv2/service/database/constants.dart';
|
||||||
|
import 'package:moxxyv2/service/database/database.dart';
|
||||||
|
|
||||||
|
Future<void> upgradeFromV48ToV49(DatabaseMigrationData data) async {
|
||||||
|
final (db, _) = data;
|
||||||
|
|
||||||
|
await db.execute(
|
||||||
|
'''
|
||||||
|
CREATE TABLE $groupchatMembersTable (
|
||||||
|
roomJid TEXT NOT NULL,
|
||||||
|
accountJid TEXT NOT NULL,
|
||||||
|
nick TEXT NOT NULL,
|
||||||
|
role TEXT NOT NULL,
|
||||||
|
affiliation TEXT NOT NULL,
|
||||||
|
avatarPath TEXT,
|
||||||
|
avatarHash TEXT,
|
||||||
|
realJid TEXT,
|
||||||
|
PRIMARY KEY (roomJid, accountJid, nick),
|
||||||
|
CONSTRAINT fk_muc
|
||||||
|
FOREIGN KEY (roomJid, accountJid)
|
||||||
|
REFERENCES $conversationsTable (jid, accountJid)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
)''',
|
||||||
|
);
|
||||||
|
await db.execute(
|
||||||
|
'CREATE INDEX idx_members ON $groupchatMembersTable (roomJid, accountJid)',
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -118,6 +118,7 @@ void setupBackgroundEventHandler() {
|
|||||||
performFetchRecipientInformation,
|
performFetchRecipientInformation,
|
||||||
),
|
),
|
||||||
EventTypeMatcher<ExitConversationCommand>(performConversationExited),
|
EventTypeMatcher<ExitConversationCommand>(performConversationExited),
|
||||||
|
EventTypeMatcher<GetMembersForGroupchatCommand>(performGetMembers),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
GetIt.I.registerSingleton<EventHandler>(handler);
|
GetIt.I.registerSingleton<EventHandler>(handler);
|
||||||
@@ -336,13 +337,10 @@ Future<void> performAddConversation(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (conversation!.type == ConversationType.groupchat) {
|
if (conversation!.type == ConversationType.groupchat) {
|
||||||
await GetIt.I
|
await GetIt.I.get<GroupchatService>().joinRoom(
|
||||||
.get<XmppConnection>()
|
|
||||||
.getManagerById<MUCManager>(mucManager)!
|
|
||||||
.joinRoom(
|
|
||||||
JID.fromString(conversation.jid),
|
JID.fromString(conversation.jid),
|
||||||
|
accountJid,
|
||||||
conversation.groupchatDetails!.nick,
|
conversation.groupchatDetails!.nick,
|
||||||
maxHistoryStanzas: 0,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1631,18 +1629,6 @@ Future<void> performJoinGroupchat(
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// We did not have a conversation with that JID.
|
// We did not have a conversation with that JID.
|
||||||
final joinRoomResult = await GetIt.I.get<GroupchatService>().joinRoom(
|
|
||||||
JID.fromString(jid),
|
|
||||||
accountJid,
|
|
||||||
nick,
|
|
||||||
);
|
|
||||||
if (joinRoomResult.isType<GroupchatErrorType>()) {
|
|
||||||
sendEvent(
|
|
||||||
ErrorEvent(errorId: joinRoomResult.get<GroupchatErrorType>().value),
|
|
||||||
id: id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await cs.createOrUpdateConversation(
|
await cs.createOrUpdateConversation(
|
||||||
jid,
|
jid,
|
||||||
accountJid,
|
accountJid,
|
||||||
@@ -1682,6 +1668,19 @@ Future<void> performJoinGroupchat(
|
|||||||
return newConversation;
|
return newConversation;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Join the room.
|
||||||
|
final joinRoomResult = await GetIt.I.get<GroupchatService>().joinRoom(
|
||||||
|
JID.fromString(jid),
|
||||||
|
accountJid,
|
||||||
|
nick,
|
||||||
|
);
|
||||||
|
if (joinRoomResult.isType<GroupchatErrorType>()) {
|
||||||
|
sendEvent(
|
||||||
|
ErrorEvent(errorId: joinRoomResult.get<GroupchatErrorType>().value),
|
||||||
|
id: id,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1746,3 +1745,22 @@ Future<void> performConversationExited(
|
|||||||
// Reset the active conversation
|
// Reset the active conversation
|
||||||
cs.activeConversationJid = null;
|
cs.activeConversationJid = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> performGetMembers(
|
||||||
|
GetMembersForGroupchatCommand command, {
|
||||||
|
dynamic extra,
|
||||||
|
}) async {
|
||||||
|
final accountJid = await GetIt.I.get<XmppStateService>().getAccountJid();
|
||||||
|
final gs = GetIt.I.get<GroupchatService>();
|
||||||
|
|
||||||
|
// TODO(Unknown): Page this request
|
||||||
|
sendEvent(
|
||||||
|
GroupchatMembersResult(
|
||||||
|
members: await gs.getMembers(
|
||||||
|
JID.fromString(command.jid),
|
||||||
|
accountJid!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
id: extra as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
import 'package:moxlib/moxlib.dart';
|
import 'package:moxlib/moxlib.dart';
|
||||||
import 'package:moxxmpp/moxxmpp.dart';
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
import 'package:moxxyv2/service/database/constants.dart';
|
import 'package:moxxyv2/service/database/constants.dart';
|
||||||
@@ -7,12 +8,16 @@ import 'package:moxxyv2/service/database/helpers.dart';
|
|||||||
import 'package:moxxyv2/service/xmpp_state.dart';
|
import 'package:moxxyv2/service/xmpp_state.dart';
|
||||||
import 'package:moxxyv2/shared/error_types.dart';
|
import 'package:moxxyv2/shared/error_types.dart';
|
||||||
import 'package:moxxyv2/shared/models/groupchat.dart';
|
import 'package:moxxyv2/shared/models/groupchat.dart';
|
||||||
|
import 'package:moxxyv2/shared/models/groupchat_member.dart';
|
||||||
|
|
||||||
/// The value of the "var" attribute of the field containing the avatar hash (for Prosody).
|
/// The value of the "var" attribute of the field containing the avatar hash (for Prosody).
|
||||||
const _prosodyAvatarHashFieldVar =
|
const _prosodyAvatarHashFieldVar =
|
||||||
'{http://modules.prosody.im/mod_vcard_muc}avatar#sha1';
|
'{http://modules.prosody.im/mod_vcard_muc}avatar#sha1';
|
||||||
|
|
||||||
class GroupchatService {
|
class GroupchatService {
|
||||||
|
/// Logger.
|
||||||
|
final Logger _log = Logger('GroupchatService');
|
||||||
|
|
||||||
/// Retrieves the information about a group chat room specified by the given
|
/// Retrieves the information about a group chat room specified by the given
|
||||||
/// JID.
|
/// JID.
|
||||||
/// Returns a [Future] that resolves to a [RoomInformation] object containing
|
/// Returns a [Future] that resolves to a [RoomInformation] object containing
|
||||||
@@ -59,6 +64,35 @@ class GroupchatService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
// TODO(Unknown): Maybe be a bit smarter about it
|
||||||
|
final db = GetIt.I.get<DatabaseService>().database;
|
||||||
|
await db.delete(
|
||||||
|
groupchatMembersTable,
|
||||||
|
where: 'roomJid = ? AND accountJid = ?',
|
||||||
|
whereArgs: [muc.toString(), accountJid],
|
||||||
|
);
|
||||||
|
final state = (await mm.getRoomState(muc))!;
|
||||||
|
final members = List<GroupchatMember>.empty(growable: true);
|
||||||
|
_log.finest('Got ${state.members.length} members for $muc');
|
||||||
|
for (final rawMember in state.members.values) {
|
||||||
|
final member = GroupchatMember(
|
||||||
|
accountJid,
|
||||||
|
muc.toString(),
|
||||||
|
rawMember.nick,
|
||||||
|
rawMember.role,
|
||||||
|
rawMember.affiliation,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
await db.insert(
|
||||||
|
groupchatMembersTable,
|
||||||
|
member.toJson(),
|
||||||
|
);
|
||||||
|
members.add(member);
|
||||||
|
}
|
||||||
|
members.sort((a, b) => a.nick.compareTo(b.nick));
|
||||||
|
|
||||||
return Result(
|
return Result(
|
||||||
GroupchatDetails(
|
GroupchatDetails(
|
||||||
muc.toBare().toString(),
|
muc.toBare().toString(),
|
||||||
@@ -157,4 +191,13 @@ class GroupchatService {
|
|||||||
}
|
}
|
||||||
return hashField.values.first;
|
return hashField.values.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<GroupchatMember>> getMembers(JID muc, String accountJid) async {
|
||||||
|
final result = await GetIt.I.get<DatabaseService>().database.query(
|
||||||
|
groupchatMembersTable,
|
||||||
|
where: 'roomJid = ? AND accountJid = ?',
|
||||||
|
whereArgs: [muc.toString(), accountJid],
|
||||||
|
);
|
||||||
|
return result.map(GroupchatMember.fromJson).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'package:moxdns/moxdns.dart';
|
|||||||
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
|
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
|
||||||
|
|
||||||
class MoxxyTCPSocketWrapper extends TCPSocketWrapper {
|
class MoxxyTCPSocketWrapper extends TCPSocketWrapper {
|
||||||
MoxxyTCPSocketWrapper() : super();
|
MoxxyTCPSocketWrapper() : super(false);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MoxSrvRecord>> srvQuery(String domain, bool dnssec) async {
|
Future<List<MoxSrvRecord>> srvQuery(String domain, bool dnssec) async {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:moxlib/moxlib.dart';
|
import 'package:moxlib/moxlib.dart';
|
||||||
import 'package:moxxy_native/moxxy_native.dart';
|
import 'package:moxxy_native/moxxy_native.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/message.dart';
|
import 'package:moxxyv2/shared/models/message.dart';
|
||||||
import 'package:moxxyv2/shared/models/omemo_device.dart';
|
import 'package:moxxyv2/shared/models/omemo_device.dart';
|
||||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||||
|
|||||||
51
lib/shared/models/groupchat_member.dart
Normal file
51
lib/shared/models/groupchat_member.dart
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
|
|
||||||
|
part 'groupchat_member.freezed.dart';
|
||||||
|
part 'groupchat_member.g.dart';
|
||||||
|
|
||||||
|
class RoleTypeConverter extends JsonConverter<Role, String> {
|
||||||
|
const RoleTypeConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Role fromJson(String json) {
|
||||||
|
return Role.fromString(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toJson(Role object) {
|
||||||
|
return object.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AffiliationTypeConverter extends JsonConverter<Affiliation, String> {
|
||||||
|
const AffiliationTypeConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Affiliation fromJson(String json) {
|
||||||
|
return Affiliation.fromString(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toJson(Affiliation object) {
|
||||||
|
return object.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class GroupchatMember with _$GroupchatMember {
|
||||||
|
factory GroupchatMember(
|
||||||
|
String accountJid,
|
||||||
|
String roomJid,
|
||||||
|
String nick,
|
||||||
|
@RoleTypeConverter() Role role,
|
||||||
|
@AffiliationTypeConverter() Affiliation affiliation,
|
||||||
|
String? avatarPath,
|
||||||
|
String? avatarHash,
|
||||||
|
String? realJid,
|
||||||
|
) = _GroupchatMember;
|
||||||
|
|
||||||
|
/// JSON
|
||||||
|
factory GroupchatMember.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$GroupchatMemberFromJson(json);
|
||||||
|
}
|
||||||
@@ -1,36 +1,154 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
|
import 'package:moxxy_native/moxxy_native.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
|
import 'package:moxxyv2/shared/commands.dart';
|
||||||
|
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/bloc/server_info_bloc.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';
|
||||||
|
import 'package:moxxyv2/ui/widgets/avatar.dart';
|
||||||
|
|
||||||
class ProfileView extends StatelessWidget {
|
int affiliationToInt(Affiliation a) => switch (a) {
|
||||||
|
Affiliation.owner => 4,
|
||||||
|
Affiliation.admin => 3,
|
||||||
|
Affiliation.member => 2,
|
||||||
|
Affiliation.none => 1,
|
||||||
|
Affiliation.outcast => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
int affiliationSortingFunction(Affiliation a, Affiliation b) =>
|
||||||
|
affiliationToInt(a).compareTo(affiliationToInt(b));
|
||||||
|
|
||||||
|
int groupchatMemberSortingFunction(GroupchatMember a, GroupchatMember b) {
|
||||||
|
if (a.affiliation == b.affiliation) {
|
||||||
|
return b.nick.compareTo(a.nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
return affiliationSortingFunction(b.affiliation, a.affiliation);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileView extends StatefulWidget {
|
||||||
const ProfileView(this.arguments, {super.key});
|
const ProfileView(this.arguments, {super.key});
|
||||||
|
|
||||||
final ProfileArguments arguments;
|
final ProfileArguments arguments;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ProfileViewState createState() => ProfileViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileViewState extends State<ProfileView> {
|
||||||
|
List<GroupchatMember>? _members;
|
||||||
|
|
||||||
|
Future<void> _initStateAsync() async {
|
||||||
|
if (widget.arguments.type != ConversationType.groupchat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final result = (await getForegroundService().send(
|
||||||
|
GetMembersForGroupchatCommand(
|
||||||
|
jid: widget.arguments.jid,
|
||||||
|
),
|
||||||
|
))! 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(() {
|
||||||
|
_members = members;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_initStateAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildMemberList() {
|
||||||
|
if (_members == null) {
|
||||||
|
return const SliverToBoxAdapter(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Stack(
|
body: Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
ListView(
|
CustomScrollView(
|
||||||
children: [
|
slivers: [
|
||||||
Padding(
|
SliverToBoxAdapter(
|
||||||
padding: const EdgeInsets.only(top: 8),
|
child: Padding(
|
||||||
child: arguments.isSelfProfile
|
padding: const EdgeInsets.only(top: 8),
|
||||||
? SelfProfileHeader(arguments)
|
child: widget.arguments.isSelfProfile
|
||||||
: const ConversationProfileHeader(),
|
? SelfProfileHeader(widget.arguments)
|
||||||
|
: const ConversationProfileHeader(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
if (widget.arguments.type == ConversationType.groupchat)
|
||||||
|
_buildMemberList(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 8,
|
top: 8,
|
||||||
right: 8,
|
right: 8,
|
||||||
child: Visibility(
|
child: Visibility(
|
||||||
visible: arguments.isSelfProfile,
|
visible: widget.arguments.isSelfProfile,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
icon: const Icon(Icons.info_outline),
|
icon: const Icon(Icons.info_outline),
|
||||||
|
|||||||
17
pubspec.lock
17
pubspec.lock
@@ -988,11 +988,9 @@ packages:
|
|||||||
moxxmpp:
|
moxxmpp:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "packages/moxxmpp"
|
path: "../moxxmpp/packages/moxxmpp"
|
||||||
ref: HEAD
|
relative: true
|
||||||
resolved-ref: "814f99436b4bc5ff53136dfce73c2735b140b474"
|
source: path
|
||||||
url: "https://codeberg.org/moxxy/moxxmpp.git"
|
|
||||||
source: git
|
|
||||||
version: "0.4.0"
|
version: "0.4.0"
|
||||||
moxxmpp_color:
|
moxxmpp_color:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
@@ -1005,11 +1003,10 @@ packages:
|
|||||||
moxxmpp_socket_tcp:
|
moxxmpp_socket_tcp:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: moxxmpp_socket_tcp
|
path: "../moxxmpp/packages/moxxmpp_socket_tcp"
|
||||||
sha256: "32c2ee3316c6b87d9c6082e8ba35bb577700f7c0294587fb0b79e62c54d90577"
|
relative: true
|
||||||
url: "https://git.polynom.me/api/packages/Moxxy/pub/"
|
source: path
|
||||||
source: hosted
|
version: "0.4.0"
|
||||||
version: "0.3.1"
|
|
||||||
moxxy_native:
|
moxxy_native:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
20
pubspec.yaml
20
pubspec.yaml
@@ -67,7 +67,7 @@ dependencies:
|
|||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
moxxmpp_socket_tcp:
|
moxxmpp_socket_tcp:
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
version: 0.3.1
|
version: 0.4.0
|
||||||
moxxy_native:
|
moxxy_native:
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
version: 0.3.2
|
version: 0.3.2
|
||||||
@@ -121,18 +121,18 @@ dev_dependencies:
|
|||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
# NOTE: Leave here for development purposes
|
# NOTE: Leave here for development purposes
|
||||||
# moxxmpp:
|
moxxmpp:
|
||||||
# path: ../moxxmpp/packages/moxxmpp
|
path: ../moxxmpp/packages/moxxmpp
|
||||||
# moxxmpp_socket_tcp:
|
moxxmpp_socket_tcp:
|
||||||
# path: ../moxxmpp/packages/moxxmpp_socket_tcp
|
path: ../moxxmpp/packages/moxxmpp_socket_tcp
|
||||||
# omemo_dart:
|
# omemo_dart:
|
||||||
# path: ../../Personal/omemo_dart
|
# path: ../../Personal/omemo_dart
|
||||||
|
|
||||||
moxxmpp:
|
#moxxmpp:
|
||||||
git:
|
# git:
|
||||||
url: https://codeberg.org/moxxy/moxxmpp.git
|
# url: https://codeberg.org/moxxy/moxxmpp.git
|
||||||
rev: 814f99436b4bc5ff53136dfce73c2735b140b474
|
# rev: 814f99436b4bc5ff53136dfce73c2735b140b474
|
||||||
path: packages/moxxmpp
|
# path: packages/moxxmpp
|
||||||
|
|
||||||
# NOTE: Leave here for development purposes
|
# NOTE: Leave here for development purposes
|
||||||
# moxxy_native:
|
# moxxy_native:
|
||||||
|
|||||||
Reference in New Issue
Block a user