reorganize and rename widgets
This commit is contained in:
parent
05d25869ef
commit
d5f29dc344
3 changed files with 568 additions and 547 deletions
84
lib/widgets/emoji/emoji_picker.dart
Normal file
84
lib/widgets/emoji/emoji_picker.dart
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import "dart:async";
|
||||
|
||||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:material_emoji_picker/material_emoji_picker.dart" as upstream;
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/controllers/all_emoji.dart";
|
||||
import "package:nexus/controllers/image_packs.dart";
|
||||
import "package:nexus/controllers/recent_emoji.dart";
|
||||
import "package:nexus/helpers/extensions/better_when.dart";
|
||||
import "package:nexus/helpers/extensions/image_pack_emoji.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/models/content/image_pack.dart";
|
||||
|
||||
class const EmojiPicker({
|
||||
required final String roomId,
|
||||
|
||||
/// Has the [shortcode] and [description] of images from packs.
|
||||
required final FutureOr<void> Function(
|
||||
String value, {
|
||||
String? shortcode,
|
||||
String? description,
|
||||
})
|
||||
onSelection,
|
||||
final bool allowFreeText = false,
|
||||
super.key,
|
||||
}) extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final recentEmoji = ref.watch(RecentEmojiController.provider);
|
||||
|
||||
return ref
|
||||
.watch(AllEmojiController.provider(roomId))
|
||||
.betterWhen(
|
||||
data: (categories) {
|
||||
final allEmoji = categories.expand((category) => category.emojis);
|
||||
final customCategories =
|
||||
ref
|
||||
.watch(ImagePacksController.provider(roomId))
|
||||
.value
|
||||
?.map((pack) => pack.emojiCategory)
|
||||
.nonNulls
|
||||
.toIList() ??
|
||||
const .empty();
|
||||
|
||||
return upstream.EmojiPicker(
|
||||
onSelection: (emoji) async {
|
||||
final image = switch (emoji.data) {
|
||||
final PackImage image => image,
|
||||
_ => null,
|
||||
};
|
||||
await onSelection(
|
||||
emoji.value,
|
||||
shortcode: image == null ? null : emoji.aliases.first,
|
||||
description: image?.body,
|
||||
);
|
||||
|
||||
await ref
|
||||
.read(RecentEmojiController.provider.notifier)
|
||||
.add(emoji.value)
|
||||
.onError(showError);
|
||||
},
|
||||
onFreeText: allowFreeText ? (text) => onSelection(text) : null,
|
||||
prependCategories: IList<upstream.EmojiCategory>([
|
||||
.new(
|
||||
icon: Icon(Icons.history),
|
||||
name: "Recent",
|
||||
emojis: .new(
|
||||
recentEmoji
|
||||
.map(
|
||||
(recent) => allEmoji.firstWhereOrNull(
|
||||
(element) => element.value == recent.emoji,
|
||||
),
|
||||
)
|
||||
.nonNulls,
|
||||
),
|
||||
),
|
||||
]).addAll(customCategories),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
16
lib/widgets/emoji/mxc_emoji.dart
Normal file
16
lib/widgets/emoji/mxc_emoji.dart
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import "package:material_ui/material_ui.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/helpers/mxc_image.dart";
|
||||
|
||||
/// A custom emoji or sticker from an image pack, scaled to fit its parent.
|
||||
class const MxcEmoji(final Uri url, {final String? label, super.key})
|
||||
extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) => Image(
|
||||
image: MxcImage(ref, .new(mxc: url)),
|
||||
semanticLabel: label,
|
||||
fit: .contain,
|
||||
errorBuilder: (context, _, _) =>
|
||||
Icon(Icons.broken_image, color: Theme.of(context).colorScheme.error),
|
||||
);
|
||||
}
|
||||
47
lib/widgets/emoji/sticker_picker.dart
Normal file
47
lib/widgets/emoji/sticker_picker.dart
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import "dart:async";
|
||||
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:material_emoji_picker/material_emoji_picker.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/controllers/image_packs.dart";
|
||||
import "package:nexus/helpers/extensions/better_when.dart";
|
||||
import "package:nexus/helpers/extensions/image_pack_emoji.dart";
|
||||
import "package:nexus/models/content/image_pack.dart";
|
||||
|
||||
/// Stickers from the image packs available in [roomId], grouped by pack.
|
||||
class const StickerPicker({
|
||||
required final String roomId,
|
||||
required final FutureOr<void> Function(String shortcode, PackImage image)
|
||||
onSelection,
|
||||
super.key,
|
||||
}) extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) => ref
|
||||
.watch(ImagePacksController.provider(roomId))
|
||||
.betterWhen(
|
||||
data: (packs) {
|
||||
final categories = packs
|
||||
.map((pack) => pack.stickerCategory)
|
||||
.nonNulls
|
||||
.toIList();
|
||||
|
||||
return categories.isEmpty
|
||||
? Padding(
|
||||
padding: .all(16),
|
||||
child: Center(child: Text("No sticker packs available")),
|
||||
)
|
||||
: EmojiPicker(
|
||||
prependCategories: categories,
|
||||
includeDefaultEmoji: false,
|
||||
itemSize: 96,
|
||||
searchHint: "Search stickers",
|
||||
onSelection: (sticker) {
|
||||
if (sticker.data case final PackImage image) {
|
||||
return onSelection(sticker.aliases.first, image);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue