mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-27 13:55:54 +08:00
@@ -1,12 +1,15 @@
|
||||
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/search_trending/trending_data.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:get/get_rx/src/rx_workers/utils/debouncer.dart';
|
||||
import 'package:stream_transform/stream_transform.dart';
|
||||
|
||||
class SSearchController extends GetxController {
|
||||
SSearchController(this.tag);
|
||||
@@ -15,31 +18,32 @@ class SSearchController extends GetxController {
|
||||
final searchFocusNode = FocusNode();
|
||||
final controller = TextEditingController();
|
||||
|
||||
RxList<String> historyList = <String>[].obs;
|
||||
|
||||
RxList<SearchSuggestItem> searchSuggestList = <SearchSuggestItem>[].obs;
|
||||
|
||||
String hintText = '搜索';
|
||||
|
||||
late bool enableHotKey;
|
||||
late bool enableSearchRcmd;
|
||||
|
||||
Rx<LoadingState<TrendingData>> loadingState =
|
||||
LoadingState<TrendingData>.loading().obs;
|
||||
|
||||
Rx<LoadingState<SearchKeywordData>> recommendData =
|
||||
LoadingState<SearchKeywordData>.loading().obs;
|
||||
|
||||
int initIndex = 0;
|
||||
|
||||
// uid
|
||||
RxBool showUidBtn = false.obs;
|
||||
|
||||
final _debouncer = Debouncer(delay: const Duration(milliseconds: 200));
|
||||
late final searchSuggestion = GStorage.searchSuggestion;
|
||||
late final RxBool recordSearchHistory = GStorage.recordSearchHistory.obs;
|
||||
|
||||
late final digitOnlyRegExp = RegExp(r'^\d+$');
|
||||
|
||||
// history
|
||||
late final RxBool recordSearchHistory;
|
||||
late final RxList<String> historyList;
|
||||
|
||||
// suggestion
|
||||
late final bool searchSuggestion;
|
||||
StreamController<String>? _ctr;
|
||||
StreamSubscription<String>? _sub;
|
||||
late final RxList<SearchSuggestItem> searchSuggestList;
|
||||
|
||||
// trending
|
||||
late final bool enableHotKey;
|
||||
late final Rx<LoadingState<SearchTrendingData>> loadingState;
|
||||
|
||||
// rcmd
|
||||
late final bool enableSearchRcmd;
|
||||
late final Rx<LoadingState<SearchRcmdData>> recommendData;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
@@ -54,19 +58,33 @@ class SSearchController extends GetxController {
|
||||
controller.text = Get.parameters['text']!;
|
||||
}
|
||||
|
||||
historyList.value = List.from(GStorage.historyWord.get('cacheList') ?? []);
|
||||
|
||||
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<String>.from(GStorage.historyWord.get('cacheList') ?? []).obs;
|
||||
}
|
||||
|
||||
if (searchSuggestion) {
|
||||
_ctr = StreamController<String>();
|
||||
_sub = _ctr!.stream
|
||||
.debounce(const Duration(milliseconds: 200), trailing: true)
|
||||
.listen(querySearchSuggest);
|
||||
searchSuggestList = <SearchSuggestItem>[].obs;
|
||||
}
|
||||
|
||||
if (enableHotKey) {
|
||||
loadingState = LoadingState<SearchTrendingData>.loading().obs;
|
||||
queryHotSearchList();
|
||||
}
|
||||
|
||||
if (enableSearchRcmd) {
|
||||
recommendData = LoadingState<SearchRcmdData>.loading().obs;
|
||||
queryRecommendList();
|
||||
}
|
||||
}
|
||||
@@ -77,10 +95,12 @@ class SSearchController extends GetxController {
|
||||
|
||||
void onChange(String value) {
|
||||
validateUid();
|
||||
if (value.isEmpty) {
|
||||
searchSuggestList.clear();
|
||||
} else if (searchSuggestion) {
|
||||
_debouncer.call(() => querySearchSuggest(value));
|
||||
if (searchSuggestion) {
|
||||
if (value.isEmpty) {
|
||||
searchSuggestList.clear();
|
||||
} else {
|
||||
_ctr!.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,15 +166,16 @@ class SSearchController extends GetxController {
|
||||
}
|
||||
|
||||
Future<void> querySearchSuggest(String value) async {
|
||||
var result = await SearchHttp.searchSuggest(term: value);
|
||||
if (result['status']) {
|
||||
if (result['data'] is SearchSuggestModel) {
|
||||
searchSuggestList.value = result['data'].tag;
|
||||
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(word) {
|
||||
void onLongSelect(String word) {
|
||||
historyList.remove(word);
|
||||
GStorage.historyWord.put('cacheList', historyList);
|
||||
}
|
||||
@@ -174,7 +195,8 @@ class SSearchController extends GetxController {
|
||||
void onClose() {
|
||||
searchFocusNode.dispose();
|
||||
controller.dispose();
|
||||
_debouncer.cancel();
|
||||
_sub?.cancel();
|
||||
_ctr?.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'package:PiliPlus/common/widgets/disabled_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/search/search_trending/trending_data.dart';
|
||||
import 'package:PiliPlus/models/search/suggest.dart';
|
||||
import 'package:PiliPlus/models_new/search/search_rcmd/data.dart';
|
||||
import 'package:PiliPlus/pages/search/controller.dart';
|
||||
import 'package:PiliPlus/pages/search/widgets/hot_keyword.dart';
|
||||
import 'package:PiliPlus/pages/search/widgets/search_text.dart';
|
||||
import 'package:PiliPlus/utils/em.dart' show Em;
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -76,7 +76,6 @@ class _SearchPageState extends State<SearchPage> {
|
||||
padding: MediaQuery.paddingOf(context).copyWith(top: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
// 搜索建议
|
||||
if (_searchController.searchSuggestion) _searchSuggest(),
|
||||
if (context.orientation == Orientation.portrait) ...[
|
||||
if (_searchController.enableHotKey) hotSearch(theme),
|
||||
@@ -127,7 +126,23 @@ class _SearchPageState extends State<SearchPage> {
|
||||
top: 9,
|
||||
bottom: 9,
|
||||
),
|
||||
child: highlightText(context, item.textRich),
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: Em.regTitle(item.textRich)
|
||||
.map((e) => TextSpan(
|
||||
text: e.text,
|
||||
style: e.isEm
|
||||
? TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
)
|
||||
: null,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -264,9 +279,7 @@ class _SearchPageState extends State<SearchPage> {
|
||||
icon: _searchController.recordSearchHistory.value
|
||||
? historyIcon(theme)
|
||||
: historyIcon(theme).disable(),
|
||||
style: IconButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
style: IconButton.styleFrom(padding: EdgeInsets.zero),
|
||||
onPressed: () {
|
||||
_searchController.recordSearchHistory.value =
|
||||
!_searchController.recordSearchHistory.value;
|
||||
@@ -284,11 +297,9 @@ class _SearchPageState extends State<SearchPage> {
|
||||
child: TextButton.icon(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(
|
||||
const EdgeInsets.only(
|
||||
left: 10,
|
||||
top: 6,
|
||||
bottom: 6,
|
||||
right: 10,
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 6,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -300,9 +311,7 @@ class _SearchPageState extends State<SearchPage> {
|
||||
),
|
||||
label: Text(
|
||||
'清空',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.secondary,
|
||||
),
|
||||
style: TextStyle(color: theme.colorScheme.secondary),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -335,8 +344,7 @@ class _SearchPageState extends State<SearchPage> {
|
||||
Icon historyIcon(ThemeData theme) => Icon(Icons.history,
|
||||
color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.8));
|
||||
|
||||
Widget _buildHotKey(
|
||||
LoadingState<SearchKeywordData> loadingState, bool isHot) {
|
||||
Widget _buildHotKey(LoadingState<SearchRcmdData> loadingState, bool isHot) {
|
||||
return switch (loadingState) {
|
||||
Success(:var response) => response.list?.isNotEmpty == true
|
||||
? LayoutBuilder(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:PiliPlus/models/search/search_trending/trending_list.dart';
|
||||
import 'package:PiliPlus/models_new/search/search_trending/list.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class HotKeyword extends StatelessWidget {
|
||||
final double width;
|
||||
final List<SearchKeywordList> hotSearchList;
|
||||
final List<SearchTrendingItemModel> hotSearchList;
|
||||
final Function? onClick;
|
||||
final bool showMore;
|
||||
const HotKeyword({
|
||||
|
||||
Reference in New Issue
Block a user