diff --git a/lib/views/chat_list.dart b/lib/views/chat_list.dart index 279bc9be..d26f693e 100644 --- a/lib/views/chat_list.dart +++ b/lib/views/chat_list.dart @@ -20,7 +20,7 @@ import '../utils/url_launcher.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; enum SelectMode { normal, share, select } -enum PopupMenuAction { settings, invite, newGroup } +enum PopupMenuAction { settings, invite, newGroup, setStatus } class ChatList extends StatefulWidget { final String activeChat; @@ -151,6 +151,29 @@ class _ChatListState extends State { setState(() => null); } + void _setStatus(BuildContext context) async { + final input = await showTextInputDialog( + context: context, + title: L10n.of(context).setStatus, + okLabel: L10n.of(context).ok, + cancelLabel: L10n.of(context).cancel, + useRootNavigator: false, + textFields: [ + DialogTextField( + hintText: L10n.of(context).statusExampleMessage, + ), + ]); + if (input == null) return; + await showFutureLoadingDialog( + context: context, + future: () => Matrix.of(context).client.sendPresence( + Matrix.of(context).client.userID, + PresenceType.online, + statusMsg: input.single, + ), + ); + } + Future _archiveSelectedRooms(BuildContext context) async { final client = Matrix.of(context).client; while (_selectedRoomIds.isNotEmpty) { @@ -243,6 +266,9 @@ class _ChatListState extends State { PopupMenuButton( onSelected: (action) { switch (action) { + case PopupMenuAction.setStatus: + _setStatus(context); + break; case PopupMenuAction.settings: AdaptivePageLayout.of(context) .pushNamed('/settings'); @@ -261,6 +287,17 @@ class _ChatListState extends State { } }, itemBuilder: (_) => [ + PopupMenuItem( + value: PopupMenuAction.setStatus, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.edit_outlined), + SizedBox(width: 12), + Text(L10n.of(context).setStatus), + ], + ), + ), PopupMenuItem( value: PopupMenuAction.newGroup, child: Row( diff --git a/lib/views/discover.dart b/lib/views/discover.dart deleted file mode 100644 index 3a03e4be..00000000 --- a/lib/views/discover.dart +++ /dev/null @@ -1,300 +0,0 @@ -import 'dart:async'; - -import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; -import 'package:famedlysdk/famedlysdk.dart'; -import 'package:fluffychat/components/avatar.dart'; -import 'package:fluffychat/components/default_app_bar_search_field.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; -import 'package:fluffychat/components/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../utils/localized_exception_extension.dart'; - -class Discover extends StatefulWidget { - final String alias; - - const Discover({ - Key key, - this.alias, - }) : super(key: key); - @override - _DiscoverState createState() => _DiscoverState(); -} - -class _DiscoverState extends State { - Future _publicRoomsResponse; - String _lastServer; - Timer _coolDown; - String _genericSearchTerm; - - void _search(BuildContext context, String query) async { - _coolDown?.cancel(); - _coolDown = Timer( - Duration(milliseconds: 500), - () => setState(() { - _genericSearchTerm = query; - _publicRoomsResponse = null; - }), - ); - } - - Future _joinRoomAndWait( - BuildContext context, - String roomId, - String alias, - ) async { - if (Matrix.of(context).client.getRoomById(roomId) != null) { - return roomId; - } - final newRoomId = await Matrix.of(context) - .client - .joinRoomOrAlias(alias?.isNotEmpty ?? false ? alias : roomId); - await Matrix.of(context) - .client - .onRoomUpdate - .stream - .firstWhere((r) => r.id == newRoomId); - return newRoomId; - } - - void _joinGroupAction(BuildContext context, PublicRoom room) async { - if (await showOkCancelAlertDialog( - context: context, - okLabel: L10n.of(context).joinRoom, - title: '${room.name} (${room.numJoinedMembers ?? 0})', - message: room.topic ?? L10n.of(context).noDescription, - cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, - ) == - OkCancelResult.cancel) { - return; - } - final success = await showFutureLoadingDialog( - context: context, - future: () => _joinRoomAndWait( - context, - room.roomId, - room.canonicalAlias ?? room.aliases.first, - ), - ); - if (success.error == null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${success.result}'); - } - } - - String _server; - - void _setServer(BuildContext context) async { - final newServer = await showTextInputDialog( - title: L10n.of(context).changeTheHomeserver, - context: context, - okLabel: L10n.of(context).ok, - cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, - textFields: [ - DialogTextField( - prefixText: 'https://', - hintText: Matrix.of(context).client.homeserver.host, - initialText: _server, - keyboardType: TextInputType.url, - ) - ]); - if (newServer == null) return; - setState(() { - _server = newServer.single; - }); - } - - @override - void initState() { - _genericSearchTerm = widget.alias; - super.initState(); - } - - @override - Widget build(BuildContext context) { - final server = _genericSearchTerm?.isValidMatrixId ?? false - ? _genericSearchTerm.domain - : _server; - if (_lastServer != server) { - _lastServer = server; - _publicRoomsResponse = null; - } - _publicRoomsResponse ??= Matrix.of(context) - .client - .searchPublicRooms( - server: server, - genericSearchTerm: _genericSearchTerm, - ) - .catchError((error) { - if (widget.alias == null) { - throw error; - } - return PublicRoomsResponse.fromJson({ - 'chunk': [], - }); - }).then((PublicRoomsResponse res) { - if (widget.alias != null && - !res.chunk.any((room) => - (room.aliases?.contains(widget.alias) ?? false) || - room.canonicalAlias == widget.alias)) { - // we have to tack on the original alias - res.chunk.add(PublicRoom.fromJson({ - 'aliases': [widget.alias], - 'name': widget.alias, - })); - } - return res; - }); - return Scaffold( - appBar: AppBar( - elevation: 1, - automaticallyImplyLeading: false, - title: Text(L10n.of(context).discoverGroups), - actions: [ - TextButton.icon( - label: Text( - server ?? Matrix.of(context).client.userID.domain, - style: TextStyle(color: Theme.of(context).accentColor), - ), - icon: Icon( - Icons.edit_outlined, - color: Theme.of(context).accentColor, - ), - onPressed: () => _setServer(context), - ), - ], - ), - body: ListView( - children: [ - Padding( - padding: EdgeInsets.all(12), - child: DefaultAppBarSearchField( - hintText: L10n.of(context).search, - prefixIcon: Icon(Icons.search_outlined), - onChanged: (t) => _search(context, t), - padding: EdgeInsets.zero, - ), - ), - FutureBuilder( - future: _publicRoomsResponse, - builder: (BuildContext context, - AsyncSnapshot snapshot) { - if (snapshot.hasError) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox(height: 32), - Icon( - Icons.error_outlined, - size: 80, - color: Colors.grey, - ), - Center( - child: Text( - snapshot.error.toLocalizedString(context), - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.grey, - fontSize: 16, - ), - ), - ), - ], - ); - } - if (snapshot.connectionState != ConnectionState.done) { - return Center(child: CircularProgressIndicator()); - } - final publicRoomsResponse = snapshot.data; - if (publicRoomsResponse.chunk.isEmpty) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox(height: 32), - Icon( - Icons.search_outlined, - size: 80, - color: Colors.grey, - ), - Center( - child: Text( - L10n.of(context).noPublicRoomsFound, - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.grey, - fontSize: 16, - ), - ), - ), - ], - ); - } - return GridView.builder( - shrinkWrap: true, - padding: EdgeInsets.all(12), - physics: NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: 1, - crossAxisSpacing: 16, - mainAxisSpacing: 16, - ), - itemCount: publicRoomsResponse.chunk.length, - itemBuilder: (BuildContext context, int i) => Material( - elevation: 2, - borderRadius: BorderRadius.circular(16), - child: InkWell( - onTap: () => _joinGroupAction( - context, - publicRoomsResponse.chunk[i], - ), - borderRadius: BorderRadius.circular(16), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Avatar( - Uri.parse( - publicRoomsResponse.chunk[i].avatarUrl ?? - ''), - publicRoomsResponse.chunk[i].name), - Text( - publicRoomsResponse.chunk[i].name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - Text( - L10n.of(context).countParticipants( - publicRoomsResponse - .chunk[i].numJoinedMembers ?? - 0), - style: TextStyle(fontSize: 10.5), - maxLines: 1, - textAlign: TextAlign.center, - ), - Text( - publicRoomsResponse.chunk[i].topic ?? - L10n.of(context).noDescription, - maxLines: 4, - textAlign: TextAlign.center, - ), - ], - ), - ), - ), - ), - ); - }), - ], - ), - ); - } -}