refactor(ui): update tags in DeviceLogsScreen

This commit is contained in:
anhtunz
2024-12-27 10:59:47 +07:00
parent 70e3ed8978
commit 178a00f5ba
11 changed files with 373 additions and 58 deletions

View File

@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />

View File

@@ -0,0 +1,178 @@
[
{
"elementType": "geometry",
"stylers": [
{
"color": "#212121"
}
]
},
{
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#212121"
}
]
},
{
"featureType": "administrative",
"elementType": "geometry",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "administrative.country",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
},
{
"featureType": "administrative.land_parcel",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "administrative.locality",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#bdbdbd"
}
]
},
{
"featureType": "poi",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "poi.park",
"elementType": "geometry",
"stylers": [
{
"color": "#181818"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#1b1b1b"
}
]
},
{
"featureType": "road",
"elementType": "geometry.fill",
"stylers": [
{
"color": "#2c2c2c"
}
]
},
{
"featureType": "road",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#8a8a8a"
}
]
},
{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
{
"color": "#373737"
}
]
},
{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
{
"color": "#3c3c3c"
}
]
},
{
"featureType": "road.highway.controlled_access",
"elementType": "geometry",
"stylers": [
{
"color": "#4e4e4e"
}
]
},
{
"featureType": "road.local",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "transit",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "water",
"elementType": "geometry",
"stylers": [
{
"color": "#000000"
}
]
},
{
"featureType": "water",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#3d3d3d"
}
]
}
]

View File

@@ -0,0 +1,65 @@
[
{
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "geometry",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "geometry.fill",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "geometry.stroke",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "labels.icon",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "labels.text",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "labels.text.fill",
"stylers": [
{
"visibility": "on"
}
]
},
{
"elementType": "labels.text.stroke",
"stylers": [
{
"visibility": "on"
}
]
}
]

View File

@@ -209,12 +209,6 @@ class _LoginScreenState extends State<LoginScreen> {
log("Role: ${LocaleManager.instance.getStringValue(PreferencesKeys.ROLE)}"); log("Role: ${LocaleManager.instance.getStringValue(PreferencesKeys.ROLE)}");
log("Theme: ${LocaleManager.instance.getStringValue(PreferencesKeys.THEME)}"); log("Theme: ${LocaleManager.instance.getStringValue(PreferencesKeys.THEME)}");
log("Lang: ${LocaleManager.instance.getStringValue(PreferencesKeys.LANGUAGE_CODE)}"); log("Lang: ${LocaleManager.instance.getStringValue(PreferencesKeys.LANGUAGE_CODE)}");
// log("Theme: $theme");
// if (theme == AppThemes.DARK.name) {
// themeNotifier.changeValue(AppThemes.DARK);
// } else {
// themeNotifier.changeValue(AppThemes.LIGHT);
// }
int timeNow = DateTime.now().millisecondsSinceEpoch ~/ 1000; int timeNow = DateTime.now().millisecondsSinceEpoch ~/ 1000;
if (token != "" && (exp - timeNow) > 7200) { if (token != "" && (exp - timeNow) > 7200) {
context.goNamed(AppRoutes.HOME.name); context.goNamed(AppRoutes.HOME.name);

View File

@@ -3,6 +3,7 @@ import 'dart:developer';
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:sfm_app/feature/device_log/widgets/tag_widget.dart';
import 'package:sfm_app/feature/devices/device_model.dart'; import 'package:sfm_app/feature/devices/device_model.dart';
import 'package:sfm_app/feature/device_log/device_logs_bloc.dart'; import 'package:sfm_app/feature/device_log/device_logs_bloc.dart';
import 'package:sfm_app/product/constant/icon/icon_constants.dart'; import 'package:sfm_app/product/constant/icon/icon_constants.dart';
@@ -179,6 +180,8 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
style: const ButtonStyle( style: const ButtonStyle(
backgroundColor: MaterialStatePropertyAll( backgroundColor: MaterialStatePropertyAll(
Colors.green), Colors.green),
foregroundColor: MaterialStatePropertyAll(
Colors.white),
), ),
onPressed: () { onPressed: () {
if (fromDateApi.isEmpty) { if (fromDateApi.isEmpty) {
@@ -196,8 +199,8 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
dateTime!, dateTime!,
sensors); sensors);
} }
log("ThingID: $thingID"); // log("ThingID: $thingID");
log("From Date: ${DateTimeUtils.instance.formatDateTimeToString(dateTime!)}"); // log("From Date: ${DateTimeUtils.instance.formatDateTimeToString(dateTime!)}");
}, },
icon: IconConstants.instance icon: IconConstants.instance
.getMaterialIcon(Icons.search), .getMaterialIcon(Icons.search),
@@ -275,8 +278,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
ListTile( ListTile(
subtitle: subtitle:
Text(DeviceUtils.instance.getDeviceSensorsLog(context, sensor)), Text(DeviceUtils.instance.getDeviceSensorsLog(context, sensor)),
// leading: const Icon(Icons.sensors_outlined), leading: leadingList(sensor),
leading: Text(index.toString()),
title: Text( title: Text(
DateTimeUtils.instance DateTimeUtils.instance
.convertCurrentMillisToDateTimeString(sensor.time ?? 0), .convertCurrentMillisToDateTimeString(sensor.time ?? 0),
@@ -299,4 +301,23 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
deviceLogsBloc.sinkHasMore.add(hasMore); deviceLogsBloc.sinkHasMore.add(hasMore);
deviceLogsBloc.getDeviceLogByThingID(offset, thingID, dateTime!, sensors); deviceLogsBloc.getDeviceLogByThingID(offset, thingID, dateTime!, sensors);
} }
Widget leadingList(SensorLogs sensor) {
Color boxColor;
String content;
if (sensor.name == "1" || sensor.name == "11") {
boxColor = Colors.blue;
content = "Điều khiển";
} else {
boxColor = Colors.lightGreen;
content = "Sự kiện";
}
return TagWidgetShared(
boxColor: boxColor,
tagContent: content,
boxHeight: context.mediumValue,
boxWidth: context.dynamicWidth(0.2),
);
}
} }

View File

@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
class TagWidgetShared extends StatelessWidget {
const TagWidgetShared({
super.key,
required this.boxColor,
this.boxRadius,
this.boxHeight,
this.boxWidth,
required this.tagContent,
});
final Color? boxColor;
final double? boxRadius;
final double? boxHeight;
final double? boxWidth;
final String? tagContent;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: boxColor,
borderRadius: BorderRadius.circular(boxRadius ?? 10),
),
height: boxHeight ?? 40,
width: boxWidth ?? 100,
child: Center(
child: Text(
tagContent ?? "",
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
);
}
}

View File

@@ -16,6 +16,10 @@ class MapBloc extends BlocBase {
@override @override
void dispose() {} void dispose() {}
final mapTheme = StreamController<String>.broadcast();
StreamSink<String> get sinkMapTheme => mapTheme.sink;
Stream<String> get streamMapTheme => mapTheme.stream;
final mapType = StreamController<MapType>.broadcast(); final mapType = StreamController<MapType>.broadcast();
StreamSink<MapType> get sinkMapType => mapType.sink; StreamSink<MapType> get sinkMapType => mapType.sink;
Stream<MapType> get streamMapType => mapType.stream; Stream<MapType> get streamMapType => mapType.stream;

View File

@@ -14,6 +14,8 @@ import 'package:sfm_app/product/constant/icon/icon_constants.dart';
import 'package:sfm_app/product/permission/location_permission.dart'; import 'package:sfm_app/product/permission/location_permission.dart';
import 'package:sfm_app/product/services/api_services.dart'; import 'package:sfm_app/product/services/api_services.dart';
import '../../product/constant/enums/app_theme_enums.dart';
class MapScreen extends StatefulWidget { class MapScreen extends StatefulWidget {
const MapScreen({super.key}); const MapScreen({super.key});
@@ -51,13 +53,20 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
LatLng myLocation = const LatLng(213761, 123123); LatLng myLocation = const LatLng(213761, 123123);
Position? position; Position? position;
bool isAllowLocationPermission = false; bool isAllowLocationPermission = false;
String themeMode = "";
@override @override
void initState() { void initState() {
super.initState(); super.initState();
mapBloc = BlocProvider.of(context); mapBloc = BlocProvider.of(context);
checkTheme();
_loadIcons(); _loadIcons();
getAllMarkers(); getAllMarkers();
clusterManager = _initClusterManager(); clusterManager = _initClusterManager();
DefaultAssetBundle.of(context)
.loadString("assets/map_themes/maps_dark_theme.json")
.then(
(value) => {themeMode = value},
);
} }
@override @override
@@ -78,36 +87,41 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
return StreamBuilder<List<LatLng>>( return StreamBuilder<List<LatLng>>(
stream: mapBloc.streamPolylines, stream: mapBloc.streamPolylines,
builder: (context, polylinesSnapshot) { builder: (context, polylinesSnapshot) {
return GoogleMap( return StreamBuilder<String>(
initialCameraPosition: _myPosition, stream: mapBloc.streamMapTheme,
mapType: mapType, builder: (context, mapThemeSnapshot) {
onMapCreated: (GoogleMapController controller) { return GoogleMap(
if (!_controller.isCompleted) { initialCameraPosition: _myPosition,
_controller.complete(controller); mapType: mapType,
} onMapCreated: (GoogleMapController controller) {
streamController.sink.add(controller); controller.setMapStyle(themeMode);
clusterManager.setMapId(controller.mapId); if (!_controller.isCompleted) {
}, _controller.complete(controller);
markers: markerSnapshot.data ?? markersAll }
..addAll(markers), streamController.sink.add(controller);
zoomControlsEnabled: true, clusterManager.setMapId(controller.mapId);
myLocationEnabled: true, },
mapToolbarEnabled: false, markers: markerSnapshot.data ?? markersAll
onCameraMove: (position) { ..addAll(markers),
clusterManager.onCameraMove(position); zoomControlsEnabled: true,
}, myLocationEnabled: true,
onCameraIdle: () { mapToolbarEnabled: false,
clusterManager.updateMap(); onCameraMove: (position) {
}, clusterManager.onCameraMove(position);
polylines: { },
Polyline( onCameraIdle: () {
polylineId: const PolylineId('router'), clusterManager.updateMap();
points: polylinesSnapshot.data ?? [], },
color: Colors.deepPurpleAccent, polylines: {
width: 8, Polyline(
), polylineId: const PolylineId('router'),
}, points: polylinesSnapshot.data ?? [],
); color: Colors.deepPurpleAccent,
width: 8,
),
},
);
});
}, },
); );
}, },
@@ -117,6 +131,22 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
); );
} }
void checkTheme() async {
String theme = await apiServices.checkTheme();
if (theme == AppThemes.LIGHT.name) {
getThemeMode('assets/map_themes/maps_light_theme.json');
} else {
getThemeMode('assets/map_themes/maps_dark_theme.json');
}
}
void getThemeMode(String path) {
DefaultAssetBundle.of(context)
.loadString(path)
.then((value) => {themeMode = value});
mapBloc.sinkMapTheme.add(themeMode);
}
Future<void> _loadIcons() async { Future<void> _loadIcons() async {
List<Future<BitmapDescriptor>> iconFutures = imageAssets.map((asset) { List<Future<BitmapDescriptor>> iconFutures = imageAssets.map((asset) {
return BitmapDescriptor.fromAssetImage(const ImageConfiguration(), asset); return BitmapDescriptor.fromAssetImage(const ImageConfiguration(), asset);

View File

@@ -11,6 +11,6 @@ class DateTimeUtils {
String convertCurrentMillisToDateTimeString(int time) { String convertCurrentMillisToDateTimeString(int time) {
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch((time) * 1000); DateTime dateTime = DateTime.fromMillisecondsSinceEpoch((time) * 1000);
return DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime); return DateFormat('HH:mm:ss dd-MM-yyyy').format(dateTime);
} }
} }

View File

@@ -517,14 +517,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@@ -629,14 +621,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
provider:
dependency: "direct main"
description:
name: provider
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
version: "6.1.2"
qr: qr:
dependency: transitive dependency: transitive
description: description:

View File

@@ -42,7 +42,6 @@ dependencies:
flutter_local_notifications: ^17.2.4 flutter_local_notifications: ^17.2.4
permission_handler: ^11.0.1 permission_handler: ^11.0.1
app_settings: ^5.1.1 app_settings: ^5.1.1
provider: ^6.1.2
flex_color_scheme: ^7.2.0 flex_color_scheme: ^7.2.0
go_router: ^13.1.0 go_router: ^13.1.0
http: ^1.1.0 http: ^1.1.0
@@ -88,6 +87,7 @@ flutter:
assets: assets:
- assets/images/ - assets/images/
- assets/icons/ - assets/icons/
- assets/map_themes/
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware # https://flutter.dev/assets-and-images/#resolution-aware