add selecting of users and communities
also made simplified version of reformat
This commit is contained in:
parent
116b0d7961
commit
63032ebae1
|
@ -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<AccountsStore>().defaultUserDataFor(store.instanceHost);
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Select User'),
|
||||||
|
content: TypeAheadField<PersonViewSafe>(
|
||||||
|
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<PersonViewSafe?> show(BuildContext context) async {
|
||||||
|
final store = context.read<EditorToolbarStore>();
|
||||||
|
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<AccountsStore>().defaultUserDataFor(store.instanceHost);
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Select Community'),
|
||||||
|
content: TypeAheadField<CommunityView>(
|
||||||
|
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<CommunityView?> show(BuildContext context) async {
|
||||||
|
final store = context.read<EditorToolbarStore>();
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => PickCommunityDialog._(store),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,11 +4,13 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import '../../formatter.dart';
|
import '../../formatter.dart';
|
||||||
import '../../hooks/logged_in_action.dart';
|
import '../../hooks/logged_in_action.dart';
|
||||||
import '../../util/async_store_listener.dart';
|
import '../../util/async_store_listener.dart';
|
||||||
|
import '../../util/extensions/api.dart';
|
||||||
import '../../util/extensions/spaced.dart';
|
import '../../util/extensions/spaced.dart';
|
||||||
import '../../util/files.dart';
|
import '../../util/files.dart';
|
||||||
import '../../util/mobx_provider.dart';
|
import '../../util/mobx_provider.dart';
|
||||||
import '../../util/observer_consumers.dart';
|
import '../../util/observer_consumers.dart';
|
||||||
import '../../util/text_lines_iterator.dart';
|
import '../../util/text_lines_iterator.dart';
|
||||||
|
import 'editor_picking_dialog.dart';
|
||||||
import 'editor_toolbar_store.dart';
|
import 'editor_toolbar_store.dart';
|
||||||
|
|
||||||
class Reformat {
|
class Reformat {
|
||||||
|
@ -113,6 +115,9 @@ extension on TextEditingController {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reformatSimple(String text) =>
|
||||||
|
reformat((selection) => Reformat(text: text));
|
||||||
}
|
}
|
||||||
|
|
||||||
class Toolbar extends HookWidget {
|
class Toolbar extends HookWidget {
|
||||||
|
@ -202,8 +207,7 @@ class _ToolbarBody extends HookWidget {
|
||||||
.uploadImage(pic.path, token);
|
.uploadImage(pic.path, token);
|
||||||
|
|
||||||
if (picUrl != null) {
|
if (picUrl != null) {
|
||||||
controller.reformat(
|
controller.reformatSimple('![]($picUrl)');
|
||||||
(selection) => Reformat(text: '![]($picUrl)'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on Exception catch (_) {
|
} on Exception catch (_) {
|
||||||
|
@ -218,11 +222,30 @@ class _ToolbarBody extends HookWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
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),
|
icon: const Icon(Icons.person),
|
||||||
),
|
),
|
||||||
IconButton(
|
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),
|
icon: const Icon(Icons.home),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
|
|
Loading…
Reference in New Issue