fix performance issues with new emoji picker
This commit is contained in:
parent
a0fa30e036
commit
3af38e615e
1 changed files with 100 additions and 104 deletions
|
|
@ -14,118 +14,114 @@ final class const EmojiPicker({
|
||||||
super.key,
|
super.key,
|
||||||
}) extends HookConsumerWidget {
|
}) extends HookConsumerWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) => Container(
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
padding: .symmetric(horizontal: 16),
|
final selectedCategory = useState<int?>(null);
|
||||||
constraints: .loose(.new(500, 700)),
|
final scrollController = useScrollController();
|
||||||
child: ref
|
final listController = useMemoized(ListController.new);
|
||||||
.watch(EmojiController.provider)
|
|
||||||
.betterWhen(
|
|
||||||
data: (categories) {
|
|
||||||
final combined = categories.addAll(extraCategories);
|
|
||||||
|
|
||||||
return HookBuilder(
|
useEffect(() {
|
||||||
builder: (context) {
|
void onChange() {
|
||||||
final selectedCategory = useState<int?>(null);
|
final range = listController.visibleRange;
|
||||||
final scrollController = useScrollController();
|
if (range != null) {
|
||||||
final listController = useMemoized(ListController.new);
|
final firstVisible = range.$1;
|
||||||
|
if (selectedCategory.value != firstVisible) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
selectedCategory.value = firstVisible;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() {
|
listController.addListener(onChange);
|
||||||
void onChange() {
|
return () => listController.removeListener(onChange);
|
||||||
final range = listController.visibleRange;
|
}, [listController]);
|
||||||
if (range != null) {
|
|
||||||
final firstVisible = range.$1;
|
|
||||||
if (selectedCategory.value != firstVisible) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
selectedCategory.value = firstVisible;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listController.addListener(onChange);
|
return Container(
|
||||||
return () => listController.removeListener(onChange);
|
padding: .symmetric(horizontal: 16),
|
||||||
}, [listController]);
|
constraints: .loose(.new(500, 700)),
|
||||||
|
child: ref
|
||||||
|
.watch(EmojiController.provider)
|
||||||
|
.betterWhen(
|
||||||
|
data: (categories) {
|
||||||
|
final combined = categories.addAll(extraCategories);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
SearchAnchor.bar(
|
SearchAnchor.bar(
|
||||||
barHintText: "Search emoji",
|
barHintText: "Search emoji",
|
||||||
suggestionsBuilder: (context, controller) {
|
suggestionsBuilder: (context, controller) {
|
||||||
return [];
|
return [];
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 48,
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: .horizontal,
|
||||||
|
children: combined
|
||||||
|
.mapIndexed(
|
||||||
|
(index, category) => Padding(
|
||||||
|
padding: .symmetric(horizontal: 4),
|
||||||
|
child: FilterChip(
|
||||||
|
label: Text(category.name),
|
||||||
|
avatar: category.icon,
|
||||||
|
selected: selectedCategory.value == index,
|
||||||
|
showCheckmark: false,
|
||||||
|
onSelected: (_) {
|
||||||
|
selectedCategory.value = index;
|
||||||
|
|
||||||
|
listController.animateToItem(
|
||||||
|
index: index,
|
||||||
|
scrollController: scrollController,
|
||||||
|
curve: (_) => Curves.easeInOut,
|
||||||
|
duration: (_) =>
|
||||||
|
Duration(milliseconds: 300),
|
||||||
|
alignment: 0,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: SuperListView.builder(
|
||||||
|
listController: listController,
|
||||||
|
controller: scrollController,
|
||||||
|
itemCount: combined.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final category = combined[index];
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
DividerText(category.name),
|
||||||
|
Wrap(
|
||||||
|
children: category.emojis
|
||||||
|
.map(
|
||||||
|
(emoji) => IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: SizedBox.square(
|
||||||
|
dimension: 36,
|
||||||
|
child: FittedBox(
|
||||||
|
fit: .contain,
|
||||||
|
child: emoji.widget,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SizedBox(
|
),
|
||||||
height: 48,
|
],
|
||||||
child: ListView(
|
);
|
||||||
scrollDirection: .horizontal,
|
},
|
||||||
children: combined
|
),
|
||||||
.mapIndexed(
|
);
|
||||||
(index, category) => Padding(
|
}
|
||||||
padding: .symmetric(horizontal: 4),
|
|
||||||
child: FilterChip(
|
|
||||||
label: Text(category.name),
|
|
||||||
avatar: category.icon,
|
|
||||||
selected: selectedCategory.value == index,
|
|
||||||
showCheckmark: false,
|
|
||||||
onSelected: (_) {
|
|
||||||
selectedCategory.value = index;
|
|
||||||
|
|
||||||
listController.animateToItem(
|
|
||||||
index: index,
|
|
||||||
scrollController: scrollController,
|
|
||||||
curve: (_) => Curves.easeInOut,
|
|
||||||
duration: (_) =>
|
|
||||||
Duration(milliseconds: 300),
|
|
||||||
alignment: 0,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: SuperListView.builder(
|
|
||||||
listController: listController,
|
|
||||||
controller: scrollController,
|
|
||||||
itemCount: combined.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final category = combined[index];
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
DividerText(category.name),
|
|
||||||
DefaultTextStyle(
|
|
||||||
style: TextStyle(fontSize: 24),
|
|
||||||
child: GridView(
|
|
||||||
gridDelegate:
|
|
||||||
const SliverGridDelegateWithMaxCrossAxisExtent(
|
|
||||||
maxCrossAxisExtent: 52,
|
|
||||||
mainAxisExtent: 52,
|
|
||||||
),
|
|
||||||
children: category.emojis
|
|
||||||
.map(
|
|
||||||
(emoji) => IconButton(
|
|
||||||
onPressed: () {},
|
|
||||||
icon: emoji.widget,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue