Improve sticker loading

This commit is contained in:
LittleSheep 2024-09-16 21:00:19 +08:00
parent 152efd97a0
commit 029e72fb0b
3 changed files with 48 additions and 41 deletions

View File

@ -1,47 +1,48 @@
import 'dart:async';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/exceptions/request.dart'; import 'package:solian/exceptions/request.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/models/stickers.dart'; import 'package:solian/models/stickers.dart';
import 'package:solian/services.dart'; import 'package:solian/services.dart';
class StickerProvider extends GetxController { class StickerProvider extends GetxController {
final RxMap<String, String> aliasImageMapping = RxMap(); final RxMap<String, FutureOr<Sticker?>> stickerCache = RxMap();
final RxList<Sticker> availableStickers = RxList.empty(growable: true);
Future<void> refreshAvailableStickers() async { Future<Sticker?> getStickerByAlias(String alias) {
availableStickers.clear(); if (stickerCache.containsKey(alias)) {
aliasImageMapping.clear(); return Future.value(stickerCache[alias]);
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<Sticker>.empty())) {
sticker.pack = pack;
aliasImageMapping[sticker.textPlaceholder.toUpperCase()] =
sticker.imageUrl;
availableStickers.add(sticker);
}
}
}
availableStickers.refresh();
} }
Future<Sticker?> getStickerByAlias(String alias) async { stickerCache[alias] = Future(() async {
final client = await ServiceFinder.configureClient('files'); final client = await ServiceFinder.configureClient('files');
final resp = await client.get( final resp = await client.get(
'/stickers/lookup/$alias', '/stickers/lookup/$alias',
); );
if (resp.statusCode != 200) { if (resp.statusCode != 200) {
if (resp.statusCode == 404) {
stickerCache[alias] = null;
}
throw RequestException(resp); throw RequestException(resp);
} }
return Sticker.fromJson(resp.body); return Sticker.fromJson(resp.body);
}).then((result) {
stickerCache[alias] = result;
return result;
});
return Future.value(stickerCache[alias]);
}
Future<List<Sticker>> searchStickerByAlias(String alias) async {
final client = await ServiceFinder.configureClient('files');
final resp = await client.get(
'/stickers/lookup?probe=$alias',
);
if (resp.statusCode != 200) {
throw RequestException(resp);
}
return List<Sticker>.from(resp.body.map((x) => Sticker.fromJson(x)));
} }
} }

View File

@ -405,12 +405,9 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
if (emojiMatch != null) { if (emojiMatch != null) {
final StickerProvider stickers = Get.find(); final StickerProvider stickers = Get.find();
final emoteSearch = emojiMatch[2]!; final emoteSearch = emojiMatch[2]!;
return stickers.availableStickers final result = await stickers
.where( .searchStickerByAlias(emoteSearch.substring(1));
(x) => x.textWarpedPlaceholder return result
.toUpperCase()
.contains(emoteSearch.toUpperCase()),
)
.map( .map(
(x) => ChatMessageSuggestion( (x) => ChatMessageSuggestion(
type: 'emotes', type: 'emotes',

View File

@ -89,7 +89,6 @@ class MarkdownTextContent extends StatelessWidget {
case 'stickers': case 'stickers':
double radius = 8; double radius = 8;
final StickerProvider sticker = Get.find(); final StickerProvider sticker = Get.find();
url = sticker.aliasImageMapping[segments[1].toUpperCase()]!;
if (emojiMatch.length <= 1 && isOnlyEmoji) { if (emojiMatch.length <= 1 && isOnlyEmoji) {
width = 128; width = 128;
height = 128; height = 128;
@ -106,11 +105,20 @@ class MarkdownTextContent extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(radius)), borderRadius: BorderRadius.all(Radius.circular(radius)),
child: Container( child: Container(
color: Theme.of(context).colorScheme.surfaceContainer, color: Theme.of(context).colorScheme.surfaceContainer,
child: AutoCacheImage( child: FutureBuilder(
url, future: sticker.getStickerByAlias(segments[1]),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
return AutoCacheImage(
snapshot.data!.imageUrl,
width: width, width: width,
height: height, height: height,
fit: fit, fit: fit,
noErrorWidget: true,
);
},
), ),
), ),
).paddingSymmetric(vertical: 4); ).paddingSymmetric(vertical: 4);
@ -172,7 +180,8 @@ class _CustomEmoteInlineSyntax extends InlineSyntax {
bool onMatch(markdown.InlineParser parser, Match match) { bool onMatch(markdown.InlineParser parser, Match match) {
final StickerProvider sticker = Get.find(); final StickerProvider sticker = Get.find();
final alias = match[1]!.toUpperCase(); final alias = match[1]!.toUpperCase();
if (sticker.aliasImageMapping[alias] == null) { if (sticker.stickerCache.containsKey(alias) &&
sticker.stickerCache[alias] == null) {
parser.advanceBy(1); parser.advanceBy(1);
return false; return false;
} }