Compare commits
20 Commits
update_doo
...
forgetpass
| Author | SHA1 | Date | |
|---|---|---|---|
| 76be98354b | |||
| 3418fbe7b4 | |||
| ea3bc4b5e1 | |||
| e63bf2a2c2 | |||
| bf944a6121 | |||
| eb5aa56536 | |||
| 1e35bb8736 | |||
| 9c23ab1399 | |||
| b3bb0b9eea | |||
| dcc98445d7 | |||
| 611c515173 | |||
| e733dd9230 | |||
| 8e104aeea7 | |||
| f6fbf452a0 | |||
| 5aec3d37fb | |||
| a32d885e50 | |||
| afe37dd68a | |||
| f83224ce60 | |||
| 3f0fcc79aa | |||
| 33ec234c0d |
116
ios/Podfile.lock
@ -1,46 +1,54 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Firebase/Analytics (10.20.0):
|
- Firebase/Analytics (10.25.0):
|
||||||
- Firebase/Core
|
- Firebase/Core
|
||||||
- Firebase/Core (10.20.0):
|
- Firebase/Core (10.25.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseAnalytics (~> 10.20.0)
|
- FirebaseAnalytics (~> 10.25.0)
|
||||||
- Firebase/CoreOnly (10.20.0):
|
- Firebase/CoreOnly (10.25.0):
|
||||||
- FirebaseCore (= 10.20.0)
|
- FirebaseCore (= 10.25.0)
|
||||||
- Firebase/Crashlytics (10.20.0):
|
- Firebase/Crashlytics (10.25.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseCrashlytics (~> 10.20.0)
|
- FirebaseCrashlytics (~> 10.25.0)
|
||||||
|
- Firebase/Database (10.25.0):
|
||||||
|
- Firebase/CoreOnly
|
||||||
|
- FirebaseDatabase (~> 10.25.0)
|
||||||
- firebase_analytics (10.8.7):
|
- firebase_analytics (10.8.7):
|
||||||
- Firebase/Analytics (= 10.20.0)
|
- Firebase/Analytics (= 10.25.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_core (2.25.5):
|
- firebase_core (2.32.0):
|
||||||
- Firebase/CoreOnly (= 10.20.0)
|
- Firebase/CoreOnly (= 10.25.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_crashlytics (3.4.16):
|
- firebase_crashlytics (3.4.16):
|
||||||
- Firebase/Crashlytics (= 10.20.0)
|
- Firebase/Crashlytics (= 10.25.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseAnalytics (10.20.0):
|
- firebase_database (10.5.7):
|
||||||
- FirebaseAnalytics/AdIdSupport (= 10.20.0)
|
- Firebase/Database (= 10.25.0)
|
||||||
|
- firebase_core
|
||||||
|
- Flutter
|
||||||
|
- FirebaseAnalytics (10.25.0):
|
||||||
|
- FirebaseAnalytics/AdIdSupport (= 10.25.0)
|
||||||
- FirebaseCore (~> 10.0)
|
- FirebaseCore (~> 10.0)
|
||||||
- FirebaseInstallations (~> 10.0)
|
- FirebaseInstallations (~> 10.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/Network (~> 7.11)
|
- GoogleUtilities/Network (~> 7.11)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- FirebaseAnalytics/AdIdSupport (10.20.0):
|
- FirebaseAnalytics/AdIdSupport (10.25.0):
|
||||||
- FirebaseCore (~> 10.0)
|
- FirebaseCore (~> 10.0)
|
||||||
- FirebaseInstallations (~> 10.0)
|
- FirebaseInstallations (~> 10.0)
|
||||||
- GoogleAppMeasurement (= 10.20.0)
|
- GoogleAppMeasurement (= 10.25.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/Network (~> 7.11)
|
- GoogleUtilities/Network (~> 7.11)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- FirebaseCore (10.20.0):
|
- FirebaseAppCheckInterop (10.29.0)
|
||||||
|
- FirebaseCore (10.25.0):
|
||||||
- FirebaseCoreInternal (~> 10.0)
|
- FirebaseCoreInternal (~> 10.0)
|
||||||
- GoogleUtilities/Environment (~> 7.12)
|
- GoogleUtilities/Environment (~> 7.12)
|
||||||
- GoogleUtilities/Logger (~> 7.12)
|
- GoogleUtilities/Logger (~> 7.12)
|
||||||
@ -48,19 +56,27 @@ PODS:
|
|||||||
- FirebaseCore (~> 10.0)
|
- FirebaseCore (~> 10.0)
|
||||||
- FirebaseCoreInternal (10.29.0):
|
- FirebaseCoreInternal (10.29.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||||
- FirebaseCrashlytics (10.20.0):
|
- FirebaseCrashlytics (10.25.0):
|
||||||
- FirebaseCore (~> 10.5)
|
- FirebaseCore (~> 10.5)
|
||||||
- FirebaseInstallations (~> 10.0)
|
- FirebaseInstallations (~> 10.0)
|
||||||
|
- FirebaseRemoteConfigInterop (~> 10.23)
|
||||||
- FirebaseSessions (~> 10.5)
|
- FirebaseSessions (~> 10.5)
|
||||||
- GoogleDataTransport (~> 9.2)
|
- GoogleDataTransport (~> 9.2)
|
||||||
- GoogleUtilities/Environment (~> 7.8)
|
- GoogleUtilities/Environment (~> 7.8)
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- PromisesObjC (~> 2.1)
|
- PromisesObjC (~> 2.1)
|
||||||
|
- FirebaseDatabase (10.25.0):
|
||||||
|
- FirebaseAppCheckInterop (~> 10.17)
|
||||||
|
- FirebaseCore (~> 10.0)
|
||||||
|
- FirebaseSharedSwift (~> 10.0)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 7.13)
|
||||||
|
- leveldb-library (~> 1.22)
|
||||||
- FirebaseInstallations (10.29.0):
|
- FirebaseInstallations (10.29.0):
|
||||||
- FirebaseCore (~> 10.0)
|
- FirebaseCore (~> 10.0)
|
||||||
- GoogleUtilities/Environment (~> 7.8)
|
- GoogleUtilities/Environment (~> 7.8)
|
||||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||||
- PromisesObjC (~> 2.1)
|
- PromisesObjC (~> 2.1)
|
||||||
|
- FirebaseRemoteConfigInterop (10.29.0)
|
||||||
- FirebaseSessions (10.29.0):
|
- FirebaseSessions (10.29.0):
|
||||||
- FirebaseCore (~> 10.5)
|
- FirebaseCore (~> 10.5)
|
||||||
- FirebaseCoreExtension (~> 10.0)
|
- FirebaseCoreExtension (~> 10.0)
|
||||||
@ -70,31 +86,32 @@ PODS:
|
|||||||
- GoogleUtilities/UserDefaults (~> 7.13)
|
- GoogleUtilities/UserDefaults (~> 7.13)
|
||||||
- nanopb (< 2.30911.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- PromisesSwift (~> 2.1)
|
- PromisesSwift (~> 2.1)
|
||||||
|
- FirebaseSharedSwift (10.29.0)
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_localization (0.0.1):
|
- flutter_localization (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_secure_storage (6.0.0):
|
- flutter_secure_storage (6.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- GoogleAppMeasurement (10.20.0):
|
- GoogleAppMeasurement (10.25.0):
|
||||||
- GoogleAppMeasurement/AdIdSupport (= 10.20.0)
|
- GoogleAppMeasurement/AdIdSupport (= 10.25.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/Network (~> 7.11)
|
- GoogleUtilities/Network (~> 7.11)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- GoogleAppMeasurement/AdIdSupport (10.20.0):
|
- GoogleAppMeasurement/AdIdSupport (10.25.0):
|
||||||
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.20.0)
|
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.25.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/Network (~> 7.11)
|
- GoogleUtilities/Network (~> 7.11)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- GoogleAppMeasurement/WithoutAdIdSupport (10.20.0):
|
- GoogleAppMeasurement/WithoutAdIdSupport (10.25.0):
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||||
- GoogleUtilities/Network (~> 7.11)
|
- GoogleUtilities/Network (~> 7.11)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
- GoogleDataTransport (9.4.1):
|
- GoogleDataTransport (9.4.1):
|
||||||
- GoogleUtilities/Environment (~> 7.7)
|
- GoogleUtilities/Environment (~> 7.7)
|
||||||
- nanopb (< 2.30911.0, >= 2.30908.0)
|
- nanopb (< 2.30911.0, >= 2.30908.0)
|
||||||
@ -129,11 +146,12 @@ PODS:
|
|||||||
- GoogleUtilities/Privacy
|
- GoogleUtilities/Privacy
|
||||||
- image_picker_ios (0.0.1):
|
- image_picker_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- nanopb (2.30909.1):
|
- leveldb-library (1.22.5)
|
||||||
- nanopb/decode (= 2.30909.1)
|
- nanopb (2.30910.0):
|
||||||
- nanopb/encode (= 2.30909.1)
|
- nanopb/decode (= 2.30910.0)
|
||||||
- nanopb/decode (2.30909.1)
|
- nanopb/encode (= 2.30910.0)
|
||||||
- nanopb/encode (2.30909.1)
|
- nanopb/decode (2.30910.0)
|
||||||
|
- nanopb/encode (2.30910.0)
|
||||||
- onesignal_flutter (5.2.0):
|
- onesignal_flutter (5.2.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- OneSignalXCFramework (= 5.2.0)
|
- OneSignalXCFramework (= 5.2.0)
|
||||||
@ -207,6 +225,7 @@ DEPENDENCIES:
|
|||||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||||
|
- firebase_database (from `.symlinks/plugins/firebase_database/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_localization (from `.symlinks/plugins/flutter_localization/ios`)
|
- flutter_localization (from `.symlinks/plugins/flutter_localization/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
@ -223,15 +242,20 @@ SPEC REPOS:
|
|||||||
trunk:
|
trunk:
|
||||||
- Firebase
|
- Firebase
|
||||||
- FirebaseAnalytics
|
- FirebaseAnalytics
|
||||||
|
- FirebaseAppCheckInterop
|
||||||
- FirebaseCore
|
- FirebaseCore
|
||||||
- FirebaseCoreExtension
|
- FirebaseCoreExtension
|
||||||
- FirebaseCoreInternal
|
- FirebaseCoreInternal
|
||||||
- FirebaseCrashlytics
|
- FirebaseCrashlytics
|
||||||
|
- FirebaseDatabase
|
||||||
- FirebaseInstallations
|
- FirebaseInstallations
|
||||||
|
- FirebaseRemoteConfigInterop
|
||||||
- FirebaseSessions
|
- FirebaseSessions
|
||||||
|
- FirebaseSharedSwift
|
||||||
- GoogleAppMeasurement
|
- GoogleAppMeasurement
|
||||||
- GoogleDataTransport
|
- GoogleDataTransport
|
||||||
- GoogleUtilities
|
- GoogleUtilities
|
||||||
|
- leveldb-library
|
||||||
- nanopb
|
- nanopb
|
||||||
- OneSignalXCFramework
|
- OneSignalXCFramework
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
@ -246,6 +270,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_core/ios"
|
:path: ".symlinks/plugins/firebase_core/ios"
|
||||||
firebase_crashlytics:
|
firebase_crashlytics:
|
||||||
:path: ".symlinks/plugins/firebase_crashlytics/ios"
|
:path: ".symlinks/plugins/firebase_crashlytics/ios"
|
||||||
|
firebase_database:
|
||||||
|
:path: ".symlinks/plugins/firebase_database/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_localization:
|
flutter_localization:
|
||||||
@ -271,25 +297,31 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
|
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
|
||||||
Firebase: 10c8cb12fb7ad2ae0c09ffc86cd9c1ab392a0031
|
Firebase: 0312a2352584f782ea56f66d91606891d4607f06
|
||||||
firebase_analytics: 2c1c3057d5da3bd3aab819f7e6ee153a4e46c59e
|
firebase_analytics: 3a9263fedec72970e6bd30a7132bbdd386de2c14
|
||||||
firebase_core: c8628c7ce80f79439149549052bff22f6784fbf5
|
firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197
|
||||||
firebase_crashlytics: 012078b4eec6fc9716f97ba3da0f0e44a04e95b1
|
firebase_crashlytics: 0b7cb41f5fb3b6889d0fb408cfce3cc7a4247061
|
||||||
FirebaseAnalytics: a2731bf3670747ce8f65368b118d18aa8e368246
|
firebase_database: 2713033e426b176d4fe5e7195f3d19aa1b549a91
|
||||||
FirebaseCore: 28045c1560a2600d284b9c45a904fe322dc890b6
|
FirebaseAnalytics: ec00fe8b93b41dc6fe4a28784b8e51da0647a248
|
||||||
|
FirebaseAppCheckInterop: 6a1757cfd4067d8e00fccd14fcc1b8fd78cfac07
|
||||||
|
FirebaseCore: 7ec4d0484817f12c3373955bc87762d96842d483
|
||||||
FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f
|
FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f
|
||||||
FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934
|
FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934
|
||||||
FirebaseCrashlytics: 81530595edb6d99f1918f723a6c33766a24a4c86
|
FirebaseCrashlytics: 4b96efb0ce73b38b2a85e8b8bd1bd8f63f09d015
|
||||||
|
FirebaseDatabase: faa489a42f5f868d23a55dd442d6e2099348458e
|
||||||
FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd
|
FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd
|
||||||
|
FirebaseRemoteConfigInterop: 6efda51fb5e2f15b16585197e26eaa09574e8a4d
|
||||||
FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
|
FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
|
||||||
|
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4
|
flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4
|
||||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||||
GoogleAppMeasurement: bb3c564c3efb933136af0e94899e0a46167466a8
|
GoogleAppMeasurement: 9abf64b682732fed36da827aa2a68f0221fd2356
|
||||||
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
||||||
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
|
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
|
||||||
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
|
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
|
||||||
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
|
leveldb-library: e8eadf9008a61f9e1dde3978c086d2b6d9b9dc28
|
||||||
|
nanopb: 438bc412db1928dac798aa6fd75726007be04262
|
||||||
onesignal_flutter: 5ce68a29861960168e81101cb1bd685d264361de
|
onesignal_flutter: 5ce68a29861960168e81101cb1bd685d264361de
|
||||||
OneSignalXCFramework: bdf74fdc06888f9466dc21e826fe1549ed143095
|
OneSignalXCFramework: bdf74fdc06888f9466dc21e826fe1549ed143095
|
||||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||||
|
|||||||
@ -514,8 +514,8 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
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 = 20;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = 48V27SBR8J;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
||||||
@ -524,7 +524,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.0;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@ -706,8 +706,8 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
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 = 20;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = 48V27SBR8J;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
||||||
@ -716,7 +716,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.0;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@ -736,8 +736,8 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
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 = 20;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = 48V27SBR8J;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
||||||
@ -746,7 +746,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.0;
|
MARKETING_VERSION = 1.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|||||||
@ -1,115 +1,115 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "logo-20@2x.png",
|
"filename" : "Syncrow Icon-20@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-20@3x.png",
|
"filename" : "Syncrow Icon-20@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-29.png",
|
"filename" : "Syncrow Icon-29.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-29@2x.png",
|
"filename" : "Syncrow Icon-29@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-29@3x.png",
|
"filename" : "Syncrow Icon-29@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-40@2x.png",
|
"filename" : "Syncrow Icon-40@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-40@3x.png",
|
"filename" : "Syncrow Icon-40@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-60@2x.png",
|
"filename" : "Syncrow Icon-60@2x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-60@3x.png",
|
"filename" : "Syncrow Icon-60@3x.png",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"size" : "60x60"
|
"size" : "60x60"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-20.png",
|
"filename" : "Syncrow Icon-20.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-20@2x 1.png",
|
"filename" : "Syncrow Icon-20@2x 1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "20x20"
|
"size" : "20x20"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-29 1.png",
|
"filename" : "Syncrow Icon-29 1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-29@2x 1.png",
|
"filename" : "Syncrow Icon-29@2x 1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "29x29"
|
"size" : "29x29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-40.png",
|
"filename" : "Syncrow Icon-40.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-40@2x 1.png",
|
"filename" : "Syncrow Icon-40@2x 1.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "40x40"
|
"size" : "40x40"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-76.png",
|
"filename" : "Syncrow Icon-76.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "76x76"
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-76@2x.png",
|
"filename" : "Syncrow Icon-76@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "76x76"
|
"size" : "76x76"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-83.5@2x.png",
|
"filename" : "Syncrow Icon-83.5@2x.png",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "83.5x83.5"
|
"size" : "83.5x83.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "logo-1024.png",
|
"filename" : "Syncrow Icon-1024.png",
|
||||||
"idiom" : "ios-marketing",
|
"idiom" : "ios-marketing",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
|||||||
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
@ -11,10 +11,7 @@ import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdo
|
|||||||
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||||
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
|
||||||
import 'package:syncrow_app/features/menu/view/menu_view.dart';
|
import 'package:syncrow_app/features/menu/view/menu_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||||
@ -22,10 +19,7 @@ import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_b
|
|||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
import 'package:syncrow_app/features/scene/bloc/smart_scene/smart_scene_select_dart_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||||
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
import 'package:syncrow_app/features/scene/model/scene_settings_route_arguments.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/create_scene_view.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||||
@ -33,10 +27,8 @@ import 'package:syncrow_app/navigation/routing_constants.dart';
|
|||||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
import 'package:syncrow_app/services/api/profile_api.dart';
|
import 'package:syncrow_app/services/api/profile_api.dart';
|
||||||
import 'package:syncrow_app/services/api/spaces_api.dart';
|
import 'package:syncrow_app/services/api/spaces_api.dart';
|
||||||
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
|
||||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
|
||||||
|
|
||||||
part 'home_state.dart';
|
part 'home_state.dart';
|
||||||
|
|
||||||
@ -161,7 +153,7 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sendSubscriptionId() async {
|
_sendSubscriptionId() async {
|
||||||
String? subscriptionId = OneSignal.User.pushSubscription.id ?? '';
|
// String? subscriptionId = OneSignal.User.pushSubscription.id ?? '';
|
||||||
//TODO send the subscription id to BE
|
//TODO send the subscription id to BE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
@ -59,18 +58,30 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
|
|
||||||
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
||||||
String? passwordValidator(String? value) {
|
String? passwordValidator(String? value) {
|
||||||
if (value != null) {
|
if (value == null || value.isEmpty) {
|
||||||
if (value.isEmpty) {
|
return "Please enter your password";
|
||||||
return 'Please enter your password';
|
|
||||||
}
|
|
||||||
if (value.isNotEmpty) {
|
|
||||||
if (!RegExp(
|
|
||||||
r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!"#$%&()*+,-./:;<=>?@[\]^_`{|}~])[A-Za-z\d!"#$%&()*+,-./:;<=>?@[\]^_`{|}~]{8,}$')
|
|
||||||
.hasMatch(value)) {
|
|
||||||
return 'Password must contain at least:\n - one uppercase letter.\n - one lowercase letter.\n - one number. \n - special character';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value.length < 8) {
|
||||||
|
return 'Password must be at least 8 characters long';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RegExp(r'[a-z]').hasMatch(value)) {
|
||||||
|
return 'Password must contain at least one lowercase letter';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RegExp(r'[A-Z]').hasMatch(value)) {
|
||||||
|
return 'Password must contain at least one uppercase letter';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RegExp(r'\d').hasMatch(value)) {
|
||||||
|
return 'Password must contain at least one number';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RegExp(r'[!"#$%&()*+,-./:;<=>?@[\]^_`{|}~]').hasMatch(value)) {
|
||||||
|
return 'Password must contain at least one special character';
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,13 +193,10 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
debugPrint('token: ${token.accessToken}');
|
debugPrint('token: ${token.accessToken}');
|
||||||
FlutterSecureStorage storage = const FlutterSecureStorage();
|
FlutterSecureStorage storage = const FlutterSecureStorage();
|
||||||
await storage.write(
|
await storage.write(
|
||||||
key: Token.loginAccessTokenKey,
|
key: Token.loginAccessTokenKey, value: token.accessToken);
|
||||||
value: token.accessToken
|
|
||||||
);
|
|
||||||
const FlutterSecureStorage().write(
|
const FlutterSecureStorage().write(
|
||||||
key: UserModel.userUuidKey,
|
key: UserModel.userUuidKey,
|
||||||
value: Token.decodeToken(token.accessToken)['uuid'].toString()
|
value: Token.decodeToken(token.accessToken)['uuid'].toString());
|
||||||
);
|
|
||||||
user = UserModel.fromToken(token);
|
user = UserModel.fromToken(token);
|
||||||
emailController.clear();
|
emailController.clear();
|
||||||
passwordController.clear();
|
passwordController.clear();
|
||||||
@ -225,7 +233,8 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
sendOtp() async {
|
sendOtp() async {
|
||||||
try {
|
try {
|
||||||
emit(AuthLoading());
|
emit(AuthLoading());
|
||||||
await AuthenticationAPI.sendOtp(body: {'email': email, 'type': 'VERIFICATION'});
|
await AuthenticationAPI.sendOtp(
|
||||||
|
body: {'email': email, 'type': 'VERIFICATION'});
|
||||||
emit(AuthSignUpSuccess());
|
emit(AuthSignUpSuccess());
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
emit(AuthLoginError(message: 'Something went wrong'));
|
emit(AuthLoginError(message: 'Something went wrong'));
|
||||||
@ -235,7 +244,8 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
reSendOtp() async {
|
reSendOtp() async {
|
||||||
try {
|
try {
|
||||||
emit(AuthLoading());
|
emit(AuthLoading());
|
||||||
await AuthenticationAPI.sendOtp(body: {'email': email, 'type': 'VERIFICATION'});
|
await AuthenticationAPI.sendOtp(
|
||||||
|
body: {'email': email, 'type': 'VERIFICATION'});
|
||||||
emit(ResendOtpSuccess());
|
emit(ResendOtpSuccess());
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
emit(AuthLoginError(message: 'Something went wrong'));
|
emit(AuthLoginError(message: 'Something went wrong'));
|
||||||
@ -282,13 +292,16 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
try {
|
try {
|
||||||
emit(AuthTokenLoading());
|
emit(AuthTokenLoading());
|
||||||
const storage = FlutterSecureStorage();
|
const storage = FlutterSecureStorage();
|
||||||
final firstLaunch = await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
|
final firstLaunch = await SharedPreferencesHelper.readBoolFromSP(
|
||||||
|
StringsManager.firstLaunch) ??
|
||||||
|
true;
|
||||||
|
|
||||||
if (firstLaunch) {
|
if (firstLaunch) {
|
||||||
storage.deleteAll();
|
storage.deleteAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
|
await SharedPreferencesHelper.saveBoolToSP(
|
||||||
|
StringsManager.firstLaunch, false);
|
||||||
|
|
||||||
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
|
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
@ -315,7 +328,6 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sendToForgetPassword({required String password}) async {
|
sendToForgetPassword({required String password}) async {
|
||||||
try {
|
try {
|
||||||
emit(AuthForgetPassLoading());
|
emit(AuthForgetPassLoading());
|
||||||
@ -325,8 +337,4 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
emit(AuthForgetPassError(message: 'Something went wrong'));
|
emit(AuthForgetPassError(message: 'Something went wrong'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
|
||||||
@ -40,6 +40,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
|
|||||||
on<ChangeAllSwitch>(_changeAllAcSwitch);
|
on<ChangeAllSwitch>(_changeAllAcSwitch);
|
||||||
on<IncreaseAllTemp>(_increaseAllTemp);
|
on<IncreaseAllTemp>(_increaseAllTemp);
|
||||||
on<DecreaseAllTemp>(_decreaseAllTemp);
|
on<DecreaseAllTemp>(_decreaseAllTemp);
|
||||||
|
on<AcUpdated>(_onAcUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchAcsStatus(AcsInitial event, Emitter<AcsState> emit) async {
|
void _fetchAcsStatus(AcsInitial event, Emitter<AcsState> emit) async {
|
||||||
@ -62,6 +63,8 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
|
|||||||
}
|
}
|
||||||
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
|
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
|
||||||
emit(GetAcStatusState(acStatusModel: deviceStatus));
|
emit(GetAcStatusState(acStatusModel: deviceStatus));
|
||||||
|
Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
_listenToChanges();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(AcsFailedState(errorMessage: e.toString()));
|
emit(AcsFailedState(errorMessage: e.toString()));
|
||||||
@ -69,6 +72,29 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$acId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) {
|
||||||
|
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = AcStatusModel.fromJson(usersMap['productUuid'], statusList);
|
||||||
|
add(AcUpdated());
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onAcUpdated(AcUpdated event, Emitter<AcsState> emit) {
|
||||||
|
emit(GetAcStatusState(acStatusModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
_getAllAcs() async {
|
_getAllAcs() async {
|
||||||
deviceStatusList = [];
|
deviceStatusList = [];
|
||||||
devicesList = [];
|
devicesList = [];
|
||||||
@ -164,7 +190,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
|
|||||||
deviceStatus.childLock = lockValue;
|
deviceStatus.childLock = lockValue;
|
||||||
emit(AcModifyingState(acStatusModel: deviceStatus));
|
emit(AcModifyingState(acStatusModel: deviceStatus));
|
||||||
|
|
||||||
_runDeBouncerForOneDevice(deviceId: acId, code: 'child_lock', value: lockValue);
|
await _runDeBouncerForOneDevice(deviceId: acId, code: 'child_lock', value: lockValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _increaseCoolTo(IncreaseCoolToTemp event, Emitter<AcsState> emit) async {
|
void _increaseCoolTo(IncreaseCoolToTemp event, Emitter<AcsState> emit) async {
|
||||||
|
|||||||
@ -20,6 +20,8 @@ class AcSwitch extends AcsEvent {
|
|||||||
List<Object> get props => [acSwitch, deviceId, productId];
|
List<Object> get props => [acSwitch, deviceId, productId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AcUpdated extends AcsEvent {}
|
||||||
|
|
||||||
class AcsInitial extends AcsEvent {
|
class AcsInitial extends AcsEvent {
|
||||||
final bool allAcs;
|
final bool allAcs;
|
||||||
const AcsInitial({required this.allAcs});
|
const AcsInitial({required this.allAcs});
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
|
||||||
@ -15,6 +16,7 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
CeilingSensorBloc({required this.deviceId}) : super(InitialState()) {
|
CeilingSensorBloc({required this.deviceId}) : super(InitialState()) {
|
||||||
on<InitialEvent>(_fetchCeilingSensorStatus);
|
on<InitialEvent>(_fetchCeilingSensorStatus);
|
||||||
on<ChangeValueEvent>(_changeValue);
|
on<ChangeValueEvent>(_changeValue);
|
||||||
|
on<CeilingSensorUpdated>(_onCeilingSensorUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<CeilingSensorState> emit) async {
|
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
@ -27,12 +29,36 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
}
|
}
|
||||||
deviceStatus = CeilingSensorModel.fromJson(statusModelList);
|
deviceStatus = CeilingSensorModel.fromJson(statusModelList);
|
||||||
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(error: e.toString()));
|
emit(FailedState(error: e.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) {
|
||||||
|
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = CeilingSensorModel.fromJson(statusList);
|
||||||
|
add(CeilingSensorUpdated());
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_onCeilingSensorUpdated(CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
|
||||||
|
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
void _changeValue(ChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
void _changeValue(ChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
emit(LoadingNewSate(ceilingSensorModel: deviceStatus));
|
emit(LoadingNewSate(ceilingSensorModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -11,6 +11,8 @@ class LoadingEvent extends CeilingSensorEvent {}
|
|||||||
|
|
||||||
class InitialEvent extends CeilingSensorEvent {}
|
class InitialEvent extends CeilingSensorEvent {}
|
||||||
|
|
||||||
|
class CeilingSensorUpdated extends CeilingSensorEvent {}
|
||||||
|
|
||||||
class ChangeValueEvent extends CeilingSensorEvent {
|
class ChangeValueEvent extends CeilingSensorEvent {
|
||||||
final int value;
|
final int value;
|
||||||
final String code;
|
final String code;
|
||||||
|
|||||||
184
lib/features/devices/bloc/curtain_bloc/curtain_bloc.dart
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||||
|
double curtainWidth = 270;
|
||||||
|
double curtainOpeningSpace = 195;
|
||||||
|
double blindHeight = 310;
|
||||||
|
double blindOpeningSpace = 245;
|
||||||
|
double openPercentage = 0;
|
||||||
|
bool isMoving = false;
|
||||||
|
final String curtainId;
|
||||||
|
|
||||||
|
CurtainBloc(
|
||||||
|
this.curtainId,
|
||||||
|
) : super(CurtainInitial()) {
|
||||||
|
on<InitCurtain>(_fetchStatus);
|
||||||
|
on<OpenCurtain>(_onOpenCurtain);
|
||||||
|
on<CloseCurtain>(_onCloseCurtain);
|
||||||
|
on<PauseCurtain>(_onPauseCurtain);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onOpenCurtain(
|
||||||
|
OpenCurtain event,
|
||||||
|
Emitter<CurtainState> emit) async {
|
||||||
|
isMoving = true;
|
||||||
|
while (openPercentage < 100.0) {
|
||||||
|
if (state is CurtainsClosing) {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emit(CurtainsOpening(
|
||||||
|
curtainWidth: curtainWidth,
|
||||||
|
blindHeight: blindHeight,
|
||||||
|
openPercentage: openPercentage,
|
||||||
|
));
|
||||||
|
if (isMoving) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 200), () async {
|
||||||
|
openPercentage += 10.0;
|
||||||
|
event.deviceType == DeviceType.Curtain
|
||||||
|
? curtainWidth -= curtainOpeningSpace / 10
|
||||||
|
: blindHeight -= blindOpeningSpace / 10;
|
||||||
|
if (openPercentage >= 100.0) {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (openPercentage >=100.0) {
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: curtainId,
|
||||||
|
code: 'control',
|
||||||
|
value: 'close',
|
||||||
|
),
|
||||||
|
curtainId,
|
||||||
|
);
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: curtainId,
|
||||||
|
code: 'percent_control',
|
||||||
|
value: 100,
|
||||||
|
),
|
||||||
|
curtainId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onCloseCurtain(
|
||||||
|
CloseCurtain event, Emitter<CurtainState> emit) async {
|
||||||
|
isMoving = true;
|
||||||
|
while (openPercentage > 0.0) {
|
||||||
|
if (state is CurtainsOpening) {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emit(CurtainsClosing(
|
||||||
|
curtainWidth: curtainWidth,
|
||||||
|
blindHeight: blindHeight,
|
||||||
|
openPercentage: openPercentage,
|
||||||
|
));
|
||||||
|
if (isMoving) {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 200), () async {
|
||||||
|
openPercentage -= 10.0;
|
||||||
|
event.deviceType == DeviceType.Curtain
|
||||||
|
? curtainWidth += curtainOpeningSpace / 10
|
||||||
|
: blindHeight += blindOpeningSpace / 10;
|
||||||
|
if (openPercentage <= 0.0) {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (openPercentage == 0.0) {
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: curtainId,
|
||||||
|
code: 'percent_control',
|
||||||
|
value: 0,
|
||||||
|
),
|
||||||
|
curtainId,
|
||||||
|
);
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: curtainId,
|
||||||
|
code: 'control',
|
||||||
|
value: 'open',
|
||||||
|
),
|
||||||
|
curtainId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onPauseCurtain(
|
||||||
|
PauseCurtain event, Emitter<CurtainState> emit) async {
|
||||||
|
_pauseCurtain(emit);
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: curtainId,
|
||||||
|
code: 'control',
|
||||||
|
value: 'stop',
|
||||||
|
),
|
||||||
|
curtainId,
|
||||||
|
);
|
||||||
|
await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: curtainId,
|
||||||
|
code: 'percent_control',
|
||||||
|
value: openPercentage.ceil(),
|
||||||
|
),
|
||||||
|
curtainId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _pauseCurtain(Emitter<CurtainState> emit) async {
|
||||||
|
isMoving = false;
|
||||||
|
emit(CurtainsPaused(
|
||||||
|
curtainWidth: curtainWidth,
|
||||||
|
blindHeight: blindHeight,
|
||||||
|
openPercentage: openPercentage,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async {
|
||||||
|
try {
|
||||||
|
emit(CurtainLoadingState());
|
||||||
|
// Fetch the status from the API
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(curtainId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
// Get the open percentage from the response
|
||||||
|
openPercentage = double.tryParse(statusModelList[1].value.toString())!;
|
||||||
|
// Calculate curtain width and blind height based on the open percentage
|
||||||
|
if (openPercentage != null) {
|
||||||
|
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
|
||||||
|
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
|
||||||
|
}
|
||||||
|
emit(CurtainsOpening(
|
||||||
|
curtainWidth: curtainWidth,
|
||||||
|
blindHeight: blindHeight,
|
||||||
|
openPercentage: openPercentage,
|
||||||
|
));
|
||||||
|
} catch (e) {
|
||||||
|
emit(FailedState());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
34
lib/features/devices/bloc/curtain_bloc/curtain_event.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
|
|
||||||
|
abstract class CurtainEvent extends Equatable {
|
||||||
|
const CurtainEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class OpenCurtain extends CurtainEvent {
|
||||||
|
final DeviceType deviceType;
|
||||||
|
|
||||||
|
const OpenCurtain(this.deviceType);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [deviceType];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CloseCurtain extends CurtainEvent {
|
||||||
|
final DeviceType deviceType;
|
||||||
|
|
||||||
|
const CloseCurtain(this.deviceType);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [deviceType];
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitCurtain extends CurtainEvent {}
|
||||||
|
class PauseCurtain extends CurtainEvent {}
|
||||||
|
class useCurtainEvent extends CurtainEvent {}
|
||||||
76
lib/features/devices/bloc/curtain_bloc/curtain_state.dart
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// curtain_state.dart
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class CurtainState extends Equatable {
|
||||||
|
const CurtainState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CurtainInitial extends CurtainState {}
|
||||||
|
|
||||||
|
class UpdateCurtain extends CurtainState {
|
||||||
|
|
||||||
|
final double curtainWidth;
|
||||||
|
final double blindHeight;
|
||||||
|
final double openPercentage;
|
||||||
|
|
||||||
|
const UpdateCurtain({
|
||||||
|
required this.curtainWidth,
|
||||||
|
required this.blindHeight,
|
||||||
|
required this.openPercentage,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FailedState extends CurtainState {}
|
||||||
|
|
||||||
|
class CurtainLoadingState extends CurtainState {}
|
||||||
|
|
||||||
|
class CurtainsOpening extends CurtainState {
|
||||||
|
final double curtainWidth;
|
||||||
|
final double blindHeight;
|
||||||
|
final double openPercentage;
|
||||||
|
|
||||||
|
const CurtainsOpening({
|
||||||
|
required this.curtainWidth,
|
||||||
|
required this.blindHeight,
|
||||||
|
required this.openPercentage,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CurtainsClosing extends CurtainState {
|
||||||
|
final double curtainWidth;
|
||||||
|
final double blindHeight;
|
||||||
|
final double openPercentage;
|
||||||
|
|
||||||
|
const CurtainsClosing({
|
||||||
|
required this.curtainWidth,
|
||||||
|
required this.blindHeight,
|
||||||
|
required this.openPercentage,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CurtainsPaused extends CurtainState {
|
||||||
|
final double curtainWidth;
|
||||||
|
final double blindHeight;
|
||||||
|
final double openPercentage;
|
||||||
|
|
||||||
|
const CurtainsPaused({
|
||||||
|
required this.curtainWidth,
|
||||||
|
required this.blindHeight,
|
||||||
|
required this.openPercentage,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [curtainWidth, blindHeight, openPercentage];
|
||||||
|
}
|
||||||
@ -87,10 +87,10 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
return const DoorsListView();
|
return const DoorsListView();
|
||||||
case DeviceType.Curtain:
|
case DeviceType.Curtain:
|
||||||
return const CurtainListView();
|
return const CurtainListView();
|
||||||
// case DeviceType.ThreeGang:
|
// case DeviceType.ThreeGang:
|
||||||
// return const ThreeGangSwitchesView();
|
// return const ThreeGangSwitchesView();
|
||||||
// case DeviceType.Gateway:
|
// case DeviceType.Gateway:
|
||||||
// return const GateWayView();
|
// return const GateWayView();
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -308,10 +308,10 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
|
|
||||||
emitSafe(GetDevicesLoading());
|
emitSafe(GetDevicesLoading());
|
||||||
int roomIndex =
|
int roomIndex =
|
||||||
HomeCubit.getInstance().selectedSpace!.rooms!.indexWhere((element) => element.id == roomId);
|
HomeCubit.getInstance().selectedSpace!.rooms!.indexWhere((element) => element.id == roomId);
|
||||||
try {
|
try {
|
||||||
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices =
|
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices =
|
||||||
await DevicesAPI.getDevicesByRoomId(roomId);
|
await DevicesAPI.getDevicesByRoomId(roomId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emitSafe(GetDevicesError(e.toString()));
|
emitSafe(GetDevicesError(e.toString()));
|
||||||
return;
|
return;
|
||||||
@ -397,87 +397,7 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//////////////////////////////////CURTAINS//////////////////////////////////////
|
|
||||||
double curtainWidth = 270;
|
|
||||||
double curtainOpeningSpace = 195;
|
|
||||||
double blindWindowHight = 310;
|
|
||||||
double blindOpeningSpace = 245;
|
|
||||||
double _openPercentage = 0;
|
|
||||||
bool isMoving = false;
|
|
||||||
|
|
||||||
openCurtain(DeviceType type) async {
|
|
||||||
if (state is CurtainsIsOpening) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isMoving = true;
|
|
||||||
while (_openPercentage < 100.0) {
|
|
||||||
if (state is CurtainsIsClosing) {
|
|
||||||
//listen to interruption by the closing process
|
|
||||||
pauseCurtain();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(CurtainsIsOpening());
|
|
||||||
|
|
||||||
if (isMoving) {
|
|
||||||
await Future.delayed(const Duration(milliseconds: 200), () {
|
|
||||||
_openPercentage += 10.0;
|
|
||||||
//25.5 is the 10% of the curtain opening space, its used to update the
|
|
||||||
// animated container of thecurtain
|
|
||||||
|
|
||||||
type == DeviceType.Curtain
|
|
||||||
? curtainWidth -= curtainOpeningSpace / 10
|
|
||||||
: blindWindowHight -= blindOpeningSpace / 10;
|
|
||||||
if (_openPercentage >= 100.0) {
|
|
||||||
pauseCurtain();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
pauseCurtain();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closeCurtain(DeviceType type) async {
|
|
||||||
if (state is CurtainsIsClosing) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isMoving = true;
|
|
||||||
while (_openPercentage > 0.0) {
|
|
||||||
if (state is CurtainsIsOpening) {
|
|
||||||
// interrupted by the opening process
|
|
||||||
pauseCurtain();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(CurtainsIsClosing());
|
|
||||||
|
|
||||||
if (isMoving) {
|
|
||||||
await Future.delayed(const Duration(milliseconds: 200), () {
|
|
||||||
_openPercentage -= 10.0;
|
|
||||||
//25.5 is the 10% of the curtain opening space, its used to update the
|
|
||||||
type == DeviceType.Curtain
|
|
||||||
? curtainWidth += curtainOpeningSpace / 10
|
|
||||||
: blindWindowHight += 24.5;
|
|
||||||
|
|
||||||
if (_openPercentage <= 0.0) {
|
|
||||||
pauseCurtain();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
pauseCurtain();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pauseCurtain() {
|
|
||||||
isMoving = false;
|
|
||||||
emit(CurtainsStopped());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LightMode {
|
enum LightMode {
|
||||||
|
|||||||
@ -1,17 +1,18 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/model/offline_password_model.dart';
|
import 'package:syncrow_app/features/devices/model/offline_password_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/offline_temporary_password.dart';
|
import 'package:syncrow_app/features/devices/model/offline_temporary_password.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/create_temporary_password_model.dart';
|
import 'package:syncrow_app/features/devices/model/create_temporary_password_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
|
import 'package:syncrow_app/features/devices/model/temporary_password_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/hour_picker_dialog.dart';
|
||||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
@ -23,6 +24,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
|
|
||||||
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
|
SmartDoorBloc({required this.deviceId}) : super(InitialState()) {
|
||||||
on<InitialEvent>(_fetchSmartDoorStatus);
|
on<InitialEvent>(_fetchSmartDoorStatus);
|
||||||
|
on<DoorLockUpdated>(_doorLockUpdated);
|
||||||
on<InitialPasswordsPage>(getTemporaryPasswords);
|
on<InitialPasswordsPage>(getTemporaryPasswords);
|
||||||
on<InitialOneTimePassword>(getOneTimePasswords);
|
on<InitialOneTimePassword>(getOneTimePasswords);
|
||||||
on<InitialTimeLimitPassword>(getTimeLimitPasswords);
|
on<InitialTimeLimitPassword>(getTimeLimitPasswords);
|
||||||
@ -32,7 +34,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
on<SetStartEndTimeEvent>(setStartEndTime);
|
on<SetStartEndTimeEvent>(setStartEndTime);
|
||||||
on<ChangeTimeEvent>(changeTime);
|
on<ChangeTimeEvent>(changeTime);
|
||||||
on<GeneratePasswordEvent>(generate7DigitNumber);
|
on<GeneratePasswordEvent>(generate7DigitNumber);
|
||||||
on<SelectTimeEvent>(selectTime);
|
on<SelectTimeEvent>(selectTimeOfLinePassword);
|
||||||
|
on<SelectTimeOnlinePasswordEvent>(selectTimeOnlinePassword);
|
||||||
on<DeletePasswordEvent>(deletePassword);
|
on<DeletePasswordEvent>(deletePassword);
|
||||||
on<GenerateAndSavePasswordTimeLimitEvent>(generateAndSavePasswordTimeLimited);
|
on<GenerateAndSavePasswordTimeLimitEvent>(generateAndSavePasswordTimeLimited);
|
||||||
on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime);
|
on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime);
|
||||||
@ -51,6 +54,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
bool isStartEndTime = true;
|
bool isStartEndTime = true;
|
||||||
DateTime? startTime;
|
DateTime? startTime;
|
||||||
DateTime? endTime;
|
DateTime? endTime;
|
||||||
|
int unlockRequest = 0;
|
||||||
List<TemporaryPassword>? temporaryPasswords = [];
|
List<TemporaryPassword>? temporaryPasswords = [];
|
||||||
List<OfflinePasswordModel>? oneTimePasswords = [];
|
List<OfflinePasswordModel>? oneTimePasswords = [];
|
||||||
List<OfflinePasswordModel>? timeLimitPasswords = [];
|
List<OfflinePasswordModel>? timeLimitPasswords = [];
|
||||||
@ -66,20 +70,24 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
return passwordController.text;
|
return passwordController.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future generateAndSavePasswordOneTime(
|
||||||
Future generateAndSavePasswordOneTime (GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async {
|
GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
if (isSavingPassword) return;
|
if (isSavingPassword) return;
|
||||||
isSavingPassword = true;
|
isSavingPassword = true;
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
var res = await DevicesAPI.generateOneTimePassword(deviceId: deviceId);
|
var res = await DevicesAPI.generateOneTimePassword(deviceId: deviceId);
|
||||||
ApiResponse pass= ApiResponse.fromJson(res);
|
ApiResponse pass = ApiResponse.fromJson(res);
|
||||||
passwordController.text =pass.data.offlineTempPassword;
|
passwordController.text = pass.data.offlineTempPassword;
|
||||||
passwordId=pass.data.offlineTempPasswordId;
|
passwordId = pass.data.offlineTempPasswordId;
|
||||||
|
|
||||||
|
Future.delayed(const Duration(seconds: 1), () {
|
||||||
|
Clipboard.setData(ClipboardData(text: passwordController.text));
|
||||||
|
});
|
||||||
emit(const GeneratePasswordOneTimestate(generated: true));
|
emit(const GeneratePasswordOneTimestate(generated: true));
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
emit(FailedState(errorMessage: _.toString()));
|
emit(FailedState(errorMessage: _.toString()));
|
||||||
}finally {
|
} finally {
|
||||||
isSavingPassword = false;
|
isSavingPassword = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,20 +102,44 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
}
|
}
|
||||||
deviceStatus = SmartDoorModel.fromJson(statusModelList);
|
deviceStatus = SmartDoorModel.fromJson(statusModelList);
|
||||||
emit(UpdateState(smartDoorModel: deviceStatus));
|
emit(UpdateState(smartDoorModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(errorMessage: e.toString()));
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) {
|
||||||
|
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = SmartDoorModel.fromJson(statusList);
|
||||||
|
add(DoorLockUpdated());
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_doorLockUpdated(DoorLockUpdated event, Emitter<SmartDoorState> emit) {
|
||||||
|
unlockRequest = deviceStatus.unlockRequest;
|
||||||
|
emit(UpdateState(smartDoorModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
void _renamePassword(RenamePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
void _renamePassword(RenamePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
var response = await DevicesAPI.renamePass(
|
await DevicesAPI.renamePass(
|
||||||
name:passwordNameController.text ,
|
name: passwordNameController.text, doorLockUuid: deviceId, passwordId: passwordId);
|
||||||
doorLockUuid:deviceId ,
|
add(InitialOneTimePassword());
|
||||||
passwordId:passwordId
|
add(InitialTimeLimitPassword());
|
||||||
);
|
|
||||||
emit(UpdateState(smartDoorModel: deviceStatus));
|
emit(UpdateState(smartDoorModel: deviceStatus));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(errorMessage: e.toString()));
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
@ -118,11 +150,14 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
|
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
var response = await DevicesAPI.getTemporaryPasswords(deviceId, );
|
var response = await DevicesAPI.getTemporaryPasswords(
|
||||||
|
deviceId,
|
||||||
|
);
|
||||||
if (response is List) {
|
if (response is List) {
|
||||||
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
|
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
|
||||||
} else if (response is Map && response.containsKey('data')) {
|
} else if (response is Map && response.containsKey('data')) {
|
||||||
temporaryPasswords = (response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
|
temporaryPasswords =
|
||||||
|
(response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
|
||||||
}
|
}
|
||||||
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -150,6 +185,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
if (response is List) {
|
if (response is List) {
|
||||||
timeLimitPasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
|
timeLimitPasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(errorMessage: e.toString()));
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
@ -174,25 +210,80 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
|
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
isStartEndTime = event.val;
|
isStartEndTime = event.val;
|
||||||
emit(IsStartEndState(isStartEndTime:isStartEndTime));
|
emit(IsStartEndState(isStartEndTime: isStartEndTime));
|
||||||
return isStartEndTime;
|
return isStartEndTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateLock(UpdateLockEvent event, Emitter<SmartDoorState> emit) async {
|
void _updateLock(UpdateLockEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
emit(LoadingNewSate(smartDoorModel: deviceStatus));
|
emit(LoadingNewSate(smartDoorModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
final response = await DevicesAPI.controlDevice(
|
// final response = await DevicesAPI.controlDevice(
|
||||||
DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
|
// DeviceControlModel(deviceId: deviceId, code: 'normal_open_switch', value: !event.value),
|
||||||
deviceId);
|
// deviceId);
|
||||||
|
|
||||||
if (response['success'] ?? false) {
|
final response = await DevicesAPI.openDoorLock(deviceId);
|
||||||
|
|
||||||
|
if (response) {
|
||||||
deviceStatus.normalOpenSwitch = !event.value;
|
deviceStatus.normalOpenSwitch = !event.value;
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
emit(UpdateState(smartDoorModel: deviceStatus));
|
emit(UpdateState(smartDoorModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> selectTime(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
|
Future<void> selectTimeOfLinePassword(SelectTimeEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
final DateTime? picked = await showDatePicker(
|
||||||
|
context: event.context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime.now(),
|
||||||
|
lastDate: DateTime(2101),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final TimeOfDay? timePicked = await showHourPicker(
|
||||||
|
context: event.context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (timePicked != null) {
|
||||||
|
final selectedDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
timePicked.hour,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
final selectedTimestamp = DateTime(
|
||||||
|
selectedDateTime.year,
|
||||||
|
selectedDateTime.month,
|
||||||
|
selectedDateTime.day,
|
||||||
|
selectedDateTime.hour,
|
||||||
|
selectedDateTime.minute,
|
||||||
|
).millisecondsSinceEpoch ~/
|
||||||
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
|
if (event.isEffective) {
|
||||||
|
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
|
||||||
|
} else {
|
||||||
|
effectiveTime =
|
||||||
|
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
|
||||||
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Expiration Time cannot be earlier than Effective Time.');
|
||||||
|
} else {
|
||||||
|
expirationTime =
|
||||||
|
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
|
||||||
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit(TimeSelectedState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> selectTimeOnlinePassword(
|
||||||
|
SelectTimeOnlinePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
@ -230,12 +321,12 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
timePicked.minute,
|
timePicked.minute,
|
||||||
);
|
);
|
||||||
final selectedTimestamp = DateTime(
|
final selectedTimestamp = DateTime(
|
||||||
selectedDateTime.year,
|
selectedDateTime.year,
|
||||||
selectedDateTime.month,
|
selectedDateTime.month,
|
||||||
selectedDateTime.day,
|
selectedDateTime.day,
|
||||||
selectedDateTime.hour,
|
selectedDateTime.hour,
|
||||||
selectedDateTime.minute,
|
selectedDateTime.minute,
|
||||||
).millisecondsSinceEpoch ~/
|
).millisecondsSinceEpoch ~/
|
||||||
1000; // Divide by 1000 to remove milliseconds
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
if (event.isEffective) {
|
if (event.isEffective) {
|
||||||
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
|
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
@ -247,7 +338,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Expiration Time cannot be earlier than Effective Time.');
|
||||||
} else {
|
} else {
|
||||||
expirationTime =
|
expirationTime =
|
||||||
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
|
selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
|
||||||
@ -264,7 +356,7 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
try {
|
try {
|
||||||
isSavingPassword = true;
|
isSavingPassword = true;
|
||||||
emit(LoadingSaveState());
|
emit(LoadingSaveState());
|
||||||
var res = await DevicesAPI.createPassword(
|
await DevicesAPI.createPassword(
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
invalidTime: expirationTimeTimeStamp.toString(),
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
@ -283,29 +375,34 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
emit(SaveState());
|
emit(SaveState());
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
|
} finally {
|
||||||
}finally {
|
|
||||||
isSavingPassword = false;
|
isSavingPassword = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> generateAndSavePasswordTimeLimited (GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async {
|
Future<void> generateAndSavePasswordTimeLimited(
|
||||||
|
GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
if (timeLimitValidate() || isSavingPassword) return;
|
if (timeLimitValidate() || isSavingPassword) return;
|
||||||
try {
|
try {
|
||||||
isSavingPassword = true;
|
isSavingPassword = true;
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
var res = await DevicesAPI.generateMultiTimePassword(deviceId: deviceId,
|
var res = await DevicesAPI.generateMultiTimePassword(
|
||||||
|
deviceId: deviceId,
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
invalidTime: expirationTimeTimeStamp.toString(), );
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
ApiResponse pass= ApiResponse.fromJson(res);
|
);
|
||||||
passwordController.text =pass.data.offlineTempPassword;
|
ApiResponse pass = ApiResponse.fromJson(res);
|
||||||
passwordId=pass.data.offlineTempPasswordId;
|
passwordController.text = pass.data.offlineTempPassword;
|
||||||
|
passwordId = pass.data.offlineTempPasswordId;
|
||||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
|
add(InitialTimeLimitPassword());
|
||||||
|
Future.delayed(const Duration(seconds: 1), () {
|
||||||
|
Clipboard.setData(ClipboardData(text: passwordController.text));
|
||||||
|
});
|
||||||
emit(const GeneratePasswordOneTimestate(generated: true));
|
emit(const GeneratePasswordOneTimestate(generated: true));
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
emit(FailedState(errorMessage: e.toString()));
|
add(InitialPasswordsPage());
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
isSavingPassword = false;
|
isSavingPassword = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +410,6 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
Future<void> deletePassword(DeletePasswordEvent event, Emitter<SmartDoorState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
var response =
|
|
||||||
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
|
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
|
||||||
.then((value) async {
|
.then((value) async {
|
||||||
add(InitialPasswordsPage());
|
add(InitialPasswordsPage());
|
||||||
@ -324,34 +420,38 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _validateInputs() {
|
bool _validateInputs() {
|
||||||
if (passwordController.text.length < 7 ) {
|
if (passwordController.text.length < 7) {
|
||||||
CustomSnackBar.displaySnackBar('Password less than 7');
|
CustomSnackBar.displaySnackBar('Password less than 7');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passwordController.text.isEmpty) {
|
if (passwordController.text.isEmpty) {
|
||||||
CustomSnackBar.displaySnackBar('Password required');
|
CustomSnackBar.displaySnackBar('Password required');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (passwordNameController.text.isEmpty ) {
|
if (passwordNameController.text.isEmpty) {
|
||||||
CustomSnackBar.displaySnackBar('Password name required');
|
CustomSnackBar.displaySnackBar('Password name required');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
|
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
|
||||||
CustomSnackBar.displaySnackBar('Select effective time');
|
CustomSnackBar.displaySnackBar('Select effective time');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expirationTime == 'Select Time' || expirationTimeTimeStamp == null) {
|
if (expirationTime == 'Select Time' || expirationTimeTimeStamp == null) {
|
||||||
CustomSnackBar.displaySnackBar('Select expiration time');
|
CustomSnackBar.displaySnackBar('Select expiration time');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (repeat == true && (endTime == null || startTime == null || selectedDays == null)) {
|
|
||||||
|
if (repeat == true && (endTime == null || startTime == null)) {
|
||||||
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
|
CustomSnackBar.displaySnackBar('Start Time and End time and the days required ');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool timeLimitValidate() {
|
|
||||||
|
|
||||||
|
bool timeLimitValidate() {
|
||||||
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
|
if (effectiveTime == 'Select Time' || effectiveTimeTimeStamp == null) {
|
||||||
CustomSnackBar.displaySnackBar('Select effective time');
|
CustomSnackBar.displaySnackBar('Select effective time');
|
||||||
return true;
|
return true;
|
||||||
@ -375,7 +475,10 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
|
|
||||||
List<String> selectedDays = [];
|
List<String> selectedDays = [];
|
||||||
|
|
||||||
Future<void> toggleDaySelection(ToggleDaySelectionEvent event, Emitter<SmartDoorState> emit,)async {
|
Future<void> toggleDaySelection(
|
||||||
|
ToggleDaySelectionEvent event,
|
||||||
|
Emitter<SmartDoorState> emit,
|
||||||
|
) async {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
if (selectedDays.contains(event.key)) {
|
if (selectedDays.contains(event.key)) {
|
||||||
selectedDays.remove(event.key);
|
selectedDays.remove(event.key);
|
||||||
@ -390,5 +493,3 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
|
|||||||
return DateFormat('HH:mm').format(dateTime);
|
return DateFormat('HH:mm').format(dateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,15 @@ abstract class SmartDoorEvent extends Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InitialEvent extends SmartDoorEvent {}
|
class InitialEvent extends SmartDoorEvent {}
|
||||||
|
|
||||||
class InitialPasswordsPage extends SmartDoorEvent {}
|
class InitialPasswordsPage extends SmartDoorEvent {}
|
||||||
|
|
||||||
class InitialOneTimePassword extends SmartDoorEvent {}
|
class InitialOneTimePassword extends SmartDoorEvent {}
|
||||||
|
|
||||||
class InitialTimeLimitPassword extends SmartDoorEvent {}
|
class InitialTimeLimitPassword extends SmartDoorEvent {}
|
||||||
|
|
||||||
|
class DoorLockUpdated extends SmartDoorEvent {}
|
||||||
|
|
||||||
class UpdateLockEvent extends SmartDoorEvent {
|
class UpdateLockEvent extends SmartDoorEvent {
|
||||||
final bool value;
|
final bool value;
|
||||||
const UpdateLockEvent({required this.value});
|
const UpdateLockEvent({required this.value});
|
||||||
@ -26,6 +31,7 @@ class SavePasswordEvent extends SmartDoorEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [context];
|
List<Object> get props => [context];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenerateAndSavePasswordTimeLimitEvent extends SmartDoorEvent {
|
class GenerateAndSavePasswordTimeLimitEvent extends SmartDoorEvent {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
const GenerateAndSavePasswordTimeLimitEvent({required this.context});
|
const GenerateAndSavePasswordTimeLimitEvent({required this.context});
|
||||||
@ -40,20 +46,26 @@ class GenerateAndSavePasswordOneTimeEvent extends SmartDoorEvent {
|
|||||||
List<Object> get props => [context];
|
List<Object> get props => [context];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratePasswordEvent extends SmartDoorEvent {
|
class GeneratePasswordEvent extends SmartDoorEvent {}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class SelectTimeEvent extends SmartDoorEvent {
|
class SelectTimeEvent extends SmartDoorEvent {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final bool isEffective;
|
final bool isEffective;
|
||||||
const SelectTimeEvent({required this.context,required this.isEffective});
|
const SelectTimeEvent({required this.context, required this.isEffective});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [context,isEffective];
|
List<Object> get props => [context, isEffective];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectTimeOnlinePasswordEvent extends SmartDoorEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
final bool isEffective;
|
||||||
|
const SelectTimeOnlinePasswordEvent({required this.context, required this.isEffective});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [context, isEffective];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToggleRepeatEvent extends SmartDoorEvent {}
|
class ToggleRepeatEvent extends SmartDoorEvent {}
|
||||||
|
|
||||||
class SetStartEndTimeEvent extends SmartDoorEvent {
|
class SetStartEndTimeEvent extends SmartDoorEvent {
|
||||||
final bool val;
|
final bool val;
|
||||||
const SetStartEndTimeEvent({required this.val});
|
const SetStartEndTimeEvent({required this.val});
|
||||||
@ -62,7 +74,7 @@ class SetStartEndTimeEvent extends SmartDoorEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DeletePasswordEvent extends SmartDoorEvent {
|
class DeletePasswordEvent extends SmartDoorEvent {
|
||||||
final String passwordId;
|
final String passwordId;
|
||||||
|
|
||||||
const DeletePasswordEvent({required this.passwordId});
|
const DeletePasswordEvent({required this.passwordId});
|
||||||
@override
|
@override
|
||||||
@ -70,7 +82,7 @@ class DeletePasswordEvent extends SmartDoorEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ToggleDaySelectionEvent extends SmartDoorEvent {
|
class ToggleDaySelectionEvent extends SmartDoorEvent {
|
||||||
final String key;
|
final String key;
|
||||||
|
|
||||||
const ToggleDaySelectionEvent({required this.key});
|
const ToggleDaySelectionEvent({required this.key});
|
||||||
@override
|
@override
|
||||||
@ -81,12 +93,9 @@ class ChangeTimeEvent extends SmartDoorEvent {
|
|||||||
final dynamic val;
|
final dynamic val;
|
||||||
final bool isStartEndTime;
|
final bool isStartEndTime;
|
||||||
|
|
||||||
const ChangeTimeEvent({required this.val,required this.isStartEndTime});
|
const ChangeTimeEvent({required this.val, required this.isStartEndTime});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [val,isStartEndTime];
|
List<Object> get props => [val, isStartEndTime];
|
||||||
}
|
}
|
||||||
|
|
||||||
class RenamePasswordEvent extends SmartDoorEvent {
|
class RenamePasswordEvent extends SmartDoorEvent {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
||||||
@ -20,6 +21,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
secondCountDown: 0,
|
secondCountDown: 0,
|
||||||
thirdCountDown: 0);
|
thirdCountDown: 0);
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
|
// Timer? _firstSwitchTimer;
|
||||||
|
// Timer? _secondSwitchTimer;
|
||||||
|
// Timer? _thirdSwitchTimer;
|
||||||
|
|
||||||
bool threeGangGroup = false;
|
bool threeGangGroup = false;
|
||||||
List<DeviceModel> devicesList = [];
|
List<DeviceModel> devicesList = [];
|
||||||
List<GroupThreeGangModel> groupThreeGangList = [];
|
List<GroupThreeGangModel> groupThreeGangList = [];
|
||||||
@ -27,6 +32,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
|
|
||||||
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
|
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) {
|
||||||
on<InitialEvent>(_fetchThreeGangStatus);
|
on<InitialEvent>(_fetchThreeGangStatus);
|
||||||
|
on<ThreeGangUpdated>(_threeGangUpdated);
|
||||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||||
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
|
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
|
||||||
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
||||||
@ -85,6 +91,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
}
|
}
|
||||||
deviceStatus = ThreeGangModel.fromJson(statusModelList);
|
deviceStatus = ThreeGangModel.fromJson(statusModelList);
|
||||||
emit(UpdateState(threeGangModel: deviceStatus));
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(error: e.toString()));
|
emit(FailedState(error: e.toString()));
|
||||||
@ -92,6 +99,34 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) async {
|
||||||
|
if (_timer != null) {
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = ThreeGangModel.fromJson(statusList);
|
||||||
|
if (!isClosed) {
|
||||||
|
add(ThreeGangUpdated());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_threeGangUpdated(ThreeGangUpdated event, Emitter<ThreeGangState> emit) {
|
||||||
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
|
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
|
||||||
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
@ -111,16 +146,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
emit(UpdateState(threeGangModel: deviceStatus));
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
final response = await DevicesAPI.controlDevice(
|
if (_timer != null) {
|
||||||
DeviceControlModel(
|
_timer!.cancel();
|
||||||
deviceId: threeGangGroup ? event.deviceId : threeGangId,
|
|
||||||
code: 'switch_1',
|
|
||||||
value: !event.value),
|
|
||||||
threeGangGroup ? event.deviceId : threeGangId);
|
|
||||||
|
|
||||||
if (!response['success']) {
|
|
||||||
add(InitialEvent(groupScreen: threeGangGroup));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeGangGroup ? event.deviceId : threeGangId,
|
||||||
|
code: 'switch_1',
|
||||||
|
value: !event.value),
|
||||||
|
threeGangGroup ? event.deviceId : threeGangId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: threeGangGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
add(InitialEvent(groupScreen: threeGangGroup));
|
add(InitialEvent(groupScreen: threeGangGroup));
|
||||||
}
|
}
|
||||||
@ -146,16 +187,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
emit(UpdateState(threeGangModel: deviceStatus));
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
final response = await DevicesAPI.controlDevice(
|
if (_timer != null) {
|
||||||
DeviceControlModel(
|
_timer!.cancel();
|
||||||
deviceId: threeGangGroup ? event.deviceId : threeGangId,
|
|
||||||
code: 'switch_2',
|
|
||||||
value: !event.value),
|
|
||||||
threeGangGroup ? event.deviceId : threeGangId);
|
|
||||||
|
|
||||||
if (!response['success']) {
|
|
||||||
add(InitialEvent(groupScreen: threeGangGroup));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeGangGroup ? event.deviceId : threeGangId,
|
||||||
|
code: 'switch_2',
|
||||||
|
value: !event.value),
|
||||||
|
threeGangGroup ? event.deviceId : threeGangId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: threeGangGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
add(InitialEvent(groupScreen: threeGangGroup));
|
add(InitialEvent(groupScreen: threeGangGroup));
|
||||||
}
|
}
|
||||||
@ -180,16 +227,22 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
emit(UpdateState(threeGangModel: deviceStatus));
|
emit(UpdateState(threeGangModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
final response = await DevicesAPI.controlDevice(
|
if (_timer != null) {
|
||||||
DeviceControlModel(
|
_timer!.cancel();
|
||||||
deviceId: threeGangGroup ? event.deviceId : threeGangId,
|
|
||||||
code: 'switch_3',
|
|
||||||
value: !event.value),
|
|
||||||
threeGangGroup ? event.deviceId : threeGangId);
|
|
||||||
|
|
||||||
if (!response['success']) {
|
|
||||||
add(InitialEvent(groupScreen: threeGangGroup));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||||
|
final response = await DevicesAPI.controlDevice(
|
||||||
|
DeviceControlModel(
|
||||||
|
deviceId: threeGangGroup ? event.deviceId : threeGangId,
|
||||||
|
code: 'switch_3',
|
||||||
|
value: !event.value),
|
||||||
|
threeGangGroup ? event.deviceId : threeGangId);
|
||||||
|
|
||||||
|
if (!response['success']) {
|
||||||
|
add(InitialEvent(groupScreen: threeGangGroup));
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
add(InitialEvent(groupScreen: threeGangGroup));
|
add(InitialEvent(groupScreen: threeGangGroup));
|
||||||
}
|
}
|
||||||
@ -407,6 +460,9 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
|||||||
|
|
||||||
void _onClose(OnClose event, Emitter<ThreeGangState> emit) {
|
void _onClose(OnClose event, Emitter<ThreeGangState> emit) {
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
|
// _firstSwitchTimer?.cancel();
|
||||||
|
// _secondSwitchTimer?.cancel();
|
||||||
|
// _thirdSwitchTimer?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onStartTimer(int seconds) {
|
void _onStartTimer(int seconds) {
|
||||||
|
|||||||
@ -9,6 +9,8 @@ abstract class ThreeGangEvent extends Equatable {
|
|||||||
|
|
||||||
class LoadingEvent extends ThreeGangEvent {}
|
class LoadingEvent extends ThreeGangEvent {}
|
||||||
|
|
||||||
|
class ThreeGangUpdated extends ThreeGangEvent {}
|
||||||
|
|
||||||
class InitialEvent extends ThreeGangEvent {
|
class InitialEvent extends ThreeGangEvent {
|
||||||
final bool groupScreen;
|
final bool groupScreen;
|
||||||
const InitialEvent({required this.groupScreen});
|
const InitialEvent({required this.groupScreen});
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_event.dart';
|
||||||
@ -16,6 +17,7 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
on<InitialEvent>(_fetchCeilingSensorStatus);
|
on<InitialEvent>(_fetchCeilingSensorStatus);
|
||||||
on<ChangeIndicatorEvent>(_changeIndicator);
|
on<ChangeIndicatorEvent>(_changeIndicator);
|
||||||
on<ChangeValueEvent>(_changeValue);
|
on<ChangeValueEvent>(_changeValue);
|
||||||
|
on<WallSensorUpdatedEvent>(_wallSensorUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async {
|
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async {
|
||||||
@ -28,12 +30,36 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
|
|||||||
}
|
}
|
||||||
deviceStatus = WallSensorModel.fromJson(statusModelList);
|
deviceStatus = WallSensorModel.fromJson(statusModelList);
|
||||||
emit(UpdateState(wallSensorModel: deviceStatus));
|
emit(UpdateState(wallSensorModel: deviceStatus));
|
||||||
|
_listenToChanges();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(error: e.toString()));
|
emit(FailedState(error: e.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) {
|
||||||
|
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = WallSensorModel.fromJson(statusList);
|
||||||
|
add(WallSensorUpdatedEvent());
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_wallSensorUpdated(WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
|
||||||
|
emit(UpdateState(wallSensorModel: deviceStatus));
|
||||||
|
}
|
||||||
|
|
||||||
void _changeIndicator(ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async {
|
void _changeIndicator(ChangeIndicatorEvent event, Emitter<WallSensorState> emit) async {
|
||||||
emit(LoadingNewSate(wallSensorModel: deviceStatus));
|
emit(LoadingNewSate(wallSensorModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -11,6 +11,8 @@ class LoadingEvent extends WallSensorEvent {}
|
|||||||
|
|
||||||
class InitialEvent extends WallSensorEvent {}
|
class InitialEvent extends WallSensorEvent {}
|
||||||
|
|
||||||
|
class WallSensorUpdatedEvent extends WallSensorEvent {}
|
||||||
|
|
||||||
class ChangeIndicatorEvent extends WallSensorEvent {
|
class ChangeIndicatorEvent extends WallSensorEvent {
|
||||||
final bool value;
|
final bool value;
|
||||||
const ChangeIndicatorEvent({required this.value});
|
const ChangeIndicatorEvent({required this.value});
|
||||||
|
|||||||
@ -4,28 +4,47 @@ class CeilingSensorModel {
|
|||||||
String presenceState;
|
String presenceState;
|
||||||
int sensitivity;
|
int sensitivity;
|
||||||
String checkingResult;
|
String checkingResult;
|
||||||
|
int presenceRange;
|
||||||
|
int sportsPara;
|
||||||
|
String bodyMovement;
|
||||||
|
|
||||||
CeilingSensorModel({
|
CeilingSensorModel(
|
||||||
required this.presenceState,
|
{required this.presenceState,
|
||||||
required this.sensitivity,
|
required this.sensitivity,
|
||||||
required this.checkingResult,
|
required this.checkingResult,
|
||||||
});
|
required this.presenceRange,
|
||||||
|
required this.sportsPara,
|
||||||
|
required this.bodyMovement});
|
||||||
|
|
||||||
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
|
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
|
||||||
late String _presenceState;
|
late String _presenceState;
|
||||||
late int _sensitivity;
|
late int _sensitivity;
|
||||||
late String _checkingResult;
|
late String _checkingResult;
|
||||||
|
int _presenceRange = 1;
|
||||||
|
int _sportsPara = 1;
|
||||||
|
String _bodyMovement = 'none';
|
||||||
|
|
||||||
for (int i = 0; i < jsonList.length; i++) {
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
if (jsonList[i].code == 'presence_state') {
|
if (jsonList[i].code == 'presence_state') {
|
||||||
_presenceState = jsonList[i].value ?? 'none';
|
_presenceState = jsonList[i].value ?? 'none';
|
||||||
} else if (jsonList[i].code == 'sensitivity') {
|
} else if (jsonList[i].code == 'sensitivity') {
|
||||||
_sensitivity = jsonList[i].value ?? false;
|
_sensitivity = jsonList[i].value ?? 1;
|
||||||
} else if (jsonList[i].code == 'checking_result') {
|
} else if (jsonList[i].code == 'checking_result') {
|
||||||
_checkingResult = jsonList[i].value ?? false;
|
_checkingResult = jsonList[i].value ?? '';
|
||||||
|
} else if (jsonList[i].code == 'presence_range') {
|
||||||
|
_presenceRange = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'sports_para') {
|
||||||
|
_sportsPara = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'body_movement') {
|
||||||
|
_bodyMovement = jsonList[i].value ?? '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CeilingSensorModel(
|
return CeilingSensorModel(
|
||||||
presenceState: _presenceState, sensitivity: _sensitivity, checkingResult: _checkingResult);
|
presenceState: _presenceState,
|
||||||
|
sensitivity: _sensitivity,
|
||||||
|
checkingResult: _checkingResult,
|
||||||
|
presenceRange: _presenceRange,
|
||||||
|
sportsPara: _sportsPara,
|
||||||
|
bodyMovement: _bodyMovement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,9 +35,9 @@ class WallSensorModel {
|
|||||||
if (jsonList[i].code == 'presence_state') {
|
if (jsonList[i].code == 'presence_state') {
|
||||||
_presenceState = jsonList[i].value ?? 'none';
|
_presenceState = jsonList[i].value ?? 'none';
|
||||||
} else if (jsonList[i].code == 'far_detection') {
|
} else if (jsonList[i].code == 'far_detection') {
|
||||||
_farDetection = jsonList[i].value ?? false;
|
_farDetection = jsonList[i].value ?? 0;
|
||||||
} else if (jsonList[i].code == 'presence_time') {
|
} else if (jsonList[i].code == 'presence_time') {
|
||||||
_presenceTime = jsonList[i].value ?? false;
|
_presenceTime = jsonList[i].value ?? 0;
|
||||||
} else if (jsonList[i].code == 'motion_sensitivity_value') {
|
} else if (jsonList[i].code == 'motion_sensitivity_value') {
|
||||||
_motionSensitivity = jsonList[i].value ?? 0;
|
_motionSensitivity = jsonList[i].value ?? 0;
|
||||||
} else if (jsonList[i].code == 'motionless_sensitivity') {
|
} else if (jsonList[i].code == 'motionless_sensitivity') {
|
||||||
@ -47,7 +47,7 @@ class WallSensorModel {
|
|||||||
} else if (jsonList[i].code == 'illuminance_value') {
|
} else if (jsonList[i].code == 'illuminance_value') {
|
||||||
_illuminance = jsonList[i].value ?? 0;
|
_illuminance = jsonList[i].value ?? 0;
|
||||||
} else if (jsonList[i].code == 'indicator') {
|
} else if (jsonList[i].code == 'indicator') {
|
||||||
_indicator = jsonList[i].value ?? 0;
|
_indicator = jsonList[i].value ?? false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WallSensorModel(
|
return WallSensorModel(
|
||||||
|
|||||||
@ -34,8 +34,13 @@ class CeilingSensorInterface extends StatelessWidget {
|
|||||||
create: (context) =>
|
create: (context) =>
|
||||||
CeilingSensorBloc(deviceId: ceilingSensor.uuid ?? '')..add(InitialEvent()),
|
CeilingSensorBloc(deviceId: ceilingSensor.uuid ?? '')..add(InitialEvent()),
|
||||||
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(builder: (context, state) {
|
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(builder: (context, state) {
|
||||||
CeilingSensorModel ceilingSensorModel =
|
CeilingSensorModel ceilingSensorModel = CeilingSensorModel(
|
||||||
CeilingSensorModel(presenceState: 'none', sensitivity: 1, checkingResult: '');
|
presenceState: 'none',
|
||||||
|
sensitivity: 1,
|
||||||
|
checkingResult: '',
|
||||||
|
presenceRange: 1,
|
||||||
|
sportsPara: 1,
|
||||||
|
bodyMovement: 'none');
|
||||||
if (state is UpdateState) {
|
if (state is UpdateState) {
|
||||||
ceilingSensorModel = state.ceilingSensorModel;
|
ceilingSensorModel = state.ceilingSensorModel;
|
||||||
} else if (state is LoadingNewSate) {
|
} else if (state is LoadingNewSate) {
|
||||||
@ -178,7 +183,8 @@ class CeilingSensorInterface extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const BodySmall(text: 'Sports Para'),
|
const BodySmall(text: 'Sports Para'),
|
||||||
BodyLarge(
|
BodyLarge(
|
||||||
text: '0',
|
text: ceilingSensorModel.sportsPara
|
||||||
|
.toString(),
|
||||||
style: context.bodyLarge.copyWith(
|
style: context.bodyLarge.copyWith(
|
||||||
fontWeight: FontsManager.bold,
|
fontWeight: FontsManager.bold,
|
||||||
),
|
),
|
||||||
@ -204,7 +210,8 @@ class CeilingSensorInterface extends StatelessWidget {
|
|||||||
textOverflow: TextOverflow.ellipsis,
|
textOverflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
BodyLarge(
|
BodyLarge(
|
||||||
text: '0.0M',
|
text:
|
||||||
|
'${ceilingSensorModel.presenceRange}M',
|
||||||
textOverflow: TextOverflow.ellipsis,
|
textOverflow: TextOverflow.ellipsis,
|
||||||
style: context.bodyLarge.copyWith(
|
style: context.bodyLarge.copyWith(
|
||||||
fontWeight: FontsManager.bold,
|
fontWeight: FontsManager.bold,
|
||||||
@ -231,7 +238,7 @@ class CeilingSensorInterface extends StatelessWidget {
|
|||||||
textOverflow: TextOverflow.ellipsis,
|
textOverflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
BodyLarge(
|
BodyLarge(
|
||||||
text: 'none',
|
text: ceilingSensorModel.bodyMovement,
|
||||||
textOverflow: TextOverflow.ellipsis,
|
textOverflow: TextOverflow.ellipsis,
|
||||||
style: context.bodyLarge.copyWith(
|
style: context.bodyLarge.copyWith(
|
||||||
fontWeight: FontsManager.bold,
|
fontWeight: FontsManager.bold,
|
||||||
|
|||||||
@ -1,163 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
|
||||||
|
|
||||||
class BlindsView extends StatelessWidget {
|
|
||||||
const BlindsView({
|
|
||||||
super.key,
|
|
||||||
this.blind,
|
|
||||||
});
|
|
||||||
final DeviceModel? blind;
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return BlocProvider(
|
|
||||||
create: (context) => DevicesCubit.getInstance(),
|
|
||||||
child: BlocBuilder<DevicesCubit, DevicesState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return DefaultScaffold(
|
|
||||||
title: blind?.name ?? 'Blinds',
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
Stack(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
height: 340,
|
|
||||||
width: 365,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage(
|
|
||||||
Assets.assetsImagesWindow,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 15, bottom: 10),
|
|
||||||
child: AnimatedContainer(
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
curve: Curves.linear,
|
|
||||||
height: DevicesCubit.get(context).blindWindowHight,
|
|
||||||
width: 270,
|
|
||||||
child: Stack(
|
|
||||||
children: List.generate(
|
|
||||||
25,
|
|
||||||
(index) {
|
|
||||||
double spacing = DevicesCubit.get(context)
|
|
||||||
.blindWindowHight /
|
|
||||||
24;
|
|
||||||
double topPosition = index * spacing;
|
|
||||||
return AnimatedPositioned(
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
curve: Curves.linear,
|
|
||||||
top: topPosition,
|
|
||||||
child: SizedBox(
|
|
||||||
height: 10,
|
|
||||||
width: 270,
|
|
||||||
child: Image.asset(
|
|
||||||
Assets.assetsImagesHorizintalBlade,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 80),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
DecoratedBox(
|
|
||||||
decoration:
|
|
||||||
BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.grey.withOpacity(0.5),
|
|
||||||
spreadRadius: 1,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: const Offset(3, 3),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
child: InkWell(
|
|
||||||
overlayColor:
|
|
||||||
MaterialStateProperty.all(Colors.transparent),
|
|
||||||
onTap: () {
|
|
||||||
// DevicesCubit.get(context).setHight(false);
|
|
||||||
DevicesCubit.get(context).openCurtain(
|
|
||||||
blind?.productType! ?? DeviceType.Blind);
|
|
||||||
},
|
|
||||||
child: Image.asset(
|
|
||||||
Assets.assetsImagesUp,
|
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
DecoratedBox(
|
|
||||||
decoration:
|
|
||||||
BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.grey.withOpacity(0.5),
|
|
||||||
spreadRadius: 1,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: const Offset(3, 3),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
child: InkWell(
|
|
||||||
overlayColor:
|
|
||||||
MaterialStateProperty.all(Colors.transparent),
|
|
||||||
onTap: () {
|
|
||||||
DevicesCubit.get(context).pauseCurtain();
|
|
||||||
},
|
|
||||||
child: Image.asset(
|
|
||||||
Assets.assetsImagesPause,
|
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
DecoratedBox(
|
|
||||||
decoration:
|
|
||||||
BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.grey.withOpacity(0.5),
|
|
||||||
spreadRadius: 1,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: const Offset(3, 3),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
child: InkWell(
|
|
||||||
overlayColor:
|
|
||||||
MaterialStateProperty.all(Colors.transparent),
|
|
||||||
onTap: () {
|
|
||||||
DevicesCubit.get(context).closeCurtain(
|
|
||||||
blind?.productType! ?? DeviceType.Blind);
|
|
||||||
},
|
|
||||||
child: Image.asset(
|
|
||||||
Assets.assetsImagesDown,
|
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
// import 'package:flutter/material.dart';
|
|
||||||
// import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
|
||||||
// import 'package:syncrow_app/generated2/assets.dart';
|
|
||||||
|
|
||||||
// class BlindsBottons extends StatelessWidget {
|
|
||||||
// const BlindsBottons({
|
|
||||||
// super.key,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// @override
|
|
||||||
// Widget build(BuildContext context) {
|
|
||||||
// return Row(
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
// children: [
|
|
||||||
// DecoratedBox(
|
|
||||||
// decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
// BoxShadow(
|
|
||||||
// color: Colors.grey.withOpacity(0.5),
|
|
||||||
// spreadRadius: 1,
|
|
||||||
// blurRadius: 5,
|
|
||||||
// offset: const Offset(3, 3),
|
|
||||||
// ),
|
|
||||||
// ]),
|
|
||||||
// child: InkWell(
|
|
||||||
// overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
// onTap: () {
|
|
||||||
// // DevicesCubit.get(context).setHight(false);
|
|
||||||
// DevicesCubit.get(context).closeCurtain();
|
|
||||||
// },
|
|
||||||
// child: Image.asset(
|
|
||||||
// Assets.assetsImagesUp,
|
|
||||||
// width: 60,
|
|
||||||
// height: 60,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// DecoratedBox(
|
|
||||||
// decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
// BoxShadow(
|
|
||||||
// color: Colors.grey.withOpacity(0.5),
|
|
||||||
// spreadRadius: 1,
|
|
||||||
// blurRadius: 5,
|
|
||||||
// offset: const Offset(3, 3),
|
|
||||||
// ),
|
|
||||||
// ]),
|
|
||||||
// child: InkWell(
|
|
||||||
// overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
// onTap: () {
|
|
||||||
// // DevicesCubit.get(context).setHight(false);
|
|
||||||
// },
|
|
||||||
// child: Image.asset(
|
|
||||||
// Assets.assetsImagesPause,
|
|
||||||
// width: 60,
|
|
||||||
// height: 60,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// DecoratedBox(
|
|
||||||
// decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
// BoxShadow(
|
|
||||||
// color: Colors.grey.withOpacity(0.5),
|
|
||||||
// spreadRadius: 1,
|
|
||||||
// blurRadius: 5,
|
|
||||||
// offset: const Offset(3, 3),
|
|
||||||
// ),
|
|
||||||
// ]),
|
|
||||||
// child: InkWell(
|
|
||||||
// overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
// onTap: () {
|
|
||||||
// // DevicesCubit.get(context).setHight(true);
|
|
||||||
// DevicesCubit.get(context).openCurtain();
|
|
||||||
// },
|
|
||||||
// child: Image.asset(
|
|
||||||
// Assets.assetsImagesDown,
|
|
||||||
// width: 60,
|
|
||||||
// height: 60,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@ -1,114 +1,73 @@
|
|||||||
part of "curtain_view.dart";
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
|
||||||
class CurtainButtons extends StatelessWidget {
|
class CurtainButtons extends StatelessWidget {
|
||||||
const CurtainButtons({super.key, required this.curtain});
|
const CurtainButtons({super.key, required this.curtain});
|
||||||
final DeviceModel curtain;
|
final DeviceModel curtain;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
Stack(
|
_buildButton(
|
||||||
alignment: Alignment.center,
|
onTap: () => context.read<CurtainBloc>().add(OpenCurtain(curtain.productType!)),
|
||||||
children: [
|
iconPath: Assets.assetsIconsCurtainsIconOpenCurtain,
|
||||||
DecoratedBox(
|
|
||||||
decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.grey.withOpacity(0.5),
|
|
||||||
spreadRadius: 1,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: const Offset(3, 3),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
child: InkWell(
|
|
||||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
onTap: () {
|
|
||||||
DevicesCubit.get(context).openCurtain(curtain.productType!);
|
|
||||||
},
|
|
||||||
child: const SizedBox.square(
|
|
||||||
dimension: 60,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 5, bottom: 5),
|
|
||||||
child: InkWell(
|
|
||||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
onTap: () {
|
|
||||||
DevicesCubit.get(context).openCurtain(curtain.productType!);
|
|
||||||
},
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.assetsIconsCurtainsIconOpenCurtain,
|
|
||||||
width: 110,
|
|
||||||
height: 110,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
_buildButton(
|
||||||
|
onTap: () => context.read<CurtainBloc>().add(PauseCurtain()),
|
||||||
|
iconPath: Assets.assetsImagesPause,
|
||||||
|
isSvg: false,
|
||||||
|
),
|
||||||
|
_buildButton(
|
||||||
|
onTap: () => context.read<CurtainBloc>().add(CloseCurtain(curtain.productType!)),
|
||||||
|
iconPath: Assets.assetsIconsCurtainsIconCloseCurtain,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildButton({
|
||||||
|
required VoidCallback onTap,
|
||||||
|
required String iconPath,
|
||||||
|
bool isSvg = true,
|
||||||
|
}) {
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
DecoratedBox(
|
DecoratedBox(
|
||||||
decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
decoration: BoxDecoration(
|
||||||
BoxShadow(
|
shape: BoxShape.circle,
|
||||||
color: Colors.grey.withOpacity(0.5),
|
boxShadow: [
|
||||||
spreadRadius: 1,
|
BoxShadow(
|
||||||
blurRadius: 5,
|
color: Colors.grey.withOpacity(0.5),
|
||||||
offset: const Offset(3, 3),
|
spreadRadius: 1,
|
||||||
),
|
blurRadius: 5,
|
||||||
]),
|
offset: const Offset(3, 3),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||||||
onTap: () {
|
onTap: onTap,
|
||||||
DevicesCubit.get(context).pauseCurtain();
|
child: const SizedBox.square(dimension: 60),
|
||||||
},
|
|
||||||
child: Image.asset(
|
|
||||||
Assets.assetsImagesPause,
|
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Stack(
|
Padding(
|
||||||
alignment: Alignment.center,
|
padding: const EdgeInsets.only(right: 5, bottom: 5),
|
||||||
children: [
|
child: InkWell(
|
||||||
DecoratedBox(
|
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||||||
decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
|
onTap: onTap,
|
||||||
BoxShadow(
|
child: isSvg
|
||||||
color: Colors.grey.withOpacity(0.5),
|
? SvgPicture.asset(iconPath, width: 110, height: 110)
|
||||||
spreadRadius: 1,
|
: Image.asset(iconPath, width: 60, height: 60),
|
||||||
blurRadius: 5,
|
),
|
||||||
offset: const Offset(3, 3),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
child: const SizedBox.square(
|
|
||||||
dimension: 60,
|
|
||||||
),
|
|
||||||
// InkWell(
|
|
||||||
// overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
// onTap: () {
|
|
||||||
// DevicesCubit.get(context).closeCurtain(curtain.productType!);
|
|
||||||
// },
|
|
||||||
// child: SvgPicture.asset(
|
|
||||||
// Assets.assetsIconsCurtainsIconCloseCurtain,
|
|
||||||
// width: 60,
|
|
||||||
// height: 60,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 5, bottom: 5),
|
|
||||||
child: InkWell(
|
|
||||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
|
||||||
onTap: () {
|
|
||||||
DevicesCubit.get(context).closeCurtain(curtain.productType!);
|
|
||||||
},
|
|
||||||
child: SvgPicture.asset(
|
|
||||||
Assets.assetsIconsCurtainsIconCloseCurtain,
|
|
||||||
width: 110,
|
|
||||||
height: 110,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,86 +1,99 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_buttons.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
|
||||||
part "curtain_buttons.dart";
|
|
||||||
|
|
||||||
class CurtainView extends StatelessWidget {
|
class CurtainView extends StatelessWidget {
|
||||||
const CurtainView({super.key, required this.curtain});
|
const CurtainView({super.key, required this.curtain});
|
||||||
final DeviceModel curtain;
|
final DeviceModel curtain;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => DevicesCubit.getInstance(),
|
create: (context) => CurtainBloc(curtain.uuid!)..add(InitCurtain()),
|
||||||
child: BlocBuilder<DevicesCubit, DevicesState>(
|
child: BlocBuilder<CurtainBloc, CurtainState>(
|
||||||
builder: (context, state) => DefaultScaffold(
|
builder: (context, state) {
|
||||||
title: curtain.name,
|
double curtainWidth = 270;
|
||||||
child: Column(
|
double blindHeight = 310;
|
||||||
children: [
|
if (state is CurtainsOpening) {
|
||||||
Stack(
|
curtainWidth = state.curtainWidth;
|
||||||
alignment: Alignment.centerLeft,
|
blindHeight = state.blindHeight;
|
||||||
children: [
|
} else if (state is CurtainsClosing) {
|
||||||
Container(
|
curtainWidth = state.curtainWidth;
|
||||||
height: 340,
|
blindHeight = state.blindHeight;
|
||||||
width: 365,
|
} else if (state is CurtainsPaused) {
|
||||||
decoration: const BoxDecoration(
|
curtainWidth = state.curtainWidth;
|
||||||
image: DecorationImage(
|
blindHeight = state.blindHeight;
|
||||||
image: AssetImage(
|
}
|
||||||
Assets.assetsImagesWindow,
|
return DefaultScaffold(
|
||||||
|
title: curtain.name,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 340,
|
||||||
|
width: 365,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesWindow,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.all(40),
|
||||||
padding: const EdgeInsets.all(40),
|
child: AnimatedContainer(
|
||||||
child: AnimatedContainer(
|
duration: const Duration(milliseconds: 200),
|
||||||
duration: const Duration(milliseconds: 200),
|
curve: Curves.linear,
|
||||||
curve: Curves.linear,
|
height: 310,
|
||||||
height: 310,
|
width: curtainWidth,
|
||||||
width: DevicesCubit.getInstance().curtainWidth,
|
child: Stack(
|
||||||
child: Stack(
|
children: List.generate(
|
||||||
children: List.generate(
|
10, (index) {
|
||||||
10,
|
double spacing = curtainWidth / 9;
|
||||||
(index) {
|
double leftMostPosition = index * spacing;
|
||||||
double spacing =
|
return AnimatedPositioned(
|
||||||
DevicesCubit.getInstance().curtainWidth / 9;
|
duration: const Duration(milliseconds: 200),
|
||||||
double leftMostPosition = index * spacing;
|
curve: Curves.linear,
|
||||||
return AnimatedPositioned(
|
left: leftMostPosition,
|
||||||
duration: const Duration(milliseconds: 200),
|
child: SizedBox(
|
||||||
curve: Curves.linear,
|
height: 320,
|
||||||
left: leftMostPosition,
|
width: 32,
|
||||||
child: SizedBox(
|
child: SvgPicture.asset(
|
||||||
height: 320,
|
Assets.assetsIconsCurtainsIconVerticalBlade,
|
||||||
width: 32,
|
fit: BoxFit.fill,
|
||||||
child: SvgPicture.asset(
|
),
|
||||||
Assets.assetsIconsCurtainsIconVerticalBlade,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Positioned(
|
||||||
Positioned(
|
|
||||||
top: 27,
|
top: 27,
|
||||||
left: 43,
|
left: 43,
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.assetsIconsCurtainsIconCurtainHolder)),
|
Assets.assetsIconsCurtainsIconCurtainHolder,
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 80),
|
],
|
||||||
CurtainButtons(
|
),
|
||||||
curtain: curtain,
|
const SizedBox(height: 80),
|
||||||
),
|
CurtainButtons(curtain: curtain),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,6 +66,7 @@ class DevicesViewBody extends StatelessWidget {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 10,
|
height: 10,
|
||||||
),
|
),
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: PageView(
|
child: PageView(
|
||||||
controller: HomeCubit.getInstance().devicesPageController,
|
controller: HomeCubit.getInstance().devicesPageController,
|
||||||
|
|||||||
92
lib/features/devices/view/widgets/hour_picker_dialog.dart
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class HourPickerDialog extends StatefulWidget {
|
||||||
|
final TimeOfDay initialTime;
|
||||||
|
HourPickerDialog({required this.initialTime});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_HourPickerDialogState createState() => _HourPickerDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HourPickerDialogState extends State<HourPickerDialog> {
|
||||||
|
late int _selectedHour;
|
||||||
|
bool _isPm = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedHour = widget.initialTime.hour > 12 ? widget.initialTime.hour - 12 : widget.initialTime.hour;
|
||||||
|
_isPm = widget.initialTime.period == DayPeriod.pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('Select Hour'),
|
||||||
|
content: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
DropdownButton<int>(
|
||||||
|
value: _selectedHour,
|
||||||
|
items: List.generate(12, (index) {
|
||||||
|
int displayHour = index + 1;
|
||||||
|
return DropdownMenuItem(
|
||||||
|
value: displayHour,
|
||||||
|
child: Text(displayHour.toString()),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_selectedHour = value!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(width: 16.0),
|
||||||
|
DropdownButton<bool>(
|
||||||
|
value: _isPm,
|
||||||
|
items: [
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: false,
|
||||||
|
child: Text('AM'),
|
||||||
|
),
|
||||||
|
DropdownMenuItem(
|
||||||
|
value: true,
|
||||||
|
child: Text('PM'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_isPm = value!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(null),
|
||||||
|
child: Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
int hour = _isPm ? _selectedHour + 12 : _selectedHour;
|
||||||
|
Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0));
|
||||||
|
},
|
||||||
|
child: Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TimeOfDay?> showHourPicker({
|
||||||
|
required BuildContext context,
|
||||||
|
required TimeOfDay initialTime,
|
||||||
|
}) {
|
||||||
|
return showDialog<TimeOfDay>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => HourPickerDialog(initialTime: initialTime),
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -60,7 +60,7 @@ class NameTimeWidget extends StatelessWidget {
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeEvent(context: context, isEffective: true));
|
BlocProvider.of<SmartDoorBloc>(context).add(SelectTimeOnlinePasswordEvent(context: context, isEffective: true));
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
BlocProvider.of<SmartDoorBloc>(context).effectiveTime,
|
||||||
@ -92,7 +92,7 @@ class NameTimeWidget extends StatelessWidget {
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(
|
BlocProvider.of<SmartDoorBloc>(context).add(
|
||||||
SelectTimeEvent(
|
SelectTimeOnlinePasswordEvent(
|
||||||
context: context, isEffective: false));
|
context: context, isEffective: false));
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
|||||||
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
@ -28,11 +29,8 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
|||||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||||
if (state is FailedState) {
|
if (state is FailedState) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
CustomSnackBar.displaySnackBar(
|
||||||
SnackBar(
|
state.errorMessage
|
||||||
content: Text(state.errorMessage),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (state is IsRepeatState){
|
if (state is IsRepeatState){
|
||||||
@ -104,6 +102,7 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: BodyLarge(
|
child: BodyLarge(
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
@ -114,8 +113,9 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
|||||||
wordSpacing: 2),
|
wordSpacing: 2),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
text: smartDoorBloc.passwordController.text,
|
text: smartDoorBloc.passwordController.text,
|
||||||
fontSize: 25,
|
fontSize: 23,
|
||||||
),),
|
),),
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await Clipboard.setData(ClipboardData(
|
await Clipboard.setData(ClipboardData(
|
||||||
@ -166,7 +166,6 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
|||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -195,9 +194,6 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if(generated==false){
|
if(generated==false){
|
||||||
smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
||||||
await Clipboard.setData(
|
|
||||||
ClipboardData(text: smartDoorBloc.passwordController.text)
|
|
||||||
);
|
|
||||||
}else{
|
}else{
|
||||||
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||||
smartDoorBloc.add(RenamePasswordEvent());
|
smartDoorBloc.add(RenamePasswordEvent());
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
||||||
@ -102,6 +103,11 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
|||||||
// navigateToInterface(CeilingSensorInterface(ceilingSensor: device), context);
|
// navigateToInterface(CeilingSensorInterface(ceilingSensor: device), context);
|
||||||
break;
|
break;
|
||||||
case DeviceType.Curtain:
|
case DeviceType.Curtain:
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
PageRouteBuilder(
|
||||||
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
|
CurtainView(curtain: device,)));
|
||||||
break;
|
break;
|
||||||
case DeviceType.Blind:
|
case DeviceType.Blind:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,14 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
// import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart';
|
|
||||||
// import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
||||||
// import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
||||||
// import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
|
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
@ -35,40 +31,36 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_animationController = AnimationController(
|
_animationController = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
duration: const Duration(seconds: 2),
|
value: context.read<SmartDoorBloc>().unlockRequest > 0 ? 1 : 0,
|
||||||
|
duration: Duration(seconds: context.read<SmartDoorBloc>().unlockRequest),
|
||||||
);
|
);
|
||||||
_animation = Tween<double>(begin: 0, end: 1.0).animate(_animationController)
|
if (context.read<SmartDoorBloc>().unlockRequest > 0) {
|
||||||
|
_animationController.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
_animation = Tween<double>(begin: 0, end: 1).animate(_animationController)
|
||||||
..addListener(() {
|
..addListener(() {
|
||||||
if (_animation.status == AnimationStatus.completed) {
|
|
||||||
// if (widget.doorLock.status
|
|
||||||
// .firstWhere((element) => element.code == 'normal_open_switch')
|
|
||||||
// .value !=
|
|
||||||
// true) {
|
|
||||||
// DevicesCubit.getInstance().deviceControl(
|
|
||||||
// DeviceControlModel(
|
|
||||||
// deviceId: widget.doorLock.uuid, code: 'normal_open_switch', value: true),
|
|
||||||
// widget.doorLock.uuid ?? "");
|
|
||||||
// }
|
|
||||||
BlocProvider.of<SmartDoorBloc>(context)
|
|
||||||
.add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
|
|
||||||
_animationController.reverse();
|
|
||||||
} else if (_animation.status == AnimationStatus.dismissed) {
|
|
||||||
// if (widget.doorLock.status
|
|
||||||
// .firstWhere((element) => element.code == 'normal_open_switch')
|
|
||||||
// .value !=
|
|
||||||
// false) {
|
|
||||||
// DevicesCubit.getInstance().deviceControl(
|
|
||||||
// DeviceControlModel(
|
|
||||||
// deviceId: widget.doorLock.uuid, code: 'normal_open_switch', value: false),
|
|
||||||
// widget.doorLock.uuid ?? "");
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(DoorLockButton oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
|
if (_animationController.status == AnimationStatus.dismissed) {
|
||||||
|
if (context.read<SmartDoorBloc>().unlockRequest > 0) {
|
||||||
|
_animationController.value = 1;
|
||||||
|
_animationController.duration =
|
||||||
|
Duration(seconds: context.read<SmartDoorBloc>().unlockRequest);
|
||||||
|
_animationController.reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_animationController.dispose();
|
_animationController.dispose();
|
||||||
@ -88,14 +80,18 @@ class _DoorLockButtonState extends State<DoorLockButton> with SingleTickerProvid
|
|||||||
WidgetStateProperty.all(ColorsManager.primaryColorWithOpacity.withOpacity(0.1)),
|
WidgetStateProperty.all(ColorsManager.primaryColorWithOpacity.withOpacity(0.1)),
|
||||||
borderRadius: BorderRadius.circular(999),
|
borderRadius: BorderRadius.circular(999),
|
||||||
onTapDown: (details) {
|
onTapDown: (details) {
|
||||||
if (_animationController.status == AnimationStatus.dismissed) {
|
// if (_animationController.status == AnimationStatus.dismissed) {
|
||||||
_animationController.forward();
|
// _animationController.forward();
|
||||||
} else if (_animationController.status == AnimationStatus.completed) {
|
// } else if (_animationController.status == AnimationStatus.completed) {
|
||||||
_animationController.reverse();
|
// _animationController.reverse();
|
||||||
} else if (_animationController.status == AnimationStatus.forward) {
|
// } else if (_animationController.status == AnimationStatus.forward) {
|
||||||
_animationController.reverse();
|
// _animationController.reverse();
|
||||||
} else if (_animationController.status == AnimationStatus.reverse) {
|
// } else if (_animationController.status == AnimationStatus.reverse) {
|
||||||
_animationController.forward();
|
// _animationController.forward();
|
||||||
|
// }
|
||||||
|
if (context.read<SmartDoorBloc>().unlockRequest > 0) {
|
||||||
|
BlocProvider.of<SmartDoorBloc>(context)
|
||||||
|
.add(UpdateLockEvent(value: smartDoorModel.normalOpenSwitch));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onTapUp: (details) {
|
onTapUp: (details) {
|
||||||
|
|||||||
@ -7,27 +7,22 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_sta
|
|||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/popup_menu_widget.dart';
|
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_button.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_button.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_grid.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_grid.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_status_bar.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
|
||||||
|
|
||||||
class DoorInterface extends StatelessWidget {
|
class DoorInterface extends StatelessWidget {
|
||||||
|
const DoorInterface({super.key, required this.doorLock});
|
||||||
DoorInterface({super.key, required this.doorLock});
|
|
||||||
|
|
||||||
final DeviceModel doorLock;
|
final DeviceModel doorLock;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => SmartDoorBloc(deviceId: doorLock.uuid ?? '')..add(InitialEvent()),
|
create: (context) => SmartDoorBloc(deviceId: doorLock.uuid ?? '')..add(InitialEvent()),
|
||||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||||
listener: (context, state) {
|
|
||||||
if (state is FailedState) {
|
if (state is FailedState) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
@ -63,32 +58,32 @@ class DoorInterface extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AnnotatedRegion(
|
return AnnotatedRegion(
|
||||||
value: SystemUiOverlayStyle(
|
value: SystemUiOverlayStyle(
|
||||||
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
statusBarIconBrightness: Brightness.light,
|
statusBarIconBrightness: Brightness.light,
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: ColorsManager.backgroundColor,
|
|
||||||
extendBodyBehindAppBar: true,
|
|
||||||
extendBody: true,
|
|
||||||
appBar: DeviceAppbar(
|
|
||||||
deviceName: doorLock.name!,
|
|
||||||
deviceUuid: doorLock.uuid!,
|
|
||||||
),
|
),
|
||||||
body: Container(
|
child: Scaffold(
|
||||||
width: MediaQuery.sizeOf(context).width,
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
height: MediaQuery.sizeOf(context).height,
|
extendBodyBehindAppBar: true,
|
||||||
decoration: const BoxDecoration(
|
extendBody: true,
|
||||||
image: DecorationImage(
|
appBar: DeviceAppbar(
|
||||||
image: AssetImage(
|
deviceName: doorLock.name!,
|
||||||
Assets.assetsImagesBackground,
|
deviceUuid: doorLock.uuid!,
|
||||||
),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
opacity: 0.4,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: SafeArea(
|
body: Container(
|
||||||
child: Padding(
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(
|
||||||
|
Assets.assetsImagesBackground,
|
||||||
|
),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: Constants.appBarHeight,
|
top: Constants.appBarHeight,
|
||||||
left: Constants.defaultPadding,
|
left: Constants.defaultPadding,
|
||||||
@ -98,38 +93,35 @@ class DoorInterface extends StatelessWidget {
|
|||||||
? const Center(
|
? const Center(
|
||||||
child: RefreshProgressIndicator(),
|
child: RefreshProgressIndicator(),
|
||||||
)
|
)
|
||||||
:
|
: RefreshIndicator(
|
||||||
|
onRefresh: () async {
|
||||||
RefreshIndicator(
|
BlocProvider.of<SmartDoorBloc>(context).add(InitialEvent());
|
||||||
onRefresh: () async {
|
},
|
||||||
BlocProvider.of<SmartDoorBloc>(context).add(InitialEvent());
|
child: ListView(
|
||||||
},
|
children: [
|
||||||
child:
|
DoorLockStatusBar(
|
||||||
ListView(
|
smartDoorModel: smartDoorModel,
|
||||||
children: [
|
),
|
||||||
DoorLockStatusBar(
|
Column(
|
||||||
smartDoorModel: smartDoorModel,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
),
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
Column(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
DoorLockButton(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
doorLock: doorLock,
|
||||||
children: [
|
smartDoorModel: smartDoorModel,
|
||||||
DoorLockButton(
|
),
|
||||||
doorLock: doorLock,
|
DoorLockGrid(
|
||||||
smartDoorModel: smartDoorModel,
|
uuid: doorLock.uuid!,
|
||||||
),
|
),
|
||||||
DoorLockGrid( uuid: doorLock.uuid!, ),
|
],
|
||||||
|
)
|
||||||
],
|
],
|
||||||
)
|
)),
|
||||||
],
|
),
|
||||||
)),
|
),
|
||||||
),
|
),
|
||||||
),
|
));
|
||||||
),
|
|
||||||
));
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
|||||||
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
@ -27,11 +28,8 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
|||||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is FailedState) {
|
if (state is FailedState) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
CustomSnackBar.displaySnackBar(
|
||||||
SnackBar(
|
state.errorMessage
|
||||||
content: Text(state.errorMessage),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (state is IsRepeatState) {
|
if (state is IsRepeatState) {
|
||||||
@ -240,8 +238,7 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const BodyMedium(
|
const BodyMedium(
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
text:
|
text: 'Use the time-limited password at least once within 24 hours after the password takes effect. Otherwise, the password becomes invalid.',
|
||||||
'Use the time-limited password at least once within 24 hours after the password takes effect. Otherwise, the password becomes invalid.',
|
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
fontColor: ColorsManager.grayColor,
|
fontColor: ColorsManager.grayColor,
|
||||||
),
|
),
|
||||||
@ -259,14 +256,10 @@ class CreateOfflineTimeLimitPasswordPage extends StatelessWidget {
|
|||||||
backgroundColor: ColorsManager.primaryColor,
|
backgroundColor: ColorsManager.primaryColor,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (generated == false) {
|
if (generated == false) {
|
||||||
smartDoorBloc.add(
|
smartDoorBloc.add(GenerateAndSavePasswordTimeLimitEvent(context: context));
|
||||||
GenerateAndSavePasswordTimeLimitEvent(context: context));
|
|
||||||
await Clipboard.setData(
|
|
||||||
ClipboardData(text: smartDoorBloc.passwordController.text)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||||
smartDoorBloc.add(RenamePasswordEvent());
|
smartDoorBloc.add(RenamePasswordEvent());
|
||||||
}
|
}
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
|||||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
import 'door_dialog.dart';
|
import 'door_dialog.dart';
|
||||||
|
|
||||||
@ -22,11 +23,8 @@ class TimeLimitedPasswordPage extends StatelessWidget {
|
|||||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is FailedState) {
|
if (state is FailedState) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
CustomSnackBar.displaySnackBar(
|
||||||
SnackBar(
|
state.errorMessage
|
||||||
content: Text(state.errorMessage),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -40,10 +38,8 @@ class TimeLimitedPasswordPage extends StatelessWidget {
|
|||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute(builder: (context) => CreateOfflineTimeLimitPasswordPage(deviceId: deviceId,)
|
MaterialPageRoute(builder: (context) => CreateOfflineTimeLimitPasswordPage(deviceId: deviceId,)
|
||||||
)).then((result) {
|
)).then((result) {
|
||||||
if (result != null) {
|
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.add)
|
icon: const Icon(Icons.add)
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class ManageHomeView extends StatelessWidget {
|
|||||||
title: 'Manage Your Home',
|
title: 'Manage Your Home',
|
||||||
child: spaces == null
|
child: spaces == null
|
||||||
? const Center(
|
? const Center(
|
||||||
child: CircularProgressIndicator(),
|
child: BodyMedium(text: 'No spaces found'),
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -30,8 +30,7 @@ class ManageHomeView extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children:
|
children: List.generate(
|
||||||
List.generate(
|
|
||||||
spaces.length,
|
spaces.length,
|
||||||
(index) {
|
(index) {
|
||||||
if (index == spaces.length - 1) {
|
if (index == spaces.length - 1) {
|
||||||
@ -43,12 +42,10 @@ class ManageHomeView extends StatelessWidget {
|
|||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
children: [
|
||||||
BodyMedium(
|
BodyMedium(
|
||||||
text: StringHelpers.toTitleCase(
|
text: StringHelpers.toTitleCase(spaces[index].name ?? "")),
|
||||||
spaces[index].name ?? "")),
|
|
||||||
const Icon(
|
const Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
color: ColorsManager.greyColor,
|
color: ColorsManager.greyColor,
|
||||||
@ -76,14 +73,10 @@ class ManageHomeView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
children: [
|
||||||
BodyMedium(
|
BodyMedium(
|
||||||
text: HomeCubit.getInstance()
|
text: HomeCubit.getInstance().spaces![index].name ?? ""),
|
||||||
.spaces![index]
|
|
||||||
.name ??
|
|
||||||
""),
|
|
||||||
const Icon(
|
const Icon(
|
||||||
Icons.arrow_forward_ios,
|
Icons.arrow_forward_ios,
|
||||||
color: ColorsManager.greyColor,
|
color: ColorsManager.greyColor,
|
||||||
@ -92,8 +85,7 @@ class ManageHomeView extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
margin:
|
margin: const EdgeInsets.symmetric(vertical: 15),
|
||||||
const EdgeInsets.symmetric(vertical: 15),
|
|
||||||
height: 1,
|
height: 1,
|
||||||
color: ColorsManager.greyColor,
|
color: ColorsManager.greyColor,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||||
@ -10,6 +9,16 @@ import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
|||||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||||
|
|
||||||
class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
||||||
|
final daysMap = {
|
||||||
|
'Sun': 'S',
|
||||||
|
'Mon': 'M',
|
||||||
|
'Tue': 'T',
|
||||||
|
'Wed': 'W',
|
||||||
|
'Thu': 'T',
|
||||||
|
'Fri': 'F',
|
||||||
|
'Sat': 'S',
|
||||||
|
};
|
||||||
|
|
||||||
EffectPeriodBloc() : super(EffectPeriodState.initial()) {
|
EffectPeriodBloc() : super(EffectPeriodState.initial()) {
|
||||||
on<SetPeriod>(_onSetPeriod);
|
on<SetPeriod>(_onSetPeriod);
|
||||||
on<ToggleDay>(_onToggleDay);
|
on<ToggleDay>(_onToggleDay);
|
||||||
@ -44,20 +53,17 @@ class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlocProvider.of<CreateSceneBloc>(
|
BlocProvider.of<CreateSceneBloc>(NavigationService.navigatorKey.currentContext!).add(
|
||||||
NavigationService.navigatorKey.currentContext!)
|
EffectiveTimePeriodEvent(
|
||||||
.add(EffectiveTimePeriodEvent(EffectiveTime(
|
EffectiveTime(start: startTime, end: endTime, loops: state.selectedDaysBinary)));
|
||||||
start: startTime, end: endTime, loops: state.selectedDaysBinary)));
|
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
selectedPeriod: event.period,
|
selectedPeriod: event.period, customStartTime: startTime, customEndTime: endTime));
|
||||||
customStartTime: startTime,
|
|
||||||
customEndTime: endTime));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onToggleDay(ToggleDay event, Emitter<EffectPeriodState> emit) {
|
void _onToggleDay(ToggleDay event, Emitter<EffectPeriodState> emit) {
|
||||||
final daysList = state.selectedDaysBinary.split('');
|
final daysList = state.selectedDaysBinary.split('');
|
||||||
final dayIndex = _getDayIndex(event.day);
|
final dayIndex = getDayIndex(event.day);
|
||||||
if (daysList[dayIndex] == '1') {
|
if (daysList[dayIndex] == '1') {
|
||||||
daysList[dayIndex] = '0';
|
daysList[dayIndex] = '0';
|
||||||
} else {
|
} else {
|
||||||
@ -66,9 +72,8 @@ class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
|||||||
final newDaysBinary = daysList.join();
|
final newDaysBinary = daysList.join();
|
||||||
emit(state.copyWith(selectedDaysBinary: newDaysBinary));
|
emit(state.copyWith(selectedDaysBinary: newDaysBinary));
|
||||||
|
|
||||||
BlocProvider.of<CreateSceneBloc>(
|
BlocProvider.of<CreateSceneBloc>(NavigationService.navigatorKey.currentContext!).add(
|
||||||
NavigationService.navigatorKey.currentContext!)
|
EffectiveTimePeriodEvent(EffectiveTime(
|
||||||
.add(EffectiveTimePeriodEvent(EffectiveTime(
|
|
||||||
start: state.customStartTime ?? '00:00',
|
start: state.customStartTime ?? '00:00',
|
||||||
end: state.customEndTime ?? '23:59',
|
end: state.customEndTime ?? '23:59',
|
||||||
loops: newDaysBinary)));
|
loops: newDaysBinary)));
|
||||||
@ -90,37 +95,31 @@ class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
|||||||
period = EnumEffectivePeriodOptions.custom;
|
period = EnumEffectivePeriodOptions.custom;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(
|
||||||
customStartTime: startTime,
|
state.copyWith(customStartTime: startTime, customEndTime: endTime, selectedPeriod: period));
|
||||||
customEndTime: endTime,
|
|
||||||
selectedPeriod: period));
|
|
||||||
|
|
||||||
BlocProvider.of<CreateSceneBloc>(
|
BlocProvider.of<CreateSceneBloc>(NavigationService.navigatorKey.currentContext!).add(
|
||||||
NavigationService.navigatorKey.currentContext!)
|
EffectiveTimePeriodEvent(
|
||||||
.add(EffectiveTimePeriodEvent(EffectiveTime(
|
EffectiveTime(start: startTime, end: endTime, loops: state.selectedDaysBinary)));
|
||||||
start: startTime, end: endTime, loops: state.selectedDaysBinary)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onResetEffectivePeriod(
|
void _onResetEffectivePeriod(ResetEffectivePeriod event, Emitter<EffectPeriodState> emit) {
|
||||||
ResetEffectivePeriod event, Emitter<EffectPeriodState> emit) {
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
selectedPeriod: EnumEffectivePeriodOptions.allDay,
|
selectedPeriod: EnumEffectivePeriodOptions.allDay,
|
||||||
customStartTime: '00:00',
|
customStartTime: '00:00',
|
||||||
customEndTime: '23:59',
|
customEndTime: '23:59',
|
||||||
selectedDaysBinary: '1111111'));
|
selectedDaysBinary: '1111111'));
|
||||||
|
|
||||||
BlocProvider.of<CreateSceneBloc>(
|
BlocProvider.of<CreateSceneBloc>(NavigationService.navigatorKey.currentContext!).add(
|
||||||
NavigationService.navigatorKey.currentContext!)
|
EffectiveTimePeriodEvent(EffectiveTime(start: '00:00', end: '23:59', loops: '1111111')));
|
||||||
.add(EffectiveTimePeriodEvent(
|
|
||||||
EffectiveTime(start: '00:00', end: '23:59', loops: '1111111')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onResetDays(ResetDays event, Emitter<EffectPeriodState> emit) {
|
void _onResetDays(ResetDays event, Emitter<EffectPeriodState> emit) {
|
||||||
emit(state.copyWith(selectedDaysBinary: '1111111'));
|
emit(state.copyWith(selectedDaysBinary: '1111111'));
|
||||||
}
|
}
|
||||||
|
|
||||||
int _getDayIndex(String day) {
|
int getDayIndex(String day) {
|
||||||
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||||
return days.indexOf(day);
|
return days.indexOf(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,7 @@ mixin SceneLogicHelper {
|
|||||||
required List<SceneStaticFunction> conditions,
|
required List<SceneStaticFunction> conditions,
|
||||||
}) {
|
}) {
|
||||||
final sceneBloc = context.read<CreateSceneBloc>();
|
final sceneBloc = context.read<CreateSceneBloc>();
|
||||||
|
final effectiveTime = sceneBloc.effectiveTime;
|
||||||
|
|
||||||
if (isOnlyDelayOrDelayLast(actions)) {
|
if (isOnlyDelayOrDelayLast(actions)) {
|
||||||
context.showCustomSnackbar(
|
context.showCustomSnackbar(
|
||||||
@ -46,6 +47,17 @@ mixin SceneLogicHelper {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAutomation == true && effectiveTime?.loops == '0000000') {
|
||||||
|
context.showCustomSnackbar(
|
||||||
|
message: 'At least one day in Effective Period must be selected!',
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.error,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isAutomation) {
|
if (isAutomation) {
|
||||||
final createAutomationModel = CreateAutomationModel(
|
final createAutomationModel = CreateAutomationModel(
|
||||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||||
@ -81,7 +93,7 @@ mixin SceneLogicHelper {
|
|||||||
executorProperty: CreateSceneExecutorProperty(
|
executorProperty: CreateSceneExecutorProperty(
|
||||||
functionCode: '',
|
functionCode: '',
|
||||||
functionValue: '',
|
functionValue: '',
|
||||||
delaySeconds: task.functionValue,
|
delaySeconds: task.functionValue ?? 1,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -159,21 +171,24 @@ mixin SceneLogicHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getTheCorrectDialogBody(SceneStaticFunction taskItem, dynamic functionValue,
|
Widget getTheCorrectDialogBody(
|
||||||
|
SceneStaticFunction taskItem, dynamic functionValue,
|
||||||
{required bool isAutomation}) {
|
{required bool isAutomation}) {
|
||||||
if (taskItem.operationDialogType == OperationDialogType.temperature) {
|
if (taskItem.operationDialogType == OperationDialogType.temperature) {
|
||||||
return AlertDialogTemperatureBody(
|
return AlertDialogTemperatureBody(
|
||||||
taskItem: taskItem,
|
taskItem: taskItem,
|
||||||
functionValue: functionValue ?? taskItem.functionValue,
|
functionValue: functionValue ?? taskItem.functionValue,
|
||||||
);
|
);
|
||||||
} else if ((taskItem.operationDialogType == OperationDialogType.countdown) ||
|
} else if ((taskItem.operationDialogType ==
|
||||||
|
OperationDialogType.countdown) ||
|
||||||
(taskItem.operationDialogType == OperationDialogType.delay)) {
|
(taskItem.operationDialogType == OperationDialogType.delay)) {
|
||||||
return AlertDialogCountdown(
|
return AlertDialogCountdown(
|
||||||
durationValue: taskItem.functionValue ?? 0,
|
durationValue: taskItem.functionValue ?? 0,
|
||||||
functionValue: functionValue ?? taskItem.functionValue,
|
functionValue: functionValue ?? taskItem.functionValue,
|
||||||
function: taskItem,
|
function: taskItem,
|
||||||
);
|
);
|
||||||
} else if (taskItem.operationDialogType == OperationDialogType.integerSteps) {
|
} else if (taskItem.operationDialogType ==
|
||||||
|
OperationDialogType.integerSteps) {
|
||||||
return AlertDialogSliderSteps(
|
return AlertDialogSliderSteps(
|
||||||
taskItem: taskItem,
|
taskItem: taskItem,
|
||||||
functionValue: functionValue ?? taskItem.functionValue,
|
functionValue: functionValue ?? taskItem.functionValue,
|
||||||
|
|||||||
@ -15,10 +15,12 @@ class SceneAutoSettings extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sceneSettings = ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>? ?? {};
|
final sceneSettings =
|
||||||
|
ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>? ??
|
||||||
|
{};
|
||||||
final sceneId = sceneSettings['sceneId'] as String? ?? '';
|
final sceneId = sceneSettings['sceneId'] as String? ?? '';
|
||||||
final isAutomation =
|
final isAutomation = context.read<CreateSceneBloc>().sceneType ==
|
||||||
context.read<CreateSceneBloc>().sceneType == CreateSceneEnum.deviceStatusChanges;
|
CreateSceneEnum.deviceStatusChanges;
|
||||||
final sceneName = sceneSettings['sceneName'] as String? ?? '';
|
final sceneName = sceneSettings['sceneName'] as String? ?? '';
|
||||||
|
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
@ -48,9 +50,11 @@ class SceneAutoSettings extends StatelessWidget {
|
|||||||
Visibility(
|
Visibility(
|
||||||
visible: isAutomation,
|
visible: isAutomation,
|
||||||
child: SceneListTile(
|
child: SceneListTile(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16, vertical: 8),
|
||||||
titleString: "Effective Period",
|
titleString: "Effective Period",
|
||||||
trailingWidget: const Icon(Icons.arrow_forward_ios_rounded),
|
trailingWidget:
|
||||||
|
const Icon(Icons.arrow_forward_ios_rounded),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.customBottomSheet(
|
context.customBottomSheet(
|
||||||
child: const EffectPeriodBottomSheetContent(),
|
child: const EffectPeriodBottomSheetContent(),
|
||||||
|
|||||||
@ -48,12 +48,21 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (widget.taskItem.code == 'temp_current') {
|
||||||
if (widget.functionValue != null) {
|
if (widget.functionValue != null) {
|
||||||
groupValue = _normalizeValue(widget.functionValue);
|
groupValue = _normalizeValue(
|
||||||
|
double.tryParse(widget.functionValue.toString()) ??
|
||||||
|
widget.taskItem.operationalValues[0].minValue);
|
||||||
|
} else {
|
||||||
|
groupValue = widget.taskItem.operationalValues[0].minValue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
groupValue =
|
if (widget.functionValue != null) {
|
||||||
_normalizeValue(widget.taskItem.operationalValues[0].minValue);
|
groupValue = _normalizeValue(widget.functionValue);
|
||||||
|
} else {
|
||||||
|
groupValue =
|
||||||
|
_normalizeValue(widget.taskItem.operationalValues[0].minValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@ -68,14 +77,6 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double _normalizeValue(dynamic value) {
|
|
||||||
if (((widget.taskItem.code == "temp_set" && value > 199) ||
|
|
||||||
widget.taskItem.code == "temp_current")) {
|
|
||||||
return (value) / 10;
|
|
||||||
}
|
|
||||||
return value.toDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _comparatorToIndex(String? comparator) {
|
int _comparatorToIndex(String? comparator) {
|
||||||
switch (comparator) {
|
switch (comparator) {
|
||||||
case "<":
|
case "<":
|
||||||
@ -216,7 +217,7 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
: null,
|
: null,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
groupValue = normalizeValue(value);
|
groupValue = normalizeToDoubleValue(value);
|
||||||
});
|
});
|
||||||
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||||
value: _deNormalizeValue(groupValue),
|
value: _deNormalizeValue(groupValue),
|
||||||
@ -237,8 +238,16 @@ class _AlertDialogSliderStepsState extends State<AlertDialogSliderSteps> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double normalizeValue(double value) {
|
double _normalizeValue(dynamic value) {
|
||||||
return double.parse(value.toStringAsFixed(1));
|
if ((widget.taskItem.code == "temp_set" && value > 199) ||
|
||||||
|
(widget.taskItem.code == "temp_current" && value >= -99.0)) {
|
||||||
|
return (value) / 10;
|
||||||
|
}
|
||||||
|
return value.toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
double? normalizeToDoubleValue(double value) {
|
||||||
|
return double.tryParse(value.toStringAsFixed(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
double _deNormalizeValue(double? value) {
|
double _deNormalizeValue(double? value) {
|
||||||
|
|||||||
@ -50,10 +50,10 @@ class _AlertDialogTemperatureBodyState
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
context.read<CreateSceneBloc>().add(SelectedValueEvent(
|
||||||
// value: temperature * 10,
|
value: temperature * 10,
|
||||||
// code: widget.taskItem.code,
|
code: widget.taskItem.code,
|
||||||
// ));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
int _normalizeTemperature(dynamic value) {
|
int _normalizeTemperature(dynamic value) {
|
||||||
|
|||||||
@ -19,18 +19,8 @@ class EffectPeriodBottomSheetContent extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
// Expanded(
|
|
||||||
// child: TextButton(
|
|
||||||
// onPressed: () => Navigator.pop(context),
|
|
||||||
// child: BodySmall(
|
|
||||||
// text: 'Save',
|
|
||||||
// style:
|
|
||||||
// context.bodySmall.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
|
||||||
// )),
|
|
||||||
// ),
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Expanded(
|
Expanded(
|
||||||
// flex: 2,
|
|
||||||
child: BodyMedium(
|
child: BodyMedium(
|
||||||
text: 'Effective Period',
|
text: 'Effective Period',
|
||||||
fontColor: ColorsManager.primaryColorWithOpacity,
|
fontColor: ColorsManager.primaryColorWithOpacity,
|
||||||
|
|||||||
@ -4,22 +4,16 @@ import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_b
|
|||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
|
||||||
class RepeatDays extends StatelessWidget {
|
class RepeatDays extends StatelessWidget {
|
||||||
const RepeatDays({super.key});
|
const RepeatDays({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final daysMap = {
|
final effectiveBloc = context.read<EffectPeriodBloc>();
|
||||||
'Mon': 'M',
|
|
||||||
'Tue': 'T',
|
|
||||||
'Wed': 'W',
|
|
||||||
'Thu': 'T',
|
|
||||||
'Fri': 'F',
|
|
||||||
'Sat': 'S',
|
|
||||||
'Sun': 'S',
|
|
||||||
};
|
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@ -27,53 +21,61 @@ class RepeatDays extends StatelessWidget {
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Row(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: daysMap.entries.map((entry) {
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
final day = entry.key;
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
final abbreviation = entry.value;
|
children: [
|
||||||
final dayIndex = _getDayIndex(day);
|
Row(
|
||||||
final isSelected = state.selectedDaysBinary[dayIndex] == '1';
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
return Padding(
|
children: effectiveBloc.daysMap.entries.map((entry) {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
final day = entry.key;
|
||||||
child: GestureDetector(
|
final abbreviation = entry.value;
|
||||||
onTap: () {
|
final dayIndex = effectiveBloc.getDayIndex(day);
|
||||||
context.read<EffectPeriodBloc>().add(ToggleDay(day));
|
final isSelected = state.selectedDaysBinary[dayIndex] == '1';
|
||||||
},
|
return Padding(
|
||||||
child: Container(
|
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||||
decoration: BoxDecoration(
|
child: GestureDetector(
|
||||||
shape: BoxShape.circle,
|
onTap: () {
|
||||||
border: Border.all(
|
effectiveBloc.add(ToggleDay(day));
|
||||||
color:
|
},
|
||||||
isSelected ? Colors.grey : Colors.grey.shade300,
|
child: Container(
|
||||||
width: 1,
|
decoration: BoxDecoration(
|
||||||
),
|
shape: BoxShape.circle,
|
||||||
),
|
border: Border.all(
|
||||||
child: CircleAvatar(
|
color: isSelected ? Colors.grey : Colors.grey.shade300,
|
||||||
radius: 15,
|
width: 1,
|
||||||
backgroundColor: Colors.white,
|
),
|
||||||
child: Text(
|
),
|
||||||
abbreviation,
|
child: CircleAvatar(
|
||||||
style: TextStyle(
|
radius: 15,
|
||||||
fontSize: 16,
|
backgroundColor: Colors.white,
|
||||||
color:
|
child: Text(
|
||||||
isSelected ? Colors.grey : Colors.grey.shade300,
|
abbreviation,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: isSelected ? Colors.grey : Colors.grey.shade300,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
if (state.selectedDaysBinary == '0000000')
|
||||||
|
BodySmall(
|
||||||
|
text: 'At least one day must be selected',
|
||||||
|
style: context.bodyMedium.copyWith(color: ColorsManager.red),
|
||||||
),
|
),
|
||||||
);
|
],
|
||||||
}).toList(),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _getDayIndex(String day) {
|
|
||||||
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
|
||||||
return days.indexOf(day);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ class _SmartSceneSelectTabToRunListState extends State<SmartSceneSelectTabToRunL
|
|||||||
.read<SmartSceneSelectBloc>()
|
.read<SmartSceneSelectBloc>()
|
||||||
.add(SmartSceneEnableEvent(SmartSceneEnable(
|
.add(SmartSceneEnableEvent(SmartSceneEnable(
|
||||||
entityId: scene.id,
|
entityId: scene.id,
|
||||||
actionExecutor: 'rule_enable',
|
actionExecutor: 'rule_trigger',
|
||||||
sceneORAutomationName: scene.name,
|
sceneORAutomationName: scene.name,
|
||||||
type: scene.type,
|
type: scene.type,
|
||||||
isAutomation: false,
|
isAutomation: false,
|
||||||
@ -109,7 +109,7 @@ class _SmartSceneSelectTabToRunListState extends State<SmartSceneSelectTabToRunL
|
|||||||
});
|
});
|
||||||
context.read<SmartSceneSelectBloc>().add(SmartSceneEnableEvent(SmartSceneEnable(
|
context.read<SmartSceneSelectBloc>().add(SmartSceneEnableEvent(SmartSceneEnable(
|
||||||
entityId: scene.id,
|
entityId: scene.id,
|
||||||
actionExecutor: 'rule_enable',
|
actionExecutor: 'rule_trigger',
|
||||||
sceneORAutomationName: scene.name,
|
sceneORAutomationName: scene.name,
|
||||||
type: scene.type,
|
type: scene.type,
|
||||||
isAutomation: false,
|
isAutomation: false,
|
||||||
|
|||||||
@ -7,9 +7,7 @@ import 'package:syncrow_app/firebase_options.dart';
|
|||||||
import 'package:syncrow_app/services/locator.dart';
|
import 'package:syncrow_app/services/locator.dart';
|
||||||
import 'package:syncrow_app/utils/bloc_observer.dart';
|
import 'package:syncrow_app/utils/bloc_observer.dart';
|
||||||
import 'package:syncrow_app/utils/helpers/localization_helpers.dart';
|
import 'package:syncrow_app/utils/helpers/localization_helpers.dart';
|
||||||
|
|
||||||
import 'my_app.dart';
|
import 'my_app.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
//to observe the state of the blocs in the output console
|
//to observe the state of the blocs in the output console
|
||||||
Bloc.observer = MyBlocObserver();
|
Bloc.observer = MyBlocObserver();
|
||||||
|
|||||||
@ -81,8 +81,7 @@ abstract class ApiEndpoints {
|
|||||||
static const String controlGroup = '/group/control';
|
static const String controlGroup = '/group/control';
|
||||||
//GET
|
//GET
|
||||||
static const String groupBySpace = '/group/{unitUuid}';
|
static const String groupBySpace = '/group/{unitUuid}';
|
||||||
static const String devicesByGroupName =
|
static const String devicesByGroupName = '/group/{unitUuid}/devices/{groupName}';
|
||||||
'/group/{unitUuid}/devices/{groupName}';
|
|
||||||
|
|
||||||
static const String groupByUuid = '/group/{groupUuid}';
|
static const String groupByUuid = '/group/{groupUuid}';
|
||||||
//DELETE
|
//DELETE
|
||||||
@ -94,18 +93,17 @@ abstract class ApiEndpoints {
|
|||||||
static const String addDeviceToRoom = '/device/room';
|
static const String addDeviceToRoom = '/device/room';
|
||||||
static const String addDeviceToGroup = '/device/group';
|
static const String addDeviceToGroup = '/device/group';
|
||||||
static const String controlDevice = '/device/{deviceUuid}/control';
|
static const String controlDevice = '/device/{deviceUuid}/control';
|
||||||
static const String firmwareDevice =
|
static const String firmwareDevice = '/device/{deviceUuid}/firmware/{firmwareVersion}';
|
||||||
'/device/{deviceUuid}/firmware/{firmwareVersion}';
|
|
||||||
static const String getDevicesByUserId = '/device/user/{userId}';
|
static const String getDevicesByUserId = '/device/user/{userId}';
|
||||||
static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
|
static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
|
||||||
|
static const String openDoorLock = '/door-lock/open/{doorLockUuid}';
|
||||||
|
|
||||||
//GET
|
//GET
|
||||||
static const String deviceByRoom = '/device/room';
|
static const String deviceByRoom = '/device/room';
|
||||||
static const String deviceByUuid = '/device/{deviceUuid}';
|
static const String deviceByUuid = '/device/{deviceUuid}';
|
||||||
static const String deviceFunctions = '/device/{deviceUuid}/functions';
|
static const String deviceFunctions = '/device/{deviceUuid}/functions';
|
||||||
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
|
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
|
||||||
static const String deviceFunctionsStatus =
|
static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status';
|
||||||
'/device/{deviceUuid}/functions/status';
|
|
||||||
|
|
||||||
///Device Permission Module
|
///Device Permission Module
|
||||||
//POST
|
//POST
|
||||||
@ -130,29 +128,24 @@ abstract class ApiEndpoints {
|
|||||||
|
|
||||||
static const String getUnitAutomation = '/automation/{unitUuid}';
|
static const String getUnitAutomation = '/automation/{unitUuid}';
|
||||||
|
|
||||||
static const String getAutomationDetails =
|
static const String getAutomationDetails = '/automation/details/{automationId}';
|
||||||
'/automation/details/{automationId}';
|
|
||||||
|
|
||||||
/// PUT
|
/// PUT
|
||||||
static const String updateScene = '/scene/tap-to-run/{sceneId}';
|
static const String updateScene = '/scene/tap-to-run/{sceneId}';
|
||||||
|
|
||||||
static const String updateAutomation = '/automation/{automationId}';
|
static const String updateAutomation = '/automation/{automationId}';
|
||||||
|
|
||||||
static const String updateAutomationStatus =
|
static const String updateAutomationStatus = '/automation/status/{automationId}';
|
||||||
'/automation/status/{automationId}';
|
|
||||||
|
|
||||||
/// DELETE
|
/// DELETE
|
||||||
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
|
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
|
||||||
|
|
||||||
static const String deleteAutomation =
|
static const String deleteAutomation = '/automation/{unitUuid}/{automationId}';
|
||||||
'/automation/{unitUuid}/{automationId}';
|
|
||||||
|
|
||||||
//////////////////////Door Lock //////////////////////
|
//////////////////////Door Lock //////////////////////
|
||||||
//online
|
//online
|
||||||
static const String addTemporaryPassword =
|
static const String addTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
|
||||||
'/door-lock/temporary-password/online/{doorLockUuid}';
|
static const String getTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
|
||||||
static const String getTemporaryPassword =
|
|
||||||
'/door-lock/temporary-password/online/{doorLockUuid}';
|
|
||||||
|
|
||||||
//one-time offline
|
//one-time offline
|
||||||
static const String addOneTimeTemporaryPassword =
|
static const String addOneTimeTemporaryPassword =
|
||||||
@ -160,8 +153,6 @@ abstract class ApiEndpoints {
|
|||||||
static const String getOneTimeTemporaryPassword =
|
static const String getOneTimeTemporaryPassword =
|
||||||
'/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
|
'/door-lock/temporary-password/offline/one-time/{doorLockUuid}';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//user
|
//user
|
||||||
|
|
||||||
static const String getUser = '/user/{userUuid}';
|
static const String getUser = '/user/{userUuid}';
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class DevicesAPI {
|
|||||||
static Future<Map<String, dynamic>> controlDevice(
|
static Future<Map<String, dynamic>> controlDevice(
|
||||||
DeviceControlModel controlModel, String deviceId) async {
|
DeviceControlModel controlModel, String deviceId) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.controlDevice.replaceAll('{deviceUuid}', deviceId),
|
path: ApiEndpoints.controlDevice.replaceAll('{deviceUuid}', deviceId),
|
||||||
body: controlModel.toJson(),
|
body: controlModel.toJson(),
|
||||||
@ -46,6 +47,17 @@ class DevicesAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<bool> openDoorLock(String deviceId) async {
|
||||||
|
final response = await _httpService.post(
|
||||||
|
path: ApiEndpoints.openDoorLock.replaceAll('{doorLockUuid}', deviceId),
|
||||||
|
showServerMessage: false,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json['success'] ?? false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
static Future<List<DevicesCategoryModel>> fetchGroups(String spaceId) async {
|
static Future<List<DevicesCategoryModel>> fetchGroups(String spaceId) async {
|
||||||
// Map<String, dynamic> params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1};
|
// Map<String, dynamic> params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1};
|
||||||
|
|
||||||
@ -69,17 +81,13 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Map<String, dynamic>> renamePass({
|
static Future<Map<String, dynamic>> renamePass(
|
||||||
required String name,
|
{required String name, required String doorLockUuid, required String passwordId}) async {
|
||||||
required String doorLockUuid,
|
|
||||||
required String passwordId}) async {
|
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.renamePassword
|
path: ApiEndpoints.renamePassword
|
||||||
.replaceAll('{doorLockUuid}', doorLockUuid)
|
.replaceAll('{doorLockUuid}', doorLockUuid)
|
||||||
.replaceAll('{passwordId}', passwordId),
|
.replaceAll('{passwordId}', passwordId),
|
||||||
body: {
|
body: {"name": name},
|
||||||
"name": name
|
|
||||||
},
|
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
@ -156,9 +164,11 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future getTemporaryPasswords(String deviceId, ) async {
|
static Future getTemporaryPasswords(
|
||||||
|
String deviceId,
|
||||||
|
) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
@ -196,8 +206,8 @@ class DevicesAPI {
|
|||||||
required String effectiveTime,
|
required String effectiveTime,
|
||||||
required String invalidTime,
|
required String invalidTime,
|
||||||
required String deviceId,
|
required String deviceId,
|
||||||
List<Schedule>? scheduleList,}) async {
|
List<Schedule>? scheduleList,
|
||||||
|
}) async {
|
||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"password": password,
|
"password": password,
|
||||||
@ -216,7 +226,7 @@ class DevicesAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future generateOneTimePassword({deviceId}) async {
|
static Future generateOneTimePassword({deviceId}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
@ -231,15 +241,12 @@ class DevicesAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future generateMultiTimePassword({deviceId,effectiveTime,invalidTime}) async {
|
static Future generateMultiTimePassword({deviceId, effectiveTime, invalidTime}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||||
showServerMessage: false,
|
showServerMessage: true,
|
||||||
body: {
|
body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
|
||||||
"effectiveTime": effectiveTime,
|
|
||||||
"invalidTime": invalidTime
|
|
||||||
},
|
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return json;
|
return json;
|
||||||
},
|
},
|
||||||
@ -263,5 +270,4 @@ class DevicesAPI {
|
|||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,6 +68,7 @@ Map<String, DeviceType> devicesTypesMap = {
|
|||||||
"DL": DeviceType.DoorLock,
|
"DL": DeviceType.DoorLock,
|
||||||
"WPS": DeviceType.WallSensor,
|
"WPS": DeviceType.WallSensor,
|
||||||
"3G": DeviceType.ThreeGang,
|
"3G": DeviceType.ThreeGang,
|
||||||
|
"CUR": DeviceType.Curtain,
|
||||||
};
|
};
|
||||||
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||||
DeviceType.AC: [
|
DeviceType.AC: [
|
||||||
@ -174,6 +175,21 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
|||||||
type: functionTypesMap['Integer'],
|
type: functionTypesMap['Integer'],
|
||||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||||
],
|
],
|
||||||
|
DeviceType.Curtain: [
|
||||||
|
FunctionModel(
|
||||||
|
code: 'control',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"range": ["open","stop","close"]}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'percent_control',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "%", "min": 0, "max": 100, "scale": 0, "step": 1})
|
||||||
|
),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TempModes { hot, cold, wind }
|
enum TempModes { hot, cold, wind }
|
||||||
|
|||||||
32
pubspec.lock
@ -5,10 +5,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
sha256: fe4c077084ddda88f327dc1c96d16631cd68d4948644593fcbcd911c2c89e2fa
|
sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.23"
|
version: "1.3.35"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -245,10 +245,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: "797379ea206eaeeb62499775de812761493d0692890fdc7f90b6183a3369176d"
|
sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.25.5"
|
version: "2.32.0"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -281,6 +281,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.6.23"
|
version: "3.6.23"
|
||||||
|
firebase_database:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_database
|
||||||
|
sha256: "3b9ca306d26ad243ccbc4c717ff6e8563a080ebe11ee77fa7349b419c894b42d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "10.5.7"
|
||||||
|
firebase_database_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_database_platform_interface
|
||||||
|
sha256: "5864cc362275465e9bd682b243f19419c9d78b861c2db820241eea596ae3b320"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.5+35"
|
||||||
|
firebase_database_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_database_web
|
||||||
|
sha256: a6008395dd20e8b8dde0691b441c181a1216c3866f89f48dcb6889d34fd35905
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.5+7"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -5,7 +5,7 @@ description: This is the mobile application project, developed with Flutter for
|
|||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
version: 1.0.2+18
|
version: 1.0.3+21
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.6 <4.0.0"
|
sdk: ">=3.0.6 <4.0.0"
|
||||||
@ -45,6 +45,7 @@ dependencies:
|
|||||||
time_picker_spinner: ^1.0.0
|
time_picker_spinner: ^1.0.0
|
||||||
image_picker: ^1.1.2
|
image_picker: ^1.1.2
|
||||||
device_info_plus: ^10.1.0
|
device_info_plus: ^10.1.0
|
||||||
|
firebase_database: ^10.5.7
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^3.0.1
|
flutter_lints: ^3.0.1
|
||||||
|
|||||||