From 63032ebae1353b86e15994a2129659c8b63e0071 Mon Sep 17 00:00:00 2001 From: Filip Krawczyk Date: Sun, 21 Aug 2022 19:03:22 +0200 Subject: [PATCH] add selecting of users and communities also made simplified version of reformat --- lib/widgets/editor/editor_picking_dialog.dart | 132 ++++++++++++++++++ lib/widgets/editor/editor_toolbar.dart | 31 +++- 2 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 lib/widgets/editor/editor_picking_dialog.dart diff --git a/lib/widgets/editor/editor_picking_dialog.dart b/lib/widgets/editor/editor_picking_dialog.dart new file mode 100644 index 0000000..df9cc26 --- /dev/null +++ b/lib/widgets/editor/editor_picking_dialog.dart @@ -0,0 +1,132 @@ +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 'package:provider/provider.dart'; + +import '../../../util/extensions/api.dart'; +import '../../../widgets/avatar.dart'; +import '../../stores/accounts_store.dart'; +import 'editor_toolbar_store.dart'; + +class PickPersonDialog extends HookWidget { + final EditorToolbarStore store; + + const PickPersonDialog._(this.store); + + @override + Widget build(BuildContext context) { + final userData = + context.read().defaultUserDataFor(store.instanceHost); + + return AlertDialog( + title: const Text('Select User'), + content: TypeAheadField( + suggestionsCallback: (pattern) async { + if (pattern.trim().isEmpty) return const Iterable.empty(); + return LemmyApiV3(store.instanceHost) + .run(Search( + q: pattern, + auth: userData?.jwt.raw, + type: SearchType.users, + limit: 10, + )) + .then((value) => value.users); + }, + itemBuilder: (context, user) { + return ListTile( + leading: Avatar( + url: user.person.avatar, + radius: 20, + ), + title: Text(user.person.originPreferredName), + ); + }, + onSuggestionSelected: (suggestion) => + Navigator.of(context).pop(suggestion), + loadingBuilder: (context) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Padding( + padding: EdgeInsets.all(16), + child: CircularProgressIndicator.adaptive(), + ), + ], + ), + keepSuggestionsOnLoading: false, + noItemsFoundBuilder: (context) => const SizedBox(), + hideOnEmpty: true, + textFieldConfiguration: const TextFieldConfiguration(autofocus: true), + ), + ); + } + + static Future show(BuildContext context) async { + final store = context.read(); + return showDialog( + context: context, + builder: (context) => PickPersonDialog._(store), + ); + } +} + +class PickCommunityDialog extends HookWidget { + final EditorToolbarStore store; + + const PickCommunityDialog._(this.store); + + @override + Widget build(BuildContext context) { + final userData = + context.read().defaultUserDataFor(store.instanceHost); + + return AlertDialog( + title: const Text('Select Community'), + content: TypeAheadField( + suggestionsCallback: (pattern) async { + if (pattern.trim().isEmpty) return const Iterable.empty(); + return LemmyApiV3(store.instanceHost) + .run(Search( + q: pattern, + auth: userData?.jwt.raw, + type: SearchType.communities, + limit: 10, + )) + .then((value) => value.communities); + }, + itemBuilder: (context, community) { + return ListTile( + leading: Avatar( + url: community.community.icon, + radius: 20, + ), + title: Text(community.community.originPreferredName), + ); + }, + onSuggestionSelected: (suggestion) => + Navigator.of(context).pop(suggestion), + loadingBuilder: (context) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Padding( + padding: EdgeInsets.all(16), + child: CircularProgressIndicator.adaptive(), + ), + ], + ), + keepSuggestionsOnLoading: false, + noItemsFoundBuilder: (context) => const SizedBox(), + hideOnEmpty: true, + textFieldConfiguration: const TextFieldConfiguration(autofocus: true), + ), + ); + } + + static Future show(BuildContext context) async { + final store = context.read(); + return showDialog( + context: context, + builder: (context) => PickCommunityDialog._(store), + ); + } +} diff --git a/lib/widgets/editor/editor_toolbar.dart b/lib/widgets/editor/editor_toolbar.dart index d2d4b6f..803cfc1 100644 --- a/lib/widgets/editor/editor_toolbar.dart +++ b/lib/widgets/editor/editor_toolbar.dart @@ -4,11 +4,13 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import '../../formatter.dart'; import '../../hooks/logged_in_action.dart'; import '../../util/async_store_listener.dart'; +import '../../util/extensions/api.dart'; import '../../util/extensions/spaced.dart'; import '../../util/files.dart'; import '../../util/mobx_provider.dart'; import '../../util/observer_consumers.dart'; import '../../util/text_lines_iterator.dart'; +import 'editor_picking_dialog.dart'; import 'editor_toolbar_store.dart'; class Reformat { @@ -113,6 +115,9 @@ extension on TextEditingController { ), ); } + + void reformatSimple(String text) => + reformat((selection) => Reformat(text: text)); } class Toolbar extends HookWidget { @@ -202,8 +207,7 @@ class _ToolbarBody extends HookWidget { .uploadImage(pic.path, token); if (picUrl != null) { - controller.reformat( - (selection) => Reformat(text: '![]($picUrl)')); + controller.reformatSimple('![]($picUrl)'); } } } on Exception catch (_) { @@ -218,11 +222,30 @@ class _ToolbarBody extends HookWidget { }, ), IconButton( - onPressed: () {}, + onPressed: () async { + final person = await PickPersonDialog.show(context); + + if (person != null) { + final name = + '@${person.person.name}@${person.person.originInstanceHost}'; + final link = person.person.actorId; + + controller.reformatSimple('[$name]($link)'); + } + }, icon: const Icon(Icons.person), ), IconButton( - onPressed: () {}, + onPressed: () async { + final community = await PickCommunityDialog.show(context); + if (community != null) { + final name = + '!${community.community.name}@${community.community.originInstanceHost}'; + final link = community.community.actorId; + + controller.reformatSimple('[$name]($link)'); + } + }, icon: const Icon(Icons.home), ), IconButton(