diff --git a/lib/providers/stickers.dart b/lib/providers/stickers.dart index de89197..37c8b71 100644 --- a/lib/providers/stickers.dart +++ b/lib/providers/stickers.dart @@ -1,47 +1,48 @@ +import 'dart:async'; + import 'package:get/get.dart'; import 'package:solian/exceptions/request.dart'; -import 'package:solian/models/pagination.dart'; import 'package:solian/models/stickers.dart'; import 'package:solian/services.dart'; class StickerProvider extends GetxController { - final RxMap aliasImageMapping = RxMap(); - final RxList availableStickers = RxList.empty(growable: true); + final RxMap> stickerCache = RxMap(); - Future refreshAvailableStickers() async { - availableStickers.clear(); - aliasImageMapping.clear(); - - final client = await ServiceFinder.configureClient('files'); - final resp = await client.get( - '/stickers/manifest?take=100', - ); - if (resp.statusCode == 200) { - final result = PaginationResult.fromJson(resp.body); - final out = result.data?.map((e) => StickerPack.fromJson(e)).toList(); - if (out == null) return; - - for (final pack in out) { - for (final sticker in (pack.stickers ?? List.empty())) { - sticker.pack = pack; - aliasImageMapping[sticker.textPlaceholder.toUpperCase()] = - sticker.imageUrl; - availableStickers.add(sticker); - } - } + Future getStickerByAlias(String alias) { + if (stickerCache.containsKey(alias)) { + return Future.value(stickerCache[alias]); } - availableStickers.refresh(); + + stickerCache[alias] = Future(() async { + final client = await ServiceFinder.configureClient('files'); + final resp = await client.get( + '/stickers/lookup/$alias', + ); + if (resp.statusCode != 200) { + if (resp.statusCode == 404) { + stickerCache[alias] = null; + } + throw RequestException(resp); + } + + return Sticker.fromJson(resp.body); + }).then((result) { + stickerCache[alias] = result; + return result; + }); + + return Future.value(stickerCache[alias]); } - Future getStickerByAlias(String alias) async { + Future> searchStickerByAlias(String alias) async { final client = await ServiceFinder.configureClient('files'); final resp = await client.get( - '/stickers/lookup/$alias', + '/stickers/lookup?probe=$alias', ); if (resp.statusCode != 200) { throw RequestException(resp); } - return Sticker.fromJson(resp.body); + return List.from(resp.body.map((x) => Sticker.fromJson(x))); } } diff --git a/lib/widgets/chat/chat_message_input.dart b/lib/widgets/chat/chat_message_input.dart index b2be661..bab789c 100644 --- a/lib/widgets/chat/chat_message_input.dart +++ b/lib/widgets/chat/chat_message_input.dart @@ -405,12 +405,9 @@ class _ChatMessageInputState extends State { if (emojiMatch != null) { final StickerProvider stickers = Get.find(); final emoteSearch = emojiMatch[2]!; - return stickers.availableStickers - .where( - (x) => x.textWarpedPlaceholder - .toUpperCase() - .contains(emoteSearch.toUpperCase()), - ) + final result = await stickers + .searchStickerByAlias(emoteSearch.substring(1)); + return result .map( (x) => ChatMessageSuggestion( type: 'emotes', diff --git a/lib/widgets/markdown_text_content.dart b/lib/widgets/markdown_text_content.dart index 8c4aee8..c9cb928 100644 --- a/lib/widgets/markdown_text_content.dart +++ b/lib/widgets/markdown_text_content.dart @@ -89,7 +89,6 @@ class MarkdownTextContent extends StatelessWidget { case 'stickers': double radius = 8; final StickerProvider sticker = Get.find(); - url = sticker.aliasImageMapping[segments[1].toUpperCase()]!; if (emojiMatch.length <= 1 && isOnlyEmoji) { width = 128; height = 128; @@ -106,11 +105,20 @@ class MarkdownTextContent extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(radius)), child: Container( color: Theme.of(context).colorScheme.surfaceContainer, - child: AutoCacheImage( - url, - width: width, - height: height, - fit: fit, + child: FutureBuilder( + future: sticker.getStickerByAlias(segments[1]), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } + return AutoCacheImage( + snapshot.data!.imageUrl, + width: width, + height: height, + fit: fit, + noErrorWidget: true, + ); + }, ), ), ).paddingSymmetric(vertical: 4); @@ -172,7 +180,8 @@ class _CustomEmoteInlineSyntax extends InlineSyntax { bool onMatch(markdown.InlineParser parser, Match match) { final StickerProvider sticker = Get.find(); final alias = match[1]!.toUpperCase(); - if (sticker.aliasImageMapping[alias] == null) { + if (sticker.stickerCache.containsKey(alias) && + sticker.stickerCache[alias] == null) { parser.advanceBy(1); return false; }