- BLE: 修复 BlueZ LocalName 与 Includes 冲突,串行注册与退避 - HTTP: 语音对话补 Live2D talking 标志与 session;Web 补 X-Session-Id - Flutter: 角色/对话/模型页 + API,Gradle/依赖升级,麦克风权限 - 文档: 新增 docs/STATUS.md,校准 CLAUDE/PROGRESS/README - 清理: 移除根目录截图与临时模型,运维脚本迁入 scripts/device
84 lines
2.2 KiB
Dart
84 lines
2.2 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
|
|
import '../models/character_pack.dart';
|
|
import '../services/http_api_service.dart';
|
|
import 'debug_provider.dart';
|
|
|
|
class CharacterProvider extends ChangeNotifier {
|
|
CharacterProvider({
|
|
required HttpApiService httpApiService,
|
|
required DebugProvider debugProvider,
|
|
}) : _http = httpApiService,
|
|
_debug = debugProvider;
|
|
|
|
final HttpApiService _http;
|
|
final DebugProvider _debug;
|
|
|
|
List<CharacterPack> _packs = const [];
|
|
String _active = '';
|
|
bool _loading = false;
|
|
bool _switching = false;
|
|
String? _error;
|
|
|
|
List<CharacterPack> get packs => _packs;
|
|
String get activeFilename => _active;
|
|
bool get isLoading => _loading;
|
|
bool get isSwitching => _switching;
|
|
String? get error => _error;
|
|
|
|
CharacterPack? get activePack {
|
|
for (final pack in _packs) {
|
|
if (pack.filename == _active) return pack;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Future<void> refresh() async {
|
|
_loading = true;
|
|
_error = null;
|
|
notifyListeners();
|
|
try {
|
|
final snapshot = await _http.getAvailableCharacterConfigs();
|
|
_packs = snapshot.configs;
|
|
_active = snapshot.active;
|
|
_debug.addHttpLog(
|
|
'Loaded characters',
|
|
details: 'count=${_packs.length} active=$_active',
|
|
);
|
|
} catch (error) {
|
|
_error = error.toString();
|
|
_debug.addHttpLog('Load characters failed', details: _error);
|
|
} finally {
|
|
_loading = false;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
|
|
Future<bool> switchTo(String filename) async {
|
|
if (_switching || filename == _active) return false;
|
|
_switching = true;
|
|
_error = null;
|
|
notifyListeners();
|
|
try {
|
|
final result = await _http.switchConfig(filename);
|
|
if (!result.isOk) {
|
|
_error = result.message;
|
|
_debug.addHttpLog('Switch character failed', details: result.message);
|
|
return false;
|
|
}
|
|
_active = filename;
|
|
_debug.addHttpLog('Switched character', details: filename);
|
|
// 热重载后刷新列表,确保 active 与服务端一致
|
|
await refresh();
|
|
return true;
|
|
} catch (error) {
|
|
_error = error.toString();
|
|
_debug.addHttpLog('Switch character failed', details: _error);
|
|
return false;
|
|
} finally {
|
|
_switching = false;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
}
|