import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:injectable/injectable.dart'; import 'package:keyboard/base/base_controller.dart'; import 'package:keyboard/data/bean/character_info.dart'; import 'package:keyboard/data/consts/event_report.dart'; import 'package:keyboard/data/repository/account_repository.dart'; import 'package:keyboard/data/repository/keyboard_repository.dart'; import 'package:keyboard/dialog/character_add_dialog.dart'; import 'package:keyboard/dialog/custom_character/custom_character_add_dialog.dart'; import 'package:keyboard/dialog/login/login_dialog.dart'; import 'package:keyboard/handler/event_handler.dart'; import 'package:keyboard/module/character/content/character_group_content_controller.dart'; import 'package:keyboard/resource/string.gen.dart'; import 'package:keyboard/utils/atmob_log.dart'; import 'package:keyboard/utils/toast_util.dart'; import '../../data/bean/keyboard_info.dart'; import '../../data/consts/error_code.dart'; import '../../plugins/keyboard_android_platform.dart'; import '../../utils/error_handler.dart'; import '../../utils/http_handler.dart'; enum KeyboardType { system, //通用键盘 custom, //自定义键盘 } @injectable class KeyboardManageController extends BaseController with GetTickerProviderStateMixin { final String tag = 'KeyboardManageController'; final AccountRepository accountRepository; bool get isLogin => accountRepository.isLogin.value; // 自定义键盘列表 final RxList _customKeyboardInfoList = RxList(); List get customKeyboardInfoList => _customKeyboardInfoList; // 当前自定义键盘 final Rx _currentCustomKeyboardInfo = KeyboardInfo().obs; KeyboardInfo get currentCustomKeyboardInfo => _currentCustomKeyboardInfo.value; //当前自定义键盘人设列表 final RxList _currentCustomKeyboardCharacterList = RxList(); RxList get currentCustomKeyboardCharacterList => _currentCustomKeyboardCharacterList; // 当前自定义键盘亲密度 final RxInt _currentCustomIntimacy = 0.obs; int get currentCustomIntimacy => _currentCustomIntimacy.value; // 当前定制亲密度是否有变化 final RxBool _customIntimacyChanged = false.obs; bool get customIntimacyChanged => _customIntimacyChanged.value; final RxBool _customKeyboardCharacterListChanged = false.obs; bool get customKeyboardCharacterListChanged => _customKeyboardCharacterListChanged.value; // 存储排序前的定制人设列表,用于比较是否有变化 List _oldCustomCharacterList = []; // 通用键盘列表 final RxList _generalKeyboardInfoList = RxList(); List get generalKeyboardInfoList => _generalKeyboardInfoList; // 当前通用键盘 final Rx _currentGeneralKeyboardInfo = KeyboardInfo().obs; KeyboardInfo get currentGeneralKeyboardInfo => _currentGeneralKeyboardInfo.value; // 当前通用键盘人设列表 final RxList _currentGeneralKeyboardCharacterList = RxList(); List get currentGeneralKeyboardCharacterList => _currentGeneralKeyboardCharacterList; // 当前通用键盘亲密度 final RxInt _currentGeneralIntimacy = 0.obs; int get currentGeneralIntimacy => _currentGeneralIntimacy.value; // 当前通用亲密度是否有变化 final RxBool _generalIntimacyChanged = false.obs; RxBool get generalIntimacyChanged => _generalIntimacyChanged; final RxBool _generalKeyboardCharacterListChanged = false.obs; bool get generalKeyboardCharacterListChanged => _generalKeyboardCharacterListChanged.value; // 存储排序前的通用人设列表,用于比较是否有变化 late List _oldGeneralCharacterList; final KeyboardRepository keyboardRepository; // 最小人设数量 final _minCount = 9; // 键盘管理类型 List keyboardManageType = [ StringName.keyboardCustom, StringName.generalKeyboard, ]; // 键盘管理页面的tabController,用于控制通用键盘和自定义键盘的切换 late TabController tabController; // 键盘管理页面的pageController,用于控制通用键盘和自定义键盘的切换 late PageController pageController; // 首次加载数据标志 final isFirstLoad = true.obs; KeyboardManageController(this.keyboardRepository, this.accountRepository); @override void onInit() async { super.onInit(); final args = Get.arguments; if (args is Map && args["customKeyboardInfo"] is KeyboardInfo) { _currentCustomKeyboardInfo.value = args["customKeyboardInfo"]; } await _dataLoad(); } _dataLoad() async { tabController = TabController( length: keyboardManageType.length, vsync: this, initialIndex: 0, ); tabController.addListener(() { if (tabController.indexIsChanging) { switchTabKeyboardType(tabController.index); if (tabController.index == 0) { EventHandler.report(EventId.event_13001); } else { EventHandler.report(EventId.event_13003); } } }); pageController = PageController(); await getCustomKeyboard(); if (isFirstLoad.value) { if (_customKeyboardInfoList.isEmpty) { // 去另一个tab pageController.jumpToPage(1); } isFirstLoad.value = false; } if (tabController.index == 0) { EventHandler.report(EventId.event_13001); } getGeneralKeyboard(); } clickBack() { AtmobLog.i(tag, 'clickBack'); Get.back(); } @override void onReady() { super.onReady(); } // 获取定制键盘 Future getCustomKeyboard() async { AtmobLog.i(tag, 'getCustomKeyboard'); await keyboardRepository.getKeyboardList(type: KeyboardType.custom.name).then(( keyboardListResponse, ) { AtmobLog.i( tag, 'keyboardListResponse: ${keyboardListResponse.keyboardInfos}', ); _customKeyboardInfoList.value = keyboardListResponse.keyboardInfos; //检查是否是选择的键盘,如果没有选择的键盘,默认选择第一个 if (_customKeyboardInfoList.isNotEmpty) { if (_currentCustomKeyboardInfo.value.id == null) { _currentCustomKeyboardInfo.value = _customKeyboardInfoList.firstWhere( (element) => element.isChoose == true, orElse: () => _customKeyboardInfoList.first, ); } _currentCustomIntimacy.value = _currentCustomKeyboardInfo.value.intimacy ?? 0; _currentCustomIntimacy.listen((intimacy) { _customIntimacyChanged.value = _currentCustomKeyboardInfo.value.intimacy != intimacy; AtmobLog.d(tag, 'intimacyChanged: $_customIntimacyChanged'); }); String? id = _currentCustomKeyboardInfo.value.id; if (id != null) { getKeyboardCharacterList(keyboardId: id, isCustom: true); } } }); } // 获取通用键盘 void getGeneralKeyboard() { AtmobLog.i(tag, 'getGeneralKeyboard'); keyboardRepository.getKeyboardList(type: KeyboardType.system.name).then(( keyboardListResponse, ) { AtmobLog.i( tag, 'keyboardListResponse: ${keyboardListResponse.keyboardInfos}', ); _generalKeyboardInfoList.value = keyboardListResponse.keyboardInfos; _currentGeneralKeyboardInfo.value = _generalKeyboardInfoList.first; _currentGeneralIntimacy.value = _currentGeneralKeyboardInfo.value.intimacy ?? 0; _currentGeneralIntimacy.listen((intimacy) { _generalIntimacyChanged.value = _currentGeneralKeyboardInfo.value.intimacy != intimacy; AtmobLog.d(tag, 'intimacyChanged: $_generalIntimacyChanged'); }); String? id = _currentGeneralKeyboardInfo.value.id; if (id != null) { getKeyboardCharacterList(keyboardId: id, isCustom: false); } }); } // 获取当前键盘人设列表 void getKeyboardCharacterList({ required String keyboardId, required bool isCustom, }) { if (isCustom) { keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then(( keyboardCharacterListResponse, ) { AtmobLog.i( tag, 'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}', ); _currentCustomKeyboardCharacterList.assignAll( keyboardCharacterListResponse.characterInfos, ); _oldCustomCharacterList = List.from( _currentCustomKeyboardCharacterList, ); _customKeyboardCharacterListChanged.value = false; _currentCustomKeyboardCharacterList.listen((event) { _customKeyboardCharacterListChanged.value = !ListEquality().equals(_oldCustomCharacterList, event); AtmobLog.d( tag, '_customKeyboardCharacterListChanged: $_customKeyboardCharacterListChanged', ); }); }); } else { keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then(( keyboardCharacterListResponse, ) { AtmobLog.i( tag, 'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}', ); if (_currentGeneralKeyboardInfo.value.id == keyboardId) { _currentGeneralKeyboardCharacterList.value = keyboardCharacterListResponse.characterInfos; _oldGeneralCharacterList = List.from( _currentGeneralKeyboardCharacterList, ); _generalKeyboardCharacterListChanged.value = false; _currentGeneralKeyboardCharacterList.listen((event) { _generalKeyboardCharacterListChanged.value = !ListEquality().equals(_oldGeneralCharacterList, event); AtmobLog.d( tag, '_generalKeyboardCharacterListChanged: $_generalKeyboardCharacterListChanged', ); }); } if (_currentCustomKeyboardInfo.value.id == keyboardId) { _currentCustomKeyboardCharacterList.value = keyboardCharacterListResponse.characterInfos; } }); } } // 切换当前定制键盘 void switchCustomKeyboard(String? keyboardName) { _currentCustomKeyboardInfo.value = _customKeyboardInfoList.firstWhere( (element) => element.name == keyboardName, orElse: () => _customKeyboardInfoList.first, ); String? keyboardId = _currentCustomKeyboardInfo.value.id; _currentCustomIntimacy.value = _currentCustomKeyboardInfo.value.intimacy ?? 0; if (keyboardId != null) { getKeyboardCharacterList(keyboardId: keyboardId, isCustom: true); } } // tab切换 void switchTabKeyboardType(int index) { // AtmobLog.i(tag, 'onTabChanged: $index'); pageController.animateToPage( index, duration: const Duration(milliseconds: 300), curve: Curves.easeInToLinear, ); } // page切换 void switchPageKeyboardType(int index) { // AtmobLog.i(tag, 'onPageChanged: $index'); tabController.animateTo(index, duration: const Duration(milliseconds: 300)); if (index == 0) { _currentGeneralIntimacy.value = _currentGeneralKeyboardInfo.value.intimacy ?? 0; _currentGeneralKeyboardCharacterList.value = _oldGeneralCharacterList; _generalIntimacyChanged.value = false; _generalKeyboardCharacterListChanged.value = false; getCustomKeyboard(); } else { _currentCustomIntimacy.value = _currentCustomKeyboardInfo.value.intimacy ?? 0; if (_oldCustomCharacterList.isNotEmpty) { _currentCustomKeyboardCharacterList.value = _oldCustomCharacterList; } _customIntimacyChanged.value = false; _customKeyboardCharacterListChanged.value = false; getGeneralKeyboard(); } } // 更新亲密度 void updateIntimacy(int intimacy, bool isCustom) { if (isCustom) { _currentCustomIntimacy.value = intimacy; } else { _currentGeneralIntimacy.value = intimacy; } } // 排序 void onReorder(int oldIndex, int newIndex, bool isCustom) { if (isCustom) { reorderList(_currentCustomKeyboardCharacterList, oldIndex, newIndex); } else { reorderList(_currentGeneralKeyboardCharacterList, oldIndex, newIndex); } } // 排序 void reorderList(RxList list, int oldIndex, int newIndex) { AtmobLog.d(tag, 'reorderList: $oldIndex, $newIndex'); final item = list.removeAt(oldIndex); list.insert(newIndex, item); } void clickSave(bool isCustom) { isCustom ? saveCustomKeyboardCharacterList() : saveGeneralKeyboardCharacterList(); } void saveCustomKeyboardCharacterList() { EventHandler.report(EventId.event_13002); _saveKeyboardInfo( intimacyChanged: _customIntimacyChanged, currentIntimacy: currentCustomIntimacy, currentKeyboardInfo: _currentCustomKeyboardInfo, characterListChanged: _customKeyboardCharacterListChanged, currentCharacterList: _currentCustomKeyboardCharacterList, onUpdateSuccess: () { _oldCustomCharacterList = List.from( _currentCustomKeyboardCharacterList, ); Get.find().refreshData(); // 通知键盘,刷新人设列表 KeyboardAndroidPlatform.refreshCharacterList(); saveSuccessGetBack(); }, ); } void saveGeneralKeyboardCharacterList() { EventHandler.report(EventId.event_13004); _saveKeyboardInfo( intimacyChanged: _generalIntimacyChanged, currentIntimacy: currentGeneralIntimacy, currentKeyboardInfo: _currentGeneralKeyboardInfo, characterListChanged: _generalKeyboardCharacterListChanged, currentCharacterList: _currentGeneralKeyboardCharacterList, onUpdateSuccess: () { _oldGeneralCharacterList = List.from( _currentGeneralKeyboardCharacterList, ); // 通知键盘,刷新人设列表 KeyboardAndroidPlatform.refreshCharacterList(); }, ); } void _saveKeyboardInfo({ required RxBool intimacyChanged, required int currentIntimacy, required Rx currentKeyboardInfo, required RxBool characterListChanged, required List currentCharacterList, required VoidCallback onUpdateSuccess, }) { String? keyboardId = currentKeyboardInfo.value.id; if (intimacyChanged.value && keyboardId != null) { AtmobLog.i(tag, 'clickSave intimacyChanged'); currentKeyboardInfo.value.intimacy = currentIntimacy; keyboardRepository .updateKeyboardInfo(keyboardId: keyboardId, intimacy: currentIntimacy) .then((_) async { ToastUtil.show(StringName.keyboardSaveSuccess); await keyboardRepository.refreshData(); }) .catchError((error) { if (error is ServerErrorException) { ErrorHandler.toastError(error); if (error.code == ErrorCode.noLoginError) { LoginDialog.show(); } } else { ToastUtil.show(StringName.keyboardSaveFailed); } }) .whenComplete(() => intimacyChanged.value = false); } if (characterListChanged.value && keyboardId != null) { AtmobLog.i(tag, 'clickSave keyboardChanged'); List characterIds = currentCharacterList.map((e) => e.id).cast().toList(); keyboardRepository .keyboardCharacterUpdate( keyboardId: keyboardId, characterIds: characterIds, ) .then((_) async { onUpdateSuccess(); ToastUtil.show(StringName.keyboardSaveSuccess); await keyboardRepository.refreshData(); }) .catchError((error) { if (error is ServerErrorException) { ErrorHandler.toastError(error); if (error.code == ErrorCode.noLoginError) { LoginDialog.show(); } } else { ToastUtil.show(StringName.keyboardSaveFailed); } }) .whenComplete(() => characterListChanged.value = false); } } void clickRemoveCharacter(CharacterInfo characterInfo, bool isCustom) { if (isCustom) { if (_currentCustomKeyboardCharacterList.length <= _minCount) { ToastUtil.show("最少需要保持$_minCount个人设"); return; } AtmobLog.i(tag, 'clickRemoveCharacter'); _currentCustomKeyboardCharacterList.remove(characterInfo); } else { if (_currentGeneralKeyboardCharacterList.length <= _minCount) { ToastUtil.show("最少需要保持$_minCount个人设"); return; } AtmobLog.i(tag, 'clickRemoveCharacter'); _currentGeneralKeyboardCharacterList.remove(characterInfo); } } clickAddCharacter({required bool isCustom}) { if (!isLogin) { ToastUtil.show("请先登录"); LoginDialog.show(); return; } if (isCustom) { CharacterAddDialog.show( currentKeyboardInfo: currentCustomKeyboardInfo, clickCallback: () { getKeyboardCharacterList( keyboardId: _currentCustomKeyboardInfo.value.id ?? "", isCustom: true, ); }, ); } else { CharacterAddDialog.show( currentKeyboardInfo: currentGeneralKeyboardInfo, clickCallback: () { getGeneralKeyboard(); }, ); } } clickCustomCharacter() { if (!isLogin) { ToastUtil.show("请先登录"); LoginDialog.show(); return; } AtmobLog.i(tag, 'clickCustomCharacter'); CustomCharacterAddDialog.show( currentKeyboardInfo: currentCustomKeyboardInfo, clickCallback: () { getKeyboardCharacterList( keyboardId: _currentCustomKeyboardInfo.value.id ?? "", isCustom: true, ); }, ); } @override void onClose() { tabController.dispose(); pageController.dispose(); super.onClose(); } void saveSuccessGetBack() { Get.back(result: _currentCustomKeyboardCharacterList); } }