✨ Search advance filter with tags
This commit is contained in:
		| @@ -162,7 +162,6 @@ class ChatMessageController extends ChangeNotifier { | ||||
|   } | ||||
|  | ||||
|   Future<void> _applyMessage(SnChatMessage message) async { | ||||
|     print(message.toJson()); | ||||
|     if (message.channelId != channel?.id) return; | ||||
|  | ||||
|     switch (message.type) { | ||||
|   | ||||
| @@ -29,22 +29,14 @@ class SnPostContentProvider { | ||||
|     for (var i = 0; i < out.length; i++) { | ||||
|       out[i] = out[i].copyWith( | ||||
|         preload: SnPostPreload( | ||||
|           thumbnail: attachments | ||||
|               .where((ele) => ele?.rid == out[i].body['thumbnail']) | ||||
|               .firstOrNull, | ||||
|           attachments: attachments | ||||
|               .where((ele) => | ||||
|                   out[i].body['attachments']?.contains(ele?.rid) ?? false) | ||||
|               .toList(), | ||||
|           thumbnail: attachments.where((ele) => ele?.rid == out[i].body['thumbnail']).firstOrNull, | ||||
|           attachments: attachments.where((ele) => out[i].body['attachments']?.contains(ele?.rid) ?? false).toList(), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     await _ud.listAccount( | ||||
|       attachments | ||||
|           .where((ele) => ele != null) | ||||
|           .map((ele) => ele!.accountId) | ||||
|           .toSet(), | ||||
|       attachments.where((ele) => ele != null).map((ele) => ele!.accountId).toSet(), | ||||
|     ); | ||||
|  | ||||
|     return out; | ||||
| @@ -60,13 +52,8 @@ class SnPostContentProvider { | ||||
|     final attachments = await _attach.getMultiple(rids.toList()); | ||||
|     out = out.copyWith( | ||||
|       preload: SnPostPreload( | ||||
|         thumbnail: attachments | ||||
|             .where((ele) => ele?.rid == out.body['thumbnail']) | ||||
|             .firstOrNull, | ||||
|         attachments: attachments | ||||
|             .where( | ||||
|                 (ele) => out.body['attachments']?.contains(ele?.rid) ?? false) | ||||
|             .toList(), | ||||
|         thumbnail: attachments.where((ele) => ele?.rid == out.body['thumbnail']).firstOrNull, | ||||
|         attachments: attachments.where((ele) => out.body['attachments']?.contains(ele?.rid) ?? false).toList(), | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
| @@ -97,8 +84,7 @@ class SnPostContentProvider { | ||||
|     int take = 10, | ||||
|     int offset = 0, | ||||
|   }) async { | ||||
|     final resp = await _sn.client | ||||
|         .get('/cgi/co/posts/$parentId/replies', queryParameters: { | ||||
|     final resp = await _sn.client.get('/cgi/co/posts/$parentId/replies', queryParameters: { | ||||
|       'take': take, | ||||
|       'offset': offset, | ||||
|     }); | ||||
| @@ -113,11 +99,13 @@ class SnPostContentProvider { | ||||
|     String searchTerm, { | ||||
|     int take = 10, | ||||
|     int offset = 0, | ||||
|     Iterable<String>? tags, | ||||
|   }) async { | ||||
|     final resp = await _sn.client.get('/cgi/co/posts/search', queryParameters: { | ||||
|       'take': take, | ||||
|       'offset': offset, | ||||
|       'probe': searchTerm, | ||||
|       if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','), | ||||
|     }); | ||||
|     final List<SnPost> out = await _preloadRelatedDataInBatch( | ||||
|       List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []), | ||||
|   | ||||
| @@ -87,7 +87,7 @@ class _ChatScreenState extends State<ChatScreen> { | ||||
|       const uuid = Uuid(); | ||||
|       final sn = context.read<SnNetworkProvider>(); | ||||
|       final ua = context.read<UserProvider>(); | ||||
|       final resp = await sn.client.post('/cgi/im/channels/global/dm', data: { | ||||
|       await sn.client.post('/cgi/im/channels/global/dm', data: { | ||||
|         'alias': uuid.v4().replaceAll('-', '').substring(0, 12), | ||||
|         'name': 'DM', | ||||
|         'description': 'A direct message channel between @${ua.user?.name} and @${user.name}', | ||||
|   | ||||
| @@ -5,9 +5,12 @@ import 'package:go_router/go_router.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:surface/controllers/post_write_controller.dart'; | ||||
| import 'package:surface/providers/post.dart'; | ||||
| import 'package:surface/types/post.dart'; | ||||
| import 'package:surface/widgets/dialog.dart'; | ||||
| import 'package:surface/widgets/post/post_item.dart'; | ||||
| import 'package:surface/widgets/post/post_tags_field.dart'; | ||||
| import 'package:very_good_infinite_list/very_good_infinite_list.dart'; | ||||
|  | ||||
| class PostSearchScreen extends StatefulWidget { | ||||
| @@ -20,6 +23,8 @@ class PostSearchScreen extends StatefulWidget { | ||||
| class _PostSearchScreenState extends State<PostSearchScreen> { | ||||
|   bool _isBusy = false; | ||||
|  | ||||
|   List<String> _searchTags = List.empty(growable: true); | ||||
|  | ||||
|   final List<SnPost> _posts = List.empty(growable: true); | ||||
|   int? _postCount; | ||||
|  | ||||
| @@ -27,28 +32,32 @@ class _PostSearchScreenState extends State<PostSearchScreen> { | ||||
|   Duration? _lastTook; | ||||
|  | ||||
|   Future<void> _fetchPosts() async { | ||||
|     if (_searchTerm.isEmpty) return; | ||||
|     if (_searchTerm.isEmpty && _searchTags.isEmpty) return; | ||||
|     if (_postCount != null && _posts.length >= _postCount!) return; | ||||
|  | ||||
|     setState(() => _isBusy = true); | ||||
|  | ||||
|     final stopwatch = Stopwatch()..start(); | ||||
|  | ||||
|     final pt = context.read<SnPostContentProvider>(); | ||||
|     final result = await pt.searchPosts( | ||||
|       _searchTerm, | ||||
|       take: 10, | ||||
|       offset: _posts.length, | ||||
|     ); | ||||
|     final List<SnPost> out = result.$1; | ||||
|  | ||||
|     if (!mounted) return; | ||||
|  | ||||
|     stopwatch.stop(); | ||||
|  | ||||
|     _lastTook = stopwatch.elapsed; | ||||
|     _postCount = result.$2; | ||||
|     _posts.addAll(out); | ||||
|     try { | ||||
|       final pt = context.read<SnPostContentProvider>(); | ||||
|       final result = await pt.searchPosts( | ||||
|         _searchTerm, | ||||
|         take: 10, | ||||
|         offset: _posts.length, | ||||
|         tags: _searchTags, | ||||
|       ); | ||||
|       final List<SnPost> out = result.$1; | ||||
|       _postCount = result.$2; | ||||
|       _posts.addAll(out); | ||||
|     } catch (err) { | ||||
|       if (!mounted) return; | ||||
|       context.showErrorDialog(err); | ||||
|       return; | ||||
|     } finally { | ||||
|       stopwatch.stop(); | ||||
|       _lastTook = stopwatch.elapsed; | ||||
|     } | ||||
|  | ||||
|     if (mounted) setState(() => _isBusy = false); | ||||
|   } | ||||
| @@ -57,8 +66,16 @@ class _PostSearchScreenState extends State<PostSearchScreen> { | ||||
|     showModalBottomSheet( | ||||
|       context: context, | ||||
|       builder: (context) => Column( | ||||
|         children: [], | ||||
|       ), | ||||
|         children: [ | ||||
|           PostTagsField( | ||||
|             labelText: 'fieldPostTags'.tr(), | ||||
|             initialTags: _searchTags, | ||||
|             onUpdate: (value) { | ||||
|               setState(() => _searchTags = value); | ||||
|             }, | ||||
|           ), | ||||
|         ], | ||||
|       ).padding(horizontal: 24, vertical: 16), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user