make grid more flexible

This commit is contained in:
Henry Hiles 2026-10-23 17:11:05 -04:00
commit 97c4324c8f
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -15,17 +15,30 @@ class EmojiPicker extends HookConsumerWidget {
this.appendCategories = const IList.empty(),
required this.onSelection,
this.onFreeText,
this.includeDefaultEmoji = true,
this.itemSize = 56,
this.searchHint = "Search emoji",
super.key,
});
final IList<EmojiCategory> prependCategories;
final IList<EmojiCategory> appendCategories;
/// Called with the emoji that was selected.
final FutureOr<void> Function(Emoji emoji) onSelection;
/// If set, the search text can be submitted as is, calling this with it.
final FutureOr<void> Function(String text)? onFreeText;
/// Whether to show the default unicode emoji after [prependCategories],
/// e.g. false for a sticker picker of only custom categories.
final bool includeDefaultEmoji;
/// The width and height of each item in the grid.
final double itemSize;
final String searchHint;
@override
Widget build(BuildContext context, WidgetRef ref) {
final selectedCategory = useState<int>(0);
@ -39,7 +52,9 @@ class EmojiPicker extends HookConsumerWidget {
return Container(
padding: .all(16),
constraints: .loose(.new(500, 700)),
child: switch (ref.watch(EmojiController.provider)) {
child: switch (includeDefaultEmoji
? ref.watch(EmojiController.provider)
: const AsyncData(IList<EmojiCategory>.empty())) {
AsyncError(:final error) => throw error,
AsyncLoading _ => Center(child: CircularProgressIndicator()),
AsyncData(value: final categories) => HookBuilder(
@ -47,6 +62,7 @@ class EmojiPicker extends HookConsumerWidget {
final combined = useMemoized(
() =>
prependCategories.addAll(categories).addAll(appendCategories),
[prependCategories, categories, appendCategories],
);
final headerKeys = useMemoized(
@ -106,7 +122,7 @@ class EmojiPicker extends HookConsumerWidget {
return Column(
children: [
SearchBar(
hintText: "Search emoji",
hintText: searchHint,
padding: const WidgetStatePropertyAll<EdgeInsets>(
.symmetric(horizontal: 16.0),
),
@ -207,9 +223,9 @@ class EmojiPicker extends HookConsumerWidget {
),
SliverGrid.builder(
gridDelegate:
const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 56,
mainAxisExtent: 56,
SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: itemSize,
mainAxisExtent: itemSize,
),
itemCount: emojis.length,
itemBuilder: (context, index) {
@ -217,10 +233,9 @@ class EmojiPicker extends HookConsumerWidget {
return IconButton(
padding: EdgeInsets.zero,
onPressed: () =>
onSelection(emoji),
onPressed: () => onSelection(emoji),
icon: SizedBox.square(
dimension: 36,
dimension: itemSize * 9 / 14,
child: FittedBox(child: emoji.widget),
),
);