mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt search topic
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -404,81 +404,6 @@ class DraggableScrollableSheet extends StatefulWidget {
|
||||
_DraggableScrollableSheetState();
|
||||
}
|
||||
|
||||
/// A [Notification] related to the extent, which is the size, and scroll
|
||||
/// offset, which is the position of the child list, of the
|
||||
/// [DraggableScrollableSheet].
|
||||
///
|
||||
/// [DraggableScrollableSheet] widgets notify their ancestors when the size of
|
||||
/// the sheet changes. When the extent of the sheet changes via a drag,
|
||||
/// this notification bubbles up through the tree, which means a given
|
||||
/// [NotificationListener] will receive notifications for all descendant
|
||||
/// [DraggableScrollableSheet] widgets. To focus on notifications from the
|
||||
/// nearest [DraggableScrollableSheet] descendant, check that the [depth]
|
||||
/// property of the notification is zero.
|
||||
///
|
||||
/// When an extent notification is received by a [NotificationListener], the
|
||||
/// listener will already have completed build and layout, and it is therefore
|
||||
/// too late for that widget to call [State.setState]. Any attempt to adjust the
|
||||
/// build or layout based on an extent notification would result in a layout
|
||||
/// that lagged one frame behind, which is a poor user experience. Extent
|
||||
/// notifications are used primarily to drive animations. The [Scaffold] widget
|
||||
/// listens for extent notifications and responds by driving animations for the
|
||||
/// [FloatingActionButton] as the bottom sheet scrolls up.
|
||||
class DraggableScrollableNotification extends Notification
|
||||
with ViewportNotificationMixin {
|
||||
/// Creates a notification that the extent of a [DraggableScrollableSheet] has
|
||||
/// changed.
|
||||
///
|
||||
/// All parameters are required. The [minExtent] must be >= 0. The [maxExtent]
|
||||
/// must be <= 1.0. The [extent] must be between [minExtent] and [maxExtent].
|
||||
DraggableScrollableNotification({
|
||||
required this.extent,
|
||||
required this.minExtent,
|
||||
required this.maxExtent,
|
||||
required this.initialExtent,
|
||||
required this.context,
|
||||
this.shouldCloseOnMinExtent = true,
|
||||
}) : assert(0.0 <= minExtent),
|
||||
assert(maxExtent <= 1.0),
|
||||
assert(minExtent <= extent),
|
||||
assert(minExtent <= initialExtent),
|
||||
assert(extent <= maxExtent),
|
||||
assert(initialExtent <= maxExtent);
|
||||
|
||||
/// The current value of the extent, between [minExtent] and [maxExtent].
|
||||
final double extent;
|
||||
|
||||
/// The minimum value of [extent], which is >= 0.
|
||||
final double minExtent;
|
||||
|
||||
/// The maximum value of [extent].
|
||||
final double maxExtent;
|
||||
|
||||
/// The initially requested value for [extent].
|
||||
final double initialExtent;
|
||||
|
||||
/// The build context of the widget that fired this notification.
|
||||
///
|
||||
/// This can be used to find the sheet's render objects to determine the size
|
||||
/// of the viewport, for instance. A listener can only assume this context
|
||||
/// is live when it first gets the notification.
|
||||
final BuildContext context;
|
||||
|
||||
/// Whether the widget that fired this notification, when dragged (or flung)
|
||||
/// to minExtent, should cause its parent sheet to close.
|
||||
///
|
||||
/// It is up to parent classes to properly read and handle this value.
|
||||
final bool shouldCloseOnMinExtent;
|
||||
|
||||
@override
|
||||
void debugFillDescription(List<String> description) {
|
||||
super.debugFillDescription(description);
|
||||
description.add(
|
||||
'minExtent: $minExtent, extent: $extent, maxExtent: $maxExtent, initialExtent: $initialExtent',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Manages state between [_DraggableScrollableSheetState],
|
||||
/// [_DraggableScrollableSheetScrollController], and
|
||||
/// [_DraggableScrollableSheetScrollPosition].
|
||||
|
||||
@@ -614,7 +614,7 @@ class _CreateDynPanelState extends CommonPublishPageState<CreateDynPanel> {
|
||||
maxChildSize: 1,
|
||||
initialChildSize: _offset == 0 ? 0.65 : 1,
|
||||
initialScrollOffset: _offset,
|
||||
snapSizes: [0.65],
|
||||
snapSizes: const [0.65],
|
||||
builder: (context, scrollController) => SelectTopicPanel(
|
||||
scrollController: scrollController,
|
||||
callback: (offset) => _offset = offset,
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:get/get.dart';
|
||||
|
||||
class SelectTopicController
|
||||
extends CommonListController<TopicPubSearchData, TopicPubSearchItem> {
|
||||
final focusNode = FocusNode();
|
||||
final controller = TextEditingController();
|
||||
|
||||
final RxBool enableClear = false.obs;
|
||||
@@ -32,6 +33,7 @@ class SelectTopicController
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
focusNode.dispose();
|
||||
controller.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:PiliPlus/common/widgets/custom_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
@@ -5,9 +7,9 @@ import 'package:PiliPlus/models/topic_pub_search/topic_item.dart';
|
||||
import 'package:PiliPlus/pages/dynamics_select_topic/controller.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:stream_transform/stream_transform.dart';
|
||||
|
||||
class SelectTopicPanel extends StatefulWidget {
|
||||
const SelectTopicPanel({
|
||||
@@ -25,8 +27,9 @@ class SelectTopicPanel extends StatefulWidget {
|
||||
|
||||
class _SelectTopicPanelState extends State<SelectTopicPanel> {
|
||||
final _controller = Get.put(SelectTopicController());
|
||||
|
||||
double offset = 0;
|
||||
late double offset;
|
||||
final StreamController<String> _ctr = StreamController<String>();
|
||||
late StreamSubscription<String> _sub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -35,11 +38,21 @@ class _SelectTopicPanelState extends State<SelectTopicPanel> {
|
||||
_controller.onReload();
|
||||
}
|
||||
offset = widget.scrollController?.initialScrollOffset ?? 0;
|
||||
_sub = _ctr.stream
|
||||
.debounce(const Duration(milliseconds: 300), trailing: true)
|
||||
.listen((value) {
|
||||
_controller
|
||||
..enableClear.value = value.isNotEmpty
|
||||
..onRefresh().whenComplete(() => WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) => widget.scrollController?.jumpToTop()));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.callback?.call(offset);
|
||||
_sub.cancel();
|
||||
_ctr.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -69,17 +82,9 @@ class _SelectTopicPanelState extends State<SelectTopicPanel> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 5),
|
||||
child: TextField(
|
||||
focusNode: _controller.focusNode,
|
||||
controller: _controller.controller,
|
||||
onChanged: (value) {
|
||||
EasyThrottle.throttle(
|
||||
'topicPubSearch',
|
||||
const Duration(milliseconds: 300),
|
||||
() => _controller
|
||||
..enableClear.value = value.isNotEmpty
|
||||
..onRefresh()
|
||||
.whenComplete(() => widget.scrollController?.jumpToTop()),
|
||||
);
|
||||
},
|
||||
onChanged: _ctr.add,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(
|
||||
gapPadding: 0,
|
||||
@@ -119,8 +124,10 @@ class _SelectTopicPanelState extends State<SelectTopicPanel> {
|
||||
onTap: () => _controller
|
||||
..enableClear.value = false
|
||||
..controller.clear()
|
||||
..onRefresh().whenComplete(
|
||||
() => widget.scrollController?.jumpToTop()),
|
||||
..onRefresh().whenComplete(() => WidgetsBinding
|
||||
.instance
|
||||
.addPostFrameCallback((_) =>
|
||||
widget.scrollController?.jumpToTop())),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
@@ -148,6 +155,9 @@ class _SelectTopicPanelState extends State<SelectTopicPanel> {
|
||||
response?.isNotEmpty == true
|
||||
? NotificationListener<ScrollNotification>(
|
||||
onNotification: (notification) {
|
||||
if (_controller.focusNode.hasFocus) {
|
||||
_controller.focusNode.unfocus();
|
||||
}
|
||||
offset = notification.metrics.pixels;
|
||||
return false;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user