⚡ Sticker cache
This commit is contained in:
parent
e075804782
commit
6235e736b9
@ -1,11 +1,17 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:surface/database/database.dart';
|
||||||
import 'package:surface/logger.dart';
|
import 'package:surface/logger.dart';
|
||||||
|
import 'package:surface/providers/database.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/types/attachment.dart';
|
import 'package:surface/types/attachment.dart';
|
||||||
|
|
||||||
class SnStickerProvider {
|
class SnStickerProvider {
|
||||||
late final SnNetworkProvider _sn;
|
late final SnNetworkProvider _sn;
|
||||||
|
late final DatabaseProvider _dt;
|
||||||
final Map<String, SnSticker?> _cache = {};
|
final Map<String, SnSticker?> _cache = {};
|
||||||
|
|
||||||
final Map<int, List<SnSticker>> stickersByPack = {};
|
final Map<int, List<SnSticker>> stickersByPack = {};
|
||||||
@ -15,6 +21,7 @@ class SnStickerProvider {
|
|||||||
|
|
||||||
SnStickerProvider(BuildContext context) {
|
SnStickerProvider(BuildContext context) {
|
||||||
_sn = context.read<SnNetworkProvider>();
|
_sn = context.read<SnNetworkProvider>();
|
||||||
|
_dt = context.read<DatabaseProvider>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNotSticker(String alias) {
|
bool hasNotSticker(String alias) {
|
||||||
@ -31,22 +38,32 @@ class SnStickerProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void putSticker(Iterable<SnSticker> sticker) {
|
void putSticker(Iterable<SnSticker> stickers) {
|
||||||
for (final ele in sticker) {
|
for (final ele in stickers) {
|
||||||
_cacheSticker(ele);
|
_cacheSticker(ele);
|
||||||
}
|
}
|
||||||
|
_saveStickerToLocal(stickers);
|
||||||
|
_saveStickerPackToLocal(stickers.map((ele) => ele.pack).toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<SnSticker?> lookupSticker(String alias) async {
|
Future<SnSticker?> lookupSticker(String alias) async {
|
||||||
|
// In-memory cache
|
||||||
if (_cache.containsKey(alias)) {
|
if (_cache.containsKey(alias)) {
|
||||||
return _cache[alias];
|
return _cache[alias];
|
||||||
}
|
}
|
||||||
|
// On-disk cache
|
||||||
|
final localStickers = await (_dt.db.snLocalSticker.select()
|
||||||
|
..where((e) => e.fullAlias.equals(alias)))
|
||||||
|
.getSingleOrNull();
|
||||||
|
if (localStickers != null) {
|
||||||
|
_cache[alias] = localStickers.content;
|
||||||
|
return localStickers.content;
|
||||||
|
}
|
||||||
|
// Remote server
|
||||||
try {
|
try {
|
||||||
final resp = await _sn.client.get('/cgi/uc/stickers/lookup/$alias');
|
final resp = await _sn.client.get('/cgi/uc/stickers/lookup/$alias');
|
||||||
final sticker = SnSticker.fromJson(resp.data);
|
final sticker = SnSticker.fromJson(resp.data);
|
||||||
_cacheSticker(sticker);
|
putSticker([sticker]);
|
||||||
|
|
||||||
return sticker;
|
return sticker;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
_cache[alias] = null;
|
_cache[alias] = null;
|
||||||
@ -57,6 +74,18 @@ class SnStickerProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> listSticker() async {
|
Future<void> listSticker() async {
|
||||||
|
final localPacks = await _dt.db.snLocalStickerPack.select().get();
|
||||||
|
final localStickers = await _dt.db.snLocalSticker.select().get();
|
||||||
|
final local = localStickers.map((ele) {
|
||||||
|
return ele.content.copyWith(
|
||||||
|
pack: localPacks
|
||||||
|
.firstWhere((pk) => pk.content.id == ele.content.packId)
|
||||||
|
.content,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
for (final sticker in local) {
|
||||||
|
_cacheSticker(sticker);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final resp = await _sn.client.get('/cgi/uc/stickers');
|
final resp = await _sn.client.get('/cgi/uc/stickers');
|
||||||
final data = resp.data;
|
final data = resp.data;
|
||||||
@ -69,4 +98,35 @@ class SnStickerProvider {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _saveStickerToLocal(Iterable<SnSticker> stickers) async {
|
||||||
|
await _dt.db.snLocalSticker.insertAll(
|
||||||
|
stickers.map(
|
||||||
|
(ele) => SnLocalStickerCompanion.insert(
|
||||||
|
id: Value(ele.id),
|
||||||
|
alias: ele.alias,
|
||||||
|
fullAlias: '${ele.pack.prefix}${ele.alias}',
|
||||||
|
content: ele,
|
||||||
|
createdAt: Value(ele.createdAt),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onConflict: DoNothing(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _saveStickerPackToLocal(Iterable<SnStickerPack> packs) async {
|
||||||
|
final queries = packs
|
||||||
|
.map(
|
||||||
|
(ele) => _dt.db.snLocalStickerPack.insertOne(
|
||||||
|
SnLocalStickerPackCompanion.insert(
|
||||||
|
id: Value(ele.id),
|
||||||
|
content: ele,
|
||||||
|
createdAt: Value(ele.createdAt),
|
||||||
|
),
|
||||||
|
onConflict: DoUpdate((_) => SnLocalStickerPackCompanion.custom(
|
||||||
|
content: Constant(jsonEncode(ele.toJson()))))),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
await Future.wait(queries);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,10 @@ class _StickerPackAddPopupState extends State<_StickerPackAddPopup> {
|
|||||||
);
|
);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
context.showSnackbar('stickersAdded'.tr());
|
context.showSnackbar('stickersAdded'.tr());
|
||||||
if (_pack?.stickers != null) stickers.putSticker(_pack!.stickers!);
|
if (_pack?.stickers != null) {
|
||||||
|
stickers.putSticker(
|
||||||
|
_pack!.stickers!.map((ele) => ele.copyWith(pack: _pack!)));
|
||||||
|
}
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user