forked from Nexus/nexus
121 lines
3.1 KiB
Dart
121 lines
3.1 KiB
Dart
import "dart:convert";
|
|
import "package:collection/collection.dart";
|
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
|
import "package:flutter/foundation.dart";
|
|
import "package:flutter/material.dart";
|
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
|
import "package:http/http.dart";
|
|
import "package:nexus/models/gemoji.dart";
|
|
|
|
class EmoteSection {
|
|
final String category;
|
|
final String label;
|
|
final IconData icon;
|
|
final List<EmoteItem> items;
|
|
final bool isRecent;
|
|
|
|
const EmoteSection({
|
|
required this.category,
|
|
required this.label,
|
|
required this.icon,
|
|
required this.items,
|
|
this.isRecent = false,
|
|
});
|
|
}
|
|
|
|
class EmoteItem {
|
|
final String id;
|
|
final String display;
|
|
final List<String> keywords;
|
|
final int useCounter;
|
|
final Image? customImage;
|
|
|
|
const EmoteItem({
|
|
required this.id,
|
|
required this.display,
|
|
required this.keywords,
|
|
required this.useCounter,
|
|
this.customImage,
|
|
});
|
|
}
|
|
|
|
class EmojiController extends AsyncNotifier<IList<EmoteSection>> {
|
|
@override
|
|
Future<IList<EmoteSection>> build() async {
|
|
final response = await get(
|
|
.https("github.com", "github/gemoji/raw/refs/heads/master/db/emoji.json"),
|
|
);
|
|
|
|
if (response.statusCode != 200) {
|
|
throw Exception("Failed to load emoji data");
|
|
}
|
|
|
|
return compute(parseEmojiJson, response.body);
|
|
}
|
|
|
|
static IList<EmoteSection> parseEmojiJson(String body) {
|
|
final data = json.decode(body) as List;
|
|
final allEntries = data
|
|
.cast<Map<String, dynamic>>()
|
|
.map(Gemoji.fromJson)
|
|
.toIList();
|
|
|
|
final groupedByCategory = groupBy(allEntries, (g) => g.category);
|
|
|
|
final result = groupedByCategory.entries.fold<IList<EmoteSection>>(
|
|
.new(),
|
|
(resultList, entry) => resultList.add(
|
|
EmoteSection(
|
|
category: entry.key,
|
|
label: entry.key,
|
|
icon: getIconForCategory(entry.key),
|
|
items: entry.value
|
|
.map(
|
|
(gemoji) => EmoteItem(
|
|
id: gemoji.emoji,
|
|
display: gemoji.emoji,
|
|
keywords: [
|
|
...gemoji.tags,
|
|
...gemoji.aliases,
|
|
...gemoji.description.split(" "),
|
|
],
|
|
useCounter: 0,
|
|
),
|
|
)
|
|
.toList(),
|
|
isRecent: false,
|
|
),
|
|
),
|
|
);
|
|
|
|
return result;
|
|
}
|
|
|
|
static final provider =
|
|
AsyncNotifierProvider<EmojiController, IList<EmoteSection>>(
|
|
EmojiController.new,
|
|
);
|
|
|
|
static IconData getIconForCategory(String category) {
|
|
switch (category.toLowerCase()) {
|
|
case "smileys & emotion":
|
|
return Icons.sentiment_very_satisfied;
|
|
case "people & body":
|
|
return Icons.face;
|
|
case "food & drink":
|
|
return Icons.restaurant;
|
|
case "travel & places":
|
|
return Icons.flag;
|
|
case "activities":
|
|
return Icons.sports_soccer;
|
|
case "objects":
|
|
return Icons.lightbulb;
|
|
case "symbols":
|
|
return Icons.circle;
|
|
case "flags":
|
|
return Icons.flag;
|
|
default:
|
|
return Icons.emoji_emotions_outlined;
|
|
}
|
|
}
|
|
}
|