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)
|
@Freezed(toJson: false, fromJson: false)
|
||||||
@JsonSerializable(createToJson: false)
|
@JsonSerializable(createToJson: false)
|
||||||
class Emoji({
|
class Emoji({
|
||||||
@JsonKey(fromJson: Emoji.widgetFromJson, name: "emoji")
|
@JsonKey(
|
||||||
|
fromJson: Emoji.widgetFromJson,
|
||||||
|
readValue: Emoji.readWidgetValueFromJson,
|
||||||
|
)
|
||||||
required final Widget widget,
|
required final Widget widget,
|
||||||
|
@JsonKey(name: "emoji") required final String value,
|
||||||
required final IList<String> aliases,
|
required final IList<String> aliases,
|
||||||
required final String description,
|
required final String description,
|
||||||
required final IList<String> tags,
|
required final IList<String> tags,
|
||||||
}) with _$Emoji {
|
}) with _$Emoji {
|
||||||
static Widget widgetFromJson(String emoji) => Text(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);
|
factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import "dart:async";
|
||||||
|
|
||||||
import "package:collection/collection.dart";
|
import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.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 class const EmojiPicker({
|
||||||
final IList<EmojiCategory> extraCategories = const IList.empty(),
|
final IList<EmojiCategory> extraCategories = const IList.empty(),
|
||||||
|
required final FutureOr<void> Function(String value) onSelection,
|
||||||
super.key,
|
super.key,
|
||||||
}) extends HookConsumerWidget {
|
}) extends HookConsumerWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final selectedCategory = useState<int?>(null);
|
final selectedCategory = useState<int?>(null);
|
||||||
|
|
||||||
final scrollController = useScrollController();
|
final scrollController = useScrollController();
|
||||||
final listController = useMemoized(ListController.new);
|
final listController = useMemoized(ListController.new);
|
||||||
|
|
||||||
|
final categoryScrollController = useScrollController();
|
||||||
|
final categoryListController = useMemoized(ListController.new);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
void onChange() {
|
void onChange() {
|
||||||
final range = listController.visibleRange;
|
final range = listController.visibleRange;
|
||||||
|
|
@ -27,6 +34,13 @@ final class const EmojiPicker({
|
||||||
if (selectedCategory.value != firstVisible) {
|
if (selectedCategory.value != firstVisible) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
selectedCategory.value = firstVisible;
|
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)
|
.watch(EmojiController.provider)
|
||||||
.betterWhen(
|
.betterWhen(
|
||||||
data: (categories) {
|
data: (categories) {
|
||||||
final combined = categories.addAll(extraCategories);
|
final combined = useMemoized(
|
||||||
|
() => categories.addAll(extraCategories),
|
||||||
|
);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
|
|
@ -56,8 +72,10 @@ final class const EmojiPicker({
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 48,
|
height: 48,
|
||||||
child: ListView(
|
child: SuperListView(
|
||||||
scrollDirection: .horizontal,
|
scrollDirection: .horizontal,
|
||||||
|
controller: categoryScrollController,
|
||||||
|
listController: categoryListController,
|
||||||
children: combined
|
children: combined
|
||||||
.mapIndexed(
|
.mapIndexed(
|
||||||
(index, category) => Padding(
|
(index, category) => Padding(
|
||||||
|
|
@ -97,21 +115,30 @@ final class const EmojiPicker({
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
DividerText(category.name),
|
DividerText(category.name),
|
||||||
Wrap(
|
GridView.builder(
|
||||||
children: category.emojis
|
gridDelegate:
|
||||||
.map(
|
const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
(emoji) => IconButton(
|
maxCrossAxisExtent: 56,
|
||||||
onPressed: () {},
|
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(
|
icon: SizedBox.square(
|
||||||
dimension: 36,
|
dimension: 36,
|
||||||
child: FittedBox(
|
child: FittedBox(child: emoji.widget),
|
||||||
fit: .contain,
|
|
||||||
child: emoji.widget,
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,11 @@ final class const RoomChat({
|
||||||
showDragHandle: true,
|
showDragHandle: true,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => EmojiPicker(),
|
builder: (context) => EmojiPicker(
|
||||||
|
onSelection: (value) => notifier
|
||||||
|
.sendReaction(value, event)
|
||||||
|
.onError(showError),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue