feat: make core pages local-first offline
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:miaoji_zhang/shared/api/api_client.dart';
|
||||
import 'package:miaoji_zhang/shared/api/backend_identity.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
|
||||
class BrandConfig {
|
||||
@@ -41,6 +45,13 @@ class AvatarItem {
|
||||
defaultName = j['defaultName'] as String,
|
||||
speechTic = j['speechTic'] as String? ?? '',
|
||||
imageUrl = j['imageUrl'] as String?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'key': key,
|
||||
'defaultName': defaultName,
|
||||
'speechTic': speechTic,
|
||||
'imageUrl': imageUrl,
|
||||
};
|
||||
}
|
||||
|
||||
class PersonaItem {
|
||||
@@ -50,6 +61,13 @@ class PersonaItem {
|
||||
name = j['name'] as String,
|
||||
description = j['description'] as String? ?? '',
|
||||
sampleLine = j['sampleLine'] as String? ?? '';
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'key': key,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'sampleLine': sampleLine,
|
||||
};
|
||||
}
|
||||
|
||||
class CompanionDisplay {
|
||||
@@ -145,16 +163,59 @@ class PublicConfigApi {
|
||||
|
||||
static Future<List<AvatarItem>> avatars() async {
|
||||
final res = await _dio.get('/api/public/avatars');
|
||||
return (res.data as List)
|
||||
final values = (res.data as List)
|
||||
.map((e) => AvatarItem.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
await _cacheCatalog(
|
||||
_avatarCacheKey,
|
||||
values.map((e) => e.toJson()).toList(),
|
||||
);
|
||||
return values;
|
||||
}
|
||||
|
||||
static Future<List<PersonaItem>> personas() async {
|
||||
final res = await _dio.get('/api/public/personas');
|
||||
return (res.data as List)
|
||||
final values = (res.data as List)
|
||||
.map((e) => PersonaItem.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
await _cacheCatalog(
|
||||
_personaCacheKey,
|
||||
values.map((e) => e.toJson()).toList(),
|
||||
);
|
||||
return values;
|
||||
}
|
||||
|
||||
static Future<List<AvatarItem>> cachedAvatars() async =>
|
||||
(await _cachedCatalog(_avatarCacheKey)).map(AvatarItem.fromJson).toList();
|
||||
|
||||
static Future<List<PersonaItem>> cachedPersonas() async =>
|
||||
(await _cachedCatalog(
|
||||
_personaCacheKey,
|
||||
)).map(PersonaItem.fromJson).toList();
|
||||
|
||||
static String get _avatarCacheKey =>
|
||||
'public_avatars_${BackendIdentity.scope}';
|
||||
static String get _personaCacheKey =>
|
||||
'public_personas_${BackendIdentity.scope}';
|
||||
|
||||
static Future<void> _cacheCatalog(
|
||||
String key,
|
||||
List<Map<String, dynamic>> values,
|
||||
) async {
|
||||
await (await SharedPreferences.getInstance()).setString(
|
||||
key,
|
||||
jsonEncode(values),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<List<Map<String, dynamic>>> _cachedCatalog(String key) async {
|
||||
final value = (await SharedPreferences.getInstance()).getString(key);
|
||||
if (value == null) return const [];
|
||||
try {
|
||||
return (jsonDecode(value) as List).cast<Map<String, dynamic>>().toList();
|
||||
} catch (_) {
|
||||
return const [];
|
||||
}
|
||||
}
|
||||
|
||||
static String? _normalizeName(String? value) {
|
||||
|
||||
Reference in New Issue
Block a user