diff --git a/lib/components/dialogs/simple_dialogs.dart b/lib/components/dialogs/simple_dialogs.dart new file mode 100644 index 0000000..cad187f --- /dev/null +++ b/lib/components/dialogs/simple_dialogs.dart @@ -0,0 +1,39 @@ +import 'package:fluffychat/i18n/i18n.dart'; +import 'package:flutter/material.dart'; + +class SimpleDialogs { + final BuildContext context; + + const SimpleDialogs(this.context); + + Future askConfirmation({ + String titleText, + String confirmText, + String cancelText, + }) async { + bool confirmed = false; + await showDialog( + context: context, + builder: (c) => AlertDialog( + title: Text(I18n.of(context).areYouSure ?? titleText), + actions: [ + FlatButton( + child: Text(cancelText ?? I18n.of(context).close.toUpperCase(), + style: TextStyle(color: Colors.blueGrey)), + onPressed: () => Navigator.of(context).pop(), + ), + FlatButton( + child: Text( + confirmText ?? I18n.of(context).confirm.toUpperCase(), + ), + onPressed: () { + confirmed = true; + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + return confirmed; + } +} diff --git a/lib/components/list_items/chat_list_item.dart b/lib/components/list_items/chat_list_item.dart index e63777a..e3e99a4 100644 --- a/lib/components/list_items/chat_list_item.dart +++ b/lib/components/list_items/chat_list_item.dart @@ -1,4 +1,5 @@ import 'package:famedlysdk/famedlysdk.dart'; +import 'package:fluffychat/components/dialogs/simple_dialogs.dart'; import 'package:fluffychat/i18n/i18n.dart'; import 'package:fluffychat/utils/event_extension.dart'; import 'package:fluffychat/utils/date_time_extension.dart'; @@ -7,6 +8,7 @@ import 'package:fluffychat/utils/room_extension.dart'; import 'package:fluffychat/views/chat.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:toast/toast.dart'; import 'package:pedantic/pedantic.dart'; @@ -84,84 +86,116 @@ class ChatListItem extends StatelessWidget { } } + Future archiveAction(BuildContext context) async { + { + final bool confirmed = await SimpleDialogs(context).askConfirmation(); + if (!confirmed) { + return false; + } + final success = + await Matrix.of(context).tryRequestWithLoadingDialog(room.leave()); + if (success == false) { + return false; + } + return true; + } + } + @override Widget build(BuildContext context) { - return Material( - color: activeChat ? Color(0xFFE8E8E8) : Colors.white, - child: ListTile( - leading: Avatar(room.avatar, room.displayname), - title: Row( - children: [ - Expanded( - child: Text( - room.getLocalizedDisplayname(context), - maxLines: 1, - overflow: TextOverflow.ellipsis, + return Slidable( + key: Key(room.id), + secondaryActions: [ + if ([Membership.join, Membership.invite].contains(room.membership)) + IconSlideAction( + caption: I18n.of(context).leave, + color: Colors.red, + icon: Icons.archive, + onTap: () => archiveAction(context), + ), + ], + actionPane: SlidableDrawerActionPane(), + dismissal: SlidableDismissal( + child: SlidableDrawerDismissal(), + onWillDismiss: (actionType) => archiveAction(context), + ), + child: Material( + color: activeChat ? Color(0xFFE8E8E8) : Colors.white, + child: ListTile( + leading: Avatar(room.avatar, room.displayname), + title: Row( + children: [ + Expanded( + child: Text( + room.getLocalizedDisplayname(context), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), ), - ), - SizedBox(width: 16), - room.pushRuleState == PushRuleState.notify - ? Container() - : Icon( - Icons.notifications_off, - color: Colors.grey[400], - size: 16, - ), - SizedBox(width: 4), - Text( - room.timeCreated.localizedTimeShort(context), - style: TextStyle( - color: Color(0xFF555555), - fontSize: 13, + SizedBox(width: 16), + room.pushRuleState == PushRuleState.notify + ? Container() + : Icon( + Icons.notifications_off, + color: Colors.grey[400], + size: 16, + ), + SizedBox(width: 4), + Text( + room.timeCreated.localizedTimeShort(context), + style: TextStyle( + color: Color(0xFF555555), + fontSize: 13, + ), ), - ), - ], - ), - subtitle: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: room.membership == Membership.invite - ? Text( - I18n.of(context).youAreInvitedToThisChat, - style: TextStyle( - color: Theme.of(context).primaryColor, + ], + ), + subtitle: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: room.membership == Membership.invite + ? Text( + I18n.of(context).youAreInvitedToThisChat, + style: TextStyle( + color: Theme.of(context).primaryColor, + ), + ) + : Text( + room.lastEvent.getLocalizedBody(context, + withSenderNamePrefix: true, hideQuotes: true), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + decoration: room.lastEvent.redacted + ? TextDecoration.lineThrough + : null, + ), + ), + ), + SizedBox(width: 8), + room.notificationCount > 0 + ? Container( + padding: EdgeInsets.symmetric(horizontal: 5), + height: 20, + decoration: BoxDecoration( + color: room.highlightCount > 0 + ? Colors.red + : Theme.of(context).primaryColor, + borderRadius: BorderRadius.circular(20), + ), + child: Center( + child: Text( + room.notificationCount.toString(), + style: TextStyle(color: Colors.white), + ), ), ) - : Text( - room.lastEvent.getLocalizedBody(context, - withSenderNamePrefix: true, hideQuotes: true), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - decoration: room.lastEvent.redacted - ? TextDecoration.lineThrough - : null, - ), - ), - ), - SizedBox(width: 8), - room.notificationCount > 0 - ? Container( - padding: EdgeInsets.symmetric(horizontal: 5), - height: 20, - decoration: BoxDecoration( - color: room.highlightCount > 0 - ? Colors.red - : Theme.of(context).primaryColor, - borderRadius: BorderRadius.circular(20), - ), - child: Center( - child: Text( - room.notificationCount.toString(), - style: TextStyle(color: Colors.white), - ), - ), - ) - : Text(" "), - ], + : Text(" "), + ], + ), + onTap: () => clickAction(context), ), - onTap: () => clickAction(context), ), ); } diff --git a/lib/i18n/i18n.dart b/lib/i18n/i18n.dart index c427380..bb80859 100644 --- a/lib/i18n/i18n.dart +++ b/lib/i18n/i18n.dart @@ -74,6 +74,8 @@ class I18n { String get areGuestsAllowedToJoin => Intl.message("Are guest users allowed to join"); + String get areYouSure => Intl.message("Are you sure?"); + String get authentication => Intl.message("Authentication"); String get avatarHasBeenChanged => Intl.message("Avatar has been changed"); diff --git a/lib/views/chat_list.dart b/lib/views/chat_list.dart index b2581c1..cf52d8c 100644 --- a/lib/views/chat_list.dart +++ b/lib/views/chat_list.dart @@ -18,7 +18,7 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:toast/toast.dart'; import 'package:uni_links/uni_links.dart'; -enum SelectMode { normal, multi_select, share } +enum SelectMode { normal, share } class ChatListView extends StatelessWidget { @override @@ -86,7 +86,8 @@ class _ChatListState extends State { } }, onError: (error) => Toast.show( - I18n.of(context).oopsSomethingWentWrong + " " + error.toString(), context, + I18n.of(context).oopsSomethingWentWrong + " " + error.toString(), + context, duration: 5), ); } diff --git a/pubspec.lock b/pubspec.lock index c4394a3..188811c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -188,6 +188,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.3.1+1" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.4" flutter_speed_dial: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 23e3a63..1d981fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: universal_html: ^1.1.12 uni_links: ^0.2.0 flutter_svg: ^0.17.1 + flutter_slidable: ^0.5.4 intl: ^0.16.0 intl_translation: ^0.17.9