Add infinite scroll for word search results
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
(TODO: add description)
|
||||
|
||||
## New features ✨
|
||||
|
||||
- Added infinite scroll for word search results.
|
||||
|
||||
## Changes 🔧
|
||||
|
||||
- Display proper language names for "From language" references.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:jadb/models/word_search/word_search_result.dart';
|
||||
import 'package:jadb/search.dart' show JaDBConnection;
|
||||
import 'package:mdi/mdi.dart';
|
||||
@@ -10,6 +11,9 @@ import 'package:sqflite/sqflite.dart';
|
||||
|
||||
import '../../components/search/search_results_body/search_card.dart';
|
||||
|
||||
const int pageSize = 50;
|
||||
const int invisibleItemsThreshold = 25;
|
||||
|
||||
class WordSearchResultPage extends StatefulWidget {
|
||||
final String searchTerm;
|
||||
|
||||
@@ -23,10 +27,37 @@ class WordSearchResultPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _WordSearchResultPageState extends State<WordSearchResultPage> {
|
||||
final List<WordSearchResult> results = [];
|
||||
|
||||
bool addedToDatabase = false;
|
||||
|
||||
late final _pagingController = PagingController<int, WordSearchResult>(
|
||||
getNextPageKey: (state) =>
|
||||
state.lastPageIsEmpty ? null : state.nextIntPageKey,
|
||||
fetchPage: (pageKey) => GetIt.instance
|
||||
.get<Database>()
|
||||
.jadbSearchWord(
|
||||
widget.searchTerm,
|
||||
page: pageKey,
|
||||
pageSize: pageSize,
|
||||
)
|
||||
.then((v) => v ?? <WordSearchResult>[]),
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (!incognitoModeEnabled && !addedToDatabase) {
|
||||
HistoryEntry.insertWord(word: widget.searchTerm);
|
||||
addedToDatabase = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pagingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -42,44 +73,44 @@ class _WordSearchResultPageState extends State<WordSearchResultPage> {
|
||||
],
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: (() async {
|
||||
final jadbConnection = GetIt.instance.get<Database>();
|
||||
|
||||
final results = await Future.wait([
|
||||
jadbConnection
|
||||
.jadbSearchWordCount(widget.searchTerm)
|
||||
.then((v) => v ?? 0),
|
||||
jadbConnection
|
||||
.jadbSearchWord(widget.searchTerm)
|
||||
.then((v) => v ?? <WordSearchResult>[]),
|
||||
]);
|
||||
|
||||
return (results[0] as int, results[1] as List<WordSearchResult>);
|
||||
})(),
|
||||
future: GetIt.instance
|
||||
.get<Database>()
|
||||
.jadbSearchWordCount(widget.searchTerm)
|
||||
.then((v) => v ?? 0),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasError) return ErrorWidget(snapshot.error!);
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (!incognitoModeEnabled && !addedToDatabase) {
|
||||
HistoryEntry.insertWord(word: widget.searchTerm);
|
||||
addedToDatabase = true;
|
||||
}
|
||||
final searchCount = snapshot.data!;
|
||||
|
||||
return ListView(
|
||||
return Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
'Found ${snapshot.data!.$1} results for "${widget.searchTerm}"',
|
||||
'Found $searchCount results for "${widget.searchTerm}"',
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
for (final result in snapshot.data!.$2)
|
||||
SearchResultCard(result: result)
|
||||
Expanded(
|
||||
child: PagingListener(
|
||||
controller: _pagingController,
|
||||
builder: (context, state, fetchNextPage) =>
|
||||
PagedListView<int, WordSearchResult>(
|
||||
state: state,
|
||||
fetchNextPage: fetchNextPage,
|
||||
builderDelegate: PagedChildBuilderDelegate(
|
||||
invisibleItemsThreshold: invisibleItemsThreshold,
|
||||
itemBuilder: (context, item, index) =>
|
||||
SearchResultCard(result: item),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
24
pubspec.lock
24
pubspec.lock
@@ -230,6 +230,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
flutter_staggered_grid_view:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_staggered_grid_view
|
||||
sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.0"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -296,6 +304,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.4"
|
||||
infinite_scroll_pagination:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: infinite_scroll_pagination
|
||||
sha256: "9b8f95362928a1de835658835194b435c40f2bfc386f6545c1fd706203df0cd4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
jadb:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -622,6 +638,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
sliver_tools:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sliver_tools
|
||||
sha256: eae28220badfb9d0559207badcbbc9ad5331aac829a88cb0964d330d2a4636a6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.12"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -41,6 +41,7 @@ dependencies:
|
||||
flutter_markdown_plus: ^1.0.3
|
||||
markdown: ^7.3.0
|
||||
sealed_languages: ^2.1.0
|
||||
infinite_scroll_pagination: ^5.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
Reference in New Issue
Block a user