mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-17 09:35:12 +00:00
design: Nicer user bottom sheet
This commit is contained in:
parent
195694a252
commit
924e4bce23
7 changed files with 192 additions and 160 deletions
|
@ -2540,5 +2540,6 @@
|
||||||
"replace": "Ersetzen",
|
"replace": "Ersetzen",
|
||||||
"@replace": {},
|
"@replace": {},
|
||||||
"sendTypingNotifications": "Tippbenachrichtigungen senden",
|
"sendTypingNotifications": "Tippbenachrichtigungen senden",
|
||||||
"@sendTypingNotifications": {}
|
"@sendTypingNotifications": {},
|
||||||
|
"profileNotFound": "Der Benutzer konnte auf dem Server nicht gefunden werden. Vielleicht gibt es ein Verbindungsproblem oder der Benutzer existiert nicht."
|
||||||
}
|
}
|
||||||
|
|
|
@ -2500,5 +2500,6 @@
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"provider": {}
|
"provider": {}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"profileNotFound": "The user could not be found on the server. Maybe there is a connection problem or the user doesn't exist."
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/space_view.dart';
|
import 'package:fluffychat/pages/chat_list/space_view.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/stories_header.dart';
|
import 'package:fluffychat/pages/chat_list/stories_header.dart';
|
||||||
|
import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart';
|
||||||
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
|
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/stream_extension.dart';
|
import 'package:fluffychat/utils/stream_extension.dart';
|
||||||
import 'package:fluffychat/widgets/avatar.dart';
|
import 'package:fluffychat/widgets/avatar.dart';
|
||||||
import 'package:fluffychat/widgets/profile_bottom_sheet.dart';
|
|
||||||
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
|
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
|
||||||
import '../../config/themes.dart';
|
import '../../config/themes.dart';
|
||||||
import '../../widgets/connection_status_header.dart';
|
import '../../widgets/connection_status_header.dart';
|
||||||
|
@ -150,9 +150,8 @@ class ChatListViewBody extends StatelessWidget {
|
||||||
userSearchResult.results[i].avatarUrl,
|
userSearchResult.results[i].avatarUrl,
|
||||||
onPressed: () => showAdaptiveBottomSheet(
|
onPressed: () => showAdaptiveBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (c) => ProfileBottomSheet(
|
builder: (c) => UserBottomSheet(
|
||||||
userId:
|
profile: userSearchResult.results[i],
|
||||||
userSearchResult.results[i].userId,
|
|
||||||
outerContext: context,
|
outerContext: context,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,17 +21,66 @@ enum UserBottomSheetAction {
|
||||||
ignore,
|
ignore,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LoadProfileBottomSheet extends StatelessWidget {
|
||||||
|
final String userId;
|
||||||
|
final BuildContext outerContext;
|
||||||
|
|
||||||
|
const LoadProfileBottomSheet({
|
||||||
|
super.key,
|
||||||
|
required this.userId,
|
||||||
|
required this.outerContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<ProfileInformation>(
|
||||||
|
future: Matrix.of(context)
|
||||||
|
.client
|
||||||
|
.getUserProfile(userId)
|
||||||
|
.timeout(const Duration(seconds: 3)),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState != ConnectionState.done) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: CloseButton(
|
||||||
|
onPressed: Navigator.of(context, rootNavigator: false).pop,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: const Center(
|
||||||
|
child: CircularProgressIndicator.adaptive(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return UserBottomSheet(
|
||||||
|
outerContext: outerContext,
|
||||||
|
profile: Profile(
|
||||||
|
userId: userId,
|
||||||
|
avatarUrl: snapshot.data?.avatarUrl,
|
||||||
|
displayName: snapshot.data?.displayname,
|
||||||
|
),
|
||||||
|
profileSearchError: snapshot.error,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class UserBottomSheet extends StatefulWidget {
|
class UserBottomSheet extends StatefulWidget {
|
||||||
final User user;
|
final User? user;
|
||||||
|
final Profile? profile;
|
||||||
final Function? onMention;
|
final Function? onMention;
|
||||||
final BuildContext outerContext;
|
final BuildContext outerContext;
|
||||||
|
final Object? profileSearchError;
|
||||||
|
|
||||||
const UserBottomSheet({
|
const UserBottomSheet({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.user,
|
this.user,
|
||||||
|
this.profile,
|
||||||
required this.outerContext,
|
required this.outerContext,
|
||||||
this.onMention,
|
this.onMention,
|
||||||
}) : super(key: key);
|
this.profileSearchError,
|
||||||
|
}) : assert(user != null || profile != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
UserBottomSheetController createState() => UserBottomSheetController();
|
UserBottomSheetController createState() => UserBottomSheetController();
|
||||||
|
@ -39,6 +88,9 @@ class UserBottomSheet extends StatefulWidget {
|
||||||
|
|
||||||
class UserBottomSheetController extends State<UserBottomSheet> {
|
class UserBottomSheetController extends State<UserBottomSheet> {
|
||||||
void participantAction(UserBottomSheetAction action) async {
|
void participantAction(UserBottomSheetAction action) async {
|
||||||
|
final user = widget.user;
|
||||||
|
final userId = user?.id ?? widget.profile?.userId;
|
||||||
|
if (userId == null) throw ('user or profile must not be null!');
|
||||||
// ignore: prefer_function_declarations_over_variables
|
// ignore: prefer_function_declarations_over_variables
|
||||||
final Function askConfirmation = () async => (await showOkCancelAlertDialog(
|
final Function askConfirmation = () async => (await showOkCancelAlertDialog(
|
||||||
useRootNavigator: false,
|
useRootNavigator: false,
|
||||||
|
@ -50,7 +102,8 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
||||||
OkCancelResult.ok);
|
OkCancelResult.ok);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case UserBottomSheetAction.report:
|
case UserBottomSheetAction.report:
|
||||||
final event = widget.user;
|
if (user == null) throw ('User must not be null for this action!');
|
||||||
|
|
||||||
final score = await showConfirmationDialog<int>(
|
final score = await showConfirmationDialog<int>(
|
||||||
context: context,
|
context: context,
|
||||||
title: L10n.of(context)!.reportUser,
|
title: L10n.of(context)!.reportUser,
|
||||||
|
@ -85,8 +138,8 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
||||||
final result = await showFutureLoadingDialog(
|
final result = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => Matrix.of(context).client.reportContent(
|
future: () => Matrix.of(context).client.reportContent(
|
||||||
event.roomId!,
|
user.roomId!,
|
||||||
event.eventId,
|
user.eventId,
|
||||||
reason: reason.single,
|
reason: reason.single,
|
||||||
score: score,
|
score: score,
|
||||||
),
|
),
|
||||||
|
@ -97,46 +150,51 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case UserBottomSheetAction.mention:
|
case UserBottomSheetAction.mention:
|
||||||
|
if (user == null) throw ('User must not be null for this action!');
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
widget.onMention!();
|
widget.onMention!();
|
||||||
break;
|
break;
|
||||||
case UserBottomSheetAction.ban:
|
case UserBottomSheetAction.ban:
|
||||||
|
if (user == null) throw ('User must not be null for this action!');
|
||||||
if (await askConfirmation()) {
|
if (await askConfirmation()) {
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.user.ban(),
|
future: () => user.ban(),
|
||||||
);
|
);
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UserBottomSheetAction.unban:
|
case UserBottomSheetAction.unban:
|
||||||
|
if (user == null) throw ('User must not be null for this action!');
|
||||||
if (await askConfirmation()) {
|
if (await askConfirmation()) {
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.user.unban(),
|
future: () => user.unban(),
|
||||||
);
|
);
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UserBottomSheetAction.kick:
|
case UserBottomSheetAction.kick:
|
||||||
|
if (user == null) throw ('User must not be null for this action!');
|
||||||
if (await askConfirmation()) {
|
if (await askConfirmation()) {
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.user.kick(),
|
future: () => user.kick(),
|
||||||
);
|
);
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UserBottomSheetAction.permission:
|
case UserBottomSheetAction.permission:
|
||||||
|
if (user == null) throw ('User must not be null for this action!');
|
||||||
final newPermission = await showPermissionChooser(
|
final newPermission = await showPermissionChooser(
|
||||||
context,
|
context,
|
||||||
currentLevel: widget.user.powerLevel,
|
currentLevel: user.powerLevel,
|
||||||
);
|
);
|
||||||
if (newPermission != null) {
|
if (newPermission != null) {
|
||||||
if (newPermission == 100 && await askConfirmation() == false) break;
|
if (newPermission == 100 && await askConfirmation() == false) break;
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.user.setPower(newPermission),
|
future: () => user.setPower(newPermission),
|
||||||
);
|
);
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
}
|
}
|
||||||
|
@ -144,7 +202,9 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
||||||
case UserBottomSheetAction.message:
|
case UserBottomSheetAction.message:
|
||||||
final roomIdResult = await showFutureLoadingDialog(
|
final roomIdResult = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => widget.user.startDirectChat(),
|
future: () => Matrix.of(context)
|
||||||
|
.client
|
||||||
|
.startDirectChat(user?.id ?? widget.profile!.userId),
|
||||||
);
|
);
|
||||||
if (roomIdResult.error != null) return;
|
if (roomIdResult.error != null) return;
|
||||||
widget.outerContext.go(['', 'rooms', roomIdResult.result!].join('/'));
|
widget.outerContext.go(['', 'rooms', roomIdResult.result!].join('/'));
|
||||||
|
@ -154,7 +214,9 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
||||||
if (await askConfirmation()) {
|
if (await askConfirmation()) {
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () => Matrix.of(context).client.ignoreUser(widget.user.id),
|
future: () => Matrix.of(context)
|
||||||
|
.client
|
||||||
|
.ignoreUser(user?.id ?? widget.profile!.userId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/utils/fluffy_share.dart';
|
import 'package:fluffychat/utils/fluffy_share.dart';
|
||||||
import 'package:fluffychat/widgets/avatar.dart';
|
import 'package:fluffychat/widgets/avatar.dart';
|
||||||
import '../../utils/matrix_sdk_extensions/presence_extension.dart';
|
|
||||||
import '../../widgets/matrix.dart';
|
import '../../widgets/matrix.dart';
|
||||||
import 'user_bottom_sheet.dart';
|
import 'user_bottom_sheet.dart';
|
||||||
|
|
||||||
|
@ -17,24 +16,38 @@ class UserBottomSheetView extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final user = controller.widget.user;
|
final user = controller.widget.user;
|
||||||
|
final userId = (user?.id ?? controller.widget.profile?.userId)!;
|
||||||
|
final displayname = (user?.calcDisplayname() ??
|
||||||
|
controller.widget.profile?.displayName ??
|
||||||
|
controller.widget.profile?.userId.localpart)!;
|
||||||
|
final avatarUrl = user?.avatarUrl ?? controller.widget.profile?.avatarUrl;
|
||||||
|
|
||||||
final client = Matrix.of(context).client;
|
final client = Matrix.of(context).client;
|
||||||
final presence = client.presences[user.id];
|
final profileSearchError = controller.widget.profileSearchError;
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: CloseButton(
|
leading: CloseButton(
|
||||||
onPressed: Navigator.of(context, rootNavigator: false).pop,
|
onPressed: Navigator.of(context, rootNavigator: false).pop,
|
||||||
),
|
),
|
||||||
title: Text(user.calcDisplayname()),
|
|
||||||
actions: [
|
actions: [
|
||||||
if (user.id != client.userID)
|
if (userId != client.userID &&
|
||||||
|
!client.ignoredUsers.contains(userId))
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
|
label: Text(
|
||||||
|
L10n.of(context)!.ignore,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.shield_outlined,
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
onPressed: () => controller
|
onPressed: () => controller
|
||||||
.participantAction(UserBottomSheetAction.message),
|
.participantAction(UserBottomSheetAction.ignore),
|
||||||
icon: const Icon(Icons.forum_outlined),
|
|
||||||
label: Text(L10n.of(context)!.sendAMessage),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -45,31 +58,81 @@ class UserBottomSheetView extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Avatar(
|
child: Material(
|
||||||
mxContent: user.avatarUrl,
|
elevation:
|
||||||
name: user.calcDisplayname(),
|
Theme.of(context).appBarTheme.scrolledUnderElevation ??
|
||||||
size: Avatar.defaultSize * 2,
|
4,
|
||||||
fontSize: 24,
|
shadowColor: Theme.of(context).appBarTheme.shadowColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: BorderSide(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Avatar.defaultSize * 2.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Avatar(
|
||||||
|
mxContent: avatarUrl,
|
||||||
|
name: displayname,
|
||||||
|
size: Avatar.defaultSize * 2.5,
|
||||||
|
fontSize: 18 * 2.5,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListTile(
|
child: Column(
|
||||||
contentPadding: const EdgeInsets.only(right: 16.0),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
title: Text(user.id),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
subtitle: presence == null
|
children: [
|
||||||
? null
|
TextButton.icon(
|
||||||
: Text(presence.getLocalizedLastActiveAgo(context)),
|
onPressed: () => FluffyShare.share(userId, context),
|
||||||
trailing: IconButton(
|
icon: Icon(
|
||||||
icon: Icon(Icons.adaptive.share),
|
Icons.adaptive.share_outlined,
|
||||||
onPressed: () => FluffyShare.share(
|
size: 16,
|
||||||
user.id,
|
),
|
||||||
context,
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context).colorScheme.onBackground,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
displayname,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
// style: const TextStyle(fontSize: 18),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
TextButton.icon(
|
||||||
|
onPressed: () => FluffyShare.share(userId, context),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.copy_outlined,
|
||||||
|
size: 14,
|
||||||
|
),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor:
|
||||||
|
Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
userId,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
// style: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (userId != client.userID)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
onPressed: () => controller
|
||||||
|
.participantAction(UserBottomSheetAction.message),
|
||||||
|
icon: const Icon(Icons.forum_outlined),
|
||||||
|
label: Text(L10n.of(context)!.sendAMessage),
|
||||||
|
),
|
||||||
|
),
|
||||||
if (controller.widget.onMention != null)
|
if (controller.widget.onMention != null)
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.alternate_email_outlined),
|
leading: const Icon(Icons.alternate_email_outlined),
|
||||||
|
@ -77,53 +140,58 @@ class UserBottomSheetView extends StatelessWidget {
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
controller.participantAction(UserBottomSheetAction.mention),
|
controller.participantAction(UserBottomSheetAction.mention),
|
||||||
),
|
),
|
||||||
if (user.canChangePowerLevel)
|
if (user != null && user.canChangePowerLevel)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context)!.setPermissionsLevel),
|
title: Text(L10n.of(context)!.setPermissionsLevel),
|
||||||
leading: const Icon(Icons.edit_attributes_outlined),
|
leading: const Icon(Icons.edit_attributes_outlined),
|
||||||
onTap: () => controller
|
onTap: () => controller
|
||||||
.participantAction(UserBottomSheetAction.permission),
|
.participantAction(UserBottomSheetAction.permission),
|
||||||
),
|
),
|
||||||
if (user.canKick)
|
if (user != null && user.canKick)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context)!.kickFromChat),
|
title: Text(L10n.of(context)!.kickFromChat),
|
||||||
leading: const Icon(Icons.exit_to_app_outlined),
|
leading: const Icon(Icons.exit_to_app_outlined),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
controller.participantAction(UserBottomSheetAction.kick),
|
controller.participantAction(UserBottomSheetAction.kick),
|
||||||
),
|
),
|
||||||
if (user.canBan && user.membership != Membership.ban)
|
if (user != null &&
|
||||||
|
user.canBan &&
|
||||||
|
user.membership != Membership.ban)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context)!.banFromChat),
|
title: Text(L10n.of(context)!.banFromChat),
|
||||||
leading: const Icon(Icons.warning_sharp),
|
leading: const Icon(Icons.warning_sharp),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
controller.participantAction(UserBottomSheetAction.ban),
|
controller.participantAction(UserBottomSheetAction.ban),
|
||||||
)
|
)
|
||||||
else if (user.canBan && user.membership == Membership.ban)
|
else if (user != null &&
|
||||||
|
user.canBan &&
|
||||||
|
user.membership == Membership.ban)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context)!.unbanFromChat),
|
title: Text(L10n.of(context)!.unbanFromChat),
|
||||||
leading: const Icon(Icons.warning_outlined),
|
leading: const Icon(Icons.warning_outlined),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
controller.participantAction(UserBottomSheetAction.unban),
|
controller.participantAction(UserBottomSheetAction.unban),
|
||||||
),
|
),
|
||||||
if (user.id != client.userID &&
|
if (user != null && user.id != client.userID)
|
||||||
!client.ignoredUsers.contains(user.id))
|
|
||||||
ListTile(
|
ListTile(
|
||||||
textColor: Theme.of(context).colorScheme.onErrorContainer,
|
textColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||||
iconColor: Theme.of(context).colorScheme.onErrorContainer,
|
iconColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||||
title: Text(L10n.of(context)!.ignore),
|
|
||||||
leading: const Icon(Icons.block),
|
|
||||||
onTap: () =>
|
|
||||||
controller.participantAction(UserBottomSheetAction.ignore),
|
|
||||||
),
|
|
||||||
if (user.id != client.userID)
|
|
||||||
ListTile(
|
|
||||||
textColor: Theme.of(context).colorScheme.error,
|
|
||||||
iconColor: Theme.of(context).colorScheme.error,
|
|
||||||
title: Text(L10n.of(context)!.reportUser),
|
title: Text(L10n.of(context)!.reportUser),
|
||||||
leading: const Icon(Icons.shield_outlined),
|
leading: const Icon(Icons.report_outlined),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
controller.participantAction(UserBottomSheetAction.report),
|
controller.participantAction(UserBottomSheetAction.report),
|
||||||
),
|
),
|
||||||
|
if (profileSearchError != null)
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(
|
||||||
|
Icons.warning_outlined,
|
||||||
|
color: Colors.orange,
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
L10n.of(context)!.profileNotFound,
|
||||||
|
style: const TextStyle(color: Colors.orange),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -11,9 +11,9 @@ import 'package:punycode/punycode.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
|
import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart';
|
||||||
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
|
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
import 'package:fluffychat/widgets/profile_bottom_sheet.dart';
|
|
||||||
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
|
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
|
||||||
import 'platform_infos.dart';
|
import 'platform_infos.dart';
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ class UrlLauncher {
|
||||||
} else if (identityParts.primaryIdentifier.sigil == '@') {
|
} else if (identityParts.primaryIdentifier.sigil == '@') {
|
||||||
await showAdaptiveBottomSheet(
|
await showAdaptiveBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (c) => ProfileBottomSheet(
|
builder: (c) => LoadProfileBottomSheet(
|
||||||
userId: identityParts.primaryIdentifier,
|
userId: identityParts.primaryIdentifier,
|
||||||
outerContext: context,
|
outerContext: context,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
import 'package:matrix/matrix.dart';
|
|
||||||
|
|
||||||
import 'package:fluffychat/widgets/avatar.dart';
|
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
|
||||||
|
|
||||||
class ProfileBottomSheet extends StatelessWidget {
|
|
||||||
final String userId;
|
|
||||||
final BuildContext outerContext;
|
|
||||||
|
|
||||||
const ProfileBottomSheet({
|
|
||||||
required this.userId,
|
|
||||||
required this.outerContext,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
void _startDirectChat(BuildContext context) async {
|
|
||||||
final client = Matrix.of(context).client;
|
|
||||||
final result = await showFutureLoadingDialog<String>(
|
|
||||||
context: context,
|
|
||||||
future: () => client.startDirectChat(userId),
|
|
||||||
);
|
|
||||||
if (result.error == null) {
|
|
||||||
context.go(['', 'rooms', result.result!].join('/'));
|
|
||||||
|
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return SafeArea(
|
|
||||||
child: FutureBuilder<Profile>(
|
|
||||||
future: Matrix.of(context).client.getProfileFromUserId(userId),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
final profile = snapshot.data;
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
leading: CloseButton(
|
|
||||||
onPressed: Navigator.of(context, rootNavigator: false).pop,
|
|
||||||
),
|
|
||||||
title: ListTile(
|
|
||||||
contentPadding: const EdgeInsets.only(right: 16.0),
|
|
||||||
title: Text(
|
|
||||||
profile?.displayName ?? userId.localpart ?? userId,
|
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
userId,
|
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: OutlinedButton.icon(
|
|
||||||
onPressed: () => _startDirectChat(context),
|
|
||||||
icon: Icon(Icons.adaptive.share_outlined),
|
|
||||||
label: Text(L10n.of(context)!.share),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: ListView(
|
|
||||||
children: [
|
|
||||||
Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Avatar(
|
|
||||||
mxContent: profile?.avatarUrl,
|
|
||||||
name: profile?.displayName ?? userId,
|
|
||||||
size: Avatar.defaultSize * 3,
|
|
||||||
fontSize: 36,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: double.infinity,
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
child: FloatingActionButton.extended(
|
|
||||||
onPressed: () => _startDirectChat(context),
|
|
||||||
label: Text(L10n.of(context)!.newChat),
|
|
||||||
icon: const Icon(Icons.send_outlined),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue