Add flutter 3+ support. Update dependencies. Fix code style and format issues.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import 'dart:core';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:thingsboard_app/constants/assets_path.dart';
|
||||
@@ -14,7 +13,6 @@ import 'package:thingsboard_app/utils/utils.dart';
|
||||
import 'package:thingsboard_client/thingsboard_client.dart';
|
||||
|
||||
mixin DevicesBase on EntitiesBase<EntityData, EntityDataQuery> {
|
||||
|
||||
@override
|
||||
String get title => 'Devices';
|
||||
|
||||
@@ -28,14 +26,19 @@ mixin DevicesBase on EntitiesBase<EntityData, EntityDataQuery> {
|
||||
|
||||
@override
|
||||
void onEntityTap(EntityData device) async {
|
||||
var profile = await DeviceProfileCache.getDeviceProfileInfo(tbClient, device.field('type')!, device.entityId.id!);
|
||||
var profile = await DeviceProfileCache.getDeviceProfileInfo(
|
||||
tbClient, device.field('type')!, device.entityId.id!);
|
||||
if (profile.defaultDashboardId != null) {
|
||||
var dashboardId = profile.defaultDashboardId!.id!;
|
||||
var state = Utils.createDashboardEntityState(device.entityId, entityName: device.field('name')!, entityLabel: device.field('label')!);
|
||||
navigateToDashboard(dashboardId, dashboardTitle: device.field('name'), state: state);
|
||||
var state = Utils.createDashboardEntityState(device.entityId,
|
||||
entityName: device.field('name')!,
|
||||
entityLabel: device.field('label')!);
|
||||
navigateToDashboard(dashboardId,
|
||||
dashboardTitle: device.field('name'), state: state);
|
||||
} else {
|
||||
if (tbClient.isTenantAdmin()) {
|
||||
showWarnNotification('Mobile dashboard should be configured in device profile!');
|
||||
showWarnNotification(
|
||||
'Mobile dashboard should be configured in device profile!');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,42 +60,51 @@ mixin DevicesBase on EntitiesBase<EntityData, EntityDataQuery> {
|
||||
|
||||
bool displayCardImage(bool listWidgetCard) => listWidgetCard;
|
||||
|
||||
Widget _buildEntityListCard(BuildContext context, EntityData device, bool listWidgetCard) {
|
||||
return DeviceCard(tbContext, device: device, listWidgetCard: listWidgetCard, displayImage: displayCardImage(listWidgetCard));
|
||||
Widget _buildEntityListCard(
|
||||
BuildContext context, EntityData device, bool listWidgetCard) {
|
||||
return DeviceCard(tbContext,
|
||||
device: device,
|
||||
listWidgetCard: listWidgetCard,
|
||||
displayImage: displayCardImage(listWidgetCard));
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceQueryController extends PageKeyController<EntityDataQuery> {
|
||||
|
||||
DeviceQueryController({int pageSize = 20, String? searchText, String? deviceType, bool? active}):
|
||||
super(EntityQueryApi.createDefaultDeviceQuery(pageSize: pageSize, searchText: searchText, deviceType: deviceType, active: active));
|
||||
DeviceQueryController(
|
||||
{int pageSize = 20, String? searchText, String? deviceType, bool? active})
|
||||
: super(EntityQueryApi.createDefaultDeviceQuery(
|
||||
pageSize: pageSize,
|
||||
searchText: searchText,
|
||||
deviceType: deviceType,
|
||||
active: active));
|
||||
|
||||
@override
|
||||
EntityDataQuery nextPageKey(EntityDataQuery deviceQuery) => deviceQuery.next();
|
||||
EntityDataQuery nextPageKey(EntityDataQuery deviceQuery) =>
|
||||
deviceQuery.next();
|
||||
|
||||
onSearchText(String searchText) {
|
||||
value.pageKey.pageLink.page = 0;
|
||||
value.pageKey.pageLink.textSearch = searchText;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DeviceCard extends TbContextWidget {
|
||||
|
||||
final EntityData device;
|
||||
final bool listWidgetCard;
|
||||
final bool displayImage;
|
||||
|
||||
DeviceCard(TbContext tbContext, {required this.device, this.listWidgetCard = false, this.displayImage = false}) : super(tbContext);
|
||||
DeviceCard(TbContext tbContext,
|
||||
{required this.device,
|
||||
this.listWidgetCard = false,
|
||||
this.displayImage = false})
|
||||
: super(tbContext);
|
||||
|
||||
@override
|
||||
_DeviceCardState createState() => _DeviceCardState();
|
||||
|
||||
}
|
||||
|
||||
class _DeviceCardState extends TbContextState<DeviceCard> {
|
||||
|
||||
final entityDateFormat = DateFormat('yyyy-MM-dd');
|
||||
|
||||
late Future<DeviceProfileInfo> deviceProfileFuture;
|
||||
@@ -129,250 +141,256 @@ class _DeviceCardState extends TbContextState<DeviceCard> {
|
||||
}
|
||||
|
||||
Widget buildCard(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
return Stack(children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Container(
|
||||
width: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: widget.device.attribute('active') == 'true' ? Color(0xFF008A00) : Color(0xFFAFAFAF),
|
||||
borderRadius: BorderRadius.only(topLeft: Radius.circular(4), bottomLeft: Radius.circular(4))
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
FutureBuilder<DeviceProfileInfo>(
|
||||
width: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: widget.device.attribute('active') == 'true'
|
||||
? Color(0xFF008A00)
|
||||
: Color(0xFFAFAFAF),
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(4),
|
||||
bottomLeft: Radius.circular(4))),
|
||||
))),
|
||||
FutureBuilder<DeviceProfileInfo>(
|
||||
future: deviceProfileFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData &&
|
||||
snapshot.connectionState == ConnectionState.done) {
|
||||
var profile = snapshot.data!;
|
||||
bool hasDashboard = profile.defaultDashboardId != null;
|
||||
Widget image;
|
||||
BoxFit imageFit;
|
||||
if (profile.image != null) {
|
||||
image = Utils.imageFromBase64(profile.image!);
|
||||
imageFit = BoxFit.contain;
|
||||
} else {
|
||||
image = SvgPicture.asset(
|
||||
ThingsboardImage.deviceProfilePlaceholder,
|
||||
color: Theme.of(context).primaryColor,
|
||||
colorBlendMode: BlendMode.overlay,
|
||||
semanticsLabel: 'Device');
|
||||
imageFit = BoxFit.cover;
|
||||
}
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (widget.displayImage)
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(4))),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(4)),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: FittedBox(
|
||||
fit: imageFit,
|
||||
child: image,
|
||||
))
|
||||
],
|
||||
))),
|
||||
SizedBox(width: 12),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: Column(children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment:
|
||||
Alignment.centerLeft,
|
||||
child: Text(
|
||||
'${widget.device.field('name')!}',
|
||||
style: TextStyle(
|
||||
color: Color(
|
||||
0xFF282828),
|
||||
fontSize: 14,
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.w500,
|
||||
height:
|
||||
20 / 14)))),
|
||||
SizedBox(width: 12),
|
||||
Text(
|
||||
entityDateFormat.format(DateTime
|
||||
.fromMillisecondsSinceEpoch(
|
||||
widget.device
|
||||
.createdTime!)),
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.normal,
|
||||
height: 16 / 12))
|
||||
]),
|
||||
SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${widget.device.field('type')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight:
|
||||
FontWeight.normal,
|
||||
height: 16 / 12)),
|
||||
Text(
|
||||
widget.device.attribute(
|
||||
'active') ==
|
||||
'true'
|
||||
? 'Active'
|
||||
: 'Inactive',
|
||||
style: TextStyle(
|
||||
color: widget.device
|
||||
.attribute(
|
||||
'active') ==
|
||||
'true'
|
||||
? Color(0xFF008A00)
|
||||
: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
height: 16 / 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
))
|
||||
],
|
||||
)
|
||||
])),
|
||||
SizedBox(width: 16),
|
||||
if (hasDashboard)
|
||||
Icon(Icons.chevron_right,
|
||||
color: Color(0xFFACACAC)),
|
||||
if (hasDashboard) SizedBox(width: 16),
|
||||
]),
|
||||
SizedBox(height: 12)
|
||||
],
|
||||
))
|
||||
]);
|
||||
} else {
|
||||
return Container(
|
||||
height: 64,
|
||||
child: Center(
|
||||
child: RefreshProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
Theme.of(tbContext.currentState!.context)
|
||||
.colorScheme
|
||||
.primary))));
|
||||
}
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
Widget buildListWidgetCard(BuildContext context) {
|
||||
return Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
if (widget.displayImage)
|
||||
Container(
|
||||
width: 58,
|
||||
height: 58,
|
||||
decoration: BoxDecoration(
|
||||
// color: Color(0xFFEEEEEE),
|
||||
borderRadius: BorderRadius.horizontal(left: Radius.circular(4))),
|
||||
child: FutureBuilder<DeviceProfileInfo>(
|
||||
future: deviceProfileFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.hasData &&
|
||||
snapshot.connectionState == ConnectionState.done) {
|
||||
var profile = snapshot.data!;
|
||||
bool hasDashboard = profile.defaultDashboardId != null;
|
||||
Widget image;
|
||||
BoxFit imageFit;
|
||||
if (profile.image != null) {
|
||||
image = Utils.imageFromBase64(profile.image!);
|
||||
imageFit = BoxFit.contain;
|
||||
} else {
|
||||
image = SvgPicture.asset(ThingsboardImage.deviceProfilePlaceholder,
|
||||
image = SvgPicture.asset(
|
||||
ThingsboardImage.deviceProfilePlaceholder,
|
||||
color: Theme.of(context).primaryColor,
|
||||
colorBlendMode: BlendMode.overlay,
|
||||
semanticsLabel: 'Device');
|
||||
imageFit = BoxFit.cover;
|
||||
}
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(width: 20),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (widget.displayImage) Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4))
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(4)),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: FittedBox(
|
||||
fit: imageFit,
|
||||
child: image,
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text('${widget.device.field('name')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF282828),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 20 / 14
|
||||
))
|
||||
)
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Text(entityDateFormat.format(DateTime.fromMillisecondsSinceEpoch(widget.device.createdTime!)),
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
))
|
||||
]
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('${widget.device.field('type')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
)),
|
||||
Text(widget.device.attribute('active') == 'true' ? 'Active' : 'Inactive',
|
||||
style: TextStyle(
|
||||
color: widget.device.attribute('active') == 'true' ? Color(0xFF008A00) : Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
height: 16 / 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
))
|
||||
],
|
||||
)
|
||||
]
|
||||
)
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
if (hasDashboard) Icon(Icons.chevron_right, color: Color(0xFFACACAC)),
|
||||
if (hasDashboard) SizedBox(width: 16),
|
||||
]
|
||||
),
|
||||
SizedBox(height: 12)
|
||||
],
|
||||
)
|
||||
)
|
||||
]
|
||||
);
|
||||
return ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.horizontal(left: Radius.circular(4)),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: FittedBox(
|
||||
fit: imageFit,
|
||||
child: image,
|
||||
))
|
||||
],
|
||||
));
|
||||
} else {
|
||||
return Container(
|
||||
height: 64,
|
||||
child: Center(
|
||||
child: RefreshProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(Theme.of(tbContext.currentState!.context).colorScheme.primary)
|
||||
)
|
||||
)
|
||||
);
|
||||
return Center(
|
||||
child: RefreshProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
Theme.of(tbContext.currentState!.context)
|
||||
.colorScheme
|
||||
.primary)));
|
||||
}
|
||||
}
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildListWidgetCard(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.displayImage) Container(
|
||||
width: 58,
|
||||
height: 58,
|
||||
decoration: BoxDecoration(
|
||||
// color: Color(0xFFEEEEEE),
|
||||
borderRadius: BorderRadius.horizontal(left: Radius.circular(4))
|
||||
),
|
||||
child: FutureBuilder<DeviceProfileInfo>(
|
||||
future: deviceProfileFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) {
|
||||
var profile = snapshot.data!;
|
||||
Widget image;
|
||||
BoxFit imageFit;
|
||||
if (profile.image != null) {
|
||||
image = Utils.imageFromBase64(profile.image!);
|
||||
imageFit = BoxFit.contain;
|
||||
} else {
|
||||
image = SvgPicture.asset(ThingsboardImage.deviceProfilePlaceholder,
|
||||
color: Theme.of(context).primaryColor,
|
||||
colorBlendMode: BlendMode.overlay,
|
||||
semanticsLabel: 'Device');
|
||||
imageFit = BoxFit.cover;
|
||||
}
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.horizontal(left: Radius.circular(4)),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: FittedBox(
|
||||
fit: imageFit,
|
||||
child: image,
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return Center(child: RefreshProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation(Theme.of(tbContext.currentState!.context).colorScheme.primary)
|
||||
));
|
||||
}
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child:
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 9, horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text('${widget.device.field('name')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF282828),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 20 / 14
|
||||
))
|
||||
)
|
||||
]
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('${widget.device.field('type')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
)),
|
||||
]
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
);
|
||||
),
|
||||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 9, horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text('${widget.device.field('name')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF282828),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 20 / 14)))
|
||||
]),
|
||||
SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('${widget.device.field('type')!}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12)),
|
||||
])
|
||||
],
|
||||
)))
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user