add onSelection callback
This commit is contained in:
parent
3af38e615e
commit
457299ad81
3 changed files with 57 additions and 19 deletions
|
|
@ -7,12 +7,19 @@ part "emoji.g.dart";
|
|||
@Freezed(toJson: false, fromJson: false)
|
||||
@JsonSerializable(createToJson: false)
|
||||
class Emoji({
|
||||
@JsonKey(fromJson: Emoji.widgetFromJson, name: "emoji")
|
||||
@JsonKey(
|
||||
fromJson: Emoji.widgetFromJson,
|
||||
readValue: Emoji.readWidgetValueFromJson,
|
||||
)
|
||||
required final Widget widget,
|
||||
@JsonKey(name: "emoji") required final String value,
|
||||
required final IList<String> aliases,
|
||||
required final String description,
|
||||
required final IList<String> tags,
|
||||
}) with _$Emoji {
|
||||
static Widget widgetFromJson(String emoji) => Text(emoji);
|
||||
|
||||
static String readWidgetValueFromJson(Map<dynamic, dynamic> json, _) =>
|
||||
json["emoji"];
|
||||
factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import "dart:async";
|
||||
|
||||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_hooks/flutter_hooks.dart";
|
||||
|
|
@ -11,14 +13,19 @@ import "package:super_sliver_list/super_sliver_list.dart";
|
|||
|
||||
final class const EmojiPicker({
|
||||
final IList<EmojiCategory> extraCategories = const IList.empty(),
|
||||
required final FutureOr<void> Function(String value) onSelection,
|
||||
super.key,
|
||||
}) extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final selectedCategory = useState<int?>(null);
|
||||
|
||||
final scrollController = useScrollController();
|
||||
final listController = useMemoized(ListController.new);
|
||||
|
||||
final categoryScrollController = useScrollController();
|
||||
final categoryListController = useMemoized(ListController.new);
|
||||
|
||||
useEffect(() {
|
||||
void onChange() {
|
||||
final range = listController.visibleRange;
|
||||
|
|
@ -27,6 +34,13 @@ final class const EmojiPicker({
|
|||
if (selectedCategory.value != firstVisible) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
selectedCategory.value = firstVisible;
|
||||
categoryListController.animateToItem(
|
||||
index: firstVisible,
|
||||
scrollController: categoryScrollController,
|
||||
alignment: 0,
|
||||
duration: (_) => Duration(milliseconds: 300),
|
||||
curve: (_) => Curves.easeInOut,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -43,7 +57,9 @@ final class const EmojiPicker({
|
|||
.watch(EmojiController.provider)
|
||||
.betterWhen(
|
||||
data: (categories) {
|
||||
final combined = categories.addAll(extraCategories);
|
||||
final combined = useMemoized(
|
||||
() => categories.addAll(extraCategories),
|
||||
);
|
||||
|
||||
return Column(
|
||||
spacing: 4,
|
||||
|
|
@ -56,8 +72,10 @@ final class const EmojiPicker({
|
|||
),
|
||||
SizedBox(
|
||||
height: 48,
|
||||
child: ListView(
|
||||
child: SuperListView(
|
||||
scrollDirection: .horizontal,
|
||||
controller: categoryScrollController,
|
||||
listController: categoryListController,
|
||||
children: combined
|
||||
.mapIndexed(
|
||||
(index, category) => Padding(
|
||||
|
|
@ -97,21 +115,30 @@ final class const EmojiPicker({
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DividerText(category.name),
|
||||
Wrap(
|
||||
children: category.emojis
|
||||
.map(
|
||||
(emoji) => IconButton(
|
||||
onPressed: () {},
|
||||
GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 56,
|
||||
mainAxisExtent: 56,
|
||||
),
|
||||
itemCount: category.emojis.length,
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
final emoji = category.emojis[index];
|
||||
|
||||
return IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
await onSelection(emoji.value);
|
||||
},
|
||||
icon: SizedBox.square(
|
||||
dimension: 36,
|
||||
child: FittedBox(
|
||||
fit: .contain,
|
||||
child: emoji.widget,
|
||||
child: FittedBox(child: emoji.widget),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -244,7 +244,11 @@ final class const RoomChat({
|
|||
showDragHandle: true,
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
builder: (context) => EmojiPicker(),
|
||||
builder: (context) => EmojiPicker(
|
||||
onSelection: (value) => notifier
|
||||
.sendReaction(value, event)
|
||||
.onError(showError),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue