forked from Nexus/nexus
Compare commits
4 commits
windows-de
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
f4b2dcb824 |
|||
|
50e1a8e4c7 |
|||
|
82dab26fd4 |
|||
|
313dc377ec |
5 changed files with 135 additions and 20 deletions
88
lib/controllers/emoji_controller.dart
Normal file
88
lib/controllers/emoji_controller.dart
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
import "dart:convert";
|
||||||
|
import "package:emoji_text_field/models/emoji_category.dart";
|
||||||
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:http/http.dart";
|
||||||
|
import "package:nexus/models/emoji.dart";
|
||||||
|
|
||||||
|
typedef EmojiTuple = (IMap<String, EmojiCategory>, IMap<String, List<String>>);
|
||||||
|
|
||||||
|
class EmojiController extends AsyncNotifier<EmojiTuple> {
|
||||||
|
@override
|
||||||
|
Future<EmojiTuple> build() async {
|
||||||
|
final response = await get(
|
||||||
|
Uri.https(
|
||||||
|
"github.com",
|
||||||
|
"github/gemoji/raw/refs/heads/master/db/emoji.json",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
throw Exception("Failed to load emoji data");
|
||||||
|
}
|
||||||
|
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
|
||||||
|
final entries = (data as List)
|
||||||
|
.cast<Map<String, dynamic>>()
|
||||||
|
.map(Emoji.fromJson)
|
||||||
|
.toIList();
|
||||||
|
|
||||||
|
final categoryMap = entries.fold<IMap<String, IList<String>>>(
|
||||||
|
const IMap.empty(),
|
||||||
|
(acc, entry) => acc.update(
|
||||||
|
entry.category,
|
||||||
|
(list) => list.add(entry.emoji),
|
||||||
|
ifAbsent: () => IList([entry.emoji]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final keywordMap = entries.fold<IMap<String, IList<String>>>(
|
||||||
|
const IMap.empty(),
|
||||||
|
(acc, entry) => acc.add(
|
||||||
|
entry.emoji,
|
||||||
|
IList<String>([...entry.tags, ...entry.aliases, entry.description]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final customCategories = IMap.fromEntries(
|
||||||
|
categoryMap.entries.map(
|
||||||
|
(entry) => MapEntry(
|
||||||
|
entry.key,
|
||||||
|
EmojiCategory(
|
||||||
|
name: entry.key,
|
||||||
|
icon: switch (entry.key) {
|
||||||
|
"Smileys & Emotion" => Icons.emoji_emotions,
|
||||||
|
"People & Body" => Icons.emoji_people,
|
||||||
|
"Animals & Nature" => Icons.emoji_nature,
|
||||||
|
"Food & Drink" => Icons.emoji_food_beverage,
|
||||||
|
"Travel & Places" => Icons.travel_explore,
|
||||||
|
"Activities" => Icons.sports_soccer,
|
||||||
|
"Objects" => Icons.emoji_objects,
|
||||||
|
"Symbols" => Icons.emoji_symbols,
|
||||||
|
"Flags" => Icons.emoji_flags,
|
||||||
|
_ => Icons.category,
|
||||||
|
},
|
||||||
|
emojis: entry.value.toList(growable: false),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final customKeywords = IMap(
|
||||||
|
Map.fromEntries(
|
||||||
|
keywordMap.entries.map(
|
||||||
|
(e) => MapEntry(e.key, e.value.toList(growable: false)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return (customCategories, customKeywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final provider =
|
||||||
|
AsyncNotifierProvider.autoDispose<EmojiController, EmojiTuple>(
|
||||||
|
EmojiController.new,
|
||||||
|
);
|
||||||
|
}
|
||||||
17
lib/models/emoji.dart
Normal file
17
lib/models/emoji.dart
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
part "emoji.freezed.dart";
|
||||||
|
part "emoji.g.dart";
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class Emoji with _$Emoji {
|
||||||
|
const factory Emoji({
|
||||||
|
required String emoji,
|
||||||
|
required String category,
|
||||||
|
required IList<String> aliases,
|
||||||
|
required String description,
|
||||||
|
required IList<String> tags,
|
||||||
|
}) = _Emoji;
|
||||||
|
|
||||||
|
factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import "package:emoji_text_field/emoji_text_field.dart";
|
import "package:emoji_text_field/emoji_text_field.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
|
import "package:nexus/controllers/emoji_controller.dart";
|
||||||
|
|
||||||
class EmojiPickerButton extends HookWidget {
|
class EmojiPickerButton extends HookConsumerWidget {
|
||||||
final TextEditingController? controller;
|
final TextEditingController? controller;
|
||||||
final void Function(String emoji)? onSelection;
|
final void Function(String emoji)? onSelection;
|
||||||
final VoidCallback? onPressed;
|
final VoidCallback? onPressed;
|
||||||
|
|
@ -16,25 +17,34 @@ class EmojiPickerButton extends HookWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(_) => IconButton(
|
Widget build(_, WidgetRef ref) => IconButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
onPressed?.call();
|
onPressed?.call();
|
||||||
final controller = this.controller ?? TextEditingController();
|
final controller = this.controller ?? TextEditingController();
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
final emojis = await ref.watch(EmojiController.provider.future);
|
||||||
builder: (context) => EmojiKeyboardView(
|
if (context.mounted) {
|
||||||
config: EmojiViewConfig(
|
showModalBottomSheet(
|
||||||
showRecentTab: false,
|
context: context,
|
||||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
|
builder: (context) => EmojiKeyboardView(
|
||||||
height: 600,
|
config: EmojiViewConfig(
|
||||||
|
showRecentTab: false,
|
||||||
|
customCategories: emojis.$1.unlock,
|
||||||
|
customKeywords: emojis.$2.unlock,
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
height: 600,
|
||||||
|
),
|
||||||
|
textController: controller
|
||||||
|
..addListener(() {
|
||||||
|
// Without this, there will sometimes be a debugLocked is not true error sometimes
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
if (context.mounted) Navigator.of(context).pop();
|
||||||
|
});
|
||||||
|
onSelection?.call(controller.text);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
textController: controller
|
);
|
||||||
..addListener(() async {
|
}
|
||||||
Navigator.of(context).pop();
|
|
||||||
onSelection?.call(controller.text);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.emoji_emotions),
|
icon: Icon(Icons.emoji_emotions),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ flutter.buildFlutterApplication {
|
||||||
dynamic_system_colors = "sha256-es6rjMK1drkqZBKYUP77yw/q5+0uLwWOEDOXRawy3Dc=";
|
dynamic_system_colors = "sha256-es6rjMK1drkqZBKYUP77yw/q5+0uLwWOEDOXRawy3Dc=";
|
||||||
flutter_chat_ui = "sha256-4fuag7lRH5cMBFD3fUzj2K541JwXLoz8HF/4OMr3uhk=";
|
flutter_chat_ui = "sha256-4fuag7lRH5cMBFD3fUzj2K541JwXLoz8HF/4OMr3uhk=";
|
||||||
flutter_link_previewer = "sha256-4fuag7lRH5cMBFD3fUzj2K541JwXLoz8HF/4OMr3uhk=";
|
flutter_link_previewer = "sha256-4fuag7lRH5cMBFD3fUzj2K541JwXLoz8HF/4OMr3uhk=";
|
||||||
emoji_text_field = "sha256-F0QbIHP3wpKoL6QbJ20Oun0SsOdwnXe84IqsK2ad85w=";
|
emoji_text_field = "sha256-3TOys09EP2GRo6pUBGPXaqBlE39O2Cmwt42Hs1cTDKo=";
|
||||||
};
|
};
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,7 @@ packages:
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: HEAD
|
ref: HEAD
|
||||||
resolved-ref: "0e90703a6e876939be70bd1816c49cf14474de61"
|
resolved-ref: "5f7baaf8a6f059ec3ab8ff0f5d02339b00bf6997"
|
||||||
url: "https://github.com/Henry-Hiles/emoji_text_field"
|
url: "https://github.com/Henry-Hiles/emoji_text_field"
|
||||||
source: git
|
source: git
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue