diff --git a/lib/pages/create_post/create_post_community_picker.dart b/lib/pages/create_post/create_post_community_picker.dart new file mode 100644 index 0000000..8e9b3ed --- /dev/null +++ b/lib/pages/create_post/create_post_community_picker.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; +import 'package:lemmy_api_client/v3.dart'; + +import '../../l10n/l10n.dart'; +import '../../util/async_store_listener.dart'; +import '../../util/extensions/api.dart'; +import '../../util/extensions/context.dart'; +import '../../util/observer_consumers.dart'; +import '../../widgets/avatar.dart'; +import 'create_post_store.dart'; + +class CreatePostCommunityPicker extends HookWidget { + const CreatePostCommunityPicker({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final controller = useTextEditingController(); + final store = context.read(); + + return AsyncStoreListener( + asyncStore: context.read().searchCommunitiesState, + child: Focus( + onFocusChange: (hasFocus) { + if (!hasFocus && store.selectedCommunity == null) { + controller.text = ''; + } + }, + child: TypeAheadFormField( + textFieldConfiguration: TextFieldConfiguration( + controller: controller, + enabled: !store.isEdit, + decoration: InputDecoration( + hintText: L10n.of(context).community, + contentPadding: const EdgeInsets.symmetric( + vertical: 16, + horizontal: 20, + ), + suffixIcon: const Icon(Icons.arrow_drop_down), + ), + onChanged: (_) => store.selectedCommunity = null, + ), + validator: (choice) { + if (choice?.isEmpty ?? false) { + return L10n.of(context).required_field; + } + }, + suggestionsCallback: (pattern) async { + final communities = await store.searchCommunities( + pattern, + context.defaultJwt(store.instanceHost), + ); + + return communities ?? []; + }, + itemBuilder: (context, community) { + return ListTile( + leading: Avatar( + url: community.community.icon, + radius: 20, + ), + title: Text(_communityString(community)), + ); + }, + onSuggestionSelected: (community) { + store.selectedCommunity = community; + controller.text = _communityString(community); + }, + noItemsFoundBuilder: (context) => SizedBox( + width: double.infinity, + child: Padding( + padding: const EdgeInsets.all(8), + child: Text( + L10n.of(context).no_communities_found, + textAlign: TextAlign.center, + ), + ), + ), + loadingBuilder: (context) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Padding( + padding: EdgeInsets.all(8), + child: CircularProgressIndicator.adaptive(), + ), + ], + ), + debounceDuration: const Duration(milliseconds: 400), + ), + ), + ); + } +} + +String _communityString(CommunityView communityView) { + if (communityView.community.local) { + return communityView.community.title; + } else { + return '${communityView.community.originInstanceHost}/${communityView.community.title}'; + } +}