keyboard_manage_controller.dart 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. import 'package:collection/collection.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import 'package:injectable/injectable.dart';
  5. import 'package:keyboard/base/base_controller.dart';
  6. import 'package:keyboard/data/bean/character_info.dart';
  7. import 'package:keyboard/data/repository/account_repository.dart';
  8. import 'package:keyboard/data/repository/keyboard_repository.dart';
  9. import 'package:keyboard/dialog/character_add_dialog.dart';
  10. import 'package:keyboard/dialog/custom_character/custom_character_add_dialog.dart';
  11. import 'package:keyboard/module/character/content/character_group_content_controller.dart';
  12. import 'package:keyboard/resource/string.gen.dart';
  13. import 'package:keyboard/utils/atmob_log.dart';
  14. import 'package:keyboard/utils/toast_util.dart';
  15. import '../../data/bean/keyboard_info.dart';
  16. import '../../utils/error_handler.dart';
  17. import '../../utils/http_handler.dart';
  18. enum KeyboardType {
  19. system, //通用键盘
  20. custom, //自定义键盘
  21. }
  22. @injectable
  23. class KeyboardManageController extends BaseController
  24. with GetTickerProviderStateMixin {
  25. final String tag = 'KeyboardManageController';
  26. final AccountRepository accountRepository;
  27. bool get isLogin => accountRepository.isLogin.value;
  28. // 自定义键盘列表
  29. final RxList<KeyboardInfo> _customKeyboardInfoList = RxList();
  30. List<KeyboardInfo> get customKeyboardInfoList => _customKeyboardInfoList;
  31. // 当前自定义键盘
  32. final Rx<KeyboardInfo> _currentCustomKeyboardInfo = KeyboardInfo().obs;
  33. KeyboardInfo get currentCustomKeyboardInfo =>
  34. _currentCustomKeyboardInfo.value;
  35. //当前自定义键盘人设列表
  36. final RxList<CharacterInfo> _currentCustomKeyboardCharacterList = RxList();
  37. RxList<CharacterInfo> get currentCustomKeyboardCharacterList =>
  38. _currentCustomKeyboardCharacterList;
  39. // 当前自定义键盘亲密度
  40. final RxInt _currentCustomIntimacy = 0.obs;
  41. int get currentCustomIntimacy => _currentCustomIntimacy.value;
  42. // 当前定制亲密度是否有变化
  43. final RxBool _customIntimacyChanged = false.obs;
  44. bool get customIntimacyChanged => _customIntimacyChanged.value;
  45. final RxBool _customKeyboardCharacterListChanged = false.obs;
  46. bool get customKeyboardCharacterListChanged =>
  47. _customKeyboardCharacterListChanged.value;
  48. // 存储排序前的定制人设列表,用于比较是否有变化
  49. List<CharacterInfo> _oldCustomCharacterList = [];
  50. // 通用键盘列表
  51. final RxList<KeyboardInfo> _generalKeyboardInfoList = RxList();
  52. List<KeyboardInfo> get generalKeyboardInfoList => _generalKeyboardInfoList;
  53. // 当前通用键盘
  54. final Rx<KeyboardInfo> _currentGeneralKeyboardInfo = KeyboardInfo().obs;
  55. KeyboardInfo get currentGeneralKeyboardInfo =>
  56. _currentGeneralKeyboardInfo.value;
  57. // 当前通用键盘人设列表
  58. final RxList<CharacterInfo> _currentGeneralKeyboardCharacterList = RxList();
  59. List<CharacterInfo> get currentGeneralKeyboardCharacterList =>
  60. _currentGeneralKeyboardCharacterList;
  61. // 当前通用键盘亲密度
  62. final RxInt _currentGeneralIntimacy = 0.obs;
  63. int get currentGeneralIntimacy => _currentGeneralIntimacy.value;
  64. // 当前通用亲密度是否有变化
  65. final RxBool _generalIntimacyChanged = false.obs;
  66. RxBool get generalIntimacyChanged => _generalIntimacyChanged;
  67. final RxBool _generalKeyboardCharacterListChanged = false.obs;
  68. bool get generalKeyboardCharacterListChanged =>
  69. _generalKeyboardCharacterListChanged.value;
  70. // 存储排序前的通用人设列表,用于比较是否有变化
  71. late List<CharacterInfo> _oldGeneralCharacterList;
  72. final KeyboardRepository keyboardRepository;
  73. // 最小人设数量
  74. final _minCount = 9;
  75. // 键盘管理类型
  76. List<String> keyboardManageType = [
  77. StringName.keyboardCustom,
  78. StringName.generalKeyboard,
  79. ];
  80. // 键盘管理页面的tabController,用于控制通用键盘和自定义键盘的切换
  81. late TabController tabController;
  82. // 键盘管理页面的pageController,用于控制通用键盘和自定义键盘的切换
  83. late PageController pageController;
  84. KeyboardManageController(this.keyboardRepository, this.accountRepository);
  85. @override
  86. void onInit() {
  87. super.onInit();
  88. final args = Get.arguments;
  89. if (args is Map && args["customKeyboardInfo"] is KeyboardInfo) {
  90. _currentCustomKeyboardInfo.value = args["customKeyboardInfo"];
  91. }
  92. _dataLoad();
  93. }
  94. _dataLoad() {
  95. tabController = TabController(
  96. length: keyboardManageType.length,
  97. vsync: this,
  98. initialIndex: 0,
  99. );
  100. tabController.addListener(() {
  101. if (tabController.indexIsChanging) {
  102. switchTabKeyboardType(tabController.index);
  103. }
  104. });
  105. pageController = PageController();
  106. getCustomKeyboard();
  107. getGeneralKeyboard();
  108. }
  109. clickBack() {
  110. AtmobLog.i(tag, 'clickBack');
  111. Get.back();
  112. }
  113. // 获取定制键盘
  114. void getCustomKeyboard() {
  115. AtmobLog.i(tag, 'getCustomKeyboard');
  116. keyboardRepository.getKeyboardList(type: KeyboardType.custom.name).then((
  117. keyboardListResponse,
  118. ) {
  119. AtmobLog.i(
  120. tag,
  121. 'keyboardListResponse: ${keyboardListResponse.keyboardInfos}',
  122. );
  123. _customKeyboardInfoList.value = keyboardListResponse.keyboardInfos;
  124. //检查是否是选择的键盘,如果没有选择的键盘,默认选择第一个
  125. if (_customKeyboardInfoList.isNotEmpty) {
  126. if (_currentCustomKeyboardInfo.value.id == null) {
  127. _currentCustomKeyboardInfo.value = _customKeyboardInfoList.firstWhere(
  128. (element) => element.isChoose == true,
  129. orElse: () => _customKeyboardInfoList.first,
  130. );
  131. }
  132. _currentCustomIntimacy.value =
  133. _currentCustomKeyboardInfo.value.intimacy ?? 0;
  134. _currentCustomIntimacy.listen((intimacy) {
  135. _customIntimacyChanged.value =
  136. _currentCustomKeyboardInfo.value.intimacy != intimacy;
  137. AtmobLog.d(tag, 'intimacyChanged: $_customIntimacyChanged');
  138. });
  139. String? id = _currentCustomKeyboardInfo.value.id;
  140. if (id != null) {
  141. getKeyboardCharacterList(keyboardId: id, isCustom: true);
  142. }
  143. }
  144. });
  145. }
  146. // 获取通用键盘
  147. void getGeneralKeyboard() {
  148. AtmobLog.i(tag, 'getGeneralKeyboard');
  149. keyboardRepository.getKeyboardList(type: KeyboardType.system.name).then((
  150. keyboardListResponse,
  151. ) {
  152. AtmobLog.i(
  153. tag,
  154. 'keyboardListResponse: ${keyboardListResponse.keyboardInfos}',
  155. );
  156. _generalKeyboardInfoList.value = keyboardListResponse.keyboardInfos;
  157. _currentGeneralKeyboardInfo.value = _generalKeyboardInfoList.first;
  158. _currentGeneralIntimacy.value =
  159. _currentGeneralKeyboardInfo.value.intimacy ?? 0;
  160. _currentGeneralIntimacy.listen((intimacy) {
  161. _generalIntimacyChanged.value =
  162. _currentGeneralKeyboardInfo.value.intimacy != intimacy;
  163. AtmobLog.d(tag, 'intimacyChanged: $_generalIntimacyChanged');
  164. });
  165. String? id = _currentGeneralKeyboardInfo.value.id;
  166. if (id != null) {
  167. getKeyboardCharacterList(keyboardId: id, isCustom: false);
  168. }
  169. });
  170. }
  171. // 获取当前键盘人设列表
  172. void getKeyboardCharacterList({
  173. required String keyboardId,
  174. required bool isCustom,
  175. }) {
  176. if (isCustom) {
  177. keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then((
  178. keyboardCharacterListResponse,
  179. ) {
  180. AtmobLog.i(
  181. tag,
  182. 'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}',
  183. );
  184. _currentCustomKeyboardCharacterList.assignAll(
  185. keyboardCharacterListResponse.characterInfos,
  186. );
  187. _oldCustomCharacterList = List<CharacterInfo>.from(
  188. _currentCustomKeyboardCharacterList,
  189. );
  190. _customKeyboardCharacterListChanged.value = false;
  191. _currentCustomKeyboardCharacterList.listen((event) {
  192. _customKeyboardCharacterListChanged.value =
  193. !ListEquality().equals(_oldCustomCharacterList, event);
  194. AtmobLog.d(
  195. tag,
  196. '_customKeyboardCharacterListChanged: $_customKeyboardCharacterListChanged',
  197. );
  198. });
  199. });
  200. } else {
  201. keyboardRepository.getKeyboardCharacterList(keyboardId: keyboardId).then((
  202. keyboardCharacterListResponse,
  203. ) {
  204. AtmobLog.i(
  205. tag,
  206. 'keyboardCharacterListResponse: ${keyboardCharacterListResponse.characterInfos.toString()}',
  207. );
  208. if (_currentGeneralKeyboardInfo.value.id == keyboardId) {
  209. _currentGeneralKeyboardCharacterList.value =
  210. keyboardCharacterListResponse.characterInfos;
  211. _oldGeneralCharacterList = List<CharacterInfo>.from(
  212. _currentGeneralKeyboardCharacterList,
  213. );
  214. _generalKeyboardCharacterListChanged.value = false;
  215. _currentGeneralKeyboardCharacterList.listen((event) {
  216. _generalKeyboardCharacterListChanged.value =
  217. !ListEquality().equals(_oldGeneralCharacterList, event);
  218. AtmobLog.d(
  219. tag,
  220. '_generalKeyboardCharacterListChanged: $_generalKeyboardCharacterListChanged',
  221. );
  222. });
  223. }
  224. if (_currentCustomKeyboardInfo.value.id == keyboardId) {
  225. _currentCustomKeyboardCharacterList.value =
  226. keyboardCharacterListResponse.characterInfos;
  227. }
  228. });
  229. }
  230. }
  231. // 切换当前定制键盘
  232. void switchCustomKeyboard(String? keyboardName) {
  233. _currentCustomKeyboardInfo.value = _customKeyboardInfoList.firstWhere(
  234. (element) => element.name == keyboardName,
  235. orElse: () => _customKeyboardInfoList.first,
  236. );
  237. String? keyboardId = _currentCustomKeyboardInfo.value.id;
  238. _currentCustomIntimacy.value =
  239. _currentCustomKeyboardInfo.value.intimacy ?? 0;
  240. if (keyboardId != null) {
  241. getKeyboardCharacterList(keyboardId: keyboardId, isCustom: true);
  242. }
  243. }
  244. // 切换当前通用键盘
  245. void switchGeneralKeyboard(String? keyboardName) {
  246. _currentGeneralKeyboardInfo.value = _generalKeyboardInfoList.firstWhere(
  247. (element) => element.name == keyboardName,
  248. orElse: () => _generalKeyboardInfoList.first,
  249. );
  250. String? keyboardId = _currentGeneralKeyboardInfo.value.id;
  251. _currentGeneralIntimacy.value =
  252. _currentGeneralKeyboardInfo.value.intimacy ?? 0;
  253. if (keyboardId != null) {
  254. getKeyboardCharacterList(keyboardId: keyboardId, isCustom: false);
  255. }
  256. }
  257. // tab切换
  258. void switchTabKeyboardType(int index) {
  259. // AtmobLog.i(tag, 'onTabChanged: $index');
  260. pageController.animateToPage(
  261. index,
  262. duration: const Duration(milliseconds: 300),
  263. curve: Curves.easeInToLinear,
  264. );
  265. }
  266. // page切换
  267. void switchPageKeyboardType(int index) {
  268. // AtmobLog.i(tag, 'onPageChanged: $index');
  269. tabController.animateTo(index, duration: const Duration(milliseconds: 300));
  270. if (index == 0) {
  271. _currentGeneralIntimacy.value =
  272. _currentGeneralKeyboardInfo.value.intimacy ?? 0;
  273. _currentGeneralKeyboardCharacterList.value = _oldGeneralCharacterList;
  274. _generalIntimacyChanged.value = false;
  275. _generalKeyboardCharacterListChanged.value = false;
  276. getCustomKeyboard();
  277. } else {
  278. _currentCustomIntimacy.value =
  279. _currentCustomKeyboardInfo.value.intimacy ?? 0;
  280. if(_oldCustomCharacterList.isNotEmpty){
  281. _currentCustomKeyboardCharacterList.value = _oldCustomCharacterList;
  282. }
  283. _customIntimacyChanged.value = false;
  284. _customKeyboardCharacterListChanged.value = false;
  285. getGeneralKeyboard();
  286. }
  287. }
  288. // 更新亲密度
  289. void updateIntimacy(int intimacy, bool isCustom) {
  290. if (isCustom) {
  291. _currentCustomIntimacy.value = intimacy;
  292. } else {
  293. _currentGeneralIntimacy.value = intimacy;
  294. }
  295. }
  296. // 排序
  297. void onReorder(int oldIndex, int newIndex, bool isCustom) {
  298. if (isCustom) {
  299. reorderList(_currentCustomKeyboardCharacterList, oldIndex, newIndex);
  300. } else {
  301. reorderList(_currentGeneralKeyboardCharacterList, oldIndex, newIndex);
  302. }
  303. }
  304. // 排序
  305. void reorderList<T>(RxList<T> list, int oldIndex, int newIndex) {
  306. AtmobLog.d(tag, 'reorderList: $oldIndex, $newIndex');
  307. final item = list.removeAt(oldIndex);
  308. list.insert(newIndex, item);
  309. }
  310. void clickSave(bool isCustom) {
  311. isCustom
  312. ? saveCustomKeyboardCharacterList()
  313. : saveGeneralKeyboardCharacterList();
  314. }
  315. void saveCustomKeyboardCharacterList() {
  316. _saveKeyboardInfo(
  317. intimacyChanged: _customIntimacyChanged,
  318. currentIntimacy: currentCustomIntimacy,
  319. currentKeyboardInfo: _currentCustomKeyboardInfo,
  320. characterListChanged: _customKeyboardCharacterListChanged,
  321. currentCharacterList: _currentCustomKeyboardCharacterList,
  322. onUpdateSuccess: () {
  323. _oldCustomCharacterList = List<CharacterInfo>.from(
  324. _currentCustomKeyboardCharacterList,
  325. );
  326. Get.find<CharacterGroupContentController>().refreshData();
  327. saveSuccessGetBack();
  328. },
  329. );
  330. }
  331. void saveGeneralKeyboardCharacterList() {
  332. _saveKeyboardInfo(
  333. intimacyChanged: _generalIntimacyChanged,
  334. currentIntimacy: currentGeneralIntimacy,
  335. currentKeyboardInfo: _currentGeneralKeyboardInfo,
  336. characterListChanged: _generalKeyboardCharacterListChanged,
  337. currentCharacterList: _currentGeneralKeyboardCharacterList,
  338. onUpdateSuccess: () {
  339. _oldGeneralCharacterList = List<CharacterInfo>.from(
  340. _currentGeneralKeyboardCharacterList,
  341. );
  342. },
  343. );
  344. }
  345. void _saveKeyboardInfo({
  346. required RxBool intimacyChanged,
  347. required int currentIntimacy,
  348. required Rx<KeyboardInfo> currentKeyboardInfo,
  349. required RxBool characterListChanged,
  350. required List<CharacterInfo> currentCharacterList,
  351. required VoidCallback onUpdateSuccess,
  352. }) {
  353. String? keyboardId = currentKeyboardInfo.value.id;
  354. if (intimacyChanged.value && keyboardId != null) {
  355. AtmobLog.i(tag, 'clickSave intimacyChanged');
  356. currentKeyboardInfo.value.intimacy = currentIntimacy;
  357. keyboardRepository
  358. .updateKeyboardInfo(keyboardId: keyboardId, intimacy: currentIntimacy)
  359. .then((_) async {
  360. ToastUtil.show(StringName.keyboardSaveSuccess);
  361. await keyboardRepository.refreshData();
  362. })
  363. .catchError((error) {
  364. if (error is ServerErrorException) {
  365. ErrorHandler.toastError(error);
  366. }
  367. ToastUtil.show(StringName.keyboardSaveFailed);
  368. })
  369. .whenComplete(() => intimacyChanged.value = false);
  370. }
  371. if (characterListChanged.value && keyboardId != null) {
  372. AtmobLog.i(tag, 'clickSave keyboardChanged');
  373. List<String> characterIds =
  374. currentCharacterList.map((e) => e.id).cast<String>().toList();
  375. keyboardRepository
  376. .keyboardCharacterUpdate(
  377. keyboardId: keyboardId,
  378. characterIds: characterIds,
  379. )
  380. .then((_) async {
  381. onUpdateSuccess();
  382. ToastUtil.show(StringName.keyboardSaveSuccess);
  383. await keyboardRepository.refreshData();
  384. })
  385. .catchError((error) {
  386. if (error is ServerErrorException) {
  387. ErrorHandler.toastError(error);
  388. }
  389. ToastUtil.show(StringName.keyboardSaveFailed);
  390. })
  391. .whenComplete(() => characterListChanged.value = false);
  392. }
  393. }
  394. void clickRemoveCharacter(CharacterInfo characterInfo, bool isCustom) {
  395. if (isCustom) {
  396. if (_currentCustomKeyboardCharacterList.length <= _minCount) {
  397. ToastUtil.show("最少需要保持$_minCount个人设");
  398. return;
  399. }
  400. AtmobLog.i(tag, 'clickRemoveCharacter');
  401. _currentCustomKeyboardCharacterList.remove(characterInfo);
  402. } else {
  403. if (_currentGeneralKeyboardCharacterList.length <= _minCount) {
  404. ToastUtil.show("最少需要保持$_minCount个人设");
  405. return;
  406. }
  407. AtmobLog.i(tag, 'clickRemoveCharacter');
  408. _currentGeneralKeyboardCharacterList.remove(characterInfo);
  409. }
  410. }
  411. clickAddCharacter({required bool isCustom}) {
  412. if (!isLogin) {
  413. ToastUtil.show("请先登录");
  414. return;
  415. }
  416. if (isCustom) {
  417. CharacterAddDialog.show(
  418. currentKeyboardInfo: currentCustomKeyboardInfo,
  419. clickCallback: () {
  420. getKeyboardCharacterList(
  421. keyboardId: _currentCustomKeyboardInfo.value.id ?? "",
  422. isCustom: true,
  423. );
  424. },
  425. );
  426. } else {
  427. CharacterAddDialog.show(
  428. currentKeyboardInfo: currentGeneralKeyboardInfo,
  429. clickCallback: () {
  430. getGeneralKeyboard();
  431. },
  432. );
  433. }
  434. }
  435. clickCustomCharacter() {
  436. if (!isLogin) {
  437. ToastUtil.show("请先登录");
  438. return;
  439. }
  440. AtmobLog.i(tag, 'clickCustomCharacter');
  441. CustomCharacterAddDialog.show(
  442. currentKeyboardInfo: currentCustomKeyboardInfo,
  443. clickCallback: () {
  444. getKeyboardCharacterList(
  445. keyboardId: _currentCustomKeyboardInfo.value.id ?? "",
  446. isCustom: true,
  447. );
  448. },
  449. );
  450. }
  451. @override
  452. void onClose() {
  453. tabController.dispose();
  454. pageController.dispose();
  455. super.onClose();
  456. }
  457. void saveSuccessGetBack(){
  458. Get.back(result: _currentCustomKeyboardCharacterList);
  459. }
  460. }