Alarms, Devices and More pages
This commit is contained in:
@@ -306,6 +306,20 @@ class TbContext {
|
||||
router.pop<T>(currentState!.context, result);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool?> confirm({required String title, required String message, String cancel = 'Cancel', String ok = 'Ok'}) {
|
||||
return showDialog<bool>(context: currentState!.context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(message),
|
||||
actions: [
|
||||
TextButton(onPressed: () => pop(false),
|
||||
child: Text(cancel)),
|
||||
TextButton(onPressed: () => pop(true),
|
||||
child: Text(ok))
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
mixin HasTbContext {
|
||||
@@ -343,6 +357,8 @@ mixin HasTbContext {
|
||||
|
||||
void pop<T>([T? result]) => _tbContext.pop<T>(result);
|
||||
|
||||
Future<bool?> confirm({required String title, required String message, String cancel = 'Cancel', String ok = 'Ok'}) => _tbContext.confirm(title: title, message: message, cancel: cancel, ok: ok);
|
||||
|
||||
void hideNotification() => _tbContext.hideNotification();
|
||||
|
||||
void showErrorNotification(String message, {Duration? duration}) => _tbContext.showErrorNotification(message, duration: duration);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:thingsboard_app/core/context/tb_context.dart';
|
||||
|
||||
abstract class RefreshableWidget extends Widget {
|
||||
refresh();
|
||||
}
|
||||
|
||||
abstract class TbContextStatelessWidget extends StatelessWidget with HasTbContext {
|
||||
TbContextStatelessWidget(TbContext tbContext, {Key? key}) : super(key: key) {
|
||||
setTbContext(tbContext);
|
||||
@@ -71,3 +76,23 @@ abstract class TbPageState<W extends TbPageWidget<W,S>, S extends TbPageState<W,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TextContextWidget extends TbContextWidget<TextContextWidget, _TextContextWidgetState> {
|
||||
|
||||
final String text;
|
||||
|
||||
TextContextWidget(TbContext tbContext, this.text) : super(tbContext);
|
||||
|
||||
@override
|
||||
_TextContextWidgetState createState() => _TextContextWidgetState();
|
||||
|
||||
}
|
||||
|
||||
class _TextContextWidgetState extends TbContextState<TextContextWidget, _TextContextWidgetState> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: Center(child: Text(widget.text)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,10 +42,6 @@ mixin EntitiesBase<T, P> on HasTbContext {
|
||||
return Text('Not implemented!');
|
||||
}
|
||||
|
||||
P createFirstKey({int pageSize = 10}) => throw UnimplementedError('Not implemented');
|
||||
|
||||
P nextPageKey(P pageKey) => throw UnimplementedError('Not implemented');
|
||||
|
||||
EntityCardSettings entityListCardSettings(T entity) => EntityCardSettings();
|
||||
|
||||
EntityCardSettings entityGridCardSettings(T entity) => EntityCardSettings();
|
||||
@@ -54,37 +50,67 @@ mixin EntitiesBase<T, P> on HasTbContext {
|
||||
|
||||
}
|
||||
|
||||
mixin EntitiesBaseWithPageLink<T> on EntitiesBase<T, PageLink> {
|
||||
abstract class PageKeyController<P> extends ValueNotifier<PageKeyValue<P>> {
|
||||
|
||||
@override
|
||||
PageLink createFirstKey({int pageSize = 10}) => PageLink(pageSize, 0, null, SortOrder('createdTime', Direction.DESC));
|
||||
PageKeyController(P initialPageKey) : super(PageKeyValue(initialPageKey));
|
||||
|
||||
P nextPageKey(P pageKey);
|
||||
|
||||
}
|
||||
|
||||
class PageKeyValue<P> {
|
||||
|
||||
final P pageKey;
|
||||
|
||||
PageKeyValue(this.pageKey);
|
||||
|
||||
}
|
||||
|
||||
class PageLinkController extends PageKeyController<PageLink> {
|
||||
|
||||
PageLinkController({int pageSize = 10, String? searchText}) : super(PageLink(pageSize, 0, searchText, SortOrder('createdTime', Direction.DESC)));
|
||||
|
||||
@override
|
||||
PageLink nextPageKey(PageLink pageKey) => pageKey.nextPageLink();
|
||||
|
||||
onSearchText(String searchText) {
|
||||
value.pageKey.page = 0;
|
||||
value.pageKey.textSearch = searchText;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mixin EntitiesBaseWithTimePageLink<T> on EntitiesBase<T, TimePageLink> {
|
||||
class TimePageLinkController extends PageKeyController<TimePageLink> {
|
||||
|
||||
@override
|
||||
TimePageLink createFirstKey({int pageSize = 10}) => TimePageLink(pageSize, 0, null, SortOrder('createdTime', Direction.DESC));
|
||||
TimePageLinkController({int pageSize = 10, String? searchText}) : super(TimePageLink(pageSize, 0, searchText, SortOrder('createdTime', Direction.DESC)));
|
||||
|
||||
@override
|
||||
TimePageLink nextPageKey(TimePageLink pageKey) => pageKey.nextPageLink();
|
||||
|
||||
}
|
||||
onSearchText(String searchText) {
|
||||
value.pageKey.page = 0;
|
||||
value.pageKey.textSearch = searchText;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
abstract class BaseEntitiesPageLinkWidget<T> extends BaseEntitiesWidget<T, PageLink> with EntitiesBaseWithPageLink<T> {
|
||||
BaseEntitiesPageLinkWidget(TbContext tbContext): super(tbContext);
|
||||
}
|
||||
|
||||
abstract class BaseEntitiesTimePageLinkWidget<T> extends BaseEntitiesWidget<T, TimePageLink> with EntitiesBaseWithTimePageLink<T> {
|
||||
BaseEntitiesTimePageLinkWidget(TbContext tbContext): super(tbContext);
|
||||
}
|
||||
|
||||
abstract class BaseEntitiesWidget<T, P> extends TbContextWidget<BaseEntitiesWidget<T, P>, BaseEntitiesState<T, P>> with EntitiesBase<T, P> {
|
||||
|
||||
BaseEntitiesWidget(TbContext tbContext): super(tbContext);
|
||||
final bool searchMode;
|
||||
final PageKeyController<P> pageKeyController;
|
||||
|
||||
BaseEntitiesWidget(TbContext tbContext, this.pageKeyController, {this.searchMode = false}):
|
||||
super(tbContext);
|
||||
|
||||
@override
|
||||
Widget? buildHeading(BuildContext context) => searchMode ? Text('Search results', style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 16,
|
||||
height: 24 / 16
|
||||
)) : null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -92,24 +118,42 @@ abstract class BaseEntitiesState<T, P> extends TbContextState<BaseEntitiesWidget
|
||||
|
||||
late final PagingController<P, T> pagingController;
|
||||
Completer<void>? _refreshCompleter;
|
||||
bool _dataLoading = false;
|
||||
bool _scheduleRefresh = false;
|
||||
bool _reloadData = false;
|
||||
|
||||
BaseEntitiesState();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
pagingController = PagingController(firstPageKey: widget.createFirstKey());
|
||||
pagingController = PagingController(firstPageKey: widget.pageKeyController.value.pageKey);
|
||||
widget.pageKeyController.addListener(_didChangePageKeyValue);
|
||||
pagingController.addPageRequestListener((pageKey) {
|
||||
_fetchPage(pageKey);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(BaseEntitiesWidget<T, P> oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.pageKeyController != oldWidget.pageKeyController) {
|
||||
oldWidget.pageKeyController.removeListener(_didChangePageKeyValue);
|
||||
widget.pageKeyController.addListener(_didChangePageKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.pageKeyController.removeListener(_didChangePageKeyValue);
|
||||
pagingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _dataLoading = false;
|
||||
bool _scheduleRefresh = false;
|
||||
void _didChangePageKeyValue() {
|
||||
_reloadData = true;
|
||||
_refresh();
|
||||
}
|
||||
|
||||
Future<void> _refresh() {
|
||||
if (_refreshCompleter == null) {
|
||||
@@ -124,7 +168,12 @@ abstract class BaseEntitiesState<T, P> extends TbContextState<BaseEntitiesWidget
|
||||
}
|
||||
|
||||
void _refreshPagingController() {
|
||||
_fetchPage(widget.createFirstKey(), refresh: true);
|
||||
if (_reloadData) {
|
||||
pagingController.refresh();
|
||||
_reloadData = false;
|
||||
} else {
|
||||
_fetchPage(widget.pageKeyController.value.pageKey, refresh: true);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchPage(P pageKey, {bool refresh = false}) async {
|
||||
@@ -143,7 +192,7 @@ abstract class BaseEntitiesState<T, P> extends TbContextState<BaseEntitiesWidget
|
||||
if (isLastPage) {
|
||||
pagingController.appendLastPage(pageData.data);
|
||||
} else {
|
||||
final nextPageKey = widget.nextPageKey(pageKey);
|
||||
final nextPageKey = widget.pageKeyController.nextPageKey(pageKey);
|
||||
pagingController.appendPage(pageData.data, nextPageKey);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -207,7 +256,7 @@ abstract class BaseEntitiesState<T, P> extends TbContextState<BaseEntitiesWidget
|
||||
return FirstPageExceptionIndicator(
|
||||
title: widget.noItemsFoundText,
|
||||
message: 'The list is currently empty.',
|
||||
onTryAgain: () => pagingController.refresh(),
|
||||
onTryAgain: widget.searchMode ? null : () => pagingController.refresh(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ mixin EntitiesGridStateBase on StatefulWidget {
|
||||
|
||||
class _EntitiesGridState<T, P> extends BaseEntitiesState<T, P> {
|
||||
|
||||
_EntitiesGridState() : super();
|
||||
|
||||
@override
|
||||
Widget pagedViewBuilder(BuildContext context) {
|
||||
var heading = widget.buildHeading(context);
|
||||
|
||||
@@ -14,6 +14,8 @@ mixin EntitiesListStateBase on StatefulWidget {
|
||||
|
||||
class _EntitiesListState<T,P> extends BaseEntitiesState<T, P> {
|
||||
|
||||
_EntitiesListState() : super();
|
||||
|
||||
@override
|
||||
Widget pagedViewBuilder(BuildContext context) {
|
||||
var heading = widget.buildHeading(context);
|
||||
|
||||
@@ -32,8 +32,13 @@ class EntitiesListWidgetController {
|
||||
|
||||
}
|
||||
|
||||
abstract class EntitiesListPageLinkWidget<T> extends EntitiesListWidget<T, PageLink> with EntitiesBaseWithPageLink<T> {
|
||||
EntitiesListPageLinkWidget(TbContext tbContext, {EntitiesListWidgetController? controller}): super(tbContext, controller: controller);
|
||||
abstract class EntitiesListPageLinkWidget<T> extends EntitiesListWidget<T, PageLink> {
|
||||
|
||||
EntitiesListPageLinkWidget(TbContext tbContext, {EntitiesListWidgetController? controller}) : super(tbContext, controller: controller);
|
||||
|
||||
@override
|
||||
PageKeyController<PageLink> createPageKeyController() => PageLinkController(pageSize: 5);
|
||||
|
||||
}
|
||||
|
||||
abstract class EntitiesListWidget<T, P> extends TbContextWidget<EntitiesListWidget<T,P>, _EntitiesListWidgetState<T,P>> with EntitiesBase<T,P> {
|
||||
@@ -47,6 +52,8 @@ abstract class EntitiesListWidget<T, P> extends TbContextWidget<EntitiesListWidg
|
||||
@override
|
||||
_EntitiesListWidgetState createState() => _EntitiesListWidgetState(_controller);
|
||||
|
||||
PageKeyController<P> createPageKeyController();
|
||||
|
||||
void onViewAll();
|
||||
|
||||
}
|
||||
@@ -55,6 +62,8 @@ class _EntitiesListWidgetState<T,P> extends TbContextState<EntitiesListWidget<T,
|
||||
|
||||
final EntitiesListWidgetController? _controller;
|
||||
|
||||
late final PageKeyController<P> _pageKeyController;
|
||||
|
||||
final StreamController<PageData<T>?> _entitiesStreamController = StreamController.broadcast();
|
||||
|
||||
_EntitiesListWidgetState(EntitiesListWidgetController? controller):
|
||||
@@ -63,6 +72,7 @@ class _EntitiesListWidgetState<T,P> extends TbContextState<EntitiesListWidget<T,
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_pageKeyController = widget.createPageKeyController();
|
||||
if (_controller != null) {
|
||||
_controller!._registerEntitiesWidgetState(this);
|
||||
}
|
||||
@@ -74,13 +84,14 @@ class _EntitiesListWidgetState<T,P> extends TbContextState<EntitiesListWidget<T,
|
||||
if (_controller != null) {
|
||||
_controller!._unregisterEntitiesWidgetState(this);
|
||||
}
|
||||
_pageKeyController.dispose();
|
||||
_entitiesStreamController.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _refresh() {
|
||||
_entitiesStreamController.add(null);
|
||||
var entitiesFuture = widget.fetchEntities(widget.createFirstKey(pageSize: 5));
|
||||
var entitiesFuture = widget.fetchEntities(_pageKeyController.value.pageKey);
|
||||
entitiesFuture.then((value) => _entitiesStreamController.add(value));
|
||||
return entitiesFuture;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user