✨ Realm channels
This commit is contained in:
		| @@ -21,6 +21,22 @@ class ChannelProvider extends GetxController { | |||||||
|     return resp; |     return resp; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Future<Response> listChannel({String scope = 'global'}) async { | ||||||
|  |     final AuthProvider auth = Get.find(); | ||||||
|  |     if (!await auth.isAuthorized) throw Exception('unauthorized'); | ||||||
|  |  | ||||||
|  |     final client = GetConnect(maxAuthRetries: 3); | ||||||
|  |     client.httpClient.baseUrl = ServiceFinder.services['messaging']; | ||||||
|  |     client.httpClient.addAuthenticator(auth.requestAuthenticator); | ||||||
|  |  | ||||||
|  |     final resp = await client.get('/api/channels/$scope'); | ||||||
|  |     if (resp.statusCode != 200) { | ||||||
|  |       throw Exception(resp.bodyString); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return resp; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   Future<Response> listAvailableChannel({String realm = 'global'}) async { |   Future<Response> listAvailableChannel({String realm = 'global'}) async { | ||||||
|     final AuthProvider auth = Get.find(); |     final AuthProvider auth = Get.find(); | ||||||
|     if (!await auth.isAuthorized) throw Exception('unauthorized'); |     if (!await auth.isAuthorized) throw Exception('unauthorized'); | ||||||
|   | |||||||
| @@ -110,7 +110,7 @@ abstract class AppRouter { | |||||||
|           final arguments = state.extra as ChannelOrganizeArguments?; |           final arguments = state.extra as ChannelOrganizeArguments?; | ||||||
|           return ChannelOrganizeScreen( |           return ChannelOrganizeScreen( | ||||||
|             edit: arguments?.edit, |             edit: arguments?.edit, | ||||||
|             realm: state.uri.queryParameters['realm'], |             realm: arguments?.realm, | ||||||
|           ); |           ); | ||||||
|         }, |         }, | ||||||
|       ), |       ), | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import 'package:flutter_animate/flutter_animate.dart'; | |||||||
| import 'package:get/get.dart'; | import 'package:get/get.dart'; | ||||||
| import 'package:solian/exts.dart'; | import 'package:solian/exts.dart'; | ||||||
| import 'package:solian/models/channel.dart'; | import 'package:solian/models/channel.dart'; | ||||||
|  | import 'package:solian/models/realm.dart'; | ||||||
| import 'package:solian/providers/auth.dart'; | import 'package:solian/providers/auth.dart'; | ||||||
| import 'package:solian/providers/content/channel.dart'; | import 'package:solian/providers/content/channel.dart'; | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| @@ -12,13 +13,14 @@ import 'package:uuid/uuid.dart'; | |||||||
|  |  | ||||||
| class ChannelOrganizeArguments { | class ChannelOrganizeArguments { | ||||||
|   final Channel? edit; |   final Channel? edit; | ||||||
|  |   final Realm? realm; | ||||||
|  |  | ||||||
|   ChannelOrganizeArguments({this.edit}); |   ChannelOrganizeArguments({this.edit, this.realm}); | ||||||
| } | } | ||||||
|  |  | ||||||
| class ChannelOrganizeScreen extends StatefulWidget { | class ChannelOrganizeScreen extends StatefulWidget { | ||||||
|   final Channel? edit; |   final Channel? edit; | ||||||
|   final String? realm; |   final Realm? realm; | ||||||
|  |  | ||||||
|   const ChannelOrganizeScreen({super.key, this.edit, this.realm}); |   const ChannelOrganizeScreen({super.key, this.edit, this.realm}); | ||||||
|  |  | ||||||
| @@ -49,7 +51,7 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> { | |||||||
|     client.httpClient.baseUrl = ServiceFinder.services['messaging']; |     client.httpClient.baseUrl = ServiceFinder.services['messaging']; | ||||||
|     client.httpClient.addAuthenticator(auth.requestAuthenticator); |     client.httpClient.addAuthenticator(auth.requestAuthenticator); | ||||||
|  |  | ||||||
|     final scope = (widget.realm?.isNotEmpty ?? false) ? widget.realm : 'global'; |     final scope = widget.realm != null ? widget.realm!.alias : 'global'; | ||||||
|     final payload = { |     final payload = { | ||||||
|       'alias': _aliasController.value.text.toLowerCase(), |       'alias': _aliasController.value.text.toLowerCase(), | ||||||
|       'name': _nameController.value.text, |       'name': _nameController.value.text, | ||||||
| @@ -60,9 +62,9 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> { | |||||||
|     Response? resp; |     Response? resp; | ||||||
|     try { |     try { | ||||||
|       if (widget.edit != null) { |       if (widget.edit != null) { | ||||||
|         resp = await provider.updateChannel(scope!, widget.edit!.id, payload); |         resp = await provider.updateChannel(scope, widget.edit!.id, payload); | ||||||
|       } else { |       } else { | ||||||
|         resp = await provider.createChannel(scope!, payload); |         resp = await provider.createChannel(scope, payload); | ||||||
|       } |       } | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       context.showErrorDialog(e); |       context.showErrorDialog(e); | ||||||
| @@ -99,6 +101,13 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|  |     final notifyBannerActions = [ | ||||||
|  |       TextButton( | ||||||
|  |         onPressed: cancelAction, | ||||||
|  |         child: Text('cancel'.tr), | ||||||
|  |       ), | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|     return Material( |     return Material( | ||||||
|       color: Theme.of(context).colorScheme.surface, |       color: Theme.of(context).colorScheme.surface, | ||||||
|       child: Scaffold( |       child: Scaffold( | ||||||
| @@ -126,13 +135,19 @@ class _ChannelOrganizeScreenState extends State<ChannelOrganizeScreen> { | |||||||
|                     'channelEditingNotify' |                     'channelEditingNotify' | ||||||
|                         .trParams({'channel': '#${widget.edit!.alias}'}), |                         .trParams({'channel': '#${widget.edit!.alias}'}), | ||||||
|                   ), |                   ), | ||||||
|                   actions: [ |                   actions: notifyBannerActions, | ||||||
|                     TextButton( |                 ).paddingOnly(bottom: 6), | ||||||
|                       onPressed: cancelAction, |               if (widget.realm != null) | ||||||
|                       child: Text('cancel'.tr), |                 MaterialBanner( | ||||||
|                     ), |                   leading: const Icon(Icons.group), | ||||||
|                   ], |                   leadingPadding: const EdgeInsets.only(left: 10, right: 20), | ||||||
|                 ), |                   dividerColor: Colors.transparent, | ||||||
|  |                   content: Text( | ||||||
|  |                     'channelInRealmNotify' | ||||||
|  |                         .trParams({'realm': '#${widget.realm!.alias}'}), | ||||||
|  |                   ), | ||||||
|  |                   actions: notifyBannerActions, | ||||||
|  |                 ).paddingOnly(bottom: 6), | ||||||
|               Row( |               Row( | ||||||
|                 children: [ |                 children: [ | ||||||
|                   Expanded( |                   Expanded( | ||||||
|   | |||||||
| @@ -8,8 +8,8 @@ import 'package:solian/providers/content/channel.dart'; | |||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
| import 'package:solian/screens/account/notification.dart'; | import 'package:solian/screens/account/notification.dart'; | ||||||
| import 'package:solian/theme.dart'; | import 'package:solian/theme.dart'; | ||||||
| import 'package:solian/widgets/account/account_avatar.dart'; |  | ||||||
| import 'package:solian/widgets/account/signin_required_overlay.dart'; | import 'package:solian/widgets/account/signin_required_overlay.dart'; | ||||||
|  | import 'package:solian/widgets/channel/channel_list.dart'; | ||||||
|  |  | ||||||
| class ContactScreen extends StatefulWidget { | class ContactScreen extends StatefulWidget { | ||||||
|   const ContactScreen({super.key}); |   const ContactScreen({super.key}); | ||||||
| @@ -137,13 +137,7 @@ class _ContactScreenState extends State<ContactScreen> { | |||||||
|                   SliverToBoxAdapter( |                   SliverToBoxAdapter( | ||||||
|                     child: const LinearProgressIndicator().animate().scaleX(), |                     child: const LinearProgressIndicator().animate().scaleX(), | ||||||
|                   ), |                   ), | ||||||
|                 SliverList.builder( |                 ChannelListWidget(channels: _channels, selfId: _accountId ?? 0), | ||||||
|                   itemCount: _channels.length, |  | ||||||
|                   itemBuilder: (context, index) { |  | ||||||
|                     final element = _channels[index]; |  | ||||||
|                     return buildItem(element); |  | ||||||
|                   }, |  | ||||||
|                 ), |  | ||||||
|               ], |               ], | ||||||
|             ), |             ), | ||||||
|           ); |           ); | ||||||
| @@ -151,58 +145,4 @@ class _ContactScreenState extends State<ContactScreen> { | |||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Widget buildItem(Channel element) { |  | ||||||
|     if (element.type == 1) { |  | ||||||
|       final otherside = element.members! |  | ||||||
|           .where((e) => e.account.externalId != _accountId) |  | ||||||
|           .first; |  | ||||||
|  |  | ||||||
|       return ListTile( |  | ||||||
|         leading: AccountAvatar( |  | ||||||
|           content: otherside.account.avatar, |  | ||||||
|           bgColor: Colors.indigo, |  | ||||||
|           feColor: Colors.white, |  | ||||||
|         ), |  | ||||||
|         contentPadding: const EdgeInsets.symmetric(horizontal: 24), |  | ||||||
|         title: Text(otherside.account.nick), |  | ||||||
|         subtitle: Text( |  | ||||||
|           'channelDirectDescription' |  | ||||||
|               .trParams({'username': '@${otherside.account.name}'}), |  | ||||||
|         ), |  | ||||||
|         onTap: () { |  | ||||||
|           AppRouter.instance.pushNamed( |  | ||||||
|             'channelChat', |  | ||||||
|             pathParameters: {'alias': element.alias}, |  | ||||||
|             queryParameters: { |  | ||||||
|               if (element.realmId != null) 'realm': element.realm!.alias, |  | ||||||
|             }, |  | ||||||
|           ); |  | ||||||
|         }, |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return ListTile( |  | ||||||
|       leading: const CircleAvatar( |  | ||||||
|         backgroundColor: Colors.indigo, |  | ||||||
|         child: FaIcon( |  | ||||||
|           FontAwesomeIcons.hashtag, |  | ||||||
|           color: Colors.white, |  | ||||||
|           size: 16, |  | ||||||
|         ), |  | ||||||
|       ), |  | ||||||
|       contentPadding: const EdgeInsets.symmetric(horizontal: 24), |  | ||||||
|       title: Text(element.name), |  | ||||||
|       subtitle: Text(element.description), |  | ||||||
|       onTap: () { |  | ||||||
|         AppRouter.instance.pushNamed( |  | ||||||
|           'channelChat', |  | ||||||
|           pathParameters: {'alias': element.alias}, |  | ||||||
|           queryParameters: { |  | ||||||
|             if (element.realmId != null) 'realm': element.realm!.alias, |  | ||||||
|           }, |  | ||||||
|         ); |  | ||||||
|       }, |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,14 +2,19 @@ import 'package:flutter/material.dart'; | |||||||
| import 'package:get/get.dart'; | import 'package:get/get.dart'; | ||||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||||
| import 'package:solian/exts.dart'; | import 'package:solian/exts.dart'; | ||||||
|  | import 'package:solian/models/channel.dart'; | ||||||
| import 'package:solian/models/pagination.dart'; | import 'package:solian/models/pagination.dart'; | ||||||
| import 'package:solian/models/post.dart'; | import 'package:solian/models/post.dart'; | ||||||
| import 'package:solian/models/realm.dart'; | import 'package:solian/models/realm.dart'; | ||||||
|  | import 'package:solian/providers/auth.dart'; | ||||||
|  | import 'package:solian/providers/content/channel.dart'; | ||||||
| import 'package:solian/providers/content/post.dart'; | import 'package:solian/providers/content/post.dart'; | ||||||
| import 'package:solian/providers/content/realm.dart'; | import 'package:solian/providers/content/realm.dart'; | ||||||
| import 'package:solian/router.dart'; | import 'package:solian/router.dart'; | ||||||
|  | import 'package:solian/screens/channel/channel_organize.dart'; | ||||||
| import 'package:solian/screens/posts/post_publish.dart'; | import 'package:solian/screens/posts/post_publish.dart'; | ||||||
| import 'package:solian/theme.dart'; | import 'package:solian/theme.dart'; | ||||||
|  | import 'package:solian/widgets/channel/channel_list.dart'; | ||||||
| import 'package:solian/widgets/posts/post_list.dart'; | import 'package:solian/widgets/posts/post_list.dart'; | ||||||
|  |  | ||||||
| class RealmViewScreen extends StatefulWidget { | class RealmViewScreen extends StatefulWidget { | ||||||
| @@ -26,6 +31,7 @@ class _RealmViewScreenState extends State<RealmViewScreen> { | |||||||
|   String? _overrideAlias; |   String? _overrideAlias; | ||||||
|  |  | ||||||
|   Realm? _realm; |   Realm? _realm; | ||||||
|  |   final List<Channel> _channels = List.empty(growable: true); | ||||||
|  |  | ||||||
|   getRealm({String? overrideAlias}) async { |   getRealm({String? overrideAlias}) async { | ||||||
|     final RealmProvider provider = Get.find(); |     final RealmProvider provider = Get.find(); | ||||||
| @@ -46,11 +52,29 @@ class _RealmViewScreenState extends State<RealmViewScreen> { | |||||||
|     setState(() => _isBusy = false); |     setState(() => _isBusy = false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getChannels() async { | ||||||
|  |     setState(() => _isBusy = true); | ||||||
|  |  | ||||||
|  |     final ChannelProvider provider = Get.find(); | ||||||
|  |     final resp = await provider.listChannel(scope: _realm!.alias); | ||||||
|  |  | ||||||
|  |     setState(() { | ||||||
|  |       _channels.clear(); | ||||||
|  |       _channels.addAll( | ||||||
|  |         resp.body.map((e) => Channel.fromJson(e)).toList().cast<Channel>(), | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     setState(() => _isBusy = false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|     super.initState(); |     super.initState(); | ||||||
|  |  | ||||||
|     getRealm(); |     getRealm().then((_) { | ||||||
|  |       getChannels(); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -113,7 +137,11 @@ class _RealmViewScreenState extends State<RealmViewScreen> { | |||||||
|                 return TabBarView( |                 return TabBarView( | ||||||
|                   children: [ |                   children: [ | ||||||
|                     RealmPostListWidget(realm: _realm!), |                     RealmPostListWidget(realm: _realm!), | ||||||
|                     Icon(Icons.directions_transit), |                     RealmChannelListWidget( | ||||||
|  |                       realm: _realm!, | ||||||
|  |                       channels: _channels, | ||||||
|  |                       onRefresh: () => getChannels(), | ||||||
|  |                     ), | ||||||
|                   ], |                   ], | ||||||
|                 ); |                 ); | ||||||
|               }, |               }, | ||||||
| @@ -174,7 +202,7 @@ class _RealmPostListWidgetState extends State<RealmPostListWidget> { | |||||||
|           SliverToBoxAdapter( |           SliverToBoxAdapter( | ||||||
|             child: ListTile( |             child: ListTile( | ||||||
|               leading: const Icon(Icons.post_add), |               leading: const Icon(Icons.post_add), | ||||||
|               contentPadding: const EdgeInsets.symmetric(horizontal: 24), |               contentPadding: const EdgeInsets.only(left: 24, right: 8), | ||||||
|               tileColor: Theme.of(context).colorScheme.surfaceContainer, |               tileColor: Theme.of(context).colorScheme.surfaceContainer, | ||||||
|               title: Text('postNew'.tr), |               title: Text('postNew'.tr), | ||||||
|               subtitle: Text( |               subtitle: Text( | ||||||
| @@ -199,3 +227,60 @@ class _RealmPostListWidgetState extends State<RealmPostListWidget> { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | class RealmChannelListWidget extends StatelessWidget { | ||||||
|  |   final Realm realm; | ||||||
|  |   final List<Channel> channels; | ||||||
|  |   final Future Function() onRefresh; | ||||||
|  |  | ||||||
|  |   const RealmChannelListWidget({ | ||||||
|  |     super.key, | ||||||
|  |     required this.realm, | ||||||
|  |     required this.channels, | ||||||
|  |     required this.onRefresh, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     final AuthProvider auth = Get.find(); | ||||||
|  |  | ||||||
|  |     return FutureBuilder( | ||||||
|  |       future: auth.getProfile(), | ||||||
|  |       builder: (context, snapshot) { | ||||||
|  |         return RefreshIndicator( | ||||||
|  |           onRefresh: onRefresh, | ||||||
|  |           child: CustomScrollView( | ||||||
|  |             slivers: [ | ||||||
|  |               SliverToBoxAdapter( | ||||||
|  |                 child: ListTile( | ||||||
|  |                   leading: const Icon(Icons.add_box), | ||||||
|  |                   contentPadding: const EdgeInsets.only(left: 32, right: 8), | ||||||
|  |                   tileColor: Theme.of(context).colorScheme.surfaceContainer, | ||||||
|  |                   title: Text('channelNew'.tr), | ||||||
|  |                   subtitle: Text( | ||||||
|  |                     'channelNewInRealmHint' | ||||||
|  |                         .trParams({'realm': '#${realm.alias}'}), | ||||||
|  |                   ), | ||||||
|  |                   onTap: () { | ||||||
|  |                     AppRouter.instance | ||||||
|  |                         .pushNamed( | ||||||
|  |                       'channelOrganizing', | ||||||
|  |                       extra: ChannelOrganizeArguments(realm: realm), | ||||||
|  |                     ) | ||||||
|  |                         .then((value) { | ||||||
|  |                       if (value != null) onRefresh(); | ||||||
|  |                     }); | ||||||
|  |                   }, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               ChannelListWidget( | ||||||
|  |                 channels: channels, | ||||||
|  |                 selfId: snapshot.data?.body['id'] ?? 0, | ||||||
|  |               ) | ||||||
|  |             ], | ||||||
|  |           ), | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -108,10 +108,13 @@ class SolianMessages extends Translations { | |||||||
|           'realmPublic': 'Public Realm', |           'realmPublic': 'Public Realm', | ||||||
|           'realmCommunity': 'Community Realm', |           'realmCommunity': 'Community Realm', | ||||||
|           'realmDetail': 'Realm detail', |           'realmDetail': 'Realm detail', | ||||||
|  |           'channelNew': 'Create a new channel', | ||||||
|  |           'channelNewInRealmHint': 'Create channel in realm @realm', | ||||||
|           'channelOrganizing': 'Organize a channel', |           'channelOrganizing': 'Organize a channel', | ||||||
|           'channelOrganizeCommon': 'Create regular channel', |           'channelOrganizeCommon': 'Create regular channel', | ||||||
|           'channelOrganizeDirect': 'Create DM', |           'channelOrganizeDirect': 'Create DM', | ||||||
|           'channelOrganizeDirectHint': 'Choose friend to create DM', |           'channelOrganizeDirectHint': 'Choose friend to create DM', | ||||||
|  |           'channelInRealmNotify': 'You\'re creating channel in realm @realm', | ||||||
|           'channelEditingNotify': 'You\'re editing channel @channel', |           'channelEditingNotify': 'You\'re editing channel @channel', | ||||||
|           'channelAlias': 'Alias (Identifier)', |           'channelAlias': 'Alias (Identifier)', | ||||||
|           'channelName': 'Name', |           'channelName': 'Name', | ||||||
| @@ -233,10 +236,13 @@ class SolianMessages extends Translations { | |||||||
|           'realmPublic': '公开领域', |           'realmPublic': '公开领域', | ||||||
|           'realmCommunity': '社区领域', |           'realmCommunity': '社区领域', | ||||||
|           'realmDetail': '领域详情', |           'realmDetail': '领域详情', | ||||||
|  |           'channelNew': '创建新频道', | ||||||
|  |           'channelNewInRealmHint': '在领域 @realm 里创建新频道', | ||||||
|           'channelOrganizing': '组织频道', |           'channelOrganizing': '组织频道', | ||||||
|           'channelOrganizeCommon': '创建普通频道', |           'channelOrganizeCommon': '创建普通频道', | ||||||
|           'channelOrganizeDirect': '创建私信频道', |           'channelOrganizeDirect': '创建私信频道', | ||||||
|           'channelOrganizeDirectHint': '选择好友来创建私信', |           'channelOrganizeDirectHint': '选择好友来创建私信', | ||||||
|  |           'channelInRealmNotify': '你正在领域 @realm 中创建频道', | ||||||
|           'channelEditingNotify': '你正在编辑频道 @channel', |           'channelEditingNotify': '你正在编辑频道 @channel', | ||||||
|           'channelAlias': '别称(标识符)', |           'channelAlias': '别称(标识符)', | ||||||
|           'channelName': '显示名称', |           'channelName': '显示名称', | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								lib/widgets/channel/channel_list.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								lib/widgets/channel/channel_list.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||||
|  | import 'package:get/get.dart'; | ||||||
|  | import 'package:solian/models/channel.dart'; | ||||||
|  | import 'package:solian/router.dart'; | ||||||
|  | import 'package:solian/widgets/account/account_avatar.dart'; | ||||||
|  |  | ||||||
|  | class ChannelListWidget extends StatelessWidget { | ||||||
|  |   final List<Channel> channels; | ||||||
|  |   final int selfId; | ||||||
|  |  | ||||||
|  |   const ChannelListWidget( | ||||||
|  |       {super.key, required this.channels, required this.selfId}); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return SliverList.builder( | ||||||
|  |       itemCount: channels.length, | ||||||
|  |       itemBuilder: (context, index) { | ||||||
|  |         final element = channels[index]; | ||||||
|  |  | ||||||
|  |         if (element.type == 1) { | ||||||
|  |           final otherside = element.members! | ||||||
|  |               .where((e) => e.account.externalId != selfId) | ||||||
|  |               .first; | ||||||
|  |  | ||||||
|  |           return ListTile( | ||||||
|  |             leading: AccountAvatar( | ||||||
|  |               content: otherside.account.avatar, | ||||||
|  |               bgColor: Colors.indigo, | ||||||
|  |               feColor: Colors.white, | ||||||
|  |             ), | ||||||
|  |             contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||||
|  |             title: Text(otherside.account.nick), | ||||||
|  |             subtitle: Text( | ||||||
|  |               'channelDirectDescription' | ||||||
|  |                   .trParams({'username': '@${otherside.account.name}'}), | ||||||
|  |             ), | ||||||
|  |             onTap: () { | ||||||
|  |               AppRouter.instance.pushNamed( | ||||||
|  |                 'channelChat', | ||||||
|  |                 pathParameters: {'alias': element.alias}, | ||||||
|  |                 queryParameters: { | ||||||
|  |                   if (element.realmId != null) 'realm': element.realm!.alias, | ||||||
|  |                 }, | ||||||
|  |               ); | ||||||
|  |             }, | ||||||
|  |           ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return ListTile( | ||||||
|  |           leading: const CircleAvatar( | ||||||
|  |             backgroundColor: Colors.indigo, | ||||||
|  |             child: FaIcon( | ||||||
|  |               FontAwesomeIcons.hashtag, | ||||||
|  |               color: Colors.white, | ||||||
|  |               size: 16, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           contentPadding: const EdgeInsets.symmetric(horizontal: 24), | ||||||
|  |           title: Text(element.name), | ||||||
|  |           subtitle: Text(element.description), | ||||||
|  |           onTap: () { | ||||||
|  |             AppRouter.instance.pushNamed( | ||||||
|  |               'channelChat', | ||||||
|  |               pathParameters: {'alias': element.alias}, | ||||||
|  |               queryParameters: { | ||||||
|  |                 if (element.realmId != null) 'realm': element.realm!.alias, | ||||||
|  |               }, | ||||||
|  |             ); | ||||||
|  |           }, | ||||||
|  |         ); | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user