Show query count and pages, some fixes
scrollbar fixed
MODIFY
packages/isar/lib/src/isar_connect.dart
packages/isar/lib/src/isar_connect.dart
@@ -137,25 +137,28 @@ abstract class _IsarConnect {
);
}
- static Future<List<Map<String, dynamic>>> _executeQuery(
+ static Future<Map<String, dynamic>> _executeQuery(
Map<String, dynamic> params,
) async {
if (_querySubscription != null) {
unawaited(_querySubscription!.cancel());
}
_querySubscription = null;
- if (params.isEmpty) {
- return <Map<String, dynamic>>[];
- }
final query = _getQuery(params);
+ params.remove('limit');
+ params.remove('offset');
+ final countQuery = _getQuery(params);
final stream = query.watchLazy();
_querySubscription = stream.listen((event) {
postEvent(ConnectEvent.queryChanged.event, {});
});
- return query.exportJson();
+ return {
+ 'results': await query.exportJson(),
+ 'count': await countQuery.count(),
+ };
}
static Future<bool> _removeQuery(Map<String, dynamic> params) async {

MODIFY
packages/isar_inspector/lib/collections.dart
packages/isar_inspector/lib/collections.dart
@@ -6,6 +6,7 @@ import 'package:isar_inspector/desktop/download.dart'
import 'package:isar_inspector/state/collections_state.dart';
import 'package:isar_inspector/state/instances_state.dart';
import 'package:isar_inspector/state/isar_connect_state_notifier.dart';
+import 'package:isar_inspector/state/query_state.dart';
class CollectionsList extends ConsumerWidget {
const CollectionsList({super.key});
@@ -30,7 +31,12 @@ class CollectionsList extends ConsumerWidget {
color: collection == selectedCollection ? theme.primaryColor : null,
radius: BorderRadius.circular(60),
onTap: () {
- ref.read(selectedCollectionNamePod.state).state = collection.name;
+ if (ref.read(selectedCollectionNamePod.state).state !=
+ collection.name) {
+ ref.read(selectedCollectionNamePod.state).state =
+ collection.name;
+ ref.read(queryPagePod.state).state = 1;
+ }
},
child: Padding(
padding: const EdgeInsets.only(left: 25, right: 10),

MODIFY
packages/isar_inspector/lib/connected_layout.dart
packages/isar_inspector/lib/connected_layout.dart
@@ -37,9 +37,9 @@ class _ConnectedLayoutState extends ConsumerState<ConnectedLayout> {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- const FilterField(),
- const SizedBox(height: 25),
+ children: const [
+ FilterField(),
+ SizedBox(height: 25),
Expanded(
child: QueryTable(),
),

MODIFY
packages/isar_inspector/lib/desktop/app.dart
packages/isar_inspector/lib/desktop/app.dart
@@ -44,6 +44,9 @@ class _AppState extends State<App> {
secondary: Colors.blue,
brightness: Brightness.dark,
),
+ scrollbarTheme: ScrollbarThemeData(
+ thumbColor: MaterialStateProperty.all(Colors.grey),
+ ),
),
home: ColoredPage(
child: _port != null

MODIFY
packages/isar_inspector/lib/edit_popup.dart
packages/isar_inspector/lib/edit_popup.dart
@@ -85,7 +85,7 @@ class _EditPopupState extends State<EditPopup> {
),
const SizedBox(height: 15),
],
- if (widget.type == IsarType.Bool) ...[
+ if (widget.type == IsarType.Bool)
DropdownButtonHideUnderline(
child: DropdownButton<bool>(
value: _boolValue,
@@ -109,10 +109,8 @@ class _EditPopupState extends State<EditPopup> {
}
},
),
- ),
- const SizedBox(height: 15),
- ],
- if (widget.type != IsarType.Bool) ...[
+ )
+ else
Form(
key: _formKey,
child: TextFormField(
@@ -146,7 +144,6 @@ class _EditPopupState extends State<EditPopup> {
),
),
const SizedBox(height: 15),
- ],
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [

MODIFY
packages/isar_inspector/lib/filter_field.dart
packages/isar_inspector/lib/filter_field.dart
@@ -56,7 +56,7 @@ class _FilterFieldState extends ConsumerState<FilterField> {
final selectedCollection = ref.read(selectedCollectionPod).value!;
final filter = _parseFilter(selectedCollection);
ref.read(queryFilterPod.state).state = filter;
- ref.read(queryPagePod.state).state = 0;
+ ref.read(queryPagePod.state).state = 1;
},
child: const Text('Query'),
),

MODIFY
packages/isar_inspector/lib/prev_next.dart
packages/isar_inspector/lib/prev_next.dart
@@ -11,35 +11,72 @@ class PrevNext extends ConsumerWidget {
final theme = Theme.of(context);
final page = ref.watch(queryPagePod);
final result = ref.watch(queryResultsPod).valueOrNull;
- return Column(
+
+ int from, to, total, pages = 1;
+ if (result != null && result.count > 0) {
+ from = (page - 1) * objectsPerPage + 1;
+ to = from + objectsPerPage - 1;
+ total = result.count;
+
+ if (to > total) {
+ to = total;
+ }
+
+ pages = (total / objectsPerPage).ceil();
+ } else {
+ from = to = total = 0;
+ }
+
+ return Stack(
children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
+ Align(
+ alignment: Alignment.bottomLeft,
+ child: Text('Displaying objects $from - $to of $total'),
+ ),
+ Align(
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
children: [
_Button(
label: 'Prev',
- onPressed: () {
- if (page > 0) {
- ref.read(queryPagePod.state).state -= 1;
- }
- },
+ onPressed: page > 1
+ ? () => ref.read(queryPagePod.state).state -= 1
+ : null,
),
const SizedBox(width: 10),
- Text(
- 'Page ${page + 1}',
- style: TextStyle(fontSize: 12, color: theme.hintColor),
+ DropdownButtonHideUnderline(
+ child: ButtonTheme(
+ alignedDropdown: true,
+ child: DropdownButton<int>(
+ icon: const Icon(Icons.arrow_drop_up),
+ value: page,
+ items: List.generate(
+ pages,
+ (page) => DropdownMenuItem(
+ value: page + 1,
+ child: Center(child: Text('Page ${page + 1}')),
+ ),
+ ),
+ onChanged: pages > 1
+ ? (p) {
+ if (p != null) {
+ ref.read(queryPagePod.state).state = p;
+ }
+ }
+ : null,
+ ),
+ ),
),
const SizedBox(width: 10),
_Button(
label: 'Next',
- onPressed: () {
- if (result?.hasMore ?? false) {
- ref.read(queryPagePod.state).state += 1;
- }
- },
+ onPressed: to == total
+ ? null
+ : () => ref.read(queryPagePod.state).state += 1,
),
],
),
+ ),
],
);
}
@@ -52,6 +89,7 @@ class _Button extends StatelessWidget {
required this.label,
this.onPressed,
});
+
final String label;
final VoidCallback? onPressed;

MODIFY
packages/isar_inspector/lib/query_table.dart
packages/isar_inspector/lib/query_table.dart
@@ -26,9 +26,7 @@ typedef Editor = void Function(
);
class QueryTable extends ConsumerWidget {
- QueryTable({super.key});
-
- final _controller = ScrollController();
+ const QueryTable({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -44,11 +42,8 @@ class QueryTable extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
- child: RawScrollbar(
- controller: _controller,
- thumbColor: Colors.grey,
child: ListView.separated(
- controller: _controller,
+ controller: ScrollController(),
itemCount: objects.length,
itemBuilder: (context, index) {
return Stack(
@@ -112,7 +107,6 @@ class QueryTable extends ConsumerWidget {
},
),
),
- ),
const SizedBox(height: 20),
const PrevNext(),
],

MODIFY
packages/isar_inspector/lib/state/isar_connect_state_notifier.dart
packages/isar_inspector/lib/state/isar_connect_state_notifier.dart
@@ -147,13 +147,12 @@ class IsarConnectStateNotifier
);
}
- Future<List<Map<String, Object?>>> executeQuery(ConnectQuery query) async {
- final objects = await _call<List<dynamic>>(
+ Future<Map<String, Object?>> executeQuery(ConnectQuery query) async {
+ return _call<Map<String, Object?>>(
ConnectAction.executeQuery,
args: query.toJson(),
timeout: kLongTimeout,
);
- return objects.cast();
}
Future<void> removeQuery(ConnectQuery query) async {

MODIFY
packages/isar_inspector/lib/state/query_state.dart
packages/isar_inspector/lib/state/query_state.dart
-import 'dart:async';
-
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:isar/isar.dart';
@@ -11,21 +9,26 @@ const int objectsPerPage = 50;
class QueryObject {
const QueryObject(this.data);
+
final Map<String, dynamic> data;
dynamic getValue(String propertyName) => data[propertyName];
}
-final queryPagePod = StateProvider((ref) => 0);
+final queryPagePod = StateProvider((ref) => 1);
final queryFilterPod = StateProvider<FilterOperation?>((ref) => null);
final querySortPod = StateProvider<SortProperty?>((ref) => null);
class QueryResult {
- QueryResult({required this.objects, required this.hasMore});
+ QueryResult({
+ required this.objects,
+ required this.count,
+ });
+
final List<QueryObject> objects;
- final bool hasMore;
+ final int count;
}
final queryResultsPod = FutureProvider<QueryResult>((ref) async {
@@ -42,23 +45,20 @@ final queryResultsPod = FutureProvider<QueryResult>((ref) async {
collection: selectedCollection.name,
filter: filter,
sortProperty: sort,
- offset: page * objectsPerPage,
- limit: objectsPerPage + 1,
+ offset: (page - 1) * objectsPerPage,
+ limit: objectsPerPage,
),
);
- final objects = result.map(QueryObject.new).toList();
-
- if (objects.isEmpty && page != 0) {
- Timer.run(() {
- ref.read(queryPagePod.state).state = 0;
- });
- }
+ //ignore: avoid_dynamic_calls
+ final objects = (result['results']! as List<dynamic>)
+ .map((e) => e as Map<String, dynamic>)
+ .toList()
+ .map(QueryObject.new)
+ .toList();
return QueryResult(
- objects: objects.length > objectsPerPage
- ? objects.sublist(0, objectsPerPage - 1)
- : objects,
- hasMore: objects.length > objectsPerPage,
+ objects: objects,
+ count: result['count']! as int,
);
});

MODIFY
packages/isar_inspector/lib/web/app.dart
packages/isar_inspector/lib/web/app.dart
@@ -72,6 +72,9 @@ class App extends StatelessWidget {
secondary: Colors.blue,
brightness: Brightness.dark,
),
+ scrollbarTheme: ScrollbarThemeData(
+ thumbColor: MaterialStateProperty.all(Colors.grey),
+ ),
),
),
);

Show query count and pages, some fixes

scrollbar fixed