showPlexAutoCompleteSelectionList<T> function

dynamic showPlexAutoCompleteSelectionList<T>(
  1. BuildContext context, {
  2. FocusNode? focusNode,
  3. required Future<List<T>> asyncItems(
    1. String query
    ),
  4. required String itemText(
    1. T item
    ),
  5. required dynamic onSelect(
    1. T item
    ),
  6. int minQueryLength = 2,
  7. Widget itemWidget(
    1. dynamic item
    )?,
  8. Widget leadingIcon(
    1. T item
    )?,
  9. bool showBarCode = false,
  10. double inputDelay = 1000,
})

Implementation

showPlexAutoCompleteSelectionList<T>(
  BuildContext context, {
  FocusNode? focusNode,
  required Future<List<T>> Function(String query) asyncItems,
  required String Function(T item) itemText,
  required Function(T item) onSelect,
  int minQueryLength = 2,
  Widget Function(dynamic item)? itemWidget,
  Widget Function(T item)? leadingIcon,
  bool showBarCode = false,
  double inputDelay = 1000,
}) async {
  DateTime lastInputAt = DateTime.now();
  String? query;
  String? searchedQuery;

  var inputController = TextEditingController();
  var filteredListController = PlexWidgetController<List<T>>(data: List.empty());
  var loadingController = PlexWidgetController<int>(data: 0);

  if (focusNode == null) {
    focusNode = FocusNode();
    focusNode.requestFocus();
  }

  onSearch(String data) async {
    lastInputAt = DateTime.now();
    query = data;
    if (data.length < minQueryLength) return;

    delay(() async {
      if (DateTime.now().difference(lastInputAt).inMilliseconds < inputDelay) return;
      if (query == null || query!.length < minQueryLength) return;
      if (searchedQuery == query) return;

      loadingController.increment();
      searchedQuery = query;
      var filteredList = await asyncItems.call(searchedQuery!);
      loadingController.decrement();
      filteredListController.setValue(filteredList);
    }, delayMillis: inputDelay.toInt());
  }

  // ignore: use_build_context_synchronously
  showModalBottomSheet(
    enableDrag: true,
    showDragHandle: true,
    useSafeArea: true,
    isScrollControlled: true,
    context: context,
    builder: (context) {
      return Padding(
        padding: MediaQuery.of(context).viewInsets,
        child: Container(
          constraints: const BoxConstraints(maxHeight: 500),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Row(
                children: [
                  Expanded(
                    child: PlexWidget(
                      controller: loadingController,
                      createWidget: (context, data) {
                        return PlexFormFieldInput(
                          properties: PlexFormFieldGeneric(title: "Search", enabled: data <= 0),
                          inputController: inputController,
                          inputHint: "Search Here...",
                          inputFocusNode: focusNode,
                          inputOnChange: (value) async {
                            onSearch(value);
                          },
                        );
                      },
                    ),
                  ),
                  if (showBarCode) ...{
                    PlexFormFieldButton(
                      buttonIcon: Icon(Icons.barcode_reader),
                      buttonClick: () async {
                        var result = await Plex.to(PlexScanner());
                        if (result != null) {
                          inputController.text = result.toString();
                          onSearch(inputController.text);
                        }
                      },
                    )
                  }
                ],
              ),
              spaceSmall(),
              PlexWidget(
                  controller: loadingController,
                  createWidget: (context, data) {
                    if (data > 0) {
                      return SizedBox(
                        width: 50,
                        height: 50,
                        child: const PlexLoaderV2(),
                      );
                    }
                    return Container();
                  }),
              spaceSmall(),
              Expanded(
                child: PlexWidget(
                  controller: filteredListController,
                  createWidget: (con, data) {
                    var listData = data as List<T>;
                    return ListView.builder(
                      physics: const BouncingScrollPhysics(),
                      itemCount: listData.length,
                      itemBuilder: (context, index) {
                        var item = listData[index];
                        if (itemWidget != null) {
                          return InkWell(
                            onTap: () {
                              onSelect.call(item);
                              Get.back();
                            },
                            child: itemWidget.call(item),
                          );
                        }
                        return ListTile(
                          selectedTileColor: Colors.green.withValues(alpha: 0.25),
                          leading: leadingIcon?.call(item),
                          title: Text(itemText.call(item)),
                          onTap: () {
                            onSelect.call(item);
                            Get.back();
                          },
                        );
                      },
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      );
    },
  );
}