fluffychat merge
This commit is contained in:
commit
236f192877
7 changed files with 264 additions and 145 deletions
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
// import 'package:fluffychat/config/app_config.dart';
|
||||
// import 'package:fluffychat/l10n/l10n.dart';
|
||||
// import 'package:fluffychat/pages/chat/encryption_button.dart';
|
||||
// import 'package:fluffychat/utils/other_party_can_receive.dart';
|
||||
// import 'package:fluffychat/utils/platform_infos.dart';
|
||||
// import 'package:fluffychat/widgets/avatar.dart';
|
||||
|
|
@ -227,7 +228,6 @@
|
|||
// ),
|
||||
// Container(
|
||||
// height: height,
|
||||
// width: height,
|
||||
// alignment: Alignment.center,
|
||||
// child: IconButton(
|
||||
// tooltip: L10n.of(context).emojis,
|
||||
|
|
@ -256,6 +256,11 @@
|
|||
// onPressed: controller.emojiPickerAction,
|
||||
// ),
|
||||
// ),
|
||||
// Container(
|
||||
// height: height,
|
||||
// alignment: Alignment.center,
|
||||
// child: EncryptionButton(controller.room),
|
||||
// ),
|
||||
// if (Matrix.of(context).isMultiAccount &&
|
||||
// Matrix.of(context).hasComplexBundles &&
|
||||
// Matrix.of(context).currentBundle!.length > 1)
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ class ChatView extends StatelessWidget {
|
|||
// icon: const Icon(Icons.call_outlined),
|
||||
// tooltip: L10n.of(context).placeCall,
|
||||
// ),
|
||||
// EncryptionButton(controller.room),
|
||||
// ChatSettingsPopupMenu(controller.room, true),
|
||||
// ];
|
||||
// }
|
||||
|
|
@ -488,67 +487,67 @@ class ChatView extends StatelessWidget {
|
|||
// #Pangea
|
||||
// else if (controller.room.canSendDefaultMessages &&
|
||||
// controller.room.membership == Membership.join)
|
||||
// Container(
|
||||
// margin: EdgeInsets.all(bottomSheetPadding),
|
||||
// constraints: const BoxConstraints(
|
||||
// maxWidth: FluffyThemes.maxTimelineWidth,
|
||||
// ),
|
||||
// alignment: Alignment.center,
|
||||
// child: Material(
|
||||
// clipBehavior: Clip.hardEdge,
|
||||
// color: controller.selectedEvents.isNotEmpty
|
||||
// ? theme.colorScheme.tertiaryContainer
|
||||
// : theme.colorScheme.surfaceContainerHigh,
|
||||
// borderRadius: const BorderRadius.all(
|
||||
// Radius.circular(24),
|
||||
// Container(
|
||||
// margin: EdgeInsets.all(bottomSheetPadding),
|
||||
// constraints: const BoxConstraints(
|
||||
// maxWidth: FluffyThemes.maxTimelineWidth,
|
||||
// ),
|
||||
// child: controller.room.isAbandonedDMRoom == true
|
||||
// ? Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.spaceEvenly,
|
||||
// children: [
|
||||
// TextButton.icon(
|
||||
// style: TextButton.styleFrom(
|
||||
// padding: const EdgeInsets.all(
|
||||
// 16,
|
||||
// alignment: Alignment.center,
|
||||
// child: Material(
|
||||
// clipBehavior: Clip.hardEdge,
|
||||
// color: controller.selectedEvents.isNotEmpty
|
||||
// ? theme.colorScheme.tertiaryContainer
|
||||
// : theme.colorScheme.surfaceContainerHigh,
|
||||
// borderRadius: const BorderRadius.all(
|
||||
// Radius.circular(24),
|
||||
// ),
|
||||
// child: controller.room.isAbandonedDMRoom == true
|
||||
// ? Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.spaceEvenly,
|
||||
// children: [
|
||||
// TextButton.icon(
|
||||
// style: TextButton.styleFrom(
|
||||
// padding: const EdgeInsets.all(
|
||||
// 16,
|
||||
// ),
|
||||
// foregroundColor:
|
||||
// theme.colorScheme.error,
|
||||
// ),
|
||||
// foregroundColor:
|
||||
// theme.colorScheme.error,
|
||||
// ),
|
||||
// icon: const Icon(
|
||||
// Icons.archive_outlined,
|
||||
// ),
|
||||
// onPressed: controller.leaveChat,
|
||||
// label: Text(
|
||||
// L10n.of(context).leave,
|
||||
// ),
|
||||
// ),
|
||||
// TextButton.icon(
|
||||
// style: TextButton.styleFrom(
|
||||
// padding: const EdgeInsets.all(
|
||||
// 16,
|
||||
// icon: const Icon(
|
||||
// Icons.archive_outlined,
|
||||
// ),
|
||||
// onPressed: controller.leaveChat,
|
||||
// label: Text(
|
||||
// L10n.of(context).leave,
|
||||
// ),
|
||||
// ),
|
||||
// icon: const Icon(
|
||||
// Icons.forum_outlined,
|
||||
// TextButton.icon(
|
||||
// style: TextButton.styleFrom(
|
||||
// padding: const EdgeInsets.all(
|
||||
// 16,
|
||||
// ),
|
||||
// ),
|
||||
// icon: const Icon(
|
||||
// Icons.forum_outlined,
|
||||
// ),
|
||||
// onPressed: controller.recreateChat,
|
||||
// label: Text(
|
||||
// L10n.of(context).reopenChat,
|
||||
// ),
|
||||
// ),
|
||||
// onPressed: controller.recreateChat,
|
||||
// label: Text(
|
||||
// L10n.of(context).reopenChat,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// )
|
||||
// : Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// ReplyDisplay(controller),
|
||||
// ChatInputRow(controller),
|
||||
// ChatEmojiPicker(controller),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// )
|
||||
// : Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// ReplyDisplay(controller),
|
||||
// ChatInputRow(controller),
|
||||
// ChatEmojiPicker(controller),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
else if (controller.room.canSendDefaultMessages &&
|
||||
controller.room.membership == Membership.join &&
|
||||
(controller.room.activityPlan == null ||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:badges/badges.dart' as b;
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
|
|
@ -12,6 +13,7 @@ class EncryptionButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return StreamBuilder<SyncUpdate>(
|
||||
stream: Matrix.of(context)
|
||||
.client
|
||||
|
|
@ -27,16 +29,27 @@ class EncryptionButton extends StatelessWidget {
|
|||
tooltip: room.encrypted
|
||||
? L10n.of(context).encrypted
|
||||
: L10n.of(context).encryptionNotEnabled,
|
||||
icon: Icon(
|
||||
room.encrypted ? Icons.lock_outlined : Icons.lock_open_outlined,
|
||||
size: 20,
|
||||
color: room.joinRules != JoinRules.public && !room.encrypted
|
||||
? Colors.red
|
||||
: room.joinRules != JoinRules.public &&
|
||||
snapshot.data ==
|
||||
EncryptionHealthState.unverifiedDevices
|
||||
? Colors.orange
|
||||
: null,
|
||||
icon: b.Badge(
|
||||
badgeAnimation: const b.BadgeAnimation.fade(),
|
||||
showBadge:
|
||||
snapshot.data == EncryptionHealthState.unverifiedDevices,
|
||||
badgeStyle: b.BadgeStyle(
|
||||
badgeColor: theme.colorScheme.error,
|
||||
elevation: 4,
|
||||
),
|
||||
badgeContent: Text(
|
||||
'!',
|
||||
style: TextStyle(
|
||||
fontSize: 9,
|
||||
color: theme.colorScheme.onError,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
room.encrypted ? Icons.lock_outlined : Icons.lock_open_outlined,
|
||||
size: 20,
|
||||
color: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
onPressed: () => context.go('/rooms/${room.id}/encryption'),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:matrix/matrix.dart' as sdk;
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -166,20 +165,6 @@ class ChatDetailsController extends State<ChatDetails>
|
|||
// Pangea#
|
||||
}
|
||||
|
||||
void goToEmoteSettings() async {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId!)!;
|
||||
// okay, we need to test if there are any emote state events other than the default one
|
||||
// if so, we need to be directed to a selection screen for which pack we want to look at
|
||||
// otherwise, we just open the normal one.
|
||||
if ((room.states['im.ponies.room_emotes'] ?? <String, Event>{})
|
||||
.keys
|
||||
.any((String s) => s.isNotEmpty)) {
|
||||
context.push('/rooms/${room.id}/details/multiple_emotes');
|
||||
} else {
|
||||
context.push('/rooms/${room.id}/details/emotes');
|
||||
}
|
||||
}
|
||||
|
||||
void setAvatarAction() async {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId!);
|
||||
final actions = [
|
||||
|
|
|
|||
|
|
@ -210,68 +210,59 @@ class ChatDetailsView extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
Divider(color: theme.dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context).chatDescription,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
if (room.canChangeStateEvent(EventTypes.RoomTopic) ||
|
||||
room.topic.isNotEmpty) ...[
|
||||
Divider(color: theme.dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context).chatDescription,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.secondary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
trailing:
|
||||
room.canChangeStateEvent(EventTypes.RoomTopic)
|
||||
? IconButton(
|
||||
onPressed: controller.setTopicAction,
|
||||
tooltip:
|
||||
L10n.of(context).setChatDescription,
|
||||
icon: const Icon(Icons.edit_outlined),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
),
|
||||
child: SelectableLinkify(
|
||||
text: room.topic.isEmpty
|
||||
? L10n.of(context).noChatDescriptionYet
|
||||
: room.topic,
|
||||
textScaleFactor:
|
||||
MediaQuery.textScalerOf(context).scale(1),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
linkStyle: const TextStyle(
|
||||
color: Colors.blueAccent,
|
||||
decorationColor: Colors.blueAccent,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontStyle: room.topic.isEmpty
|
||||
? FontStyle.italic
|
||||
: FontStyle.normal,
|
||||
color: theme.textTheme.bodyMedium!.color,
|
||||
decorationColor:
|
||||
theme.textTheme.bodyMedium!.color,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
),
|
||||
trailing: room
|
||||
.canChangeStateEvent(EventTypes.RoomTopic)
|
||||
? IconButton(
|
||||
onPressed: controller.setTopicAction,
|
||||
tooltip: L10n.of(context).setChatDescription,
|
||||
icon: const Icon(Icons.edit_outlined),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
),
|
||||
child: SelectableLinkify(
|
||||
text: room.topic.isEmpty
|
||||
? L10n.of(context).noChatDescriptionYet
|
||||
: room.topic,
|
||||
textScaleFactor:
|
||||
MediaQuery.textScalerOf(context).scale(1),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
linkStyle: const TextStyle(
|
||||
color: Colors.blueAccent,
|
||||
decorationColor: Colors.blueAccent,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontStyle: room.topic.isEmpty
|
||||
? FontStyle.italic
|
||||
: FontStyle.normal,
|
||||
color: theme.textTheme.bodyMedium!.color,
|
||||
decorationColor:
|
||||
theme.textTheme.bodyMedium!.color,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Divider(color: theme.dividerColor),
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
foregroundColor: iconColor,
|
||||
child: const Icon(
|
||||
Icons.insert_emoticon_outlined,
|
||||
),
|
||||
),
|
||||
title: Text(L10n.of(context).customEmojisAndStickers),
|
||||
subtitle: Text(L10n.of(context).setCustomEmotes),
|
||||
onTap: controller.goToEmoteSettings,
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
),
|
||||
if (!room.isDirectChat)
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
if (!room.isDirectChat) ...[
|
||||
Divider(color: theme.dividerColor),
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
|
|
@ -288,7 +279,6 @@ class ChatDetailsView extends StatelessWidget {
|
|||
.push('/rooms/${room.id}/details/access'),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
),
|
||||
if (!room.isDirectChat)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context).chatPermissions),
|
||||
subtitle: Text(
|
||||
|
|
@ -305,6 +295,7 @@ class ChatDetailsView extends StatelessWidget {
|
|||
onTap: () => context
|
||||
.push('/rooms/${room.id}/details/permissions'),
|
||||
),
|
||||
],
|
||||
Divider(color: theme.dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
|
|
|
|||
100
lib/widgets/avatar_page_header.dart
Normal file
100
lib/widgets/avatar_page_header.dart
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
|
||||
class AvatarPageHeader extends StatelessWidget {
|
||||
final Widget avatar;
|
||||
final void Function()? onAvatarEdit;
|
||||
final Widget? textButtonLeft, textButtonRight;
|
||||
final List<Widget> iconButtons;
|
||||
|
||||
const AvatarPageHeader({
|
||||
super.key,
|
||||
required this.avatar,
|
||||
this.onAvatarEdit,
|
||||
this.iconButtons = const [],
|
||||
this.textButtonLeft,
|
||||
this.textButtonRight,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final onAvatarEdit = this.onAvatarEdit;
|
||||
return Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: FluffyThemes.columnWidth),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
avatar,
|
||||
if (onAvatarEdit != null)
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: FloatingActionButton.small(
|
||||
elevation: 2,
|
||||
onPressed: onAvatarEdit,
|
||||
heroTag: null,
|
||||
child: const Icon(Icons.camera_alt_outlined),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButtonTheme(
|
||||
data: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
disabledForegroundColor: theme.colorScheme.onSurface,
|
||||
foregroundColor: theme.colorScheme.onSurface,
|
||||
textStyle: const TextStyle(fontWeight: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: constraints.maxWidth / 2,
|
||||
),
|
||||
child: textButtonLeft,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: constraints.maxWidth / 2,
|
||||
),
|
||||
child: textButtonRight,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButtonTheme(
|
||||
data: IconButtonThemeData(
|
||||
style: IconButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.surfaceContainer,
|
||||
iconSize: 24,
|
||||
padding: const EdgeInsets.all(16),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: iconButtons,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 0.0),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.
|
|||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
import 'matrix.dart';
|
||||
|
||||
enum ChatPopupMenuActions { details, mute, unmute, leave, search }
|
||||
enum ChatPopupMenuActions { details, mute, unmute, emote, leave, search }
|
||||
|
||||
class ChatSettingsPopupMenu extends StatefulWidget {
|
||||
final Room room;
|
||||
|
|
@ -31,6 +31,20 @@ class ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
void goToEmoteSettings() async {
|
||||
final room = widget.room;
|
||||
// okay, we need to test if there are any emote state events other than the default one
|
||||
// if so, we need to be directed to a selection screen for which pack we want to look at
|
||||
// otherwise, we just open the normal one.
|
||||
if ((room.states['im.ponies.room_emotes'] ?? <String, Event>{})
|
||||
.keys
|
||||
.any((String s) => s.isNotEmpty)) {
|
||||
context.push('/rooms/${room.id}/details/multiple_emotes');
|
||||
} else {
|
||||
context.push('/rooms/${room.id}/details/emotes');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
notificationChangeSub ??= Matrix.of(context)
|
||||
|
|
@ -98,6 +112,8 @@ class ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
|
|||
case ChatPopupMenuActions.search:
|
||||
context.go('/rooms/${widget.room.id}/search');
|
||||
break;
|
||||
case ChatPopupMenuActions.emote:
|
||||
goToEmoteSettings();
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => [
|
||||
|
|
@ -144,6 +160,16 @@ class ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
|
|||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem<ChatPopupMenuActions>(
|
||||
value: ChatPopupMenuActions.emote,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.emoji_emotions_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).emoteSettings),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem<ChatPopupMenuActions>(
|
||||
value: ChatPopupMenuActions.leave,
|
||||
child: Row(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue