Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 33f5f27eaa | |||
| 84f10271e9 |
@@ -7,10 +7,6 @@
|
|||||||
|
|
||||||
# The following line activates a set of recommended lints for Flutter apps,
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
# packages, and plugins designed to encourage good coding practices.
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
analyzer:
|
|
||||||
errors:
|
|
||||||
use_build_context_synchronously: ignore
|
|
||||||
avoid_print: ignore
|
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
@@ -26,8 +22,8 @@ linter:
|
|||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
# producing the lint.
|
# producing the lint.
|
||||||
rules:
|
rules:
|
||||||
- prefer_relative_imports: true
|
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
|||||||
@@ -1,10 +1,3 @@
|
|||||||
plugins {
|
|
||||||
id "com.android.application"
|
|
||||||
id "kotlin-android"
|
|
||||||
id "dev.flutter.flutter-gradle-plugin"
|
|
||||||
id 'com.google.gms.google-services'
|
|
||||||
}
|
|
||||||
|
|
||||||
def localProperties = new Properties()
|
def localProperties = new Properties()
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
@@ -13,6 +6,11 @@ if (localPropertiesFile.exists()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
// throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
if (flutterVersionCode == null) {
|
if (flutterVersionCode == null) {
|
||||||
flutterVersionCode = '1'
|
flutterVersionCode = '1'
|
||||||
@@ -23,12 +21,21 @@ if (flutterVersionName == null) {
|
|||||||
flutterVersionName = '1.0'
|
flutterVersionName = '1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
// START: FlutterFire Configuration
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
// END: FlutterFire Configuration
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
if (keystorePropertiesFile.exists()) {
|
if (keystorePropertiesFile.exists()) {
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace "vn.smatec.sfm"
|
namespace "vn.smatec.sfm"
|
||||||
compileSdkVersion 35
|
compileSdkVersion 35
|
||||||
@@ -37,12 +44,12 @@ android {
|
|||||||
compileOptions {
|
compileOptions {
|
||||||
// Flag to enable support for the new language APIs
|
// Flag to enable support for the new language APIs
|
||||||
coreLibraryDesugaringEnabled true
|
coreLibraryDesugaringEnabled true
|
||||||
sourceCompatibility JavaVersion.VERSION_17
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_17
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '17'
|
jvmTarget = '1.8'
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@@ -95,9 +102,9 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation platform('com.google.firebase:firebase-bom:33.15.0')
|
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
|
||||||
implementation 'androidx.window:window:1.0.0'
|
implementation 'androidx.window:window:1.0.0'
|
||||||
implementation 'androidx.window:window-java:1.0.0'
|
implementation 'androidx.window:window-java:1.0.0'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,30 @@
|
|||||||
<manifest xmlns:tools="http://schemas.android.com/tools"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<uses-feature
|
|
||||||
android:name="android.hardware.camera"
|
|
||||||
android:required="false"
|
|
||||||
tools:targetApi="5" />
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<!-- <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> -->
|
||||||
|
<!-- NOTE: the example app requests USE_EXACT_ALARM to make it easier to run the app.
|
||||||
|
Developers will need to check if their own app needs to use SCHEDULE_EXACT_ALARM instead -->
|
||||||
|
<!-- <uses-permission android:name="android.permission.USE_EXACT_ALARM" /> -->
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<!-- NOTE: Special use was selected as it's the closest match for this example app.
|
||||||
|
apps should specify the appropriate permission for their use cases. -->
|
||||||
|
<!-- <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" /> -->
|
||||||
|
<!-- START Permissions Package -->
|
||||||
<!-- Permissions options for the `camera` group -->
|
<!-- Permissions options for the `camera` group -->
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
<!-- Permissions options for the `location` group -->
|
<!-- Permissions options for the `location` group -->
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<!-- Permissions options for the `alarm` group -->
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
|
||||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
|
||||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM"
|
|
||||||
tools:ignore="ExactAlarm" />
|
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
|
||||||
<!-- END Permissions Package -->
|
<!-- END Permissions Package -->
|
||||||
<application
|
<application
|
||||||
android:label="SFM"
|
android:label="SFM"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/launcher_icon">
|
android:icon="@mipmap/launcher_icon">
|
||||||
<meta-data android:name="com.google.android.geo.API_KEY"
|
<meta-data android:name="com.google.android.geo.API_KEY"
|
||||||
android:value="AIzaSyDI8b-PUgKUgj5rHdtgEHCwWjUXYJrqYhE"/>
|
android:value="AIzaSyA9C7Pmxw6Gw3H2mM4WA_XGngRIIr2VS7k"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
@@ -40,7 +34,6 @@
|
|||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:showWhenLocked="true"
|
android:showWhenLocked="true"
|
||||||
android:turnScreenOn="true"
|
android:turnScreenOn="true"
|
||||||
android:enableOnBackInvokedCallback="true"
|
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
the Android process has started. This theme is visible to the user
|
the Android process has started. This theme is visible to the user
|
||||||
@@ -67,25 +60,7 @@
|
|||||||
<service
|
<service
|
||||||
android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
|
android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:stopWithTask="false"
|
android:stopWithTask="false"/>
|
||||||
android:foregroundServiceType="specialUse" />
|
|
||||||
<service android:name="com.gdelataillade.alarm.services.NotificationOnKillService" />
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
|
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
|
||||||
android:exported="false"/>
|
|
||||||
<receiver
|
|
||||||
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmBroadcastReceiver"
|
|
||||||
android:exported="false"/>
|
|
||||||
<receiver
|
|
||||||
android:name="dev.fluttercommunity.plus.androidalarmmanager.RebootBroadcastReceiver"
|
|
||||||
android:enabled="false"
|
|
||||||
android:exported="false">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
|
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
|
||||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
|
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
|
||||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
|
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 442 B |
@@ -1,9 +1,21 @@
|
|||||||
plugins {
|
buildscript {
|
||||||
id 'com.google.gms.google-services' version '4.3.15' apply false
|
ext.kotlin_version = '1.8.22'
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// START: FlutterFire Configuration
|
||||||
|
classpath 'com.google.gms:google-services:4.3.15'
|
||||||
|
// END: FlutterFire Configuration
|
||||||
|
classpath 'com.android.tools.build:gradle:8.2.1'
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
@@ -31,7 +43,3 @@ subprojects {
|
|||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip
|
||||||
|
|||||||
@@ -18,11 +18,8 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
id "com.android.application" version "8.3.2" apply false
|
id "com.android.application" version "8.2.1" apply false
|
||||||
// START: FlutterFire Configuration
|
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
|
||||||
id "com.google.gms.google-services" version "4.3.15" apply false
|
|
||||||
// END: FlutterFire Configuration
|
|
||||||
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
include ":app"
|
include ":app"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,3 +0,0 @@
|
|||||||
description: This file stores settings for Dart & Flutter DevTools.
|
|
||||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
|
||||||
extensions:
|
|
||||||
31
ios/Podfile
31
ios/Podfile
@@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '15.0'
|
platform :ios, '14.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
@@ -37,35 +37,6 @@ end
|
|||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
|
||||||
target.build_configurations.each do |config|
|
|
||||||
# You can remove unused permissions here
|
|
||||||
# for more information: https://github.com/BaseflowIT/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
|
|
||||||
# e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
|
|
||||||
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
|
|
||||||
'$(inherited)',
|
|
||||||
|
|
||||||
## dart: PermissionGroup.camera
|
|
||||||
'PERMISSION_CAMERA=1',
|
|
||||||
|
|
||||||
## The 'PERMISSION_LOCATION' macro enables the `locationWhenInUse` and `locationAlways` permission. If
|
|
||||||
## the application only requires `locationWhenInUse`, only specify the `PERMISSION_LOCATION_WHENINUSE`
|
|
||||||
## macro.
|
|
||||||
##
|
|
||||||
## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
|
|
||||||
'PERMISSION_LOCATION=0',
|
|
||||||
'PERMISSION_LOCATION_WHENINUSE=1',
|
|
||||||
|
|
||||||
## dart: PermissionGroup.notification
|
|
||||||
'PERMISSION_NOTIFICATIONS=1',
|
|
||||||
|
|
||||||
|
|
||||||
## dart: PermissionGroup.criticalAlerts
|
|
||||||
'PERMISSION_CRITICAL_ALERTS=1',
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
end
|
|
||||||
target.build_configurations.each do |config|
|
target.build_configurations.each do |config|
|
||||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
|
||||||
end
|
end
|
||||||
|
|||||||
147
ios/Podfile.lock
147
ios/Podfile.lock
@@ -1,197 +1,62 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- alarm (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- app_settings (5.1.1):
|
|
||||||
- Flutter
|
|
||||||
- connectivity_plus (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Firebase/CoreOnly (11.10.0):
|
|
||||||
- FirebaseCore (~> 11.10.0)
|
|
||||||
- Firebase/Messaging (11.10.0):
|
|
||||||
- Firebase/CoreOnly
|
|
||||||
- FirebaseMessaging (~> 11.10.0)
|
|
||||||
- firebase_core (3.13.0):
|
|
||||||
- Firebase/CoreOnly (= 11.10.0)
|
|
||||||
- Flutter
|
|
||||||
- firebase_messaging (15.2.5):
|
|
||||||
- Firebase/Messaging (= 11.10.0)
|
|
||||||
- firebase_core
|
|
||||||
- Flutter
|
|
||||||
- FirebaseCore (11.10.0):
|
|
||||||
- FirebaseCoreInternal (~> 11.10.0)
|
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
|
||||||
- GoogleUtilities/Logger (~> 8.0)
|
|
||||||
- FirebaseCoreInternal (11.10.0):
|
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
|
||||||
- FirebaseInstallations (11.10.0):
|
|
||||||
- FirebaseCore (~> 11.10.0)
|
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
|
||||||
- PromisesObjC (~> 2.4)
|
|
||||||
- FirebaseMessaging (11.10.0):
|
|
||||||
- FirebaseCore (~> 11.10.0)
|
|
||||||
- FirebaseInstallations (~> 11.0)
|
|
||||||
- GoogleDataTransport (~> 10.0)
|
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
|
||||||
- GoogleUtilities/Reachability (~> 8.0)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
|
||||||
- nanopb (~> 3.30910.0)
|
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_barcode_scanner_plus (3.0.7):
|
- flutter_barcode_scanner_plus (3.0.7):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_fgbg (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_local_notifications (0.0.1):
|
- flutter_local_notifications (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- geolocator_apple (1.2.0):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- Google-Maps-iOS-Utils (5.0.0):
|
- Google-Maps-iOS-Utils (5.0.0):
|
||||||
- GoogleMaps (~> 8.0)
|
- GoogleMaps (~> 8.0)
|
||||||
- google_maps_flutter_ios (0.0.1):
|
- google_maps_flutter_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Google-Maps-iOS-Utils (< 7.0, >= 5.0)
|
- Google-Maps-iOS-Utils (< 7.0, >= 5.0)
|
||||||
- GoogleMaps (< 10.0, >= 8.4)
|
- GoogleMaps (< 10.0, >= 8.4)
|
||||||
- GoogleDataTransport (10.1.0):
|
|
||||||
- nanopb (~> 3.30910.0)
|
|
||||||
- PromisesObjC (~> 2.4)
|
|
||||||
- GoogleMaps (8.4.0):
|
- GoogleMaps (8.4.0):
|
||||||
- GoogleMaps/Maps (= 8.4.0)
|
- GoogleMaps/Maps (= 8.4.0)
|
||||||
- GoogleMaps/Base (8.4.0)
|
- GoogleMaps/Base (8.4.0)
|
||||||
- GoogleMaps/Maps (8.4.0):
|
- GoogleMaps/Maps (8.4.0):
|
||||||
- GoogleMaps/Base
|
- GoogleMaps/Base
|
||||||
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
|
|
||||||
- GoogleUtilities/Environment
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- GoogleUtilities/Network
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- GoogleUtilities/Environment (8.1.0):
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- GoogleUtilities/Logger (8.1.0):
|
|
||||||
- GoogleUtilities/Environment
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- GoogleUtilities/Network (8.1.0):
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- "GoogleUtilities/NSData+zlib"
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- GoogleUtilities/Reachability
|
|
||||||
- "GoogleUtilities/NSData+zlib (8.1.0)":
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- GoogleUtilities/Privacy (8.1.0)
|
|
||||||
- GoogleUtilities/Reachability (8.1.0):
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- GoogleUtilities/UserDefaults (8.1.0):
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- GoogleUtilities/Privacy
|
|
||||||
- maps_launcher (0.0.1):
|
- maps_launcher (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- nanopb (3.30910.0):
|
|
||||||
- nanopb/decode (= 3.30910.0)
|
|
||||||
- nanopb/encode (= 3.30910.0)
|
|
||||||
- nanopb/decode (3.30910.0)
|
|
||||||
- nanopb/encode (3.30910.0)
|
|
||||||
- permission_handler_apple (9.3.0):
|
- permission_handler_apple (9.3.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- PromisesObjC (2.4.0)
|
|
||||||
- shared_preferences_foundation (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
- url_launcher_ios (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- alarm (from `.symlinks/plugins/alarm/ios`)
|
|
||||||
- app_settings (from `.symlinks/plugins/app_settings/ios`)
|
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_barcode_scanner_plus (from `.symlinks/plugins/flutter_barcode_scanner_plus/ios`)
|
- flutter_barcode_scanner_plus (from `.symlinks/plugins/flutter_barcode_scanner_plus/ios`)
|
||||||
- flutter_fgbg (from `.symlinks/plugins/flutter_fgbg/ios`)
|
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
|
|
||||||
- google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`)
|
- google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`)
|
||||||
- maps_launcher (from `.symlinks/plugins/maps_launcher/ios`)
|
- maps_launcher (from `.symlinks/plugins/maps_launcher/ios`)
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
- Firebase
|
|
||||||
- FirebaseCore
|
|
||||||
- FirebaseCoreInternal
|
|
||||||
- FirebaseInstallations
|
|
||||||
- FirebaseMessaging
|
|
||||||
- Google-Maps-iOS-Utils
|
- Google-Maps-iOS-Utils
|
||||||
- GoogleDataTransport
|
|
||||||
- GoogleMaps
|
- GoogleMaps
|
||||||
- GoogleUtilities
|
|
||||||
- nanopb
|
|
||||||
- PromisesObjC
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
alarm:
|
|
||||||
:path: ".symlinks/plugins/alarm/ios"
|
|
||||||
app_settings:
|
|
||||||
:path: ".symlinks/plugins/app_settings/ios"
|
|
||||||
connectivity_plus:
|
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
|
||||||
firebase_core:
|
|
||||||
:path: ".symlinks/plugins/firebase_core/ios"
|
|
||||||
firebase_messaging:
|
|
||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_barcode_scanner_plus:
|
flutter_barcode_scanner_plus:
|
||||||
:path: ".symlinks/plugins/flutter_barcode_scanner_plus/ios"
|
:path: ".symlinks/plugins/flutter_barcode_scanner_plus/ios"
|
||||||
flutter_fgbg:
|
|
||||||
:path: ".symlinks/plugins/flutter_fgbg/ios"
|
|
||||||
flutter_local_notifications:
|
flutter_local_notifications:
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
geolocator_apple:
|
|
||||||
:path: ".symlinks/plugins/geolocator_apple/darwin"
|
|
||||||
google_maps_flutter_ios:
|
google_maps_flutter_ios:
|
||||||
:path: ".symlinks/plugins/google_maps_flutter_ios/ios"
|
:path: ".symlinks/plugins/google_maps_flutter_ios/ios"
|
||||||
maps_launcher:
|
maps_launcher:
|
||||||
:path: ".symlinks/plugins/maps_launcher/ios"
|
:path: ".symlinks/plugins/maps_launcher/ios"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
shared_preferences_foundation:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
|
||||||
url_launcher_ios:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
alarm: 9ff6d2dae9bd69c4022622f7e0a1e9c1dd70064e
|
|
||||||
app_settings: 5127ae0678de1dcc19f2293271c51d37c89428b2
|
|
||||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
|
||||||
Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
|
|
||||||
firebase_core: 2d4534e7b489907dcede540c835b48981d890943
|
|
||||||
firebase_messaging: 75bc93a4df25faccad67f6662ae872ac9ae69b64
|
|
||||||
FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7
|
|
||||||
FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
|
|
||||||
FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
|
|
||||||
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
|
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_barcode_scanner_plus: e5ef7f41cdbf3086e1b9348dce986dde3aa08696
|
flutter_barcode_scanner_plus: 5777819a85622aed4284fb14d1fa33b72a64003d
|
||||||
flutter_fgbg: d3da78df78454b1808f0829a5da9cd17dfe16444
|
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||||
flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100
|
|
||||||
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
|
|
||||||
Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321
|
Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321
|
||||||
google_maps_flutter_ios: 0291eb2aa252298a769b04d075e4a9d747ff7264
|
google_maps_flutter_ios: e31555a04d1986ab130f2b9f24b6cdc861acc6d3
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
|
||||||
GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d
|
GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
maps_launcher: 2e5b6a2d664ec6c27f82ffa81b74228d770ab203
|
||||||
maps_launcher: edf829809ba9e894d70e569bab11c16352dedb45
|
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
|
||||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
|
||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: 72b62bbc58143b910914489c5ddbf2bfa99b3dd4
|
PODFILE CHECKSUM: 9de95a6a40372eef38c524a1823cf12342740f38
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -11,13 +11,12 @@
|
|||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
5EFD34A62DA7D89800351DB2 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5EFD34A52DA7D89800351DB2 /* GoogleService-Info.plist */; };
|
5EFD34A62DA7D89800351DB2 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5EFD34A52DA7D89800351DB2 /* GoogleService-Info.plist */; };
|
||||||
634E6B9E5E8AF15560F03990 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 501AA52756E2B08A7E1FBE73 /* Pods_Runner.framework */; };
|
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||||
|
8C56D767FE4FABDBA3A6FEC5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9FD75834CF1BDB8A25BFFEC /* Pods_Runner.framework */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
A241E2BF2EAA2F1C00664284 /* warning_alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = A241E2BE2EAA2F1C00664284 /* warning_alarm.caf */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -46,18 +45,17 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
22127402AC507377520FA076 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
25C6B6667708ECABC11CB63A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
30C8386A287397C265D21D0C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
501AA52756E2B08A7E1FBE73 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
5EE624442DA6030500B7B650 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
5EE624442DA6030500B7B650 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
5EFD34A52DA7D89800351DB2 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
5EFD34A52DA7D89800351DB2 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
78334C166CCB562F36E48821 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
7F880EC2F80617123414BCDC /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
932B4AD0BAFC1BC9FBBFA388 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -65,7 +63,7 @@
|
|||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
A241E2BE2EAA2F1C00664284 /* warning_alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = warning_alarm.caf; sourceTree = "<group>"; };
|
F9FD75834CF1BDB8A25BFFEC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -74,13 +72,21 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||||
634E6B9E5E8AF15560F03990 /* Pods_Runner.framework in Frameworks */,
|
8C56D767FE4FABDBA3A6FEC5 /* Pods_Runner.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
316923E64F63A0F9D874FB14 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F9FD75834CF1BDB8A25BFFEC /* Pods_Runner.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -89,14 +95,6 @@
|
|||||||
path = RunnerTests;
|
path = RunnerTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7E17DC341A9804E98C0A4D9D /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
501AA52756E2B08A7E1FBE73 /* Pods_Runner.framework */,
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -111,13 +109,12 @@
|
|||||||
97C146E51CF9000F007C117D = {
|
97C146E51CF9000F007C117D = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A241E2BE2EAA2F1C00664284 /* warning_alarm.caf */,
|
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
E4B9BF767E8449E8CDAC1C45 /* Pods */,
|
E4B9BF767E8449E8CDAC1C45 /* Pods */,
|
||||||
7E17DC341A9804E98C0A4D9D /* Frameworks */,
|
316923E64F63A0F9D874FB14 /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -150,9 +147,9 @@
|
|||||||
E4B9BF767E8449E8CDAC1C45 /* Pods */ = {
|
E4B9BF767E8449E8CDAC1C45 /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
30C8386A287397C265D21D0C /* Pods-Runner.debug.xcconfig */,
|
7F880EC2F80617123414BCDC /* Pods-Runner.debug.xcconfig */,
|
||||||
25C6B6667708ECABC11CB63A /* Pods-Runner.release.xcconfig */,
|
78334C166CCB562F36E48821 /* Pods-Runner.release.xcconfig */,
|
||||||
22127402AC507377520FA076 /* Pods-Runner.profile.xcconfig */,
|
932B4AD0BAFC1BC9FBBFA388 /* Pods-Runner.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -181,15 +178,15 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
63291DA6552A39BD8B950BE6 /* [CP] Check Pods Manifest.lock */,
|
9EC01057D3A8F2BAF61BC6F6 /* [CP] Check Pods Manifest.lock */,
|
||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
6E40E7EA960942FA803CE7C6 /* [CP] Embed Pods Frameworks */,
|
F412CDB3CB7EB2B89B8A1F67 /* [CP] Embed Pods Frameworks */,
|
||||||
1DD8F2A74CC23CF717FB4664 /* [CP] Copy Pods Resources */,
|
7A68DAC237480EA02778D297 /* [CP] Copy Pods Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -259,7 +256,6 @@
|
|||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
5EFD34A62DA7D89800351DB2 /* GoogleService-Info.plist in Resources */,
|
5EFD34A62DA7D89800351DB2 /* GoogleService-Info.plist in Resources */,
|
||||||
A241E2BF2EAA2F1C00664284 /* warning_alarm.caf in Resources */,
|
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||||
);
|
);
|
||||||
@@ -268,23 +264,6 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
1DD8F2A74CC23CF717FB4664 /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputFileListPaths = (
|
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
alwaysOutOfDate = 1;
|
alwaysOutOfDate = 1;
|
||||||
@@ -301,7 +280,39 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
};
|
};
|
||||||
63291DA6552A39BD8B950BE6 /* [CP] Check Pods Manifest.lock */ = {
|
7A68DAC237480EA02778D297 /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Run Script";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
|
};
|
||||||
|
9EC01057D3A8F2BAF61BC6F6 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
@@ -323,7 +334,7 @@
|
|||||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
6E40E7EA960942FA803CE7C6 /* [CP] Embed Pods Frameworks */ = {
|
F412CDB3CB7EB2B89B8A1F67 /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
@@ -340,21 +351,6 @@
|
|||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Run Script";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -446,7 +442,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -464,17 +460,17 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = 6;
|
||||||
DEVELOPMENT_TEAM = WM843WW2NF;
|
DEVELOPMENT_TEAM = WM843WW2NF;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SmartFM;
|
INFOPLIST_KEY_CFBundleDisplayName = SmartFM;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.5;
|
MARKETING_VERSION = 1.0.6;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = vn.smatec.sfm;
|
PRODUCT_BUNDLE_IDENTIFIER = vn.smatec.sfm;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -578,7 +574,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -627,7 +623,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -647,17 +643,17 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = 6;
|
||||||
DEVELOPMENT_TEAM = WM843WW2NF;
|
DEVELOPMENT_TEAM = WM843WW2NF;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SmartFM;
|
INFOPLIST_KEY_CFBundleDisplayName = SmartFM;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.5;
|
MARKETING_VERSION = 1.0.6;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = vn.smatec.sfm;
|
PRODUCT_BUNDLE_IDENTIFIER = vn.smatec.sfm;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -677,17 +673,17 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = 6;
|
||||||
DEVELOPMENT_TEAM = WM843WW2NF;
|
DEVELOPMENT_TEAM = WM843WW2NF;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SmartFM;
|
INFOPLIST_KEY_CFBundleDisplayName = SmartFM;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.5;
|
MARKETING_VERSION = 1.0.6;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = vn.smatec.sfm;
|
PRODUCT_BUNDLE_IDENTIFIER = vn.smatec.sfm;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "55c94c702657474632f237e12a19340acc7419ac493c42deecaaa9d0cd699fd8",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "abseil-cpp-binary",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/abseil-cpp-binary.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5",
|
||||||
|
"version" : "1.2024072200.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "app-check",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/app-check.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "61b85103a1aeed8218f17c794687781505fbbef5",
|
||||||
|
"version" : "11.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "firebase-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/firebase-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "d1f7c7e8eaa74d7e44467184dc5f592268247d33",
|
||||||
|
"version" : "11.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "flutterfire",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/flutterfire",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a80a123386fd4904cad6938673020a7bcf31b2f2",
|
||||||
|
"version" : "3.13.0-firebase-core-swift"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googleappmeasurement",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleAppMeasurement.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "dd89fc79a77183830742a16866d87e4e54785734",
|
||||||
|
"version" : "11.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googledatatransport",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleDataTransport.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "617af071af9aa1d6a091d59a202910ac482128f9",
|
||||||
|
"version" : "10.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googleutilities",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleUtilities.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb",
|
||||||
|
"version" : "8.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "grpc-binary",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/grpc-binary.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "cc0001a0cf963aa40501d9c2b181e7fc9fd8ec71",
|
||||||
|
"version" : "1.69.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "gtm-session-fetcher",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/gtm-session-fetcher.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "4d70340d55d7d07cc2fdf8e8125c4c126c1d5f35",
|
||||||
|
"version" : "4.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "interop-ios-for-google-sdks",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/interop-ios-for-google-sdks.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe",
|
||||||
|
"version" : "101.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "leveldb",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/leveldb.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1",
|
||||||
|
"version" : "1.22.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "nanopb",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/nanopb.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1",
|
||||||
|
"version" : "2.30910.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "promises",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/promises.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac",
|
||||||
|
"version" : "2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-protobuf",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "d72aed98f8253ec1aa9ea1141e28150f408cf17f",
|
||||||
|
"version" : "1.29.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
@@ -44,7 +44,6 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
@@ -73,13 +72,11 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
debugServiceExtension = "internal"
|
debugServiceExtension = "internal"
|
||||||
enableGPUValidationMode = "1"
|
|
||||||
allowLocationSimulation = "YES">
|
allowLocationSimulation = "YES">
|
||||||
<BuildableProductRunnable
|
<BuildableProductRunnable
|
||||||
runnableDebuggingMode = "0">
|
runnableDebuggingMode = "0">
|
||||||
|
|||||||
132
ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved
Normal file
132
ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"originHash" : "55c94c702657474632f237e12a19340acc7419ac493c42deecaaa9d0cd699fd8",
|
||||||
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "abseil-cpp-binary",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/abseil-cpp-binary.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5",
|
||||||
|
"version" : "1.2024072200.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "app-check",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/app-check.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "61b85103a1aeed8218f17c794687781505fbbef5",
|
||||||
|
"version" : "11.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "firebase-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/firebase-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "d1f7c7e8eaa74d7e44467184dc5f592268247d33",
|
||||||
|
"version" : "11.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "flutterfire",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/flutterfire",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a80a123386fd4904cad6938673020a7bcf31b2f2",
|
||||||
|
"version" : "3.13.0-firebase-core-swift"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googleappmeasurement",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleAppMeasurement.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "dd89fc79a77183830742a16866d87e4e54785734",
|
||||||
|
"version" : "11.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googledatatransport",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleDataTransport.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "617af071af9aa1d6a091d59a202910ac482128f9",
|
||||||
|
"version" : "10.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googleutilities",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleUtilities.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb",
|
||||||
|
"version" : "8.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "grpc-binary",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/grpc-binary.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "cc0001a0cf963aa40501d9c2b181e7fc9fd8ec71",
|
||||||
|
"version" : "1.69.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "gtm-session-fetcher",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/gtm-session-fetcher.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "4d70340d55d7d07cc2fdf8e8125c4c126c1d5f35",
|
||||||
|
"version" : "4.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "interop-ios-for-google-sdks",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/interop-ios-for-google-sdks.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe",
|
||||||
|
"version" : "101.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "leveldb",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/leveldb.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1",
|
||||||
|
"version" : "1.22.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "nanopb",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/nanopb.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1",
|
||||||
|
"version" : "2.30910.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "promises",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/promises.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac",
|
||||||
|
"version" : "2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-protobuf",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "d72aed98f8253ec1aa9ea1141e28150f408cf17f",
|
||||||
|
"version" : "1.29.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version" : 3
|
||||||
|
}
|
||||||
@@ -4,8 +4,6 @@ import flutter_local_notifications
|
|||||||
import GoogleMaps
|
import GoogleMaps
|
||||||
import FirebaseCore
|
import FirebaseCore
|
||||||
import FirebaseMessaging
|
import FirebaseMessaging
|
||||||
import UserNotifications
|
|
||||||
import alarm
|
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
@@ -16,7 +14,6 @@ import alarm
|
|||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
|
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
|
||||||
}
|
}
|
||||||
SwiftAlarmPlugin.registerBackgroundTasks()
|
|
||||||
FirebaseApp.configure()
|
FirebaseApp.configure()
|
||||||
GMSServices.provideAPIKey("AIzaSyA9C7Pmxw6Gw3H2mM4WA_XGngRIIr2VS7k")
|
GMSServices.provideAPIKey("AIzaSyA9C7Pmxw6Gw3H2mM4WA_XGngRIIr2VS7k")
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||||
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--Flutter View Controller-->
|
<!--Flutter View Controller-->
|
||||||
@@ -16,14 +14,13 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="121" y="-34"/>
|
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>SmartFM</string>
|
<string>Sfm App</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
@@ -28,18 +28,19 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>Camera permission is required for barcode scanning.</string>
|
<string>Camera permission is required for barcode scanning.</string>
|
||||||
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
|
<string>Always and when in use!</string>
|
||||||
|
<key>NSLocationAlwaysUsageDescription</key>
|
||||||
|
<string>Can I have location always?</string>
|
||||||
|
<key>NSLocationUsageDescription</key>
|
||||||
|
<string>Older devices need location.</string>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string>Cần vị trí để hiển thị bản đồ hoặc tìm địa điểm gần bạn</string>
|
<string>Need location when in use</string>
|
||||||
<key>NSUserNotificationsUsageDescription</key>
|
|
||||||
<string>Chúng tôi cần gửi thông báo khẩn cấp để cảnh báo về việc thiết bị phát hiện có cháy.</string>
|
|
||||||
<key>com.apple.developer.usernotifications.critical-alerts</key>
|
|
||||||
<true/>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
<string>audio</string>
|
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
@@ -61,9 +62,5 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
|
||||||
<array>
|
|
||||||
<string>com.gdelataillade.fetch</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
Binary file not shown.
1
ios/build/.last_build_id
Normal file
1
ios/build/.last_build_id
Normal file
@@ -0,0 +1 @@
|
|||||||
|
4f4dfcdc103d3d3b4ca43bd2cac6c5ac
|
||||||
1
ios/sfmTranslateErrors.txt
Normal file
1
ios/sfmTranslateErrors.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
Binary file not shown.
@@ -4,6 +4,7 @@ import '../product/base/bloc/base_bloc.dart';
|
|||||||
import '../feature/bell/bell_model.dart';
|
import '../feature/bell/bell_model.dart';
|
||||||
|
|
||||||
class BellBloc extends BlocBase {
|
class BellBloc extends BlocBase {
|
||||||
|
|
||||||
final bellItems = StreamController<List<BellItems>>.broadcast();
|
final bellItems = StreamController<List<BellItems>>.broadcast();
|
||||||
StreamSink<List<BellItems>> get sinkBellItems => bellItems.sink;
|
StreamSink<List<BellItems>> get sinkBellItems => bellItems.sink;
|
||||||
Stream<List<BellItems>> get streamBellItems => bellItems.stream;
|
Stream<List<BellItems>> get streamBellItems => bellItems.stream;
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
|
import 'package:sfm_app/product/services/api_services.dart';
|
||||||
|
import 'package:sfm_app/product/utils/device_utils.dart';
|
||||||
|
|
||||||
import '../product/services/api_services.dart';
|
|
||||||
import '../product/utils/date_time_utils.dart';
|
import '../product/utils/date_time_utils.dart';
|
||||||
import '../feature/device_log/device_logs_model.dart';
|
import '../feature/device_log/device_logs_model.dart';
|
||||||
import '../feature/devices/device_model.dart';
|
import '../feature/devices/device_model.dart';
|
||||||
|
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/utils/device_utils.dart';
|
|
||||||
|
|
||||||
class DetailDeviceBloc extends BlocBase {
|
class DetailDeviceBloc extends BlocBase {
|
||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
@@ -38,12 +42,14 @@ class DetailDeviceBloc extends BlocBase {
|
|||||||
String thingID,
|
String thingID,
|
||||||
Completer<GoogleMapController> controller,
|
Completer<GoogleMapController> controller,
|
||||||
) async {
|
) async {
|
||||||
await apiServices.execute(context, () async {
|
String body = await apiServices.getDeviceInfomation(thingID);
|
||||||
Device device = await apiServices.getDeviceInformation(thingID);
|
if (body != "") {
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
Device device = Device.fromJson(data);
|
||||||
sinkDeviceInfo.add(device);
|
sinkDeviceInfo.add(device);
|
||||||
if (device.areaPath != null) {
|
if (device.areaPath != null) {
|
||||||
String fullLocation = await DeviceUtils.instance
|
String fullLocation = await DeviceUtils.instance
|
||||||
.getFullDeviceLocation(context, device.areaPath!, "");
|
.getFullDeviceLocation(context, device.areaPath!);
|
||||||
log("Location: $fullLocation");
|
log("Location: $fullLocation");
|
||||||
sinkDeviceLocation.add(fullLocation);
|
sinkDeviceLocation.add(fullLocation);
|
||||||
}
|
}
|
||||||
@@ -68,103 +74,40 @@ class DetailDeviceBloc extends BlocBase {
|
|||||||
mapController
|
mapController
|
||||||
.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
|
.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
// try {
|
|
||||||
// Device device = await apiServices.getDeviceInformation(thingID);
|
|
||||||
// sinkDeviceInfo.add(device);
|
|
||||||
// if (device.areaPath != null) {
|
|
||||||
// String fullLocation = await DeviceUtils.instance
|
|
||||||
// .getFullDeviceLocation(context, device.areaPath!, "");
|
|
||||||
// log("Location: $fullLocation");
|
|
||||||
// sinkDeviceLocation.add(fullLocation);
|
|
||||||
// }
|
|
||||||
// Map<String, dynamic> sensorMap = {};
|
|
||||||
// if (device.status!.sensors != null) {
|
|
||||||
// sensorMap = DeviceUtils.instance
|
|
||||||
// .getDeviceSensors(context, device.status!.sensors!);
|
|
||||||
// } else {
|
|
||||||
// sensorMap = DeviceUtils.instance.getDeviceSensors(context, []);
|
|
||||||
// }
|
|
||||||
// sinkDeviceSensor.add(sensorMap);
|
|
||||||
// if (device.settings!.latitude! != "" &&
|
|
||||||
// device.settings!.longitude! != "") {
|
|
||||||
// final CameraPosition cameraPosition = CameraPosition(
|
|
||||||
// target: LatLng(
|
|
||||||
// double.parse(device.settings!.latitude!),
|
|
||||||
// double.parse(device.settings!.longitude!),
|
|
||||||
// ),
|
|
||||||
// zoom: 13,
|
|
||||||
// );
|
|
||||||
// final GoogleMapController mapController = await controller.future;
|
|
||||||
// mapController
|
|
||||||
// .animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void findLocation(BuildContext context, String areaPath) async {
|
void findLocation(BuildContext context, String areaPath) async {
|
||||||
String fullLocation =
|
String fullLocation =
|
||||||
await DeviceUtils.instance.getFullDeviceLocation(context, areaPath, "");
|
await DeviceUtils.instance.getFullDeviceLocation(context, areaPath);
|
||||||
sinkDeviceLocation.add(fullLocation);
|
sinkDeviceLocation.add(fullLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getNearerSensorValue(BuildContext context, String thingID) async {
|
void getNearerSensorValue(String thingID) async {
|
||||||
apiServices.execute(context, () async {
|
List<SensorLogs> sensorTemps = [];
|
||||||
List<SensorLogs> sensorTemps = [];
|
DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
|
||||||
DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
|
String from = DateTimeUtils.instance.formatDateTimeToString(twoDaysAgo);
|
||||||
String from = DateTimeUtils.instance.formatDateTimeToString(twoDaysAgo);
|
String now = DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
||||||
String now =
|
Map<String, dynamic> params = {
|
||||||
DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
'thing_id': thingID,
|
||||||
Map<String, dynamic> params = {
|
'from': from,
|
||||||
'thing_id': thingID,
|
'to': now,
|
||||||
'from': from,
|
'limit': '100',
|
||||||
'to': now,
|
'n': '7',
|
||||||
'limit': '100',
|
};
|
||||||
'n': '7',
|
final body = await apiServices.getLogsOfDevice(thingID, params);
|
||||||
};
|
if (body != "") {
|
||||||
DeviceLog devicesListLog =
|
final data = jsonDecode(body);
|
||||||
await apiServices.getLogsOfDevice(thingID, params);
|
DeviceLog devicesListLog = DeviceLog.fromJson(data);
|
||||||
if (devicesListLog.sensors!.isNotEmpty) {
|
if (devicesListLog.sensors!.isNotEmpty) {
|
||||||
for (var sensor in devicesListLog.sensors!) {
|
for (var sensor in devicesListLog.sensors!) {
|
||||||
sensorTemps.add(sensor);
|
sensorTemps.add(sensor);
|
||||||
}
|
}
|
||||||
sensorTemps = sensorTemps.reversed.toList();
|
sensorTemps = sensorTemps.reversed.toList();
|
||||||
sinkSensorTemps.add(sensorTemps);
|
sinkSensorTemps.add(sensorTemps);
|
||||||
} else {
|
} else{
|
||||||
sinkSensorTemps.add([]);
|
sinkSensorTemps.add([]);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
// try {
|
|
||||||
// List<SensorLogs> sensorTemps = [];
|
|
||||||
// DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
|
|
||||||
// String from = DateTimeUtils.instance.formatDateTimeToString(twoDaysAgo);
|
|
||||||
// String now =
|
|
||||||
// DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
|
||||||
// Map<String, dynamic> params = {
|
|
||||||
// 'thing_id': thingID,
|
|
||||||
// 'from': from,
|
|
||||||
// 'to': now,
|
|
||||||
// 'limit': '100',
|
|
||||||
// 'n': '7',
|
|
||||||
// };
|
|
||||||
// DeviceLog devicesListLog =
|
|
||||||
// await apiServices.getLogsOfDevice(thingID, params);
|
|
||||||
// if (devicesListLog.sensors!.isNotEmpty) {
|
|
||||||
// for (var sensor in devicesListLog.sensors!) {
|
|
||||||
// sensorTemps.add(sensor);
|
|
||||||
// }
|
|
||||||
// sensorTemps = sensorTemps.reversed.toList();
|
|
||||||
// sinkSensorTemps.add(sensorTemps);
|
|
||||||
// } else {
|
|
||||||
// sinkSensorTemps.add([]);
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// sinkSensorTemps.add([]);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'dart:convert';
|
||||||
|
|
||||||
import '../feature/devices/device_model.dart';
|
import '../feature/devices/device_model.dart';
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/constant/app/app_constants.dart';
|
import '../product/constant/app/app_constants.dart';
|
||||||
import '../product/services/api_services.dart';
|
import '../product/services/api_services.dart';
|
||||||
import '../product/utils/date_time_utils.dart';
|
import '../product/utils/date_time_utils.dart';
|
||||||
|
|
||||||
import '../product/utils/device_utils.dart';
|
import '../product/utils/device_utils.dart';
|
||||||
import '../feature/device_log/device_logs_model.dart';
|
import '../feature/device_log/device_logs_model.dart';
|
||||||
|
|
||||||
@@ -34,38 +35,40 @@ class DeviceLogsBloc extends BlocBase {
|
|||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
|
|
||||||
void getAllDevices(BuildContext context) async {
|
void getAllDevices() async {
|
||||||
await apiServices.execute(context, () async {
|
String body = await apiServices.getOwnerDevices();
|
||||||
List<Device> originalDevices = await apiServices.getOwnerDevices();
|
if (body != "") {
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
List<dynamic> items = data['items'];
|
||||||
|
List<Device> originalDevices = Device.fromJsonDynamicList(items);
|
||||||
List<Device> devices =
|
List<Device> devices =
|
||||||
DeviceUtils.instance.sortDeviceByState(originalDevices);
|
DeviceUtils.instance.sortDeviceByState(originalDevices);
|
||||||
sinkAllDevices.add(devices);
|
sinkAllDevices.add(devices);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void getDeviceLogByThingID(
|
void getDeviceLogByThingID(
|
||||||
BuildContext context,
|
|
||||||
int offset,
|
int offset,
|
||||||
String thingID,
|
String thingID,
|
||||||
DateTime fromDate,
|
DateTime fromDate,
|
||||||
List<SensorLogs> sensors,
|
List<SensorLogs> sensors,
|
||||||
) async {
|
) async {
|
||||||
await apiServices.execute(context, () async {
|
sinkmessage.add(ApplicationConstants.LOADING);
|
||||||
sinkmessage.add(ApplicationConstants.LOADING);
|
String fromDateString =
|
||||||
String fromDateString =
|
DateTimeUtils.instance.formatDateTimeToString(fromDate);
|
||||||
DateTimeUtils.instance.formatDateTimeToString(fromDate);
|
String now = DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
||||||
String now =
|
Map<String, dynamic> params = {
|
||||||
DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
'thing_id': thingID,
|
||||||
Map<String, dynamic> params = {
|
'from': fromDateString,
|
||||||
'thing_id': thingID,
|
'to': now,
|
||||||
'from': fromDateString,
|
'limit': '30',
|
||||||
'to': now,
|
"offset": offset.toString(),
|
||||||
'limit': '30',
|
"asc": "true"
|
||||||
"offset": offset.toString(),
|
};
|
||||||
"asc": "true"
|
final body = await apiServices.getLogsOfDevice(thingID, params);
|
||||||
};
|
if (body != "") {
|
||||||
DeviceLog devicesListLog =
|
final data = jsonDecode(body);
|
||||||
await apiServices.getLogsOfDevice(thingID, params);
|
DeviceLog devicesListLog = DeviceLog.fromJson(data);
|
||||||
if (devicesListLog.sensors!.isEmpty) {
|
if (devicesListLog.sensors!.isEmpty) {
|
||||||
bool hasMore = false;
|
bool hasMore = false;
|
||||||
sinkHasMore.add(hasMore);
|
sinkHasMore.add(hasMore);
|
||||||
@@ -78,38 +81,6 @@ class DeviceLogsBloc extends BlocBase {
|
|||||||
sinkmessage.add(ApplicationConstants.NO_DATA);
|
sinkmessage.add(ApplicationConstants.NO_DATA);
|
||||||
}
|
}
|
||||||
sinkSensors.add(sensors);
|
sinkSensors.add(sensors);
|
||||||
});
|
}
|
||||||
// try {
|
|
||||||
// sinkmessage.add(ApplicationConstants.LOADING);
|
|
||||||
// String fromDateString =
|
|
||||||
// DateTimeUtils.instance.formatDateTimeToString(fromDate);
|
|
||||||
// String now =
|
|
||||||
// DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
|
|
||||||
// Map<String, dynamic> params = {
|
|
||||||
// 'thing_id': thingID,
|
|
||||||
// 'from': fromDateString,
|
|
||||||
// 'to': now,
|
|
||||||
// 'limit': '30',
|
|
||||||
// "offset": offset.toString(),
|
|
||||||
// "asc": "true"
|
|
||||||
// };
|
|
||||||
// DeviceLog devicesListLog =
|
|
||||||
// await apiServices.getLogsOfDevice(thingID, params);
|
|
||||||
// if (devicesListLog.sensors!.isEmpty) {
|
|
||||||
// bool hasMore = false;
|
|
||||||
// sinkHasMore.add(hasMore);
|
|
||||||
// }
|
|
||||||
// if (devicesListLog.sensors!.isNotEmpty) {
|
|
||||||
// for (var sensor in devicesListLog.sensors!) {
|
|
||||||
// sensors.add(sensor);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// sinkmessage.add(ApplicationConstants.NO_DATA);
|
|
||||||
// }
|
|
||||||
// sinkSensors.add(sensors);
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../feature/settings/device_notification_settings/device_notification_settings_model.dart';
|
import '../feature/settings/device_notification_settings/device_notification_settings_model.dart';
|
||||||
@@ -35,6 +36,7 @@ class DeviceNotificationSettingsBloc extends BlocBase {
|
|||||||
StreamSink<String> get sinkMessageChange => messageChange.sink;
|
StreamSink<String> get sinkMessageChange => messageChange.sink;
|
||||||
Stream<String> get streaMmessageChange => messageChange.stream;
|
Stream<String> get streaMmessageChange => messageChange.stream;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import '../product/services/api_services.dart';
|
import '../product/services/api_services.dart';
|
||||||
import '../product/services/language_services.dart';
|
import '../product/services/language_services.dart';
|
||||||
import '../product/shared/model/ward_model.dart';
|
import '../product/shared/model/ward_model.dart';
|
||||||
import '../product/shared/shared_snack_bar.dart';
|
|
||||||
import '../product/utils/response_status_utils.dart';
|
import '../product/utils/response_status_utils.dart';
|
||||||
|
|
||||||
import '../product/shared/model/district_model.dart';
|
import '../product/shared/model/district_model.dart';
|
||||||
import '../product/shared/model/province_model.dart';
|
import '../product/shared/model/province_model.dart';
|
||||||
import '../feature/devices/device_model.dart';
|
import '../feature/devices/device_model.dart';
|
||||||
@@ -75,281 +75,151 @@ class DeviceUpdateBloc extends BlocBase {
|
|||||||
// deviceInfo.done;
|
// deviceInfo.done;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getAllProvinces(BuildContext context) async {
|
Future<void> getAllProvinces() async {
|
||||||
List<DropdownMenuItem<Province>> provincesData = [];
|
List<DropdownMenuItem<Province>> provincesData = [];
|
||||||
provincesData.clear();
|
provincesData.clear();
|
||||||
sinkListProvinces.add(provincesData);
|
sinkListProvinces.add(provincesData);
|
||||||
await apiServices.execute(context, () async {
|
final body = await apiServices.getAllProvinces();
|
||||||
List<Province> provinces = await apiServices.getAllProvinces();
|
final data = jsonDecode(body);
|
||||||
for (var province in provinces) {
|
List<dynamic> items = data["items"];
|
||||||
provincesData.add(
|
|
||||||
DropdownMenuItem(value: province, child: Text(province.fullName!)));
|
final provinces = Province.fromJsonDynamicList(items);
|
||||||
}
|
for (var province in provinces) {
|
||||||
sinkListProvinces.add(provincesData);
|
provincesData.add(
|
||||||
});
|
DropdownMenuItem(value: province, child: Text(province.fullName!)));
|
||||||
|
}
|
||||||
|
sinkListProvinces.add(provincesData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getAllDistricts(BuildContext context, String provinceID) async {
|
Future<void> getAllDistricts(String provinceID) async {
|
||||||
List<DropdownMenuItem<District>> districtsData = [];
|
List<DropdownMenuItem<District>> districtsData = [];
|
||||||
districtsData.clear();
|
districtsData.clear();
|
||||||
sinkListDistricts.add(districtsData);
|
sinkListDistricts.add(districtsData);
|
||||||
await apiServices.execute(context, () async {
|
final body = await apiServices.getAllDistricts(provinceID);
|
||||||
final districts = await apiServices.getAllDistricts(provinceID);
|
final data = jsonDecode(body);
|
||||||
for (var district in districts) {
|
List<dynamic> items = data["items"];
|
||||||
districtsData.add(
|
final districts = District.fromJsonDynamicList(items);
|
||||||
DropdownMenuItem(value: district, child: Text(district.fullName!)));
|
for (var district in districts) {
|
||||||
}
|
districtsData.add(
|
||||||
sinkListDistricts.add(districtsData);
|
DropdownMenuItem(value: district, child: Text(district.fullName!)));
|
||||||
});
|
}
|
||||||
|
sinkListDistricts.add(districtsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getAllWards(BuildContext context, String districtID) async {
|
Future<void> getAllWards(String districtID) async {
|
||||||
List<DropdownMenuItem<Ward>> wardsData = [];
|
List<DropdownMenuItem<Ward>> wardsData = [];
|
||||||
wardsData.clear();
|
wardsData.clear();
|
||||||
sinkListWards.add(wardsData);
|
sinkListWards.add(wardsData);
|
||||||
await apiServices.execute(context, () async {
|
final body = await apiServices.getAllWards(districtID);
|
||||||
final wards = await apiServices.getAllWards(districtID);
|
final data = jsonDecode(body);
|
||||||
for (var ward in wards) {
|
List<dynamic> items = data["items"];
|
||||||
wardsData
|
final wards = Ward.fromJsonDynamicList(items);
|
||||||
.add(DropdownMenuItem(value: ward, child: Text(ward.fullName!)));
|
for (var ward in wards) {
|
||||||
}
|
wardsData.add(DropdownMenuItem(value: ward, child: Text(ward.fullName!)));
|
||||||
sinkListWards.add(wardsData);
|
}
|
||||||
});
|
sinkListWards.add(wardsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getDeviceInformation(
|
Future<void> getDeviceInfomation(
|
||||||
BuildContext context,
|
|
||||||
String thingID,
|
String thingID,
|
||||||
|
List<DropdownMenuItem<District>> districtsData,
|
||||||
|
List<DropdownMenuItem<Ward>> wardsData,
|
||||||
TextEditingController deviceNameController,
|
TextEditingController deviceNameController,
|
||||||
TextEditingController latitudeController,
|
TextEditingController latitudeController,
|
||||||
TextEditingController longitudeController) async {
|
TextEditingController longitudeController) async {
|
||||||
await apiServices.execute(context, () async {
|
String body = await apiServices.getDeviceInfomation(thingID);
|
||||||
Device device = await apiServices.getDeviceInformation(thingID);
|
final data = jsonDecode(body);
|
||||||
sinkDeviceInfo.add(device);
|
Device device = Device.fromJson(data);
|
||||||
deviceNameController.text = device.name ?? "";
|
sinkDeviceInfo.add(device);
|
||||||
latitudeController.text = device.settings!.latitude ?? "";
|
deviceNameController.text = device.name ?? "";
|
||||||
longitudeController.text = device.settings!.longitude ?? "";
|
latitudeController.text = device.settings!.latitude ?? "";
|
||||||
|
longitudeController.text = device.settings!.longitude ?? "";
|
||||||
if (device.areaPath != null && device.areaPath!.isNotEmpty) {
|
if (device.areaPath != "") {
|
||||||
List<String> areaPath = device.areaPath!.split('_');
|
List<String> areaPath = device.areaPath!.split('_');
|
||||||
|
String provinceCode = areaPath[0];
|
||||||
// Kiểm tra độ dài của areaPath
|
String districtCode = areaPath[1];
|
||||||
if (areaPath.length >= 3) {
|
String wardCode = areaPath[2];
|
||||||
String provinceCode = areaPath[0];
|
getAllDistricts(provinceCode);
|
||||||
String districtCode = areaPath[1];
|
getAllWards(districtCode);
|
||||||
String wardCode = areaPath[2];
|
final provinceResponse = await apiServices.getProvinceByID(provinceCode);
|
||||||
|
final provincesData = jsonDecode(provinceResponse);
|
||||||
// Kiểm tra các mã có hợp lệ không (không rỗng)
|
Province province = Province.fromJson(provincesData['data']);
|
||||||
if (provinceCode.isNotEmpty &&
|
final districtResponse = await apiServices.getDistrictByID(districtCode);
|
||||||
districtCode.isNotEmpty &&
|
final districtData = jsonDecode(districtResponse);
|
||||||
wardCode.isNotEmpty) {
|
District district = District.fromJson(districtData['data']);
|
||||||
try {
|
final wardResponse = await apiServices.getWardByID(wardCode);
|
||||||
// Lấy danh sách districts và wards
|
final wardData = jsonDecode(wardResponse);
|
||||||
await getAllDistricts(context, provinceCode);
|
Ward ward = Ward.fromJson(wardData['data']);
|
||||||
await getAllWards(context, districtCode);
|
Map<String, String> provinceData = {
|
||||||
|
"name": province.fullName!,
|
||||||
// Xử lý Province
|
"code": province.code!
|
||||||
try {
|
};
|
||||||
Province province =
|
sinkProvinceData.add(provinceData);
|
||||||
await apiServices.getProvinceByID(provinceCode);
|
Map<String, String> districData = {
|
||||||
Map<String, String> provinceData = {
|
"name": district.fullName!,
|
||||||
"name": province.fullName ?? "Unknown Province",
|
"code": district.code!,
|
||||||
"code": province.code ?? provinceCode
|
};
|
||||||
};
|
sinkDistrictData.add(districData);
|
||||||
sinkProvinceData.add(provinceData);
|
Map<String, String> wardMap = {
|
||||||
} catch (e) {
|
"name": ward.fullName!,
|
||||||
// Thêm dữ liệu mặc định khi lỗi
|
"code": ward.code!,
|
||||||
Map<String, String> provinceData = {
|
};
|
||||||
"name": "Error Loading Province",
|
sinkWardData.add(wardMap);
|
||||||
"code": provinceCode
|
}
|
||||||
};
|
|
||||||
sinkProvinceData.add(provinceData);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Xử lý District
|
|
||||||
try {
|
|
||||||
District district =
|
|
||||||
await apiServices.getDistrictByID(districtCode);
|
|
||||||
Map<String, String> districData = {
|
|
||||||
"name": district.fullName ?? "Unknown District",
|
|
||||||
"code": district.code ?? districtCode,
|
|
||||||
};
|
|
||||||
sinkDistrictData.add(districData);
|
|
||||||
} catch (e) {
|
|
||||||
log("Lỗi khi lấy thông tin district ($districtCode): $e");
|
|
||||||
Map<String, String> districData = {
|
|
||||||
"name": "Error Loading District",
|
|
||||||
"code": districtCode,
|
|
||||||
};
|
|
||||||
sinkDistrictData.add(districData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Xử lý Ward
|
|
||||||
try {
|
|
||||||
Ward ward = await apiServices.getWardByID(wardCode);
|
|
||||||
Map<String, String> wardMap = {
|
|
||||||
"name": ward.fullName ?? "Unknown Ward",
|
|
||||||
"code": ward.code ?? wardCode,
|
|
||||||
};
|
|
||||||
sinkWardData.add(wardMap);
|
|
||||||
} catch (e) {
|
|
||||||
log("Lỗi khi lấy thông tin ward ($wardCode): $e");
|
|
||||||
Map<String, String> wardMap = {
|
|
||||||
"name": "Error Loading Ward",
|
|
||||||
"code": wardCode,
|
|
||||||
};
|
|
||||||
sinkWardData.add(wardMap);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log("Lỗi khi gọi getAllDistricts hoặc getAllWards: $e");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await getAllProvinces(context);
|
|
||||||
log("Một hoặc nhiều mã địa phương trống: Province: $provinceCode, District: $districtCode, Ward: $wardCode");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showNoIconTopSnackBar(
|
|
||||||
context,
|
|
||||||
"AreaPath không đủ thông tin: ${device.areaPath}",
|
|
||||||
Colors.orangeAccent,
|
|
||||||
Colors.white);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// Device device = await apiServices.getDeviceInformation(thingID);
|
|
||||||
// sinkDeviceInfo.add(device);
|
|
||||||
// deviceNameController.text = device.name ?? "";
|
|
||||||
// latitudeController.text = device.settings!.latitude ?? "";
|
|
||||||
// longitudeController.text = device.settings!.longitude ?? "";
|
|
||||||
|
|
||||||
// if (device.areaPath != null && device.areaPath!.isNotEmpty) {
|
|
||||||
// List<String> areaPath = device.areaPath!.split('_');
|
|
||||||
|
|
||||||
// // Kiểm tra độ dài của areaPath
|
|
||||||
// if (areaPath.length >= 3) {
|
|
||||||
// String provinceCode = areaPath[0];
|
|
||||||
// String districtCode = areaPath[1];
|
|
||||||
// String wardCode = areaPath[2];
|
|
||||||
|
|
||||||
// // Kiểm tra các mã có hợp lệ không (không rỗng)
|
|
||||||
// if (provinceCode.isNotEmpty &&
|
|
||||||
// districtCode.isNotEmpty &&
|
|
||||||
// wardCode.isNotEmpty) {
|
|
||||||
// try {
|
|
||||||
// // Lấy danh sách districts và wards
|
|
||||||
// await getAllDistricts(context, provinceCode);
|
|
||||||
// await getAllWards(context, districtCode);
|
|
||||||
|
|
||||||
// // Xử lý Province
|
|
||||||
// try {
|
|
||||||
// Province province =
|
|
||||||
// await apiServices.getProvinceByID(provinceCode);
|
|
||||||
// Map<String, String> provinceData = {
|
|
||||||
// "name": province.fullName ?? "Unknown Province",
|
|
||||||
// "code": province.code ?? provinceCode
|
|
||||||
// };
|
|
||||||
// sinkProvinceData.add(provinceData);
|
|
||||||
// } catch (e) {
|
|
||||||
// // Thêm dữ liệu mặc định khi lỗi
|
|
||||||
// Map<String, String> provinceData = {
|
|
||||||
// "name": "Error Loading Province",
|
|
||||||
// "code": provinceCode
|
|
||||||
// };
|
|
||||||
// sinkProvinceData.add(provinceData);
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Xử lý District
|
|
||||||
// try {
|
|
||||||
// District district =
|
|
||||||
// await apiServices.getDistrictByID(districtCode);
|
|
||||||
// Map<String, String> districData = {
|
|
||||||
// "name": district.fullName ?? "Unknown District",
|
|
||||||
// "code": district.code ?? districtCode,
|
|
||||||
// };
|
|
||||||
// sinkDistrictData.add(districData);
|
|
||||||
// } catch (e) {
|
|
||||||
// log("Lỗi khi lấy thông tin district ($districtCode): $e");
|
|
||||||
// Map<String, String> districData = {
|
|
||||||
// "name": "Error Loading District",
|
|
||||||
// "code": districtCode,
|
|
||||||
// };
|
|
||||||
// sinkDistrictData.add(districData);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Xử lý Ward
|
|
||||||
// try {
|
|
||||||
// Ward ward = await apiServices.getWardByID(wardCode);
|
|
||||||
// Map<String, String> wardMap = {
|
|
||||||
// "name": ward.fullName ?? "Unknown Ward",
|
|
||||||
// "code": ward.code ?? wardCode,
|
|
||||||
// };
|
|
||||||
// sinkWardData.add(wardMap);
|
|
||||||
// } catch (e) {
|
|
||||||
// print("Lỗi khi lấy thông tin ward ($wardCode): $e");
|
|
||||||
// Map<String, String> wardMap = {
|
|
||||||
// "name": "Error Loading Ward",
|
|
||||||
// "code": wardCode,
|
|
||||||
// };
|
|
||||||
// sinkWardData.add(wardMap);
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// print("Lỗi khi gọi getAllDistricts hoặc getAllWards: $e");
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// await getAllProvinces(context);
|
|
||||||
// print(
|
|
||||||
// "Một hoặc nhiều mã địa phương trống: Province: $provinceCode, District: $districtCode, Ward: $wardCode");
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// showNoIconTopSnackBar(
|
|
||||||
// context,
|
|
||||||
// "AreaPath không đủ thông tin: ${device.areaPath}",
|
|
||||||
// Colors.orangeAccent,
|
|
||||||
// Colors.white);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// showNoIconTopSnackBar(context, "Lỗi trong getDeviceInfomation: $e",
|
|
||||||
// Colors.orangeAccent, Colors.white);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Province> getProvinceByName(BuildContext context, String name) async {
|
Future<Province> getProvinceByName(String name) async {
|
||||||
return await apiServices.execute(context, () async {
|
final response = await apiServices.getProvincesByName(name);
|
||||||
List<Province> provinces = await apiServices.getProvincesByName(name);
|
final data = jsonDecode(response);
|
||||||
|
if (data != null &&
|
||||||
|
data.containsKey('items') &&
|
||||||
|
data['items'] != null &&
|
||||||
|
data['items'].isNotEmpty) {
|
||||||
|
List<dynamic> items = data['items'];
|
||||||
|
List<Province> provinces = Province.fromJsonDynamicList(items);
|
||||||
if (provinces.isNotEmpty) {
|
if (provinces.isNotEmpty) {
|
||||||
return provinces[0];
|
return provinces[0];
|
||||||
} else {
|
|
||||||
return Province(name: "null");
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return Province(name: "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<District> getDistrictByName(
|
Future<District> getDistrictByName(String name, String provinceCode) async {
|
||||||
BuildContext context, String name, String provinceCode) async {
|
final response = await apiServices.getDistrictsByName(name);
|
||||||
return apiServices.execute(context, () async {
|
if (response != "") {
|
||||||
final districts = await apiServices.getDistrictsByName(name);
|
final data = jsonDecode(response);
|
||||||
return districts.firstWhere(
|
List<dynamic> items = data['items'];
|
||||||
(district) => district.provinceCode == provinceCode,
|
if (items.isNotEmpty) {
|
||||||
orElse: () => District(name: "null"),
|
List<District> districts = District.fromJsonDynamicList(items);
|
||||||
);
|
if (districts.isNotEmpty) {
|
||||||
});
|
for (var district in districts) {
|
||||||
|
if (district.provinceCode == provinceCode) {
|
||||||
|
return district;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return District(name: "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Ward> getWardByName(
|
Future<Ward> getWardByName(String name, String districtCode) async {
|
||||||
BuildContext context, String name, String districtCode) async {
|
final response = await apiServices.getWarsdByName(name);
|
||||||
return apiServices.execute(context, () async {
|
final data = jsonDecode(response);
|
||||||
final wards = await apiServices.getWardsByName(name);
|
if (data != null && data['items'] != null) {
|
||||||
return wards.firstWhere(
|
List<dynamic> items = data['items'];
|
||||||
(ward) => ward.districtCode == districtCode,
|
if (items.isNotEmpty) {
|
||||||
orElse: () => Ward(name: "null"),
|
List<Ward> wards = Ward.fromJsonDynamicList(items);
|
||||||
);
|
if (wards.isNotEmpty) {
|
||||||
});
|
for (var ward in wards) {
|
||||||
|
if (ward.districtCode == districtCode) {
|
||||||
|
return ward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ward(name: "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateDevice(
|
Future<void> updateDevice(
|
||||||
@@ -362,50 +232,24 @@ class DeviceUpdateBloc extends BlocBase {
|
|||||||
String districtCode,
|
String districtCode,
|
||||||
String wardCode,
|
String wardCode,
|
||||||
) async {
|
) async {
|
||||||
await apiServices.execute(context, () async {
|
DateTime dateTime = DateTime.now();
|
||||||
DateTime dateTime = DateTime.now();
|
String formattedDateTime =
|
||||||
String formattedDateTime =
|
DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
||||||
DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
Map<String, dynamic> body = {
|
||||||
Map<String, dynamic> body = {
|
"name": name,
|
||||||
"name": name,
|
"area_province": provinceCode,
|
||||||
"area_province": provinceCode,
|
"area_district": districtCode,
|
||||||
"area_district": districtCode,
|
"area_ward": wardCode,
|
||||||
"area_ward": wardCode,
|
"latitude": latitude,
|
||||||
"latitude": latitude,
|
"longitude": longitude,
|
||||||
"longitude": longitude,
|
"note": "User updated device infomation at $formattedDateTime",
|
||||||
"note": "User updated device infomation at $formattedDateTime",
|
};
|
||||||
};
|
int statusCode = await apiServices.updateOwnerDevice(thingID, body);
|
||||||
int statusCode = await apiServices.updateOwnerDevice(thingID, body);
|
showSnackBarResponseByStatusCodeNoIcon(
|
||||||
showSnackBarResponseByStatusCodeNoIcon(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_update_device_success,
|
||||||
appLocalization(context).notification_update_device_success,
|
appLocalization(context).notification_update_device_failed,
|
||||||
appLocalization(context).notification_update_device_failed,
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// DateTime dateTime = DateTime.now();
|
|
||||||
// String formattedDateTime =
|
|
||||||
// DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
|
||||||
// Map<String, dynamic> body = {
|
|
||||||
// "name": name,
|
|
||||||
// "area_province": provinceCode,
|
|
||||||
// "area_district": districtCode,
|
|
||||||
// "area_ward": wardCode,
|
|
||||||
// "latitude": latitude,
|
|
||||||
// "longitude": longitude,
|
|
||||||
// "note": "User updated device infomation at $formattedDateTime",
|
|
||||||
// };
|
|
||||||
// int statusCode = await apiServices.updateOwnerDevice(thingID, body);
|
|
||||||
// showSnackBarResponseByStatusCodeNoIcon(
|
|
||||||
// context,
|
|
||||||
// statusCode,
|
|
||||||
// appLocalization(context).notification_update_device_success,
|
|
||||||
// appLocalization(context).notification_update_device_failed,
|
|
||||||
// );
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'dart:convert';
|
||||||
|
|
||||||
import '../feature/devices/device_model.dart';
|
import '../feature/devices/device_model.dart';
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/constant/app/app_constants.dart';
|
import '../product/constant/app/app_constants.dart';
|
||||||
import '../product/services/api_services.dart';
|
import '../product/services/api_services.dart';
|
||||||
import '../product/shared/shared_snack_bar.dart';
|
|
||||||
import '../product/utils/device_utils.dart';
|
import '../product/utils/device_utils.dart';
|
||||||
|
|
||||||
class DevicesManagerBloc extends BlocBase {
|
class DevicesManagerBloc extends BlocBase {
|
||||||
@@ -73,51 +73,46 @@ class DevicesManagerBloc extends BlocBase {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void getDeviceByState(BuildContext context, int state) async {
|
void getDeviceByState(int state) async {
|
||||||
try {
|
sinkTagStates.add([state]);
|
||||||
sinkTagStates.add([state]);
|
|
||||||
|
|
||||||
Map<String, List<Device>> deviceByState = {
|
Map<String, List<Device>> deviceByState = {
|
||||||
ApplicationConstants.OFFLINE_STATE: [],
|
ApplicationConstants.OFFLINE_STATE: [],
|
||||||
ApplicationConstants.NORMAL_STATE: [],
|
ApplicationConstants.NORMAL_STATE: [],
|
||||||
ApplicationConstants.WARNING_STATE: [],
|
ApplicationConstants.WARNING_STATE: [],
|
||||||
ApplicationConstants.INPROGRESS_STATE: [],
|
ApplicationConstants.INPROGRESS_STATE: [],
|
||||||
ApplicationConstants.ERROR_STATE: [],
|
ApplicationConstants.ERROR_STATE: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
List<Device> devices = [];
|
List<Device> devices = [];
|
||||||
List<Device> originalDevices = [];
|
String body;
|
||||||
if (state != -2) {
|
|
||||||
originalDevices = await apiServices
|
|
||||||
.getOwnerDeviceByState({"state": state.toString()});
|
|
||||||
} else {
|
|
||||||
originalDevices = await apiServices.getOwnerDevices();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Device> publicDevices = [];
|
if (state != -2) {
|
||||||
|
body =
|
||||||
|
await apiServices.getOwnerDeviceByState({"state": state.toString()});
|
||||||
|
} else {
|
||||||
|
body = await apiServices.getOwnerDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body.isNotEmpty) {
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
List<dynamic> items = data['items'];
|
||||||
|
List<Device> originalDevices = Device.fromJsonDynamicList(items);
|
||||||
|
|
||||||
for (var device in originalDevices) {
|
|
||||||
if (device.visibility == "PUBLIC") {
|
|
||||||
publicDevices.add(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
devices = (state != -2)
|
devices = (state != -2)
|
||||||
? DeviceUtils.instance.sortDeviceAZByName(publicDevices)
|
? DeviceUtils.instance.sortDeviceAZByName(originalDevices)
|
||||||
: DeviceUtils.instance.sortDeviceByState(publicDevices);
|
: DeviceUtils.instance.sortDeviceByState(originalDevices);
|
||||||
|
|
||||||
if (state == -2) {
|
if (state == -2) {
|
||||||
for (var device in publicDevices) {
|
for (var device in originalDevices) {
|
||||||
String stateKey = _getStateKey(device.state!);
|
String stateKey = _getStateKey(device.state!);
|
||||||
deviceByState[stateKey]!.add(device);
|
deviceByState[stateKey]!.add(device);
|
||||||
}
|
}
|
||||||
sinkDeviceByState.add(deviceByState);
|
sinkDeviceByState.add(deviceByState);
|
||||||
}
|
}
|
||||||
|
|
||||||
sinkAllDevices.add(devices);
|
|
||||||
} catch (e) {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sinkAllDevices.add(devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getStateKey(int state) {
|
String _getStateKey(int state) {
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import '../feature/devices/device_model.dart';
|
import '../feature/devices/device_model.dart';
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/services/api_services.dart';
|
import '../product/services/api_services.dart';
|
||||||
import '../product/services/language_services.dart';
|
import '../product/services/language_services.dart';
|
||||||
import '../product/utils/response_status_utils.dart';
|
import '../product/utils/response_status_utils.dart';
|
||||||
|
|
||||||
import '../feature/inter_family/group_detail/group_detail_model.dart';
|
import '../feature/inter_family/group_detail/group_detail_model.dart';
|
||||||
|
|
||||||
class DetailGroupBloc extends BlocBase {
|
class DetailGroupBloc extends BlocBase {
|
||||||
@@ -27,10 +29,12 @@ class DetailGroupBloc extends BlocBase {
|
|||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
|
|
||||||
Future<void> getGroupDetail(BuildContext context, String groupID) async {
|
Future<void> getGroupDetail(String groupID) async {
|
||||||
await apiServices.execute(context, () async {
|
final body = await apiServices.getGroupDetail(groupID);
|
||||||
List<DeviceOfGroup> warningDevices = [];
|
final data = jsonDecode(body);
|
||||||
GroupDetail group = await apiServices.getGroupDetail(groupID);
|
List<DeviceOfGroup> warningDevices = [];
|
||||||
|
if (data != null) {
|
||||||
|
GroupDetail group = GroupDetail.fromJson(data);
|
||||||
sinkDetailGroup.add(group);
|
sinkDetailGroup.add(group);
|
||||||
if (group.devices != null) {
|
if (group.devices != null) {
|
||||||
for (var device in group.devices!) {
|
for (var device in group.devices!) {
|
||||||
@@ -40,135 +44,62 @@ class DetailGroupBloc extends BlocBase {
|
|||||||
}
|
}
|
||||||
sinkWarningDevice.add(warningDevices);
|
sinkWarningDevice.add(warningDevices);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
// try {
|
|
||||||
// List<DeviceOfGroup> warningDevices = [];
|
|
||||||
// GroupDetail group = await apiServices.getGroupDetail(groupID);
|
|
||||||
// sinkDetailGroup.add(group);
|
|
||||||
// if (group.devices != null) {
|
|
||||||
// for (var device in group.devices!) {
|
|
||||||
// if (device.state == 1) {
|
|
||||||
// warningDevices.add(device);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// sinkWarningDevice.add(warningDevices);
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> approveUserToGroup(BuildContext context, String groupID,
|
Future<void> approveUserToGroup(BuildContext context, String groupID,
|
||||||
String userID, String userName) async {
|
String userID, String userName) async {
|
||||||
await apiServices.execute(context, () async {
|
Map<String, dynamic> body = {"group_id": groupID, "user_id": userID};
|
||||||
Map<String, dynamic> body = {"group_id": groupID, "user_id": userID};
|
int statusCode = await apiServices.approveGroup(body);
|
||||||
int statusCode = await apiServices.approveGroup(body);
|
showSnackBarResponseByStatusCode(context, statusCode,
|
||||||
showSnackBarResponseByStatusCode(context, statusCode,
|
"Đã duyệt $userName vào nhóm!", "Duyệt $userName thất bại!");
|
||||||
"Đã duyệt $userName vào nhóm!", "Duyệt $userName thất bại!");
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// Map<String, dynamic> body = {"group_id": groupID, "user_id": userID};
|
|
||||||
// int statusCode = await apiServices.approveGroup(body);
|
|
||||||
// showSnackBarResponseByStatusCode(context, statusCode,
|
|
||||||
// "Đã duyệt $userName vào nhóm!", "Duyệt $userName thất bại!");
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteOrUnapproveUser(BuildContext context, String groupID,
|
Future<void> deleteOrUnapproveUser(BuildContext context, String groupID,
|
||||||
String userID, String userName) async {
|
String userID, String userName) async {
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
||||||
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
showSnackBarResponseByStatusCode(context, statusCode,
|
||||||
showSnackBarResponseByStatusCode(context, statusCode,
|
"Đã xóa người dùng $userName", "Xóa người dùng $userName thất bại");
|
||||||
"Đã xóa người dùng $userName", "Xóa người dùng $userName thất bại");
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
|
||||||
// showSnackBarResponseByStatusCode(context, statusCode,
|
|
||||||
// "Đã xóa người dùng $userName", "Xóa người dùng $userName thất bại");
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteDevice(BuildContext context, String groupID,
|
Future<void> deleteDevice(BuildContext context, String groupID,
|
||||||
String thingID, String deviceName) async {
|
String thingID, String deviceName) async {
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.deleteDeviceInGroup(groupID, thingID);
|
||||||
int statusCode = await apiServices.deleteDeviceInGroup(groupID, thingID);
|
showSnackBarResponseByStatusCode(context, statusCode,
|
||||||
showSnackBarResponseByStatusCode(context, statusCode,
|
"Đã xóa thiết bị $deviceName", "Xóa thiết bị $deviceName thất bại");
|
||||||
"Đã xóa thiết bị $deviceName", "Xóa thiết bị $deviceName thất bại");
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// int statusCode = await apiServices.deleteDeviceInGroup(groupID, thingID);
|
|
||||||
// showSnackBarResponseByStatusCode(context, statusCode,
|
|
||||||
// "Đã xóa thiết bị $deviceName", "Xóa thiết bị $deviceName thất bại");
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> leaveGroup(
|
Future<void> leaveGroup(
|
||||||
BuildContext context, String groupID, String userID) async {
|
BuildContext context, String groupID, String userID) async {
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
||||||
int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_leave_group_success,
|
||||||
appLocalization(context).notification_leave_group_success,
|
appLocalization(context).notification_leave_group_failed);
|
||||||
appLocalization(context).notification_leave_group_failed);
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// int statusCode = await apiServices.deleteUserInGroup(groupID, userID);
|
|
||||||
// showSnackBarResponseByStatusCode(
|
|
||||||
// context,
|
|
||||||
// statusCode,
|
|
||||||
// appLocalization(context).notification_leave_group_success,
|
|
||||||
// appLocalization(context).notification_leave_group_failed);
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateDeviceNameInGroup(
|
Future<void> updateDeviceNameInGroup(
|
||||||
BuildContext context, String thingID, String newAlias) async {
|
BuildContext context, String thingID, String newAlias) async {
|
||||||
await apiServices.execute(context, () async {
|
Map<String, dynamic> body = {"thing_id": thingID, "alias": newAlias};
|
||||||
Map<String, dynamic> body = {"thing_id": thingID, "alias": newAlias};
|
int statusCode = await apiServices.updateDeviceAlias(body);
|
||||||
int statusCode = await apiServices.updateDeviceAlias(body);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_update_device_success,
|
||||||
appLocalization(context).notification_update_device_success,
|
appLocalization(context).notification_update_device_failed,
|
||||||
appLocalization(context).notification_update_device_failed,
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// Map<String, dynamic> body = {"thing_id": thingID, "alias": newAlias};
|
|
||||||
// int statusCode = await apiServices.updateDeviceAlias(body);
|
|
||||||
// showSnackBarResponseByStatusCode(
|
|
||||||
// context,
|
|
||||||
// statusCode,
|
|
||||||
// appLocalization(context).notification_update_device_success,
|
|
||||||
// appLocalization(context).notification_update_device_failed,
|
|
||||||
// );
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Device>> getOwnerDevices(BuildContext context) {
|
Future<List<Device>> getOwnerDevices() async {
|
||||||
return apiServices.execute(context, () async {
|
List<Device> allDevices = [];
|
||||||
final originalDevices = await apiServices.getOwnerDevices();
|
String body = await apiServices.getOwnerDevices();
|
||||||
return originalDevices
|
if (body != "") {
|
||||||
.where((device) => device.visibility == "PUBLIC")
|
final data = jsonDecode(body);
|
||||||
.toList();
|
List<dynamic> items = data['items'];
|
||||||
});
|
allDevices = Device.fromJsonDynamicList(items);
|
||||||
|
}
|
||||||
|
return allDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addDeviceToGroup(
|
Future<void> addDeviceToGroup(
|
||||||
@@ -176,26 +107,12 @@ class DetailGroupBloc extends BlocBase {
|
|||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"thing_id": thingID,
|
"thing_id": thingID,
|
||||||
};
|
};
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.addDeviceToGroup(groupID, body);
|
||||||
int statusCode = await apiServices.addDeviceToGroup(groupID, body);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_add_device_success,
|
||||||
appLocalization(context).notification_add_device_success,
|
appLocalization(context).notification_add_device_failed,
|
||||||
appLocalization(context).notification_add_device_failed,
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// int statusCode = await apiServices.addDeviceToGroup(groupID, body);
|
|
||||||
// showSnackBarResponseByStatusCode(
|
|
||||||
// context,
|
|
||||||
// statusCode,
|
|
||||||
// appLocalization(context).notification_add_device_success,
|
|
||||||
// appLocalization(context).notification_add_device_failed,
|
|
||||||
// );
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +1,34 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../product/extension/context_extension.dart';
|
|
||||||
import '../product/services/api_services.dart';
|
|
||||||
import '../feature/home/device_alias_model.dart';
|
import '../feature/home/device_alias_model.dart';
|
||||||
|
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/services/language_services.dart';
|
|
||||||
import '../product/utils/device_utils.dart';
|
|
||||||
|
|
||||||
class HomeBloc extends BlocBase {
|
class HomeBloc extends BlocBase {
|
||||||
APIServices apiServices = APIServices();
|
|
||||||
|
|
||||||
final allDevicesAliasMap =
|
final allDevicesAliasMap = StreamController<Map<String,List<DeviceWithAlias>>>.broadcast();
|
||||||
StreamController<Map<String, List<DeviceWithAlias>>?>.broadcast();
|
StreamSink<Map<String,List<DeviceWithAlias>>> get sinkAllDevicesAliasMap =>
|
||||||
StreamSink<Map<String, List<DeviceWithAlias>>?> get sinkAllDevicesAliasMap =>
|
|
||||||
allDevicesAliasMap.sink;
|
allDevicesAliasMap.sink;
|
||||||
Stream<Map<String, List<DeviceWithAlias>>?> get streamAllDevicesAliasMap =>
|
Stream<Map<String,List<DeviceWithAlias>>> get streamAllDevicesAliasMap =>
|
||||||
allDevicesAliasMap.stream;
|
allDevicesAliasMap.stream;
|
||||||
|
|
||||||
// final allDevicesAliasJoinedMap =
|
final allDevicesAliasJoinedMap = StreamController<Map<String,List<DeviceWithAlias>>>.broadcast();
|
||||||
// StreamController<Map<String, List<DeviceWithAlias>>>.broadcast();
|
StreamSink<Map<String,List<DeviceWithAlias>>> get sinkAllDevicesAliasJoinedMap =>
|
||||||
// StreamSink<Map<String, List<DeviceWithAlias>>>
|
allDevicesAliasJoinedMap.sink;
|
||||||
// get sinkAllDevicesAliasJoinedMap => allDevicesAliasJoinedMap.sink;
|
Stream<Map<String,List<DeviceWithAlias>>> get streamAllDevicesAliasJoinedMap =>
|
||||||
// Stream<Map<String, List<DeviceWithAlias>>>
|
allDevicesAliasJoinedMap.stream;
|
||||||
// get streamAllDevicesAliasJoinedMap => allDevicesAliasJoinedMap.stream;
|
|
||||||
|
|
||||||
final countNotification = StreamController<int>.broadcast();
|
final countNotification = StreamController<int>.broadcast();
|
||||||
StreamSink<int> get sinkCountNotification => countNotification.sink;
|
StreamSink<int> get sinkCountNotification => countNotification.sink;
|
||||||
Stream<int> get streamCountNotification => countNotification.stream;
|
Stream<int> get streamCountNotification => countNotification.stream;
|
||||||
|
|
||||||
final hasJoinedDevice = StreamController<bool?>.broadcast();
|
final ownerDevicesStatus =
|
||||||
StreamSink<bool?> get sinkHasJoinedDevice => hasJoinedDevice.sink;
|
|
||||||
Stream<bool?> get streamHasJoinedDevice => hasJoinedDevice.stream;
|
|
||||||
|
|
||||||
final ownerDevicesStatus =
|
|
||||||
StreamController<Map<String, List<DeviceWithAlias>>>.broadcast();
|
StreamController<Map<String, List<DeviceWithAlias>>>.broadcast();
|
||||||
StreamSink<Map<String, List<DeviceWithAlias>>> get sinkOwnerDevicesStatus =>
|
StreamSink<Map<String, List<DeviceWithAlias>>>
|
||||||
ownerDevicesStatus.sink;
|
get sinkOwnerDevicesStatus => ownerDevicesStatus.sink;
|
||||||
Stream<Map<String, List<DeviceWithAlias>>> get streamOwnerDevicesStatus =>
|
Stream<Map<String, List<DeviceWithAlias>>> get streamOwnerDevicesStatus =>
|
||||||
ownerDevicesStatus.stream;
|
ownerDevicesStatus.stream;
|
||||||
|
|
||||||
|
|
||||||
final aliasDevices = StreamController<List<DeviceWithAlias>?>.broadcast();
|
|
||||||
StreamSink<List<DeviceWithAlias>?> get sinkAliasDevices => aliasDevices.sink;
|
|
||||||
Stream<List<DeviceWithAlias>?> get streamAliasDevices => aliasDevices.stream;
|
|
||||||
|
|
||||||
void getOwnerAndJoinedDevices(BuildContext context) async {
|
|
||||||
await apiServices.execute(context, () async {
|
|
||||||
List<DeviceWithAlias> devices = await apiServices.getDashBoardDevices().handleApiError();
|
|
||||||
List<DeviceWithAlias> publicDevices = [];
|
|
||||||
for (var device in devices) {
|
|
||||||
if (device.visibility == "PUBLIC") {
|
|
||||||
publicDevices.add(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// getDeviceStatusAliasMap(publicDevices);
|
|
||||||
sinkAllDevicesAliasMap.add(null);
|
|
||||||
sinkAliasDevices.add(publicDevices);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
getOwnerDeviceState(context, publicDevices);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void getOwnerDeviceState(BuildContext context,List<DeviceWithAlias> allDevices) async {
|
|
||||||
// int notificationCount = 0;
|
|
||||||
Map<String, List<DeviceWithAlias>> ownerDevicesStatus = {};
|
|
||||||
|
|
||||||
if (!context.mounted) return;
|
|
||||||
sinkOwnerDevicesStatus.add(ownerDevicesStatus);
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
for (var device in allDevices) {
|
|
||||||
// if (device.isOwner != true) continue;
|
|
||||||
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Map<String, dynamic> sensorMap = DeviceUtils.instance
|
|
||||||
.getDeviceSensors(context, device.status?.sensors ?? []);
|
|
||||||
|
|
||||||
if (device.state == 1 || device.state == 3) {
|
|
||||||
ownerDevicesStatus["state"] ??= [];
|
|
||||||
ownerDevicesStatus["state"]!.add(device);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
sinkOwnerDevicesStatus.add(ownerDevicesStatus);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
final noDataMessage = appLocalization(context).no_data_message;
|
|
||||||
if (sensorMap['sensorBattery'] != noDataMessage) {
|
|
||||||
if (double.parse(sensorMap['sensorBattery']) <= 20) {
|
|
||||||
ownerDevicesStatus['battery'] ??= [];
|
|
||||||
ownerDevicesStatus['battery']!.add(device);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
sinkOwnerDevicesStatus.add(ownerDevicesStatus);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!context.mounted) return;
|
|
||||||
sinkCountNotification.add(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void getDeviceStatusAliasMap(List<DeviceWithAlias> devices) {
|
|
||||||
Map<String, List<DeviceWithAlias>> allDevicesAliasMap = {};
|
|
||||||
for (var key in ['all', 'online', 'offline', 'warning', 'not-use']) {
|
|
||||||
allDevicesAliasMap[key] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (DeviceWithAlias device in devices) {
|
|
||||||
allDevicesAliasMap['all']!.add(device);
|
|
||||||
if (device.state == 0 || device.state == 1) {
|
|
||||||
allDevicesAliasMap['online']!.add(device);
|
|
||||||
}
|
|
||||||
if (device.state == -1) {
|
|
||||||
allDevicesAliasMap['offline']!.add(device);
|
|
||||||
}
|
|
||||||
if (device.state == 1) {
|
|
||||||
allDevicesAliasMap['warning']!.add(device);
|
|
||||||
}
|
|
||||||
if (device.state == -2) {
|
|
||||||
allDevicesAliasMap['not-use']!.add(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
sinkAllDevicesAliasMap.add(allDevicesAliasMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {}
|
||||||
allDevicesAliasMap.close();
|
|
||||||
// allDevicesAliasJoinedMap.close();
|
|
||||||
countNotification.close();
|
|
||||||
hasJoinedDevice.close();
|
|
||||||
ownerDevicesStatus.close();
|
|
||||||
aliasDevices.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import '../product/constant/app/app_constants.dart';
|
import '../product/constant/app/app_constants.dart';
|
||||||
|
|
||||||
import '../product/services/api_services.dart';
|
import '../product/services/api_services.dart';
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/services/language_services.dart';
|
import '../product/services/language_services.dart';
|
||||||
@@ -32,78 +35,82 @@ class InterFamilyBloc extends BlocBase {
|
|||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
|
|
||||||
void getAllGroup(BuildContext context, String role) async {
|
void getAllGroup(String role) async {
|
||||||
List<Group> groups = [];
|
List<Group> groups = [];
|
||||||
sinkCurrentGroups.add(groups);
|
sinkCurrentGroups.add(groups);
|
||||||
await apiServices.execute(context, () async {
|
final body = await apiServices.getAllGroups();
|
||||||
groups = await apiServices.getAllGroups();
|
|
||||||
|
if (body.isNotEmpty) {
|
||||||
|
final data = jsonDecode(body);
|
||||||
|
List<dynamic> items = data["items"];
|
||||||
|
groups = Group.fromJsonDynamicList(items);
|
||||||
groups = sortGroupByName(groups);
|
groups = sortGroupByName(groups);
|
||||||
|
|
||||||
List<Group> currentGroups = groups.where(
|
List<Group> currentGroups = groups.where(
|
||||||
(group) {
|
(group) {
|
||||||
bool isPublic = group.visibility == "PUBLIC";
|
bool isPublic = group.visibility == "PUBLIC";
|
||||||
|
|
||||||
if (role == ApplicationConstants.OWNER_GROUP) {
|
if (role == ApplicationConstants.OWNER_GROUP) {
|
||||||
return group.isOwner == true && isPublic;
|
return group.isOwner == true && isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == ApplicationConstants.PARTICIPANT_GROUP) {
|
if (role == ApplicationConstants.PARTICIPANT_GROUP) {
|
||||||
return group.isOwner == null && isPublic;
|
return group.isOwner == null && isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
).toList();
|
).toList();
|
||||||
|
|
||||||
sinkCurrentGroups.add(currentGroups);
|
sinkCurrentGroups.add(currentGroups);
|
||||||
});
|
} else {
|
||||||
|
log("Get groups from API failed");
|
||||||
|
}
|
||||||
|
log("Inter Family Role: $role");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createGroup(
|
Future<void> createGroup(
|
||||||
BuildContext context, String name, String description) async {
|
BuildContext context, String name, String description) async {
|
||||||
await apiServices.execute(context, () async {
|
APIServices apiServices = APIServices();
|
||||||
Map<String, dynamic> body = {"name": name, "description": description};
|
Map<String, dynamic> body = {"name": name, "description": description};
|
||||||
int? statusCode = await apiServices.createGroup(body);
|
int? statusCode = await apiServices.createGroup(body);
|
||||||
showSnackBarResponseByStatusCode(
|
showSnackBarResponseByStatusCode(
|
||||||
context,
|
context,
|
||||||
statusCode,
|
statusCode,
|
||||||
appLocalization(context).notification_add_group_success,
|
appLocalization(context).notification_add_group_success,
|
||||||
appLocalization(context).notification_add_group_failed);
|
appLocalization(context).notification_add_group_failed);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> changeGroupInformation(BuildContext context, String groupID,
|
Future<void> changeGroupInfomation(BuildContext context, String groupID,
|
||||||
String name, String description) async {
|
String name, String description) async {
|
||||||
await apiServices.execute(context, () async {
|
Map<String, dynamic> body = {"name": name, "description": description};
|
||||||
Map<String, dynamic> body = {"name": name, "description": description};
|
int statusCode = await apiServices.updateGroup(body, groupID);
|
||||||
int statusCode = await apiServices.updateGroup(body, groupID);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_update_group_success,
|
||||||
appLocalization(context).notification_update_group_success,
|
appLocalization(context).notification_update_group_failed);
|
||||||
appLocalization(context).notification_update_group_failed);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> joinGroup(BuildContext context, String groupID) async {
|
Future<void> joinGroup(BuildContext context, String groupID) async {
|
||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"group_id": groupID,
|
"group_id": groupID,
|
||||||
};
|
};
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.joinGroup(groupID, body);
|
||||||
int statusCode = await apiServices.joinGroup(groupID, body);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_join_request_group_success,
|
||||||
appLocalization(context).notification_join_request_group_success,
|
appLocalization(context).notification_join_request_group_failed);
|
||||||
appLocalization(context).notification_join_request_group_failed);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteGroup(BuildContext context, String groupID) async {
|
Future<void> deleteGroup(BuildContext context, String groupID) async {
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.deleteGroup(groupID);
|
||||||
int statusCode = await apiServices.deleteGroup(groupID);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_delete_group_success,
|
||||||
appLocalization(context).notification_delete_group_success,
|
appLocalization(context).notification_delete_group_failed);
|
||||||
appLocalization(context).notification_delete_group_failed);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Group> sortGroupByName(List<Group> groups) {
|
List<Group> sortGroupByName(List<Group> groups) {
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
|
|
||||||
class LoginBloc extends BlocBase {
|
class LoginBloc extends BlocBase{
|
||||||
final loginRequest = StreamController<Map<String, dynamic>>.broadcast();
|
|
||||||
StreamSink<Map<String, dynamic>> get sinkLoginRequest => loginRequest.sink;
|
final loginRequest = StreamController<Map<String,dynamic>>.broadcast();
|
||||||
Stream<Map<String, dynamic>> get streamLoginRequest => loginRequest.stream;
|
StreamSink<Map<String,dynamic>> get sinkLoginRequest => loginRequest.sink;
|
||||||
|
Stream<Map<String,dynamic>> get streamLoginRequest => loginRequest.stream;
|
||||||
|
|
||||||
final isShowPassword = StreamController<bool>.broadcast();
|
final isShowPassword = StreamController<bool>.broadcast();
|
||||||
StreamSink<bool> get sinkIsShowPassword => isShowPassword.sink;
|
StreamSink<bool> get sinkIsShowPassword => isShowPassword.sink;
|
||||||
Stream<bool> get streamIsShowPassword => isShowPassword.stream;
|
Stream<bool> get streamIsShowPassword => isShowPassword.stream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/product/cache/local_manager.dart';
|
||||||
import '../product/cache/local_manager.dart';
|
import 'package:sfm_app/product/constant/app/api_path_constant.dart';
|
||||||
import '../product/constant/app/api_path_constant.dart';
|
import 'package:sfm_app/product/constant/enums/local_keys_enums.dart';
|
||||||
import '../product/constant/enums/local_keys_enums.dart';
|
import 'package:sfm_app/product/network/network_manager.dart';
|
||||||
import '../product/network/network_manager.dart';
|
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
import '../product/services/api_services.dart';
|
import '../product/services/api_services.dart';
|
||||||
import '../feature/bell/bell_model.dart';
|
import '../feature/bell/bell_model.dart';
|
||||||
@@ -41,14 +42,14 @@ class MainBloc extends BlocBase {
|
|||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
|
|
||||||
void getUserProfile(BuildContext context) async {
|
void getUserProfile() async {
|
||||||
await apiServices.execute(context, () async {
|
String data = await apiServices.getUserDetail();
|
||||||
User user = await apiServices.getUserDetail();
|
User user = User.fromJson(jsonDecode(data));
|
||||||
sinkUserProfile.add(user);
|
sinkUserProfile.add(user);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFCMTokenAndPresentations() async {
|
getFCMTokenAndPresentations() async {
|
||||||
|
|
||||||
String? firebaseAppToken = await FirebaseMessaging.instance.getToken();
|
String? firebaseAppToken = await FirebaseMessaging.instance.getToken();
|
||||||
|
|
||||||
if (firebaseAppToken != null) {
|
if (firebaseAppToken != null) {
|
||||||
@@ -59,11 +60,14 @@ class MainBloc extends BlocBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> sendNotificationToken(String token) async {
|
Future<int> sendNotificationToken(String token) async{
|
||||||
String uid = await getUID();
|
String uid = await getUID();
|
||||||
Map<String, dynamic> body = {"user_id": uid, "app_token": token};
|
Map<String,dynamic> body = {
|
||||||
int statusCode = await NetworkManager.instance!
|
"user_id": uid,
|
||||||
.updateDataInServer(APIPathConstants.NOTIFICATION_TOKEN_PATH, body);
|
"app_token": token
|
||||||
|
};
|
||||||
|
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
|
APIPathConstants.NOTIFICATION_TOKEN_PATH, body);
|
||||||
return statusCode;
|
return statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
|
|
||||||
import '../product/services/map_services.dart';
|
import '../product/services/map_services.dart';
|
||||||
import '../product/shared/shared_snack_bar.dart';
|
import '../product/shared/shared_snack_bar.dart';
|
||||||
import '../feature/devices/device_model.dart';
|
import '../feature/devices/device_model.dart';
|
||||||
@@ -75,4 +75,6 @@ class MapBloc extends BlocBase {
|
|||||||
context, "Không tìm thấy đường", Colors.orange, Colors.white);
|
context, "Không tìm thấy đường", Colors.orange, Colors.white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
|
|
||||||
import '../product/services/api_services.dart';
|
|
||||||
import '../feature/settings/profile/profile_model.dart';
|
import '../feature/settings/profile/profile_model.dart';
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
import '../product/base/bloc/base_bloc.dart';
|
||||||
|
|
||||||
class SettingsBloc extends BlocBase {
|
class SettingsBloc extends BlocBase {
|
||||||
// Settings Screen
|
// Settings Screen
|
||||||
APIServices apiServices = APIServices();
|
|
||||||
final userProfile = StreamController<User>.broadcast();
|
final userProfile = StreamController<User>.broadcast();
|
||||||
StreamSink<User> get sinkUserProfile => userProfile.sink;
|
StreamSink<User> get sinkUserProfile => userProfile.sink;
|
||||||
Stream<User> get streamUserProfile => userProfile.stream;
|
Stream<User> get streamUserProfile => userProfile.stream;
|
||||||
|
|
||||||
|
|
||||||
// Profile Screen
|
// Profile Screen
|
||||||
final isChangeProfileInfomation = StreamController<bool>.broadcast();
|
final isChangeProfileInfomation = StreamController<bool>.broadcast();
|
||||||
StreamSink<bool> get sinkIsChangeProfileInfomation =>
|
StreamSink<bool> get sinkIsChangeProfileInfomation =>
|
||||||
@@ -19,13 +17,9 @@ class SettingsBloc extends BlocBase {
|
|||||||
Stream<bool> get streamIsChangeProfileInfomation =>
|
Stream<bool> get streamIsChangeProfileInfomation =>
|
||||||
isChangeProfileInfomation.stream;
|
isChangeProfileInfomation.stream;
|
||||||
|
|
||||||
void getUserProfile(BuildContext context) async {
|
|
||||||
await apiServices.execute(context, () async {
|
|
||||||
User user = await apiServices.getUserDetail();
|
|
||||||
sinkUserProfile.add(user);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {}
|
void dispose() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../product/services/api_services.dart';
|
|
||||||
import '../feature/devices/device_model.dart';
|
|
||||||
import '../product/base/bloc/base_bloc.dart';
|
|
||||||
|
|
||||||
class SimDataBloc extends BlocBase{
|
|
||||||
|
|
||||||
APIServices apiServices = APIServices();
|
|
||||||
|
|
||||||
final devices = StreamController<List<Device>>.broadcast();
|
|
||||||
StreamSink<List<Device>> get sinkDevices => devices.sink;
|
|
||||||
Stream<List<Device>> get streamDevices => devices.stream;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {}
|
|
||||||
|
|
||||||
void getOwnerDevices(BuildContext context) async {
|
|
||||||
await apiServices.execute(context, () async {
|
|
||||||
List<Device> devices = [];
|
|
||||||
devices = await apiServices.getOwnerDevices();
|
|
||||||
|
|
||||||
List<Device> publicDevices = [];
|
|
||||||
for (var device in devices) {
|
|
||||||
if (device.visibility == "PUBLIC") {
|
|
||||||
publicDevices.add(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sinkDevices.add(publicDevices);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../product/extension/context_extension.dart';
|
||||||
import '../../product/services/language_services.dart';
|
import '../../product/services/language_services.dart';
|
||||||
import '../../bloc/bell_bloc.dart';
|
import '../../bloc/bell_bloc.dart';
|
||||||
import '../../product/base/bloc/base_bloc.dart';
|
import '../../product/base/bloc/base_bloc.dart';
|
||||||
import '../../product/services/api_services.dart';
|
import '../../product/services/api_services.dart';
|
||||||
import '../../product/shared/shared_component_loading_animation.dart';
|
|
||||||
import '../../product/shared/shared_loading_animation.dart';
|
|
||||||
import 'bell_model.dart';
|
import 'bell_model.dart';
|
||||||
|
|
||||||
class BellScreen extends StatefulWidget {
|
class BellScreen extends StatefulWidget {
|
||||||
@@ -57,7 +56,11 @@ class _BellScreenState extends State<BellScreen> {
|
|||||||
initialData: items,
|
initialData: items,
|
||||||
builder: (context, bellSnapshot) {
|
builder: (context, bellSnapshot) {
|
||||||
return check
|
return check
|
||||||
? const SharedLoadingAnimation()
|
? Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
value: context.highValue,
|
||||||
|
),
|
||||||
|
)
|
||||||
: bellSnapshot.data?.isEmpty ?? true
|
: bellSnapshot.data?.isEmpty ?? true
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -75,8 +78,16 @@ class _BellScreenState extends State<BellScreen> {
|
|||||||
if (index < bellSnapshot.data!.length) {
|
if (index < bellSnapshot.data!.length) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
readNotification(
|
List<String> read = [];
|
||||||
bellSnapshot.data![index].id!);
|
read.add(bellSnapshot.data![index].id!);
|
||||||
|
int code = await apiServices
|
||||||
|
.updateStatusOfNotification(read);
|
||||||
|
if (code == 200) {
|
||||||
|
read.clear();
|
||||||
|
} else {
|
||||||
|
read.clear();
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -132,7 +143,7 @@ class _BellScreenState extends State<BellScreen> {
|
|||||||
builder: (context, hasMoreSnapshot) {
|
builder: (context, hasMoreSnapshot) {
|
||||||
return Center(
|
return Center(
|
||||||
child: hasMoreSnapshot.data ?? hasMore
|
child: hasMoreSnapshot.data ?? hasMore
|
||||||
? const SharedComponentLoadingAnimation()
|
? const CircularProgressIndicator()
|
||||||
: Text(
|
: Text(
|
||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
.bell_read_all,
|
.bell_read_all,
|
||||||
@@ -162,31 +173,20 @@ class _BellScreenState extends State<BellScreen> {
|
|||||||
getBellNotification(offset);
|
getBellNotification(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readNotification(String id) async {
|
|
||||||
await apiServices.execute(context, () async {
|
|
||||||
List<String> read = [];
|
|
||||||
read.add(id);
|
|
||||||
await apiServices.updateStatusOfNotification(read);
|
|
||||||
read.clear();
|
|
||||||
});
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> getBellNotification(int offset) async {
|
Future<void> getBellNotification(int offset) async {
|
||||||
apiServices.execute(context, () async {
|
bell = await apiServices.getBellNotifications(
|
||||||
bell = await apiServices.getBellNotifications(
|
offset.toString(), (offset + 20).toString());
|
||||||
offset.toString(), (offset + 20).toString());
|
|
||||||
if (bell.items!.isEmpty) {
|
if (bell.items!.isEmpty) {
|
||||||
hasMore = false;
|
hasMore = false;
|
||||||
bellBloc.sinkHasMore.add(hasMore);
|
bellBloc.sinkHasMore.add(hasMore);
|
||||||
} else {
|
} else {
|
||||||
for (var item in bell.items!) {
|
for (var item in bell.items!) {
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bellBloc.bellItems.add(items);
|
}
|
||||||
check = false;
|
bellBloc.bellItems.add(items);
|
||||||
});
|
check = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String timeAgo(BuildContext context, DateTime dateTime) {
|
String timeAgo(BuildContext context, DateTime dateTime) {
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
|
|
||||||
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 '../../product/shared/shared_component_loading_animation.dart';
|
|
||||||
import '../../product/shared/shared_loading_animation.dart';
|
|
||||||
import 'widgets/tag_widget.dart';
|
import 'widgets/tag_widget.dart';
|
||||||
import '../devices/device_model.dart';
|
import '../devices/device_model.dart';
|
||||||
import '../../bloc/device_logs_bloc.dart';
|
import '../../bloc/device_logs_bloc.dart';
|
||||||
@@ -15,6 +12,7 @@ import '../../product/services/language_services.dart';
|
|||||||
import '../../product/shared/shared_snack_bar.dart';
|
import '../../product/shared/shared_snack_bar.dart';
|
||||||
import '../../product/utils/date_time_utils.dart';
|
import '../../product/utils/date_time_utils.dart';
|
||||||
import '../../product/utils/device_utils.dart';
|
import '../../product/utils/device_utils.dart';
|
||||||
|
|
||||||
import '../../product/base/bloc/base_bloc.dart';
|
import '../../product/base/bloc/base_bloc.dart';
|
||||||
import 'device_logs_model.dart';
|
import 'device_logs_model.dart';
|
||||||
|
|
||||||
@@ -44,7 +42,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
() {
|
() {
|
||||||
if (controller.position.maxScrollExtent == controller.offset) {
|
if (controller.position.maxScrollExtent == controller.offset) {
|
||||||
offset += 30;
|
offset += 30;
|
||||||
deviceLogsBloc.getDeviceLogByThingID(context,
|
deviceLogsBloc.getDeviceLogByThingID(
|
||||||
offset, thingID, dateTime!, sensors);
|
offset, thingID, dateTime!, sensors);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -65,9 +63,11 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
body: StreamBuilder<List<Device>>(
|
body: StreamBuilder<List<Device>>(
|
||||||
stream: deviceLogsBloc.streamAllDevices,
|
stream: deviceLogsBloc.streamAllDevices,
|
||||||
builder: (context, allDevicesSnapshot) {
|
builder: (context, allDevicesSnapshot) {
|
||||||
if (allDevicesSnapshot.data == null) {
|
if (allDevicesSnapshot.data?[0].thingId == null) {
|
||||||
deviceLogsBloc.getAllDevices(context);
|
deviceLogsBloc.getAllDevices();
|
||||||
return const SharedLoadingAnimation();
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return StreamBuilder<List<SensorLogs>>(
|
return StreamBuilder<List<SensorLogs>>(
|
||||||
stream: deviceLogsBloc.streamSensors,
|
stream: deviceLogsBloc.streamSensors,
|
||||||
@@ -90,7 +90,9 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
hint: Text(
|
hint: Text(
|
||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
.choose_device_dropdownButton,
|
.choose_device_dropdownButton,
|
||||||
style: context.responsiveBodySmall
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
items: allDevicesSnapshot.data?.isNotEmpty ?? false
|
items: allDevicesSnapshot.data?.isNotEmpty ?? false
|
||||||
? allDevicesSnapshot.data!
|
? allDevicesSnapshot.data!
|
||||||
@@ -99,7 +101,9 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
value: device.thingId,
|
value: device.thingId,
|
||||||
child: Text(
|
child: Text(
|
||||||
device.name!,
|
device.name!,
|
||||||
style: context.responsiveBodySmall
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -188,7 +192,6 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
deviceLogsBloc.getDeviceLogByThingID(
|
deviceLogsBloc.getDeviceLogByThingID(
|
||||||
context,
|
|
||||||
offset,
|
offset,
|
||||||
thingID,
|
thingID,
|
||||||
dateTime!,
|
dateTime!,
|
||||||
@@ -247,7 +250,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
return Center(
|
return Center(
|
||||||
child: hasMoreSnapshot.data ??
|
child: hasMoreSnapshot.data ??
|
||||||
hasMore
|
hasMore
|
||||||
? const SharedComponentLoadingAnimation()
|
? const CircularProgressIndicator()
|
||||||
: Text(
|
: Text(
|
||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
.main_no_data),
|
.main_no_data),
|
||||||
@@ -311,7 +314,7 @@ class _DeviceLogsScreenState extends State<DeviceLogsScreen> {
|
|||||||
deviceLogsBloc.sensors.add(sensors);
|
deviceLogsBloc.sensors.add(sensors);
|
||||||
hasMore = true;
|
hasMore = true;
|
||||||
deviceLogsBloc.sinkHasMore.add(hasMore);
|
deviceLogsBloc.sinkHasMore.add(hasMore);
|
||||||
deviceLogsBloc.getDeviceLogByThingID(context,offset, thingID, dateTime!, sensors);
|
deviceLogsBloc.getDeviceLogByThingID(offset, thingID, dateTime!, sensors);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget leadingList(SensorLogs sensor) {
|
Widget leadingList(SensorLogs sensor) {
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/product/shared/shared_snack_bar.dart';
|
||||||
import '../../bloc/devices_manager_bloc.dart';
|
|
||||||
import '../../product/shared/shared_snack_bar.dart';
|
|
||||||
import '../../product/utils/response_status_utils.dart';
|
import '../../product/utils/response_status_utils.dart';
|
||||||
import '../../product/constant/enums/role_enums.dart';
|
import '../../product/constant/enums/role_enums.dart';
|
||||||
import '../../product/services/api_services.dart';
|
import '../../product/services/api_services.dart';
|
||||||
@@ -12,8 +10,7 @@ import '../../product/constant/icon/icon_constants.dart';
|
|||||||
import '../../product/extension/context_extension.dart';
|
import '../../product/extension/context_extension.dart';
|
||||||
import '../../product/services/language_services.dart';
|
import '../../product/services/language_services.dart';
|
||||||
|
|
||||||
addNewDevice(BuildContext context, String role,
|
addNewDevice(BuildContext context, String role) async {
|
||||||
DevicesManagerBloc deviceManagerBloc) async {
|
|
||||||
TextEditingController extIDController = TextEditingController(text: "");
|
TextEditingController extIDController = TextEditingController(text: "");
|
||||||
TextEditingController deviceNameController = TextEditingController(text: "");
|
TextEditingController deviceNameController = TextEditingController(text: "");
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@@ -28,7 +25,8 @@ addNewDevice(BuildContext context, String role,
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${appLocalization(context).add_device_title}: ',
|
'${appLocalization(context).add_device_title}: ',
|
||||||
style: context.responsiveBodyLargeWithBold,
|
style:
|
||||||
|
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
@@ -79,8 +77,7 @@ addNewDevice(BuildContext context, String role,
|
|||||||
Colors.white);
|
Colors.white);
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
} else {
|
} else {
|
||||||
addDevices(
|
addDevices(context, role, extID, deviceName);
|
||||||
context, role, extID, deviceName, deviceManagerBloc);
|
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -93,31 +90,25 @@ addNewDevice(BuildContext context, String role,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addDevices(BuildContext context, String role, String extID,
|
void addDevices(
|
||||||
String deviceName, DevicesManagerBloc deviceManagerBloc) async {
|
BuildContext context, String role, String extID, String deviceName) async {
|
||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
Map<String, dynamic> body = {};
|
Map<String, dynamic> body = {};
|
||||||
if (role == RoleEnums.ADMIN.name) {
|
if (role == RoleEnums.ADMIN.name) {
|
||||||
await apiServices.execute(context,() async {
|
body = {"ext_id": extID, "name": deviceName};
|
||||||
body = {"ext_id": extID, "name": deviceName};
|
int statusCode = await apiServices.createDeviceByAdmin(body);
|
||||||
int statusCode = await apiServices.createDeviceByAdmin(body);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_create_device_success,
|
||||||
appLocalization(context).notification_create_device_success,
|
appLocalization(context).notification_create_device_failed);
|
||||||
appLocalization(context).notification_create_device_failed);
|
|
||||||
deviceManagerBloc.getDeviceByState(context, -2);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
await apiServices.execute(context,() async {
|
body = {"ext_id": extID};
|
||||||
body = {"ext_id": extID};
|
int statusCode = await apiServices.registerDevice(body);
|
||||||
int statusCode = await apiServices.registerDevice(body);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_add_device_success,
|
||||||
appLocalization(context).notification_add_device_success,
|
appLocalization(context).notification_device_not_exist);
|
||||||
appLocalization(context).notification_device_not_exist);
|
|
||||||
deviceManagerBloc.getDeviceByState(context, -2);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../../bloc/devices_manager_bloc.dart';
|
import '../../bloc/devices_manager_bloc.dart';
|
||||||
import '../../product/constant/enums/role_enums.dart';
|
import '../../product/constant/enums/role_enums.dart';
|
||||||
import '../../product/services/api_services.dart';
|
import '../../product/services/api_services.dart';
|
||||||
@@ -48,24 +47,20 @@ deleteOrUnregisterDevice(BuildContext context, DevicesManagerBloc devicesBloc,
|
|||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"ext_id": extID,
|
"ext_id": extID,
|
||||||
};
|
};
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.unregisterDevice(body);
|
||||||
int statusCode = await apiServices.unregisterDevice(body);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_delete_device_success,
|
||||||
appLocalization(context).notification_delete_device_success,
|
appLocalization(context).notification_delete_device_failed);
|
||||||
appLocalization(context).notification_delete_device_failed);
|
devicesBloc.getDeviceByState(-2);
|
||||||
devicesBloc.getDeviceByState(context, -2);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.deleteDeviceByAdmin(extID);
|
||||||
int statusCode = await apiServices.deleteDeviceByAdmin(extID);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context).notification_delete_device_success,
|
||||||
appLocalization(context).notification_delete_device_success,
|
appLocalization(context).notification_delete_device_failed);
|
||||||
appLocalization(context).notification_delete_device_failed);
|
devicesBloc.getDeviceByState(-2);
|
||||||
devicesBloc.getDeviceByState(context, -2);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:search_choices/search_choices.dart';
|
import 'package:search_choices/search_choices.dart';
|
||||||
|
|
||||||
import '../../../product/shared/shared_loading_animation.dart';
|
|
||||||
import '../device_model.dart';
|
import '../device_model.dart';
|
||||||
import '../../../bloc/device_update_bloc.dart';
|
import '../../../bloc/device_update_bloc.dart';
|
||||||
import 'map_dialog.dart';
|
import 'map_dialog.dart';
|
||||||
@@ -9,6 +8,7 @@ import '../../../product/base/bloc/base_bloc.dart';
|
|||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/api_services.dart';
|
import '../../../product/services/api_services.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
import '../../../product/shared/model/district_model.dart';
|
import '../../../product/shared/model/district_model.dart';
|
||||||
import '../../../product/shared/model/province_model.dart';
|
import '../../../product/shared/model/province_model.dart';
|
||||||
import '../../../product/shared/model/ward_model.dart';
|
import '../../../product/shared/model/ward_model.dart';
|
||||||
@@ -47,7 +47,7 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
deviceUpdateBloc = BlocProvider.of(context);
|
deviceUpdateBloc = BlocProvider.of(context);
|
||||||
deviceUpdateBloc.getAllProvinces(context);
|
deviceUpdateBloc.getAllProvinces();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -72,16 +72,16 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
|||||||
initialData: device,
|
initialData: device,
|
||||||
builder: (context, deviceInfoSnapshot) {
|
builder: (context, deviceInfoSnapshot) {
|
||||||
if (deviceInfoSnapshot.data!.thingId == null) {
|
if (deviceInfoSnapshot.data!.thingId == null) {
|
||||||
deviceUpdateBloc.getDeviceInformation(
|
deviceUpdateBloc.getDeviceInfomation(
|
||||||
context,
|
|
||||||
widget.thingID,
|
widget.thingID,
|
||||||
// provincesData,
|
districtsData,
|
||||||
// districtsData,
|
wardsData,
|
||||||
// wardsData,
|
|
||||||
deviceNameController,
|
deviceNameController,
|
||||||
deviceLatitudeController,
|
deviceLatitudeController,
|
||||||
deviceLongitudeController);
|
deviceLongitudeController);
|
||||||
return const SharedLoadingAnimation();
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return StreamBuilder<bool>(
|
return StreamBuilder<bool>(
|
||||||
stream: deviceUpdateBloc.streamIsChanged,
|
stream: deviceUpdateBloc.streamIsChanged,
|
||||||
@@ -245,7 +245,7 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
|||||||
.sinkProvinceData
|
.sinkProvinceData
|
||||||
.add(provinceData);
|
.add(provinceData);
|
||||||
deviceUpdateBloc
|
deviceUpdateBloc
|
||||||
.getAllDistricts(context,
|
.getAllDistricts(
|
||||||
value.code);
|
value.code);
|
||||||
selectedDistrict = "";
|
selectedDistrict = "";
|
||||||
districtData['name'] =
|
districtData['name'] =
|
||||||
@@ -318,7 +318,7 @@ class _DeviceUpdateScreenState extends State<DeviceUpdateScreen> {
|
|||||||
.sinkDistrictData
|
.sinkDistrictData
|
||||||
.add(districtData);
|
.add(districtData);
|
||||||
deviceUpdateBloc
|
deviceUpdateBloc
|
||||||
.getAllWards(context,value.code);
|
.getAllWards(value.code);
|
||||||
selectedWard = "";
|
selectedWard = "";
|
||||||
wardData['name'] =
|
wardData['name'] =
|
||||||
selectedWard!;
|
selectedWard!;
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_maps_flutter/google_maps_flutter.dart' ;
|
||||||
import '../../../bloc/device_update_bloc.dart';
|
import '../../../bloc/device_update_bloc.dart';
|
||||||
import '../../../product/constant/app/app_constants.dart';
|
import '../../../product/constant/app/app_constants.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
import '../../../product/shared/find_location_maps/shared_map_search_location.dart';
|
import '../../../product/shared/find_location_maps/shared_map_search_location.dart';
|
||||||
|
|
||||||
import '../../../product/shared/find_location_maps/model/prediction_model.dart';
|
import '../../../product/shared/find_location_maps/model/prediction_model.dart';
|
||||||
import '../../../product/shared/shared_transition.dart';
|
import '../../../product/shared/shared_transition.dart';
|
||||||
import 'geocode_model.dart';
|
import 'geocode_model.dart';
|
||||||
@@ -63,8 +64,7 @@ showMapDialog(
|
|||||||
String latitude = mapDialogLatitudeController.text;
|
String latitude = mapDialogLatitudeController.text;
|
||||||
String longitude = mapDialogLongitudeController.text;
|
String longitude = mapDialogLongitudeController.text;
|
||||||
log("Finish -- Latitude: $latitude, longitude: $longitude --");
|
log("Finish -- Latitude: $latitude, longitude: $longitude --");
|
||||||
getDataFromApi(
|
getDataFromApi(latitude, longitude, deviceUpdateBloc);
|
||||||
context, latitude, longitude, deviceUpdateBloc);
|
|
||||||
latitudeController.text =
|
latitudeController.text =
|
||||||
mapDialogLatitudeController.text;
|
mapDialogLatitudeController.text;
|
||||||
longitudeController.text =
|
longitudeController.text =
|
||||||
@@ -184,7 +184,7 @@ addMarker(
|
|||||||
updateCameraPosition(position, 14, mapController);
|
updateCameraPosition(position, 14, mapController);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getDataFromApi(BuildContext context, String latitude, String longitude,
|
void getDataFromApi(String latitude, String longitude,
|
||||||
DeviceUpdateBloc deviceUpdateBloc) async {
|
DeviceUpdateBloc deviceUpdateBloc) async {
|
||||||
String path =
|
String path =
|
||||||
"maps/api/geocode/json?latlng=$latitude,$longitude&language=vi&result_type=political&key=${ApplicationConstants.MAP_KEY}";
|
"maps/api/geocode/json?latlng=$latitude,$longitude&language=vi&result_type=political&key=${ApplicationConstants.MAP_KEY}";
|
||||||
@@ -215,7 +215,7 @@ void getDataFromApi(BuildContext context, String latitude, String longitude,
|
|||||||
log("$key: $value");
|
log("$key: $value");
|
||||||
});
|
});
|
||||||
|
|
||||||
await _processLocations(context, locations, deviceUpdateBloc);
|
await _processLocations(locations, deviceUpdateBloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> _extractLocationComponents(
|
Map<String, String> _extractLocationComponents(
|
||||||
@@ -241,31 +241,31 @@ Map<String, String> _extractLocationComponents(
|
|||||||
return locations;
|
return locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _processLocations(BuildContext context,
|
Future<void> _processLocations(
|
||||||
Map<String, String> locations, DeviceUpdateBloc deviceUpdateBloc) async {
|
Map<String, String> locations, DeviceUpdateBloc deviceUpdateBloc) async {
|
||||||
String provinceNameFromAPI = locations['provincekey'] ?? "";
|
String provinceNameFromAPI = locations['provincekey'] ?? "";
|
||||||
String districtNameFromAPI = locations['districtkey'] ?? "";
|
String districtNameFromAPI = locations['districtkey'] ?? "";
|
||||||
String wardNameFromAPI = locations['wardkey'] ?? "";
|
String wardNameFromAPI = locations['wardkey'] ?? "";
|
||||||
|
|
||||||
final province =
|
final province =
|
||||||
await deviceUpdateBloc.getProvinceByName(context, provinceNameFromAPI);
|
await deviceUpdateBloc.getProvinceByName(provinceNameFromAPI);
|
||||||
if (province.name != "null") {
|
if (province.name != "null") {
|
||||||
log("Province: ${province.fullName}, ProvinceCode: ${province.code}");
|
log("Province: ${province.fullName}, ProvinceCode: ${province.code}");
|
||||||
deviceUpdateBloc.sinkProvinceData
|
deviceUpdateBloc.sinkProvinceData
|
||||||
.add({"code": province.code!, "name": province.fullName!});
|
.add({"code": province.code!, "name": province.fullName!});
|
||||||
deviceUpdateBloc.getAllProvinces(context);
|
deviceUpdateBloc.getAllProvinces();
|
||||||
|
|
||||||
final district = await deviceUpdateBloc.getDistrictByName(
|
final district = await deviceUpdateBloc.getDistrictByName(
|
||||||
context, districtNameFromAPI, province.code!);
|
districtNameFromAPI, province.code!);
|
||||||
log("Districtname: ${district.fullName}, districtCode: ${district.code}");
|
log("Districtname: ${district.fullName}, districtCode: ${district.code}");
|
||||||
deviceUpdateBloc.getAllDistricts(context, province.code!);
|
deviceUpdateBloc.getAllDistricts(province.code!);
|
||||||
if (district.name != "null") {
|
if (district.name != "null") {
|
||||||
deviceUpdateBloc.sinkDistrictData
|
deviceUpdateBloc.sinkDistrictData
|
||||||
.add({"code": district.code!, "name": district.fullName!});
|
.add({"code": district.code!, "name": district.fullName!});
|
||||||
final ward = await deviceUpdateBloc.getWardByName(
|
final ward =
|
||||||
context, wardNameFromAPI, district.code!);
|
await deviceUpdateBloc.getWardByName(wardNameFromAPI, district.code!);
|
||||||
log("Wardname: ${ward.fullName}, WardCode: ${ward.code}");
|
log("Wardname: ${ward.fullName}, WardCode: ${ward.code}");
|
||||||
deviceUpdateBloc.getAllWards(context, district.code!);
|
deviceUpdateBloc.getAllWards(district.code!);
|
||||||
if (ward.name != "null") {
|
if (ward.name != "null") {
|
||||||
log("Xac dinh duoc het thong tin tu toa do");
|
log("Xac dinh duoc het thong tin tu toa do");
|
||||||
deviceUpdateBloc.sinkWardData
|
deviceUpdateBloc.sinkWardData
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:data_table_2/data_table_2.dart';
|
import 'package:data_table_2/data_table_2.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import '../../product/shared/shared_component_loading_animation.dart';
|
|
||||||
import '../../product/shared/shared_loading_animation.dart';
|
|
||||||
import 'add_new_device_widget.dart';
|
import 'add_new_device_widget.dart';
|
||||||
import 'delete_device_widget.dart';
|
import 'delete_device_widget.dart';
|
||||||
import 'device_model.dart';
|
import 'device_model.dart';
|
||||||
@@ -31,7 +29,7 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
late DevicesManagerBloc devicesManagerBloc;
|
late DevicesManagerBloc devicesManagerBloc;
|
||||||
String role = "Undefine";
|
String role = "Undefine";
|
||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
// List<Device> devices = [];
|
List<Device> devices = [];
|
||||||
Timer? getAllDevicesTimer;
|
Timer? getAllDevicesTimer;
|
||||||
List<Widget> tags = [];
|
List<Widget> tags = [];
|
||||||
int tagIndex = -2;
|
int tagIndex = -2;
|
||||||
@@ -43,7 +41,7 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
const duration = Duration(seconds: 10);
|
const duration = Duration(seconds: 10);
|
||||||
getAllDevicesTimer = Timer.periodic(
|
getAllDevicesTimer = Timer.periodic(
|
||||||
duration,
|
duration,
|
||||||
(Timer t) => devicesManagerBloc.getDeviceByState(context,tagIndex),
|
(Timer t) => devicesManagerBloc.getDeviceByState(tagIndex),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,60 +58,36 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
body: StreamBuilder<List<int>>(
|
body: StreamBuilder<List<int>>(
|
||||||
stream: devicesManagerBloc.streamTagStates,
|
stream: devicesManagerBloc.streamTagStates,
|
||||||
builder: (context, tagSnapshot) {
|
builder: (context, tagSnapshot) {
|
||||||
return StreamBuilder<String>(
|
return SafeArea(
|
||||||
stream: devicesManagerBloc.streamUserRole,
|
child: StreamBuilder<List<Device>>(
|
||||||
initialData: role,
|
stream: devicesManagerBloc.streamAllDevices,
|
||||||
builder: (context, roleSnapshot) {
|
initialData: devices,
|
||||||
return SafeArea(
|
builder: (context, allDeviceSnapshot) {
|
||||||
child: StreamBuilder<List<Device>>(
|
if (allDeviceSnapshot.data?.isEmpty ?? devices.isEmpty) {
|
||||||
stream: devicesManagerBloc.streamAllDevices,
|
devicesManagerBloc
|
||||||
builder: (context, allDeviceSnapshot) {
|
.getDeviceByState(tagSnapshot.data?[0] ?? -2);
|
||||||
if(allDeviceSnapshot.data == null){
|
return const Center(child: CircularProgressIndicator());
|
||||||
devicesManagerBloc
|
} else {
|
||||||
.getDeviceByState(context,tagSnapshot.data?[0] ?? -2);
|
if (tagSnapshot.data!.isNotEmpty) {
|
||||||
return const SharedLoadingAnimation();
|
tagIndex = tagSnapshot.data![0];
|
||||||
}
|
devicesManagerBloc.sinkTagStates.add([tagIndex]);
|
||||||
if (allDeviceSnapshot.data!.isEmpty) {
|
}
|
||||||
return Center(
|
return SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
if (tagSnapshot.hasData &&
|
||||||
children: [
|
tagSnapshot.data!.isNotEmpty &&
|
||||||
Container(
|
tagSnapshot.data![0] != -2)
|
||||||
width: 100,
|
TagState(
|
||||||
height: 100,
|
state: tagSnapshot.data![0],
|
||||||
decoration: BoxDecoration(
|
devicesManagerBloc: devicesManagerBloc,
|
||||||
border: Border.all(color: Theme.of(context).colorScheme.primary),
|
),
|
||||||
borderRadius: BorderRadius.circular(50)
|
SizedBox(height: context.lowValue),
|
||||||
),
|
StreamBuilder<String>(
|
||||||
child: IconButton(onPressed: (){
|
stream: devicesManagerBloc.streamUserRole,
|
||||||
ScaffoldMessenger.of(context)
|
initialData: role,
|
||||||
.clearSnackBars();
|
builder: (context, roleSnapshot) {
|
||||||
addNewDevice(context,
|
return SizedBox(
|
||||||
roleSnapshot.data ?? role, devicesManagerBloc);
|
|
||||||
}, iconSize: 50, icon: const Icon(Icons.add),),),
|
|
||||||
SizedBox(height: context.mediumValue,),
|
|
||||||
Text(appLocalization(context).dont_have_device, style: context.responsiveBodyMediumWithBold,)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (tagSnapshot.data!.isNotEmpty) {
|
|
||||||
tagIndex = tagSnapshot.data![0];
|
|
||||||
devicesManagerBloc.sinkTagStates.add([tagIndex]);
|
|
||||||
}
|
|
||||||
return SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
if (tagSnapshot.hasData &&
|
|
||||||
tagSnapshot.data!.isNotEmpty &&
|
|
||||||
tagSnapshot.data![0] != -2)
|
|
||||||
TagState(
|
|
||||||
state: tagSnapshot.data![0],
|
|
||||||
devicesManagerBloc: devicesManagerBloc,
|
|
||||||
),
|
|
||||||
SizedBox(height: context.lowValue),
|
|
||||||
SizedBox(
|
|
||||||
height: getTableHeight(allDeviceSnapshot.data?.length ?? 1),
|
height: getTableHeight(allDeviceSnapshot.data?.length ?? 1),
|
||||||
child: PaginatedDataTable2(
|
child: PaginatedDataTable2(
|
||||||
wrapInCard: false,
|
wrapInCard: false,
|
||||||
@@ -129,16 +103,15 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
.paginated_data_table_title,
|
.paginated_data_table_title,
|
||||||
style: context.responsiveBodyLargeWithBold,
|
style: context.headlineMediumTextStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
if (roleSnapshot.data ==
|
if (roleSnapshot.data ==
|
||||||
RoleEnums.ADMIN.name ||
|
RoleEnums.ADMIN.name ||
|
||||||
roleSnapshot.data ==
|
roleSnapshot.data ==
|
||||||
RoleEnums.USER.name)
|
RoleEnums.USER.name)
|
||||||
DataColumn2(
|
DataColumn(
|
||||||
fixedWidth: context.dynamicWidth(0.3),
|
|
||||||
label: Text(appLocalization(context)
|
label: Text(appLocalization(context)
|
||||||
.paginated_data_table_column_deviceName),
|
.paginated_data_table_column_deviceName),
|
||||||
),
|
),
|
||||||
@@ -175,23 +148,23 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
// log('Chuyen page: $pageIndex');
|
// log('Chuyen page: $pageIndex');
|
||||||
},
|
},
|
||||||
rowsPerPage:
|
rowsPerPage:
|
||||||
(allDeviceSnapshot.data?.length ?? 1) < 6
|
(allDeviceSnapshot.data?.length ?? 1) < 6
|
||||||
? (allDeviceSnapshot.data?.length ??
|
? (allDeviceSnapshot.data?.length ??
|
||||||
0)
|
0)
|
||||||
: 5,
|
: 5,
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
if (roleSnapshot.data ==
|
if (roleSnapshot.data ==
|
||||||
RoleEnums.USER.name ||
|
RoleEnums.USER.name ||
|
||||||
roleSnapshot.data ==
|
roleSnapshot.data ==
|
||||||
RoleEnums.ADMIN.name)
|
RoleEnums.ADMIN.name)
|
||||||
IconButton(
|
IconButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
WidgetStateProperty.all<Color>(
|
WidgetStateProperty.all<Color>(
|
||||||
Colors.green),
|
Colors.green),
|
||||||
iconColor:
|
iconColor:
|
||||||
WidgetStateProperty.all<Color>(
|
WidgetStateProperty.all<Color>(
|
||||||
Colors.white,
|
Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -199,48 +172,52 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
ScaffoldMessenger.of(context)
|
ScaffoldMessenger.of(context)
|
||||||
.clearSnackBars();
|
.clearSnackBars();
|
||||||
addNewDevice(context,
|
addNewDevice(context,
|
||||||
roleSnapshot.data ?? role, devicesManagerBloc);
|
roleSnapshot.data ?? role);
|
||||||
},
|
},
|
||||||
icon: IconConstants.instance
|
icon: IconConstants.instance
|
||||||
.getMaterialIcon(Icons.add))
|
.getMaterialIcon(Icons.add))
|
||||||
],
|
],
|
||||||
source: DeviceSource(
|
source: DeviceSource(
|
||||||
devices: allDeviceSnapshot.data ?? [],
|
devices: allDeviceSnapshot.data ?? devices,
|
||||||
context: context,
|
context: context,
|
||||||
devicesBloc: devicesManagerBloc,
|
devicesBloc: devicesManagerBloc,
|
||||||
role: role,
|
role: role,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
SizedBox(height: context.lowValue),
|
},
|
||||||
Text(
|
|
||||||
appLocalization(context).overview_message,
|
|
||||||
style: context.responsiveBodyLargeWithBold
|
|
||||||
),
|
|
||||||
StreamBuilder<Map<String, List<Device>>>(
|
|
||||||
stream: devicesManagerBloc.streamDeviceByState,
|
|
||||||
builder: (context, devicesByStateSnapshot) {
|
|
||||||
if (devicesByStateSnapshot.data == null) {
|
|
||||||
devicesManagerBloc.getDeviceByState(context,
|
|
||||||
tagSnapshot.data?[0] ?? -2);
|
|
||||||
return const SharedComponentLoadingAnimation();
|
|
||||||
} else {
|
|
||||||
return SharedPieChart(
|
|
||||||
deviceByState:
|
|
||||||
devicesByStateSnapshot.data ?? {},
|
|
||||||
devicesManagerBloc: devicesManagerBloc,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
SizedBox(height: context.lowValue),
|
||||||
}
|
Text(
|
||||||
},
|
appLocalization(context).overview_message,
|
||||||
),
|
style: const TextStyle(
|
||||||
);
|
fontSize: 20,
|
||||||
}
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
StreamBuilder<Map<String, List<Device>>>(
|
||||||
|
stream: devicesManagerBloc.streamDeviceByState,
|
||||||
|
builder: (context, devicesByStateSnapshot) {
|
||||||
|
if (devicesByStateSnapshot.data == null) {
|
||||||
|
devicesManagerBloc.getDeviceByState(
|
||||||
|
tagSnapshot.data?[0] ?? -2);
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator());
|
||||||
|
} else {
|
||||||
|
return SharedPieChart(
|
||||||
|
deviceByState:
|
||||||
|
devicesByStateSnapshot.data ?? {},
|
||||||
|
devicesManagerBloc: devicesManagerBloc,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -253,7 +230,7 @@ class _DevicesManagerScreenState extends State<DevicesManagerScreen> {
|
|||||||
|
|
||||||
double getTableHeight(int dataLength){
|
double getTableHeight(int dataLength){
|
||||||
if(dataLength < 3){
|
if(dataLength < 3){
|
||||||
return context.dynamicHeight(0.35);
|
return context.dynamicHeight(0.3);
|
||||||
}else {
|
}else {
|
||||||
return context.dynamicHeight(0.4);
|
return context.dynamicHeight(0.4);
|
||||||
}
|
}
|
||||||
@@ -393,7 +370,7 @@ class TagState extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
devicesManagerBloc.getDeviceByState(context,-2);
|
devicesManagerBloc.getDeviceByState(-2);
|
||||||
},
|
},
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.close,
|
Icons.close,
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:sfm_app/product/constant/enums/app_route_enums.dart';
|
||||||
import '../../product/constant/enums/app_route_enums.dart';
|
import 'package:sfm_app/product/constant/image/image_constants.dart';
|
||||||
import '../../product/constant/image/image_constants.dart';
|
|
||||||
|
|
||||||
class NotFoundScreen extends StatelessWidget {
|
class NotFoundScreen extends StatelessWidget {
|
||||||
const NotFoundScreen({super.key});
|
const NotFoundScreen({super.key});
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'package:alarm/alarm.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../../product/shared/shared_loading_animation.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../../product/shared/shared_component_loading_animation.dart';
|
|
||||||
import 'shared/alert_card.dart';
|
import 'shared/alert_card.dart';
|
||||||
import 'shared/warning_card.dart';
|
import 'shared/warning_card.dart';
|
||||||
|
import '../../product/utils/device_utils.dart';
|
||||||
import 'device_alias_model.dart';
|
import 'device_alias_model.dart';
|
||||||
import 'shared/overview_card.dart';
|
import 'shared/overview_card.dart';
|
||||||
import '../settings/device_notification_settings/device_notification_settings_model.dart';
|
import '../settings/device_notification_settings/device_notification_settings_model.dart';
|
||||||
@@ -18,6 +17,7 @@ import '../../product/base/bloc/base_bloc.dart';
|
|||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
const HomeScreen({super.key});
|
const HomeScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<HomeScreen> createState() => _HomeScreenState();
|
State<HomeScreen> createState() => _HomeScreenState();
|
||||||
}
|
}
|
||||||
@@ -25,284 +25,305 @@ class HomeScreen extends StatefulWidget {
|
|||||||
class _HomeScreenState extends State<HomeScreen> {
|
class _HomeScreenState extends State<HomeScreen> {
|
||||||
late HomeBloc homeBloc;
|
late HomeBloc homeBloc;
|
||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
|
Map<String, List<DeviceWithAlias>> allDevicesAliasMap = {};
|
||||||
|
Map<String, List<DeviceWithAlias>> allDevicesAliasJoinedMap = {};
|
||||||
|
List<DeviceWithAlias> devices = [];
|
||||||
bool isFunctionCall = false;
|
bool isFunctionCall = false;
|
||||||
Timer? getAllDevicesTimer;
|
Timer? getAllDevicesTimer;
|
||||||
|
int notificationCount = 0;
|
||||||
|
Map<String, List<DeviceWithAlias>> ownerDevicesStatus = {};
|
||||||
|
List<String> ownerDevicesState = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
homeBloc = BlocProvider.of(context);
|
homeBloc = BlocProvider.of(context);
|
||||||
|
getOwnerAndJoinedDevices();
|
||||||
const duration = Duration(seconds: 10);
|
const duration = Duration(seconds: 10);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
getAllDevicesTimer = Timer.periodic(duration, (Timer t) => getOwnerAndJoinedDevices());
|
||||||
// Code ở đây chạy sau khi giao diện render xong
|
|
||||||
getAllDevicesTimer = Timer.periodic(
|
|
||||||
duration, (Timer t) => homeBloc.getOwnerAndJoinedDevices(context));
|
|
||||||
// Ví dụ: gọi API, scroll tới vị trí nào đó, v.v.
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> loadAlarms() async {
|
|
||||||
final alarms = await Alarm.getAlarms();
|
|
||||||
log("Alarms: $alarms");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
getAllDevicesTimer?.cancel();
|
getAllDevicesTimer?.cancel();
|
||||||
homeBloc.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<List<DeviceWithAlias>?>(
|
return Scaffold(
|
||||||
stream: homeBloc.streamAliasDevices,
|
body: Padding(
|
||||||
builder: (context, aliasDevicesSnapshot) {
|
padding: context.paddingLow,
|
||||||
if (aliasDevicesSnapshot.data == null) {
|
child: SingleChildScrollView(
|
||||||
homeBloc.getOwnerAndJoinedDevices(context);
|
child: Column(
|
||||||
return const SharedLoadingAnimation();
|
children: <Widget>[
|
||||||
} else {
|
Row(
|
||||||
homeBloc.getOwnerDeviceState(
|
children: [
|
||||||
context, aliasDevicesSnapshot.data ?? []);
|
Text(
|
||||||
homeBloc.getDeviceStatusAliasMap(aliasDevicesSnapshot.data ?? []);
|
appLocalization(context).notification,
|
||||||
checkSettingDevice(aliasDevicesSnapshot.data ?? []);
|
style: context.titleMediumTextStyle,
|
||||||
return Scaffold(
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
SizedBox(width: context.lowValue),
|
||||||
onPressed: () {
|
StreamBuilder<int>(
|
||||||
loadAlarms();
|
stream: homeBloc.streamCountNotification,
|
||||||
},
|
builder: (context, countSnapshot) {
|
||||||
child: const Icon(Icons.alarm),
|
return Text(
|
||||||
|
"(${countSnapshot.data ?? 0})",
|
||||||
|
style: context.titleMediumTextStyle,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
SizedBox(
|
||||||
padding: context.paddingLow,
|
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
scrollDirection: Axis.horizontal,
|
||||||
children: <Widget>[
|
child: StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
||||||
Row(
|
stream: homeBloc.streamOwnerDevicesStatus,
|
||||||
children: [
|
builder: (context, snapshot) {
|
||||||
Text(
|
if (snapshot.data?['state'] != null || snapshot.data?['battery'] != null) {
|
||||||
appLocalization(context).notification,
|
return Row(
|
||||||
style: context.titleMediumTextStyle,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
SizedBox(width: context.lowValue),
|
children: [
|
||||||
StreamBuilder<int>(
|
if (snapshot.data?['state'] != null)
|
||||||
stream: homeBloc.streamCountNotification,
|
...snapshot.data!['state']!
|
||||||
builder: (context, countSnapshot) {
|
.map(
|
||||||
if (countSnapshot.data == null) {
|
(item) => FutureBuilder<Widget>(
|
||||||
homeBloc.getOwnerDeviceState(
|
future: warningCard(context, apiServices, item),
|
||||||
context, aliasDevicesSnapshot.data ?? []);
|
builder: (context, warningCardSnapshot) {
|
||||||
return const Text("0");
|
if (warningCardSnapshot.hasData) {
|
||||||
} else {
|
return ConstrainedBox(
|
||||||
return Text(
|
constraints: const BoxConstraints(
|
||||||
"(${countSnapshot.data ?? 0})",
|
maxWidth: 400,
|
||||||
style: context.titleMediumTextStyle,
|
maxHeight: 260,
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
child:
|
|
||||||
StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
|
||||||
stream: homeBloc.streamOwnerDevicesStatus,
|
|
||||||
builder: (context, ownerDevicesStatusSnapshot) {
|
|
||||||
if (ownerDevicesStatusSnapshot.data == null) {
|
|
||||||
homeBloc.getOwnerDeviceState(
|
|
||||||
context, aliasDevicesSnapshot.data ?? []);
|
|
||||||
return const SharedComponentLoadingAnimation();
|
|
||||||
} else {
|
|
||||||
return AnimatedSwitcher(
|
|
||||||
duration: context.lowDuration,
|
|
||||||
transitionBuilder: (Widget child,
|
|
||||||
Animation<double> animation) {
|
|
||||||
final offsetAnimation = Tween<Offset>(
|
|
||||||
begin: const Offset(0.0, 0.2),
|
|
||||||
end: Offset.zero,
|
|
||||||
).animate(CurvedAnimation(
|
|
||||||
parent: animation,
|
|
||||||
curve: Curves.easeInOut,
|
|
||||||
));
|
|
||||||
return FadeTransition(
|
|
||||||
opacity: animation,
|
|
||||||
child: SlideTransition(
|
|
||||||
position: offsetAnimation,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: ownerDevicesStatusSnapshot
|
|
||||||
.data?['state'] !=
|
|
||||||
null ||
|
|
||||||
ownerDevicesStatusSnapshot
|
|
||||||
.data?['battery'] !=
|
|
||||||
null
|
|
||||||
? ConstrainedBox(
|
|
||||||
key: const ValueKey('data'),
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
minWidth: MediaQuery.of(context)
|
|
||||||
.size
|
|
||||||
.width),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
if (ownerDevicesStatusSnapshot
|
|
||||||
.data?['state'] !=
|
|
||||||
null)
|
|
||||||
...ownerDevicesStatusSnapshot
|
|
||||||
.data!['state']!
|
|
||||||
.map(
|
|
||||||
(item) => SizedBox(
|
|
||||||
width: context
|
|
||||||
.dynamicWidth(0.95),
|
|
||||||
child: FutureBuilder<
|
|
||||||
Widget>(
|
|
||||||
future: warningCard(
|
|
||||||
context,
|
|
||||||
apiServices,
|
|
||||||
item),
|
|
||||||
builder: (context,
|
|
||||||
warningCardSnapshot) {
|
|
||||||
if (warningCardSnapshot
|
|
||||||
.hasData) {
|
|
||||||
return warningCardSnapshot
|
|
||||||
.data!;
|
|
||||||
} else {
|
|
||||||
return const SizedBox
|
|
||||||
.shrink();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
if (ownerDevicesStatusSnapshot
|
|
||||||
.data?['battery'] !=
|
|
||||||
null)
|
|
||||||
...ownerDevicesStatusSnapshot
|
|
||||||
.data!['battery']!
|
|
||||||
.map(
|
|
||||||
(batteryItem) => SizedBox(
|
|
||||||
width: context
|
|
||||||
.dynamicWidth(0.95),
|
|
||||||
child: FutureBuilder<
|
|
||||||
Widget>(
|
|
||||||
future:
|
|
||||||
notificationCard(
|
|
||||||
context,
|
|
||||||
"lowBattery",
|
|
||||||
appLocalization(
|
|
||||||
context)
|
|
||||||
.low_battery_message,
|
|
||||||
batteryItem,
|
|
||||||
),
|
|
||||||
builder: (context,
|
|
||||||
warningCardSnapshot) {
|
|
||||||
if (warningCardSnapshot
|
|
||||||
.hasData) {
|
|
||||||
return warningCardSnapshot
|
|
||||||
.data!;
|
|
||||||
} else {
|
|
||||||
return const SizedBox
|
|
||||||
.shrink();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Padding(
|
|
||||||
key: const ValueKey('no_data'),
|
|
||||||
padding: context.paddingMedium,
|
|
||||||
child: Center(
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons
|
|
||||||
.check_circle_outline_rounded,
|
|
||||||
size: 40,
|
|
||||||
color: Colors.green,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: context.lowValue),
|
|
||||||
Text(
|
|
||||||
appLocalization(context)
|
|
||||||
.notification_description,
|
|
||||||
maxLines: 2,
|
|
||||||
overflow:
|
|
||||||
TextOverflow.ellipsis,
|
|
||||||
softWrap: true,
|
|
||||||
textAlign: TextAlign.start,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
child: warningCardSnapshot.data!,
|
||||||
),
|
);
|
||||||
);
|
} else {
|
||||||
}
|
return const SizedBox.shrink();
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
if (snapshot.data?['battery'] != null)
|
||||||
|
...snapshot.data!['battery']!
|
||||||
|
.map(
|
||||||
|
(batteryItem) => FutureBuilder<Widget>(
|
||||||
|
future: notificationCard(
|
||||||
|
context, "lowBattery", appLocalization(context).low_battery_message, batteryItem),
|
||||||
|
builder: (context, warningCardSnapshot) {
|
||||||
|
if (warningCardSnapshot.hasData) {
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxWidth: 400,
|
||||||
|
maxHeight: 260,
|
||||||
|
),
|
||||||
|
child: warningCardSnapshot.data!,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: context.paddingMedium,
|
||||||
|
child: Center(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.check_circle_outline_rounded,
|
||||||
|
size: 40,
|
||||||
|
color: Colors.green,
|
||||||
|
),
|
||||||
|
SizedBox(width: context.lowValue),
|
||||||
|
Text(
|
||||||
|
appLocalization(context).notification_description,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
softWrap: true,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
}
|
||||||
StreamBuilder<Map<String, List<DeviceWithAlias>>?>(
|
},
|
||||||
stream: homeBloc.streamAllDevicesAliasMap,
|
|
||||||
builder: (context, allDevicesAliasMapSnapshot) {
|
|
||||||
if (allDevicesAliasMapSnapshot.data == null) {
|
|
||||||
homeBloc.getDeviceStatusAliasMap(
|
|
||||||
aliasDevicesSnapshot.data ?? []);
|
|
||||||
return const SharedComponentLoadingAnimation();
|
|
||||||
} else {
|
|
||||||
final data = allDevicesAliasMapSnapshot.data!;
|
|
||||||
return OverviewCard(
|
|
||||||
isOwner: true,
|
|
||||||
total: data['all']?.length ?? 0,
|
|
||||||
active: data['online']?.length ?? 0,
|
|
||||||
inactive: data['offline']?.length ?? 0,
|
|
||||||
warning: data['warn']?.length ?? 0,
|
|
||||||
unused: data['not-use']?.length ?? 0,
|
|
||||||
showUnused: false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
||||||
|
stream: homeBloc.streamAllDevicesAliasMap,
|
||||||
|
builder: (context, allDevicesAliasMapSnapshot) {
|
||||||
|
if (!allDevicesAliasMapSnapshot.hasData ||
|
||||||
|
allDevicesAliasMapSnapshot.data == null) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
final data = allDevicesAliasMapSnapshot.data!;
|
||||||
|
return OverviewCard(
|
||||||
|
isOwner: true,
|
||||||
|
total: data['all']?.length ?? 0,
|
||||||
|
active: data['online']?.length ?? 0,
|
||||||
|
inactive: data['offline']?.length ?? 0,
|
||||||
|
warning: data['warn']?.length ?? 0,
|
||||||
|
unused: data['not-use']?.length ?? 0);
|
||||||
|
}),
|
||||||
|
SizedBox(height: context.lowValue),
|
||||||
|
StreamBuilder<Map<String, List<DeviceWithAlias>>>(
|
||||||
|
stream: homeBloc.streamAllDevicesAliasJoinedMap,
|
||||||
|
builder: (context, allDevicesAliasJoinedMapSnapshot) {
|
||||||
|
if (!allDevicesAliasJoinedMapSnapshot.hasData ||
|
||||||
|
allDevicesAliasJoinedMapSnapshot.data == null) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
final data = allDevicesAliasJoinedMapSnapshot.data!;
|
||||||
|
final total = data['all']?.length ?? 0;
|
||||||
|
final active = data['online']?.length ?? 0;
|
||||||
|
final inactive = data['offline']?.length ?? 0;
|
||||||
|
final warning = data['warn']?.length ?? 0;
|
||||||
|
final unused = data['not-use']?.length ?? 0;
|
||||||
|
|
||||||
|
if (total == 0 && active == 0 && inactive == 0 && warning == 0 && unused == 0) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return OverviewCard(
|
||||||
|
isOwner: false,
|
||||||
|
total: total,
|
||||||
|
active: active,
|
||||||
|
inactive: inactive,
|
||||||
|
warning: warning,
|
||||||
|
unused: unused,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getOwnerAndJoinedDevices() async {
|
||||||
|
String response = await apiServices.getDashBoardDevices();
|
||||||
|
final data = jsonDecode(response);
|
||||||
|
List<dynamic> result = data["items"];
|
||||||
|
devices = DeviceWithAlias.fromJsonDynamicList(result);
|
||||||
|
getOwnerDeviceState(devices);
|
||||||
|
checkSettingDevice(devices);
|
||||||
|
getDeviceStatusAliasMap(devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getOwnerDeviceState(List<DeviceWithAlias> allDevices) async {
|
||||||
|
List<DeviceWithAlias> ownerDevices = [];
|
||||||
|
for (var device in allDevices) {
|
||||||
|
if (device.isOwner!) {
|
||||||
|
ownerDevices.add(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ownerDevicesState.isEmpty || ownerDevicesState.length < devices.length) {
|
||||||
|
ownerDevicesState.clear();
|
||||||
|
ownerDevicesStatus.clear();
|
||||||
|
homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus);
|
||||||
|
int count = 0;
|
||||||
|
for (var device in ownerDevices) {
|
||||||
|
Map<String, dynamic> sensorMap =
|
||||||
|
DeviceUtils.instance.getDeviceSensors(context, device.status?.sensors ?? []);
|
||||||
|
if (device.state == 1 || device.state == 3) {
|
||||||
|
ownerDevicesStatus["state"] ??= [];
|
||||||
|
ownerDevicesStatus["state"]!.add(device);
|
||||||
|
homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (sensorMap['sensorBattery'] != appLocalization(context).no_data_message) {
|
||||||
|
if (double.parse(sensorMap['sensorBattery']) <= 20) {
|
||||||
|
ownerDevicesStatus['battery'] ??= [];
|
||||||
|
ownerDevicesStatus['battery']!.add(device);
|
||||||
|
homeBloc.sinkOwnerDevicesStatus.add(ownerDevicesStatus);
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
notificationCount = count;
|
||||||
|
homeBloc.sinkCountNotification.add(notificationCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getDeviceStatusAliasMap(List<DeviceWithAlias> devices) {
|
||||||
|
allDevicesAliasMap.clear();
|
||||||
|
allDevicesAliasJoinedMap.clear();
|
||||||
|
|
||||||
|
for (var key in ['all', 'online', 'offline', 'warning', 'not-use']) {
|
||||||
|
allDevicesAliasMap[key] = [];
|
||||||
|
allDevicesAliasJoinedMap[key] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DeviceWithAlias device in devices) {
|
||||||
|
if (device.isOwner == true) {
|
||||||
|
allDevicesAliasMap['all']!.add(device);
|
||||||
|
if (device.state == 0 || device.state == 1) {
|
||||||
|
allDevicesAliasMap['online']!.add(device);
|
||||||
|
}
|
||||||
|
if (device.state == -1) {
|
||||||
|
allDevicesAliasMap['offline']!.add(device);
|
||||||
|
}
|
||||||
|
if (device.state == 1) {
|
||||||
|
allDevicesAliasMap['warning']!.add(device);
|
||||||
|
}
|
||||||
|
if (device.state == -2) {
|
||||||
|
allDevicesAliasMap['not-use']!.add(device);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allDevicesAliasJoinedMap['all']!.add(device);
|
||||||
|
if (device.state == 0 || device.state == 1) {
|
||||||
|
allDevicesAliasJoinedMap['online']!.add(device);
|
||||||
|
}
|
||||||
|
if (device.state == -1) {
|
||||||
|
allDevicesAliasJoinedMap['offline']!.add(device);
|
||||||
|
}
|
||||||
|
if (device.state == 1) {
|
||||||
|
allDevicesAliasJoinedMap['warning']!.add(device);
|
||||||
|
}
|
||||||
|
if (device.state == -2) {
|
||||||
|
allDevicesAliasJoinedMap['not-use']!.add(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
homeBloc.sinkAllDevicesAliasMap.add(allDevicesAliasMap);
|
||||||
|
homeBloc.sinkAllDevicesAliasJoinedMap.add(allDevicesAliasJoinedMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkSettingDevice(List<DeviceWithAlias> devices) async {
|
void checkSettingDevice(List<DeviceWithAlias> devices) async {
|
||||||
if (isFunctionCall) {
|
if (isFunctionCall) {
|
||||||
log("Ham check setting da duoc goi");
|
log("Ham check setting da duoc goi");
|
||||||
} else {
|
} else {
|
||||||
await apiServices.execute(context, () async {
|
String? response = await apiServices.getAllSettingsNotificationOfDevices();
|
||||||
|
if (response != "") {
|
||||||
|
final data = jsonDecode(response);
|
||||||
|
final result = data['data'];
|
||||||
|
// log("Data ${DeviceNotificationSettings.mapFromJson(jsonDecode(data)).values.toList()}");
|
||||||
List<DeviceNotificationSettings> list =
|
List<DeviceNotificationSettings> list =
|
||||||
await apiServices.getAllSettingsNotificationOfDevices();
|
DeviceNotificationSettings.mapFromJson(result).values.toList();
|
||||||
// log("List: $list");
|
// log("List: $list");
|
||||||
Set<String> thingIdsInList =
|
Set<String> thingIdsInList = list.map((device) => device.thingId!).toSet();
|
||||||
list.map((device) => device.thingId!).toSet();
|
|
||||||
for (var device in devices) {
|
for (var device in devices) {
|
||||||
if (!thingIdsInList.contains(device.thingId)) {
|
if (!thingIdsInList.contains(device.thingId)) {
|
||||||
log("Device with Thing ID ${device.thingId} is not in the notification settings list.");
|
log("Device with Thing ID ${device.thingId} is not in the notification settings list.");
|
||||||
await apiServices.execute(context, () async {
|
await apiServices.setupDeviceNotification(device.thingId!, device.name!);
|
||||||
await apiServices.setupDeviceNotification(
|
|
||||||
device.thingId!, device.name!);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
log("All devices are in the notification settings list.");
|
log("All devices are in the notification settings list.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
|
log("apiServices: getAllSettingsNotificationofDevices error!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isFunctionCall = true;
|
isFunctionCall = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,24 +3,24 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:sfm_app/feature/home/device_alias_model.dart';
|
||||||
import '../../../product/shared/shared_rocket_container.dart';
|
|
||||||
import '../../../product/constant/enums/app_route_enums.dart';
|
import '../../../product/constant/enums/app_route_enums.dart';
|
||||||
import '../../../product/constant/image/image_constants.dart';
|
import '../../../product/constant/image/image_constants.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
import '../../../product/utils/device_utils.dart';
|
import '../../../product/utils/device_utils.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
|
||||||
import '../device_alias_model.dart';
|
|
||||||
|
|
||||||
Future<Widget> notificationCard(BuildContext context, String notificationType,
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
|
|
||||||
|
Future<Widget> notificationCard(BuildContext context, String notiticationType,
|
||||||
String notificationTitle, DeviceWithAlias device) async {
|
String notificationTitle, DeviceWithAlias device) async {
|
||||||
String location = "";
|
String location = "";
|
||||||
if (device.areaPath != "") {
|
if (device.areaPath != "") {
|
||||||
location = await DeviceUtils.instance
|
location = await DeviceUtils.instance
|
||||||
.getFullDeviceLocation(context, device.areaPath!, "");
|
.getFullDeviceLocation(context, device.areaPath!);
|
||||||
}
|
}
|
||||||
String path = "";
|
String path = "";
|
||||||
|
// DateTime time = DateTime.now();
|
||||||
String time = "";
|
String time = "";
|
||||||
for (var sensor in device.status!.sensors!) {
|
for (var sensor in device.status!.sensors!) {
|
||||||
if (sensor.name! == "7") {
|
if (sensor.name! == "7") {
|
||||||
@@ -29,7 +29,7 @@ Future<Widget> notificationCard(BuildContext context, String notificationType,
|
|||||||
time = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
time = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notificationType == "lowBattery") {
|
if (notiticationType == "lowBattery") {
|
||||||
path = ImageConstants.instance.getImage("low_battery");
|
path = ImageConstants.instance.getImage("low_battery");
|
||||||
}
|
}
|
||||||
return Card(
|
return Card(
|
||||||
@@ -62,7 +62,10 @@ Future<Widget> notificationCard(BuildContext context, String notificationType,
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
"${appLocalization(context).device_title} ${device.isOwner! ? device.name : device.alias}",
|
"${appLocalization(context).device_title} ${device.isOwner! ? device.name : device.alias}",
|
||||||
style: context.responsiveBodyLargeWithBold,
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
@@ -89,7 +92,7 @@ Future<Widget> notificationCard(BuildContext context, String notificationType,
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
location,
|
location,
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 15),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
@@ -108,7 +111,7 @@ Future<Widget> notificationCard(BuildContext context, String notificationType,
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
time.toString(),
|
time.toString(),
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 15),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
@@ -117,46 +120,24 @@ Future<Widget> notificationCard(BuildContext context, String notificationType,
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
Align(
|
||||||
height: context.lowValue,
|
alignment: Alignment.centerRight,
|
||||||
),
|
child: OutlinedButton(
|
||||||
device.isOwner!
|
style: const ButtonStyle(
|
||||||
? Align(
|
backgroundColor: WidgetStatePropertyAll(Colors.blueAccent),
|
||||||
alignment: Alignment.centerRight,
|
),
|
||||||
child: OutlinedButton(
|
onPressed: () {
|
||||||
style: const ButtonStyle(
|
context.pushNamed(AppRoutes.DEVICE_DETAIL.name,
|
||||||
backgroundColor:
|
pathParameters: {'thingID': device.thingId!});
|
||||||
WidgetStatePropertyAll(Colors.blueAccent),
|
},
|
||||||
),
|
child: Text(
|
||||||
onPressed: () {
|
appLocalization(context).detail_message,
|
||||||
context.pushNamed(AppRoutes.DEVICE_DETAIL.name,
|
style: const TextStyle(
|
||||||
pathParameters: {'thingID': device.thingId!});
|
color: Colors.white,
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
appLocalization(context).detail_message,
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
ClipPath(
|
|
||||||
clipper: SharedRocketContainer(),
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.all(context.lowValue),
|
|
||||||
height: context.mediumValue,
|
|
||||||
width: context.dynamicWidth(0.22),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.green[300],
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
appLocalization(context).interfamily_page_name,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,100 +1,75 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'status_card.dart';
|
import 'status_card.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
class OverviewCard extends StatefulWidget {
|
class OverviewCard extends StatelessWidget {
|
||||||
final bool isOwner;
|
final bool isOwner;
|
||||||
final int total;
|
final int total;
|
||||||
final int active;
|
final int active;
|
||||||
final int inactive;
|
final int inactive;
|
||||||
final int warning;
|
final int warning;
|
||||||
final int unused;
|
final int unused;
|
||||||
final bool showTotal;
|
|
||||||
final bool showActive;
|
|
||||||
final bool showInactive;
|
|
||||||
final bool showWarning;
|
|
||||||
final bool showUnused;
|
|
||||||
|
|
||||||
const OverviewCard({
|
const OverviewCard(
|
||||||
super.key,
|
{super.key,
|
||||||
required this.isOwner,
|
required this.isOwner,
|
||||||
required this.total,
|
required this.total,
|
||||||
required this.active,
|
required this.active,
|
||||||
required this.inactive,
|
required this.inactive,
|
||||||
required this.warning,
|
required this.warning,
|
||||||
required this.unused,
|
required this.unused});
|
||||||
this.showTotal = true,
|
|
||||||
this.showActive = true,
|
|
||||||
this.showInactive = true,
|
|
||||||
this.showWarning = true,
|
|
||||||
this.showUnused = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<OverviewCard> createState() => _OverviewCardState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _OverviewCardState extends State<OverviewCard> {
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FittedBox(
|
return Card(
|
||||||
alignment: Alignment.topCenter,
|
margin: context.paddingLow,
|
||||||
child: SizedBox(
|
elevation: 8,
|
||||||
width: context.width,
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
||||||
child: Card(
|
child: Padding(
|
||||||
// elevation: 8,
|
padding: context.paddingNormal,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
|
child: Column(
|
||||||
child: Padding(
|
children: [
|
||||||
padding: context.paddingNormal,
|
Text(
|
||||||
child: Column(
|
isOwner
|
||||||
mainAxisSize: MainAxisSize.min,
|
? appLocalization(context).overview_message
|
||||||
|
: appLocalization(context).interfamily_page_name,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: context.normalValue),
|
||||||
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
StatusCard(
|
||||||
widget.isOwner
|
label: appLocalization(context).total_nof_devices_message,
|
||||||
? appLocalization(context).overview_message
|
count: total,
|
||||||
: appLocalization(context).interfamily_page_name,
|
color: Colors.blue,
|
||||||
style: context.h2,
|
|
||||||
),
|
),
|
||||||
SizedBox(height: context.normalValue),
|
StatusCard(
|
||||||
Column(
|
label: appLocalization(context).active_devices_message,
|
||||||
children: [
|
count: active,
|
||||||
if (widget.showTotal)
|
color: Colors.green,
|
||||||
StatusCard(
|
),
|
||||||
label: appLocalization(context).total_nof_devices_message,
|
StatusCard(
|
||||||
count: widget.total,
|
label: appLocalization(context).inactive_devices_message,
|
||||||
color: Colors.blue,
|
count: inactive,
|
||||||
),
|
color: Colors.grey,
|
||||||
if (widget.showActive)
|
),
|
||||||
StatusCard(
|
StatusCard(
|
||||||
label: appLocalization(context).active_devices_message,
|
label: appLocalization(context).warning_devices_message,
|
||||||
count: widget.active,
|
count: warning,
|
||||||
color: Colors.green,
|
color: Colors.orange,
|
||||||
),
|
),
|
||||||
if (widget.showInactive)
|
StatusCard(
|
||||||
StatusCard(
|
label: appLocalization(context).unused_devices_message,
|
||||||
label: appLocalization(context).inactive_devices_message,
|
count: unused,
|
||||||
count: widget.inactive,
|
color: Colors.yellow,
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
if (widget.showWarning)
|
|
||||||
StatusCard(
|
|
||||||
label: appLocalization(context).warning_devices_message,
|
|
||||||
count: widget.warning,
|
|
||||||
color: Colors.orange,
|
|
||||||
),
|
|
||||||
if (widget.showUnused)
|
|
||||||
StatusCard(
|
|
||||||
label: appLocalization(context).unused_devices_message,
|
|
||||||
count: widget.unused,
|
|
||||||
color: Colors.yellow,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../../../product/extension/context_extension.dart';
|
|
||||||
|
|
||||||
class StatusCard extends StatelessWidget {
|
class StatusCard extends StatelessWidget {
|
||||||
final String label;
|
final String label;
|
||||||
final int count;
|
final int count;
|
||||||
@@ -29,8 +27,14 @@ class StatusCard extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(label, style: context.responsiveBodyLarge),
|
Text(label, style: const TextStyle(fontSize: 18)),
|
||||||
Text(count.toString(), style: context.h2),
|
Text(
|
||||||
|
count.toString(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:maps_launcher/maps_launcher.dart';
|
import 'package:maps_launcher/maps_launcher.dart';
|
||||||
|
import 'package:badges/badges.dart' as badges;
|
||||||
import '../../../product/shared/shared_rocket_container.dart';
|
|
||||||
import '../device_alias_model.dart';
|
import '../device_alias_model.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../../product/constant/image/image_constants.dart';
|
import '../../../product/constant/image/image_constants.dart';
|
||||||
@@ -22,7 +21,7 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
String fullLocation = "";
|
String fullLocation = "";
|
||||||
if (device.areaPath != "") {
|
if (device.areaPath != "") {
|
||||||
fullLocation = await DeviceUtils.instance
|
fullLocation = await DeviceUtils.instance
|
||||||
.getFullDeviceLocation(context, device.areaPath!, "");
|
.getFullDeviceLocation(context, device.areaPath!);
|
||||||
}
|
}
|
||||||
String time = "";
|
String time = "";
|
||||||
for (var sensor in device.status!.sensors!) {
|
for (var sensor in device.status!.sensors!) {
|
||||||
@@ -34,7 +33,7 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
}
|
}
|
||||||
if (device.state! == 3) {
|
if (device.state! == 3) {
|
||||||
backgroundColor = Colors.grey;
|
backgroundColor = Colors.grey;
|
||||||
textColor = Colors.white;
|
textColor = Colors.black;
|
||||||
message = appLocalization(context).in_progress_message;
|
message = appLocalization(context).in_progress_message;
|
||||||
} else if (device.state! == 2) {
|
} else if (device.state! == 2) {
|
||||||
backgroundColor = const Color.fromARGB(255, 6, 138, 72);
|
backgroundColor = const Color.fromARGB(255, 6, 138, 72);
|
||||||
@@ -43,18 +42,32 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
} else if (device.state! == 1) {
|
} else if (device.state! == 1) {
|
||||||
backgroundColor = const Color.fromARGB(255, 250, 63, 63);
|
backgroundColor = const Color.fromARGB(255, 250, 63, 63);
|
||||||
textColor = Colors.white;
|
textColor = Colors.white;
|
||||||
if(device.isOwner == true){
|
|
||||||
|
|
||||||
message = appLocalization(context).button_fake_fire_message;
|
message = appLocalization(context).button_fake_fire_message;
|
||||||
}else{
|
|
||||||
message = appLocalization(context).smoke_detecting_message_lowercase;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
backgroundColor = Colors.black;
|
backgroundColor = Colors.black;
|
||||||
textColor = Colors.white;
|
textColor = Colors.white;
|
||||||
message = appLocalization(context).disconnect_message_uppercase;
|
message = appLocalization(context).disconnect_message_uppercase;
|
||||||
}
|
}
|
||||||
return Card(
|
return badges.Badge(
|
||||||
|
badgeAnimation: const badges.BadgeAnimation.fade(),
|
||||||
|
position: badges.BadgePosition.bottomStart(bottom: 15, start: 10),
|
||||||
|
badgeContent: device.isOwner!
|
||||||
|
? null
|
||||||
|
: Text(
|
||||||
|
appLocalization(context).interfamily_page_name,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
badgeStyle: badges.BadgeStyle(
|
||||||
|
shape: badges.BadgeShape.square,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
borderSide: const BorderSide(color: Colors.white, width: 2),
|
||||||
|
badgeColor: Theme.of(context).colorScheme.surfaceDim,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||||
|
),
|
||||||
|
child: Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: context.paddingLow,
|
padding: context.paddingLow,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -84,7 +97,10 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
"${appLocalization(context).device_title}: ${device.isOwner! ? device.name : device.alias}",
|
"${appLocalization(context).device_title}: ${device.isOwner! ? device.name : device.alias}",
|
||||||
style: context.responsiveBodyLargeWithBold,
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
@@ -112,7 +128,7 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
fullLocation,
|
fullLocation,
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 15),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
@@ -131,7 +147,7 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
time,
|
time,
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 15),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
@@ -143,158 +159,114 @@ Future<Widget> warningCard(BuildContext context, APIServices apiServices,
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: context.lowValue,
|
height: context.lowValue,
|
||||||
),
|
),
|
||||||
device.isOwner == true
|
Row(
|
||||||
? Row(
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
IconButton.outlined(
|
||||||
IconButton.outlined(
|
onPressed: () async => {},
|
||||||
onPressed: () async => {},
|
// displayListOfFireStationPhoneNumbers(testDevice),
|
||||||
// displayListOfFireStationPhoneNumbers(testDevice),
|
icon: IconConstants.instance.getMaterialIcon(Icons.call),
|
||||||
icon:
|
iconSize: 25,
|
||||||
IconConstants.instance.getMaterialIcon(Icons.call),
|
style: ButtonStyle(
|
||||||
iconSize: 25,
|
backgroundColor:
|
||||||
style: ButtonStyle(
|
WidgetStateProperty.all<Color>(Colors.blue[300]!),
|
||||||
backgroundColor:
|
|
||||||
WidgetStateProperty.all<Color>(Colors.blue[300]!),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
IconButton.outlined(
|
|
||||||
onPressed: () async {
|
|
||||||
String markerLabel = "Destination";
|
|
||||||
MapsLauncher.launchCoordinates(
|
|
||||||
double.parse(device.settings!.latitude!),
|
|
||||||
double.parse(device.settings!.longitude!),
|
|
||||||
markerLabel);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.directions),
|
|
||||||
iconSize: 25,
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor:
|
|
||||||
WidgetStateProperty.all<Color>(Colors.blue[300]!),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: context.mediumValue),
|
|
||||||
Expanded(
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: OutlinedButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor:
|
|
||||||
WidgetStatePropertyAll(backgroundColor)),
|
|
||||||
onPressed: () async {
|
|
||||||
if (message ==
|
|
||||||
appLocalization(context)
|
|
||||||
.button_fake_fire_message) {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
icon: const Icon(Icons.warning),
|
|
||||||
iconColor: Colors.red,
|
|
||||||
title: Text(appLocalization(context)
|
|
||||||
.confirm_fake_fire_message),
|
|
||||||
content: Text(appLocalization(context)
|
|
||||||
.confirm_fake_fire_body),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await apiServices.execute(context,
|
|
||||||
() async {
|
|
||||||
int statusCode = await apiServices
|
|
||||||
.confirmFakeFireByUser(
|
|
||||||
device.thingId!);
|
|
||||||
if (statusCode == 200) {
|
|
||||||
showNoIconTopSnackBar(
|
|
||||||
context,
|
|
||||||
appLocalization(context)
|
|
||||||
.notification_confirm_fake_fire_success,
|
|
||||||
Colors.green,
|
|
||||||
Colors.white);
|
|
||||||
} else {
|
|
||||||
showNoIconTopSnackBar(
|
|
||||||
context,
|
|
||||||
appLocalization(context)
|
|
||||||
.notification_confirm_fake_fire_failed,
|
|
||||||
Colors.red,
|
|
||||||
Colors.red);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
appLocalization(context)
|
|
||||||
.confirm_fake_fire_sure_message,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.red)),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: Text(appLocalization(context)
|
|
||||||
.cancel_button_content),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
showNoIconTopSnackBar(
|
|
||||||
context,
|
|
||||||
appLocalization(context)
|
|
||||||
.let_PCCC_handle_message,
|
|
||||||
Colors.orange,
|
|
||||||
Colors.white);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
message,
|
|
||||||
style: TextStyle(color: textColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
ClipPath(
|
|
||||||
clipper: SharedRocketContainer(),
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.all(context.lowValue),
|
|
||||||
height: context.mediumValue,
|
|
||||||
width: context.dynamicWidth(0.22),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.green[300],
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
appLocalization(context).interfamily_page_name,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: context.mediumValue),
|
|
||||||
Expanded(
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: OutlinedButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor:
|
|
||||||
WidgetStatePropertyAll(backgroundColor)),
|
|
||||||
onPressed: () async {},
|
|
||||||
child: Text(
|
|
||||||
message,
|
|
||||||
style: TextStyle(color: textColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
IconButton.outlined(
|
||||||
|
onPressed: () async {
|
||||||
|
String markerLabel = "Destination";
|
||||||
|
MapsLauncher.launchCoordinates(
|
||||||
|
double.parse(device.settings!.latitude!),
|
||||||
|
double.parse(device.settings!.longitude!),
|
||||||
|
markerLabel);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.directions),
|
||||||
|
iconSize: 25,
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
WidgetStateProperty.all<Color>(Colors.blue[300]!),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: context.mediumValue),
|
||||||
|
Expanded(
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: OutlinedButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
WidgetStatePropertyAll(backgroundColor)),
|
||||||
|
onPressed: () async {
|
||||||
|
if (message ==
|
||||||
|
appLocalization(context).button_fake_fire_message) {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
icon: const Icon(Icons.warning),
|
||||||
|
iconColor: Colors.red,
|
||||||
|
title: Text(appLocalization(context)
|
||||||
|
.confirm_fake_fire_message),
|
||||||
|
content: Text(appLocalization(context)
|
||||||
|
.confirm_fake_fire_body),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
int statusCode = await apiServices
|
||||||
|
.confirmFakeFireByUser(device.thingId!);
|
||||||
|
if (statusCode == 200) {
|
||||||
|
showNoIconTopSnackBar(
|
||||||
|
context,
|
||||||
|
appLocalization(context)
|
||||||
|
.notification_confirm_fake_fire_success,
|
||||||
|
Colors.green,
|
||||||
|
Colors.white);
|
||||||
|
} else {
|
||||||
|
showNoIconTopSnackBar(
|
||||||
|
context,
|
||||||
|
appLocalization(context)
|
||||||
|
.notification_confirm_fake_fire_failed,
|
||||||
|
Colors.red,
|
||||||
|
Colors.red);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
appLocalization(context)
|
||||||
|
.confirm_fake_fire_sure_message,
|
||||||
|
style:
|
||||||
|
const TextStyle(color: Colors.red)),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(appLocalization(context)
|
||||||
|
.cancel_button_content),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
showNoIconTopSnackBar(
|
||||||
|
context,
|
||||||
|
appLocalization(context).let_PCCC_handle_message,
|
||||||
|
Colors.orange,
|
||||||
|
Colors.white);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
message,
|
||||||
|
style: TextStyle(color: textColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,16 @@
|
|||||||
|
|
||||||
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 '../../../product/extension/context_extension.dart';
|
|
||||||
import '../../../bloc/group_detail_bloc.dart';
|
import '../../../bloc/group_detail_bloc.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
import '../../devices/device_model.dart';
|
import '../../devices/device_model.dart';
|
||||||
import 'group_detail_model.dart';
|
import 'group_detail_model.dart';
|
||||||
|
|
||||||
addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
||||||
String groupID, List<DeviceOfGroup> devices) async {
|
String groupID, List<DeviceOfGroup> devices) async {
|
||||||
List<Device> ownerDevices = await detailGroupBloc.getOwnerDevices(context);
|
List<Device> ownerDevices = await detailGroupBloc.getOwnerDevices();
|
||||||
List<String> selectedItems = [];
|
List<String> selectedItems = [];
|
||||||
List<String> selectedDevices = [];
|
List<String> selectedDevices = [];
|
||||||
if (devices.isNotEmpty) {
|
if (devices.isNotEmpty) {
|
||||||
@@ -37,7 +36,7 @@ addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
|||||||
),
|
),
|
||||||
hint: Text(
|
hint: Text(
|
||||||
appLocalization(context).choose_device_dropdownButton,
|
appLocalization(context).choose_device_dropdownButton,
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
items: ownerDevices
|
items: ownerDevices
|
||||||
.map(
|
.map(
|
||||||
@@ -74,7 +73,7 @@ addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
item.name!,
|
item.name!,
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -131,7 +130,7 @@ addDeviceDialog(BuildContext context, DetailGroupBloc detailGroupBloc,
|
|||||||
for (var device in selectedItems) {
|
for (var device in selectedItems) {
|
||||||
await detailGroupBloc.addDeviceToGroup(
|
await detailGroupBloc.addDeviceToGroup(
|
||||||
context, groupID, device);
|
context, groupID, device);
|
||||||
await detailGroupBloc.getGroupDetail(context,groupID);
|
await detailGroupBloc.getGroupDetail(groupID);
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import '../../../bloc/group_detail_bloc.dart';
|
import '../../../bloc/group_detail_bloc.dart';
|
||||||
import '../../../product/shared/shared_loading_animation.dart';
|
|
||||||
import 'group_detail_model.dart';
|
import 'group_detail_model.dart';
|
||||||
import '../../../product/base/bloc/base_bloc.dart';
|
import '../../../product/base/bloc/base_bloc.dart';
|
||||||
import '../../../product/constant/app/app_constants.dart';
|
import '../../../product/constant/app/app_constants.dart';
|
||||||
@@ -14,6 +13,7 @@ import '../../../product/services/api_services.dart';
|
|||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
import '../../../product/utils/device_utils.dart';
|
import '../../../product/utils/device_utils.dart';
|
||||||
import '../../../product/utils/response_status_utils.dart';
|
import '../../../product/utils/response_status_utils.dart';
|
||||||
|
|
||||||
import 'add_device_to_group_dialog.dart';
|
import 'add_device_to_group_dialog.dart';
|
||||||
|
|
||||||
class DetailGroupScreen extends StatefulWidget {
|
class DetailGroupScreen extends StatefulWidget {
|
||||||
@@ -35,14 +35,14 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
const duration = Duration(seconds: 10);
|
const duration = Duration(seconds: 10);
|
||||||
getGroupDetailTimer = Timer.periodic(
|
getGroupDetailTimer = Timer.periodic(
|
||||||
duration,
|
duration,
|
||||||
(Timer t) => detailGroupBloc.getGroupDetail(context, widget.group),
|
(Timer t) => detailGroupBloc.getGroupDetail(widget.group),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
getGroupDetailTimer?.cancel();
|
getGroupDetailTimer?.cancel();
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -51,8 +51,10 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
stream: detailGroupBloc.streamDetailGroup,
|
stream: detailGroupBloc.streamDetailGroup,
|
||||||
builder: (context, detailGroupSnapshot) {
|
builder: (context, detailGroupSnapshot) {
|
||||||
if (detailGroupSnapshot.data?.id == null) {
|
if (detailGroupSnapshot.data?.id == null) {
|
||||||
detailGroupBloc.getGroupDetail(context, widget.group);
|
detailGroupBloc.getGroupDetail(widget.group);
|
||||||
return const SharedLoadingAnimation();
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: scaffoldKey,
|
key: scaffoldKey,
|
||||||
@@ -138,8 +140,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
widget.group,
|
widget.group,
|
||||||
user.id!,
|
user.id!,
|
||||||
user.name!);
|
user.name!);
|
||||||
detailGroupBloc.getGroupDetail(
|
detailGroupBloc
|
||||||
context, widget.group);
|
.getGroupDetail(widget.group);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.check,
|
Icons.check,
|
||||||
@@ -156,8 +158,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
widget.group,
|
widget.group,
|
||||||
user.id!,
|
user.id!,
|
||||||
user.name!);
|
user.name!);
|
||||||
await detailGroupBloc.getGroupDetail(
|
await detailGroupBloc
|
||||||
context, widget.group);
|
.getGroupDetail(widget.group);
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.close,
|
Icons.close,
|
||||||
@@ -203,8 +205,8 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
widget.group,
|
widget.group,
|
||||||
user.id!,
|
user.id!,
|
||||||
user.name!);
|
user.name!);
|
||||||
await detailGroupBloc.getGroupDetail(
|
await detailGroupBloc
|
||||||
context, widget.group);
|
.getGroupDetail(widget.group);
|
||||||
},
|
},
|
||||||
value: 2,
|
value: 2,
|
||||||
child: Text(appLocalization(context)
|
child: Text(appLocalization(context)
|
||||||
@@ -237,7 +239,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
? PopupMenuButton(
|
? PopupMenuButton(
|
||||||
icon: IconConstants.instance
|
icon: IconConstants.instance
|
||||||
.getMaterialIcon(Icons.more_horiz),
|
.getMaterialIcon(Icons.more_horiz),
|
||||||
itemBuilder: (context) => [
|
itemBuilder: (contex) => [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
@@ -323,17 +325,15 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
Future.delayed(context.lowDuration).then(
|
Future.delayed(context.lowDuration).then(
|
||||||
(value) => Navigator.pop(context),
|
(value) => Navigator.pop(context),
|
||||||
);
|
);
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices
|
||||||
int statusCode = await apiServices
|
.deleteGroup(widget.group);
|
||||||
.deleteGroup(widget.group);
|
showSnackBarResponseByStatusCode(
|
||||||
showSnackBarResponseByStatusCode(
|
context,
|
||||||
context,
|
statusCode,
|
||||||
statusCode,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_delete_group_success,
|
||||||
.notification_delete_group_success,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_delete_group_failed);
|
||||||
.notification_delete_group_failed);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
@@ -429,7 +429,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SafeArea(
|
return Expanded(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: devices.isEmpty
|
child: devices.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
@@ -461,8 +461,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
DeviceUtils.instance.checkStateDevice(
|
DeviceUtils.instance.checkStateDevice(
|
||||||
context, devices[index].state!),
|
context, devices[index].state!),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: DeviceUtils.instance.getTableRowColor(
|
color: DeviceUtils.instance.getTableRowColor(context,
|
||||||
context,
|
|
||||||
devices[index].state!,
|
devices[index].state!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -494,7 +493,10 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text('${appLocalization(context).map_result}: ',
|
Text('${appLocalization(context).map_result}: ',
|
||||||
style: context.h3),
|
style: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black)),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
@@ -524,7 +526,7 @@ class _DetailGroupScreenState extends State<DetailGroupScreen> {
|
|||||||
String alias = aliasController.text;
|
String alias = aliasController.text;
|
||||||
await detailGroupBloc.updateDeviceNameInGroup(
|
await detailGroupBloc.updateDeviceNameInGroup(
|
||||||
context, device.thingId!, alias);
|
context, device.thingId!, alias);
|
||||||
await detailGroupBloc.getGroupDetail(context, widget.group);
|
await detailGroupBloc.getGroupDetail(widget.group);
|
||||||
},
|
},
|
||||||
child: Text(appLocalization(context).confirm_button_content)),
|
child: Text(appLocalization(context).confirm_button_content)),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,125 +1,165 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import '../../../product/constant/enums/app_route_enums.dart';
|
import '../../../product/constant/enums/app_route_enums.dart';
|
||||||
import 'groups_model.dart';
|
import 'groups_model.dart';
|
||||||
import 'groups_widget.dart';
|
|
||||||
import '../../../bloc/inter_family_bloc.dart';
|
import '../../../bloc/inter_family_bloc.dart';
|
||||||
import '../inter_family_widget.dart';
|
import '../inter_family_widget.dart';
|
||||||
|
import '../../../product/base/bloc/base_bloc.dart';
|
||||||
import '../../../product/constant/app/app_constants.dart';
|
import '../../../product/constant/app/app_constants.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
/// Stateless widget that renders a provided list of groups. The parent
|
import 'groups_widget.dart';
|
||||||
/// screen owns fetching/updating the list; this widget only displays it and
|
|
||||||
/// forwards actions to the provided [InterFamilyBloc].
|
class GroupsScreen extends StatefulWidget {
|
||||||
class GroupsScreen extends StatelessWidget {
|
const GroupsScreen({super.key, required this.role});
|
||||||
const GroupsScreen(
|
|
||||||
{super.key,
|
|
||||||
required this.role,
|
|
||||||
required this.groups,
|
|
||||||
required this.interFamilyBloc});
|
|
||||||
|
|
||||||
final String role;
|
final String role;
|
||||||
final List<Group> groups;
|
|
||||||
final InterFamilyBloc interFamilyBloc;
|
@override
|
||||||
|
State<GroupsScreen> createState() => _GroupsScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GroupsScreenState extends State<GroupsScreen> {
|
||||||
|
late InterFamilyBloc interFamilyBloc;
|
||||||
|
Timer? getAllGroupsTimer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
interFamilyBloc = BlocProvider.of(context);
|
||||||
|
const duration = Duration(seconds: 10);
|
||||||
|
getAllGroupsTimer = Timer.periodic(
|
||||||
|
duration,
|
||||||
|
(Timer t) => interFamilyBloc.getAllGroup(widget.role),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
getAllGroupsTimer?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (role != ApplicationConstants.OWNER_GROUP &&
|
if (widget.role == ApplicationConstants.OWNER_GROUP ||
|
||||||
role != ApplicationConstants.PARTICIPANT_GROUP) {
|
widget.role == ApplicationConstants.PARTICIPANT_GROUP) {
|
||||||
|
interFamilyBloc.getAllGroup(widget.role);
|
||||||
|
return StreamBuilder<List<Group>>(
|
||||||
|
stream: interFamilyBloc.streamCurrentGroups,
|
||||||
|
builder: (context, groupsSnapshot) {
|
||||||
|
return Scaffold(
|
||||||
|
body: groupsSnapshot.data?.isEmpty ?? true
|
||||||
|
? const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
)
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: groupsSnapshot.data!.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return ListTile(
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(AppRoutes.GROUP_DETAIL.name,
|
||||||
|
pathParameters: {"groupId": groupsSnapshot.data![index].id!},
|
||||||
|
extra: widget.role);
|
||||||
|
},
|
||||||
|
leading: IconConstants.instance.getMaterialIcon(Icons.diversity_2),
|
||||||
|
title: Text(
|
||||||
|
groupsSnapshot.data![index].name ?? '',
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
subtitle: Text(groupsSnapshot.data![index].description ?? ""),
|
||||||
|
trailing: widget.role == ApplicationConstants.OWNER_GROUP
|
||||||
|
? PopupMenuButton(
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
bottomLeft: Radius.circular(8.0),
|
||||||
|
bottomRight: Radius.circular(8.0),
|
||||||
|
topLeft: Radius.circular(8.0),
|
||||||
|
topRight: Radius.circular(8.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
itemBuilder: (ctx) => [
|
||||||
|
_buildPopupMenuItem(groupsSnapshot.data![index], context,
|
||||||
|
appLocalization(context).share_group_title, Icons.share, 4),
|
||||||
|
_buildPopupMenuItem(
|
||||||
|
groupsSnapshot.data![index],
|
||||||
|
context,
|
||||||
|
appLocalization(context).change_group_infomation_title,
|
||||||
|
Icons.settings_backup_restore,
|
||||||
|
2),
|
||||||
|
_buildPopupMenuItem(
|
||||||
|
groupsSnapshot.data![index],
|
||||||
|
context,
|
||||||
|
appLocalization(context).delete_group_title,
|
||||||
|
Icons.delete_forever_rounded,
|
||||||
|
3),
|
||||||
|
],
|
||||||
|
icon: const Icon(Icons.more_horiz),
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groups.isEmpty) {
|
|
||||||
return Center(child: Text(appLocalization(context).dont_have_group));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: groups.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final group = groups[index];
|
|
||||||
return ListTile(
|
|
||||||
onTap: () => context.pushNamed(AppRoutes.GROUP_DETAIL.name,
|
|
||||||
pathParameters: {"groupId": group.id!}, extra: role),
|
|
||||||
leading: IconConstants.instance.getMaterialIcon(Icons.diversity_2),
|
|
||||||
title: Text(group.name ?? '',
|
|
||||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
|
||||||
subtitle: Text(group.description ?? ''),
|
|
||||||
trailing: role == ApplicationConstants.OWNER_GROUP
|
|
||||||
? _ownerPopupMenu(group, context)
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _ownerPopupMenu(Group group, BuildContext context) {
|
PopupMenuItem _buildPopupMenuItem(
|
||||||
return PopupMenuButton<int>(
|
Group group, BuildContext context, String title, IconData iconData, int position) {
|
||||||
shape: const RoundedRectangleBorder(
|
return PopupMenuItem(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8.0))),
|
|
||||||
itemBuilder: (ctx) => [
|
|
||||||
_buildPopupMenuItem(group, context,
|
|
||||||
appLocalization(context).share_group_title, Icons.share, 4),
|
|
||||||
_buildPopupMenuItem(
|
|
||||||
group,
|
|
||||||
context,
|
|
||||||
appLocalization(context).change_group_infomation_title,
|
|
||||||
Icons.settings_backup_restore,
|
|
||||||
2),
|
|
||||||
_buildPopupMenuItem(
|
|
||||||
group,
|
|
||||||
context,
|
|
||||||
appLocalization(context).delete_group_title,
|
|
||||||
Icons.delete_forever_rounded,
|
|
||||||
3),
|
|
||||||
],
|
|
||||||
icon: const Icon(Icons.more_horiz),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
PopupMenuItem<int> _buildPopupMenuItem(Group group, BuildContext context,
|
|
||||||
String title, IconData iconData, int value) {
|
|
||||||
return PopupMenuItem<int>(
|
|
||||||
value: value,
|
|
||||||
child: Row(children: [
|
|
||||||
Icon(iconData, color: Colors.black),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Text(title)
|
|
||||||
]),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Future.delayed(context.lowDuration, () {
|
if (title == appLocalization(context).share_group_title) {
|
||||||
if (title == appLocalization(context).share_group_title) {
|
Future.delayed(context.lowDuration, () {
|
||||||
shareGroup(context, group);
|
shareGroup(context, group);
|
||||||
} else if (title ==
|
});
|
||||||
appLocalization(context).change_group_infomation_title) {
|
} else if (title == appLocalization(context).change_group_infomation_title) {
|
||||||
|
Future.delayed(context.lowDuration, () {
|
||||||
createOrJoinGroupDialog(
|
createOrJoinGroupDialog(
|
||||||
context,
|
context,
|
||||||
interFamilyBloc,
|
interFamilyBloc,
|
||||||
role,
|
widget.role,
|
||||||
appLocalization(context).change_group_infomation_content,
|
appLocalization(context).change_group_infomation_content,
|
||||||
appLocalization(context).group_name_title,
|
appLocalization(context).group_name_title,
|
||||||
group.name ?? '',
|
group.name!,
|
||||||
false,
|
false,
|
||||||
group.id ?? '',
|
group.id!,
|
||||||
appLocalization(context).description_group,
|
appLocalization(context).description_group,
|
||||||
group.description ?? '',
|
group.description ?? "");
|
||||||
);
|
});
|
||||||
} else if (title == appLocalization(context).delete_group_title) {
|
} else if (title == appLocalization(context).delete_group_title) {
|
||||||
|
Future.delayed(context.lowDuration, () {
|
||||||
showActionDialog(
|
showActionDialog(
|
||||||
context,
|
context,
|
||||||
role,
|
widget.role,
|
||||||
interFamilyBloc,
|
interFamilyBloc,
|
||||||
appLocalization(context).delete_group_title,
|
appLocalization(context).delete_group_title,
|
||||||
appLocalization(context).delete_group_content,
|
appLocalization(context).delete_group_content,
|
||||||
group,
|
group);
|
||||||
);
|
});
|
||||||
}
|
} else {}
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
value: position,
|
||||||
|
child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
iconData,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(title),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
|
|
||||||
import '../../../bloc/inter_family_bloc.dart';
|
import '../../../bloc/inter_family_bloc.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
import 'groups_model.dart';
|
import 'groups_model.dart';
|
||||||
|
|
||||||
shareGroup(BuildContext context, Group group) {
|
shareGroup(BuildContext context, Group group) {
|
||||||
@@ -80,8 +80,7 @@ showActionDialog(
|
|||||||
if (dialogTitle == appLocalization(context).delete_group_title) {
|
if (dialogTitle == appLocalization(context).delete_group_title) {
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
await interFamilyBloc.deleteGroup(context, group.id!);
|
await interFamilyBloc.deleteGroup(context, group.id!);
|
||||||
// ignore: use_build_context_synchronously
|
interFamilyBloc.getAllGroup(role);
|
||||||
interFamilyBloc.getAllGroup(context,role);
|
|
||||||
} else {}
|
} else {}
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'groups/groups_screen.dart';
|
import 'groups/groups_screen.dart';
|
||||||
import 'groups/groups_model.dart';
|
|
||||||
import '../../bloc/inter_family_bloc.dart';
|
import '../../bloc/inter_family_bloc.dart';
|
||||||
import 'inter_family_widget.dart';
|
import 'inter_family_widget.dart';
|
||||||
import '../../product/base/bloc/base_bloc.dart';
|
import '../../product/base/bloc/base_bloc.dart';
|
||||||
@@ -26,31 +25,22 @@ class _InterFamilyScreenState extends State<InterFamilyScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
interFamilyBloc = BlocProvider.of(context);
|
interFamilyBloc = BlocProvider.of(context);
|
||||||
// fetch initial groups for the default selected tab
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
interFamilyBloc.getAllGroup(
|
|
||||||
context,
|
|
||||||
_selectedIndex == 0
|
|
||||||
? ApplicationConstants.OWNER_GROUP
|
|
||||||
: ApplicationConstants.PARTICIPANT_GROUP);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Group> ownerGroups = [];
|
final _widgetOptions = <Widget>[
|
||||||
List<Group> participantGroups = [];
|
BlocProvider(
|
||||||
|
blocBuilder: () => InterFamilyBloc(),
|
||||||
List<Widget> get _widgetOptions => [
|
child: const GroupsScreen(
|
||||||
GroupsScreen(
|
role: ApplicationConstants.OWNER_GROUP,
|
||||||
role: ApplicationConstants.OWNER_GROUP,
|
),
|
||||||
groups: ownerGroups,
|
),
|
||||||
interFamilyBloc: interFamilyBloc,
|
BlocProvider(
|
||||||
),
|
blocBuilder: () => InterFamilyBloc(),
|
||||||
GroupsScreen(
|
child: const GroupsScreen(
|
||||||
role: ApplicationConstants.PARTICIPANT_GROUP,
|
role: ApplicationConstants.PARTICIPANT_GROUP,
|
||||||
groups: participantGroups,
|
),
|
||||||
interFamilyBloc: interFamilyBloc,
|
),
|
||||||
),
|
];
|
||||||
];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -59,109 +49,96 @@ class _InterFamilyScreenState extends State<InterFamilyScreen> {
|
|||||||
stream: interFamilyBloc.streamSelectedScreen,
|
stream: interFamilyBloc.streamSelectedScreen,
|
||||||
initialData: _selectedIndex,
|
initialData: _selectedIndex,
|
||||||
builder: (context, selectSnapshot) {
|
builder: (context, selectSnapshot) {
|
||||||
// subscribe to groups stream and update local lists so child widgets render instantly
|
return Scaffold(
|
||||||
return StreamBuilder<List<Group>>(
|
appBar: AppBar(
|
||||||
stream: interFamilyBloc.streamCurrentGroups,
|
actions: [
|
||||||
builder: (context, groupsSnapshot) {
|
ElevatedButton(
|
||||||
if (groupsSnapshot.hasData) {
|
onPressed: () {
|
||||||
final all = groupsSnapshot.data!;
|
if (selectSnapshot.data == 0) {
|
||||||
ownerGroups = all
|
createOrJoinGroupDialog(
|
||||||
.where((g) => g.isOwner == true && g.visibility == 'PUBLIC')
|
context,
|
||||||
.toList();
|
interFamilyBloc,
|
||||||
participantGroups = all
|
selectSnapshot.data! == 0
|
||||||
.where((g) => g.isOwner == null && g.visibility == 'PUBLIC')
|
? ApplicationConstants.OWNER_GROUP
|
||||||
.toList();
|
: ApplicationConstants.PARTICIPANT_GROUP,
|
||||||
}
|
appLocalization(context).add_new_group,
|
||||||
// build UI below
|
appLocalization(context).group_name_title,
|
||||||
return Scaffold(
|
"",
|
||||||
appBar: AppBar(
|
false,
|
||||||
actions: [
|
"",
|
||||||
ElevatedButton(
|
"",
|
||||||
onPressed: () {
|
"");
|
||||||
if (selectSnapshot.data == 0) {
|
} else {
|
||||||
createOrJoinGroupDialog(
|
createOrJoinGroupDialog(
|
||||||
context,
|
context,
|
||||||
interFamilyBloc,
|
interFamilyBloc,
|
||||||
ApplicationConstants.OWNER_GROUP,
|
selectSnapshot.data! == 0
|
||||||
appLocalization(context).add_new_group,
|
? ApplicationConstants.OWNER_GROUP
|
||||||
appLocalization(context).group_name_title,
|
: ApplicationConstants.PARTICIPANT_GROUP,
|
||||||
"",
|
appLocalization(context).join_group,
|
||||||
false,
|
appLocalization(context).group_id_title,
|
||||||
"",
|
'',
|
||||||
"",
|
true,
|
||||||
"",
|
"",
|
||||||
);
|
appLocalization(context).group_name_title,
|
||||||
} else {
|
"");
|
||||||
createOrJoinGroupDialog(
|
}
|
||||||
context,
|
},
|
||||||
interFamilyBloc,
|
style: ElevatedButton.styleFrom(
|
||||||
ApplicationConstants.PARTICIPANT_GROUP,
|
shape: const CircleBorder(),
|
||||||
appLocalization(context).join_group,
|
),
|
||||||
appLocalization(context).group_id_title,
|
child: IconConstants.instance.getMaterialIcon(Icons.add),
|
||||||
'',
|
),
|
||||||
true,
|
],
|
||||||
"",
|
leading: Builder(
|
||||||
appLocalization(context).group_name_title,
|
builder: (context) {
|
||||||
"",
|
return IconButton(
|
||||||
);
|
onPressed: () {
|
||||||
}
|
Scaffold.of(context).openDrawer();
|
||||||
},
|
},
|
||||||
style:
|
icon: const Icon(Icons.menu),
|
||||||
ElevatedButton.styleFrom(shape: const CircleBorder()),
|
);
|
||||||
child: IconConstants.instance.getMaterialIcon(Icons.add),
|
},
|
||||||
),
|
),
|
||||||
],
|
title: StreamBuilder<String>(
|
||||||
leading: Builder(
|
stream: interFamilyBloc.streamTitleScreen,
|
||||||
builder: (context) {
|
initialData: title,
|
||||||
return IconButton(
|
builder: (context, titleSnapshot) {
|
||||||
onPressed: () {
|
return Center(
|
||||||
Scaffold.of(context).openDrawer();
|
child: Text(titleSnapshot.data ?? title),
|
||||||
},
|
);
|
||||||
icon: const Icon(Icons.menu),
|
},
|
||||||
);
|
),
|
||||||
|
),
|
||||||
|
drawer: Drawer(
|
||||||
|
width: context.dynamicWidth(0.4),
|
||||||
|
child: ListView(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: Text(appLocalization(context).my_group_title),
|
||||||
|
selected: _selectedIndex == 0,
|
||||||
|
onTap: () {
|
||||||
|
_onItemTapped(0);
|
||||||
|
title = appLocalization(context).my_group_title;
|
||||||
|
interFamilyBloc.sinkTitleScreen.add(title);
|
||||||
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: StreamBuilder<String>(
|
ListTile(
|
||||||
stream: interFamilyBloc.streamTitleScreen,
|
title: Text(appLocalization(context).invite_group),
|
||||||
initialData: title,
|
selected: _selectedIndex == 1,
|
||||||
builder: (context, titleSnapshot) {
|
onTap: () {
|
||||||
return Center(
|
_onItemTapped(1);
|
||||||
child: Text(titleSnapshot.data ?? title),
|
title = appLocalization(context).invite_group;
|
||||||
);
|
interFamilyBloc.sinkTitleScreen.add(title);
|
||||||
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
drawer: Drawer(
|
),
|
||||||
width: context.dynamicWidth(0.6),
|
),
|
||||||
child: ListView(
|
body: _widgetOptions[selectSnapshot.data ?? _selectedIndex],
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
children: [
|
|
||||||
ListTile(
|
|
||||||
title: Text(appLocalization(context).my_group_title),
|
|
||||||
selected: _selectedIndex == 0,
|
|
||||||
onTap: () {
|
|
||||||
_onItemTapped(0);
|
|
||||||
title = appLocalization(context).my_group_title;
|
|
||||||
interFamilyBloc.sinkTitleScreen.add(title);
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
title: Text(appLocalization(context).invite_group),
|
|
||||||
selected: _selectedIndex == 1,
|
|
||||||
onTap: () {
|
|
||||||
_onItemTapped(1);
|
|
||||||
title = appLocalization(context).invite_group;
|
|
||||||
interFamilyBloc.sinkTitleScreen.add(title);
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: _widgetOptions[selectSnapshot.data ?? _selectedIndex],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -182,11 +159,5 @@ class _InterFamilyScreenState extends State<InterFamilyScreen> {
|
|||||||
interFamilyBloc.sinkSelectedScreen.add(_selectedIndex);
|
interFamilyBloc.sinkSelectedScreen.add(_selectedIndex);
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
interFamilyBloc.sinkIsLoading.add(isLoading);
|
interFamilyBloc.sinkIsLoading.add(isLoading);
|
||||||
// fetch groups for the selected tab immediately
|
|
||||||
interFamilyBloc.getAllGroup(
|
|
||||||
context,
|
|
||||||
_selectedIndex == 0
|
|
||||||
? ApplicationConstants.OWNER_GROUP
|
|
||||||
: ApplicationConstants.PARTICIPANT_GROUP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ createOrJoinGroupDialog(
|
|||||||
try {
|
try {
|
||||||
await interFamilyBloc.createGroup(
|
await interFamilyBloc.createGroup(
|
||||||
context, groupName, description);
|
context, groupName, description);
|
||||||
interFamilyBloc.getAllGroup(context, role);
|
interFamilyBloc.getAllGroup(role);
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// log("Lỗi khi tạo nhóm: $e");
|
// log("Lỗi khi tạo nhóm: $e");
|
||||||
@@ -131,9 +131,9 @@ createOrJoinGroupDialog(
|
|||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
.change_group_infomation_content) {
|
.change_group_infomation_content) {
|
||||||
try {
|
try {
|
||||||
await interFamilyBloc.changeGroupInformation(
|
await interFamilyBloc.changeGroupInfomation(
|
||||||
context, groupID, groupName, description);
|
context, groupID, groupName, description);
|
||||||
interFamilyBloc.getAllGroup(context, role);
|
interFamilyBloc.getAllGroup(role);
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// log("Lỗi khi sửa nhóm: $e");
|
// log("Lỗi khi sửa nhóm: $e");
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:badges/badges.dart' as badges;
|
import 'package:badges/badges.dart' as badges;
|
||||||
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';
|
import 'package:persistent_bottom_nav_bar/persistent_bottom_nav_bar.dart';
|
||||||
|
import 'package:sfm_app/product/utils/permission_handler.dart';
|
||||||
import '../../product/shared/shared_snack_bar.dart';
|
|
||||||
import '../../product/services/notification_services.dart';
|
|
||||||
import '../../product/utils/permission_handler.dart';
|
|
||||||
import '../../product/permission/notification_permission.dart';
|
import '../../product/permission/notification_permission.dart';
|
||||||
|
import '../../product/services/notification_services.dart';
|
||||||
import '../settings/profile/profile_model.dart';
|
import '../settings/profile/profile_model.dart';
|
||||||
import '../../product/extension/context_extension.dart';
|
import '../../product/extension/context_extension.dart';
|
||||||
import '../../bloc/home_bloc.dart';
|
import '../../bloc/home_bloc.dart';
|
||||||
import '../../product/constant/app/app_constants.dart';
|
import '../../product/constant/app/app_constants.dart';
|
||||||
import '../../product/constant/enums/app_route_enums.dart';
|
import '../../product/constant/enums/app_route_enums.dart';
|
||||||
|
import '../../product/permission/location_permission.dart';
|
||||||
import '../../product/services/theme_services.dart';
|
import '../../product/services/theme_services.dart';
|
||||||
import '../../bloc/devices_manager_bloc.dart';
|
import '../../bloc/devices_manager_bloc.dart';
|
||||||
import '../devices/devices_manager_screen.dart';
|
import '../devices/devices_manager_screen.dart';
|
||||||
@@ -44,10 +46,22 @@ class MainScreen extends StatefulWidget {
|
|||||||
State<MainScreen> createState() => _MainScreenState();
|
State<MainScreen> createState() => _MainScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
PersistentTabController controller = PersistentTabController(initialIndex: 0);
|
||||||
|
|
||||||
|
// @pragma('vm:entry-point')
|
||||||
|
// Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
|
// log("Full background message payload: ${message.toMap()}");
|
||||||
|
// await Firebase.initializeApp();
|
||||||
|
// final notificationServices = NotificationServices();
|
||||||
|
// await notificationServices.initLocalNotifications(controller);
|
||||||
|
// await notificationServices.showNotification(message);
|
||||||
|
// log("Background message handled: ${message.data['title']}");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
final NotificationServices notificationServices = NotificationServices();
|
// final NotificationServices notificationServices = NotificationServices();
|
||||||
late MainBloc mainBloc;
|
late MainBloc mainBloc;
|
||||||
bool isVN = true;
|
bool isVN = true;
|
||||||
bool isLight = true;
|
bool isLight = true;
|
||||||
@@ -75,12 +89,7 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
mainBloc.sinkIsVNIcon.add(isVN);
|
mainBloc.sinkIsVNIcon.add(isVN);
|
||||||
mainBloc.sinkThemeMode.add(isLight);
|
mainBloc.sinkThemeMode.add(isLight);
|
||||||
checkAndRequestPermission();
|
checkAndRequestPermission();
|
||||||
NotificationServices.requestNotificationPermission();
|
NotificationPermission.instance.checkNotificationPermission(context);
|
||||||
// NotificationPermission.instance.checkNotificationPermission(context);
|
|
||||||
// bool? notificationStatus = await NotificationPermission.instance.requestNotificationPermission();
|
|
||||||
// if(notificationStatus == false){
|
|
||||||
// showNoIconTopSnackBar(context, "Yêu cầu quyền thông báo không thành công", Colors.orange, Colors.white12);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -91,7 +100,7 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
initialCheck();
|
initialCheck();
|
||||||
getBellNotification();
|
getBellNotification();
|
||||||
mainBloc.getUserProfile(context);
|
mainBloc.getUserProfile();
|
||||||
|
|
||||||
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
|
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
|
||||||
log("New FCM Token: $newToken");
|
log("New FCM Token: $newToken");
|
||||||
@@ -99,86 +108,129 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
mainBloc.sendNotificationToken(newToken);
|
mainBloc.sendNotificationToken(newToken);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||||
|
RemoteNotification? notification = message.notification;
|
||||||
|
AndroidNotification? android = message.notification?.android;
|
||||||
|
if (notification != null && android != null ) {
|
||||||
|
const AndroidNotificationDetails androidPlatformChannelSpecifics =
|
||||||
|
AndroidNotificationDetails(
|
||||||
|
'your channel id', 'your channel name',
|
||||||
|
importance: Importance.max,
|
||||||
|
priority: Priority.high,
|
||||||
|
ticker: 'ticker');
|
||||||
|
const NotificationDetails platformChannelSpecifics =
|
||||||
|
NotificationDetails(android: androidPlatformChannelSpecifics);
|
||||||
|
flutterLocalNotificationsPlugin.show(
|
||||||
|
notification.hashCode, notification.title, notification.body, platformChannelSpecifics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
// notificationServices.initLocalNotifications(controller);
|
// notificationServices.initLocalNotifications(controller);
|
||||||
// notificationServices.firebaseInit(context);
|
// notificationServices.firebaseInit(context);
|
||||||
// NotificationServices().setupInteractMessage(controller);
|
// NotificationServices().setupInteractMessage(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
super.didChangeAppLifecycleState(state);
|
||||||
|
if (state == AppLifecycleState.inactive) {
|
||||||
|
log("App Inactive");
|
||||||
|
} else if (state == AppLifecycleState.resumed) {
|
||||||
|
log("App Resumed");
|
||||||
|
} else if (state == AppLifecycleState.paused) {
|
||||||
|
log("App paused");
|
||||||
|
} else if (state == AppLifecycleState.detached) {
|
||||||
|
log("App detached");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
List<PersistentBottomNavBarItem> _navBarsItems() {
|
||||||
List<PersistentTabConfig> tabs = [
|
return [
|
||||||
PersistentTabConfig(
|
PersistentBottomNavBarItem(
|
||||||
screen: BlocProvider(
|
icon: IconConstants.instance.getMaterialIcon(Icons.home),
|
||||||
child: const HomeScreen(),
|
title: appLocalization(context).home_page_destination,
|
||||||
blocBuilder: () => HomeBloc(),
|
activeColorPrimary: Colors.blue,
|
||||||
),
|
inactiveColorPrimary: Colors.grey,
|
||||||
item: ItemConfig(
|
inactiveIcon:
|
||||||
icon: IconConstants.instance.getMaterialIcon(Icons.home),
|
IconConstants.instance.getMaterialIcon(Icons.home_outlined),
|
||||||
title: appLocalization(context).home_page_destination,
|
|
||||||
inactiveIcon:
|
|
||||||
IconConstants.instance.getMaterialIcon(Icons.home_outlined),
|
|
||||||
iconSize: 30,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
PersistentTabConfig(
|
PersistentBottomNavBarItem(
|
||||||
screen: BlocProvider(
|
icon: IconConstants.instance.getMaterialIcon(Icons.settings),
|
||||||
|
title: appLocalization(context).manager_page_destination,
|
||||||
|
activeColorPrimary: Colors.blue,
|
||||||
|
inactiveColorPrimary: Colors.grey,
|
||||||
|
inactiveIcon:
|
||||||
|
IconConstants.instance.getMaterialIcon(Icons.settings_outlined),
|
||||||
|
),
|
||||||
|
PersistentBottomNavBarItem(
|
||||||
|
icon: IconConstants.instance.getMaterialIcon(Icons.location_on),
|
||||||
|
title: appLocalization(context).map_page_destination,
|
||||||
|
activeColorPrimary: Colors.blue,
|
||||||
|
inactiveColorPrimary: Colors.grey,
|
||||||
|
inactiveIcon:
|
||||||
|
IconConstants.instance.getMaterialIcon(Icons.location_on_outlined),
|
||||||
|
),
|
||||||
|
PersistentBottomNavBarItem(
|
||||||
|
icon: IconConstants.instance.getMaterialIcon(Icons.history),
|
||||||
|
title: appLocalization(context).history_page_destination,
|
||||||
|
activeColorPrimary: Colors.blue,
|
||||||
|
inactiveColorPrimary: Colors.grey,
|
||||||
|
inactiveIcon:
|
||||||
|
IconConstants.instance.getMaterialIcon(Icons.history_outlined),
|
||||||
|
),
|
||||||
|
PersistentBottomNavBarItem(
|
||||||
|
icon: IconConstants.instance.getMaterialIcon(Icons.group),
|
||||||
|
title: appLocalization(context).group_page_destination,
|
||||||
|
activeColorPrimary: Colors.blue,
|
||||||
|
inactiveColorPrimary: Colors.grey,
|
||||||
|
inactiveIcon:
|
||||||
|
IconConstants.instance.getMaterialIcon(Icons.group_outlined),
|
||||||
|
),
|
||||||
|
// PersistentBottomNavBarItem(
|
||||||
|
// icon: IconConstants.instance
|
||||||
|
// .getMaterialIcon(Icons.notifications_outlined),
|
||||||
|
// title: appLocalization(context).notification,
|
||||||
|
// activeColorPrimary: Colors.blue,
|
||||||
|
// inactiveColorPrimary: Colors.grey,
|
||||||
|
// inactiveIcon: IconConstants.instance
|
||||||
|
// .getMaterialIcon(Icons.notifications_outlined),
|
||||||
|
// ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildScreens() {
|
||||||
|
return [
|
||||||
|
BlocProvider(
|
||||||
|
child: const HomeScreen(),
|
||||||
|
blocBuilder: () => HomeBloc(),
|
||||||
|
),
|
||||||
|
BlocProvider(
|
||||||
child: const DevicesManagerScreen(),
|
child: const DevicesManagerScreen(),
|
||||||
blocBuilder: () => DevicesManagerBloc(),
|
blocBuilder: () => DevicesManagerBloc()),
|
||||||
),
|
BlocProvider(
|
||||||
item: ItemConfig(
|
child: const MapScreen(),
|
||||||
icon: IconConstants.instance.getMaterialIcon(Icons.settings),
|
blocBuilder: () => MapBloc(),
|
||||||
title: appLocalization(context).manager_page_destination,
|
|
||||||
inactiveIcon:
|
|
||||||
IconConstants.instance.getMaterialIcon(Icons.settings_outlined),
|
|
||||||
iconSize: 30,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
PersistentTabConfig(
|
BlocProvider(
|
||||||
screen: BlocProvider(
|
child: const DeviceLogsScreen(),
|
||||||
child: const MapScreen(),
|
blocBuilder: () => DeviceLogsBloc(),
|
||||||
blocBuilder: () => MapBloc(),
|
|
||||||
),
|
|
||||||
item: ItemConfig(
|
|
||||||
icon: IconConstants.instance.getMaterialIcon(Icons.location_on),
|
|
||||||
title: appLocalization(context).map_page_destination,
|
|
||||||
inactiveIcon: IconConstants.instance
|
|
||||||
.getMaterialIcon(Icons.location_on_outlined),
|
|
||||||
iconSize: 30,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
PersistentTabConfig(
|
BlocProvider(
|
||||||
screen: BlocProvider(
|
child: const InterFamilyScreen(),
|
||||||
child: const DeviceLogsScreen(),
|
blocBuilder: () => InterFamilyBloc(),
|
||||||
blocBuilder: () => DeviceLogsBloc(),
|
|
||||||
),
|
|
||||||
item: ItemConfig(
|
|
||||||
icon: IconConstants.instance.getMaterialIcon(Icons.history),
|
|
||||||
title: appLocalization(context).history_page_destination,
|
|
||||||
inactiveIcon:
|
|
||||||
IconConstants.instance.getMaterialIcon(Icons.history_outlined),
|
|
||||||
iconSize: 30,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PersistentTabConfig(
|
|
||||||
screen: BlocProvider(
|
|
||||||
child: const InterFamilyScreen(),
|
|
||||||
blocBuilder: () => InterFamilyBloc(),
|
|
||||||
),
|
|
||||||
item: ItemConfig(
|
|
||||||
icon: IconConstants.instance.getMaterialIcon(Icons.group),
|
|
||||||
title: appLocalization(context).group_page_destination,
|
|
||||||
inactiveIcon:
|
|
||||||
IconConstants.instance.getMaterialIcon(Icons.group_outlined),
|
|
||||||
iconSize: 30,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
return StreamBuilder<bool>(
|
return StreamBuilder<bool>(
|
||||||
stream: mainBloc.streamThemeMode,
|
stream: mainBloc.streamThemeMode,
|
||||||
initialData: isLight,
|
initialData: isLight,
|
||||||
@@ -194,7 +246,7 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: context.lowValue,
|
width: context.lowValue,
|
||||||
),
|
),
|
||||||
Flexible(child: Text(userSnapshot.data?.name ?? ""))
|
Flexible( child: Text(userSnapshot.data?.name ?? ""))
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
@@ -327,27 +379,32 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: PersistentTabView(
|
body: PersistentTabView(
|
||||||
stateManagement: false,
|
context,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
tabs: tabs,
|
screens: _buildScreens(),
|
||||||
navBarBuilder: (navBarConfig) => Style6BottomNavBar(
|
items: _navBarsItems(),
|
||||||
navBarConfig: navBarConfig,
|
handleAndroidBackButtonPress: true,
|
||||||
navBarDecoration: NavBarDecoration(
|
resizeToAvoidBottomInset: true,
|
||||||
color: themeModeSnapshot.data! ? Colors.white : Colors.black,
|
stateManagement: true,
|
||||||
borderRadius: BorderRadius.circular(context.mediumValue),
|
|
||||||
padding: const EdgeInsets.all(10)),
|
|
||||||
),
|
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
themeModeSnapshot.data! ? Colors.white : Colors.black,
|
themeModeSnapshot.data! ? Colors.white : Colors.black,
|
||||||
navBarOverlap: const NavBarOverlap.none(),
|
decoration: NavBarDecoration(
|
||||||
// margin: EdgeInsets.only(
|
borderRadius: BorderRadius.circular(30.0),
|
||||||
// left: context.lowValue,
|
colorBehindNavBar:
|
||||||
// bottom: context.dynamicHeight(0.02),
|
themeModeSnapshot.data! ? Colors.white : Colors.black,
|
||||||
// right: context.lowValue),
|
|
||||||
screenTransitionAnimation: const ScreenTransitionAnimation(
|
|
||||||
curve: Curves.bounceInOut,
|
|
||||||
duration: Duration(milliseconds: 200),
|
|
||||||
),
|
),
|
||||||
|
animationSettings: const NavBarAnimationSettings(
|
||||||
|
navBarItemAnimation: ItemAnimationSettings(
|
||||||
|
duration: Duration(milliseconds: 200),
|
||||||
|
curve: Curves.bounceInOut,
|
||||||
|
),
|
||||||
|
screenTransitionAnimation: ScreenTransitionAnimationSettings(
|
||||||
|
animateTabTransition: true,
|
||||||
|
curve: Curves.bounceInOut,
|
||||||
|
duration: Duration(milliseconds: 200),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
navBarStyle: NavBarStyle.style13,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -355,10 +412,8 @@ class _MainScreenState extends State<MainScreen> with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getBellNotification() async {
|
Future<void> getBellNotification() async {
|
||||||
await apiServices.execute(context, () async {
|
bell = await apiServices.getBellNotifications("0", "20");
|
||||||
bell = await apiServices.getBellNotifications("0", "20");
|
mainBloc.bellBloc.add(bell);
|
||||||
mainBloc.bellBloc.add(bell);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkStatus(List<BellItems> bells) {
|
bool checkStatus(List<BellItems> bells) {
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:google_maps_cluster_manager_2/google_maps_cluster_manager_2.dart';
|
import 'package:google_maps_cluster_manager_2/google_maps_cluster_manager_2.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart'
|
import 'package:google_maps_flutter/google_maps_flutter.dart'
|
||||||
hide ClusterManager, Cluster;
|
hide ClusterManager, Cluster;
|
||||||
|
import 'package:sfm_app/feature/devices/device_model.dart';
|
||||||
import '../../bloc/map_bloc.dart';
|
import 'package:sfm_app/bloc/map_bloc.dart';
|
||||||
import '../../product/base/bloc/base_bloc.dart';
|
import 'package:sfm_app/feature/map/widget/on_tap_marker_widget.dart';
|
||||||
|
import 'package:sfm_app/product/base/bloc/base_bloc.dart';
|
||||||
|
import 'package:sfm_app/product/constant/icon/icon_constants.dart';
|
||||||
|
import 'package:sfm_app/product/permission/location_permission.dart';
|
||||||
|
import 'package:sfm_app/product/services/api_services.dart';
|
||||||
|
import 'package:sfm_app/product/utils/permission_handler.dart';
|
||||||
import '../../product/constant/enums/app_theme_enums.dart';
|
import '../../product/constant/enums/app_theme_enums.dart';
|
||||||
import '../../product/constant/icon/icon_constants.dart';
|
|
||||||
import '../../product/services/api_services.dart';
|
|
||||||
import '../../product/utils/permission_handler.dart';
|
|
||||||
import '../devices/device_model.dart';
|
|
||||||
import 'widget/on_tap_marker_widget.dart';
|
|
||||||
|
|
||||||
class MapScreen extends StatefulWidget {
|
class MapScreen extends StatefulWidget {
|
||||||
const MapScreen({super.key});
|
const MapScreen({super.key});
|
||||||
@@ -36,7 +38,7 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
final streamController = StreamController<GoogleMapController>.broadcast();
|
final streamController = StreamController<GoogleMapController>.broadcast();
|
||||||
List<Device> devices = [];
|
List<Device> devices = [];
|
||||||
final Completer<GoogleMapController> _controller = Completer();
|
Completer<GoogleMapController> _controller = Completer();
|
||||||
List<String> imageAssets = [
|
List<String> imageAssets = [
|
||||||
IconConstants.instance.getIcon("normal_icon"),
|
IconConstants.instance.getIcon("normal_icon"),
|
||||||
IconConstants.instance.getIcon("offline_icon"),
|
IconConstants.instance.getIcon("offline_icon"),
|
||||||
@@ -56,7 +58,6 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
Timer? checkThemeTimer;
|
Timer? checkThemeTimer;
|
||||||
Timer? getMarker;
|
Timer? getMarker;
|
||||||
String themeMode = '';
|
String themeMode = '';
|
||||||
bool _isDisposed = false;
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -72,20 +73,18 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_isDisposed = true;
|
super.dispose();
|
||||||
checkThemeTimer?.cancel();
|
checkThemeTimer?.cancel();
|
||||||
getMarker?.cancel();
|
getMarker?.cancel();
|
||||||
|
_controller = Completer();
|
||||||
streamController.close();
|
streamController.close();
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMapCreated(GoogleMapController controller) {
|
void onMapCreated(GoogleMapController controller) {
|
||||||
if (!_isDisposed && !streamController.isClosed) {
|
_controller.complete(controller);
|
||||||
_controller.complete(controller);
|
streamController.add(controller);
|
||||||
streamController.add(controller);
|
clusterManager.setMapId(controller.mapId);
|
||||||
clusterManager.setMapId(controller.mapId);
|
checkTheme();
|
||||||
checkTheme();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -118,15 +117,12 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
clusterManager.updateMap();
|
clusterManager.updateMap();
|
||||||
},
|
},
|
||||||
polylines: {
|
polylines: {
|
||||||
if (polylinesSnapshot.data != null &&
|
Polyline(
|
||||||
polylinesSnapshot.data!.isNotEmpty) ...[
|
polylineId: const PolylineId('router'),
|
||||||
Polyline(
|
points: polylinesSnapshot.data ?? [],
|
||||||
polylineId: const PolylineId('router'),
|
color: Colors.deepPurpleAccent,
|
||||||
points: polylinesSnapshot.data!,
|
width: 8,
|
||||||
color: Colors.deepPurpleAccent,
|
),
|
||||||
width: 8,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
style: mapThemeSnapshot.data,
|
style: mapThemeSnapshot.data,
|
||||||
);
|
);
|
||||||
@@ -174,11 +170,11 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
return ClusterManager<Device>(
|
return ClusterManager<Device>(
|
||||||
devices,
|
devices,
|
||||||
_updateMarkers,
|
_updateMarkers,
|
||||||
markerBuilder: _getMarkerBuilder(),
|
markerBuilder: _getmarkerBuilder(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Marker> Function(Cluster<Device>) _getMarkerBuilder() =>
|
Future<Marker> Function(Cluster<Device>) _getmarkerBuilder() =>
|
||||||
(cluster) async {
|
(cluster) async {
|
||||||
return Marker(
|
return Marker(
|
||||||
markerId: MarkerId(
|
markerId: MarkerId(
|
||||||
@@ -187,8 +183,7 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
position: cluster.location,
|
position: cluster.location,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
LocationPermission permission = await checkAndRequestPermission();
|
LocationPermission permission = await checkAndRequestPermission();
|
||||||
if (permission == LocationPermission.whileInUse ||
|
if (permission == LocationPermission.whileInUse || permission == LocationPermission.always) {
|
||||||
permission == LocationPermission.always) {
|
|
||||||
Position position = await Geolocator.getCurrentPosition();
|
Position position = await Geolocator.getCurrentPosition();
|
||||||
onTapMarker(
|
onTapMarker(
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
@@ -240,9 +235,9 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
if (hasStateOne) {
|
if (hasStateOne) {
|
||||||
return flameIcon; // flameIcon
|
return flameIcon; // flameIcon
|
||||||
} else if (hasOtherState) {
|
} else if (hasOtherState) {
|
||||||
return offlineIcon; // normalIcon
|
return normalIcon; // normalIcon
|
||||||
} else {
|
} else {
|
||||||
return normalIcon; // offlineIcon
|
return offlineIcon; // offlineIcon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,12 +271,26 @@ class _MapScreenState extends State<MapScreen> with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getAllMarkers() async {
|
void getAllMarkers() async {
|
||||||
await apiServices.execute(context, () async {
|
String response = await apiServices.getOwnerDevices();
|
||||||
devices.clear();
|
if (response != "") {
|
||||||
final devicesList = await apiServices.getOwnerDevices();
|
final data = jsonDecode(response);
|
||||||
for (var device in devicesList) {
|
List<dynamic> result = data['items'];
|
||||||
devices.add(device);
|
if(result.isNotEmpty){
|
||||||
|
devices.clear();
|
||||||
|
final devicesList = Device.fromJsonDynamicList(result);
|
||||||
|
for (var device in devicesList) {
|
||||||
|
devices.add(device);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<bool> checkLocationPermission(context) async {
|
||||||
|
// bool check = await LocationPermissionRequest.instance
|
||||||
|
// .checkLocationPermission(context);
|
||||||
|
// return check;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
|
|
||||||
import 'show_direction_widget.dart';
|
import 'show_direction_widget.dart';
|
||||||
import 'show_nearest_place.dart';
|
import 'show_nearest_place.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
@@ -12,6 +11,7 @@ import '../../../bloc/map_bloc.dart';
|
|||||||
import '../../../product/services/api_services.dart';
|
import '../../../product/services/api_services.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
import '../../../product/utils/device_utils.dart';
|
import '../../../product/utils/device_utils.dart';
|
||||||
|
|
||||||
import '../../devices/device_model.dart';
|
import '../../devices/device_model.dart';
|
||||||
|
|
||||||
onTapMarker(
|
onTapMarker(
|
||||||
@@ -72,14 +72,14 @@ onTapMarker(
|
|||||||
double.parse(device.settings!.latitude!),
|
double.parse(device.settings!.latitude!),
|
||||||
double.parse(device.settings!.longitude!),
|
double.parse(device.settings!.longitude!),
|
||||||
);
|
);
|
||||||
await mapBloc.findTheWay(
|
mapBloc.findTheWay(
|
||||||
context,
|
context,
|
||||||
controller,
|
controller,
|
||||||
myLocation,
|
myLocation,
|
||||||
destination,
|
destination,
|
||||||
);
|
);
|
||||||
String deviceLocations = await DeviceUtils.instance
|
String deviceLocations = await DeviceUtils.instance
|
||||||
.getFullDeviceLocation(context, device.areaPath!,device.name);
|
.getFullDeviceLocation(context, device.areaPath!);
|
||||||
String yourLocation =
|
String yourLocation =
|
||||||
appLocalization(context).map_your_location;
|
appLocalization(context).map_your_location;
|
||||||
showDirections(
|
showDirections(
|
||||||
@@ -163,7 +163,6 @@ onTapMarker(
|
|||||||
style: const ButtonStyle(
|
style: const ButtonStyle(
|
||||||
backgroundColor: WidgetStatePropertyAll(Colors.red),
|
backgroundColor: WidgetStatePropertyAll(Colors.red),
|
||||||
foregroundColor: WidgetStatePropertyAll(Colors.white),
|
foregroundColor: WidgetStatePropertyAll(Colors.white),
|
||||||
iconColor: WidgetStatePropertyAll(Colors.white),
|
|
||||||
),
|
),
|
||||||
icon: IconConstants.instance
|
icon: IconConstants.instance
|
||||||
.getMaterialIcon(Icons.fire_truck_outlined),
|
.getMaterialIcon(Icons.fire_truck_outlined),
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import 'package:maps_launcher/maps_launcher.dart';
|
import 'package:maps_launcher/maps_launcher.dart';
|
||||||
|
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
import '../../../bloc/map_bloc.dart';
|
import '../../../bloc/map_bloc.dart';
|
||||||
|
|
||||||
showDirections(
|
showDirections(
|
||||||
@@ -15,14 +16,16 @@ showDirections(
|
|||||||
MapBloc mapBloc,
|
MapBloc mapBloc,
|
||||||
String originalName,
|
String originalName,
|
||||||
String destinationLocation,
|
String destinationLocation,
|
||||||
double deviceLat,
|
double devicelat,
|
||||||
double deviceLng,
|
double devicelng,
|
||||||
) {
|
) {
|
||||||
TextEditingController originController = TextEditingController(text: originalName);
|
TextEditingController originController =
|
||||||
TextEditingController destinationController = TextEditingController(text: destinationLocation);
|
TextEditingController(text: originalName);
|
||||||
|
TextEditingController destinationController =
|
||||||
|
TextEditingController(text: destinationLocation);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
backgroundColor: Colors.transparent,
|
||||||
// dismissDirection: DismissDirection.none,
|
// dismissDirection: DismissDirection.none,
|
||||||
duration: const Duration(minutes: 5),
|
duration: const Duration(minutes: 5),
|
||||||
content: Column(
|
content: Column(
|
||||||
@@ -35,20 +38,21 @@ showDirections(
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
appLocalization(context).map_show_direction,
|
appLocalization(context).map_show_direction,
|
||||||
style: context.responsiveBodyLargeWithBold,
|
style: context.titleLargeTextStyle,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: IconButton.outlined(
|
child: IconButton.outlined(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
mapBloc.sinkPolylines.add([]);
|
|
||||||
markers.clear();
|
|
||||||
await mapBloc.updateCameraPosition(
|
await mapBloc.updateCameraPosition(
|
||||||
controller,
|
controller,
|
||||||
deviceLat,
|
devicelat,
|
||||||
deviceLng,
|
devicelng,
|
||||||
13.0,
|
13.0,
|
||||||
);
|
);
|
||||||
|
List<LatLng> polylineCoordinates = [];
|
||||||
|
mapBloc.sinkPolylines.add(polylineCoordinates);
|
||||||
|
markers.clear();
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
}
|
}
|
||||||
@@ -99,12 +103,17 @@ showDirections(
|
|||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
List<LatLng> polylineCoordinates = [];
|
List<LatLng> polylineCoordinates = [];
|
||||||
mapBloc.sinkPolylines.add(polylineCoordinates);
|
mapBloc.sinkPolylines.add(polylineCoordinates);
|
||||||
MapsLauncher.launchCoordinates(deviceLat, deviceLng);
|
MapsLauncher.launchCoordinates(devicelat, devicelng);
|
||||||
},
|
},
|
||||||
icon: IconConstants.instance.getMaterialIcon(Icons.near_me_rounded),
|
icon: IconConstants.instance
|
||||||
|
.getMaterialIcon(Icons.near_me_rounded),
|
||||||
label: Text(
|
label: Text(
|
||||||
appLocalization(context).map_stream,
|
appLocalization(context).map_stream,
|
||||||
),
|
),
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
WidgetStateProperty.all<Color>(Colors.blue[300]!),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
|
|
||||||
import '../../../bloc/map_bloc.dart';
|
import '../../../bloc/map_bloc.dart';
|
||||||
import 'show_direction_widget.dart';
|
import 'show_direction_widget.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
@@ -52,6 +52,7 @@ showNearPlacesSideSheet(
|
|||||||
padding: context.paddingLow,
|
padding: context.paddingLow,
|
||||||
width: screenWidth,
|
width: screenWidth,
|
||||||
height: screenHeight / 3,
|
height: screenHeight / 3,
|
||||||
|
color: Colors.white,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -61,7 +62,10 @@ showNearPlacesSideSheet(
|
|||||||
Center(
|
Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'${appLocalization(modalBottomSheetContext).map_result}: ',
|
'${appLocalization(modalBottomSheetContext).map_result}: ',
|
||||||
style: context.h3
|
style: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
@@ -115,7 +119,10 @@ showNearPlacesSideSheet(
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
place.result!.name!,
|
place.result!.name!,
|
||||||
style: context.responsiveBodyMediumWithBold,
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: listViewContext.lowValue),
|
SizedBox(height: listViewContext.lowValue),
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
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 '../../../product/shared/shared_snack_bar.dart';
|
import '../../../product/shared/shared_snack_bar.dart';
|
||||||
import '../../../bloc/device_notification_settings_bloc.dart';
|
import '../../../bloc/device_notification_settings_bloc.dart';
|
||||||
import 'device_notification_settings_model.dart';
|
import 'device_notification_settings_model.dart';
|
||||||
@@ -73,7 +73,7 @@ class _DeviceNotificationSettingsScreenState
|
|||||||
hint: Text(
|
hint: Text(
|
||||||
appLocalization(context)
|
appLocalization(context)
|
||||||
.choose_device_dropdownButton,
|
.choose_device_dropdownButton,
|
||||||
style: context.responsiveBodySmall,
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
iconStyleData: const IconStyleData(
|
iconStyleData: const IconStyleData(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
@@ -111,12 +111,14 @@ class _DeviceNotificationSettingsScreenState
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getNotificationSetting() async {
|
void getNotificationSetting() async {
|
||||||
await apiServices.execute(context, () async {
|
String? response = await apiServices.getAllSettingsNotificationOfDevices();
|
||||||
deviceNotifications =
|
final data = jsonDecode(response);
|
||||||
await apiServices.getAllSettingsNotificationOfDevices();
|
final result = data['data'];
|
||||||
deviceNotificationSettingsBloc.sinkListNotifications
|
// log("Data ${DeviceNotificationSettings.mapFromJson(jsonDecode(data)).values.toList()}");
|
||||||
.add(deviceNotifications);
|
deviceNotifications =
|
||||||
});
|
DeviceNotificationSettings.mapFromJson(result).values.toList();
|
||||||
|
deviceNotificationSettingsBloc.sinkListNotifications
|
||||||
|
.add(deviceNotifications);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget listNotificationSetting(
|
Widget listNotificationSetting(
|
||||||
@@ -290,25 +292,22 @@ class _DeviceNotificationSettingsScreenState
|
|||||||
|
|
||||||
void updateDeviceNotification(String thingID, Map<String, int> notifiSettings,
|
void updateDeviceNotification(String thingID, Map<String, int> notifiSettings,
|
||||||
bool isDataChange) async {
|
bool isDataChange) async {
|
||||||
await apiServices.execute(context, () async {
|
int statusCode = await apiServices.updateDeviceNotificationSettings(
|
||||||
int statusCode = await apiServices.updateDeviceNotificationSettings(
|
thingID, notifiSettings);
|
||||||
thingID, notifiSettings);
|
if (statusCode == 200) {
|
||||||
if (statusCode == 200) {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
context,
|
||||||
context,
|
appLocalization(context).notification_update_device_settings_success,
|
||||||
appLocalization(context)
|
Colors.green,
|
||||||
.notification_update_device_settings_success,
|
Colors.white);
|
||||||
Colors.green,
|
} else {
|
||||||
Colors.white);
|
showNoIconTopSnackBar(
|
||||||
} else {
|
context,
|
||||||
showNoIconTopSnackBar(
|
appLocalization(context).notification_update_device_settings_failed,
|
||||||
context,
|
Colors.red,
|
||||||
appLocalization(context).notification_update_device_settings_failed,
|
Colors.white);
|
||||||
Colors.red,
|
}
|
||||||
Colors.white);
|
isDataChange = false;
|
||||||
}
|
deviceNotificationSettingsBloc.sinkIsDataChange.add(isDataChange);
|
||||||
isDataChange = false;
|
|
||||||
deviceNotificationSettingsBloc.sinkIsDataChange.add(isDataChange);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../../../product/shared/shared_snack_bar.dart';
|
import '../../../product/shared/shared_snack_bar.dart';
|
||||||
import '../../../product/constant/icon/icon_constants.dart';
|
import '../../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../../product/services/api_services.dart';
|
import '../../../product/services/api_services.dart';
|
||||||
@@ -9,6 +8,7 @@ import '../../../bloc/settings_bloc.dart';
|
|||||||
import '../../../product/shared/shared_input_decoration.dart';
|
import '../../../product/shared/shared_input_decoration.dart';
|
||||||
import '../../../product/extension/context_extension.dart';
|
import '../../../product/extension/context_extension.dart';
|
||||||
import '../../../product/services/language_services.dart';
|
import '../../../product/services/language_services.dart';
|
||||||
|
|
||||||
import 'profile_model.dart';
|
import 'profile_model.dart';
|
||||||
|
|
||||||
changeUserInfomation(
|
changeUserInfomation(
|
||||||
@@ -38,73 +38,35 @@ changeUserInfomation(
|
|||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (formKey.currentState!.validate()) {
|
if (formKey.currentState!.validate()) {
|
||||||
await apiServices.execute(context,() async {
|
formKey.currentState!.save();
|
||||||
formKey.currentState!.save();
|
String latitude = user.latitude ?? "";
|
||||||
String latitude = user.latitude ?? "";
|
String longitude = user.longitude ?? "";
|
||||||
String longitude = user.longitude ?? "";
|
Map<String, dynamic> body = {
|
||||||
Map<String, dynamic> body = {
|
"name": username,
|
||||||
"name": username,
|
"email": email,
|
||||||
"email": email,
|
"phone": tel,
|
||||||
"phone": tel,
|
"address": address,
|
||||||
"address": address,
|
"latitude": latitude,
|
||||||
"latitude": latitude,
|
"longitude": longitude
|
||||||
"longitude": longitude
|
};
|
||||||
};
|
int statusCode =
|
||||||
int statusCode =
|
await apiServices.updateUserProfile(body);
|
||||||
await apiServices.updateUserProfile(body);
|
if (statusCode == 200) {
|
||||||
if (statusCode == 200) {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_profile_success,
|
||||||
.notification_update_profile_success,
|
Colors.green,
|
||||||
Colors.green,
|
Colors.white);
|
||||||
Colors.white);
|
} else {
|
||||||
} else {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_profile_failed,
|
||||||
.notification_update_profile_failed,
|
Colors.redAccent,
|
||||||
Colors.redAccent,
|
Colors.white);
|
||||||
Colors.white);
|
}
|
||||||
}
|
Navigator.pop(modalBottomSheetContext);
|
||||||
settingsBloc.getUserProfile(context);
|
|
||||||
Navigator.pop(modalBottomSheetContext);
|
|
||||||
});
|
|
||||||
// try {
|
|
||||||
// formKey.currentState!.save();
|
|
||||||
// String latitude = user.latitude ?? "";
|
|
||||||
// String longitude = user.longitude ?? "";
|
|
||||||
// Map<String, dynamic> body = {
|
|
||||||
// "name": username,
|
|
||||||
// "email": email,
|
|
||||||
// "phone": tel,
|
|
||||||
// "address": address,
|
|
||||||
// "latitude": latitude,
|
|
||||||
// "longitude": longitude
|
|
||||||
// };
|
|
||||||
// int statusCode =
|
|
||||||
// await apiServices.updateUserProfile(body);
|
|
||||||
// if (statusCode == 200) {
|
|
||||||
// showNoIconTopSnackBar(
|
|
||||||
// modalBottomSheetContext,
|
|
||||||
// appLocalization(context)
|
|
||||||
// .notification_update_profile_success,
|
|
||||||
// Colors.green,
|
|
||||||
// Colors.white);
|
|
||||||
// } else {
|
|
||||||
// showNoIconTopSnackBar(
|
|
||||||
// modalBottomSheetContext,
|
|
||||||
// appLocalization(context)
|
|
||||||
// .notification_update_profile_failed,
|
|
||||||
// Colors.redAccent,
|
|
||||||
// Colors.white);
|
|
||||||
// }
|
|
||||||
// settingsBloc.getUserProfile(context);
|
|
||||||
// Navigator.pop(modalBottomSheetContext);
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(context, e.toString());
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon:
|
icon:
|
||||||
@@ -243,38 +205,35 @@ changeUserInfomation(
|
|||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (formKey.currentState!.validate()) {
|
if (formKey.currentState!.validate()) {
|
||||||
await apiServices.execute(context,() async {
|
formKey.currentState!.save();
|
||||||
formKey.currentState!.save();
|
String latitude = user.latitude ?? "";
|
||||||
String latitude = user.latitude ?? "";
|
String longitude = user.longitude ?? "";
|
||||||
String longitude = user.longitude ?? "";
|
Map<String, dynamic> body = {
|
||||||
Map<String, dynamic> body = {
|
"name": username,
|
||||||
"name": username,
|
"email": email,
|
||||||
"email": email,
|
"phone": tel,
|
||||||
"phone": tel,
|
"address": address,
|
||||||
"address": address,
|
"latitude": latitude,
|
||||||
"latitude": latitude,
|
"longitude": longitude
|
||||||
"longitude": longitude
|
};
|
||||||
};
|
int statusCode = await apiServices
|
||||||
int statusCode = await apiServices
|
.updateUserProfile(body);
|
||||||
.updateUserProfile(body);
|
if (statusCode == 200) {
|
||||||
if (statusCode == 200) {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_profile_success,
|
||||||
.notification_update_profile_success,
|
Colors.green,
|
||||||
Colors.green,
|
Colors.white);
|
||||||
Colors.white);
|
} else {
|
||||||
} else {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_profile_failed,
|
||||||
.notification_update_profile_failed,
|
Colors.redAccent,
|
||||||
Colors.redAccent,
|
Colors.white);
|
||||||
Colors.white);
|
}
|
||||||
}
|
Navigator.pop(modalBottomSheetContext);
|
||||||
settingsBloc.getUserProfile(context);
|
|
||||||
Navigator.pop(modalBottomSheetContext);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: const ButtonStyle(
|
style: const ButtonStyle(
|
||||||
@@ -324,31 +283,29 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
|||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (formKey.currentState!.validate()) {
|
if (formKey.currentState!.validate()) {
|
||||||
await apiServices.execute(context,() async {
|
formKey.currentState!.save();
|
||||||
formKey.currentState!.save();
|
Map<String, dynamic> body = {
|
||||||
Map<String, dynamic> body = {
|
"password_old": oldPass,
|
||||||
"password_old": oldPass,
|
"password_new": newPass,
|
||||||
"password_new": newPass,
|
};
|
||||||
};
|
int statusCode =
|
||||||
int statusCode =
|
await apiServices.updateUserPassword(body);
|
||||||
await apiServices.updateUserPassword(body);
|
if (statusCode == 200) {
|
||||||
if (statusCode == 200) {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_password_success,
|
||||||
.notification_update_password_success,
|
Colors.green,
|
||||||
Colors.green,
|
Colors.white);
|
||||||
Colors.white);
|
} else {
|
||||||
} else {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_password_failed,
|
||||||
.notification_update_password_failed,
|
Colors.redAccent,
|
||||||
Colors.redAccent,
|
Colors.white);
|
||||||
Colors.white);
|
}
|
||||||
}
|
Navigator.pop(modalBottomSheetContext);
|
||||||
Navigator.pop(modalBottomSheetContext);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon:
|
icon:
|
||||||
@@ -433,64 +390,31 @@ changeUserPassword(BuildContext context, SettingsBloc settingsBloc) {
|
|||||||
? Center(
|
? Center(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await apiServices.execute(context,() async {
|
if (formKey.currentState!.validate()) {
|
||||||
if (formKey.currentState!.validate()) {
|
formKey.currentState!.save();
|
||||||
formKey.currentState!.save();
|
Map<String, dynamic> body = {
|
||||||
Map<String, dynamic> body = {
|
"password_old": oldPass,
|
||||||
"password_old": oldPass,
|
"password_new": newPass,
|
||||||
"password_new": newPass,
|
};
|
||||||
};
|
int statusCode = await apiServices
|
||||||
int statusCode = await apiServices
|
.updateUserPassword(body);
|
||||||
.updateUserPassword(body);
|
if (statusCode == 200) {
|
||||||
if (statusCode == 200) {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_password_success,
|
||||||
.notification_update_password_success,
|
Colors.green,
|
||||||
Colors.green,
|
Colors.white);
|
||||||
Colors.white);
|
} else {
|
||||||
} else {
|
showNoIconTopSnackBar(
|
||||||
showNoIconTopSnackBar(
|
modalBottomSheetContext,
|
||||||
modalBottomSheetContext,
|
appLocalization(context)
|
||||||
appLocalization(context)
|
.notification_update_password_failed,
|
||||||
.notification_update_password_failed,
|
Colors.redAccent,
|
||||||
Colors.redAccent,
|
Colors.white);
|
||||||
Colors.white);
|
|
||||||
}
|
|
||||||
Navigator.pop(modalBottomSheetContext);
|
|
||||||
}
|
}
|
||||||
});
|
Navigator.pop(modalBottomSheetContext);
|
||||||
// try {
|
}
|
||||||
// if (formKey.currentState!.validate()) {
|
|
||||||
// formKey.currentState!.save();
|
|
||||||
// Map<String, dynamic> body = {
|
|
||||||
// "password_old": oldPass,
|
|
||||||
// "password_new": newPass,
|
|
||||||
// };
|
|
||||||
// int statusCode = await apiServices
|
|
||||||
// .updateUserPassword(body);
|
|
||||||
// if (statusCode == 200) {
|
|
||||||
// showNoIconTopSnackBar(
|
|
||||||
// modalBottomSheetContext,
|
|
||||||
// appLocalization(context)
|
|
||||||
// .notification_update_password_success,
|
|
||||||
// Colors.green,
|
|
||||||
// Colors.white);
|
|
||||||
// } else {
|
|
||||||
// showNoIconTopSnackBar(
|
|
||||||
// modalBottomSheetContext,
|
|
||||||
// appLocalization(context)
|
|
||||||
// .notification_update_password_failed,
|
|
||||||
// Colors.redAccent,
|
|
||||||
// Colors.white);
|
|
||||||
// }
|
|
||||||
// Navigator.pop(modalBottomSheetContext);
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// if (!context.mounted) return;
|
|
||||||
// showErrorTopSnackBarCustom(
|
|
||||||
// context, e.toString());
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
style: const ButtonStyle(
|
style: const ButtonStyle(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import '../../product/constant/app/app_constants.dart';
|
import '../../product/constant/app/app_constants.dart';
|
||||||
import '../../product/shared/shared_loading_animation.dart';
|
|
||||||
import 'profile/profile_screen.dart';
|
import 'profile/profile_screen.dart';
|
||||||
import '../../product/constant/icon/icon_constants.dart';
|
import '../../product/constant/icon/icon_constants.dart';
|
||||||
import '../../product/extension/context_extension.dart';
|
import '../../product/extension/context_extension.dart';
|
||||||
@@ -27,6 +27,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
settingsBloc = BlocProvider.of(context);
|
settingsBloc = BlocProvider.of(context);
|
||||||
|
getUserProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -37,79 +38,80 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: StreamBuilder<User>(
|
body: StreamBuilder<User>(
|
||||||
stream: settingsBloc.streamUserProfile,
|
stream: settingsBloc.streamUserProfile,
|
||||||
builder: (context, userSnapshot) {
|
initialData: user,
|
||||||
if (userSnapshot.data == null) {
|
builder: (context, userSnapshot) {
|
||||||
settingsBloc.getUserProfile(context);
|
return userSnapshot.data?.id == "" || user.id == ""
|
||||||
return const SharedLoadingAnimation();
|
? Center(
|
||||||
} else {
|
child: CircularProgressIndicator(
|
||||||
return Column(
|
value: context.highValue,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
CircleAvatar(
|
|
||||||
backgroundColor: Theme.of(context).focusColor,
|
|
||||||
radius: 70,
|
|
||||||
child: CircleAvatar(
|
|
||||||
backgroundColor: Theme.of(context).highlightColor,
|
|
||||||
radius: 60,
|
|
||||||
child: CircleAvatar(
|
|
||||||
radius: 50,
|
|
||||||
child: Text(
|
|
||||||
getAvatarContent(userSnapshot.data?.username ?? ""),
|
|
||||||
style: context.dynamicResponsiveSize(36),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
),
|
: Column(
|
||||||
SizedBox(height: context.lowValue),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
||||||
children: [
|
CircleAvatar(
|
||||||
Text(
|
backgroundColor: Theme.of(context).focusColor,
|
||||||
userSnapshot.data?.name ?? "User Name",
|
radius: 70,
|
||||||
style: context.h2,
|
child: CircleAvatar(
|
||||||
)
|
backgroundColor: Theme.of(context).highlightColor,
|
||||||
],
|
radius: 60,
|
||||||
),
|
child: CircleAvatar(
|
||||||
Row(
|
radius: 50,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Text(
|
||||||
children: [Text(userSnapshot.data?.email ?? "Email")],
|
getAvatarContent(
|
||||||
),
|
userSnapshot.data?.username ?? ""),
|
||||||
SizedBox(height: context.mediumValue),
|
style: const TextStyle(
|
||||||
cardContent(
|
fontSize: 35,
|
||||||
Icons.account_circle_rounded,
|
fontWeight: FontWeight.bold,
|
||||||
appLocalization(context).profile_change_info,
|
),
|
||||||
userSnapshot.data ?? user),
|
),
|
||||||
SizedBox(height: context.lowValue),
|
),
|
||||||
cardContent(
|
),
|
||||||
Icons.lock_outline,
|
),
|
||||||
appLocalization(context).profile_change_pass,
|
SizedBox(height: context.lowValue),
|
||||||
userSnapshot.data ?? user),
|
Row(
|
||||||
SizedBox(height: context.lowValue),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
cardContent(
|
children: [
|
||||||
Icons.settings_outlined,
|
Text(
|
||||||
appLocalization(context).profile_setting,
|
userSnapshot.data?.name ?? "User Name",
|
||||||
userSnapshot.data ?? user),
|
style: const TextStyle(
|
||||||
SizedBox(height: context.lowValue),
|
fontWeight: FontWeight.w900, fontSize: 26),
|
||||||
cardContent(
|
)
|
||||||
Icons.sim_card,
|
],
|
||||||
appLocalization(context).profile_sim_data,
|
),
|
||||||
userSnapshot.data ?? user),
|
Row(
|
||||||
SizedBox(height: context.lowValue),
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
cardContent(
|
children: [Text(userSnapshot.data?.email ?? "Email")],
|
||||||
Icons.logout_outlined,
|
),
|
||||||
appLocalization(context).log_out,
|
SizedBox(height: context.mediumValue),
|
||||||
userSnapshot.data ?? user),
|
cardContent(
|
||||||
],
|
Icons.account_circle_rounded,
|
||||||
);
|
appLocalization(context).profile_change_info,
|
||||||
}
|
),
|
||||||
},
|
SizedBox(height: context.lowValue),
|
||||||
),
|
cardContent(
|
||||||
|
Icons.lock_outline,
|
||||||
|
appLocalization(context).profile_change_pass,
|
||||||
|
),
|
||||||
|
SizedBox(height: context.lowValue),
|
||||||
|
cardContent(
|
||||||
|
Icons.settings_outlined,
|
||||||
|
appLocalization(context).profile_setting,
|
||||||
|
),
|
||||||
|
SizedBox(height: context.lowValue),
|
||||||
|
cardContent(
|
||||||
|
Icons.logout_outlined,
|
||||||
|
appLocalization(context).log_out,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
cardContent(IconData icon, String content, User user) {
|
cardContent(IconData icon, String content) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (icon == Icons.account_circle_rounded) {
|
if (icon == Icons.account_circle_rounded) {
|
||||||
@@ -118,10 +120,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
changeUserPassword(context, settingsBloc);
|
changeUserPassword(context, settingsBloc);
|
||||||
} else if (icon == Icons.settings_outlined) {
|
} else if (icon == Icons.settings_outlined) {
|
||||||
context.push(ApplicationConstants.DEVICE_NOTIFICATIONS_SETTINGS);
|
context.push(ApplicationConstants.DEVICE_NOTIFICATIONS_SETTINGS);
|
||||||
} else if(icon == Icons.sim_card){
|
} else {
|
||||||
context.push(ApplicationConstants.SIM_DATA_SETTINGS);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
await apiServices.logOut(context);
|
await apiServices.logOut(context);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -133,7 +132,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
leading: IconConstants.instance.getMaterialIcon(icon),
|
leading: IconConstants.instance.getMaterialIcon(icon),
|
||||||
title: Text(
|
title: Text(
|
||||||
content,
|
content,
|
||||||
style: context.responsiveBodyMediumWithBold,
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
trailing: const Icon(
|
trailing: const Icon(
|
||||||
Icons.arrow_forward_ios_outlined,
|
Icons.arrow_forward_ios_outlined,
|
||||||
@@ -143,6 +142,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getUserProfile() async {
|
||||||
|
String data = await apiServices.getUserDetail();
|
||||||
|
user = User.fromJson(jsonDecode(data));
|
||||||
|
settingsBloc.sinkUserProfile.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
String getAvatarContent(String username) {
|
String getAvatarContent(String username) {
|
||||||
String name = "";
|
String name = "";
|
||||||
if (username.isNotEmpty) {
|
if (username.isNotEmpty) {
|
||||||
|
|||||||
@@ -1,170 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
|
|
||||||
import '../../devices/device_model.dart';
|
|
||||||
import '../../../product/extension/context_extension.dart';
|
|
||||||
import '../../../product/services/language_services.dart';
|
|
||||||
|
|
||||||
import '../../../product/utils/device_utils.dart';
|
|
||||||
|
|
||||||
class SharedSimComponent extends StatelessWidget {
|
|
||||||
|
|
||||||
const SharedSimComponent({super.key, required this.device});
|
|
||||||
final Device device;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
double screenWidth = MediaQuery.of(context).size.width;
|
|
||||||
double screenHeight = MediaQuery.of(context).size.height;
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
width: screenWidth,
|
|
||||||
height: screenHeight / 5.5,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(30),
|
|
||||||
gradient: getGradientColor(getMonthLeft())
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: context.paddingLow,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
device.name ?? "name",
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_buildStatusChip(context,device.state ?? -1),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: context.lowValue),
|
|
||||||
// Time period
|
|
||||||
Text(
|
|
||||||
"${appLocalization(context).time_title}: ${convertStartTime()} - ${convertExpireTime()}",
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: context.lowValue),
|
|
||||||
_buildDurationDisplay(context),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildStatusChip(BuildContext context,int state) {
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(color: Colors.white),
|
|
||||||
borderRadius: BorderRadius.circular(15),
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Icons.circle,
|
|
||||||
color: DeviceUtils.instance.getTableRowColor(context, state),
|
|
||||||
size: 12,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
Text(
|
|
||||||
DeviceUtils.instance.checkStateDevice(context, state),
|
|
||||||
style: TextStyle(
|
|
||||||
color: DeviceUtils.instance.getTableRowColor(context, state),
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildDurationDisplay(BuildContext context) {
|
|
||||||
return Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
|
||||||
textBaseline: TextBaseline.alphabetic,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"${getMonthLeft()}",
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 40,
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text(
|
|
||||||
appLocalization(context).sim_data_month_left_message,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String convertStartTime(){
|
|
||||||
return DateFormat('dd/MM/yyyy').format(device.createdAt!);
|
|
||||||
}
|
|
||||||
|
|
||||||
String convertExpireTime() {
|
|
||||||
final expireDate = _calculateExpireDate();
|
|
||||||
return DateFormat('dd/MM/yyyy').format(expireDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMonthLeft() {
|
|
||||||
final expireDate = _calculateExpireDate();
|
|
||||||
final now = DateTime.now();
|
|
||||||
|
|
||||||
int totalMonths = (expireDate.year - now.year) * 12 + (expireDate.month - now.month);
|
|
||||||
|
|
||||||
if (expireDate.day < now.day) {
|
|
||||||
totalMonths -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalMonths;
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime _calculateExpireDate() {
|
|
||||||
return DateTime(
|
|
||||||
device.createdAt!.year + 3,
|
|
||||||
device.createdAt!.month,
|
|
||||||
device.createdAt!.day,
|
|
||||||
device.createdAt!.hour,
|
|
||||||
device.createdAt!.minute,
|
|
||||||
device.createdAt!.second,
|
|
||||||
device.createdAt!.millisecond,
|
|
||||||
device.createdAt!.microsecond,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearGradient getGradientColor(int monthLeft){
|
|
||||||
if(monthLeft <= 3){
|
|
||||||
return const LinearGradient(
|
|
||||||
colors: [Color(0xFFff4b1f), Color(0xFFff9068)],
|
|
||||||
);
|
|
||||||
}else{
|
|
||||||
return const LinearGradient(
|
|
||||||
colors: [Color(0xFF56ab2f), Color(0xFFa8e063)],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'shared_sim_component.dart';
|
|
||||||
import '../../../product/services/language_services.dart';
|
|
||||||
import '../../../product/shared/shared_loading_animation.dart';
|
|
||||||
import '../../../bloc/sim_data_bloc.dart';
|
|
||||||
import '../../../product/base/bloc/base_bloc.dart';
|
|
||||||
|
|
||||||
class SimDataScreen extends StatefulWidget {
|
|
||||||
const SimDataScreen({super.key});
|
|
||||||
@override
|
|
||||||
State<SimDataScreen> createState() => _SimDataScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SimDataScreenState extends State<SimDataScreen> {
|
|
||||||
late SimDataBloc simDataBloc;
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
simDataBloc = BlocProvider.of(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(appLocalization(context).profile_sim_data),
|
|
||||||
centerTitle: true,
|
|
||||||
),
|
|
||||||
body: StreamBuilder(
|
|
||||||
stream: simDataBloc.streamDevices,
|
|
||||||
builder: (context, devicesSnapshot) {
|
|
||||||
if (devicesSnapshot.data == null) {
|
|
||||||
simDataBloc.getOwnerDevices(context);
|
|
||||||
return const SharedLoadingAnimation();
|
|
||||||
} else if (devicesSnapshot.data!.isEmpty) {
|
|
||||||
return Center(
|
|
||||||
child: Text(appLocalization(context).main_no_data),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return SafeArea(
|
|
||||||
child: Column(
|
|
||||||
children: devicesSnapshot.data!.map(
|
|
||||||
(device) {
|
|
||||||
return SharedSimComponent(device: device,);
|
|
||||||
},
|
|
||||||
).toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
144
lib/main.dart
144
lib/main.dart
@@ -1,12 +1,12 @@
|
|||||||
import 'package:alarm/alarm.dart';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart'
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
show PersistentTabController;
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:sfm_app/firebase_options.dart';
|
||||||
import 'firebase_options.dart';
|
|
||||||
import 'product/lang/l10n/app_localizations.dart';
|
|
||||||
import 'product/services/api_services.dart';
|
import 'product/services/api_services.dart';
|
||||||
import 'product/services/notification_services.dart';
|
import 'product/services/notification_services.dart';
|
||||||
import 'product/services/theme_services.dart';
|
import 'product/services/theme_services.dart';
|
||||||
@@ -15,17 +15,90 @@ import 'bloc/main_bloc.dart';
|
|||||||
import 'product/base/bloc/base_bloc.dart';
|
import 'product/base/bloc/base_bloc.dart';
|
||||||
import 'product/constant/navigation/navigation_router.dart';
|
import 'product/constant/navigation/navigation_router.dart';
|
||||||
|
|
||||||
PersistentTabController controller = PersistentTabController(initialIndex: 0);
|
@pragma('vm:entry-point')
|
||||||
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
|
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||||
|
await setupFlutterNotifications();
|
||||||
|
showFlutterNotification(message);
|
||||||
|
// If you're going to use other Firebase services in the background, such as Firestore,
|
||||||
|
// make sure you call `initializeApp` before using other Firebase services.
|
||||||
|
print('Handling a background message ${message.messageId}');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Create a [AndroidNotificationChannel] for heads up notifications
|
||||||
|
late AndroidNotificationChannel channel;
|
||||||
|
|
||||||
|
bool isFlutterLocalNotificationsInitialized = false;
|
||||||
|
|
||||||
|
Future<void> setupFlutterNotifications() async {
|
||||||
|
if (isFlutterLocalNotificationsInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
channel = const AndroidNotificationChannel(
|
||||||
|
'high_importance_channel', // id
|
||||||
|
'High Importance Notifications', // title
|
||||||
|
description:
|
||||||
|
'This channel is used for important notifications.', // description
|
||||||
|
importance: Importance.high,
|
||||||
|
);
|
||||||
|
|
||||||
|
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||||
|
|
||||||
|
/// Create an Android Notification Channel.
|
||||||
|
///
|
||||||
|
/// We use this channel in the `AndroidManifest.xml` file to override the
|
||||||
|
/// default FCM channel to enable heads up notifications.
|
||||||
|
await flutterLocalNotificationsPlugin
|
||||||
|
.resolvePlatformSpecificImplementation<
|
||||||
|
AndroidFlutterLocalNotificationsPlugin>()
|
||||||
|
?.createNotificationChannel(channel);
|
||||||
|
|
||||||
|
/// Update the iOS foreground notification presentation options to allow
|
||||||
|
/// heads up notifications.
|
||||||
|
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
|
||||||
|
alert: true,
|
||||||
|
badge: true,
|
||||||
|
sound: true,
|
||||||
|
);
|
||||||
|
isFlutterLocalNotificationsInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void showFlutterNotification(RemoteMessage message) {
|
||||||
|
RemoteNotification? notification = message.notification;
|
||||||
|
AndroidNotification? android = message.notification?.android;
|
||||||
|
if (notification != null && android != null && !kIsWeb) {
|
||||||
|
flutterLocalNotificationsPlugin.show(
|
||||||
|
notification.hashCode,
|
||||||
|
notification.title,
|
||||||
|
notification.body,
|
||||||
|
NotificationDetails(
|
||||||
|
android: AndroidNotificationDetails(
|
||||||
|
channel.id,
|
||||||
|
channel.name,
|
||||||
|
channelDescription: channel.description,
|
||||||
|
// TODO add a proper drawable resource to android, for now using
|
||||||
|
// one that already exists in example app.
|
||||||
|
icon: 'launch_background',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the [FlutterLocalNotificationsPlugin] package.
|
||||||
|
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp();
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
// Set the background messaging handler early on, as a named top-level function
|
||||||
name: "sfm-notification");
|
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
||||||
FirebaseMessaging.onBackgroundMessage(
|
|
||||||
NotificationServices.firebaseMessagingBackgroundHandler);
|
if (!kIsWeb) {
|
||||||
await Alarm.init();
|
await setupFlutterNotifications();
|
||||||
await Alarm.stopAll();
|
}
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
child: const MyApp(),
|
child: const MyApp(),
|
||||||
@@ -34,6 +107,7 @@ void main() async {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MyApp extends StatefulWidget {
|
class MyApp extends StatefulWidget {
|
||||||
const MyApp({super.key});
|
const MyApp({super.key});
|
||||||
|
|
||||||
@@ -56,7 +130,7 @@ class _MyAppState extends State<MyApp> {
|
|||||||
late MainBloc mainBloc;
|
late MainBloc mainBloc;
|
||||||
LanguageServices languageServices = LanguageServices();
|
LanguageServices languageServices = LanguageServices();
|
||||||
ThemeServices themeServices = ThemeServices();
|
ThemeServices themeServices = ThemeServices();
|
||||||
final NotificationServices notificationServices = NotificationServices();
|
// final NotificationServices notificationServices = NotificationServices();
|
||||||
APIServices apiServices = APIServices();
|
APIServices apiServices = APIServices();
|
||||||
setLocale(Locale locale) {
|
setLocale(Locale locale) {
|
||||||
_locale = locale;
|
_locale = locale;
|
||||||
@@ -72,11 +146,20 @@ class _MyAppState extends State<MyApp> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
mainBloc = BlocProvider.of(context);
|
mainBloc = BlocProvider.of(context);
|
||||||
notificationServices.initialize();
|
// // notificationServices.initLocalNotifications();
|
||||||
notificationServices.firebaseInit(context);
|
// // notificationServices.firebaseInit(context);
|
||||||
notificationServices.setupInteractMessage(controller);
|
// // notificationServices.setupInteractMessage();
|
||||||
|
// notificationServices.getDeviceToken().then((token){
|
||||||
|
// print("Firebase Token: $token");
|
||||||
|
// sendNotificationToken(token);
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void sendNotificationToken (String token) async {
|
||||||
|
// int statusCode = await apiServices.sendNotificationToken(token);
|
||||||
|
// log("Notification Send StatusCode : $statusCode");
|
||||||
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
languageServices.getLocale().then((locale) => {setLocale(locale)});
|
languageServices.getLocale().then((locale) => {setLocale(locale)});
|
||||||
@@ -92,18 +175,19 @@ class _MyAppState extends State<MyApp> {
|
|||||||
initialData: _locale,
|
initialData: _locale,
|
||||||
builder: (context, languageSnapshot) {
|
builder: (context, languageSnapshot) {
|
||||||
return StreamBuilder<ThemeData?>(
|
return StreamBuilder<ThemeData?>(
|
||||||
stream: mainBloc.streamTheme,
|
stream: mainBloc.streamTheme,
|
||||||
initialData: _themeData,
|
initialData: _themeData,
|
||||||
builder: (context, themeSnapshot) {
|
builder: (context, themeSnapshot) {
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
theme: themeSnapshot.data,
|
theme: themeSnapshot.data,
|
||||||
routerConfig: router,
|
routerConfig: router,
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
supportedLocales: AppLocalizations.supportedLocales,
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
locale: languageSnapshot.data,
|
locale: languageSnapshot.data,
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ class RequestPermissionDialog {
|
|||||||
child: Text(
|
child: Text(
|
||||||
"Alow app to use $content permission",
|
"Alow app to use $content permission",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: context.responsiveBodyLargeWithBold,
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, fontSize: 18),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Divider(height: dialogContext.lowValue),
|
Divider(height: dialogContext.lowValue),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// ignore_for_file: constant_identifier_names, non_constant_identifier_names
|
// ignore_for_file: constant_identifier_names
|
||||||
|
|
||||||
class ApplicationConstants {
|
class ApplicationConstants {
|
||||||
static const APP_NAME = "Smatec SFM";
|
static const APP_NAME = "Smatec SFM";
|
||||||
@@ -21,10 +21,8 @@ class ApplicationConstants {
|
|||||||
static const DEVICE_LOGS_PATH = "/device-logs";
|
static const DEVICE_LOGS_PATH = "/device-logs";
|
||||||
static const GROUP_PATH = "/groups";
|
static const GROUP_PATH = "/groups";
|
||||||
static const DEVICE_NOTIFICATIONS_SETTINGS = "/device-notifications-settings";
|
static const DEVICE_NOTIFICATIONS_SETTINGS = "/device-notifications-settings";
|
||||||
static const SIM_DATA_SETTINGS = "/sim-data-settings";
|
|
||||||
static const OWNER_GROUP = "owner";
|
static const OWNER_GROUP = "owner";
|
||||||
static const PARTICIPANT_GROUP = "participant";
|
static const PARTICIPANT_GROUP = "participant";
|
||||||
static const NO_DATA = "no_data";
|
static const NO_DATA = "no_data";
|
||||||
static const LOADING = "loading";
|
static const LOADING = "loading";
|
||||||
static int CALL_API_TIMEOUT = 30;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,4 @@ enum AppRoutes {
|
|||||||
HISTORY,
|
HISTORY,
|
||||||
GROUPS,
|
GROUPS,
|
||||||
GROUP_DETAIL,
|
GROUP_DETAIL,
|
||||||
SIM_DATA_SETTING,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import '../../../bloc/sim_data_bloc.dart';
|
|
||||||
import '../../../feature/settings/sim_data/sim_data_screen.dart';
|
|
||||||
import '../../../bloc/device_detail_bloc.dart';
|
import '../../../bloc/device_detail_bloc.dart';
|
||||||
import '../../../feature/devices/device_detail/device_detail_screen.dart';
|
import '../../../feature/devices/device_detail/device_detail_screen.dart';
|
||||||
import '../../../bloc/device_notification_settings_bloc.dart';
|
import '../../../bloc/device_notification_settings_bloc.dart';
|
||||||
@@ -154,16 +151,6 @@ GoRouter goRouter() {
|
|||||||
),
|
),
|
||||||
transitionsBuilder: transitionsRightToLeft),
|
transitionsBuilder: transitionsRightToLeft),
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
path: ApplicationConstants.SIM_DATA_SETTINGS,
|
|
||||||
name: AppRoutes.SIM_DATA_SETTING.name,
|
|
||||||
pageBuilder: (context, state) => CustomTransitionPage(
|
|
||||||
child: BlocProvider(
|
|
||||||
child: const SimDataScreen(),
|
|
||||||
blocBuilder: () => SimDataBloc(),
|
|
||||||
),
|
|
||||||
transitionsBuilder: transitionsRightToLeft),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../utils/app_logger_utils.dart';
|
|
||||||
import '../utils/responsive_text_utils.dart';
|
|
||||||
import '../theme/app_theme_light.dart';
|
import '../theme/app_theme_light.dart';
|
||||||
|
|
||||||
// MEDIA
|
// MEDIA
|
||||||
@@ -10,105 +9,55 @@ extension ContextExtension on BuildContext {
|
|||||||
MediaQueryData get mediaQuery => MediaQuery.of(this);
|
MediaQueryData get mediaQuery => MediaQuery.of(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ResponsiveTextStyle on BuildContext {
|
|
||||||
TextStyle get h1 => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, 32), fontWeight: FontWeight.bold);
|
|
||||||
|
|
||||||
TextStyle get h2 => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, 24), fontWeight: FontWeight.bold);
|
|
||||||
|
|
||||||
TextStyle get h3 => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, 20), fontWeight: FontWeight.bold);
|
|
||||||
|
|
||||||
TextStyle get responsiveBodyLarge =>
|
|
||||||
TextStyle(fontSize: ResponsiveText.getSize(this, 18));
|
|
||||||
|
|
||||||
TextStyle get responsiveBodyLargeWithBold => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, 18), fontWeight: FontWeight.bold);
|
|
||||||
|
|
||||||
TextStyle get responsiveBodyMedium =>
|
|
||||||
TextStyle(fontSize: ResponsiveText.getSize(this, 16));
|
|
||||||
|
|
||||||
TextStyle get responsiveBodyMediumWithBold => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, 16), fontWeight: FontWeight.bold);
|
|
||||||
|
|
||||||
TextStyle get responsiveBodySmall =>
|
|
||||||
TextStyle(fontSize: ResponsiveText.getSize(this, 14));
|
|
||||||
|
|
||||||
TextStyle get responsiveBodySmallWithBold => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, 14), fontWeight: FontWeight.bold);
|
|
||||||
TextStyle dynamicResponsiveSize(double val) =>
|
|
||||||
TextStyle(fontSize: ResponsiveText.getSize(this, val));
|
|
||||||
TextStyle dynamicResponsiveSizeWithBold(double val) => TextStyle(
|
|
||||||
fontSize: ResponsiveText.getSize(this, val), fontWeight: FontWeight.bold);
|
|
||||||
}
|
|
||||||
|
|
||||||
// VALUES
|
// VALUES
|
||||||
extension MediaQueryExtension on BuildContext {
|
extension MediaQueryExtension on BuildContext {
|
||||||
double get height => mediaQuery.size.height;
|
double get height => mediaQuery.size.height;
|
||||||
|
|
||||||
double get width => mediaQuery.size.width;
|
double get width => mediaQuery.size.width;
|
||||||
|
|
||||||
double get lowValue => height * 0.01;
|
double get lowValue => height * 0.01;
|
||||||
|
|
||||||
double get normalValue => height * 0.02;
|
double get normalValue => height * 0.02;
|
||||||
|
|
||||||
double get mediumValue => height * 0.04;
|
double get mediumValue => height * 0.04;
|
||||||
|
|
||||||
double get highValue => height * 0.1;
|
double get highValue => height * 0.1;
|
||||||
|
|
||||||
double dynamicWidth(double val) => width * val;
|
double dynamicWidth(double val) => width * val;
|
||||||
|
|
||||||
double dynamicHeight(double val) => height * val;
|
double dynamicHeight(double val) => height * val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// THEME
|
// THEME
|
||||||
extension ThemeExtension on BuildContext {
|
extension ThemeExtension on BuildContext {
|
||||||
ThemeData get theme => Theme.of(this);
|
ThemeData get theme => Theme.of(this);
|
||||||
|
|
||||||
TextTheme get textTheme => theme.textTheme;
|
TextTheme get textTheme => theme.textTheme;
|
||||||
|
|
||||||
ColorScheme get colors => AppThemeLight.instance.theme.colorScheme;
|
ColorScheme get colors => AppThemeLight.instance.theme.colorScheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PADDING ALLL
|
// PADDING ALLL
|
||||||
extension PaddingExtensionAll on BuildContext {
|
extension PaddingExtensionAll on BuildContext {
|
||||||
EdgeInsets get paddingLow => EdgeInsets.all(lowValue);
|
EdgeInsets get paddingLow => EdgeInsets.all(lowValue);
|
||||||
|
|
||||||
EdgeInsets get paddingNormal => EdgeInsets.all(normalValue);
|
EdgeInsets get paddingNormal => EdgeInsets.all(normalValue);
|
||||||
|
|
||||||
EdgeInsets get paddingMedium => EdgeInsets.all(mediumValue);
|
EdgeInsets get paddingMedium => EdgeInsets.all(mediumValue);
|
||||||
|
|
||||||
EdgeInsets get paddingHigh => EdgeInsets.all(highValue);
|
EdgeInsets get paddingHigh => EdgeInsets.all(highValue);
|
||||||
|
|
||||||
EdgeInsets dynamicPadding(double val) => EdgeInsets.all(val);
|
EdgeInsets dynamicPadding(double val) => EdgeInsets.all(val);
|
||||||
// double dynamicPadding(double val) => height * val;
|
// double dynamicPadding(double val) => height * val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PADDING SYMETRIC
|
// PADDING SYMETRIC
|
||||||
extension PaddingExtensionSymetric on BuildContext {
|
extension PaddingExtensionSymetric on BuildContext {
|
||||||
// VERTICAL PADDİNG
|
// VERTICAL PADDİNG
|
||||||
EdgeInsets get paddingLowVertical => EdgeInsets.symmetric(vertical: lowValue);
|
EdgeInsets get paddingLowVertical => EdgeInsets.symmetric(vertical: lowValue);
|
||||||
|
|
||||||
EdgeInsets get paddingNormalVertical =>
|
EdgeInsets get paddingNormalVertical =>
|
||||||
EdgeInsets.symmetric(vertical: normalValue);
|
EdgeInsets.symmetric(vertical: normalValue);
|
||||||
|
|
||||||
EdgeInsets get paddingMediumVertical =>
|
EdgeInsets get paddingMediumVertical =>
|
||||||
EdgeInsets.symmetric(vertical: mediumValue);
|
EdgeInsets.symmetric(vertical: mediumValue);
|
||||||
|
|
||||||
EdgeInsets get paddingHighVertical =>
|
EdgeInsets get paddingHighVertical =>
|
||||||
EdgeInsets.symmetric(vertical: highValue);
|
EdgeInsets.symmetric(vertical: highValue);
|
||||||
|
|
||||||
// HORIZONTAL PADDİNG
|
// HORIZONTAL PADDİNG
|
||||||
EdgeInsets get paddingLowHorizontal =>
|
EdgeInsets get paddingLowHorizontal =>
|
||||||
EdgeInsets.symmetric(horizontal: lowValue);
|
EdgeInsets.symmetric(horizontal: lowValue);
|
||||||
|
|
||||||
EdgeInsets get paddingNormalHorizontal =>
|
EdgeInsets get paddingNormalHorizontal =>
|
||||||
EdgeInsets.symmetric(horizontal: normalValue);
|
EdgeInsets.symmetric(horizontal: normalValue);
|
||||||
|
|
||||||
EdgeInsets get paddingMediumHorizontal =>
|
EdgeInsets get paddingMediumHorizontal =>
|
||||||
EdgeInsets.symmetric(horizontal: mediumValue);
|
EdgeInsets.symmetric(horizontal: mediumValue);
|
||||||
|
|
||||||
EdgeInsets get paddingHighHorizontal =>
|
EdgeInsets get paddingHighHorizontal =>
|
||||||
EdgeInsets.symmetric(horizontal: highValue);
|
EdgeInsets.symmetric(horizontal: highValue);
|
||||||
}
|
}
|
||||||
@@ -121,63 +70,34 @@ extension PageExtension on BuildContext {
|
|||||||
// DURATION
|
// DURATION
|
||||||
extension DurationExtension on BuildContext {
|
extension DurationExtension on BuildContext {
|
||||||
Duration get lowDuration => const Duration(milliseconds: 150);
|
Duration get lowDuration => const Duration(milliseconds: 150);
|
||||||
|
|
||||||
Duration get normalDuration => const Duration(milliseconds: 500);
|
Duration get normalDuration => const Duration(milliseconds: 500);
|
||||||
|
|
||||||
Duration dynamicMilliSecondDuration(int milliseconds) =>
|
Duration dynamicMilliSecondDuration(int milliseconds) =>
|
||||||
Duration(milliseconds: milliseconds);
|
Duration(milliseconds: milliseconds);
|
||||||
|
|
||||||
Duration dynamicMinutesDuration(int minutes) => Duration(minutes: minutes);
|
Duration dynamicMinutesDuration(int minutes) => Duration(minutes: minutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RADIUS
|
// RADIUS
|
||||||
extension RadiusExtension on BuildContext {
|
extension RadiusExtension on BuildContext {
|
||||||
Radius get lowRadius => Radius.circular(width * 0.02);
|
Radius get lowRadius => Radius.circular(width * 0.02);
|
||||||
|
|
||||||
Radius get normalRadius => Radius.circular(width * 0.05);
|
Radius get normalRadius => Radius.circular(width * 0.05);
|
||||||
|
|
||||||
Radius get highRadius => Radius.circular(width * 0.1);
|
Radius get highRadius => Radius.circular(width * 0.1);
|
||||||
|
|
||||||
Radius dynamicRadius(double radius) => Radius.circular(radius);
|
Radius dynamicRadius(double radius) => Radius.circular(radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TextStyleExtention on BuildContext {
|
extension TextStyleExtention on BuildContext {
|
||||||
TextStyle get labelSmallTextStyle => Theme.of(this).textTheme.labelSmall!;
|
TextStyle get labelSmallTextStyle => Theme.of(this).textTheme.labelSmall!;
|
||||||
|
|
||||||
TextStyle get labelMediumTextStyle => Theme.of(this).textTheme.labelMedium!;
|
TextStyle get labelMediumTextStyle => Theme.of(this).textTheme.labelMedium!;
|
||||||
|
|
||||||
TextStyle get labelLargeTextStyle => Theme.of(this).textTheme.labelLarge!;
|
TextStyle get labelLargeTextStyle => Theme.of(this).textTheme.labelLarge!;
|
||||||
|
|
||||||
TextStyle get bodySmallTextStyle => Theme.of(this).textTheme.bodySmall!;
|
TextStyle get bodySmallTextStyle => Theme.of(this).textTheme.bodySmall!;
|
||||||
|
|
||||||
TextStyle get bodyMediumTextStyle => Theme.of(this).textTheme.bodyMedium!;
|
TextStyle get bodyMediumTextStyle => Theme.of(this).textTheme.bodyMedium!;
|
||||||
|
|
||||||
TextStyle get bodyLargeTextStyle => Theme.of(this).textTheme.bodyLarge!;
|
TextStyle get bodyLargeTextStyle => Theme.of(this).textTheme.bodyLarge!;
|
||||||
|
|
||||||
TextStyle get titleSmallTextStyle => Theme.of(this).textTheme.titleSmall!;
|
TextStyle get titleSmallTextStyle => Theme.of(this).textTheme.titleSmall!;
|
||||||
|
|
||||||
TextStyle get titleMediumTextStyle => Theme.of(this).textTheme.titleMedium!;
|
TextStyle get titleMediumTextStyle => Theme.of(this).textTheme.titleMedium!;
|
||||||
|
|
||||||
TextStyle get titleLargeTextStyle => Theme.of(this).textTheme.titleLarge!;
|
TextStyle get titleLargeTextStyle => Theme.of(this).textTheme.titleLarge!;
|
||||||
|
|
||||||
TextStyle get headlineSmallTextStyle =>
|
TextStyle get headlineSmallTextStyle =>
|
||||||
Theme.of(this).textTheme.headlineSmall!;
|
Theme.of(this).textTheme.headlineSmall!;
|
||||||
|
|
||||||
TextStyle get headlineMediumTextStyle =>
|
TextStyle get headlineMediumTextStyle =>
|
||||||
Theme.of(this).textTheme.headlineMedium!;
|
Theme.of(this).textTheme.headlineMedium!;
|
||||||
|
|
||||||
TextStyle get headlineLargeTextStyle =>
|
TextStyle get headlineLargeTextStyle =>
|
||||||
Theme.of(this).textTheme.headlineLarge!;
|
Theme.of(this).textTheme.headlineLarge!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension FutureExtension<T> on Future<T> {
|
|
||||||
Future<T> handleApiError() async {
|
|
||||||
try {
|
|
||||||
return await this;
|
|
||||||
} catch (e) {
|
|
||||||
AppLoggerUtils.error(e.toString());
|
|
||||||
return Future.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,8 +22,6 @@
|
|||||||
"let_PCCC_handle_message": "Let the Fire Prevention and Fighting Team handle it!",
|
"let_PCCC_handle_message": "Let the Fire Prevention and Fighting Team handle it!",
|
||||||
"overview_message": "Overview",
|
"overview_message": "Overview",
|
||||||
"total_nof_devices_message": "Total number of devices",
|
"total_nof_devices_message": "Total number of devices",
|
||||||
"over_view_owner_devices":"Owner Devices",
|
|
||||||
"over_view_joined_devices":"Joined Devices",
|
|
||||||
"active_devices_message": "Active",
|
"active_devices_message": "Active",
|
||||||
"inactive_devices_message": "Inactive",
|
"inactive_devices_message": "Inactive",
|
||||||
"warning_devices_message": "Warning",
|
"warning_devices_message": "Warning",
|
||||||
@@ -111,10 +109,7 @@
|
|||||||
"profile_page_title": "Settings Page",
|
"profile_page_title": "Settings Page",
|
||||||
"profile_change_info": "Change information",
|
"profile_change_info": "Change information",
|
||||||
"profile_change_pass": "Change password",
|
"profile_change_pass": "Change password",
|
||||||
"profile_sim_data": "Device SIM information",
|
|
||||||
"profile_setting": "Notification Setting",
|
"profile_setting": "Notification Setting",
|
||||||
"sim_data_month_left_message": "months left",
|
|
||||||
"time_title": "Time",
|
|
||||||
"change_profile_title": "Personal information",
|
"change_profile_title": "Personal information",
|
||||||
"change_profile_username": "Username: ",
|
"change_profile_username": "Username: ",
|
||||||
"change_profile_username_hint": "Enter username ",
|
"change_profile_username_hint": "Enter username ",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,792 +0,0 @@
|
|||||||
// ignore: unused_import
|
|
||||||
import 'package:intl/intl.dart' as intl;
|
|
||||||
import 'app_localizations.dart';
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
|
|
||||||
/// The translations for English (`en`).
|
|
||||||
class AppLocalizationsEn extends AppLocalizations {
|
|
||||||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE => 'This is english language in HomePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get home_page_name => 'Home Page';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get vietnam_language => 'Vietnamese';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get english_language => 'English';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification => 'Notifications:';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_icon_title => 'Settings';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get log_out => 'Log out';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get log_out_content => 'Are you sure you want to log out?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_description => 'All devices are operating normally';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get button_fake_fire_message => 'False fire alarm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get in_progress_message => 'In progress';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get smoke_detecting_message => 'Smoke detecting!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get low_battery_message => 'Low Battery!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get smoke_detecting_message_lowercase => 'smoke detecting!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get disconnect_message_uppercase => 'Disconnected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get disconnect_message_lowercase => 'disconnected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get location_message => 'Address: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_fake_fire_message =>
|
|
||||||
'Are you sure the fire is a false alarm?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_fake_fire_body =>
|
|
||||||
'Please check carefully to ensure that this is just a normal incident. The fire department will confirm that this is a false alarm!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_fake_fire_sure_message => 'I\'\'m sure';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get let_PCCC_handle_message =>
|
|
||||||
'Let the Fire Prevention and Fighting Team handle it!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get overview_message => 'Overview';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get total_nof_devices_message => 'Total number of devices';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get over_view_owner_devices => 'Owner Devices';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get over_view_joined_devices => 'Joined Devices';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get active_devices_message => 'Active';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get inactive_devices_message => 'Inactive';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get warning_devices_message => 'Warning';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get unused_devices_message => 'Unused';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE1 =>
|
|
||||||
'This is english language in DeviceManagerPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_manager_page_name => 'Devices Manager';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_device_title => 'Add new device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_extID_device_input => 'Devcice ID';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_extID_device_hintText => 'Enter the device ID';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_name_device_device => 'Device Name';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_name_device_hintText => 'Enter the device Name';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_title => 'List of devices';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_action => 'Action';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceName => 'Device name';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceStatus => 'Status';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceBaterry => 'Battery';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceSignal => 'Signal';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceTemperature => 'Temperature';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceHump => 'Humidity';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_devicePower => 'Power';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_device_dialog_title => 'Remove device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_device_dialog_content =>
|
|
||||||
'Are you sure you want to delete this device?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_title => 'Update device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_title => 'Device location';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_longitude => 'Longitude';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_latitude => 'Latitude';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_longitude_hintText =>
|
|
||||||
'Enter longitude';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_latitude_hintText =>
|
|
||||||
'Enter latitude';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_province_hintText =>
|
|
||||||
'Select Province/City';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_province_searchHint =>
|
|
||||||
'Find Province/City';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_district_hintText =>
|
|
||||||
'Select District';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_district_searchHint =>
|
|
||||||
'Find district';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_ward_hintText =>
|
|
||||||
'Select Ward/Commune';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_ward_searchHint =>
|
|
||||||
'Find Ward/Commune';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_maps_dialog_title => 'Update location';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_search_location_hint => 'Search Location';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE8 =>
|
|
||||||
'This is english language in MapPositionPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_your_location => 'Your Location';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_show_direction => 'Give directions';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearby_hospital => 'Nearby hospital';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearest_hospital => 'Nearest hospital';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearby_firestation => 'Nearby fire station';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearest_firestation => 'Nearest fire station';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_result => 'Result';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_always_opened => 'Always open';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_openning => 'Openning';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_closed => 'Closed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_no_results => 'No results found';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_start => 'Start';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_destination => 'Destination';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_stream => 'Stream';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE2 => 'This is english language in DeviceLogPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_log_page_name => 'Devices Log';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get choose_device_dropdownButton => 'Select device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get choose_date_start_datePicker => 'Start from';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get choose_date_end_datePicker => 'End';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get main_no_data => 'No data yet.';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get event_tag_title => 'Event';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE3 => 'This is english language in InterFamily';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get interfamily_page_name => 'InterFamily';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get my_group_title => 'My group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get invite_group => 'Joined group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_new_group => 'Add new group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get join_group => 'Join group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_name_title => 'Group Name';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_id_title => 'Group ID';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_new_user_title => 'Add user';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get share_group_title => 'Share group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_group_infomation_title => 'Change Infomation';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_group_infomation_content => 'Change group infomation';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_group_title => 'Delete group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_group_content =>
|
|
||||||
'Are you sure you want to delete this group?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get leave_group_content =>
|
|
||||||
'Are you sure you want to leave this group?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dont_have_group => 'No group yet';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dont_join_group => 'You haven\'\'t joined any groups yet.';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_group => 'Description';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_new_device_title => 'Add new device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get approve_user => 'Approve members';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get devices_title => 'Devices';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_title => 'Device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get member_title => 'Members';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get leave_group_title => 'Leave group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dont_have_device => 'No device yet';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE4 => 'This is english language in ProfilePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_page_title => 'Settings Page';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_change_info => 'Change information';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_change_pass => 'Change password';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_sim_data => 'Device SIM information';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_setting => 'Notification Setting';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get sim_data_month_left_message => 'months left';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get time_title => 'Time';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_title => 'Personal information';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_username => 'Username: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_username_hint => 'Enter username ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_email => 'Email: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_email_hint => 'Enter email ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_email_not_empty => 'Email cannot be empty';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_tel => 'Phone number: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_tel_hint => 'Enter phone number';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_tel_not_empty => 'Phone number cannot be empty';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_address => 'Address: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_address_hint => 'Enter address';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_old_pass => 'Password: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_old_pass_hint => 'Enter password';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_old_pass_not_empty =>
|
|
||||||
'Old password cannot be empty';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_new_pass => 'New password: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_new_pass_hint => 'Enter new password';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_new_pass_not_empty =>
|
|
||||||
'New password cannot be empty';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_device_notification_select_all => 'Select all';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_device_notification_deselect_all => 'Deselect all';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE5 => 'This is english language in BellPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_page_title => 'Notifications';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_page_no_items_body => 'No notifications yet';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_uppercase => 'User';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_battery_device => 'Device Battery';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_joined_group => 'joined group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_leave_group => 'left group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_added_group => 'added to the group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_kick_group => 'removed from the group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_operate_normal => 'operating normally';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_invalid_code => 'Invalid event code';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_days_ago => 'days ago';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_hours_ago => 'hours ago';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_minutes_ago => 'minutes ago';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_just_now => 'just now';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_read_all => 'You have read all the notifications';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE6 =>
|
|
||||||
'This is english language in GlobalFunction';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_newly_create_message => 'Newly created';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_disconnect_message => 'Disconnected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_smoke_detected_message => 'Smoke detected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_no_signal_message => 'No Signal';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_weak_signal_message => 'Weak Signal';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_moderate_signal_message => 'Moderate signal';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_good_signal_message => 'Good signal';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_volt_detect_message => 'Voltage detected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_temp_detect_message => 'Temperature detected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_hum_detect_message => 'Humidity detected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_battery_detect_message => 'Battery detected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_offline_message => 'Offline';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_in_firefighting_message => 'In firefighting';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_device_error_message => 'Device error';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_not_move_message => 'Not moved';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_moving_message => 'Moved';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_remove_from_base_message => 'Removed from the base';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_connected_lowercase => 'connected';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE7 => 'This is english language in LoginPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_account_not_empty => 'Account cannot be empty';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_account_hint => 'Account';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_password_not_empty => 'Password cannot be empty';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_password_hint => 'Password';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_success_message => 'Login successful';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_incorrect_usernameOrPass => 'Incorrect account or password';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_button_content => 'Login';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE9 =>
|
|
||||||
'This is english language in DeviceUpdatePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_title => 'Update Device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_location => 'Device Location';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_province => 'Province/City';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_district => 'District';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_ward => 'Ward/Commune';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE10 =>
|
|
||||||
'This is english language in DetailDevicePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get detail_device_dont_has_location_message =>
|
|
||||||
'No location information available yet';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get detail_device_volt_message => 'Measured voltage (V)';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get no_data_message => 'No data yet';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get normal_message => 'Normal';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get warning_status_message => 'Warning';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get undefine_message => 'Undefined';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get low_message_uppercase => 'Low';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get moderate_message_uppercase => 'Moderate';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get good_message_uppercase => 'Good';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get low_message_lowercase => 'low';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get moderate_message_lowercase => 'moderate';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get good_message_lowercase => 'good';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get error_message_uppercase => 'Error';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get error_message_lowercase => 'error';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get warning_message => 'Warning: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get loading_message => 'Loading...';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get detail_message => 'Detail';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get permission_deny_message => 'Permission Denied';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get decline_message => 'Decline';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get allow_message => 'Allow';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_button_content => 'Add';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_button_content => 'Update';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_button_content => 'Change';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_button_content => 'Confirm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_button_content => 'Delete';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get cancel_button_content => 'Cancel';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get find_button_content => 'Find';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get home_page_destination => 'Home';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get manager_page_destination => 'Manager';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_page_destination => 'Map';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get history_page_destination => 'History';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get history_page_destination_tooltip => 'Device history';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_page_destination => 'Group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_page_destination_tooltip => 'Exchange device notifications';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_enter_all_inf =>
|
|
||||||
'Please enter all the required information';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_success => 'Device update successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_failed => 'Device update failed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_error => 'Device update Error';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_cannot_find_address_from_location =>
|
|
||||||
'Can\'\'t find the location';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_device_success => 'Device added successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_device_failed => 'Failed to add device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_create_device_success =>
|
|
||||||
'Device created successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_create_device_failed => 'Failed to create device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_device_success =>
|
|
||||||
'Device deleted successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_device_failed => 'Failed to delete device';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_device_not_exist => 'The device does not exist';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_group_success => 'Group created successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_group_failed => 'Failed to create group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_group_success => 'Group updated successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_group_failed => 'Failed to updated group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_group_success => 'Group deleted successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_group_failed => 'Failed to delete group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_leave_group_success => 'Leave group successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_leave_group_failed => 'Failed to leave group';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_join_request_group_success =>
|
|
||||||
'Group join request successful!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_join_request_group_failed =>
|
|
||||||
'Group join request failed!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_profile_success =>
|
|
||||||
'Update profile successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_profile_failed => 'Failed to update profile';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_password_success =>
|
|
||||||
'Change password successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_password_failed =>
|
|
||||||
'The old password does not match';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_settings_success =>
|
|
||||||
'Device notification updated successfully';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_settings_failed =>
|
|
||||||
'Failed to update device notification';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_confirm_fake_fire_success =>
|
|
||||||
'Information has been updated to the Fire Station';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_confirm_fake_fire_failed =>
|
|
||||||
'Failed to update confirm fake fire';
|
|
||||||
}
|
|
||||||
@@ -1,786 +0,0 @@
|
|||||||
// ignore: unused_import
|
|
||||||
import 'package:intl/intl.dart' as intl;
|
|
||||||
import 'app_localizations.dart';
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
|
|
||||||
/// The translations for Vietnamese (`vi`).
|
|
||||||
class AppLocalizationsVi extends AppLocalizations {
|
|
||||||
AppLocalizationsVi([String locale = 'vi']) : super(locale);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE => 'This is VietNam language in HomePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get home_page_name => 'Trang chủ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get vietnam_language => 'Tiếng Việt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get english_language => 'Tiếng Anh';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification => 'Thông báo:';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_icon_title => 'Cài đặt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get log_out => 'Đăng xuất';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get log_out_content => 'Bạn chắc chắn muốn đăng xuất?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_description =>
|
|
||||||
'Tất cả thiết bị hoạt động bình thường';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get button_fake_fire_message => 'Cháy giả?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get in_progress_message => 'Đang xử lý';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get smoke_detecting_message => 'Phát hiện khói!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get low_battery_message => 'Cảnh báo pin yếu!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get smoke_detecting_message_lowercase => 'Phát hiện khói!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get disconnect_message_uppercase => 'Mất kết nối';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get disconnect_message_lowercase => 'mất kết nối';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get location_message => 'Địa chỉ: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_fake_fire_message => 'Bạn chắc chắn đám cháy là cháy giả?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_fake_fire_body =>
|
|
||||||
'Bạn hãy kiểm tra thật kỹ để chắc chắn rằng đây chỉ là sự cố bình thường. Đội PCCC sẽ xác nhận đây là đám cháy giả!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_fake_fire_sure_message => 'Tôi chắc chắn';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get let_PCCC_handle_message => 'Hãy để Đội PCCC xử lý!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get overview_message => 'Tổng quan';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get total_nof_devices_message => 'Tổng số';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get over_view_owner_devices => 'Thiết bị sở hữu';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get over_view_joined_devices => 'Thiết bị tham gia';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get active_devices_message => 'Bình thường';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get inactive_devices_message => 'Đang tắt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get warning_devices_message => 'Cảnh báo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get unused_devices_message => 'Không sử dụng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE1 =>
|
|
||||||
'This is vietnamese language in DeviceManagerPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_manager_page_name => 'Quản lý thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_device_title => 'Thêm thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_extID_device_input => 'Mã thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_extID_device_hintText => 'Nhập mã thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_name_device_device => 'Tên thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get input_name_device_hintText => 'Nhập tên thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_title => 'Danh sách thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_action => 'Thao tác';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceName => 'Tên thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceStatus => 'Tình trạng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceBaterry => 'Mức pin';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceSignal => 'Mức sóng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceTemperature => 'Nhiệt độ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_deviceHump => 'Độ ẩm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get paginated_data_table_column_devicePower => 'Nguồn';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_device_dialog_title => 'Xóa thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_device_dialog_content =>
|
|
||||||
'Bạn có chắc chắn muốn xóa thiết bị này?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_title => 'Sửa thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_title => 'Ví trí thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_longitude => 'Kinh độ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_latitude => 'Vĩ độ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_longitude_hintText => 'Nhập kinh độ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_latitude_hintText => 'Nhập vĩ độ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_province_hintText =>
|
|
||||||
'Chọn Tỉnh/Thành phố';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_province_searchHint =>
|
|
||||||
'Tìm Tỉnh/Thành phố';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_district_hintText =>
|
|
||||||
'Chọn Quận/Huyện';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_district_searchHint =>
|
|
||||||
'Tìm Quận/Huyện';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_ward_hintText => 'Chọn Phường/Xã';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_location_ward_searchHint => 'Tìm Phường/Xã';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_maps_dialog_title => 'Cập nhật vị trí';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_device_dialog_search_location_hint => 'Tìm kiếm địa chỉ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE8 =>
|
|
||||||
'This is vietnamese language in MapPositionPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_your_location => 'Vị trí của bạn';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_show_direction => 'Chỉ đường';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearby_hospital => 'Bệnh viện gần đó';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearest_hospital => 'Bệnh viện gần nhất';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearby_firestation => 'Trạm cứu hỏa gần đó';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_nearest_firestation => 'Trạm cứu hỏa gần nhất';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_result => 'Kết quả';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_always_opened => 'Luôn mở cửa';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_openning => 'Đang mở cửa';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_closed => 'Đóng cửa';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_no_results => 'Không tìm thấy kết quả';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_start => 'Xuất phát';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_destination => 'Đích đến';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_stream => 'Trực tiếp';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE2 =>
|
|
||||||
'This is vietnamese language in DeviceLogPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_log_page_name => 'Lịch sử thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get choose_device_dropdownButton => 'Chọn thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get choose_date_start_datePicker => 'Bắt đầu từ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get choose_date_end_datePicker => 'Kết thúc';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get main_no_data => 'Chưa có dữ liệu.';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get event_tag_title => 'Sự kiện';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE3 =>
|
|
||||||
'This is vietnamese language in InterFamily';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get interfamily_page_name => 'Liên gia';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get my_group_title => 'Nhóm của tôi';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get invite_group => 'Nhóm tham gia';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_new_group => 'Thêm nhóm mới';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get join_group => 'Tham gia nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_name_title => 'Tên nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_id_title => 'Mã nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_new_user_title => 'Thêm người dùng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get share_group_title => 'Chia sẻ nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_group_infomation_title => 'Đổi thông tin';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_group_infomation_content => 'Chỉnh sửa thông tin nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_group_title => 'Xóa nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_group_content => 'Bạn chắc chắn muốn xóa nhóm này?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get leave_group_content => 'Bạn chắc chắn muốn rời nhóm?';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dont_have_group => 'Chưa có nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dont_join_group => 'Bạn chưa tham gia nhóm nào';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_group => 'Mô tả';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_new_device_title => 'Thêm thiết bị mới';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get approve_user => 'Duyệt thành viên';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get devices_title => 'Thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_title => 'Thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get member_title => 'Thành viên';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get leave_group_title => 'Rời nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dont_have_device => 'Chưa có thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE4 =>
|
|
||||||
'This is vietnamese language in ProfilePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_page_title => 'Cài đặt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_change_info => 'Đổi thông tin cá nhân';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_change_pass => 'Đổi mật khẩu';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_sim_data => 'Thông tin sim thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get profile_setting => 'Cài đặt thông báo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get sim_data_month_left_message => 'tháng còn lại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get time_title => 'Thời gian';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_title => 'Thông tin người dùng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_username => 'Tên người dùng: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_username_hint => 'Nhập tên ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_email => 'Email: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_email_hint => 'Nhập email ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_email_not_empty => 'Email không được để trống';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_tel => 'Số điện thoại: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_tel_hint => 'Nhập số điện thoại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_tel_not_empty =>
|
|
||||||
'Số điện thoại không được để trống';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_address => 'Địa chỉ: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_address_hint => 'Nhập địa chỉ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_old_pass => 'Mật khẩu cũ: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_old_pass_hint => 'Nhập mật khẩu cũ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_old_pass_not_empty =>
|
|
||||||
'Mật khẩu không được để trống';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_new_pass => 'Mật khẩu mới: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_new_pass_hint => 'Nhập mật khẩu mới';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_new_pass_not_empty =>
|
|
||||||
'Mật khẩu không được để trống';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_device_notification_select_all => 'Chọn tất cả';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_profile_device_notification_deselect_all =>
|
|
||||||
'Bỏ chọn tất cả';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE5 => 'This is vietnamese language in BellPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_page_title => 'Thông báo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_page_no_items_body => 'Chưa có thông báo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_uppercase => 'Người dùng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_battery_device => 'Pin thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_joined_group => 'đã tham gia nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_leave_group => 'đã rời nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_added_group => 'đã được thêm vào nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_user_kick_group => 'đã bị xóa khỏi nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_operate_normal => 'hoạt động bình thường';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_invalid_code => 'Mã sự kiện không hợp lệ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_days_ago => 'ngày trước';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_hours_ago => 'giờ trước';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_minutes_ago => 'phút trước';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_just_now => 'Vừa xong';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get bell_read_all => 'Bạn đã xem hết thông báo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE6 =>
|
|
||||||
'This is vietnamese language in GlobalFunction';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_newly_create_message => 'Mới tạo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_disconnect_message => 'Mất kết nối';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_smoke_detected_message => 'Đang hoạt động';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_no_signal_message => 'Không có sóng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_weak_signal_message => 'Mức sóng yếu';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_moderate_signal_message => 'Mức sóng khá';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_good_signal_message => 'Mức sóng tốt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_volt_detect_message => 'Có điện thế';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_temp_detect_message => 'Có nhiệt độ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_hum_detect_message => 'Có độ ẩm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_battery_detect_message => 'Có mức pin';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_offline_message => 'Không hoạt động';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_in_firefighting_message => 'Đang chữa cháy';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_device_error_message => 'Thiết bị lỗi';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_not_move_message => 'Chưa di chuyển';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_moving_message => 'Đã di chuyển';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_remove_from_base_message => 'Bị tháo khỏi đế';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get gf_connected_lowercase => 'đã kết nối';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE7 => 'This is vietnamese language in LoginPage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_account_not_empty => 'Tài khoản không được để trống';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_account_hint => 'Tài khoản';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_password_not_empty => 'Mật khẩu không được để trống';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_password_hint => 'Mật khẩu';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_success_message => 'Đăng nhập thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_incorrect_usernameOrPass =>
|
|
||||||
'Tài khoản hoặc mật khẩu không đúng';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get login_button_content => 'Đăng nhập';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE9 =>
|
|
||||||
'This is vietnamese language in DeviceUpdatePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_title => 'Chỉnh sửa chi tiết thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_location => 'Vị trí thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_province => 'Tỉnh/Thành phố';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_district => 'Quận/Huyện';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get device_update_ward => 'Phường/Xã';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get description_NOTUSE10 =>
|
|
||||||
'This is vietnamese language in DetailDevicePage';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get detail_device_dont_has_location_message =>
|
|
||||||
'Chưa có thông tin về vị trí';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get detail_device_volt_message => 'Nguồn điện đo được (V)';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get no_data_message => 'Chưa có';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get normal_message => 'Bình thường';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get warning_status_message => 'Cảnh báo';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get undefine_message => 'Không xác định';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get low_message_uppercase => 'Yếu';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get moderate_message_uppercase => 'Khá';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get good_message_uppercase => 'Tốt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get low_message_lowercase => 'yếu';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get moderate_message_lowercase => 'khá';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get good_message_lowercase => 'tốt';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get error_message_uppercase => 'Lỗi';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get error_message_lowercase => 'lỗi';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get warning_message => 'Cảnh báo:';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get loading_message => 'Đang tải...';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get detail_message => 'Chi tiết';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get permission_deny_message => 'Quyền bị từ chối';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get decline_message => 'TỪ CHỐI';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get allow_message => 'CHO PHÉP';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get add_button_content => 'Thêm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get update_button_content => 'Cập nhật';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get change_button_content => 'Chỉnh sửa';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get confirm_button_content => 'Xác nhận';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_button_content => 'Xóa';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get cancel_button_content => 'Hủy';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get find_button_content => 'Tìm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get home_page_destination => 'Trang chủ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get manager_page_destination => 'Quản lý';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get map_page_destination => 'Bản đồ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get history_page_destination => 'Lịch sử';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get history_page_destination_tooltip => 'Lịch sử thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_page_destination => 'Nhóm';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get group_page_destination_tooltip => 'Trao đổi thông báo thiết bị';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_enter_all_inf => 'Vui lòng điền đầy đủ thông tin';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_success =>
|
|
||||||
'Cập nhật thiết bị thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_failed => 'Cập nhật thiết bị thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_error => 'Cập nhật lỗi';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_cannot_find_address_from_location =>
|
|
||||||
'Không tìm được vị trí';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_device_success => 'Thêm thiết bị thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_device_failed => 'Thêm thiết bị thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_create_device_success => 'Tạo thiết bị thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_create_device_failed => 'Tạo thiết bị thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_device_success => 'Xóa thiết bị thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_device_failed => 'Xóa thiết bị thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_device_not_exist => 'Thiết bị không tồn tại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_group_success => 'Tạo nhóm thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_add_group_failed => 'Tạo nhóm thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_group_success => 'Sửa nhóm thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_group_failed => 'Sửa nhóm thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_group_success => 'Xóa nhóm thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_delete_group_failed => 'Xóa nhóm thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_leave_group_success => 'Rời nhóm thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_leave_group_failed => 'Rời nhóm thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_join_request_group_success =>
|
|
||||||
'Yêu cầu tham gia nhóm thành công!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_join_request_group_failed =>
|
|
||||||
'Yêu cầu tham gia nhóm thất bại!';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_profile_success => 'Sửa thông tin thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_profile_failed => 'Sửa thông tin thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_password_success => 'Đổi mật khẩu thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_password_failed => 'Mật khẩu cũ không khớp';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_settings_success =>
|
|
||||||
'Cập nhật thông báo cho thiết bị thành công';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_update_device_settings_failed =>
|
|
||||||
'Cập nhật thông báo cho thiết bị thất bại';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_confirm_fake_fire_success =>
|
|
||||||
'Đã cập nhật thông tin đến đội PCCC';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get notification_confirm_fake_fire_failed =>
|
|
||||||
'Cập nhật cháy giả thất bại';
|
|
||||||
}
|
|
||||||
@@ -21,8 +21,6 @@
|
|||||||
"confirm_fake_fire_sure_message": "Tôi chắc chắn",
|
"confirm_fake_fire_sure_message": "Tôi chắc chắn",
|
||||||
"let_PCCC_handle_message": "Hãy để Đội PCCC xử lý!",
|
"let_PCCC_handle_message": "Hãy để Đội PCCC xử lý!",
|
||||||
"overview_message": "Tổng quan",
|
"overview_message": "Tổng quan",
|
||||||
"over_view_owner_devices":"Thiết bị sở hữu",
|
|
||||||
"over_view_joined_devices":"Thiết bị tham gia",
|
|
||||||
"total_nof_devices_message": "Tổng số",
|
"total_nof_devices_message": "Tổng số",
|
||||||
"active_devices_message": "Bình thường",
|
"active_devices_message": "Bình thường",
|
||||||
"inactive_devices_message": "Đang tắt",
|
"inactive_devices_message": "Đang tắt",
|
||||||
@@ -112,9 +110,6 @@
|
|||||||
"profile_change_info": "Đổi thông tin cá nhân",
|
"profile_change_info": "Đổi thông tin cá nhân",
|
||||||
"profile_change_pass": "Đổi mật khẩu",
|
"profile_change_pass": "Đổi mật khẩu",
|
||||||
"profile_setting": "Cài đặt thông báo",
|
"profile_setting": "Cài đặt thông báo",
|
||||||
"profile_sim_data": "Thông tin sim thiết bị",
|
|
||||||
"sim_data_month_left_message": "tháng còn lại",
|
|
||||||
"time_title": "Thời gian",
|
|
||||||
"change_profile_title": "Thông tin người dùng",
|
"change_profile_title": "Thông tin người dùng",
|
||||||
"change_profile_username": "Tên người dùng: ",
|
"change_profile_username": "Tên người dùng: ",
|
||||||
"change_profile_username_hint": "Nhập tên ",
|
"change_profile_username_hint": "Nhập tên ",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import '../constant/icon/icon_constants.dart';
|
import 'package:sfm_app/product/constant/icon/icon_constants.dart';
|
||||||
import '../constant/lang/language_constants.dart';
|
import 'package:sfm_app/product/constant/lang/language_constants.dart';
|
||||||
|
|
||||||
class Language {
|
class Language {
|
||||||
final int id;
|
final int id;
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import '../utils/app_logger_utils.dart';
|
|
||||||
|
|
||||||
import '../constant/status_code/status_code_constants.dart';
|
import '../constant/status_code/status_code_constants.dart';
|
||||||
|
|
||||||
import '../cache/local_manager.dart';
|
import '../cache/local_manager.dart';
|
||||||
@@ -16,7 +13,6 @@ class NetworkManager {
|
|||||||
static NetworkManager? _instance;
|
static NetworkManager? _instance;
|
||||||
static NetworkManager? get instance => _instance ??= NetworkManager._init();
|
static NetworkManager? get instance => _instance ??= NetworkManager._init();
|
||||||
|
|
||||||
|
|
||||||
Future<Map<String, String>> getHeaders() async {
|
Future<Map<String, String>> getHeaders() async {
|
||||||
String? token =
|
String? token =
|
||||||
LocaleManager.instance.getStringValue(PreferencesKeys.TOKEN);
|
LocaleManager.instance.getStringValue(PreferencesKeys.TOKEN);
|
||||||
@@ -39,26 +35,15 @@ class NetworkManager {
|
|||||||
/// [String] if the request is successful (status code 200), or an empty
|
/// [String] if the request is successful (status code 200), or an empty
|
||||||
/// string if the request fails
|
/// string if the request fails
|
||||||
Future<String> getDataFromServer(String path) async {
|
Future<String> getDataFromServer(String path) async {
|
||||||
try {
|
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET url: $url");
|
||||||
AppLoggerUtils.info("GET url: $url");
|
final headers = await getHeaders();
|
||||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET url: $url");
|
final response = await http.get(url, headers: headers);
|
||||||
final headers = await getHeaders();
|
if (response.statusCode == StatusCodeConstants.OK ||
|
||||||
final response = await http.get(url, headers: headers).timeout(
|
response.statusCode == StatusCodeConstants.CREATED) {
|
||||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
return response.body;
|
||||||
onTimeout: () =>
|
} else {
|
||||||
throw TimeoutException('Yêu cầu GET hết thời gian'),
|
return "";
|
||||||
);
|
|
||||||
if (response.statusCode == StatusCodeConstants.OK ||
|
|
||||||
response.statusCode == StatusCodeConstants.CREATED) {
|
|
||||||
return response.body;
|
|
||||||
} else {
|
|
||||||
throw Exception('Lỗi server: ${response.statusCode}');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// AppLoggerUtils.error(message)
|
|
||||||
// log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
|
||||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,36 +60,16 @@ class NetworkManager {
|
|||||||
/// Returns a [Future<String>] containing the server response body.
|
/// Returns a [Future<String>] containing the server response body.
|
||||||
Future<String> getDataFromServerWithParams(
|
Future<String> getDataFromServerWithParams(
|
||||||
String path, Map<String, dynamic> params) async {
|
String path, Map<String, dynamic> params) async {
|
||||||
try {
|
final url = Uri.https(ApplicationConstants.DOMAIN, path, params);
|
||||||
final url = Uri.https(ApplicationConstants.DOMAIN, path, params);
|
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
||||||
AppLoggerUtils.info("GET Params url: $url");
|
final headers = await getHeaders();
|
||||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
final response = await http.get(url, headers: headers);
|
||||||
final headers = await getHeaders();
|
if (response.statusCode == StatusCodeConstants.CREATED ||
|
||||||
final response = await http.get(url, headers: headers).timeout(
|
response.statusCode == StatusCodeConstants.OK) {
|
||||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
return response.body;
|
||||||
onTimeout: () =>
|
} else {
|
||||||
throw TimeoutException('Yêu cầu GET+PARAM hết thời gian'),
|
return "";
|
||||||
);
|
|
||||||
if (response.statusCode == StatusCodeConstants.OK ||
|
|
||||||
response.statusCode == StatusCodeConstants.CREATED) {
|
|
||||||
return response.body;
|
|
||||||
} else {
|
|
||||||
throw Exception('Lỗi server: ${response.statusCode}');
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
|
||||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
|
||||||
}
|
}
|
||||||
// final url = Uri.https(ApplicationConstants.DOMAIN, path, params);
|
|
||||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] GET Params url: $url");
|
|
||||||
// final headers = await getHeaders();
|
|
||||||
// final response = await http.get(url, headers: headers);
|
|
||||||
// if (response.statusCode == StatusCodeConstants.CREATED ||
|
|
||||||
// response.statusCode == StatusCodeConstants.OK) {
|
|
||||||
// return response.body;
|
|
||||||
// } else {
|
|
||||||
// return "";
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates new data on the server using a POST request.
|
/// Creates new data on the server using a POST request.
|
||||||
@@ -112,28 +77,12 @@ class NetworkManager {
|
|||||||
/// [path] is the endpoint for the request, and [body] contains the data
|
/// [path] is the endpoint for the request, and [body] contains the data
|
||||||
/// to be sent. Returns the HTTP status code of the response.
|
/// to be sent. Returns the HTTP status code of the response.
|
||||||
Future<int> createDataInServer(String path, Map<String, dynamic> body) async {
|
Future<int> createDataInServer(String path, Map<String, dynamic> body) async {
|
||||||
try {
|
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] POST url: $url");
|
||||||
AppLoggerUtils.info("POST url: $url");
|
final headers = await getHeaders();
|
||||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] POST url: $url");
|
final response =
|
||||||
final headers = await getHeaders();
|
await http.post(url, headers: headers, body: jsonEncode(body));
|
||||||
final response = await http
|
return response.statusCode;
|
||||||
.post(url, headers: headers, body: jsonEncode(body))
|
|
||||||
.timeout(
|
|
||||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
|
||||||
onTimeout: () =>
|
|
||||||
throw TimeoutException('Yêu cầu POST hết thời gian'),
|
|
||||||
);
|
|
||||||
if (response.statusCode == StatusCodeConstants.OK ||
|
|
||||||
response.statusCode == StatusCodeConstants.CREATED) {
|
|
||||||
return response.statusCode;
|
|
||||||
} else {
|
|
||||||
throw Exception('Lỗi server: ${response.statusCode}');
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
|
||||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates existing data on the server using a PUT request.
|
/// Updates existing data on the server using a PUT request.
|
||||||
@@ -141,27 +90,12 @@ class NetworkManager {
|
|||||||
/// [path] is the endpoint for the request, and [body] contains the data
|
/// [path] is the endpoint for the request, and [body] contains the data
|
||||||
/// to be updated. Returns the HTTP status code of the response.
|
/// to be updated. Returns the HTTP status code of the response.
|
||||||
Future<int> updateDataInServer(String path, Map<String, dynamic> body) async {
|
Future<int> updateDataInServer(String path, Map<String, dynamic> body) async {
|
||||||
try {
|
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] PUT url: $url");
|
||||||
AppLoggerUtils.info("PUT url: $url");
|
final headers = await getHeaders();
|
||||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] PUT url: $url");
|
final response =
|
||||||
final headers = await getHeaders();
|
await http.put(url, headers: headers, body: jsonEncode(body));
|
||||||
final response =
|
return response.statusCode;
|
||||||
await http.put(url, headers: headers, body: jsonEncode(body)).timeout(
|
|
||||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
|
||||||
onTimeout: () =>
|
|
||||||
throw TimeoutException('Yêu cầu PUT hết thời gian'),
|
|
||||||
);
|
|
||||||
if (response.statusCode == StatusCodeConstants.OK ||
|
|
||||||
response.statusCode == StatusCodeConstants.CREATED) {
|
|
||||||
return response.statusCode;
|
|
||||||
} else {
|
|
||||||
throw Exception('Lỗi server: ${response.statusCode}');
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
|
||||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes data from the server using a DELETE request.
|
/// Deletes data from the server using a DELETE request.
|
||||||
@@ -171,25 +105,10 @@ class NetworkManager {
|
|||||||
/// A status code of 200 indicates success, while other codes indicate
|
/// A status code of 200 indicates success, while other codes indicate
|
||||||
/// failure or an error.
|
/// failure or an error.
|
||||||
Future<int> deleteDataInServer(String path) async {
|
Future<int> deleteDataInServer(String path) async {
|
||||||
try {
|
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
log("[${DateTime.now().toLocal().toString().split(' ')[1]}] DELETE url: $url");
|
||||||
// log("[${DateTime.now().toLocal().toString().split(' ')[1]}] DELETE url: $url");
|
final headers = await getHeaders();
|
||||||
AppLoggerUtils.info("DELETE url: $url");
|
final response = await http.delete(url, headers: headers);
|
||||||
final headers = await getHeaders();
|
return response.statusCode;
|
||||||
final response = await http.delete(url, headers: headers).timeout(
|
|
||||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
|
||||||
onTimeout: () =>
|
|
||||||
throw TimeoutException('Yêu cầu DELETE hết thời gian'),
|
|
||||||
);
|
|
||||||
if (response.statusCode == StatusCodeConstants.OK ||
|
|
||||||
response.statusCode == StatusCodeConstants.CREATED) {
|
|
||||||
return response.statusCode;
|
|
||||||
} else {
|
|
||||||
throw Exception('Lỗi server: ${response.statusCode}');
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
log('Lỗi khi lấy dữ liệu: $e, StackTrace: $stackTrace');
|
|
||||||
throw Exception('Lỗi khi lấy dữ liệu: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:app_settings/app_settings.dart';
|
import 'package:app_settings/app_settings.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import 'package:sfm_app/product/base/widget/dialog/request_permission_dialog.dart';
|
||||||
import '../base/widget/dialog/request_permission_dialog.dart';
|
|
||||||
|
|
||||||
class LocationPermissionRequest {
|
class LocationPermissionRequest {
|
||||||
LocationPermissionRequest._init();
|
LocationPermissionRequest._init();
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:app_settings/app_settings.dart';
|
import 'package:app_settings/app_settings.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import '../base/widget/dialog/request_permission_dialog.dart';
|
import '../base/widget/dialog/request_permission_dialog.dart';
|
||||||
|
|
||||||
@@ -13,7 +11,7 @@ class NotificationPermission {
|
|||||||
static NotificationPermission? _instance;
|
static NotificationPermission? _instance;
|
||||||
static NotificationPermission get instance =>
|
static NotificationPermission get instance =>
|
||||||
_instance ??= NotificationPermission._init();
|
_instance ??= NotificationPermission._init();
|
||||||
static final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
|
|
||||||
Future<bool> checkNotificationPermission(context) async {
|
Future<bool> checkNotificationPermission(context) async {
|
||||||
var status = await Permission.notification.status;
|
var status = await Permission.notification.status;
|
||||||
log("Status: $status");
|
log("Status: $status");
|
||||||
@@ -46,21 +44,4 @@ class NotificationPermission {
|
|||||||
Icons.location_on_outlined, "ABCDE", AppSettingsType.notification);
|
Icons.location_on_outlined, "ABCDE", AppSettingsType.notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Future<bool?> requestNotificationPermission() async {
|
|
||||||
try {
|
|
||||||
if (Platform.isAndroid) {
|
|
||||||
return await _notificationsPlugin
|
|
||||||
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
|
|
||||||
?.requestNotificationsPermission();
|
|
||||||
} else if (Platform.isIOS) {
|
|
||||||
return await _notificationsPlugin
|
|
||||||
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
|
|
||||||
?.requestPermissions(alert: true, sound: true, badge: true);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch (e) {
|
|
||||||
log("Error requesting notification permission: $e");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
import 'package:alarm/alarm.dart';
|
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
|
||||||
class AlarmServices {
|
|
||||||
Future<void> showAlarm(String title, String body) async {
|
|
||||||
final DateTime now = DateTime.now();
|
|
||||||
final AlarmSettings alarmSettings = AlarmSettings(
|
|
||||||
id: 42,
|
|
||||||
dateTime: now,
|
|
||||||
assetAudioPath: 'assets/sounds/warning_alarm.mp3',
|
|
||||||
loopAudio: true,
|
|
||||||
vibrate: true,
|
|
||||||
warningNotificationOnKill: Platform.isIOS,
|
|
||||||
androidFullScreenIntent: true,
|
|
||||||
allowAlarmOverlap: true,
|
|
||||||
volumeSettings: VolumeSettings.fade(
|
|
||||||
volume: 1.0,
|
|
||||||
fadeDuration: const Duration(seconds: 3),
|
|
||||||
volumeEnforced: true,
|
|
||||||
),
|
|
||||||
notificationSettings: NotificationSettings(
|
|
||||||
title: title,
|
|
||||||
body: body,
|
|
||||||
stopButton: 'Dừng cảnh báo',
|
|
||||||
icon: 'ic_launcher',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await Alarm.set(alarmSettings: alarmSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cancelAlarm({int id = 42}) async {
|
|
||||||
await Alarm.stop(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +1,10 @@
|
|||||||
// ignore_for_file: use_build_context_synchronously
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import '../shared/model/province_model.dart';
|
|
||||||
import '../utils/app_logger_utils.dart';
|
|
||||||
import '../../feature/device_log/device_logs_model.dart';
|
|
||||||
import '../../feature/devices/device_model.dart';
|
|
||||||
import '../../feature/home/device_alias_model.dart';
|
|
||||||
import '../../feature/inter_family/group_detail/group_detail_model.dart';
|
|
||||||
import '../../feature/inter_family/groups/groups_model.dart';
|
|
||||||
import '../../feature/settings/device_notification_settings/device_notification_settings_model.dart';
|
|
||||||
import '../../feature/settings/profile/profile_model.dart';
|
|
||||||
import '../constant/app/api_path_constant.dart';
|
import '../constant/app/api_path_constant.dart';
|
||||||
import '../shared/model/district_model.dart';
|
|
||||||
import '../shared/model/ward_model.dart';
|
|
||||||
import '../shared/shared_snack_bar.dart';
|
import '../shared/shared_snack_bar.dart';
|
||||||
import '../constant/enums/app_route_enums.dart';
|
import '../constant/enums/app_route_enums.dart';
|
||||||
import 'language_services.dart';
|
import 'language_services.dart';
|
||||||
@@ -55,86 +41,6 @@ class APIServices {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<T> executeApiCall<T>(Future<dynamic> Function() apiCall,
|
|
||||||
{T Function(dynamic)? parser,
|
|
||||||
String errorMessage = 'Lỗi khi gọi API',
|
|
||||||
T Function(int)? statusCodeHandler}) async {
|
|
||||||
try {
|
|
||||||
final response = await apiCall().timeout(
|
|
||||||
Duration(seconds: ApplicationConstants.CALL_API_TIMEOUT),
|
|
||||||
onTimeout: () => throw TimeoutException('Yêu cầu hết thời gian'),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (statusCodeHandler != null && response is int) {
|
|
||||||
return statusCodeHandler(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response is String && response != "") {
|
|
||||||
if (parser != null) {
|
|
||||||
try {
|
|
||||||
return parser(jsonDecode(response));
|
|
||||||
} catch (e) {
|
|
||||||
throw Exception('Lỗi parsing dữ liệu: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response as T;
|
|
||||||
} else {
|
|
||||||
throw Exception('Dữ liệu trả về rỗng');
|
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLoggerUtils.error("Lỗi gọi API", e, stackTrace);
|
|
||||||
throw Exception('$errorMessage: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Most Used Function
|
|
||||||
// Future<T> execute<T>(Future<T> Function() apiCall) async {
|
|
||||||
// try {
|
|
||||||
// return await apiCall();
|
|
||||||
// } catch (e) {
|
|
||||||
|
|
||||||
// AppLoggerUtils.error(e.toString());
|
|
||||||
// return Future.error(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
Future<T> execute<T>(
|
|
||||||
BuildContext context,
|
|
||||||
Future<T> Function() apiCall, {
|
|
||||||
bool checkMounted = true,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
// Quick connectivity check before attempting network calls.
|
|
||||||
final conn = await Connectivity().checkConnectivity();
|
|
||||||
if (conn == ConnectivityResult.none) {
|
|
||||||
AppLoggerUtils.warning('No network connectivity');
|
|
||||||
if (checkMounted && context.mounted) {
|
|
||||||
showErrorTopSnackBarCustom(context, "Không có kết nối mạng");
|
|
||||||
}
|
|
||||||
return Future.error(const SocketException('No network connectivity'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return await apiCall();
|
|
||||||
} on SocketException catch (e, stackTrace) {
|
|
||||||
// Network-related errors (DNS, timeout, host lookup...)
|
|
||||||
AppLoggerUtils.warning('Network error when calling API: $e');
|
|
||||||
if (checkMounted && context.mounted) {
|
|
||||||
AppLoggerUtils.error("Không có kết nối mạng");
|
|
||||||
}
|
|
||||||
return Future.error(e);
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
// If widget was unmounted (e.g. background isolate), preserve previous behavior
|
|
||||||
if (checkMounted && !context.mounted) {
|
|
||||||
return Future.error('Widget not mounted');
|
|
||||||
}
|
|
||||||
AppLoggerUtils.error("Lỗi hệ thống khi gọi API", e, stackTrace);
|
|
||||||
if (checkMounted && context.mounted) {
|
|
||||||
showErrorTopSnackBarCustom(context, "Lỗi hệ thống");
|
|
||||||
}
|
|
||||||
return Future.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> login(String path, Map<String, dynamic> loginRequest) async {
|
Future<String> login(String path, Map<String, dynamic> loginRequest) async {
|
||||||
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
final url = Uri.https(ApplicationConstants.DOMAIN, path);
|
||||||
final headers = await getHeaders();
|
final headers = await getHeaders();
|
||||||
@@ -143,11 +49,14 @@ class APIServices {
|
|||||||
return response.body;
|
return response.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> sendNotificationToken(String token) async {
|
Future<int> sendNotificationToken(String token) async{
|
||||||
String uid = await getUID();
|
String uid = await getUID();
|
||||||
Map<String, dynamic> body = {"user_id": uid, "app_token": token};
|
Map<String,dynamic> body = {
|
||||||
int statusCode = await NetworkManager.instance!
|
"user_id": uid,
|
||||||
.updateDataInServer(APIPathConstants.NOTIFICATION_TOKEN_PATH, body);
|
"app_token": token
|
||||||
|
};
|
||||||
|
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
|
APIPathConstants.NOTIFICATION_TOKEN_PATH, body);
|
||||||
return statusCode;
|
return statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +69,7 @@ class APIServices {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
var url = Uri.https(ApplicationConstants.DOMAIN,
|
var url = Uri.http(ApplicationConstants.DOMAIN,
|
||||||
APIPathConstants.LOGOUT_PATH);
|
APIPathConstants.LOGOUT_PATH);
|
||||||
final headers = await NetworkManager.instance!.getHeaders();
|
final headers = await NetworkManager.instance!.getHeaders();
|
||||||
final response = await http.post(url, headers: headers);
|
final response = await http.post(url, headers: headers);
|
||||||
@@ -213,89 +122,67 @@ class APIServices {
|
|||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Bell> getBellNotifications(String offset, String pageSize) async {
|
Future<Bell> getBellNotifications(String offset, String pagesize) async {
|
||||||
final params = {"offset": offset, "page_size": pageSize};
|
Bell bell = Bell();
|
||||||
return executeApiCall(
|
final params = {"offset": offset, "page_size": pagesize};
|
||||||
() => NetworkManager.instance!.getDataFromServerWithParams(
|
final data = await NetworkManager.instance!.getDataFromServerWithParams(
|
||||||
APIPathConstants.BELL_NOTIFICATIONS_PATH, params),
|
APIPathConstants.BELL_NOTIFICATIONS_PATH, params);
|
||||||
parser: (json) => Bell.fromJson(json),
|
if (data != "") {
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.BELL_NOTIFICATIONS_PATH}',
|
bell = Bell.fromJson(jsonDecode(data));
|
||||||
);
|
return bell;
|
||||||
|
} else {
|
||||||
|
return bell;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateStatusOfNotification(List<String> notificationID) async {
|
Future<int> updateStatusOfNotification(List<String> notificationID) async {
|
||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"event_ids": notificationID,
|
"event_ids": notificationID,
|
||||||
};
|
};
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
APIPathConstants.BELL_UPDATE_READ_NOTIFICATIONS_PATH, body);
|
||||||
APIPathConstants.BELL_UPDATE_READ_NOTIFICATIONS_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.BELL_NOTIFICATIONS_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<User> getUserDetail() async {
|
Future<String> getUserDetail() async {
|
||||||
String uid = await getUID();
|
String uid = await getUID();
|
||||||
return executeApiCall(
|
String? response = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer('${APIPathConstants.USER_PATH}/$uid');
|
||||||
.getDataFromServer('${APIPathConstants.USER_PATH}/$uid'),
|
return response;
|
||||||
parser: (json) => User.fromJson(json),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.USER_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateUserProfile(Map<String, dynamic> body) async {
|
Future<int> updateUserProfile(Map<String, dynamic> body) async {
|
||||||
String uid = await getUID();
|
String uid = await getUID();
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
.updateDataInServer("${APIPathConstants.USER_PROFILE_PATH}/$uid", body);
|
||||||
"${APIPathConstants.USER_PROFILE_PATH}/$uid", body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.USER_PROFILE_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateUserPassword(Map<String, dynamic> body) async {
|
Future<int> updateUserPassword(Map<String, dynamic> body) async {
|
||||||
String uid = await getUID();
|
String uid = await getUID();
|
||||||
// int statusCode = await NetworkManager.instance!.updateDataInServer(
|
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
// "${APIPathConstants.USER_PATH}/$uid/password", body);
|
"${APIPathConstants.USER_PATH}/$uid/password", body);
|
||||||
return executeApiCall(
|
return statusCode;
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
|
||||||
"${APIPathConstants.USER_PATH}/$uid/password", body),
|
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.USER_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<DeviceNotificationSettings>>
|
Future<String> getAllSettingsNotificationOfDevices() async {
|
||||||
getAllSettingsNotificationOfDevices() async {
|
String? data = await NetworkManager.instance!
|
||||||
return executeApiCall(
|
.getDataFromServer(APIPathConstants.DEVICE_NOTIFICATION_SETTINGS);
|
||||||
() => NetworkManager.instance!
|
return data;
|
||||||
.getDataFromServer(APIPathConstants.DEVICE_NOTIFICATION_SETTINGS),
|
|
||||||
parser: (json) =>
|
|
||||||
DeviceNotificationSettings.mapFromJson(json['data']).values.toList(),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateDeviceNotificationSettings(
|
Future<int> updateDeviceNotificationSettings(
|
||||||
String thingID, Map<String, int> data) async {
|
String thingID, Map<String, int> data) async {
|
||||||
Map<String, dynamic> body = {"thing_id": thingID, "notifi_settings": data};
|
Map<String, dynamic> body = {"thing_id": thingID, "notifi_settings": data};
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body);
|
||||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi PUT /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<DeviceWithAlias>> getDashBoardDevices() async {
|
Future<String> getDashBoardDevices() async {
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer(APIPathConstants.DASHBOARD_DEVICES);
|
||||||
.getDataFromServer(APIPathConstants.DASHBOARD_DEVICES),
|
return data;
|
||||||
parser: (json) => DeviceWithAlias.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DASHBOARD_DEVICES}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> setupDeviceNotification(String thingID, String deviceName) async {
|
Future<int> setupDeviceNotification(String thingID, String deviceName) async {
|
||||||
@@ -315,103 +202,68 @@ class APIServices {
|
|||||||
"104": 1,
|
"104": 1,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body);
|
||||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi PUT /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Province>> getAllProvinces() async {
|
Future<String> getAllProvinces() async {
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer(APIPathConstants.PROVINCES_PATH);
|
||||||
.getDataFromServer(APIPathConstants.PROVINCES_PATH),
|
return data;
|
||||||
parser: (json) => Province.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Province>> getProvincesByName(String name) async {
|
Future<String> getProvincesByName(String name) async {
|
||||||
final params = {'name': name};
|
final params = {'name': name};
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServerWithParams(APIPathConstants.PROVINCES_PATH, params);
|
||||||
.getDataFromServerWithParams(APIPathConstants.PROVINCES_PATH, params),
|
return data;
|
||||||
parser: (json) => Province.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}/$name',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Province> getProvinceByID(String provinceID) async {
|
Future<String> getProvinceByID(String provinceID) async {
|
||||||
return executeApiCall(
|
String data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer("${APIPathConstants.PROVINCES_PATH}/$provinceID");
|
||||||
.getDataFromServer("${APIPathConstants.PROVINCES_PATH}/$provinceID"),
|
return data;
|
||||||
parser: (json) => Province.fromJson(json['data']),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.PROVINCES_PATH}/$provinceID}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<District>> getAllDistricts(String provinceID) async {
|
Future<String> getAllDistricts(String provinceID) async {
|
||||||
final params = {"parent": provinceID};
|
final params = {"parent": provinceID};
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params);
|
||||||
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params),
|
return data;
|
||||||
parser: (json) => District.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.DISTRICTS_PATH} by parentCode $provinceID',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<District>> getDistrictsByName(String districtName) async {
|
Future<String> getDistrictsByName(String districtName) async {
|
||||||
final params = {"name": districtName};
|
final params = {"name": districtName};
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params);
|
||||||
.getDataFromServerWithParams(APIPathConstants.DISTRICTS_PATH, params),
|
return data;
|
||||||
parser: (json) => District.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.DISTRICTS_PATH} by name $districtName',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<District> getDistrictByID(String districtID) async {
|
Future<String> getDistrictByID(String districtID) async {
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer("${APIPathConstants.DISTRICTS_PATH}/$districtID");
|
||||||
.getDataFromServer("${APIPathConstants.DISTRICTS_PATH}/$districtID"),
|
return data;
|
||||||
parser: (json) => District.fromJson(json['data']),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.DISTRICTS_PATH}/$districtID',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Ward>> getAllWards(String districtID) async {
|
Future<String> getAllWards(String districtID) async {
|
||||||
final params = {'parent': districtID};
|
final params = {'parent': districtID};
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params);
|
||||||
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params),
|
return data;
|
||||||
parser: (json) => Ward.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.WARDS_PATH} by parent $districtID',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Ward>> getWardsByName(String wardName) async {
|
Future<String> getWarsdByName(String wardName) async {
|
||||||
final params = {"name": wardName};
|
final params = {"name": wardName};
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params);
|
||||||
.getDataFromServerWithParams(APIPathConstants.WARDS_PATH, params),
|
return data;
|
||||||
parser: (json) => Ward.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi GET /${APIPathConstants.WARDS_PATH} by name $wardName',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Ward> getWardByID(String wardID) async {
|
Future<String> getWardByID(String wardID) async {
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer("${APIPathConstants.WARDS_PATH}/$wardID");
|
||||||
.getDataFromServer("${APIPathConstants.WARDS_PATH}/$wardID"),
|
return data;
|
||||||
parser: (json) => Ward.fromJson(json['data']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.WARDS_PATH}/$wardID',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> confirmFakeFireByUser(String thingID) async {
|
Future<int> confirmFakeFireByUser(String thingID) async {
|
||||||
@@ -419,187 +271,131 @@ class APIServices {
|
|||||||
"state": 3,
|
"state": 3,
|
||||||
"note": "Người dùng xác nhận cháy giả!"
|
"note": "Người dùng xác nhận cháy giả!"
|
||||||
};
|
};
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
.updateDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID", body);
|
||||||
"${APIPathConstants.DEVICE_PATH}/$thingID", body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.DEVICE_PATH}/$thingID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Device>> getOwnerDevices() async {
|
Future<String> getOwnerDevices() async {
|
||||||
return executeApiCall(
|
String? data = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer(APIPathConstants.DEVICE_PATH);
|
||||||
.getDataFromServer(APIPathConstants.DEVICE_PATH),
|
return data;
|
||||||
parser: (json) => Device.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Device>> getOwnerDeviceByState(
|
Future<String> getOwnerDeviceByState(Map<String, dynamic> params) async {
|
||||||
Map<String, dynamic> params) async {
|
String? data = await NetworkManager.instance!
|
||||||
return executeApiCall(
|
.getDataFromServerWithParams(APIPathConstants.DEVICE_PATH, params);
|
||||||
() => NetworkManager.instance!
|
return data;
|
||||||
.getDataFromServerWithParams(APIPathConstants.DEVICE_PATH, params),
|
|
||||||
parser: (json) => Device.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> createDeviceByAdmin(Map<String, dynamic> body) async {
|
Future<int> createDeviceByAdmin(Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.createDataInServer(APIPathConstants.DEVICE_PATH, body);
|
||||||
.createDataInServer(APIPathConstants.DEVICE_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.DEVICE_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> registerDevice(Map<String, dynamic> body) async {
|
Future<int> registerDevice(Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.createDataInServer(APIPathConstants.DEVICE_REGISTER_PATH, body);
|
||||||
.createDataInServer(APIPathConstants.DEVICE_REGISTER_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.DEVICE_REGISTER_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> deleteDeviceByAdmin(String thingID) async {
|
Future<int> deleteDeviceByAdmin(String thingID) async {
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.deleteDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID");
|
||||||
.deleteDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID"),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi DELETE /${APIPathConstants.DEVICE_PATH}/$thingID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> unregisterDevice(Map<String, dynamic> body) async {
|
Future<int> unregisterDevice(Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.createDataInServer(APIPathConstants.DEVICE_UNREGISTER_PATH, body);
|
||||||
.createDataInServer(APIPathConstants.DEVICE_UNREGISTER_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi DELETE /${APIPathConstants.DEVICE_UNREGISTER_PATH} by USER');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Device> getDeviceInformation(String thingID) async {
|
Future<String> getDeviceInfomation(String thingID) async {
|
||||||
return executeApiCall(
|
String? response = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer("${APIPathConstants.DEVICE_PATH}/$thingID");
|
||||||
.getDataFromServer("${APIPathConstants.DEVICE_PATH}/$thingID"),
|
return response;
|
||||||
parser: (json) => Device.fromJson(json),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_PATH}/$thingID',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Group>> getAllGroups() async {
|
Future<String> getAllGroups() async {
|
||||||
return executeApiCall(
|
String? body = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer(APIPathConstants.ALL_GROUPS_PATH);
|
||||||
.getDataFromServer(APIPathConstants.ALL_GROUPS_PATH),
|
return body;
|
||||||
parser: (json) => Group.fromJsonDynamicList(json['items']),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.USER_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> createGroup(Map<String, dynamic> body) async {
|
Future<int> createGroup(Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.createDataInServer(APIPathConstants.GROUPS_PATH, body);
|
||||||
.createDataInServer(APIPathConstants.GROUPS_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.GROUPS_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateGroup(Map<String, dynamic> body, String groupID) async {
|
Future<int> updateGroup(Map<String, dynamic> body, String groupID) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
.updateDataInServer("${APIPathConstants.GROUPS_PATH}/$groupID", body);
|
||||||
"${APIPathConstants.GROUPS_PATH}/$groupID", body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.GROUPS_PATH}/$groupID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> joinGroup(String groupID, Map<String, dynamic> body) async {
|
Future<int> joinGroup(String groupID, Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.createDataInServer(APIPathConstants.JOIN_GROUP_PATH, body);
|
||||||
.createDataInServer(APIPathConstants.JOIN_GROUP_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.JOIN_GROUP_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> deleteGroup(String groupID) async {
|
Future<int> deleteGroup(String groupID) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.deleteDataInServer("${APIPathConstants.GROUPS_PATH}/$groupID");
|
||||||
.deleteDataInServer("${APIPathConstants.GROUPS_PATH}/$groupID"),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi DELETE /${APIPathConstants.GROUPS_PATH}/$groupID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GroupDetail> getGroupDetail(String groupID) async {
|
Future<String> getGroupDetail(String groupID) async {
|
||||||
return executeApiCall(
|
String? body = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.getDataFromServer("${APIPathConstants.GROUPS_PATH}/$groupID");
|
||||||
.getDataFromServer("${APIPathConstants.GROUPS_PATH}/$groupID"),
|
return body;
|
||||||
parser: (json) => GroupDetail.fromJson(json),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.GROUPS_PATH}/$groupID',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> approveGroup(Map<String, dynamic> body) async {
|
Future<int> approveGroup(Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!
|
.createDataInServer(APIPathConstants.APPROVE_GROUP_PATH, body);
|
||||||
.createDataInServer(APIPathConstants.APPROVE_GROUP_PATH, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi POST /${APIPathConstants.APPROVE_GROUP_PATH}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> deleteUserInGroup(String groupID, String userID) async {
|
Future<int> deleteUserInGroup(String groupID, String userID) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!.deleteDataInServer(
|
||||||
() => NetworkManager.instance!.deleteDataInServer(
|
"${APIPathConstants.GROUPS_PATH}/$groupID/users/$userID");
|
||||||
"${APIPathConstants.GROUPS_PATH}/$groupID/users/$userID"),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi DELETE /${APIPathConstants.GROUPS_PATH}/$groupID/users/$userID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> deleteDeviceInGroup(String groupID, String thingID) async {
|
Future<int> deleteDeviceInGroup(String groupID, String thingID) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!.deleteDataInServer(
|
||||||
() => NetworkManager.instance!.deleteDataInServer(
|
"${APIPathConstants.GROUPS_PATH}/$groupID/devices/$thingID");
|
||||||
"${APIPathConstants.GROUPS_PATH}/$groupID/devices/$thingID"),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi DELETE /${APIPathConstants.GROUPS_PATH}/$groupID/devices/$thingID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateDeviceAlias(Map<String, dynamic> body) async {
|
Future<int> updateDeviceAlias(Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!.updateDataInServer(
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body);
|
||||||
APIPathConstants.DEVICE_NOTIFICATION_SETTINGS, body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi PUT /${APIPathConstants.DEVICE_NOTIFICATION_SETTINGS}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> addDeviceToGroup(
|
Future<int> addDeviceToGroup(
|
||||||
String groupID, Map<String, dynamic> body) async {
|
String groupID, Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!.createDataInServer(
|
||||||
() => NetworkManager.instance!.createDataInServer(
|
"${APIPathConstants.GROUPS_PATH}/$groupID/things", body);
|
||||||
"${APIPathConstants.GROUPS_PATH}/$groupID/things", body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage:
|
|
||||||
'Lỗi khi PUT /${APIPathConstants.GROUPS_PATH}/$groupID/things');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateOwnerDevice(
|
Future<int> updateOwnerDevice(
|
||||||
String thingID, Map<String, dynamic> body) async {
|
String thingID, Map<String, dynamic> body) async {
|
||||||
return executeApiCall(
|
int? statusCode = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!.updateDataInServer(
|
.updateDataInServer("${APIPathConstants.DEVICE_PATH}/$thingID", body);
|
||||||
"${APIPathConstants.DEVICE_PATH}/$thingID", body),
|
return statusCode;
|
||||||
statusCodeHandler: (statusCode) => statusCode,
|
|
||||||
errorMessage: 'Lỗi khi PUT /${APIPathConstants.DEVICE_PATH}/$thingID');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DeviceLog> getLogsOfDevice(
|
Future<String> getLogsOfDevice(
|
||||||
String thingID, Map<String, dynamic> params) async {
|
String thingID, Map<String, dynamic> params) async {
|
||||||
return executeApiCall(
|
String? body = await NetworkManager.instance!
|
||||||
() => NetworkManager.instance!.getDataFromServerWithParams(
|
.getDataFromServerWithParams(APIPathConstants.DEVICE_LOGS_PATH, params);
|
||||||
APIPathConstants.DEVICE_LOGS_PATH, params),
|
return body;
|
||||||
parser: (json) => DeviceLog.fromJson(json),
|
|
||||||
errorMessage: 'Lỗi khi GET /${APIPathConstants.DEVICE_LOGS_PATH}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import '../cache/local_manager.dart';
|
import '../cache/local_manager.dart';
|
||||||
import '../constant/enums/local_keys_enums.dart';
|
import '../constant/enums/local_keys_enums.dart';
|
||||||
import '../constant/lang/language_constants.dart';
|
import '../constant/lang/language_constants.dart';
|
||||||
import '../lang/l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
class LanguageServices {
|
class LanguageServices {
|
||||||
Future<Locale> setLocale(String languageCode) async {
|
Future<Locale> setLocale(String languageCode) async {
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import '../shared/find_location_maps/model/prediction_model.dart';
|
|||||||
import '../shared/model/near_by_search_model.dart';
|
import '../shared/model/near_by_search_model.dart';
|
||||||
|
|
||||||
class MapServices {
|
class MapServices {
|
||||||
Future<List<PlaceDetails>> getNearbyPlaces(
|
|
||||||
double latitude, double longitude, String searchKey, int radius, String type) async {
|
Future<List<PlaceDetails>> getNearbyPlaces(double latitude, double longitude,
|
||||||
|
String searchKey, int radius, String type) async {
|
||||||
List<PlaceDetails> result = [];
|
List<PlaceDetails> result = [];
|
||||||
var url = Uri.parse(
|
var url = Uri.parse(
|
||||||
'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$searchKey&language=vi&location=$latitude%2C$longitude&radius=$radius&strictbounds=true&type=$type&key=${ApplicationConstants.MAP_KEY}');
|
'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$searchKey&language=vi&location=$latitude%2C$longitude&radius=$radius&strictbounds=true&type=$type&key=${ApplicationConstants.MAP_KEY}');
|
||||||
@@ -45,11 +46,12 @@ class MapServices {
|
|||||||
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
|
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
|
||||||
googleApiKey: ApplicationConstants.MAP_KEY,
|
googleApiKey: ApplicationConstants.MAP_KEY,
|
||||||
request: PolylineRequest(
|
request: PolylineRequest(
|
||||||
|
origin: PointLatLng(origin.latitude, origin.longitude),
|
||||||
origin: PointLatLng(origin.latitude, origin.longitude),
|
destination: PointLatLng(destination.latitude, destination.longitude),
|
||||||
destination: PointLatLng(destination.latitude, destination.longitude),
|
mode: TravelMode.driving,
|
||||||
mode: TravelMode.driving,
|
optimizeWaypoints: true
|
||||||
optimizeWaypoints: true));
|
)
|
||||||
|
);
|
||||||
if (result.points.isNotEmpty) {
|
if (result.points.isNotEmpty) {
|
||||||
for (var point in result.points) {
|
for (var point in result.points) {
|
||||||
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
|
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
|
||||||
@@ -60,4 +62,5 @@ class MapServices {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,262 +1,121 @@
|
|||||||
import 'dart:developer' as dev;
|
import 'dart:developer' as dev;
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'package:alarm/alarm.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart'
|
|
||||||
as firebase_messaging;
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';
|
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
|
import 'package:persistent_bottom_nav_bar/persistent_bottom_nav_bar.dart';
|
||||||
|
|
||||||
import '../utils/app_logger_utils.dart';
|
|
||||||
import '../../firebase_options.dart';
|
|
||||||
import 'alarm_services.dart';
|
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
|
||||||
class NotificationServices {
|
class NotificationServices {
|
||||||
static final FlutterLocalNotificationsPlugin _notificationsPlugin =
|
FirebaseMessaging messaging = FirebaseMessaging.instance;
|
||||||
FlutterLocalNotificationsPlugin();
|
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||||
final firebase_messaging.FirebaseMessaging _messaging =
|
|
||||||
firebase_messaging.FirebaseMessaging.instance;
|
|
||||||
AlarmServices alarmServices = AlarmServices();
|
|
||||||
|
|
||||||
Future<void> initialize() async {
|
Future<void> initLocalNotifications(PersistentTabController controller) async {
|
||||||
await initializeLocalNotifications();
|
const AndroidInitializationSettings androidInitializationSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||||
dev.log("NotificationService initialized");
|
const DarwinInitializationSettings iosInitializationSettings = DarwinInitializationSettings();
|
||||||
}
|
const InitializationSettings initializationSettings = InitializationSettings(
|
||||||
|
android: androidInitializationSettings,
|
||||||
|
iOS: iosInitializationSettings,
|
||||||
|
);
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
await _flutterLocalNotificationsPlugin.initialize(
|
||||||
Future<void> initializeLocalNotifications() async {
|
initializationSettings,
|
||||||
try {
|
onDidReceiveNotificationResponse: (NotificationResponse response) {
|
||||||
const androidInitSettings =
|
dev.log("Người dùng click thông báo ở foreground với payload: ${response.payload}");
|
||||||
AndroidInitializationSettings('@mipmap/ic_launcher');
|
handleMessage(response.payload,controller);
|
||||||
final darwinInitSettings = DarwinInitializationSettings(
|
},
|
||||||
onDidReceiveLocalNotification: _onDidReceiveLocalNotification,
|
);
|
||||||
);
|
dev.log("Local notifications initialized");
|
||||||
final initSettings = InitializationSettings(
|
|
||||||
android: androidInitSettings,
|
|
||||||
iOS: darwinInitSettings,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _notificationsPlugin.initialize(
|
|
||||||
initSettings,
|
|
||||||
onDidReceiveNotificationResponse: _onDidReceiveNotificationResponse,
|
|
||||||
);
|
|
||||||
|
|
||||||
dev.log("Local notifications initialized");
|
|
||||||
} catch (e) {
|
|
||||||
AppLoggerUtils.error("Failed to initialize local notifications", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _onDidReceiveLocalNotification(
|
|
||||||
int id, String? title, String? body, String? payload) async {
|
|
||||||
// Handle local notification tap when app is foreground (iOS)
|
|
||||||
dev.log("Local notification tapped (foreground): payload=$payload");
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _onDidReceiveNotificationResponse(
|
|
||||||
NotificationResponse response) async {
|
|
||||||
// Handle local notification tap (both foreground & background)
|
|
||||||
final payload = response.payload;
|
|
||||||
dev.log("Notification tapped: payload=$payload");
|
|
||||||
|
|
||||||
if (payload != null && payload.isNotEmpty) {
|
|
||||||
final controller = PersistentTabController(initialIndex: 0);
|
|
||||||
handleMessage(payload, controller);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void firebaseInit(BuildContext context) {
|
void firebaseInit(BuildContext context) {
|
||||||
firebase_messaging.FirebaseMessaging.onMessage.listen((message) {
|
FirebaseMessaging.onMessage.listen((message) {
|
||||||
_handleForegroundMessage(message);
|
dev.log("Foreground message payload: ${message.toMap()}");
|
||||||
|
if (WidgetsBinding.instance != null) {
|
||||||
|
showNotification(message);
|
||||||
|
} else {
|
||||||
|
dev.log("App is in background, skipping foreground notification");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String> getDeviceToken() async {
|
||||||
|
print("GET FB TOKEN");
|
||||||
|
String? token = await messaging.getAPNSToken();
|
||||||
|
print("GET FB: ${token}");
|
||||||
|
return token!;
|
||||||
|
}
|
||||||
|
|
||||||
void isTokenRefresh() {
|
void isTokenRefresh() {
|
||||||
_messaging.onTokenRefresh.listen((newToken) {
|
messaging.onTokenRefresh.listen((newToken) {
|
||||||
dev.log("Refresh Firebase Messaging Token: $newToken");
|
dev.log("Refresh Firebase Messaging Token: $newToken");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<bool?> requestNotificationPermission() async {
|
Future<void> showNotification(RemoteMessage message) async {
|
||||||
try {
|
dev.log(message.toString());
|
||||||
final messaging = firebase_messaging.FirebaseMessaging.instance;
|
dev.log(message.data.toString());
|
||||||
final settings = await messaging.requestPermission(
|
dev.log(message.data["notification"].toString());
|
||||||
alert: true,
|
String? title = message.data['title'];
|
||||||
announcement: false,
|
String? body = message.data['body'];
|
||||||
badge: true,
|
String type = message.data['type'] ?? "normal";
|
||||||
provisional: false,
|
|
||||||
sound: true,
|
if (title == null || body == null) {
|
||||||
);
|
dev.log("Skipping notification due to missing title or body");
|
||||||
return settings.authorizationStatus ==
|
return;
|
||||||
firebase_messaging.AuthorizationStatus.authorized;
|
|
||||||
} catch (e) {
|
|
||||||
AppLoggerUtils.error("Failed to request notification permission", e);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Xử lý message khi app foreground
|
AndroidNotificationChannel androidNotificationChannel = AndroidNotificationChannel(
|
||||||
Future<void> _handleForegroundMessage(
|
math.Random.secure().nextInt(1000000).toString(),
|
||||||
firebase_messaging.RemoteMessage message) async {
|
'High Importance Notification',
|
||||||
try {
|
importance: Importance.max,
|
||||||
final type = message.data['type'] as String? ?? 'normal';
|
);
|
||||||
final title =
|
|
||||||
message.notification?.title ?? message.data['title'] ?? 'SFM';
|
|
||||||
final body = message.notification?.body ?? message.data['body'] ?? '';
|
|
||||||
|
|
||||||
dev.log('Foreground message: type=$type, title=$title, body=$body');
|
final androidPlugin = _flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
|
||||||
|
await androidPlugin?.deleteNotificationChannel(androidNotificationChannel.id);
|
||||||
|
|
||||||
if (type == 'smoke_warning') {
|
AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails(
|
||||||
// Hiển thị alarm, không hiển thị notification
|
androidNotificationChannel.id,
|
||||||
await _showAlarm(title, body);
|
androidNotificationChannel.name,
|
||||||
} else {
|
channelDescription: "Channel description",
|
||||||
// Hiển thị notification local
|
sound: getSound(type),
|
||||||
await _showForegroundNotification(title, body, type);
|
importance: androidNotificationChannel.importance,
|
||||||
}
|
priority: Priority.high,
|
||||||
} catch (e, stackTrace) {
|
ticker: 'ticker',
|
||||||
AppLoggerUtils.error('Error handling foreground message', e, stackTrace);
|
actions: type == "smoke_warning"
|
||||||
}
|
? [
|
||||||
}
|
const AndroidNotificationAction(
|
||||||
|
"id1",
|
||||||
|
"Hogg xóa được",
|
||||||
|
// true thì khi nhấn vào button sẽ mở giao diện ra
|
||||||
|
showsUserInterface: true,
|
||||||
|
cancelNotification: false,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
/// Hiển thị alarm (smoke warning)
|
const DarwinNotificationDetails darwinNotificationDetails = DarwinNotificationDetails(
|
||||||
Future<void> _showAlarm(String title, String body) async {
|
presentAlert: true,
|
||||||
try {
|
presentBadge: true,
|
||||||
await Alarm.init();
|
presentBanner: true,
|
||||||
|
presentSound: true,
|
||||||
|
);
|
||||||
|
|
||||||
final alarmSettings = AlarmSettings(
|
NotificationDetails notificationDetails = NotificationDetails(
|
||||||
id: 42,
|
android: androidNotificationDetails,
|
||||||
dateTime: DateTime.now(),
|
iOS: darwinNotificationDetails,
|
||||||
assetAudioPath: 'assets/sounds/warning_alarm.mp3',
|
);
|
||||||
loopAudio: true,
|
|
||||||
vibrate: true,
|
|
||||||
warningNotificationOnKill: Platform.isIOS,
|
|
||||||
androidFullScreenIntent: true,
|
|
||||||
volumeSettings: VolumeSettings.fade(
|
|
||||||
volume: 0.8,
|
|
||||||
fadeDuration: const Duration(seconds: 5),
|
|
||||||
volumeEnforced: true,
|
|
||||||
),
|
|
||||||
notificationSettings: NotificationSettings(
|
|
||||||
title: title,
|
|
||||||
body: body,
|
|
||||||
stopButton: 'Dừng thông báo',
|
|
||||||
icon: "ic_launcher",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await Alarm.set(alarmSettings: alarmSettings);
|
// Truyền payload vào thông báo
|
||||||
dev.log('Alarm set successfully: $title');
|
String payload = message.data['type'] ?? "default";
|
||||||
} catch (e, stackTrace) {
|
await _flutterLocalNotificationsPlugin.show(
|
||||||
AppLoggerUtils.error('Failed to set alarm', e, stackTrace);
|
math.Random.secure().nextInt(1000000),
|
||||||
}
|
title,
|
||||||
}
|
body,
|
||||||
|
notificationDetails,
|
||||||
/// Hiển thị notification local khi app foreground
|
payload: payload,
|
||||||
Future<void> _showForegroundNotification(
|
);
|
||||||
String title, String body, String type) async {
|
dev.log("Displayed notification with title: $title, body: $body, type: $type");
|
||||||
try {
|
|
||||||
final androidDetails = AndroidNotificationDetails(
|
|
||||||
'sfm_channel_${math.Random.secure().nextInt(1000000)}',
|
|
||||||
'SFM Notifications',
|
|
||||||
channelDescription: 'Notifications from SFM app',
|
|
||||||
sound: getSound(type),
|
|
||||||
importance: Importance.max,
|
|
||||||
priority: Priority.high,
|
|
||||||
ticker: 'ticker',
|
|
||||||
);
|
|
||||||
|
|
||||||
final iosDetails = DarwinNotificationDetails(
|
|
||||||
sound: _getSoundNameForIOS(type),
|
|
||||||
presentAlert: true,
|
|
||||||
presentBadge: true,
|
|
||||||
presentBanner: true,
|
|
||||||
presentSound: true,
|
|
||||||
);
|
|
||||||
|
|
||||||
final notificationDetails = NotificationDetails(
|
|
||||||
android: androidDetails,
|
|
||||||
iOS: iosDetails,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _notificationsPlugin.show(
|
|
||||||
math.Random.secure().nextInt(1000000),
|
|
||||||
title,
|
|
||||||
body,
|
|
||||||
notificationDetails,
|
|
||||||
payload: type,
|
|
||||||
);
|
|
||||||
|
|
||||||
dev.log('Foreground notification shown: title=$title, type=$type');
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLoggerUtils.error(
|
|
||||||
'Failed to show foreground notification', e, stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hiển thị notification cho background/terminate
|
|
||||||
Future<void> showBackgroundOrTerminateNotification(
|
|
||||||
firebase_messaging.RemoteMessage message) async {
|
|
||||||
try {
|
|
||||||
final type = message.data['type'] as String? ?? 'normal';
|
|
||||||
final title =
|
|
||||||
message.notification?.title ?? message.data['title'] ?? 'SFM';
|
|
||||||
final body = message.notification?.body ?? message.data['body'] ?? '';
|
|
||||||
|
|
||||||
dev.log('Background/terminate notification: type=$type, title=$title');
|
|
||||||
|
|
||||||
// Cho Android: nếu type = smoke_warning, hiển thị alarm
|
|
||||||
// Cho iOS: chỉ hiển thị notification, APNs payload sẽ phát sound natively
|
|
||||||
if (type == 'smoke_warning' && Platform.isAndroid) {
|
|
||||||
dev.log('→ Showing alarm for Android background');
|
|
||||||
await _showAlarm(title, body);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hiển thị notification (cho cả iOS lẫn Android, nhưng iOS không có alarm)
|
|
||||||
final channelId = math.Random.secure().nextInt(1000000).toString();
|
|
||||||
const channelName = 'SFM Notifications';
|
|
||||||
const channelDescription = 'Notifications from SFM app';
|
|
||||||
|
|
||||||
final androidDetails = AndroidNotificationDetails(
|
|
||||||
channelId,
|
|
||||||
channelName,
|
|
||||||
channelDescription: channelDescription,
|
|
||||||
sound: getSound(type),
|
|
||||||
importance: Importance.max,
|
|
||||||
priority: Priority.high,
|
|
||||||
ticker: 'ticker',
|
|
||||||
);
|
|
||||||
|
|
||||||
final iosDetails = DarwinNotificationDetails(
|
|
||||||
sound: _getSoundNameForIOS(type),
|
|
||||||
presentAlert: true,
|
|
||||||
presentBadge: true,
|
|
||||||
presentBanner: true,
|
|
||||||
presentSound: true,
|
|
||||||
);
|
|
||||||
|
|
||||||
final notificationDetails = NotificationDetails(
|
|
||||||
android: androidDetails,
|
|
||||||
iOS: iosDetails,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _notificationsPlugin.show(
|
|
||||||
int.parse(channelId),
|
|
||||||
title,
|
|
||||||
body,
|
|
||||||
notificationDetails,
|
|
||||||
payload: type,
|
|
||||||
);
|
|
||||||
|
|
||||||
dev.log(
|
|
||||||
'Background/terminate notification shown: title=$title, type=$type');
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLoggerUtils.error(
|
|
||||||
'Failed to show background/terminate notification', e, stackTrace);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidNotificationSound getSound(String type) {
|
AndroidNotificationSound getSound(String type) {
|
||||||
@@ -269,110 +128,35 @@ class NotificationServices {
|
|||||||
} else if (type == "battery_warning") {
|
} else if (type == "battery_warning") {
|
||||||
return const RawResourceAndroidNotificationSound("new_alarm");
|
return const RawResourceAndroidNotificationSound("new_alarm");
|
||||||
} else {
|
} else {
|
||||||
return const RawResourceAndroidNotificationSound("warning_alarm");
|
return const RawResourceAndroidNotificationSound("normal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getSoundNameForIOS(String type) {
|
|
||||||
// iOS tìm file trong app bundle (không có đuôi)
|
|
||||||
if (type == "smoke_warning" || type == "battery_warning") {
|
|
||||||
return "warning_alarm"; // file: warning_alarm.caf trong bundle
|
|
||||||
}
|
|
||||||
return "default";
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleMessage(String? payload, PersistentTabController controller) {
|
void handleMessage(String? payload, PersistentTabController controller) {
|
||||||
AppLoggerUtils.info("Handling notification tap with payload: $payload");
|
dev.log("Handling notification tap with payload: $payload");
|
||||||
controller.jumpToTab(1);
|
controller.jumpToTab(1);
|
||||||
|
|
||||||
if (payload == "smoke_warning") {
|
|
||||||
// TODO: Navigate to smoke warning screen nếu cần
|
|
||||||
// NavigationRouter.navigateToSmokeWarningScreen();
|
|
||||||
} else if (payload == "battery_warning") {
|
|
||||||
// TODO: Navigate to battery warning screen nếu cần
|
|
||||||
// NavigationRouter.navigateToBatteryWarningScreen();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setupInteractMessage(PersistentTabController controller) async {
|
Future<void> setupInteractMessage(PersistentTabController controller) async {
|
||||||
// Khi app terminated, được mở bằng notification
|
// Khi app terminated
|
||||||
firebase_messaging.RemoteMessage? initialMessage =
|
RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();
|
||||||
await firebase_messaging.FirebaseMessaging.instance.getInitialMessage();
|
|
||||||
|
|
||||||
if (initialMessage != null) {
|
if (initialMessage != null) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
final type = initialMessage.data['type'] as String?;
|
try {
|
||||||
handleMessage(type, controller);
|
handleMessage(initialMessage.data['type'],controller);
|
||||||
|
} catch (e, stack) {
|
||||||
|
dev.log("Error handling initial message: $e\n$stack");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Khi app ở background
|
||||||
// Khi app background, user tap notification
|
FirebaseMessaging.onMessageOpenedApp.listen((message) {
|
||||||
firebase_messaging.FirebaseMessaging.onMessageOpenedApp.listen((message) {
|
|
||||||
try {
|
try {
|
||||||
final type = message.data['type'] as String?;
|
handleMessage(message.data['type'],controller);
|
||||||
handleMessage(type, controller);
|
} catch (e, stack) {
|
||||||
} catch (e, stackTrace) {
|
dev.log("Error in onMessageOpenedApp: $e\n$stack");
|
||||||
AppLoggerUtils.error('Error in onMessageOpenedApp', e, stackTrace);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
|
||||||
static Future<void> firebaseMessagingBackgroundHandler(
|
|
||||||
firebase_messaging.RemoteMessage message) async {
|
|
||||||
try {
|
|
||||||
// Log to device storage for debugging background isolate
|
|
||||||
dev.log('═══ BACKGROUND HANDLER STARTED ═══');
|
|
||||||
dev.log('Message data: ${message.data}');
|
|
||||||
dev.log('Notification: ${message.notification}');
|
|
||||||
|
|
||||||
await Alarm.init();
|
|
||||||
dev.log('✓ Alarm initialized');
|
|
||||||
|
|
||||||
if (Firebase.apps.isEmpty) {
|
|
||||||
await Firebase.initializeApp(
|
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
|
||||||
name: "sfm-notification",
|
|
||||||
);
|
|
||||||
dev.log('✓ Firebase initialized in background');
|
|
||||||
} else {
|
|
||||||
dev.log('✓ Firebase already initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
final type = message.data['type'] as String? ?? 'normal';
|
|
||||||
final title = message.notification?.title ??
|
|
||||||
message.data['title'] ??
|
|
||||||
'Thông báo từ SmartFM';
|
|
||||||
final body = message.notification?.body ??
|
|
||||||
message.data['body'] ??
|
|
||||||
'Bạn có một thông báo mới';
|
|
||||||
|
|
||||||
dev.log('Message type: $type');
|
|
||||||
dev.log('Title: $title');
|
|
||||||
dev.log('Body: $body');
|
|
||||||
|
|
||||||
// Logic: Hiển thị local notification cho background/terminate
|
|
||||||
// iOS sẽ phát sound natively thông qua APNs payload (aps.sound)
|
|
||||||
// Android sẽ phát sound thông qua local notification
|
|
||||||
try {
|
|
||||||
final notificationService = NotificationServices();
|
|
||||||
await notificationService.initialize();
|
|
||||||
dev.log('✓ Notification service initialized');
|
|
||||||
|
|
||||||
await notificationService
|
|
||||||
.showBackgroundOrTerminateNotification(message);
|
|
||||||
dev.log('✓ Background/terminate notification shown');
|
|
||||||
} catch (notifError, notifStackTrace) {
|
|
||||||
dev.log('✗ ERROR showing notification: $notifError');
|
|
||||||
dev.log('Stack trace: $notifStackTrace');
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev.log('═══ BACKGROUND HANDLER COMPLETED ═══');
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
dev.log('✗ BACKGROUND HANDLER FAILED');
|
|
||||||
dev.log('Error: $e');
|
|
||||||
dev.log('Stack trace: $stackTrace');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/product/constant/image/image_constants.dart';
|
||||||
import '../constant/image/image_constants.dart';
|
|
||||||
|
|
||||||
class SharedBackground extends StatelessWidget {
|
class SharedBackground extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:lottie/lottie.dart';
|
|
||||||
|
|
||||||
class SharedComponentLoadingAnimation extends StatefulWidget {
|
|
||||||
const SharedComponentLoadingAnimation({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<SharedComponentLoadingAnimation> createState() => _SharedComponentLoadingAnimationState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SharedComponentLoadingAnimationState extends State<SharedComponentLoadingAnimation> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Center(
|
|
||||||
child: LottieBuilder.asset(
|
|
||||||
'assets/animations/component_loading.json',
|
|
||||||
width: 80,
|
|
||||||
height: 80,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/product/constant/icon/icon_constants.dart';
|
||||||
import '../constant/icon/icon_constants.dart';
|
|
||||||
|
|
||||||
const int _kDuration = 300;
|
const int _kDuration = 300;
|
||||||
const double _kWidth = 60;
|
const double _kWidth = 60;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../../feature/device_log/device_logs_model.dart';
|
import 'package:sfm_app/feature/device_log/device_logs_model.dart';
|
||||||
import '../utils/date_time_utils.dart';
|
import 'package:sfm_app/product/utils/date_time_utils.dart';
|
||||||
|
|
||||||
Widget sharedLineChart(String chartName, List<SensorLogs> sensors) {
|
Widget sharedLineChart(String chartName, List<SensorLogs> sensors) {
|
||||||
return LineChart(
|
return LineChart(
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:lottie/lottie.dart';
|
|
||||||
|
|
||||||
class SharedLoadingAnimation extends StatefulWidget {
|
|
||||||
const SharedLoadingAnimation({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<SharedLoadingAnimation> createState() => _SharedLoadingAnimationState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SharedLoadingAnimationState extends State<SharedLoadingAnimation> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Center(
|
|
||||||
child: LottieBuilder.asset(
|
|
||||||
'assets/animations/loading.json',
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -182,23 +182,23 @@ class _SharedPieChartState extends State<SharedPieChart> {
|
|||||||
switch (originalIndex) {
|
switch (originalIndex) {
|
||||||
case 0: // OFFLINE_STATE
|
case 0: // OFFLINE_STATE
|
||||||
log("Touched Index device state = -1");
|
log("Touched Index device state = -1");
|
||||||
widget.devicesManagerBloc.getDeviceByState(context,-1);
|
widget.devicesManagerBloc.getDeviceByState(-1);
|
||||||
break;
|
break;
|
||||||
case 1: // NORMAL_STATE
|
case 1: // NORMAL_STATE
|
||||||
log("Touched Index Get device state = 0");
|
log("Touched Index Get device state = 0");
|
||||||
widget.devicesManagerBloc.getDeviceByState(context,0);
|
widget.devicesManagerBloc.getDeviceByState(0);
|
||||||
break;
|
break;
|
||||||
case 2: // WARNING_STATE
|
case 2: // WARNING_STATE
|
||||||
log("Touched Index Get device state = 1");
|
log("Touched Index Get device state = 1");
|
||||||
widget.devicesManagerBloc.getDeviceByState(context,1);
|
widget.devicesManagerBloc.getDeviceByState(1);
|
||||||
break;
|
break;
|
||||||
case 3: // INPROGRESS_STATE
|
case 3: // INPROGRESS_STATE
|
||||||
log("Touched Index Get device state = 2");
|
log("Touched Index Get device state = 2");
|
||||||
widget.devicesManagerBloc.getDeviceByState(context,2);
|
widget.devicesManagerBloc.getDeviceByState(2);
|
||||||
break;
|
break;
|
||||||
case 4: // ERROR_STATE
|
case 4: // ERROR_STATE
|
||||||
log("Touched Index Get device state = 3");
|
log("Touched Index Get device state = 3");
|
||||||
widget.devicesManagerBloc.getDeviceByState(context,3);
|
widget.devicesManagerBloc.getDeviceByState(3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class SharedRocketContainer extends CustomClipper<Path> {
|
|
||||||
@override
|
|
||||||
Path getClip(Size size) {
|
|
||||||
final double width = size.width;
|
|
||||||
final double height = size.height;
|
|
||||||
|
|
||||||
const double pointyWidth = 20.0;
|
|
||||||
|
|
||||||
Path path = Path();
|
|
||||||
path.moveTo(0, 0);
|
|
||||||
path.lineTo(width - pointyWidth, 0);
|
|
||||||
path.lineTo(width, height / 2);
|
|
||||||
path.lineTo(width - pointyWidth, height);
|
|
||||||
path.lineTo(0, height);
|
|
||||||
path.close();
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool shouldReclip(CustomClipper<Path> oldClipper) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/product/extension/context_extension.dart';
|
||||||
import 'package:top_snackbar_flutter/custom_snack_bar.dart';
|
import 'package:top_snackbar_flutter/custom_snack_bar.dart';
|
||||||
import 'package:top_snackbar_flutter/top_snack_bar.dart';
|
import 'package:top_snackbar_flutter/top_snack_bar.dart';
|
||||||
|
|
||||||
import '../extension/context_extension.dart';
|
|
||||||
|
|
||||||
void showNoIconTopSnackBar(BuildContext context, String message,
|
void showNoIconTopSnackBar(BuildContext context, String message,
|
||||||
Color backgroundColor, Color textColor) {
|
Color backgroundColor, Color textColor) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/product/theme/app_theme.dart';
|
||||||
|
|
||||||
import 'app_theme.dart';
|
|
||||||
class AppThemeDark extends AppTheme {
|
class AppThemeDark extends AppTheme {
|
||||||
static AppThemeDark? _instance;
|
static AppThemeDark? _instance;
|
||||||
static AppThemeDark get instance {
|
static AppThemeDark get instance {
|
||||||
@@ -13,7 +13,6 @@ class AppThemeDark extends AppTheme {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
ThemeData get theme => FlexThemeData.dark(
|
ThemeData get theme => FlexThemeData.dark(
|
||||||
scaffoldBackground: Colors.black,
|
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
scheme: FlexScheme.flutterDash,
|
scheme: FlexScheme.flutterDash,
|
||||||
subThemesData: const FlexSubThemesData(
|
subThemesData: const FlexSubThemesData(
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ class AppThemeLight extends AppTheme {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
ThemeData get theme => FlexThemeData.light(
|
ThemeData get theme => FlexThemeData.light(
|
||||||
scaffoldBackground: Colors.white,
|
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
scheme: FlexScheme.flutterDash,
|
scheme: FlexScheme.flutterDash,
|
||||||
bottomAppBarElevation: 20.0,
|
bottomAppBarElevation: 20.0,
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import 'package:logger/logger.dart';
|
|
||||||
|
|
||||||
class AppLoggerUtils{
|
|
||||||
static final Logger _logger = Logger(
|
|
||||||
printer: PrettyPrinter(
|
|
||||||
methodCount: 2,
|
|
||||||
errorMethodCount: 8,
|
|
||||||
lineLength: 120,
|
|
||||||
colors: true,
|
|
||||||
printEmojis: true,
|
|
||||||
dateTimeFormat: (DateTime dateTime) {
|
|
||||||
// Tùy chỉnh định dạng thời gian
|
|
||||||
return '[${DateTime.now().toLocal().toString().split(' ')[1]}]';
|
|
||||||
},
|
|
||||||
// dateTimeFormat: DateTimeFormat.dateAndTime
|
|
||||||
),
|
|
||||||
level: Level.debug, // Cấp độ log tối thiểu (có thể thay đổi trong môi trường production)
|
|
||||||
);
|
|
||||||
|
|
||||||
static void debug(String message, [dynamic error, StackTrace? stackTrace]) {
|
|
||||||
_logger.d(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void info(String message, [dynamic error, StackTrace? stackTrace]) {
|
|
||||||
_logger.i(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void warning(String message, [dynamic error, StackTrace? stackTrace]) {
|
|
||||||
_logger.w(message, error: error, stackTrace: stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void error(String message, [dynamic error, StackTrace? stackTrace]) {
|
|
||||||
_logger.e(message, error: error, stackTrace: stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void trace(String message, [dynamic error, StackTrace? stackTrace]) {
|
|
||||||
_logger.t(message, error: error, stackTrace: stackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sfm_app/feature/device_log/device_logs_model.dart';
|
||||||
|
import 'package:sfm_app/product/services/api_services.dart';
|
||||||
|
import 'package:sfm_app/product/services/language_services.dart';
|
||||||
|
import 'package:sfm_app/product/shared/model/district_model.dart';
|
||||||
|
import 'package:sfm_app/product/shared/model/province_model.dart';
|
||||||
|
|
||||||
import '../../feature/device_log/device_logs_model.dart';
|
|
||||||
import '../services/api_services.dart';
|
|
||||||
import '../services/language_services.dart';
|
|
||||||
import '../shared/model/district_model.dart';
|
|
||||||
import '../shared/model/province_model.dart';
|
|
||||||
import '../../feature/devices/device_model.dart';
|
import '../../feature/devices/device_model.dart';
|
||||||
import '../constant/icon/icon_constants.dart';
|
import '../constant/icon/icon_constants.dart';
|
||||||
import '../shared/model/ward_model.dart';
|
import '../shared/model/ward_model.dart';
|
||||||
@@ -91,34 +93,30 @@ class DeviceUtils {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<String> getFullDeviceLocation(
|
Future<String> getFullDeviceLocation(
|
||||||
BuildContext context, String areaPath, String? deviceName) async {
|
BuildContext context, String areaPath) async {
|
||||||
if (areaPath.isNotEmpty) {
|
if (areaPath != "") {
|
||||||
List<String> parts = areaPath.split('_');
|
List<String> parts = areaPath.split('_');
|
||||||
|
|
||||||
if (parts.length < 3 || parts[0].isEmpty || parts[1].isEmpty || parts[2].isEmpty) {
|
|
||||||
if (deviceName != null && deviceName.isNotEmpty) {
|
|
||||||
return deviceName;
|
|
||||||
} else {
|
|
||||||
return appLocalization(context).no_data_message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String provinceID = parts[0];
|
String provinceID = parts[0];
|
||||||
String districtID = parts[1];
|
String districtID = parts[1];
|
||||||
String wardID = parts[2];
|
String wardID = parts[2];
|
||||||
|
|
||||||
Province province = await apiServices.getProvinceByID(provinceID);
|
String provinceBody = await apiServices.getProvinceByID(provinceID);
|
||||||
District district = await apiServices.getDistrictByID(districtID);
|
final provinceItem = jsonDecode(provinceBody);
|
||||||
Ward ward = await apiServices.getWardByID(wardID);
|
Province province = Province.fromJson(provinceItem['data']);
|
||||||
|
String districtBody = await apiServices.getDistrictByID(districtID);
|
||||||
|
final districtItem = jsonDecode(districtBody);
|
||||||
|
District district = District.fromJson(districtItem['data']);
|
||||||
|
String wardBody = await apiServices.getWardByID(wardID);
|
||||||
|
final wardItem = jsonDecode(wardBody);
|
||||||
|
Ward ward = Ward.fromJson(wardItem['data']);
|
||||||
|
|
||||||
return "${ward.fullName}, ${district.fullName}, ${province.fullName}";
|
return "${ward.fullName}, ${district.fullName}, ${province.fullName}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return appLocalization(context).no_data_message;
|
return appLocalization(context).no_data_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String checkStateDevice(BuildContext context, int state) {
|
String checkStateDevice(BuildContext context, int state) {
|
||||||
String message = appLocalization(context).no_data_message;
|
String message = appLocalization(context).no_data_message;
|
||||||
if (state == 1) {
|
if (state == 1) {
|
||||||
@@ -159,11 +157,11 @@ class DeviceUtils {
|
|||||||
} else if (state == 0) {
|
} else if (state == 0) {
|
||||||
return const Color(0xFF9EF16D);
|
return const Color(0xFF9EF16D);
|
||||||
} else if (state == 2) {
|
} else if (state == 2) {
|
||||||
return const Color(0xFFF5EF44);
|
return const Color(0xFFF5EF44);;
|
||||||
} else if (state == -1) {
|
} else if (state == -1) {
|
||||||
return const Color(0xFFBBBAC2);
|
return const Color(0xFFBBBAC2);;
|
||||||
} else {
|
} else {
|
||||||
return const Color(0xFFF5EF44);
|
return const Color(0xFFF5EF44);;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user