✨ Adjust picker size
This commit is contained in:
@@ -1141,8 +1141,15 @@ class _ChatInput extends HookConsumerWidget {
|
|||||||
tooltip: 'stickers'.tr(),
|
tooltip: 'stickers'.tr(),
|
||||||
icon: const Icon(Symbols.emoji_symbols),
|
icon: const Icon(Symbols.emoji_symbols),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
final size = MediaQuery.of(context).size;
|
||||||
showStickerPickerPopover(
|
showStickerPickerPopover(
|
||||||
context,
|
context,
|
||||||
|
Offset(
|
||||||
|
20,
|
||||||
|
size.height -
|
||||||
|
480 -
|
||||||
|
MediaQuery.of(context).padding.bottom,
|
||||||
|
),
|
||||||
onPick: (placeholder) {
|
onPick: (placeholder) {
|
||||||
// Insert placeholder at current cursor position
|
// Insert placeholder at current cursor position
|
||||||
final text = messageController.text;
|
final text = messageController.text;
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -9,6 +11,7 @@ import 'package:island/widgets/content/cloud_files.dart';
|
|||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:flutter_popup_card/flutter_popup_card.dart';
|
||||||
|
|
||||||
part 'picker.g.dart';
|
part 'picker.g.dart';
|
||||||
|
|
||||||
@@ -40,9 +43,9 @@ class StickerPicker extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final packsAsync = ref.watch(myStickerPacksProvider);
|
final packsAsync = ref.watch(myStickerPacksProvider);
|
||||||
|
|
||||||
return Dialog(
|
return PopupCard(
|
||||||
insetPadding: const EdgeInsets.all(12),
|
elevation: 8,
|
||||||
clipBehavior: Clip.hardEdge,
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxWidth: 520, maxHeight: 520),
|
constraints: const BoxConstraints(maxWidth: 520, maxHeight: 520),
|
||||||
child: packsAsync.when(
|
child: packsAsync.when(
|
||||||
@@ -175,26 +178,28 @@ class _PackSwitcherState extends State<_PackSwitcher> {
|
|||||||
],
|
],
|
||||||
).padding(horizontal: 12, top: 8, bottom: 4),
|
).padding(horizontal: 12, top: 8, bottom: 4),
|
||||||
|
|
||||||
// Pack chips
|
// Vertical, scrollable packs rail like common emoji pickers
|
||||||
SingleChildScrollView(
|
SizedBox(
|
||||||
scrollDirection: Axis.horizontal,
|
height: 52,
|
||||||
|
child: ListView.separated(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: Row(
|
scrollDirection: Axis.horizontal,
|
||||||
children: [
|
itemCount: packs.length,
|
||||||
for (var i = 0; i < packs.length; i++)
|
separatorBuilder: (_, __) => const Gap(4),
|
||||||
Padding(
|
itemBuilder: (context, i) {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
final selected = _index == i;
|
||||||
child: ChoiceChip(
|
return Tooltip(
|
||||||
label: Text(packs[i].name),
|
message: packs[i].name,
|
||||||
selected: _index == i,
|
child: FilterChip(
|
||||||
onSelected: (v) {
|
label: Text(packs[i].name, overflow: TextOverflow.ellipsis),
|
||||||
if (!v) return;
|
selected: selected,
|
||||||
|
onSelected: (_) {
|
||||||
setState(() => _index = i);
|
setState(() => _index = i);
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
@@ -269,21 +274,33 @@ class _StickersGrid extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper to show sticker picker as a popover dialog.
|
/// Helper to show sticker picker as an anchored popover near the trigger.
|
||||||
/// Usage:
|
/// Provide the button's BuildContext (typically from the onPressed closure).
|
||||||
/// await showStickerPickerPopover(context, onPick: (placeholder) { ... });
|
/// Fallbacks to dialog if overlay cannot be found (e.g., during tests).
|
||||||
Future<void> showStickerPickerPopover(
|
Future<void> showStickerPickerPopover(
|
||||||
BuildContext context, {
|
BuildContext context,
|
||||||
|
Offset offset, {
|
||||||
required void Function(String placeholder) onPick,
|
required void Function(String placeholder) onPick,
|
||||||
}) async {
|
}) async {
|
||||||
await showDialog(
|
// Use flutter_popup_card to present the anchored popup near trigger.
|
||||||
|
await showPopupCard<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: true,
|
offset: offset,
|
||||||
builder: (ctx) {
|
alignment: Alignment.topLeft,
|
||||||
return ProviderScope(
|
dimBackground: true,
|
||||||
|
builder:
|
||||||
|
(ctx) => SizedBox(
|
||||||
|
width: math.min(480, MediaQuery.of(context).size.width * 0.9),
|
||||||
|
height: 480,
|
||||||
|
child: ProviderScope(
|
||||||
parent: ProviderScope.containerOf(context),
|
parent: ProviderScope.containerOf(context),
|
||||||
child: StickerPicker(onPick: onPick),
|
child: StickerPicker(
|
||||||
);
|
onPick: (ph) {
|
||||||
|
onPick(ph);
|
||||||
|
Navigator.of(ctx).maybePop();
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user