import 'dart:async'; import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/search/suggest.dart'; import 'package:PiliPlus/models_new/search/search_rcmd/data.dart'; import 'package:PiliPlus/models_new/search/search_trending/data.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:stream_transform/stream_transform.dart'; class SSearchController extends GetxController { SSearchController(this.tag); final String tag; final searchFocusNode = FocusNode(); final controller = TextEditingController(); String hintText = '搜索'; int initIndex = 0; // uid RxBool showUidBtn = false.obs; late final digitOnlyRegExp = RegExp(r'^\d+$'); // history late final RxBool recordSearchHistory; late final RxList historyList; // suggestion late final bool searchSuggestion; StreamController? _ctr; StreamSubscription? _sub; late final RxList searchSuggestList; // trending late final bool enableHotKey; late final Rx> loadingState; // rcmd late final bool enableSearchRcmd; late final Rx> recommendData; @override void onInit() { super.onInit(); // 其他页面跳转过来 if (Get.parameters['keyword'] != null) { onClickKeyword(Get.parameters['keyword']!); } if (Get.parameters['hintText'] != null) { hintText = Get.parameters['hintText']!; } if (Get.parameters['text'] != null) { controller.text = Get.parameters['text']!; } searchSuggestion = GStorage.searchSuggestion; enableHotKey = GStorage.setting.get(SettingBoxKey.enableHotKey, defaultValue: true); enableSearchRcmd = GStorage.setting .get(SettingBoxKey.enableSearchRcmd, defaultValue: true); recordSearchHistory = GStorage.recordSearchHistory.obs; if (recordSearchHistory.value) { historyList = List.from(GStorage.historyWord.get('cacheList') ?? []).obs; } if (searchSuggestion) { _ctr = StreamController(); _sub = _ctr!.stream .debounce(const Duration(milliseconds: 200), trailing: true) .listen(querySearchSuggest); searchSuggestList = [].obs; } if (enableHotKey) { loadingState = LoadingState.loading().obs; queryHotSearchList(); } if (enableSearchRcmd) { recommendData = LoadingState.loading().obs; queryRecommendList(); } } void validateUid() { showUidBtn.value = digitOnlyRegExp.hasMatch(controller.text); } void onChange(String value) { validateUid(); if (searchSuggestion) { if (value.isEmpty) { searchSuggestList.clear(); } else { _ctr!.add(value); } } } void onClear() { if (controller.value.text != '') { controller.clear(); searchSuggestList.clear(); searchFocusNode.requestFocus(); showUidBtn.value = false; } else { Get.back(); } } // 搜索 Future submit() async { if (controller.text.isEmpty) { if (hintText.isEmpty) { return; } controller.text = hintText; validateUid(); } if (recordSearchHistory.value) { historyList ..remove(controller.text) ..insert(0, controller.text); GStorage.historyWord.put('cacheList', historyList); } searchFocusNode.unfocus(); await Get.toNamed( '/searchResult', parameters: { 'tag': tag, 'keyword': controller.text, }, arguments: { 'initIndex': initIndex, 'fromSearch': true, }, ); searchFocusNode.requestFocus(); } // 获取热搜关键词 Future queryHotSearchList() async { loadingState.value = await SearchHttp.searchTrending(limit: 10); } Future queryRecommendList() async { recommendData.value = await SearchHttp.searchRecommend(); } void onClickKeyword(String keyword) { controller.text = keyword; validateUid(); searchSuggestList.clear(); submit(); } Future querySearchSuggest(String value) async { var res = await SearchHttp.searchSuggest(term: value); if (res['status']) { SearchSuggestModel data = res['data']; if (data.tag?.isNotEmpty == true) { searchSuggestList.value = data.tag!; } } } void onLongSelect(String word) { historyList.remove(word); GStorage.historyWord.put('cacheList', historyList); } void onClearHistory() { showConfirmDialog( context: Get.context!, title: '确定清空搜索历史?', onConfirm: () { historyList.clear(); GStorage.historyWord.put('cacheList', []); }, ); } @override void onClose() { searchFocusNode.dispose(); controller.dispose(); _sub?.cancel(); _ctr?.close(); super.onClose(); } }