Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/lib/chat_view_list_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class _ChatViewListScreenState extends State<ChatViewListScreen> {
),
searchConfig: SearchConfig(
textEditingController: _searchController,
debounceDuration: const Duration(milliseconds: 300),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
Expand Down
8 changes: 5 additions & 3 deletions lib/src/controller/chat_list_view_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ class ChatViewListController {
if (initialChatList[i] case final chat) chat.id: chat,
};

chatListMap = chatsMap;
chatListMap
..clear()
..addAll(chatsMap);

// Adds the current chat map to the stream controller
// after the first frame render.
Expand All @@ -67,10 +69,10 @@ class ChatViewListController {
/// Stores and manages chat items by their unique IDs.
/// A map is used for efficient lookup, update, and removal of chats
/// by their unique id.
Map<String, ChatViewListItem> chatListMap = {};
final Map<String, ChatViewListItem> chatListMap = {};

/// Provides scroll controller for chat list.
ScrollController scrollController;
final ScrollController scrollController;

final bool disposeOtherResources;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class SearchConfig {
this.border,
this.suffixIcon,
this.onSearch,
this.debounceDuration,
this.decoration,
this.maxLength,
});
Expand Down Expand Up @@ -122,6 +123,9 @@ class SearchConfig {
/// Callback function that is called when the search text changes.
final SearchUserCallback? onSearch;

/// Duration to debounce the search callback.
final Duration? debounceDuration;

/// Decoration for the search text field.
final InputDecoration? decoration;

Expand Down
13 changes: 6 additions & 7 deletions lib/src/utils/debounce.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,17 @@ import 'dart:async';
import 'package:flutter/material.dart';

class Debouncer {
Timer? _debounce;
Duration duration;

Debouncer(this.duration);

void run(VoidCallback callbackAfterTimeLapsed,
VoidCallback callbackBeforeTimeLapsed) {
final Duration duration;
Timer? _debounce;

void run({required VoidCallback onComplete, VoidCallback? onInterrupt}) {
if (_debounce?.isActive ?? false) {
callbackBeforeTimeLapsed();
onInterrupt?.call();
_debounce?.cancel();
}
_debounce = Timer(duration, callbackAfterTimeLapsed);
_debounce = Timer(duration, onComplete);
}

void dispose() {
Expand Down
13 changes: 13 additions & 0 deletions lib/src/widgets/chat_view_list/search_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:flutter/material.dart';

import '../../controller/chat_list_view_controller.dart';
import '../../models/config_models/chat_view_list/search_config.dart';
import '../../utils/debounce.dart';
import '../../utils/package_strings.dart';

class SearchTextField extends StatefulWidget {
Expand All @@ -50,6 +51,10 @@ class SearchTextField extends StatefulWidget {
class _SearchTextFieldState extends State<SearchTextField> {
final ValueNotifier<String> _inputText = ValueNotifier('');

late final _debouncer = _config.debounceDuration == null
? null
: Debouncer(_config.debounceDuration!);

SearchConfig get _config => widget.config;

InputBorder get _outlineBorder =>
Expand Down Expand Up @@ -121,6 +126,14 @@ class _SearchTextFieldState extends State<SearchTextField> {

FutureOr<void> _onSearchChanged(String value) async {
_inputText.value = value;
if (_debouncer != null) {
_debouncer.run(onComplete: () => _performSearch(value));
} else {
await _performSearch(value);
}
}

FutureOr<void> _performSearch(String value) async {
final chatList = await _config.onSearch?.call(value);
if (chatList != null) {
widget.chatViewListController?.setSearchChats(chatList);
Expand Down
4 changes: 2 additions & 2 deletions lib/src/widgets/chatui_textfield.dart
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,9 @@ class _ChatUITextFieldState extends State<ChatUITextField> {
}

void _onChanged(String inputText) {
debouncer.run(() {
debouncer.run(onComplete: () {
composingStatus.value = TypeWriterStatus.typed;
}, () {
}, onInterrupt: () {
composingStatus.value = TypeWriterStatus.typing;
});
_inputText.value = inputText;
Expand Down