Compare commits

..

139 Commits

Author SHA1 Message Date
21cad0d9e8 Refactor menu view and add build number and environment label 2025-05-12 10:58:16 +03:00
9c6ab888a7 Merge pull request #98 from SyncrowIOT/SP-1523-FE-Implement-Task-Dialogs-for-Editable-Sensor-Parameters-Sensitivity-Distances-Timings-Levels
Implement Flush Mounted Presence Sensor Routine Control and change th…
2025-05-12 10:51:11 +03:00
0a4ec1c6de Refactor API endpoint for getting device reports and fix the record title 2025-05-12 10:18:02 +03:00
adb42f95e8 Implement Flush Mounted Presence Sensor Routine Control and change the device type logic 2025-05-11 16:33:11 +03:00
2651de71e4 Merge pull request #97 from SyncrowIOT/SP-1522-FE-Implement-Device-Settings-Screen-Edit-Name-Location-Device-Info
Sp 1522 fe implement device settings screen edit name location device info
2025-05-07 11:07:43 +03:00
5411d84759 Refactor device avatar and add icon to setting 2025-05-07 11:01:51 +03:00
a1954b3ad3 add settings to flush sensor 2025-05-07 10:37:59 +03:00
56007d6a8c Merge pull request #96 from SyncrowIOT/SP-1520-FE-Build-Motion-Status-Illuminance-Row-and-Presence-Record-Navigation
add new flush sensor device to app
2025-05-07 10:16:12 +03:00
9cc4538dc5 Add flush sensor icon to assets and enhancement code 2025-05-07 10:11:33 +03:00
14a5d26ef9 add new flush sensor device to app 2025-05-06 16:20:05 +03:00
7fd825516f Merge pull request #95 from SyncrowIOT/staging-release-30+16
Added Client id, and client secret to `.env.prod`.
2025-05-06 09:40:23 +03:00
9919840391 Added Client id, and client secret to .env.prod. 2025-05-06 09:35:02 +03:00
8a21828dd4 add water heater device to routine and fix device type in routine 2025-05-05 10:00:54 +03:00
5890a70243 Added CLIENT_ID and CLIENT_SECRET to .env.staging file. 2025-04-29 10:37:08 +03:00
5a70df0a61 Merge pull request #94 from SyncrowIOT/SP-1471-BE-On-mobile-app-Error-while-retrieving-scene-details-on-4-6-Scenes-devices
Refactor device_info_model.dart and devices_api.dart
2025-04-28 16:13:34 +03:00
d493000c20 Refactor return type of deviceByUuid API method in devices_api.dart 2025-04-28 16:11:07 +03:00
6a27f863c3 Refactor device_info_model.dart and devices_api.dart 2025-04-28 15:59:10 +03:00
bde418e52a Merge pull request #93 from SyncrowIOT/SP-1472-FE-On-Mobile-2-3-Gangs-Devices-conditions-Action-names-are-changing-when-we-save-a-routine-then-try-to-edit-it
Sp 1472 fe on mobile 2 3 gangs devices conditions action names are changing when we save a routine then try to edit it
2025-04-28 11:25:33 +03:00
3725d28a5e Refactor device names in scene operations data helper 2025-04-28 11:06:27 +03:00
f30b7b0831 Fixed routines bug where it threw 404 because of a developer error. 2025-04-28 10:02:41 +03:00
405cccad03 Merge pull request #92 from SyncrowIOT/SP-1477-FE-On-mobile-app-Error-fetching-device-functions-status-when-we-open-the-power-clamp-device-control
SP-1477
2025-04-28 09:02:02 +03:00
a7080248cb SP-1477 2025-04-27 12:50:20 +03:00
25893e3bbd Merge pull request #90 from SyncrowIOT/sp-1268-rework-v3
SP-1268 Rework
2025-04-24 16:26:31 +03:00
c90f0874c2 Merge pull request #91 from SyncrowIOT/changed_titles_of_devices_view
Changed titles of devices view
2025-04-24 16:26:15 +03:00
214ec78a95 added title to four scene view. 2025-04-24 12:41:45 +03:00
ed9f98e653 Temporarily disable showing the NCPS device from all the all devices api, for release and demo purposes. Feel free to revert this commit once the device is needed back into the application. 2025-04-24 12:40:02 +03:00
a37236c8d2 changed titles of devices views, and responsiness of device card. 2025-04-24 12:12:56 +03:00
1f1a8a7208 SP-1268 2025-04-23 15:43:55 +03:00
e7efd2b3a1 Merge pull request #89 from SyncrowIOT/fix-device-ui-routine
Refactor device name display in Action and Condition models
2025-04-23 10:20:10 +03:00
2b0e504f05 Refactor device name display in Action and Condition models 2025-04-23 10:07:14 +03:00
a656d5981e Merge pull request #88 from SyncrowIOT/Fix-Save-Display-Condition
Fix save display condition
2025-04-22 15:42:42 +03:00
3f49a18130 remove unused code 2025-04-21 15:19:14 +03:00
a51c4d9679 Refactor device name display in RoomPageSwitch widget 2025-04-21 15:00:31 +03:00
caeed8e73f Merge pull request #87 from SyncrowIOT/FE-Complete-the-Device-Name-as
Refactor device name display in RoomPageSwitch widget
2025-04-21 10:43:22 +03:00
dc5ac9be5b Refactor device name display in RoomPageSwitch widget 2025-04-21 10:36:43 +03:00
5c9b30895f Merge pull request #86 from SyncrowIOT/SP-1286-FE-Add-Device-to-Routine-2-Gang
add tow gang and change gang device ui
2025-04-17 16:29:24 +03:00
06b14a3964 add tow gang and change gang device ui 2025-04-17 16:14:48 +03:00
3c92ea3047 Merge pull request #85 from SyncrowIOT/SP-1285-FE-Add-Device-to-Routine
Sp 1285 fe add device to routine
2025-04-17 10:42:06 +03:00
73d28a1800 Refactor Action class to use type annotations for actionExecutor and entityId 2025-04-17 10:41:01 +03:00
5493ca6fb0 Refactor device filtering logic to improve code readability 2025-04-17 10:38:25 +03:00
7005d8ba83 Refactor device filtering logic and improve code readability
- Extracted the logic for filtering implemented devices into a separate method `_getOnlyImplementedDevices`
- Created a set `allowedDevices` to store the allowed device types
- Updated the filtering logic to use the `allowedDevices` set for checking device types
- Removed unnecessary conditions for filtering devices

Fix nullability issues in `Action` model

- Added null checks for `actionExecutor`, `entityId`, `name`, `type`, and `productType` properties in the `fromJson` method of the `Action` model
- Set default values for `actionExecutor` and `entityId` if they are null
- Updated the type casting for `name`, `type`, and `productType` properties to avoid potential nullability issues
2025-04-17 10:16:10 +03:00
cb79627038 Merge pull request #83 from SyncrowIOT/SP-1397-FE-Create-Routine-SceneRoomsTabBarDevicesView-throws-TabBarController-initialization-error
Sp 1397 fe create routine scene rooms tab bar devices view throws tab bar controller initialization error
2025-04-17 09:47:46 +03:00
1cff69d496 change icon 2025-04-17 09:39:58 +03:00
60df77efad add OneGang product type to routine 2025-04-17 09:32:20 +03:00
9e84048f81 Merge pull request #84 from SyncrowIOT:SP-1416
fixed typo
2025-04-16 20:57:45 +04:00
99adb1c286 fixed typo 2025-04-16 20:57:13 +04:00
f2412aa867 refactor: extract device fetching logic into a separate method for improved readability 2025-04-16 16:10:36 +03:00
e4768c95aa refactor: rename tab change events and states for consistency, and to match blocs naming convention. 2025-04-16 16:07:30 +03:00
f25b4dbf6d implement SceneDevicesBodyTabBar for improved tab management in SceneDevicesBody. 2025-04-16 15:57:21 +03:00
9eff9ab371 refactor: consolidate device loading and error handling in SceneDevicesBody and implement SceneDevicesList widget 2025-04-16 15:46:56 +03:00
a2e68d6194 fix: restore title in DefaultScaffold for SceneRoomsTabBarDevicesView 2025-04-16 15:25:23 +03:00
94c94b170f fix: correct order of dispose method calls in SceneRoomsTabBarDevicesView 2025-04-16 15:24:47 +03:00
253cf15559 refactor: simplify SceneDevicesBody widget structure and improve loading indicator handling 2025-04-16 15:24:37 +03:00
443eea9421 SP-1397 2025-04-16 15:11:43 +03:00
87a2c08f64 Merge pull request #82 from SyncrowIOT/SP-1416
added client token login
2025-04-16 12:35:31 +04:00
dd66e7c747 added client token login 2025-04-16 12:02:19 +04:00
7af61d2f65 added client id and secret 2025-04-16 11:34:24 +04:00
f37eacb0ee Merge pull request #81 from SyncrowIOT/feat/update-additional-device-endpoints
updated endpoint for device
2025-04-14 15:11:36 +03:00
c7dcc297aa fix conflict 2025-04-14 15:11:02 +03:00
aefe5ad081 Merge branch 'dev' into feat/update-additional-device-endpoints 2025-04-14 15:10:42 +03:00
8d9af8519d Merge pull request #78 from SyncrowIOT/SP-1246
updated device endpoint
2025-04-14 14:58:09 +03:00
b1d52937c9 Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into feat/update-additional-device-endpoints 2025-04-14 10:31:09 +04:00
5fedf37421 updated endpoint for device 2025-04-14 10:30:48 +04:00
ccde857c29 Merge pull request #80 from SyncrowIOT/SP-1398-FE-in-the-wizerd-the-batch-control-title-doesn-t-represent-the-the-accurate-device-name
SP-1398-FE-in-the-wizerd-the-batch-control-title-doesn-t-represent-the-the-accurate-device-name
2025-04-13 16:23:49 +03:00
b2a8086e0e Merge pull request #79 from SyncrowIOT/sp-1268-rework-v2
Sp 1268 rework v2
2025-04-13 16:20:10 +03:00
408e78962c SP-1398 2025-04-13 16:18:49 +03:00
dcdbc02ca0 Adds AppLoadingIndicator widget and replaces CircularProgressIndicator in SceneView. 2025-04-13 15:50:52 +03:00
31025e9176 Refactors SceneView constructor and improves conditional rendering for automation list 2025-04-13 15:49:13 +03:00
8219de6821 Injects SceneBloc using the new factory. 2025-04-13 15:28:44 +03:00
fbdf3817ab Created a factory helper to create a SceneBloc. 2025-04-13 15:25:48 +03:00
17422edd0d sp-1268-rework-v2. 2025-04-13 15:21:20 +03:00
4c8f2c72df Merge branch 'dev' of https://github.com/SyncrowIOT/syncrow-app into SP-1246 2025-04-03 10:47:27 +04:00
fb867e5df3 updated device endpoint 2025-04-03 10:47:09 +04:00
9472390284 Merge pull request #76 from SyncrowIOT/bugifx/empty-subspace-routine-creation
fixed issue on empty subspace
2025-03-28 11:38:14 +04:00
731ba0f3d6 Merge pull request #77 from SyncrowIOT/SP-1268-FE-Implement-UX-Behavior-for-No-Tab-to-Run-Scene-in-Device-Screen
Sp 1268 fe implement ux behavior for no tab to run scene in device screen
2025-03-26 15:24:34 +03:00
56407c6426 indentation and trailing commas. 2025-03-26 13:49:54 +03:00
02d61ca0bb Refactor DevicesViewBody and SceneView to improve widget structure and replace CreateUnitWidget with EmptyDevicesWidget for better handling of empty states. 2025-03-26 13:44:49 +03:00
99ee4b9878 Add EmptyDevicesWidget to display message when no routines are available. 2025-03-26 13:34:07 +03:00
19edd0a275 Added /android/app/.cxx/ to .gitIgnore, because they're auto generated files that dont need to be checked into source control. 2025-03-26 13:14:23 +03:00
ef5e7c3154 fixed issue on empty subspace 2025-03-25 14:15:14 +04:00
80dd0f696f Merge pull request #75 from SyncrowIOT/SP-1245
updated endpoint for automation
2025-03-17 09:34:46 +04:00
a64a41548f updated delete endpoint for automation 2025-03-14 13:02:14 +04:00
0d50aa68fa updated endpoint for update automation 2025-03-14 12:58:12 +04:00
88aac86b10 updated endpoint for getting automation by id 2025-03-14 12:55:33 +04:00
0673548745 changed endpoint for getting automations by space 2025-03-14 12:53:29 +04:00
c2fc8fa0ae changed endpoint for create automation endpoint 2025-03-14 12:40:52 +04:00
cbf10bbf78 Merge pull request #74 from SyncrowIOT/real_time_app
Real time app
2025-03-03 17:34:34 +03:00
d95588ce84 remove unused code 2025-03-03 17:34:15 +03:00
7e2e591d71 remove unused code 2025-03-01 15:19:15 +03:00
2ec81bda9c connect the real time for all devices 2025-03-01 15:08:51 +03:00
3b0f51473c Merge pull request #73 from SyncrowIOT/SP-1190
Sp 1190
2025-02-26 12:20:06 +03:00
13757d89ee Merged with dev 2025-02-26 12:17:57 +03:00
d3068b8e14 changes in threeGang 2025-02-26 10:58:32 +03:00
7c5d7e1dda remove unused code 2025-02-25 12:45:23 +03:00
0a97a4867d disconnect real-time to some devices 2025-02-25 12:41:49 +03:00
6e55b488aa Merge pull request #72 from SyncrowIOT/feat/change-hardcode-projectid
updated project hardcoded values
2025-02-24 12:06:06 +03:00
22789234fe Sensitivity Start from 1 2025-02-23 16:30:50 +03:00
8393ec353a fetchDevices by projectUuid 2025-02-20 16:02:25 +03:00
0b45d61b25 Fixed list issue in the manage home screen 2025-02-20 10:50:47 +03:00
450b773921 set default values in the devices models instead of late, and fixed issues in the AC bloc 2025-02-20 04:13:37 +03:00
3f7f7ce49f updated project hardcoded values 2025-02-16 20:55:13 +04:00
2dc4e16a75 connect all devices to real-time and change the channel function 2025-02-16 14:54:39 +03:00
cd41720244 active the implemented device 2025-02-16 10:04:34 +03:00
67209961b4 added project model 2025-02-15 11:54:02 +04:00
9098276223 Merge pull request #71 from SyncrowIOT/fixes_bugs_sprint15
fixes bugs and add project id staging
2025-02-12 12:47:09 +03:00
36dfe2c85e change the key 2025-02-12 12:06:00 +03:00
efed5f55a7 add project id to env file and hide about 2025-02-11 11:05:13 +03:00
9897c19dad fixes bugs and add project id staging 2025-02-10 10:26:02 +03:00
48733fd65e Merge pull request #70 from SyncrowIOT/sprint_14_changes
Sprint 14 changes
2025-02-02 22:33:28 +03:00
4ca4086bd3 Merged with dev 2025-02-02 22:32:15 +03:00
4da1b16b18 Merge pull request #69 from SyncrowIOT/role_permission_restrict_user
restrict_spaceMemberUser_and_change_SignUpModel
2025-02-02 14:27:31 +03:00
1189b52c57 remove comment DevicesViewBody and fix home page 2025-02-02 13:17:25 +03:00
c578d63134 all_devices and Restrict_user 2025-01-29 14:10:38 +03:00
457b7c2c51 Updated gradle and kotlin 2025-01-26 20:38:37 +03:00
4ae04cf2af Merged with Dev 2025-01-26 13:08:40 +03:00
d72253e3de hide SceneSettings 2025-01-23 18:41:50 +03:00
790479effb restrict_spaceMemberUser_and_change_SignUpModel 2025-01-23 18:35:01 +03:00
827585815b Merge pull request #68 from SyncrowIOT/user_agreement_policy
User agreement and policy
2025-01-21 12:05:25 +03:00
de024994c9 showSpaceBottomSheet in a DefaultAppBar and Routine trigger from the device screen
and fixes github comments
and i used this package flutter_html: ^3.0.0-beta.2
2025-01-20 15:50:36 +03:00
bcc4ba98ff size changes 2025-01-19 16:56:42 +03:00
df0f1c6c94 user_agreement and privacy_policy sign up and menu 2025-01-19 16:49:54 +03:00
1f62cadcec Merge pull request #66 from SyncrowIOT/Implement_Change_Password_Flow
change_password
2025-01-16 18:02:33 +03:00
ee01a89d21 change file name 2025-01-16 18:01:23 +03:00
31cc210560 Fitch report Data 2025-01-15 17:55:07 +03:00
f779445d17 refactor code and implement CeilingSensor taps 2025-01-15 17:24:25 +03:00
c76548a17f remove role model 2025-01-13 13:16:29 +03:00
f960a553ca Updated the pacakages 2025-01-13 13:02:51 +03:00
55c1a30f10 change api generateInvitationCode 2025-01-12 12:59:10 +03:00
90812f78e8 Completed wall sensor implementation 2025-01-12 00:12:08 +03:00
b1368bf4d7 update ios packages 2025-01-12 00:10:02 +03:00
de9c51998c changes 2025-01-09 16:43:09 +03:00
763e39ef12 changeAcSwitch 2025-01-09 15:37:26 +03:00
cc9ddffa44 Join the space through the invitation code_ac countdown 2025-01-09 15:35:04 +03:00
7a22bb4bc8 count_down_ac 2025-01-08 17:17:52 +03:00
cff8c4728c change_pass 2024-12-31 10:36:52 +03:00
8be05fbd91 change_password 2024-12-30 16:51:35 +03:00
33d2bbc91f Hide unused widgets 2024-12-17 01:13:36 +03:00
f81880a704 Hide nonfunctional widgets 2024-12-15 02:22:11 +03:00
fc3f215dba Merge pull request #65 from SyncrowIOT/feat/change-community-endpoint
changed endpoint
2024-12-11 16:17:20 +04:00
236 changed files with 13534 additions and 4495 deletions

View File

@ -1,2 +1,5 @@
ENV_NAME=development
BASE_URL=https://syncrow-dev.azurewebsites.net
BASE_URL=https://syncrow-dev.azurewebsites.net
PROJECT_ID=0e62577c-06fa-41b9-8a92-99a21fbaf51c
CLIENT_ID=c024573d191a327ce74db7d4502fdc29
CLIENT_SECRET=fec6ccbc33664f94a3b84a45c7cceef3f3ebd1613ef4307db8946ede530cd1ed

View File

@ -1,2 +1,5 @@
ENV_NAME=production
BASE_URL=https://syncrow-staging.azurewebsites.net
BASE_URL=https://syncrow-staging.azurewebsites.net
PROJECT_ID=bcda711e-9fc2-4168-a05e-171b4026d1ff
CLIENT_ID=ac05b6c26bdb0543ec6200781d8177f1
CLIENT_SECRET=fdbaafdd5a94bbd542a4a6739cf0178c8bb2e87bff39232a3aaa993fbd5d71e7

View File

@ -1,2 +1,5 @@
ENV_NAME=staging
BASE_URL=https://syncrow-staging.azurewebsites.net
BASE_URL=https://syncrow-staging.azurewebsites.net
PROJECT_ID=bcda711e-9fc2-4168-a05e-171b4026d1ff
CLIENT_ID=ac05b6c26bdb0543ec6200781d8177f1
CLIENT_SECRET=fdbaafdd5a94bbd542a4a6739cf0178c8bb2e87bff39232a3aaa993fbd5d71e7

3
.gitignore vendored
View File

@ -5,9 +5,11 @@
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
@ -40,3 +42,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
/android/app/.cxx/

View File

@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '1.9.0'
repositories {
google()
mavenCentral()

View File

@ -1,3 +1,6 @@
org.gradle.jvmargs=-Xmx4G
android.useAndroidX=true
android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View File

@ -1,6 +1,6 @@
#Wed Apr 03 23:37:40 EET 2024
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View File

@ -23,7 +23,7 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "com.android.application" version '8.3.0' apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
id "com.google.firebase.crashlytics" version "2.8.1" apply false

View File

@ -0,0 +1,18 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.8326 16.8575C7.55614 16.8575 4.89062 14.192 4.89062 10.9156C4.89062 7.63915 7.55614 4.97363 10.8326 4.97363C14.1091 4.97363 16.7746 7.63915 16.7746 10.9156C16.7746 14.192 14.1091 16.8575 10.8326 16.8575Z" fill="#FFE645"/>
<path d="M10.8333 4.97363C10.8332 4.97363 10.833 4.97363 10.833 4.97363V16.8575H10.8333C14.1098 16.8575 16.7753 14.192 16.7753 10.9156C16.7753 7.63915 14.1098 4.97363 10.8333 4.97363Z" fill="#FFF1B9"/>
<path d="M10.833 21.8334C10.4824 21.8334 10.1982 21.5493 10.1982 21.1986V18.8289C10.1982 18.4784 10.4824 18.1941 10.833 18.1941C11.1836 18.1941 11.4678 18.4784 11.4678 18.8289V21.1986C11.4678 21.5493 11.1836 21.8334 10.833 21.8334Z" fill="#FFE645"/>
<path d="M21.0317 11.6348H18.7461C18.3955 11.6348 18.1113 11.3506 18.1113 11C18.1113 10.6496 18.3955 10.3652 18.7461 10.3652H21.0317C21.3824 10.3652 21.6665 10.6496 21.6665 11C21.6665 11.3506 21.3824 11.6348 21.0317 11.6348Z" fill="#FFCF2C"/>
<path d="M2.92042 11.6348H0.634766C0.284157 11.6348 0 11.3506 0 11C0 10.6496 0.284157 10.3652 0.634766 10.3652H2.92042C3.27103 10.3652 3.55518 10.6496 3.55518 11C3.55518 11.3506 3.27103 11.6348 2.92042 11.6348Z" fill="#FFE645"/>
<path d="M17.7243 7.65695C17.5049 7.65695 17.2915 7.54306 17.174 7.33941C16.9988 7.03591 17.1027 6.64761 17.4064 6.47239L19.3481 5.3513C19.6517 5.17591 20.04 5.28005 20.2152 5.58372C20.3905 5.88721 20.2865 6.27551 19.9828 6.45073L18.0412 7.57182C17.9412 7.62951 17.8321 7.65695 17.7243 7.65695Z" fill="#FFCF2C"/>
<path d="M2.03686 16.7139C1.8175 16.7139 1.60409 16.6 1.48656 16.3963C1.31117 16.0928 1.41531 15.7045 1.71881 15.5293L3.69865 14.3862C4.00231 14.2108 4.39045 14.315 4.56567 14.6186C4.74106 14.9221 4.63708 15.3104 4.33342 15.4856L2.35358 16.6287C2.25373 16.6864 2.14447 16.7139 2.03686 16.7139Z" fill="#FFE645"/>
<path d="M5.76902 20.4051C5.6614 20.4051 5.5523 20.3778 5.4523 20.32C5.14863 20.1448 5.04466 19.7565 5.21988 19.453L6.36279 17.4735C6.53801 17.17 6.92631 17.0658 7.22981 17.2412C7.53347 17.4164 7.63744 17.8047 7.46222 18.1082L6.31931 20.0877C6.20178 20.2914 5.98838 20.4051 5.76902 20.4051Z" fill="#FFE645"/>
<path d="M3.94197 7.65681C3.83419 7.65681 3.72509 7.62937 3.62524 7.57168L1.64557 6.42877C1.34207 6.25355 1.23793 5.86525 1.41332 5.56158C1.58854 5.25809 1.97667 5.15395 2.28033 5.32933L4.26001 6.47224C4.56351 6.64746 4.66748 7.03576 4.49226 7.33926C4.37473 7.54291 4.16132 7.65681 3.94197 7.65681Z" fill="#FFE645"/>
<path d="M19.6649 16.7342C19.5572 16.7342 19.4481 16.7067 19.348 16.6491L17.333 15.4857C17.0295 15.3103 16.9255 14.9221 17.1007 14.6185C17.276 14.315 17.6643 14.2108 17.9678 14.3862L19.9828 15.5496C20.2865 15.7248 20.3905 16.1131 20.2152 16.4166C20.0977 16.6203 19.8843 16.7342 19.6649 16.7342Z" fill="#FFCF2C"/>
<path d="M15.8973 20.4051C15.6778 20.4051 15.4645 20.2913 15.347 20.0877L14.2043 18.1085C14.029 17.8048 14.133 17.4167 14.4367 17.2415C14.7402 17.0661 15.1285 17.1701 15.3037 17.4737L16.4464 19.4529C16.6217 19.7566 16.5177 20.1447 16.214 20.3199C16.114 20.3778 16.0049 20.4051 15.8973 20.4051Z" fill="#FFCF2C"/>
<path d="M10.833 3.72144C10.4824 3.72144 10.1982 3.43728 10.1982 3.08667V0.801514C10.1982 0.450905 10.4824 0.166748 10.833 0.166748C11.1836 0.166748 11.4678 0.450905 11.4678 0.801514V3.08667C11.4678 3.43728 11.1836 3.72144 10.833 3.72144Z" fill="#FFE645"/>
<path d="M14.7534 4.75952C14.6458 4.75952 14.5365 4.73208 14.4367 4.67422C14.133 4.499 14.029 4.11086 14.2043 3.8072L15.3472 1.82786C15.5224 1.5242 15.9105 1.42005 16.2142 1.59544C16.5178 1.77066 16.6218 2.15896 16.4466 2.46262L15.3037 4.44197C15.1862 4.64562 14.9728 4.75952 14.7534 4.75952Z" fill="#FFCF2C"/>
<path d="M6.91292 4.75919C6.69356 4.75919 6.48015 4.64529 6.36262 4.44164L5.21988 2.46262C5.04466 2.15896 5.14863 1.77066 5.4523 1.59544C5.75579 1.42005 6.14409 1.5242 6.31931 1.82786L7.46206 3.80687C7.63728 4.11053 7.5333 4.49867 7.22964 4.67405C7.1298 4.73175 7.02053 4.75919 6.91292 4.75919Z" fill="#FFE645"/>
<path d="M10.8333 18.1941C10.8332 18.1941 10.833 18.1941 10.833 18.1941V21.8334H10.8333C11.1839 21.8334 11.4681 21.5493 11.4681 21.1986V18.8289C11.4681 18.4784 11.1839 18.1941 10.8333 18.1941Z" fill="#FFCF2C"/>
<path d="M10.8333 0.166748C10.8332 0.166748 10.833 0.166748 10.833 0.166748V3.72144H10.8333C11.1839 3.72144 11.4681 3.43728 11.4681 3.08667V0.801514C11.4681 0.450905 11.1839 0.166748 10.8333 0.166748Z" fill="#FFCF2C"/>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

28
assets/icons/bathroom.svg Normal file
View File

@ -0,0 +1,28 @@
<svg width="21" height="25" viewBox="0 0 21 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.9628 0C15.5449 0 14.3965 1.15256 14.3965 2.56632C14.3965 2.78191 14.5748 2.96018 14.7903 2.96018C15.0059 2.96018 15.1842 2.78191 15.1842 2.56632C15.1842 1.58374 15.9844 0.787724 16.9628 0.787724C17.9454 0.787724 18.7414 1.58789 18.7414 2.56632V15.1782C18.7414 15.3938 18.9197 15.5721 19.1353 15.5721C19.3509 15.5721 19.5291 15.3938 19.5291 15.1782V2.56632C19.5291 1.15256 18.3766 0 16.9628 0Z" fill="#C3BEC6"/>
<path d="M6.95808 7.69098H5.2168V3.41654C5.2168 3.18852 5.40336 3.00195 5.63139 3.00195H6.54349C6.77152 3.00195 6.95808 3.18852 6.95808 3.41654V7.69098Z" fill="#A7CCF9"/>
<path d="M6.53841 3.00195H5.63875C5.58485 3.00195 5.53096 3.01439 5.48535 3.03097C5.6429 3.09316 5.75069 3.24242 5.75069 3.42069V7.69098H6.95715V3.42069C6.95715 3.19267 6.77059 3.00195 6.53841 3.00195Z" fill="#8CBDF9"/>
<path d="M5.21973 4.34912H6.96101V5.13685H5.21973V4.34912Z" fill="#4C5E71"/>
<path d="M3.47957 7.69102H1.73828V2.54594C1.73828 2.31791 1.92485 2.13135 2.15287 2.13135H3.06497C3.293 2.13135 3.47957 2.31791 3.47957 2.54594V7.69102Z" fill="#A7DDA7"/>
<path d="M3.06185 2.13525H2.16219C2.10829 2.13525 2.05439 2.14769 2.00879 2.16428C2.16633 2.22646 2.27413 2.37572 2.27413 2.55399V7.69078H3.48059V2.55399C3.48059 2.32182 3.29402 2.13525 3.06185 2.13525Z" fill="#8ACE9B"/>
<path d="M1.73828 3.479H3.47957V4.26673H1.73828V3.479Z" fill="#4C5E71"/>
<path d="M11.3064 15.1788C11.3064 14.2004 10.5021 13.4127 9.51952 13.4417H7.47559V15.3695H11.3064V15.1788Z" fill="#EABC73"/>
<path d="M15.2205 24.7462L14.7852 23.0049V22.582H16.9618V24.9991H15.2329L15.2205 24.7462Z" fill="#C3BEC6"/>
<path d="M5.6512 24.7462L6.08652 23.0049V22.582H3.91406V24.9991H5.64291L5.6512 24.7462Z" fill="#C3BEC6"/>
<path d="M20.0045 16.3267H0.871094V16.9195L1.87855 21.6334C2.04853 22.4336 2.75749 23.0099 3.57838 23.0099H17.2931C18.114 23.0099 18.8229 22.4377 18.9929 21.6334L20.0045 16.9195V16.3267Z" fill="#E2DFE2"/>
<path d="M18.7983 16.3267V16.9195L17.7867 21.6334C17.6168 22.4336 16.9078 23.0099 16.0869 23.0099H17.2934C18.1143 23.0099 18.8232 22.4377 18.9932 21.6334L20.0048 16.9195V16.3267H18.7983Z" fill="#D3CED5"/>
<path d="M0.870642 16.9195C0.389716 16.9195 0 16.5298 0 16.0489C0 15.5679 0.389716 15.1782 0.870642 15.1782H20.004C20.485 15.1782 20.8747 15.5679 20.8747 16.0489C20.8747 16.5298 20.485 16.9195 20.004 16.9195H0.870642Z" fill="#F4F2F4"/>
<path d="M20.0053 15.1782H18.7988C19.2798 15.1782 19.6695 15.5679 19.6695 16.0489C19.6695 16.5298 19.2798 16.9195 18.7988 16.9195H20.0053C20.4862 16.9195 20.8759 16.5298 20.8759 16.0489C20.8759 15.5679 20.4862 15.1782 20.0053 15.1782Z" fill="#E2DFE2"/>
<path d="M19.5466 19.0509L19.7124 18.2632H1.15527L1.32526 19.0509H19.5466Z" fill="#C3BEC6"/>
<path d="M5.22175 13.4424C4.2599 13.4424 3.48047 14.2218 3.48047 15.1837V19.9681C3.48047 20.2085 3.67533 20.4034 3.91579 20.4034H7.39421C7.63468 20.4034 7.82953 20.2085 7.82953 19.9681V15.2168C7.82953 14.2674 8.57165 13.4673 9.52107 13.4424H5.22175Z" fill="#EFD27C"/>
<path d="M3.48047 16.9214H7.82954V18.6627H3.48047V16.9214Z" fill="#EAA96A"/>
<path d="M16.5265 4.3072C16.5265 3.34535 15.7471 2.56592 14.7852 2.56592C13.8234 2.56592 13.0439 3.34535 13.0439 4.3072V4.80471H16.5224L16.5265 4.3072Z" fill="#E2DFE2"/>
<path d="M14.785 2.56592C14.5735 2.56592 14.3704 2.60323 14.1797 2.67371C14.843 2.91832 15.3157 3.55679 15.3157 4.3072V4.80471H16.5221V4.3072C16.5263 3.34535 15.7468 2.56592 14.785 2.56592Z" fill="#D3CED5"/>
<path d="M16.5268 6.0489C17.0077 6.0489 17.3974 5.65919 17.3974 5.17826C17.3974 4.69733 17.0077 4.30762 16.5268 4.30762H13.0484C12.5675 4.30762 12.1777 4.69733 12.1777 5.17826C12.1777 5.65919 12.5675 6.0489 13.0484 6.0489H16.5268Z" fill="#F4F2F4"/>
<path d="M16.5268 4.30762H15.3203C15.8012 4.30762 16.191 4.69733 16.191 5.17826C16.191 5.65919 15.8012 6.0489 15.3203 6.0489H16.5268C17.0077 6.0489 17.3974 5.65919 17.3974 5.17826C17.3974 4.69733 17.0077 4.30762 16.5268 4.30762Z" fill="#E2DFE2"/>
<path d="M13.0491 9.05046C12.8335 9.05046 12.6553 8.87218 12.6553 8.65659V7.78595C12.6553 7.57036 12.8335 7.39209 13.0491 7.39209C13.2647 7.39209 13.443 7.57036 13.443 7.78595V8.65659C13.443 8.87218 13.2647 9.05046 13.0491 9.05046Z" fill="#A7CCF9"/>
<path d="M14.7845 9.05046C14.5689 9.05046 14.3906 8.87218 14.3906 8.65659V7.78595C14.3906 7.57036 14.5689 7.39209 14.7845 7.39209C15.0001 7.39209 15.1783 7.57036 15.1783 7.78595V8.65659C15.1783 8.87218 15.0042 9.05046 14.7845 9.05046Z" fill="#A7CCF9"/>
<path d="M16.5277 9.05046C16.3121 9.05046 16.1338 8.87218 16.1338 8.65659V7.78595C16.1338 7.57036 16.3121 7.39209 16.5277 7.39209C16.7432 7.39209 16.9215 7.57036 16.9215 7.78595V8.65659C16.9215 8.87218 16.7432 9.05046 16.5277 9.05046Z" fill="#A7CCF9"/>
<path d="M8.28354 9.09236H0.414592C0.186566 9.09236 0 8.90579 0 8.67777V7.76567C0 7.53764 0.186566 7.35107 0.414592 7.35107H8.28354C8.51157 7.35107 8.69813 7.53764 8.69813 7.76567V8.67777C8.69813 8.90579 8.51157 9.09236 8.28354 9.09236Z" fill="#EAA96A"/>
<path d="M8.2758 7.35107H7.06934C7.30151 7.35107 7.48807 7.53764 7.48807 7.76981V8.66948C7.48807 8.90165 7.30151 9.08821 7.06934 9.08821H8.2758C8.50797 9.08821 8.69453 8.90165 8.69453 8.66948V7.76981C8.69868 7.54179 8.50797 7.35107 8.2758 7.35107Z" fill="#E5935D"/>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

33
assets/icons/bedroom.svg Normal file
View File

@ -0,0 +1,33 @@
<svg width="25" height="20" viewBox="0 0 25 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.91701 6.80859H2.18457V10.1036H2.91701V6.80859Z" fill="#78A7AF"/>
<path d="M3.52837 11.1936V10.1333C3.52837 9.98345 3.40576 9.86084 3.2559 9.86084H1.84766C1.69781 9.86084 1.5752 9.98345 1.5752 10.1333V11.1936H3.52837Z" fill="#ABCCD3"/>
<path d="M4.40077 7.0244C4.53906 7.0244 4.62153 6.91546 4.58398 6.78235L3.7531 3.83726C3.71555 3.70415 3.57165 3.59521 3.43332 3.59521H1.67048C1.53215 3.59521 1.38825 3.70415 1.3507 3.83726L0.519819 6.78235C0.482269 6.91546 0.564693 7.0244 0.703026 7.0244H4.40077Z" fill="#FCC96C"/>
<path opacity="0.1" d="M1.59445 6.78235L2.42533 3.83726C2.46288 3.70415 2.60678 3.59521 2.74512 3.59521H1.67048C1.53215 3.59521 1.38825 3.70415 1.3507 3.83726L0.519819 6.78235C0.482269 6.91546 0.564693 7.0244 0.703026 7.0244H1.77761C1.63933 7.0244 1.5569 6.91546 1.59445 6.78235Z" fill="black"/>
<path d="M22.8164 6.80859H22.084V10.1036H22.8164V6.80859Z" fill="#78A7AF"/>
<path d="M23.4249 11.1936V10.1333C23.4249 9.98345 23.3022 9.86084 23.1524 9.86084H21.7441C21.5943 9.86084 21.4717 9.98345 21.4717 10.1333V11.1936H23.4249Z" fill="#ABCCD3"/>
<path d="M24.2973 7.02445C24.4356 7.02445 24.518 6.91551 24.4805 6.7824L23.6496 3.83726C23.612 3.7041 23.4681 3.59521 23.3298 3.59521H21.5669C21.4286 3.59521 21.2847 3.7041 21.2471 3.83726L20.4163 6.7824C20.3788 6.91551 20.4612 7.02445 20.5996 7.02445H24.2973Z" fill="#FCC96C"/>
<path opacity="0.1" d="M21.5628 6.7824L22.3936 3.83726C22.4312 3.7041 22.5751 3.59521 22.7134 3.59521H21.5669C21.4286 3.59521 21.2847 3.7041 21.2471 3.83726L20.4163 6.7824C20.3788 6.91551 20.4612 7.02445 20.5996 7.02445H21.7461C21.6077 7.02445 21.5253 6.91551 21.5628 6.7824Z" fill="black"/>
<path d="M3.39173 15.325C3.39173 15.1866 3.50492 15.0734 3.64325 15.0734H3.83798V13.7245C3.83798 13.3095 4.17754 12.97 4.59254 12.97H5.28821V11.048C5.28455 11.0479 5.28113 11.0469 5.27747 11.0469H0.25152C0.113186 11.0469 0 11.1601 0 11.2984V15.8435C0 15.9819 0.113186 16.095 0.25152 16.095H3.39178L3.39173 15.325Z" fill="#CB7C52"/>
<path d="M4.59249 12.97H5.28821V11.048C5.28455 11.0479 5.28113 11.0469 5.27747 11.0469H0.25152C0.113186 11.0469 0 11.1601 0 11.2984V13.03H4.2984C4.38892 12.9914 4.48829 12.97 4.59249 12.97Z" fill="#FFBB4A"/>
<path opacity="0.1" d="M1.08587 15.8435V11.2984C1.08587 11.1601 1.19905 11.0469 1.33739 11.0469H0.25152C0.113186 11.0469 0 11.1601 0 11.2984V15.8435C0 15.9819 0.113186 16.095 0.25152 16.095H1.33739C1.19905 16.095 1.08587 15.9818 1.08587 15.8435Z" fill="black"/>
<path d="M2.76563 12.3745C2.66895 12.3745 2.57471 12.3355 2.50635 12.2676C2.43848 12.1992 2.39941 12.105 2.39941 12.0088C2.39941 11.9121 2.43848 11.8179 2.50635 11.7495C2.57471 11.6816 2.66895 11.6426 2.76563 11.6426C2.86183 11.6426 2.95607 11.6816 3.02443 11.7495C3.0923 11.8179 3.13185 11.9121 3.13185 12.0088C3.13185 12.105 3.09235 12.1992 3.02443 12.2676C2.95607 12.3355 2.86183 12.3745 2.76563 12.3745Z" fill="white"/>
<path d="M24.7476 11.0469H19.7216C19.7089 11.0469 19.6968 11.0488 19.6846 11.0506V12.97H20.3803C20.7953 12.97 21.1348 13.3095 21.1348 13.7245V15.0734H21.3296C21.4679 15.0734 21.5811 15.1866 21.5811 15.3249V16.095H24.7476C24.886 16.095 24.9992 15.9819 24.9992 15.8435V11.2984C24.9991 11.1601 24.8859 11.0469 24.7476 11.0469Z" fill="#CB7C52"/>
<path d="M24.7476 11.0469H19.7216C19.7089 11.0469 19.6968 11.0488 19.6846 11.0506V12.97H20.3803C20.4845 12.97 20.5839 12.9914 20.6744 13.03H24.9991V11.2984C24.9991 11.1601 24.8859 11.0469 24.7476 11.0469Z" fill="#FFBB4A"/>
<path d="M22.2354 12.375C22.1392 12.375 22.0449 12.3355 21.9766 12.2676C21.9087 12.1992 21.8691 12.105 21.8691 12.0083C21.8691 11.9121 21.9087 11.8179 21.9766 11.7495C22.0449 11.6816 22.1392 11.6426 22.2354 11.6426C22.332 11.6426 22.4263 11.6816 22.4946 11.7495C22.5625 11.8179 22.6021 11.9121 22.6021 12.0083C22.6021 12.105 22.5625 12.1992 22.4946 12.2676C22.4263 12.3355 22.332 12.375 22.2354 12.375Z" fill="white"/>
<path d="M19.9184 13.1712V9.67632C19.9184 9.53799 19.8052 9.4248 19.6669 9.4248H5.33257C5.19424 9.4248 5.08105 9.53799 5.08105 9.67632V13.1712H19.9184Z" fill="#FF9F3D"/>
<path opacity="0.1" d="M6.1636 13.1712V9.67632C6.1636 9.53799 6.27679 9.4248 6.41512 9.4248H5.33257C5.19424 9.4248 5.08105 9.53799 5.08105 9.67632V13.1712H6.1636Z" fill="black"/>
<path d="M11.9437 13.171V12.0422C11.9437 11.6272 11.6041 11.2876 11.1891 11.2876H7.27702C6.86207 11.2876 6.52246 11.6272 6.52246 12.0422V13.171H11.9437Z" fill="white"/>
<path d="M18.636 13.171V12.0422C18.636 11.6272 18.2965 11.2876 17.8815 11.2876H13.9694C13.5544 11.2876 13.2148 11.6272 13.2148 12.0422V13.171H18.636Z" fill="white"/>
<path d="M21.3677 15.2937V13.7253C21.3677 13.3103 21.0282 12.9707 20.6132 12.9707H4.38444C3.96944 12.9707 3.62988 13.3103 3.62988 13.7253V15.2937H21.3677Z" fill="#FFCFAB"/>
<path opacity="0.1" d="M5.00365 15.2937V13.7253C5.00365 13.3103 5.34321 12.9707 5.75821 12.9707H4.38444C3.96944 12.9707 3.62988 13.3103 3.62988 13.7253V15.2937H5.00365Z" fill="black"/>
<path d="M5.16518 19.1609C5.30352 19.1609 5.4167 19.0477 5.4167 18.9094V17.5694C5.4167 17.4311 5.52989 17.3179 5.66822 17.3179H19.3331C19.4714 17.3179 19.5846 17.4311 19.5846 17.5694V18.9094C19.5846 19.0477 19.6978 19.1609 19.8361 19.1609H21.5643C21.7026 19.1609 21.8158 19.0477 21.8158 18.9094V15.3257C21.8158 15.1874 21.7026 15.0742 21.5643 15.0742H3.43707C3.29873 15.0742 3.18555 15.1874 3.18555 15.3257V18.9094C3.18555 19.0477 3.29873 19.1609 3.43707 19.1609H5.16518Z" fill="#FF9F3D"/>
<g opacity="0.1">
<path d="M4.28118 18.9089V15.3253C4.28118 15.1869 4.39437 15.0737 4.5327 15.0737H3.43511C3.29678 15.0737 3.18359 15.1869 3.18359 15.3253V18.9089C3.18359 19.0472 3.29678 19.1604 3.43511 19.1604H4.5327C4.39437 19.1604 4.28118 19.0472 4.28118 18.9089Z" fill="black"/>
</g>
<path d="M18.0893 6.21186C18.0893 6.35019 17.9761 6.46338 17.8378 6.46338H7.16265C7.02432 6.46338 6.91113 6.35019 6.91113 6.21186V0.617731C6.91113 0.479397 7.02432 0.366211 7.16265 0.366211H17.8378C17.9761 0.366211 18.0893 0.479397 18.0893 0.617731V6.21186Z" fill="#B1E8FF"/>
<path opacity="0.1" d="M8.01238 6.21186V0.617731C8.01238 0.479397 8.12557 0.366211 8.2639 0.366211H7.16265C7.02432 0.366211 6.91113 0.479397 6.91113 0.617731V6.21191C6.91113 6.35024 7.02432 6.46343 7.16265 6.46343H8.2639C8.12557 6.46333 8.01238 6.35019 8.01238 6.21186Z" fill="black"/>
<path d="M12.2235 2.33252L9.83887 6.46284H14.6082L12.2235 2.33252Z" fill="#86D5B5"/>
<path d="M12.7314 6.46345H17.8379C17.9763 6.46345 18.0894 6.35027 18.0894 6.21193V5.80025L15.6018 1.4917L12.7314 6.46345Z" fill="#FCC96C"/>
<path d="M17.8388 6.82956H7.16364C6.823 6.82956 6.5459 6.55245 6.5459 6.21182V0.61774C6.5459 0.277106 6.823 0 7.16364 0H17.8388C18.1794 0 18.4565 0.277106 18.4565 0.61774V6.21192C18.4565 6.55245 18.1794 6.82956 17.8388 6.82956ZM7.27839 6.09712H17.7241V0.73244H7.27839V6.09712Z" fill="#CB7C52"/>
<path d="M9.31653 3.35424C9.8144 3.35424 10.218 2.95063 10.218 2.45276C10.218 1.95488 9.8144 1.55127 9.31653 1.55127C8.81865 1.55127 8.41504 1.95488 8.41504 2.45276C8.41504 2.95063 8.81865 3.35424 9.31653 3.35424Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,10 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_7302_4118)">
<path d="M11.1049 10.0001L19.7712 1.33381C20.0763 1.02869 20.0763 0.534007 19.7712 0.228929C19.4661 -0.0761485 18.9714 -0.0761876 18.6663 0.228929L9.99999 8.89524L1.33372 0.228929C1.0286 -0.0761876 0.533915 -0.0761876 0.228837 0.228929C-0.0762401 0.534046 -0.0762792 1.02873 0.228837 1.33381L8.89511 10.0001L0.228837 18.6664C-0.0762792 18.9715 -0.0762792 19.4662 0.228837 19.7713C0.381376 19.9238 0.581337 20.0001 0.781297 20.0001C0.981258 20.0001 1.18118 19.9238 1.33376 19.7713L9.99999 11.105L18.6663 19.7713C18.8188 19.9238 19.0188 20.0001 19.2187 20.0001C19.4187 20.0001 19.6186 19.9238 19.7712 19.7713C20.0763 19.4662 20.0763 18.9715 19.7712 18.6664L11.1049 10.0001Z" fill="#999999"/>
</g>
<defs>
<clipPath id="clip0_7302_4118">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 939 B

View File

@ -0,0 +1,17 @@
<svg width="22" height="14" viewBox="0 0 22 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.6663 11.1257L7.02441 8.58667L10.833 13.6648H21.6663V11.1257Z" fill="#FFB54C"/>
<path d="M0 11.1257V13.6648H10.8333V8.58667L0 11.1257Z" fill="#FFCC4A"/>
<path d="M21.6663 11.1257V5.41284H20.0688L19.4341 6.04761L18.7993 5.41284H17.2018L16.5671 6.04761L15.9323 5.41284H14.3348L13.7 6.04761L13.0653 5.41284H11.4678L8.29395 8.26929L10.833 11.1257H21.6663Z" fill="#FFCC4A"/>
<path d="M10.8333 5.41284H10.1986H8.60107L7.96631 6.04761L7.33154 5.41284H5.73405L5.09928 6.04761L4.46452 5.41284H2.86702L2.23226 6.04761L1.59749 5.41284H0V11.1257H10.8333V5.41284Z" fill="#FFE278"/>
<path d="M21.0316 1.60449H10.833L10.1982 2.23926L10.833 2.87402H21.0316V1.60449Z" fill="#ABD5ED"/>
<path d="M10.8333 1.60449H1.26953V0.334961H0V4.14355H1.26953V2.87402H10.8333V1.60449Z" fill="#BFEBFF"/>
<path d="M20.3965 0.334961H21.666V4.14355H20.3965V0.334961Z" fill="#ABD5ED"/>
<path d="M1.59766 5.41284H2.86719V8.58667H1.59766V5.41284Z" fill="#587AA1"/>
<path d="M4.46484 5.41284H5.73438V7.31714H4.46484V5.41284Z" fill="#587AA1"/>
<path d="M7.33203 5.41284H8.60156V8.58667H7.33203V5.41284Z" fill="#587AA1"/>
<path d="M11.4678 7.31714H10.833L10.5156 6.99976V5.73022L10.833 5.41284H11.4678V7.31714Z" fill="#455F80"/>
<path d="M10.1982 5.41284H10.833V7.31714H10.1982V5.41284Z" fill="#587AA1"/>
<path d="M13.0654 5.41284H14.335V8.58667H13.0654V5.41284Z" fill="#455F80"/>
<path d="M15.9326 5.41284H17.2021V7.31714H15.9326V5.41284Z" fill="#455F80"/>
<path d="M18.7998 5.41284H20.0693V8.58667H18.7998V5.41284Z" fill="#455F80"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,17 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8194_10048)">
<path d="M11.4732 16.7316C8.31096 16.7316 5.73828 14.1589 5.73828 10.9967C5.73828 7.8344 8.31096 5.26172 11.4732 5.26172C14.6355 5.26172 17.2081 7.8344 17.2081 10.9967C17.2081 14.1589 14.6355 16.7316 11.4732 16.7316Z" fill="#EBF6FF"/>
<path d="M17.2076 10.9967C17.2076 7.8344 14.6349 5.26172 11.4727 5.26172V16.7316C14.6349 16.7316 17.2076 14.1589 17.2076 10.9967Z" fill="#D7E7F8"/>
<path d="M11.4721 17.3699C7.95827 17.3699 5.09961 14.5112 5.09961 10.9974C5.09961 7.48362 7.95827 4.625 11.472 4.625C14.9858 4.625 17.8445 7.48366 17.8445 10.9974C17.8445 14.5112 14.9858 17.3699 11.4721 17.3699ZM11.4721 5.89473C8.6584 5.89473 6.36934 8.18379 6.36934 10.9974C6.36934 13.811 8.6584 16.1001 11.472 16.1001C14.2857 16.1001 16.5748 13.8111 16.5748 10.9974C16.5748 8.18375 14.2857 5.89473 11.4721 5.89473Z" fill="#9FE066"/>
<path d="M11.4728 11.6318H8.28525C7.93464 11.6318 7.65039 11.3475 7.65039 10.9969C7.65039 10.6463 7.93464 10.3621 8.28525 10.3621H10.8379V8.95127C10.8379 8.60066 11.1222 8.31641 11.4728 8.31641C11.8234 8.31641 12.1076 8.60066 12.1076 8.95127V10.9969C12.1077 11.3475 11.8234 11.6318 11.4728 11.6318Z" fill="#394949"/>
<path d="M12.1075 10.9969V8.95127C12.1075 8.60066 11.8233 8.31641 11.4727 8.31641V11.6318C11.8233 11.6318 12.1075 11.3475 12.1075 10.9969Z" fill="#151F1F"/>
<path d="M16.5753 10.9974C16.5753 13.8111 14.2863 16.1001 11.4727 16.1001V17.3698C14.9865 17.3698 17.8451 14.5112 17.8451 10.9974C17.8451 7.48366 14.9864 4.625 11.4727 4.625V5.89473C14.2863 5.89473 16.5753 8.18379 16.5753 10.9974Z" fill="#4ACA7B"/>
<path d="M18.6832 3.78752C16.7572 1.86147 14.1963 0.800781 11.4725 0.800781C8.74869 0.800781 6.18782 1.86147 4.26177 3.78752C2.67775 5.37158 1.67966 7.38516 1.37492 9.56545L1.08378 9.2743C0.835882 9.02641 0.433887 9.02641 0.185951 9.2743C-0.0619838 9.52219 -0.0619838 9.92419 0.185951 10.1721L1.46097 11.4471C1.58494 11.5711 1.74742 11.6331 1.90986 11.6331C2.0723 11.6331 2.23482 11.5711 2.35875 11.4471L3.63377 10.1721C3.8817 9.92423 3.8817 9.52224 3.63377 9.2743C3.38587 9.02641 2.98388 9.02641 2.73594 9.2743L2.70678 9.30346C3.50083 5.18845 7.12907 2.07051 11.4725 2.07051C16.3953 2.07051 20.4003 6.07548 20.4003 10.9983C20.4003 15.921 16.3953 19.926 11.4725 19.926C7.46868 19.926 3.9294 17.234 2.86558 13.3794C2.77234 13.0413 2.42266 12.8429 2.08474 12.9363C1.74674 13.0295 1.54837 13.3792 1.64165 13.7171C2.22378 15.8264 3.50315 17.7286 5.24408 19.0732C7.04184 20.4618 9.19555 21.1957 11.4725 21.1957C14.1963 21.1957 16.7571 20.135 18.6832 18.209C20.6093 16.2829 21.67 13.7221 21.67 10.9983C21.67 8.27439 20.6093 5.71361 18.6832 3.78752Z" fill="#FF4D5B"/>
<path d="M20.4004 10.9983C20.4004 15.9211 16.3955 19.926 11.4727 19.926V21.1958C14.1965 21.1958 16.7573 20.135 18.6834 18.209C20.6095 16.2829 21.6702 13.7221 21.6702 10.9983C21.6702 8.27439 20.6094 5.71361 18.6834 3.78752C16.7573 1.86147 14.1965 0.800781 11.4727 0.800781V2.07051C16.3955 2.07051 20.4004 6.07548 20.4004 10.9983Z" fill="#DE0062"/>
</g>
<defs>
<clipPath id="clip0_8194_10048">
<rect width="21.67" height="21.67" fill="white" transform="translate(0 0.164062)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,17 @@
<svg width="30" height="19" viewBox="0 0 30 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M29.9999 14.9414L9.72644 11.4258L14.9999 18.457H29.9999V14.9414Z" fill="#FFB54C"/>
<path d="M0 14.9414V18.457H15V11.4258L0 14.9414Z" fill="#FFCC4A"/>
<path d="M30.0002 14.9404V7.03027H27.7883L26.9094 7.90918L26.0305 7.03027H23.8186L22.9397 7.90918L22.0608 7.03027H19.8489L18.97 7.90918L18.0911 7.03027H15.8792L11.4846 10.9854L15.0002 14.9404H30.0002Z" fill="#FFCC4A"/>
<path d="M15 7.03027H14.1211H11.9092L11.0303 7.90918L10.1514 7.03027H7.93945L7.06055 7.90918L6.18164 7.03027H3.96973L3.09082 7.90918L2.21191 7.03027H0V14.9404H15V7.03027Z" fill="#FFE278"/>
<path d="M29.1212 1.75781H15.0001L14.1212 2.63672L15.0001 3.51562H29.1212V1.75781Z" fill="#ABD5ED"/>
<path d="M15 1.75781H1.75781V0H0V5.27344H1.75781V3.51562H15V1.75781Z" fill="#BFEBFF"/>
<path d="M28.2423 0H30.0001V5.27344H28.2423V0Z" fill="#ABD5ED"/>
<path d="M2.21191 7.03076H3.96973V11.4253H2.21191V7.03076Z" fill="#587AA1"/>
<path d="M6.18152 7.03076H7.93933V9.66748H6.18152V7.03076Z" fill="#587AA1"/>
<path d="M10.1516 7.03076H11.9094V11.4253H10.1516V7.03076Z" fill="#587AA1"/>
<path d="M15.8787 9.66699H14.9998L14.5603 9.22754V7.46973L14.9998 7.03027H15.8787V9.66699Z" fill="#455F80"/>
<path d="M14.1212 7.03027H15.0001V9.66699H14.1212V7.03027Z" fill="#587AA1"/>
<path d="M18.0907 7.03027H19.8485V11.4248H18.0907V7.03027Z" fill="#455F80"/>
<path d="M22.0603 7.03027H23.8181V9.66699H22.0603V7.03027Z" fill="#455F80"/>
<path d="M26.0304 7.03027H27.7882V11.4248H26.0304V7.03027Z" fill="#455F80"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,17 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8194_10048)">
<path d="M11.4732 16.7316C8.31096 16.7316 5.73828 14.1589 5.73828 10.9967C5.73828 7.8344 8.31096 5.26172 11.4732 5.26172C14.6355 5.26172 17.2081 7.8344 17.2081 10.9967C17.2081 14.1589 14.6355 16.7316 11.4732 16.7316Z" fill="#EBF6FF"/>
<path d="M17.2076 10.9967C17.2076 7.8344 14.6349 5.26172 11.4727 5.26172V16.7316C14.6349 16.7316 17.2076 14.1589 17.2076 10.9967Z" fill="#D7E7F8"/>
<path d="M11.4721 17.3699C7.95827 17.3699 5.09961 14.5112 5.09961 10.9974C5.09961 7.48362 7.95827 4.625 11.472 4.625C14.9858 4.625 17.8445 7.48366 17.8445 10.9974C17.8445 14.5112 14.9858 17.3699 11.4721 17.3699ZM11.4721 5.89473C8.6584 5.89473 6.36934 8.18379 6.36934 10.9974C6.36934 13.811 8.6584 16.1001 11.472 16.1001C14.2857 16.1001 16.5748 13.8111 16.5748 10.9974C16.5748 8.18375 14.2857 5.89473 11.4721 5.89473Z" fill="#9FE066"/>
<path d="M11.4728 11.6318H8.28525C7.93464 11.6318 7.65039 11.3475 7.65039 10.9969C7.65039 10.6463 7.93464 10.3621 8.28525 10.3621H10.8379V8.95127C10.8379 8.60066 11.1222 8.31641 11.4728 8.31641C11.8234 8.31641 12.1076 8.60066 12.1076 8.95127V10.9969C12.1077 11.3475 11.8234 11.6318 11.4728 11.6318Z" fill="#394949"/>
<path d="M12.1075 10.9969V8.95127C12.1075 8.60066 11.8233 8.31641 11.4727 8.31641V11.6318C11.8233 11.6318 12.1075 11.3475 12.1075 10.9969Z" fill="#151F1F"/>
<path d="M16.5753 10.9974C16.5753 13.8111 14.2863 16.1001 11.4727 16.1001V17.3698C14.9865 17.3698 17.8451 14.5112 17.8451 10.9974C17.8451 7.48366 14.9864 4.625 11.4727 4.625V5.89473C14.2863 5.89473 16.5753 8.18379 16.5753 10.9974Z" fill="#4ACA7B"/>
<path d="M18.6832 3.78752C16.7572 1.86147 14.1963 0.800781 11.4725 0.800781C8.74869 0.800781 6.18782 1.86147 4.26177 3.78752C2.67775 5.37158 1.67966 7.38516 1.37492 9.56545L1.08378 9.2743C0.835882 9.02641 0.433887 9.02641 0.185951 9.2743C-0.0619838 9.52219 -0.0619838 9.92419 0.185951 10.1721L1.46097 11.4471C1.58494 11.5711 1.74742 11.6331 1.90986 11.6331C2.0723 11.6331 2.23482 11.5711 2.35875 11.4471L3.63377 10.1721C3.8817 9.92423 3.8817 9.52224 3.63377 9.2743C3.38587 9.02641 2.98388 9.02641 2.73594 9.2743L2.70678 9.30346C3.50083 5.18845 7.12907 2.07051 11.4725 2.07051C16.3953 2.07051 20.4003 6.07548 20.4003 10.9983C20.4003 15.921 16.3953 19.926 11.4725 19.926C7.46868 19.926 3.9294 17.234 2.86558 13.3794C2.77234 13.0413 2.42266 12.8429 2.08474 12.9363C1.74674 13.0295 1.54837 13.3792 1.64165 13.7171C2.22378 15.8264 3.50315 17.7286 5.24408 19.0732C7.04184 20.4618 9.19555 21.1957 11.4725 21.1957C14.1963 21.1957 16.7571 20.135 18.6832 18.209C20.6093 16.2829 21.67 13.7221 21.67 10.9983C21.67 8.27439 20.6093 5.71361 18.6832 3.78752Z" fill="#FF4D5B"/>
<path d="M20.4004 10.9983C20.4004 15.9211 16.3955 19.926 11.4727 19.926V21.1958C14.1965 21.1958 16.7573 20.135 18.6834 18.209C20.6095 16.2829 21.6702 13.7221 21.6702 10.9983C21.6702 8.27439 20.6094 5.71361 18.6834 3.78752C16.7573 1.86147 14.1965 0.800781 11.4727 0.800781V2.07051C16.3955 2.07051 20.4004 6.07548 20.4004 10.9983Z" fill="#DE0062"/>
</g>
<defs>
<clipPath id="clip0_8194_10048">
<rect width="21.67" height="21.67" fill="white" transform="translate(0 0.164062)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,17 @@
<svg width="22" height="14" viewBox="0 0 22 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.6663 11.1257L7.02441 8.58667L10.833 13.6648H21.6663V11.1257Z" fill="#FFB54C"/>
<path d="M0 11.1257V13.6648H10.8333V8.58667L0 11.1257Z" fill="#FFCC4A"/>
<path d="M21.6663 11.1257V5.41284H20.0688L19.4341 6.04761L18.7993 5.41284H17.2018L16.5671 6.04761L15.9323 5.41284H14.3348L13.7 6.04761L13.0653 5.41284H11.4678L8.29395 8.26929L10.833 11.1257H21.6663Z" fill="#FFCC4A"/>
<path d="M10.8333 5.41284H10.1986H8.60107L7.96631 6.04761L7.33154 5.41284H5.73405L5.09928 6.04761L4.46452 5.41284H2.86702L2.23226 6.04761L1.59749 5.41284H0V11.1257H10.8333V5.41284Z" fill="#FFE278"/>
<path d="M21.0316 1.60449H10.833L10.1982 2.23926L10.833 2.87402H21.0316V1.60449Z" fill="#ABD5ED"/>
<path d="M10.8333 1.60449H1.26953V0.334961H0V4.14355H1.26953V2.87402H10.8333V1.60449Z" fill="#BFEBFF"/>
<path d="M20.3965 0.334961H21.666V4.14355H20.3965V0.334961Z" fill="#ABD5ED"/>
<path d="M1.59766 5.41284H2.86719V8.58667H1.59766V5.41284Z" fill="#587AA1"/>
<path d="M4.46484 5.41284H5.73438V7.31714H4.46484V5.41284Z" fill="#587AA1"/>
<path d="M7.33203 5.41284H8.60156V8.58667H7.33203V5.41284Z" fill="#587AA1"/>
<path d="M11.4678 7.31714H10.833L10.5156 6.99976V5.73022L10.833 5.41284H11.4678V7.31714Z" fill="#455F80"/>
<path d="M10.1982 5.41284H10.833V7.31714H10.1982V5.41284Z" fill="#587AA1"/>
<path d="M13.0654 5.41284H14.335V8.58667H13.0654V5.41284Z" fill="#455F80"/>
<path d="M15.9326 5.41284H17.2021V7.31714H15.9326V5.41284Z" fill="#455F80"/>
<path d="M18.7998 5.41284H20.0693V8.58667H18.7998V5.41284Z" fill="#455F80"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

13
assets/icons/dyi.svg Normal file
View File

@ -0,0 +1,13 @@
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.6477 18.1286L14.5695 16.9625L14.5381 16.5231L16.7995 14.2617L17.2592 14.2729L18.4253 15.351L18.531 15.6845L16.0777 18.1378L15.6477 18.1286Z" fill="#9DE4FB"/>
<path d="M21.0627 1.25136C21.36 0.954133 21.36 0.467791 21.0627 0.170566C20.5522 -0.0791971 19.9499 -0.0533175 19.4627 0.239367L17.8536 1.206C16.9222 1.76553 16.4706 2.86478 16.7228 3.92175C16.9226 4.75917 16.6735 5.64059 16.0645 6.24964L16.6364 6.30048C17.2244 5.86531 17.9823 5.71853 18.7089 5.88914C19.131 5.98821 19.5596 5.97283 19.9571 5.85876L20.2488 5.31134L19.4473 4.50975C19.3068 4.36927 19.226 4.18001 19.2217 3.98137L19.21 3.44029C19.2055 3.23013 19.287 3.02719 19.4356 2.8785L21.0627 1.25136Z" fill="#9DE4FB"/>
<path d="M6.73692 15.5776C5.0442 17.2704 3.21412 15.8824 1.26475 17.8318C0.124481 18.972 -0.210539 20.6126 0.259592 22.0469C0.259836 22.0463 0.26008 22.0458 0.260276 22.0453L0.554425 22.3394C1.20913 22.5533 1.91218 22.4551 2.61679 22.3364L2.69584 22.0944L2.3972 21.7957C2.26219 21.6607 2.18631 21.4776 2.18631 21.2866V20.2244C2.18631 20.0335 2.26219 19.8504 2.3972 19.7154L3.1483 18.9643C3.28331 18.8292 3.46647 18.7534 3.65739 18.7534H4.71958C4.91055 18.7534 5.09366 18.8292 5.22868 18.9642L5.52644 19.262L5.92421 19.0998C6.02919 18.4761 5.98173 17.3544 6.61944 16.3753L6.73692 15.5776Z" fill="#9DE4FB"/>
<path d="M24.7746 3.88015C24.4774 3.58292 23.9911 3.58292 23.6938 3.88015L22.0483 5.5257C21.9105 5.66345 21.7257 5.74397 21.531 5.751L21.0555 5.76814C20.8416 5.77585 20.6341 5.69426 20.4827 5.54289L20.2504 5.31065C19.7111 5.63151 19.0563 5.74455 18.4163 5.59431C17.5859 5.39938 16.7146 5.61887 16.1028 6.20975C16.0904 6.22274 16.0788 6.23627 16.066 6.24901C15.861 6.45405 6.762 15.553 6.73842 15.5766C6.72137 15.5937 6.70399 15.6096 6.68675 15.626C5.67012 16.6895 5.75328 18.0817 5.63155 18.8046C5.60572 18.958 5.5709 19.1104 5.52793 19.261L5.98122 19.7143C6.11623 19.8493 6.19211 20.0325 6.19211 20.2234V21.2856C6.19211 21.4765 6.11623 21.6597 5.98122 21.7947L5.23012 22.5458C5.09511 22.6808 4.91195 22.7567 4.72102 22.7567H3.65884C3.46786 22.7567 3.28475 22.6808 3.14974 22.5458L2.69729 22.0933C1.90097 22.3186 1.04929 22.3015 0.261719 22.0442C0.463043 22.6591 0.811197 23.2365 1.30853 23.72C2.87869 25.2466 5.40669 25.2743 7.008 23.7803C9.10421 21.8246 7.64269 19.9312 9.36784 18.206C9.3922 18.1817 18.4983 9.0756 18.7037 8.87018C19.3169 8.25708 20.2038 8.02787 21.048 8.22602C22.096 8.47202 23.184 8.01327 23.7391 7.08932L24.7057 5.48024C24.9985 4.99297 25.0244 4.39066 24.7746 3.88015Z" fill="#7BD9EC"/>
<path d="M7.84826 17.0949C7.70162 16.9482 7.70162 16.7105 7.84826 16.5639L17.1039 7.30818C17.2505 7.1616 17.4883 7.1616 17.6349 7.30818C17.7816 7.45487 17.7816 7.69257 17.6349 7.83925L8.37928 17.0949C8.23259 17.2416 7.99489 17.2415 7.84826 17.0949Z" fill="#9DE4FB"/>
<path d="M15.6484 18.1282L18.4261 15.3506L24.5753 21.0359C25.1252 21.5442 25.1421 22.4078 24.6126 22.9373L23.2352 24.3147C22.7057 24.8442 21.8421 24.8273 21.3338 24.2774L15.6484 18.1282Z" fill="#F9BC66"/>
<path d="M14.5721 16.9625L17.2618 14.2729L7.34683 5.10596L5.40527 7.04756L14.5721 16.9625Z" fill="#43B5C3"/>
<path d="M1.59863 8.09863L3.72729 5.96998L5.7503 7.99299L3.62165 10.1216L1.59863 8.09863Z" fill="#43B5C3"/>
<path d="M9.69327 2.70391C9.56329 2.50937 9.41045 2.32582 9.23437 2.15736L7.91231 0.892578L7.6668 0.914844C6.58571 1.58352 6.19688 2.19393 3.02331 5.30428C2.76827 5.55931 2.76827 5.9728 3.02331 6.22784L5.59853 8.80306C5.84185 9.04637 6.23639 9.04637 6.47971 8.80306L9.11616 6.1666C9.56646 5.7163 9.73868 5.06438 9.59102 4.44492C9.45323 3.86669 9.50674 3.4134 9.68766 3.03946C9.71652 2.9798 9.69327 2.70391 9.69327 2.70391Z" fill="#9DE4FB"/>
<path d="M12.4915 1.11902C11.0321 -0.0662658 9.32021 -0.113826 7.66602 0.915305L9.10219 2.28927C9.33872 2.51555 9.5333 2.76907 9.68692 3.03988C10.1761 2.00879 11.5877 1.66479 12.3709 1.55175C12.5824 1.52123 12.6575 1.25374 12.4915 1.11902Z" fill="#7BD9EC"/>
<path d="M0.996513 7.33135L0.189263 8.1386C-0.0630877 8.39095 -0.0630877 8.8001 0.189263 9.05245L2.75301 11.6162C3.00536 11.8685 3.4145 11.8685 3.66685 11.6162L4.4741 10.8089C4.72645 10.5566 4.72645 10.1474 4.4741 9.8951L1.91036 7.33135C1.65801 7.079 1.24886 7.079 0.996513 7.33135Z" fill="#7BD9EC"/>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,15 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5419 20.2424C11.1182 19.3486 10.0545 18.9678 9.16647 19.3935L1.38334 23.1268C0.591819 23.3098 0 24.0197 0 24.8727V33.8466C0 34.8381 0.797668 35.6413 1.78229 35.6413C2.76668 35.6413 3.56412 34.8381 3.56412 33.8466V27.6644L9.16647 30.3516C9.41376 30.4704 9.67449 30.5264 9.93112 30.5264C10.5974 30.5264 11.2359 30.1484 11.5419 29.5025C11.9643 28.6076 11.5875 27.5367 10.699 27.1103L6.03295 24.8725L10.699 22.6346C11.5877 22.2085 11.9643 21.1376 11.5419 20.2424Z" fill="#D5D5D5"/>
<path d="M20.6084 17.6894C20.8655 17.6894 21.1257 17.6334 21.3737 17.5146L32.0481 12.3951C32.9366 11.9685 33.3141 10.8974 32.891 10.0024C32.4682 9.10864 31.4052 8.72813 30.5156 9.15359L19.8408 14.2736C18.9522 14.6999 18.5754 15.7706 18.998 16.6658C19.3038 17.3112 19.9423 17.6894 20.6084 17.6894Z" fill="#D5D5D5"/>
<path d="M42.7227 7.27445L48.1841 4.65449V10.9114C48.1841 11.9027 48.9818 12.7061 49.9659 12.7061C50.9503 12.7061 51.7478 11.9027 51.7478 10.9114V4.62192L57.2779 7.27445C57.5259 7.39303 57.7862 7.44922 58.0433 7.44922C58.7091 7.44922 59.3478 7.07124 59.6534 6.42537C60.0763 5.53041 59.6994 4.45953 58.8106 4.03316L50.7663 0.174427C50.2813 -0.0581424 49.7189 -0.0581424 49.2338 0.174427L41.19 4.03316C40.3015 4.45953 39.9244 5.53018 40.3472 6.42537C40.771 7.32101 41.8362 7.70198 42.7227 7.27445Z" fill="#D5D5D5"/>
<path d="M67.9533 12.3944L78.6281 17.5146C78.875 17.6334 79.1361 17.6894 79.3932 17.6894C80.059 17.6894 80.6978 17.3114 81.0034 16.6655C81.426 15.7706 81.0494 14.6997 80.1606 14.2733L69.4856 9.1529C68.5982 8.72721 67.5345 9.10726 67.1105 10.0018C66.6875 10.8967 67.0645 11.9676 67.9533 12.3944Z" fill="#D5D5D5"/>
<path d="M81.539 34.8099C82.4275 34.3837 82.8046 33.3128 82.3815 32.4177C81.9587 31.5232 80.8946 31.1424 80.0065 31.5695L73.167 34.8509L51.7477 24.577V16.5765C51.7477 15.5846 50.9503 14.7818 49.9659 14.7818C48.9817 14.7818 48.1841 15.5848 48.1841 16.5765V24.6096L26.8346 34.85L20.6999 31.9073C19.8093 31.481 18.7482 31.8612 18.3244 32.7564C17.9016 33.6514 18.2787 34.7225 19.1672 35.1489L25.8031 38.3319V61.6684L19.0593 64.9031C18.1707 65.3295 17.7939 66.4001 18.2165 67.2955C18.5221 67.9412 19.1606 68.3192 19.8266 68.3192C20.0837 68.3192 20.3447 68.2632 20.5917 68.1444L26.8349 65.1499L48.1841 75.3903V81.5075C48.1841 82.4993 48.9817 83.3022 49.9659 83.3022C50.9503 83.3022 51.7477 82.499 51.7477 81.5075V75.4233L73.1657 65.1501L79.6524 68.2616C79.9002 68.3802 80.1607 68.4364 80.4175 68.4364C81.0834 68.4364 81.7221 68.0584 82.0277 67.4125C82.4508 66.5175 82.0735 65.4467 81.1849 65.0201L74.1977 61.6687V38.3319L81.539 34.8099ZM70.634 62.3879L51.7479 71.4467V49.0994L70.634 40.0402V62.3879ZM29.4788 61.8939C29.4472 61.8269 29.4053 61.7691 29.3668 61.7081V40.0404L48.1841 49.0663V71.4141L29.6409 62.5198C29.6239 62.3086 29.5745 62.0964 29.4788 61.8939ZM50.0003 27.7151L69.0207 36.8383L50.0003 45.9611L30.9799 36.8383L50.0003 27.7151Z" fill="#D5D5D5"/>
<path d="M78.6271 82.486L67.9525 87.6062C67.0639 88.0328 66.6864 89.1036 67.1095 89.9979C67.4153 90.644 68.054 91.0215 68.7199 91.0215C68.9767 91.0215 69.2379 90.9656 69.485 90.8477L80.1598 85.7273C81.0483 85.3009 81.4252 84.2295 81.0025 83.3346C80.579 82.4401 79.5149 82.0616 78.6271 82.486Z" fill="#D5D5D5"/>
<path d="M57.2782 92.7266L51.748 95.3793V88.227C51.748 87.2357 50.9506 86.4323 49.9662 86.4323C48.982 86.4323 48.1844 87.2357 48.1844 88.227V95.3468L42.723 92.7266C41.8335 92.3023 40.7713 92.6807 40.3475 93.5759C39.9246 94.4709 40.3015 95.5413 41.1903 95.9676L49.2346 99.8259C49.4769 99.9417 49.7387 100 50.0008 100C50.2629 100 50.5248 99.9417 50.7671 99.8259L58.8114 95.9676C59.6999 95.5413 60.077 94.4709 59.6541 93.5759C59.2304 92.6807 58.166 92.3032 57.2782 92.7266Z" fill="#D5D5D5"/>
<path d="M32.0476 87.6061L21.3728 82.4859C20.4863 82.0605 19.4217 82.4394 18.9975 83.3343C18.5749 84.2293 18.9517 85.3006 19.8403 85.727L30.5153 90.8474C30.7622 90.9653 31.0233 91.0213 31.2802 91.0213C31.946 91.0213 32.5847 90.6438 32.8903 89.9977C33.3132 89.1036 32.9361 88.0328 32.0476 87.6061Z" fill="#D5D5D5"/>
<path d="M11.5419 70.4974C11.1182 69.6029 10.0545 69.224 9.16647 69.6488L3.56412 72.3355V65.6178C3.56412 64.6265 2.76668 63.823 1.78229 63.823C0.797668 63.823 0 64.6265 0 65.6178V74.5919C0 74.8162 0.0457694 75.0284 0.120686 75.2263C0.156892 75.8784 0.53193 76.4651 1.12215 76.7486L9.16647 80.6073C9.41376 80.7254 9.67449 80.7818 9.93112 80.7818C10.5974 80.7818 11.2359 80.4038 11.5419 79.7582C11.9643 78.8632 11.5875 77.7924 10.699 77.3655L6.03295 75.1281L10.699 72.8903C11.5877 72.4637 11.9643 71.3923 11.5419 70.4974Z" fill="#D5D5D5"/>
<path d="M1.78229 56.8226C2.76668 56.8226 3.56412 56.0193 3.56412 55.0274V44.4374C3.56412 43.4461 2.76668 42.6427 1.78229 42.6427C0.797668 42.6427 0 43.4461 0 44.4374V55.0274C0.00022771 56.0193 0.797896 56.8226 1.78229 56.8226Z" fill="#D5D5D5"/>
<path d="M98.6173 23.1268L90.8342 19.3935C89.9443 18.9667 88.8825 19.3479 88.4589 20.2424C88.0363 21.1378 88.4132 22.2084 89.3017 22.6351L93.9677 24.8729L89.3017 27.1108C88.4132 27.5371 88.0363 28.6078 88.4589 29.503C88.7645 30.1488 89.4032 30.5268 90.0691 30.5268C90.3262 30.5268 90.5873 30.4709 90.8342 30.3521L96.4365 27.6649V33.847C96.4365 34.8385 97.234 35.6418 98.2184 35.6418C99.2027 35.6418 100 34.8385 100 33.847V24.8731C100 24.0197 99.4088 23.3098 98.6173 23.1268Z" fill="#D5D5D5"/>
<path d="M98.2184 42.642C97.2337 42.642 96.4365 43.4455 96.4365 44.4367V55.0267C96.4365 56.0187 97.234 56.8214 98.2184 56.8214C99.2027 56.8214 100 56.0184 100 55.0267V44.4367C100 43.4455 99.203 42.642 98.2184 42.642Z" fill="#D5D5D5"/>
<path d="M98.2184 63.8228C97.2337 63.8228 96.4365 64.6263 96.4365 65.6175V72.3352L90.8342 69.6485C89.9443 69.2231 88.8825 69.6022 88.4589 70.4971C88.0363 71.3921 88.4132 72.4634 89.3017 72.8898L93.9677 75.1277L89.3017 77.3651C88.4132 77.7919 88.0363 78.8628 88.4589 79.7577C88.7645 80.4034 89.4032 80.7814 90.0691 80.7814C90.3262 80.7814 90.5873 80.7249 90.8342 80.6068L98.8785 76.7481C99.4687 76.4646 99.8438 75.8779 99.88 75.2258C99.9546 75.0279 100 74.8157 100 74.5914V65.6173C100 64.6263 99.203 63.8228 98.2184 63.8228Z" fill="#D5D5D5"/>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,22 @@
<svg width="38" height="40" viewBox="0 0 38 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 0C18.3528 0 17.8281 0.524531 17.8281 1.17188V5.85938C17.8281 6.50656 18.3528 7.03125 19 7.03125C19.6472 7.03125 20.1719 6.50656 20.1719 5.85938V1.17188C20.1719 0.524531 19.6472 0 19 0Z" fill="#596C76"/>
<path d="M20.1719 5.85938V1.17188C20.1719 0.524531 19.6472 0 19 0V7.03125C19.6472 7.03125 20.1719 6.50656 20.1719 5.85938Z" fill="#3B4A51"/>
<path d="M30.7188 4.6875H19H7.28125C5.34266 4.6875 3.76562 6.26453 3.76562 8.20312V13.0469C3.76562 14.9855 5.34266 16.5625 7.28125 16.5625H19H30.7188C32.6573 16.5625 34.2344 14.9855 34.2344 13.0469V8.20312C34.2344 6.26453 32.6573 4.6875 30.7188 4.6875Z" fill="#596C76"/>
<path d="M34.2344 13.0469V8.20312C34.2344 6.26453 32.6573 4.6875 30.7188 4.6875H19V16.5625H30.7188C32.6573 16.5625 34.2344 14.9855 34.2344 13.0469Z" fill="#3B4A51"/>
<path d="M28.375 0H19H9.625C8.97727 0 8.45312 0.524141 8.45312 1.17188C8.45312 1.81961 8.97727 2.34375 9.625 2.34375H19H28.375C29.0227 2.34375 29.5469 1.81961 29.5469 1.17188C29.5469 0.524141 29.0227 0 28.375 0Z" fill="#596C76"/>
<path d="M29.5469 1.17188C29.5469 0.524141 29.0227 0 28.375 0H19V2.34375H28.375C29.0227 2.34375 29.5469 1.81961 29.5469 1.17188Z" fill="#3B4A51"/>
<path d="M19 35.3125C24.5046 35.3125 29.6315 33.1096 33.4344 29.1087C33.8808 28.6395 33.8613 27.8979 33.3933 27.4516C32.9229 27.0053 32.1825 27.0247 31.7361 27.4928C28.3796 31.0244 23.8557 32.9688 19 32.9688C14.1443 32.9688 9.62037 31.0244 6.26388 27.4928C5.81873 27.0247 5.07716 27.0053 4.60677 27.4516C4.13873 27.8979 4.11927 28.6395 4.5656 29.1087C8.36841 33.1096 13.4954 35.3125 19 35.3125Z" fill="#D5E8FE"/>
<path d="M19 30.6253C23.0203 30.6253 26.8152 29.0677 29.6853 26.2399C30.1465 25.7867 30.1511 25.044 29.6967 24.5828C29.2447 24.1227 28.5031 24.1182 28.0396 24.5714C25.6112 26.9632 22.4001 28.2816 19 28.2816C15.5999 28.2816 12.3887 26.9632 9.96031 24.5714C9.49679 24.1148 8.75523 24.1217 8.3032 24.5828C7.8489 25.044 7.85343 25.7867 8.31461 26.2399C11.1848 29.0677 14.9797 30.6253 19 30.6253Z" fill="#D5E8FE"/>
<path d="M19 25.9377C21.5223 25.9377 23.9667 25.0291 25.8813 23.3788C26.3712 22.9554 26.4261 22.2161 26.0037 21.7252C25.578 21.233 24.8399 21.1816 24.3501 21.6027C22.8612 22.8868 20.9305 23.5287 19 23.5287C17.0695 23.5287 15.1387 22.8867 13.6499 21.6027C13.1578 21.1816 12.4185 21.2331 11.9962 21.7252C11.574 22.2161 11.6289 22.9554 12.1187 23.3788C14.0333 25.0291 16.4777 25.9377 19 25.9377Z" fill="#D5E8FE"/>
<path d="M16.1687 20.52C17.0316 20.9973 18.0112 21.2502 19 21.2502C19.9887 21.2502 20.9683 20.9973 21.8312 20.52C22.3977 20.2064 22.6026 19.4934 22.289 18.927C21.9754 18.3605 21.259 18.1545 20.6959 18.4692C20.1798 18.7553 19.5898 18.8984 18.9999 18.8984C18.41 18.8984 17.82 18.7553 17.3039 18.4692C16.7386 18.1545 16.0233 18.3605 15.7109 18.927C15.3974 19.4935 15.6023 20.2065 16.1687 20.52Z" fill="#D5E8FE"/>
<path d="M37.0897 30.324C36.6113 29.8903 35.8709 29.92 35.4337 30.3984C31.2177 35.0104 25.2279 37.6563 19 37.6563C12.7721 37.6563 6.78226 35.0104 2.56624 30.3985C2.12906 29.9201 1.38867 29.8904 0.910306 30.3241C0.433119 30.7613 0.399916 31.5017 0.835931 31.98C5.49593 37.0772 12.1164 40 19 40C25.8836 40 32.5041 37.0772 37.1641 31.98C37.6001 31.5017 37.5669 30.7612 37.0897 30.324Z" fill="#D5E8FE"/>
<path d="M37.0897 30.324C36.6113 29.8903 35.8709 29.92 35.4338 30.3984C31.2177 35.0104 25.2279 37.6563 19 37.6563V40C25.8836 40 32.5041 37.0772 37.1641 31.98C37.6001 31.5017 37.5669 30.7612 37.0897 30.324Z" fill="#B5DBFF"/>
<path d="M33.3932 27.4516C32.9228 27.0053 32.1824 27.0247 31.7361 27.4928C28.3796 31.0244 23.8557 32.9688 19 32.9688V35.3125C24.5046 35.3125 29.6316 33.1096 33.4345 29.1087C33.8808 28.6395 33.8613 27.8979 33.3932 27.4516Z" fill="#B5DBFF"/>
<path d="M29.6968 24.5826C29.2448 24.1225 28.5032 24.118 28.0397 24.5712C25.6113 26.963 22.4001 28.2813 19 28.2813V30.6251C23.0203 30.6251 26.8152 29.0675 29.6853 26.2397C30.1466 25.7865 30.1511 25.0438 29.6968 24.5826Z" fill="#B5DBFF"/>
<path d="M26.0038 21.7252C25.578 21.233 24.8399 21.1816 24.3501 21.6027C22.8612 22.8868 20.9305 23.5287 19 23.5287V25.9377C21.5223 25.9377 23.9667 25.0291 25.8813 23.3788C26.3712 22.9554 26.4261 22.2161 26.0038 21.7252Z" fill="#B5DBFF"/>
<path d="M22.2891 18.927C21.9755 18.3605 21.2591 18.1545 20.696 18.4692C20.1799 18.7553 19.5899 18.8984 19 18.8984V21.2501C19.9887 21.2501 20.9684 20.9972 21.8312 20.5199C22.3977 20.2064 22.6026 19.4934 22.2891 18.927Z" fill="#B5DBFF"/>
<path d="M14.3125 11.7969C14.9597 11.7969 15.4844 11.2722 15.4844 10.625C15.4844 9.97779 14.9597 9.45312 14.3125 9.45312C13.6653 9.45312 13.1406 9.97779 13.1406 10.625C13.1406 11.2722 13.6653 11.7969 14.3125 11.7969Z" fill="#EDF5FF"/>
<path d="M23.6875 11.7969C24.3347 11.7969 24.8594 11.2722 24.8594 10.625C24.8594 9.97779 24.3347 9.45312 23.6875 9.45312C23.0403 9.45312 22.5156 9.97779 22.5156 10.625C22.5156 11.2722 23.0403 11.7969 23.6875 11.7969Z" fill="#51FAFF"/>
<path d="M19 11.7969C19.6472 11.7969 20.1719 11.2722 20.1719 10.625C20.1719 9.97779 19.6472 9.45312 19 9.45312C18.3528 9.45312 17.8281 9.97779 17.8281 10.625C17.8281 11.2722 18.3528 11.7969 19 11.7969Z" fill="#EDF5FF"/>
<path d="M20.1719 10.625C20.1719 9.97766 19.6472 9.45312 19 9.45312V11.7969C19.6472 11.7969 20.1719 11.2722 20.1719 10.625Z" fill="#D5E8FE"/>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,13 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8194_10065)">
<path d="M17.6069 21.8341H4.06313C1.81893 21.8341 0 20.0151 0 17.7709V4.22719C0 1.98299 1.81893 0.164062 4.06313 0.164062H17.6069C19.8511 0.164062 21.67 1.98299 21.67 4.22719V17.7709C21.67 20.0151 19.8511 21.8341 17.6069 21.8341Z" fill="#E3F8FA"/>
<path d="M15.1312 7.18375L10.955 5.60387C10.8771 5.57475 10.7925 5.57475 10.7153 5.60387L6.53904 7.18375C6.40767 7.23386 6.32031 7.35982 6.32031 7.50067V9.30605C6.32031 9.41711 6.37516 9.5214 6.46591 9.58438C6.55868 9.64736 6.67516 9.6609 6.77877 9.6223L10.8351 8.08779L14.8915 9.62298C14.9301 9.6372 14.9707 9.64465 15.0113 9.64465C15.0791 9.64465 15.1461 9.62433 15.2043 9.58438C15.2958 9.5214 15.3499 9.41711 15.3499 9.30605V7.5C15.3499 7.35914 15.2626 7.23318 15.1312 7.18375Z" fill="#8CE1EB"/>
<path d="M15.1312 13.9572L10.955 12.3773C10.8771 12.3482 10.7925 12.3482 10.7153 12.3773L6.53904 13.9572C6.40767 14.0073 6.32031 14.1333 6.32031 14.2741V16.0795C6.32031 16.1906 6.37516 16.2948 6.46591 16.3578C6.55868 16.4215 6.67516 16.435 6.77877 16.3957L10.8351 14.8612L14.8915 16.3964C14.9301 16.4106 14.9707 16.4181 15.0113 16.4181C15.0791 16.4181 15.1461 16.3978 15.2043 16.3578C15.2958 16.2948 15.3499 16.1906 15.3499 16.0795V14.2734C15.3499 14.1326 15.2626 14.0066 15.1312 13.9572Z" fill="#26C6DA"/>
<path d="M15.1312 10.5705L10.955 8.99059C10.8771 8.96147 10.7925 8.96147 10.7153 8.99059L6.53904 10.5705C6.40767 10.6206 6.32031 10.7465 6.32031 10.8874V12.6928C6.32031 12.8038 6.37516 12.9081 6.46591 12.9711C6.55868 13.0348 6.67516 13.0483 6.77877 13.009L10.8351 11.4745L14.8915 13.0097C14.9301 13.0239 14.9707 13.0314 15.0113 13.0314C15.0791 13.0314 15.1461 13.0111 15.2043 12.9711C15.2958 12.9081 15.3499 12.8038 15.3499 12.6928V10.8867C15.3499 10.7459 15.2626 10.6199 15.1312 10.5705Z" fill="#26C6DA"/>
</g>
<defs>
<clipPath id="clip0_8194_10065">
<rect width="21.67" height="21.67" fill="white" transform="translate(0 0.164062)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,23 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8194_10077)">
<path d="M17.6 18.673C17.3521 18.4251 17.3521 18.0231 17.6 17.7752C19.4054 15.9698 20.3996 13.5678 20.3996 11.0115C20.3996 8.45525 19.4054 6.05318 17.6 4.24784C17.3521 3.99994 17.3521 3.59795 17.6 3.35001C17.8479 3.10208 18.2499 3.10208 18.4978 3.35001C20.543 5.39516 21.6694 8.11606 21.6694 11.0115C21.6694 13.9069 20.543 16.6278 18.4978 18.673C18.2503 18.9205 17.8484 18.9213 17.6 18.673Z" fill="#7AFFE4"/>
<path d="M15.6781 16.7502C15.4302 16.5023 15.4302 16.1003 15.6781 15.8524C16.9704 14.5602 17.6821 12.8408 17.6821 11.011C17.6821 9.18128 16.9705 7.46194 15.6781 6.1697C15.4302 5.92176 15.4302 5.51981 15.6781 5.27187C15.926 5.02398 16.328 5.02394 16.576 5.27187C18.1081 6.80393 18.9519 8.84213 18.9519 11.0111C18.9519 13.18 18.1081 15.2182 16.576 16.7503C16.3279 16.9982 15.926 16.9981 15.6781 16.7502Z" fill="#00DDC1"/>
<path d="M13.7543 14.8285C13.5064 14.5805 13.5064 14.1785 13.7543 13.9306C14.5331 13.152 14.9619 12.1158 14.9619 11.0131C14.9619 9.91034 14.5331 8.87416 13.7543 8.09548C13.5064 7.84758 13.5064 7.44559 13.7543 7.19765C14.0022 6.94976 14.4042 6.94972 14.6521 7.19765C15.6707 8.21619 16.2317 9.5712 16.2317 11.0131C16.2317 12.455 15.6707 13.81 14.6521 14.8285C14.4042 15.0764 14.0022 15.0763 13.7543 14.8285Z" fill="#7AFFE4"/>
<path d="M17.6 18.6732C17.8484 18.9216 18.2503 18.9207 18.4978 18.6732C20.543 16.6281 21.6694 13.9072 21.6694 11.0117H20.3996C20.3996 13.568 19.4054 15.97 17.6 17.7754C17.3521 18.0233 17.3521 18.4253 17.6 18.6732Z" fill="#00DDC1"/>
<path d="M15.6781 16.7509C15.926 16.9988 16.3279 16.9989 16.5759 16.7509C18.1081 15.2189 18.9518 13.1807 18.9518 11.0117H17.6821C17.6821 12.8415 16.9704 14.5608 15.6781 15.8531C15.4302 16.101 15.4302 16.503 15.6781 16.7509Z" fill="#00B4BC"/>
<path d="M13.7543 14.8272C14.0022 15.0751 14.4041 15.0751 14.6521 14.8272C15.6707 13.8086 16.2316 12.4536 16.2316 11.0117H14.9619C14.9619 12.1144 14.533 13.1506 13.7543 13.9293C13.5064 14.1772 13.5064 14.5792 13.7543 14.8272Z" fill="#00DDC1"/>
<path d="M3.17152 18.673C1.12633 16.6278 0 13.9069 0 11.0115C0 8.11604 1.12633 5.39515 3.17152 3.35C3.41946 3.10206 3.82141 3.10211 4.06935 3.35C4.31728 3.59793 4.31728 3.99989 4.06935 4.24782C2.26396 6.05316 1.26973 8.45523 1.26973 11.0115C1.26973 13.5677 2.26396 15.9698 4.06935 17.7751C4.31728 18.023 4.31728 18.425 4.06935 18.673C3.82141 18.921 3.41937 18.9209 3.17152 18.673Z" fill="#7AFFE4"/>
<path d="M5.09462 16.7503C3.56253 15.2182 2.71875 13.18 2.71875 11.0111C2.71875 8.84212 3.56253 6.80391 5.09466 5.27186C5.3426 5.02396 5.74459 5.02396 5.99249 5.27186C6.24038 5.51979 6.24038 5.92175 5.99249 6.16968C4.70016 7.46197 3.98848 9.1813 3.98848 11.0111C3.98848 12.8408 4.70016 14.5602 5.99249 15.8524C6.24042 16.1003 6.24042 16.5023 5.99249 16.7502C5.74489 16.9978 5.34294 16.9985 5.09462 16.7503Z" fill="#00DDC1"/>
<path d="M7.01704 14.8285C5.99847 13.81 5.4375 12.455 5.4375 11.0131C5.4375 9.5712 5.99847 8.21619 7.01704 7.19765C7.26498 6.94972 7.66697 6.94976 7.91486 7.19765C8.1628 7.44559 8.16276 7.84758 7.91486 8.09548C7.1361 8.87416 6.70723 9.91034 6.70723 11.0131C6.70723 12.1158 7.1361 13.152 7.91486 13.9306C8.1628 14.1785 8.1628 14.5805 7.91486 14.8285C7.66727 15.0761 7.26531 15.0768 7.01704 14.8285Z" fill="#7AFFE4"/>
<path d="M4.06935 18.6732C4.31728 18.4253 4.31728 18.0233 4.06935 17.7754C2.26396 15.97 1.26973 13.568 1.26973 11.0117H0C0 13.9072 1.12633 16.6281 3.17152 18.6732C3.41937 18.9211 3.82141 18.9212 4.06935 18.6732Z" fill="#00DDC1"/>
<path d="M5.99249 16.7509C6.24038 16.5029 6.24038 16.101 5.99249 15.8531C4.70016 14.5609 3.98848 12.8415 3.98848 11.0117H2.71875C2.71875 13.1807 3.56253 15.2189 5.09466 16.7509C5.34294 16.9992 5.74489 16.9985 5.99249 16.7509Z" fill="#00B4BC"/>
<path d="M7.91486 14.8271C8.1628 14.5792 8.16276 14.1772 7.91486 13.9293C7.1361 13.1506 6.70723 12.1144 6.70723 11.0117H5.4375C5.4375 12.4536 5.99846 13.8086 7.01704 14.8272C7.26527 15.0754 7.66722 15.0747 7.91486 14.8271Z" fill="#00DDC1"/>
<path d="M10.835 13.6857C12.3123 13.6857 13.5099 12.4881 13.5099 11.0108C13.5099 9.53353 12.3123 8.33594 10.835 8.33594C9.35775 8.33594 8.16016 9.53353 8.16016 11.0108C8.16016 12.4881 9.35775 13.6857 10.835 13.6857Z" fill="#00DDC1"/>
<path d="M10.835 13.6866C12.31 13.6866 13.5099 12.4866 13.5099 11.0117H8.16016C8.16016 12.4867 9.36009 13.6866 10.835 13.6866Z" fill="#00B4BC"/>
</g>
<defs>
<clipPath id="clip0_8194_10077">
<rect width="21.67" height="21.67" fill="white" transform="translate(0 0.164062)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,4 @@
<svg width="23" height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.0539 4.23654C21.4826 6.07144 22.3331 8.37817 22.3331 10.8834C22.3331 16.8663 17.4827 21.7167 11.4998 21.7167L10.2744 20.2302L11.4998 18.829C15.8882 18.829 19.4454 15.2717 19.4454 10.8834C19.4454 9.17629 18.9075 7.59487 17.9909 6.29953L11.4998 12.7906L10.5337 11.1112L11.4998 8.97612L16.0837 4.39227C14.7883 3.47567 13.2069 2.93781 11.4998 2.93781L10.2744 1.33418L11.4998 0.0500488C14.005 0.0500488 16.3118 0.900635 18.1467 2.32928L20.4115 0.0500488L22.3331 1.94165L20.0539 4.23654Z" fill="#66B3FF"/>
<path d="M3.55475 10.8834C3.55475 12.5905 4.09261 14.1719 5.00921 15.4672L11.5003 8.97612V12.7906L6.91647 17.3745C8.21182 18.2911 9.79323 18.829 11.5003 18.829V21.7167C8.99512 21.7167 6.68838 20.8661 4.85348 19.4375L2.57214 21.7167L0.666992 19.8116L2.94622 17.5302C1.51758 15.6953 0.666992 13.3886 0.666992 10.8834C0.666992 4.9005 5.51745 0.0500488 11.5003 0.0500488V2.93781C7.11198 2.93781 3.55475 6.49504 3.55475 10.8834Z" fill="#80D4FF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,18 @@
<svg width="47" height="37" viewBox="0 0 47 37" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="6" y="1" width="41" height="25" rx="12.5" fill="#E9E9E9"/>
<g filter="url(#filter0_d_6419_4507)">
<circle cx="18.5" cy="13.5" r="10.5" fill="white"/>
</g>
<defs>
<filter id="filter0_d_6419_4507" x="0" y="0" width="37" height="37" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="4"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_6419_4507"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_6419_4507" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 965 B

39
assets/icons/office.svg Normal file
View File

@ -0,0 +1,39 @@
<svg width="25" height="23" viewBox="0 0 25 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.9152 9.49653V6.93262H17.4302C17.2913 6.93262 17.1787 7.04521 17.1787 7.18413V9.49653H23.9152Z" fill="#FED402"/>
<path d="M23.7237 6.88413H18.3818L18.2641 6.93296H17.4302C17.2913 6.93296 17.1787 7.04556 17.1787 7.18447V8.19053H23.9152V6.93296L23.7514 6.88135C23.7422 6.88257 23.7332 6.88413 23.7237 6.88413Z" fill="#FE6C55"/>
<path d="M10.4375 6.52441H11.9465V8.08906H10.4375V6.52441Z" fill="#918291"/>
<path d="M13.959 9.49687V8.79409C13.959 8.37739 13.6212 8.03955 13.2044 8.03955H9.18032C8.76362 8.03955 8.42578 8.37734 8.42578 8.79409V9.49687H13.959Z" fill="#A79BA7"/>
<path d="M10.0266 9.448V8.79409C10.0266 8.37739 10.3644 8.03955 10.7812 8.03955H9.18032C8.76362 8.03955 8.42578 8.37734 8.42578 8.79409V9.448H10.0266Z" fill="#918291"/>
<path d="M15.7282 6.20679H6.65918C6.52437 6.20679 6.41504 6.09746 6.41504 5.96265V0.610352C6.41504 0.475537 6.52437 0.366211 6.65918 0.366211H15.7282C15.863 0.366211 15.9724 0.475537 15.9724 0.610352V5.96265C15.9724 6.09751 15.8631 6.20679 15.7282 6.20679Z" fill="#EAF6FF"/>
<path d="M8.4271 5.95527V0.617725C8.4271 0.478809 8.5397 0.366211 8.67861 0.366211H6.66655C6.52764 0.366211 6.41504 0.478809 6.41504 0.617725V5.95532C6.41504 6.09424 6.52764 6.20684 6.66655 6.20684H8.67861C8.5397 6.20679 8.4271 6.09419 8.4271 5.95527Z" fill="#D8ECFE"/>
<path d="M15.718 6.573H6.66362C6.323 6.573 6.0459 6.2959 6.0459 5.95527V0.617724C6.0459 0.2771 6.323 0 6.66362 0H15.7253C16.0619 0 16.3356 0.273779 16.3356 0.610351V5.95527C16.3357 6.2959 16.0585 6.573 15.718 6.573ZM6.77832 5.84058H15.6032V0.732422H6.77832V5.84058Z" fill="#A79BA7"/>
<path d="M1.88359 8.06533V7.69912H1.2311C1.01699 7.69912 0.842773 7.52495 0.842773 7.31079V6.80776C0.842773 6.59365 1.01694 6.41943 1.2311 6.41943H1.88355V5.68701H1.2311C0.613135 5.68701 0.110352 6.1898 0.110352 6.80776V7.31079C0.110352 7.92876 0.613086 8.43154 1.2311 8.43154H1.92603C1.89858 8.31377 1.88359 8.19131 1.88359 8.06533Z" fill="#EAF6FF"/>
<path d="M2.65684 9.49746H4.33486C4.82593 9.20913 5.15581 8.67593 5.15581 8.06533V5.93115C5.15581 5.79634 5.04648 5.68701 4.91167 5.68701H1.83594V8.06533C1.83594 8.67593 2.16582 9.20913 2.65684 9.49746Z" fill="#EAF6FF"/>
<path d="M2.57842 9.44863H3.83784C3.3896 9.15146 3.09346 8.64341 3.09346 8.06533V5.68701H1.83594V8.06533C1.83594 8.64282 2.13101 9.15127 2.57842 9.44863Z" fill="#D8ECFE"/>
<path d="M17.1787 8.19141H19.6977V9.44897H17.1787V8.19141Z" fill="#FAC600"/>
<path d="M19.9492 6.93262H17.4302C17.2913 6.93262 17.1787 7.04521 17.1787 7.18413V8.19019H19.6977V7.18413C19.6977 7.04521 19.8103 6.93262 19.9492 6.93262Z" fill="#FD544D"/>
<path d="M24.7477 6.93384H18.2627V5.92778C18.2627 5.78887 18.3753 5.67627 18.5142 5.67627H24.7477C24.8866 5.67627 24.9992 5.78887 24.9992 5.92778V6.68232C24.9992 6.82124 24.8866 6.93384 24.7477 6.93384Z" fill="#00C27A"/>
<path d="M20.6018 5.67627H18.5142C18.3753 5.67627 18.2627 5.78887 18.2627 5.92778V6.93384H20.3502V5.92778C20.3502 5.78887 20.4629 5.67627 20.6018 5.67627Z" fill="#09A755"/>
<path d="M2.26367 10.7251H14.0313V15.6865H2.26367V10.7251Z" fill="#FFBD86"/>
<path d="M2.31348 10.7734H3.56406V15.686H2.31348V10.7734Z" fill="#F6A96C"/>
<path d="M13.9854 10.7241V13.5457L14.1291 13.5945H22.5894L22.7364 13.5457V10.7241H13.9854Z" fill="#EA9B58"/>
<path d="M13.9854 10.7729H15.5196V13.5457H13.9854V10.7729Z" fill="#D88A55"/>
<path d="M18.9885 12.519H17.6807C17.4784 12.519 17.3145 12.3551 17.3145 12.1528C17.3145 11.9506 17.4784 11.7866 17.6807 11.7866H18.9885C19.1908 11.7866 19.3547 11.9506 19.3547 12.1528C19.3547 12.3551 19.1908 12.519 18.9885 12.519Z" fill="#D88A55"/>
<path d="M13.9854 13.5464V16.3191L14.0939 16.3679H22.6279L22.7364 16.3191V13.5464H13.9854Z" fill="#F6A96C"/>
<path d="M13.9854 13.5464H15.5196V16.3191H13.9854V13.5464Z" fill="#EA9B58"/>
<path d="M18.9885 15.291H17.6807C17.4784 15.291 17.3145 15.1271 17.3145 14.9248C17.3145 14.7226 17.4784 14.5586 17.6807 14.5586H18.9885C19.1908 14.5586 19.3547 14.7226 19.3547 14.9248C19.3547 15.1271 19.1908 15.291 18.9885 15.291Z" fill="#D88A55"/>
<path d="M22.7364 16.3188H13.9854V19.7856C13.9854 19.9245 14.0979 20.0371 14.2369 20.0371H22.7364V16.3188Z" fill="#EA9B58"/>
<path d="M15.5196 19.7856V16.3188H13.9854V19.7856C13.9854 19.9245 14.0979 20.0371 14.2369 20.0371H15.7711C15.6322 20.0371 15.5196 19.9245 15.5196 19.7856Z" fill="#D88A55"/>
<path d="M18.9885 18.064H17.6807C17.4784 18.064 17.3145 17.9 17.3145 17.6978C17.3145 17.4955 17.4784 17.3315 17.6807 17.3315H18.9885C19.1908 17.3315 19.3547 17.4955 19.3547 17.6978C19.3547 17.9 19.1908 18.064 18.9885 18.064Z" fill="#D88A55"/>
<path d="M0.804688 10.7251V21.773C0.804688 21.912 0.917285 22.0246 1.0562 22.0246H2.06226C2.20117 22.0246 2.31377 21.912 2.31377 21.773V10.7251H0.804688Z" fill="#A79BA7"/>
<path d="M1.4647 21.773V10.7251H0.804688V21.773C0.804688 21.912 0.917285 22.0246 1.0562 22.0246H1.71621C1.5773 22.0246 1.4647 21.912 1.4647 21.773Z" fill="#918291"/>
<path d="M22.6875 10.7251V21.773C22.6875 21.912 22.8001 22.0246 22.939 22.0246H23.9451C24.084 22.0246 24.1966 21.912 24.1966 21.773V10.7251H22.6875Z" fill="#A79BA7"/>
<path d="M23.3475 21.773V10.7251H22.6875V21.773C22.6875 21.912 22.8001 22.0246 22.939 22.0246H23.599C23.4601 22.0246 23.3475 21.912 23.3475 21.773Z" fill="#918291"/>
<path d="M24.7485 9.44873H0.251514C0.112598 9.44873 0 9.56133 0 9.70024V10.522C0 10.6609 0.112598 10.7735 0.251514 10.7735H24.7485C24.8874 10.7735 25 10.6609 25 10.522V9.70024C25 9.56133 24.8874 9.44873 24.7485 9.44873Z" fill="#F6A96C"/>
<path d="M3.41797 10.522V9.70024C3.41797 9.56133 3.53057 9.44873 3.66948 9.44873H0.251514C0.112598 9.44873 0 9.56133 0 9.70024V10.522C0 10.6609 0.112598 10.7735 0.251514 10.7735H3.66948C3.53057 10.7735 3.41797 10.6609 3.41797 10.522Z" fill="#EA9B58"/>
<path d="M14.3078 2.30615H10.5352C10.3329 2.30615 10.1689 2.14219 10.1689 1.93994C10.1689 1.7377 10.3329 1.57373 10.5352 1.57373H14.3078C14.5101 1.57373 14.674 1.7377 14.674 1.93994C14.674 2.14219 14.5101 2.30615 14.3078 2.30615Z" fill="#0593FC"/>
<path d="M9.37915 2.30566H8.07129C7.86904 2.30566 7.70508 2.1417 7.70508 1.93945C7.70508 1.73721 7.86904 1.57324 8.07129 1.57324H9.37915C9.5814 1.57324 9.74536 1.73721 9.74536 1.93945C9.74536 2.1417 9.5814 2.30566 9.37915 2.30566Z" fill="#0593FC"/>
<path d="M14.3078 3.61475H13.1006C12.8983 3.61475 12.7344 3.45078 12.7344 3.24854C12.7344 3.04629 12.8983 2.88232 13.1006 2.88232H14.3078C14.5101 2.88232 14.674 3.04629 14.674 3.24854C14.674 3.45078 14.5101 3.61475 14.3078 3.61475Z" fill="#0593FC"/>
<path d="M11.7936 3.61426H8.07129C7.86904 3.61426 7.70508 3.45029 7.70508 3.24805C7.70508 3.0458 7.86904 2.88184 8.07129 2.88184H11.7936C11.9959 2.88184 12.1598 3.0458 12.1598 3.24805C12.1598 3.45029 11.9959 3.61426 11.7936 3.61426Z" fill="#0593FC"/>
<path d="M10.2846 4.92236H8.07129C7.86904 4.92236 7.70508 4.7584 7.70508 4.55615C7.70508 4.35391 7.86904 4.18994 8.07129 4.18994H10.2846C10.4868 4.18994 10.6508 4.35391 10.6508 4.55615C10.6508 4.7584 10.4868 4.92236 10.2846 4.92236Z" fill="#0593FC"/>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

29
assets/icons/parlour.svg Normal file
View File

@ -0,0 +1,29 @@
<svg width="25" height="22" viewBox="0 0 25 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.05824 9.95946C8.90674 9.92645 8.73888 9.90869 8.55508 9.90869H3.02024C2.03877 9.90869 1.51074 10.4155 1.51074 11.0408V14.9798L9.56141 15.483L9.05824 9.95946Z" fill="#D273B3"/>
<path d="M10.0646 11.0403C10.0646 10.5321 9.71578 10.1022 9.05824 9.95898V14.602C9.05824 14.8104 8.88928 14.9793 8.68087 14.9793H4.02658C4.02658 14.4711 3.58802 14.0412 2.93048 13.898V14.9793H1.51074V16.659H10.5677C10.5677 16.659 10.0646 11.6656 10.0646 11.0403Z" fill="#CA59A6"/>
<path d="M18.1152 5.37996L17.6121 0H1.88812C1.67971 0 1.51074 0.168963 1.51074 0.377375V5.37996H18.1152Z" fill="#FFE07D"/>
<path d="M17.6104 0V5.37996H18.1135L18.6167 1.5095V0.377375C18.6167 0.168963 18.4477 0 18.2393 0H17.6104Z" fill="#FFC250"/>
<path d="M17.6121 2.07861C16.0781 2.99101 15.0219 3.81972 15.0219 3.81972C15.0219 3.81972 13.1458 2.57202 11.989 2.57202C9.76353 2.57202 8.06293 5.37954 1.51074 5.37954V5.88271L18.1152 6.38587L17.6121 2.07861Z" fill="#FFF0AF"/>
<path d="M17.2347 5.88339H1.51074V6.51235C1.51074 6.72076 1.67971 6.88973 1.88812 6.88973H18.241C18.4495 6.88973 18.6184 6.72076 18.6184 6.51235V1.50977C18.2658 1.69886 17.929 1.89081 17.6121 2.07935V5.50607C17.6121 5.71443 17.4431 5.88339 17.2347 5.88339Z" fill="#FFE07D"/>
<path d="M17.611 9.95946C17.4595 9.92645 17.2916 9.90869 17.1078 9.90869H11.573C10.5915 9.90869 10.0635 10.4155 10.0635 11.0408V14.9798L18.1141 15.483L17.611 9.95946Z" fill="#D273B3"/>
<path d="M17.611 9.95898V14.602C17.611 14.8104 17.442 14.9793 17.2336 14.9793H10.0635V16.659H18.6173C18.6173 16.659 18.6173 11.6656 18.6173 11.0403C18.6173 10.5321 18.2685 10.1022 17.611 9.95898Z" fill="#CA59A6"/>
<path d="M16.1014 16.489L14.5836 15.9858H10.9613C10.3775 15.9858 10.0635 16.2873 10.0635 16.6592V16.9922L18.1147 17.4953L16.1014 16.489Z" fill="#DA8BC1"/>
<path d="M16.1015 16.4888V16.6146C16.1015 16.823 15.9325 16.9919 15.7241 16.9919H10.0635V18.5014H18.6173V16.4888H16.1015Z" fill="#D273B3"/>
<path d="M9.0573 15.9858H4.02563L3.52246 17.4953H9.56046L9.0573 15.9858Z" fill="#DA8BC1"/>
<path d="M10.0646 16.6592C10.0646 16.2873 9.7505 15.9858 9.16678 15.9858H9.05824V16.6148C9.05824 16.8232 8.88928 16.9922 8.68087 16.9922H4.02658V15.9858H1.51074V18.5017H10.5677C10.5677 18.5017 10.0646 17.0311 10.0646 16.6592Z" fill="#D273B3"/>
<path d="M19.1203 12.9785C18.9688 12.9455 18.801 12.9277 18.6172 12.9277C17.6357 12.9277 17.1077 13.4346 17.1077 14.0599V18.2504H3.019L2.01267 12.9785C1.86116 12.9455 1.69331 12.9277 1.5095 12.9277C0.528023 12.9277 0 13.4346 0 14.0599V19.5084L19.6235 20.0115L19.1203 12.9785Z" fill="#DA8BC1"/>
<path d="M3.02001 18.25C3.02001 18.25 3.02001 14.6847 3.02001 14.0594C3.02001 13.5512 2.67121 13.1212 2.01367 12.978V17.9984L3.02001 18.25Z" fill="#DA8BC1"/>
<path d="M19.1203 12.978V19.1305C19.1203 19.3389 18.9514 19.5079 18.743 19.5079H0V20.1368C0 20.3452 0.168963 20.5142 0.377375 20.5142H19.7493C19.9577 20.5142 20.1267 20.3452 20.1267 20.1368V14.0594C20.1267 13.5512 19.7779 13.1212 19.1203 12.978Z" fill="#D273B3"/>
<path d="M10.2412 20.0115C8.73172 20.0115 6.03877 20.0115 4.52927 20.0115C3.01977 20.0115 2.5166 19.4172 2.5166 19.0051C2.5166 18.7272 2.74187 18.502 3.01977 18.502H11.7507C12.0286 18.502 12.2539 18.7272 12.2539 19.0051C12.2539 19.4172 11.7507 20.0115 10.2412 20.0115Z" fill="#D273B3"/>
<path d="M20.1267 18.25H14.4951C15.2643 19.2151 16.9145 19.8487 18.8263 19.8487C19.277 19.8487 19.7132 19.8116 20.1267 19.7422V18.25Z" fill="#D273B3"/>
<path d="M3.90931 18.1172L2.92104 21.2378C2.85809 21.4365 2.96819 21.6486 3.16689 21.7115C3.36559 21.7745 3.57767 21.6644 3.64057 21.4657L4.62884 18.345L3.90931 18.1172Z" fill="#DCE6EB"/>
<path d="M9.13379 18.345L10.1221 21.4657C10.185 21.6644 10.3971 21.7744 10.5957 21.7115C10.7944 21.6486 10.9045 21.4365 10.8416 21.2378L9.85332 18.1172L9.13379 18.345Z" fill="#DCE6EB"/>
<path d="M11.2477 17.4956H2.51684C2.23894 17.4956 2.01367 17.7209 2.01367 17.9988C2.01367 18.0778 2.03234 18.1635 2.07289 18.2504C2.07289 18.2504 7.89574 18.6026 9.38607 18.6026C10.8955 18.6026 11.2477 17.4956 11.2477 17.4956Z" fill="#E0BBA4"/>
<path d="M11.2481 17.4956C11.2481 17.4956 10.8959 18.2504 9.38642 18.2504C7.89609 18.2504 3.63402 18.2504 2.07324 18.2504C2.24412 18.6168 2.80656 19.0051 4.02669 19.0051H9.73859C9.73859 19.0051 11.7513 18.4108 11.7513 17.9988C11.7513 17.7209 11.526 17.4956 11.2481 17.4956Z" fill="#CF9875"/>
<path d="M15.9337 18.1172L14.9455 21.2378C14.8825 21.4365 14.9926 21.6486 15.1913 21.7115C15.39 21.7745 15.6021 21.6644 15.665 21.4657L16.6533 18.345L15.9337 18.1172Z" fill="#DCE6EB"/>
<path d="M21.2432 17.5306L22.4893 21.4653C22.5522 21.664 22.7643 21.774 22.9629 21.7111C23.1616 21.6482 23.2717 21.4361 23.2088 21.2374L21.9627 17.3027L21.2432 17.5306Z" fill="#DCE6EB"/>
<path d="M21.3791 16.4893L23.786 7.40723C23.2671 7.46846 22.8111 7.79472 22.5903 8.27755L19.6694 14.6637C19.3009 15.4694 18.4963 15.9862 17.6104 15.9862L21.3791 16.4893Z" fill="#FFE07D"/>
<path d="M24.2456 7.39551H23.9652C23.9054 7.39551 23.8465 7.39994 23.7881 7.40683L20.6881 14.1845C20.3144 15.0017 20.1277 15.4717 19.4238 15.9857L21.3812 16.4889L24.7274 7.56985C24.5968 7.46117 24.4291 7.39551 24.2456 7.39551Z" fill="#FFC250"/>
<path d="M21.4367 17.4869C22.9619 16.5631 24.1083 13.6303 24.1083 8.9209L21.4815 14.6639C21.113 15.4697 20.3084 15.9864 19.4224 15.9864C19.0923 15.9864 17.611 15.9864 17.611 15.9864H14.583C13.9515 15.9864 13.5979 16.7167 13.9916 17.2106C14.5624 17.7568 16.1091 18.3398 18.0209 18.3398C19.3581 18.3398 20.5673 18.0134 21.4367 17.4869Z" fill="#E0BBA4"/>
<path d="M24.7265 7.56982L24.1089 8.92017C23.7576 13.438 22.4593 16.0592 20.9341 16.983C20.0648 17.5095 18.8555 17.8359 17.5183 17.8359C15.6065 17.8359 14.4859 17.4952 13.9922 17.2099C14.7613 18.175 16.4116 18.8423 18.3234 18.8423C19.6606 18.8423 20.8699 18.5158 21.7392 17.9893C23.4525 16.9516 24.8794 13.7722 24.9994 8.16859C25.0045 7.92828 24.8974 7.71212 24.7265 7.56982Z" fill="#CF9875"/>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,3 @@
<svg width="17" height="8" viewBox="0 0 17 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.1551 2.33183C15.4564 2.0013 15.6902 1.64372 15.8445 1.26438C15.9791 0.93308 15.7945 0.564752 15.4321 0.441634C15.0698 0.318517 14.6666 0.487195 14.5319 0.818495C14.2555 1.49824 13.533 2.13013 12.4974 2.59786C11.3781 3.10342 9.9584 3.38183 8.50002 3.38183C7.04165 3.38183 5.62204 3.10342 4.50267 2.59786C3.4671 2.13017 2.74455 1.49829 2.46811 0.818581C2.33341 0.487323 1.93051 0.318601 1.56797 0.441762C1.20557 0.56488 1.02099 0.933251 1.15569 1.26455C1.30993 1.64384 1.54371 2.00138 1.84496 2.33187L0.205067 3.83074C-0.0683557 4.08065 -0.0683557 4.48579 0.205067 4.73569C0.341779 4.86065 0.520918 4.9231 0.700103 4.9231C0.879288 4.9231 1.05847 4.86065 1.19514 4.73569L2.87865 3.19694C3.33414 3.49453 3.85618 3.75417 4.43008 3.96875L3.77375 6.02617C3.66551 6.36545 3.87875 6.72068 4.24993 6.81961C4.31534 6.83706 4.38129 6.84533 4.44619 6.84533C4.74941 6.84533 5.02883 6.66386 5.11798 6.38439L5.76259 4.36365C6.40253 4.50861 7.08297 4.60375 7.78919 4.64214V6.76146C7.78919 7.11486 8.10266 7.40137 8.48931 7.40137C8.87597 7.40137 9.18944 7.11486 9.18944 6.76146V4.64338C9.90329 4.60575 10.5911 4.51011 11.2375 4.3637L11.8821 6.38443C11.9713 6.6639 12.2507 6.84538 12.5539 6.84538C12.6188 6.84538 12.6848 6.83706 12.7502 6.81965C13.1214 6.72072 13.3346 6.36549 13.2263 6.02621L12.57 3.96879C13.1438 3.75421 13.6659 3.49458 14.1214 3.19698L15.8049 4.73574C15.9416 4.86069 16.1207 4.92314 16.2999 4.92314C16.479 4.92314 16.6582 4.86065 16.7949 4.73574C17.0684 4.48583 17.0684 4.08069 16.7949 3.83078L15.1551 2.33183Z" fill="#D5D5D5"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,3 @@
<svg width="15" height="13" viewBox="0 0 15 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.6809 10.3829C14.394 10.5298 14.0409 10.4175 13.8928 10.1291H13.8928C12.9943 8.37829 10.609 5.86828 7.49997 5.86828C4.71173 5.86828 2.23389 7.93348 1.10719 10.1291C0.958976 10.4164 0.606008 10.5299 0.318459 10.3821C0.0309393 10.2344 -0.0828497 9.88216 0.0644257 9.5944C1.35894 7.06664 4.20568 4.69641 7.49997 4.69641C11.257 4.69641 13.9478 7.6657 14.9355 9.5944C15.083 9.88245 14.969 10.2355 14.6809 10.3829ZM0.227668 4.08996L1.53267 5.26723C1.77437 5.48528 2.14474 5.46346 2.36022 5.22463C2.57695 4.98434 2.55791 4.61385 2.31762 4.39708L1.01262 3.21981C0.772414 3.00311 0.401926 3.02209 0.18507 3.26241C-0.0316681 3.5027 -0.0126251 3.87319 0.227668 4.08996ZM13.4672 5.26723L14.7722 4.08996C15.0125 3.87319 15.0316 3.5027 14.8148 3.26241C14.598 3.02215 14.2276 3.00305 13.9873 3.21981L12.6823 4.39708C12.442 4.61382 12.423 4.98434 12.6397 5.22463C12.8554 5.46372 13.2258 5.48502 13.4672 5.26723ZM7.49994 2.93127C7.82356 2.93127 8.08588 2.66892 8.08588 2.34533V0.585937C8.08588 0.262354 7.82356 0 7.49994 0C7.17633 0 6.914 0.262354 6.914 0.585937V2.34533C6.91403 2.66895 7.17636 2.93127 7.49994 2.93127ZM10.3784 9.86136C10.3784 11.4509 9.0871 12.7441 7.49997 12.7441C5.91284 12.7441 4.62158 11.4509 4.62158 9.86136C4.62158 8.2718 5.91284 6.97857 7.49997 6.97857C9.0871 6.97857 10.3784 8.2718 10.3784 9.86136ZM9.20651 9.86136C9.20651 8.91797 8.44099 8.15045 7.5 8.15045C6.55901 8.15045 5.79346 8.91797 5.79346 9.86136C5.79346 10.8047 6.55899 11.5723 7.49997 11.5723C8.44096 11.5723 9.20651 10.8047 9.20651 9.86136Z" fill="#D5D5D5"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,18 @@
<svg width="23" height="20" viewBox="0 0 23 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5833 1.84497L1.22267 16.046C0.0476544 17.6566 1.198 19.9198 3.19166 19.9198H19.975C21.9687 19.9198 23.119 17.6566 21.944 16.046L11.5833 1.84497Z" fill="#F1FAFF"/>
<path d="M21.9431 16.0448L11.5833 1.84497L9.81055 4.27486L18.3975 16.0448C19.5729 17.6558 18.4222 19.9198 16.4279 19.9198H19.9735C21.9678 19.9198 23.1185 17.6559 21.9431 16.0448Z" fill="#C7EEFB"/>
<path d="M13.6602 6.1864H9.51926C8.38838 6.1864 7.47168 5.26966 7.47168 4.13882V2.24846C7.47168 2.13162 7.56643 2.03687 7.68327 2.03687H15.4963C15.6131 2.03687 15.7079 2.13162 15.7079 2.24846V4.13882C15.7079 5.26966 14.7911 6.1864 13.6602 6.1864Z" fill="#E0DDE2"/>
<path d="M15.498 2.03687H14.3393V2.76335C14.3393 3.89681 13.4204 4.81567 12.287 4.81567H8.15546C7.94886 4.81567 7.74959 4.78482 7.56152 4.72807C7.81628 5.57186 8.59934 6.18645 9.52624 6.18645H13.6578C14.7912 6.18645 15.7101 5.26759 15.7101 4.13413V2.24892C15.7101 2.13183 15.6151 2.03687 15.498 2.03687Z" fill="#C8C1C9"/>
<path d="M17.0524 2.78679H6.12858C6.01174 2.78679 5.91699 2.69204 5.91699 2.5752V0.544844C5.91699 0.428003 6.01174 0.333252 6.12858 0.333252H17.0524C17.1692 0.333252 17.264 0.428003 17.264 0.544844V2.5752C17.264 2.69208 17.1693 2.78679 17.0524 2.78679Z" fill="#E0DDE2"/>
<path d="M17.0519 0.333252H15.8129V1.12359C15.8129 1.24073 15.7179 1.33569 15.6008 1.33569H5.91699V2.57473C5.91699 2.69187 6.01195 2.78684 6.12909 2.78684H17.0519C17.1691 2.78684 17.264 2.69187 17.264 2.57473V0.545352C17.264 0.428215 17.1691 0.333252 17.0519 0.333252Z" fill="#C8C1C9"/>
<path d="M11.591 4.95259C11.891 4.95259 12.1342 4.7094 12.1342 4.4094C12.1342 4.10941 11.891 3.86621 11.591 3.86621C11.291 3.86621 11.0479 4.10941 11.0479 4.4094C11.0479 4.7094 11.291 4.95259 11.591 4.95259Z" fill="#FA2A3B"/>
<path d="M11.4636 10.3904C12.0045 10.3904 12.4429 9.95199 12.4429 9.41116C12.4429 8.87032 12.0045 8.43188 11.4636 8.43188C10.9228 8.43188 10.4844 8.87032 10.4844 9.41116C10.4844 9.95199 10.9228 10.3904 11.4636 10.3904Z" fill="#62D8F9"/>
<path d="M11.4638 8.43213C11.3942 8.43213 11.3262 8.43953 11.2607 8.45333C11.7041 8.54685 12.0369 8.94019 12.0369 9.4114C12.0369 9.88261 11.7041 10.276 11.2607 10.3695C11.3263 10.3833 11.3942 10.3907 11.4638 10.3907C12.0046 10.3907 12.4431 9.95222 12.4431 9.4114C12.4431 8.87058 12.0047 8.43213 11.4638 8.43213Z" fill="#00BEF7"/>
<path d="M14.8717 13.5145L13.1586 13.236L12.2278 11.4381C12.1444 11.2501 12.0134 10.9926 11.7241 10.9064L10.637 10.5802C10.5178 10.5512 10.4031 10.5405 10.1997 10.5725L7.88145 11.1109C7.74264 11.1432 7.61865 11.2211 7.5294 11.3322L6.29163 12.8728C6.07157 13.1467 6.1152 13.5471 6.38913 13.7672C6.50661 13.8617 6.64736 13.9075 6.78718 13.9075C6.97338 13.9075 7.15789 13.8262 7.28357 13.6697L8.3836 12.3006L9.47165 12.0479L8.83273 14.1772C8.82045 14.213 8.81652 14.2593 8.79896 14.3605L8.43849 16.9193L6.75734 18.3779C6.49192 18.6082 6.46344 19.0101 6.69374 19.2755C6.81959 19.4205 6.99657 19.4948 7.1746 19.4948C7.32238 19.4948 7.47087 19.4435 7.59127 19.3391L9.45227 17.7244C9.56826 17.6238 9.64393 17.4847 9.66534 17.3326L9.96009 15.2404L9.99932 15.2522L11.5919 17.1109L12.5347 19.1578C12.642 19.3907 12.8723 19.528 13.113 19.528C13.202 19.528 13.2925 19.5092 13.3787 19.4695C13.6979 19.3225 13.8374 18.9446 13.6905 18.6254L12.7106 16.4981C12.686 16.4446 12.6542 16.3949 12.6159 16.3503L11.2825 14.7941L11.7411 13.2658L12.1757 14.1053C12.2683 14.2841 12.44 14.4085 12.6386 14.4408L14.6674 14.7706C14.702 14.7762 14.7364 14.7789 14.7703 14.7789C15.0767 14.7789 15.3468 14.5569 15.3975 14.2447C15.4539 13.8978 15.2185 13.5709 14.8717 13.5145Z" fill="#62D8F9"/>
<path d="M9.74707 10.6776C9.95045 10.6457 10.0645 10.6586 10.1838 10.6876L11.2709 11.0138C11.5602 11.1 11.6911 11.3574 11.7745 11.5454L12.8085 13.5537C12.835 13.6052 12.8845 13.6409 12.9417 13.6497L15.395 14.0282C15.3479 13.7709 15.1447 13.5589 14.8718 13.5145L13.1588 13.236L12.2279 11.4381C12.1445 11.2501 12.0135 10.9926 11.7242 10.9064L10.6372 10.5802C10.5179 10.5512 10.4032 10.5405 10.1998 10.5725L9.74707 10.6776Z" fill="#00BEF7"/>
<path d="M12.7115 16.498C12.6869 16.4446 12.655 16.3948 12.6167 16.3502L11.2833 14.794L11.7419 13.266L11.6837 13.1536C11.6079 13.0072 11.3924 13.0273 11.345 13.1852L10.8916 14.6961C10.8532 14.824 10.8825 14.9627 10.9694 15.0642L12.1634 16.4576C12.2016 16.5023 12.2335 16.552 12.2581 16.6054L13.2379 18.7328C13.3691 19.0176 13.2716 19.3488 13.0223 19.5213C13.0525 19.5257 13.0831 19.528 13.1138 19.528C13.2028 19.528 13.2933 19.5092 13.3795 19.4695C13.6987 19.3224 13.8382 18.9445 13.6913 18.6254L12.7115 16.498Z" fill="#00BEF7"/>
<path d="M4.22827 18.567C4.06064 18.567 3.92032 18.436 3.91092 18.2666C3.83839 16.9594 4.84282 15.8369 6.14991 15.7644C6.32574 15.7553 6.47551 15.8889 6.4852 16.0643C6.49493 16.2398 6.36065 16.3899 6.1852 16.3996C5.22834 16.4528 4.49305 17.2745 4.54616 18.2313C4.5559 18.4067 4.42162 18.5568 4.24617 18.5666C4.2402 18.5669 4.23419 18.567 4.22827 18.567Z" fill="#00BEF7"/>
<path d="M5.51838 18.5804C5.35076 18.5804 5.21044 18.4493 5.20104 18.2799C5.16524 17.635 5.66082 17.0812 6.3057 17.0454C6.48081 17.0358 6.63121 17.17 6.64094 17.3454C6.65068 17.5209 6.51636 17.671 6.34091 17.6807C6.04634 17.6971 5.81994 17.95 5.83627 18.2447C5.84601 18.4201 5.71169 18.5702 5.53624 18.5799C5.53032 18.5802 5.52431 18.5804 5.51838 18.5804Z" fill="#00BEF7"/>
<path d="M17.7606 13.7491C17.7576 13.7491 17.7546 13.749 17.7516 13.749C17.576 13.744 17.4376 13.5977 17.4425 13.4221C17.4691 12.4641 16.7115 11.663 15.7536 11.6364C15.578 11.6315 15.4396 11.4851 15.4445 11.3095C15.4494 11.1339 15.5966 10.9955 15.7713 11.0004C17.0799 11.0368 18.115 12.1311 18.0785 13.4398C18.0737 13.6124 17.9322 13.7491 17.7606 13.7491Z" fill="#00BEF7"/>
<path d="M16.4716 13.7978C16.4686 13.7978 16.4656 13.7978 16.4626 13.7977C16.287 13.7928 16.1486 13.6465 16.1535 13.4708C16.1575 13.328 16.1055 13.1921 16.0074 13.0882C15.9091 12.9844 15.7763 12.925 15.6335 12.921C15.4579 12.9161 15.3195 12.7698 15.3243 12.5942C15.3293 12.4186 15.474 12.2798 15.6512 12.2851C15.964 12.2938 16.2546 12.4238 16.4696 12.6511C16.6846 12.8784 16.7982 13.1758 16.7895 13.4886C16.7846 13.6611 16.6432 13.7978 16.4716 13.7978Z" fill="#00BEF7"/>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1,12 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_7305_15779)">
<path d="M17.0872 11.5142C17.0872 13.2025 16.427 14.8021 15.2211 15.9954C14.0278 17.2014 12.4283 17.8615 10.7399 17.8615C9.05141 17.8615 7.45185 17.2014 6.25856 15.9954C5.05262 14.8021 4.39249 13.2025 4.39249 11.5142C4.39249 9.82574 5.05266 8.22618 6.25856 7.03289C7.45185 5.8269 9.05141 5.16681 10.7399 5.16681C11.8063 5.16681 12.8471 5.43337 13.7866 5.95388L11.2984 8.97523H21.0861L18.6486 0L16.2113 2.97053C14.5737 1.91691 12.6948 1.35835 10.7398 1.35835C8.02314 1.35835 5.47142 2.41197 3.55459 4.32888C1.63765 6.24578 0.583984 8.79747 0.583984 11.5142C0.583984 14.2309 1.63765 16.7825 3.55459 18.6994C5.47146 20.6163 8.0231 21.67 10.7398 21.67C13.4565 21.67 16.0082 20.6163 17.925 18.6994C19.8419 16.7825 20.8956 14.2309 20.8956 11.5142V10.8794H17.0872V11.5142Z" fill="#77DD00"/>
<path d="M17.0876 10.8799H20.8961V11.5146C20.8961 14.2313 19.8424 16.7829 17.9254 18.6998C16.0086 20.6168 13.4569 21.6704 10.7402 21.6704V17.862C12.4287 17.862 14.0282 17.2019 15.2215 15.9959C16.4275 14.8026 17.0876 13.203 17.0876 11.5147V10.8799H17.0876Z" fill="#66BB00"/>
<path d="M13.787 5.95388C12.8475 5.43333 11.8066 5.16681 10.7402 5.16681V1.35835C12.6952 1.35835 14.5741 1.91691 16.2117 2.97057L18.6491 0L21.0866 8.97523H11.2989L13.787 5.95388Z" fill="#66BB00"/>
</g>
<defs>
<clipPath id="clip0_7305_15779">
<rect width="21.67" height="21.67" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,10 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_7302_4149)">
<path d="M19.9969 4.94279C19.986 4.83232 19.943 4.72146 19.8674 4.62924C19.8382 4.59358 20.1367 4.89431 15.4141 0.17176C15.3015 0.0591838 15.1487 8.30277e-05 14.9996 0.00012209C14.6443 0.00012209 2.11177 0.00012209 1.75779 0.00012209C0.788544 0.00012209 0 0.788666 0 1.75791V18.2421C0 19.2113 0.788544 19.9998 1.75779 19.9998H18.2419C19.2112 19.9998 19.9997 19.2113 19.9997 18.2421C19.9998 4.01624 20.0013 4.98771 19.9969 4.94279ZM13.4764 1.17198V5.00005C13.4764 5.32314 13.2136 5.58598 12.8905 5.58598H12.1483V1.17198H13.4764ZM10.9765 1.17198V5.58598H5.54684C5.22376 5.58598 4.96091 5.32314 4.96091 5.00005V1.17198H10.9765ZM13.4764 12.539H4.96091V11.7968C4.96091 11.4738 5.22376 11.2109 5.54684 11.2109H12.8905C13.2136 11.2109 13.4764 11.4738 13.4764 11.7968V12.539ZM4.96091 18.828V13.7109H13.4764V18.828H4.96091ZM18.8279 18.2421C18.8279 18.5651 18.5651 18.828 18.242 18.828H14.6483C14.6483 18.0641 14.6483 12.6676 14.6483 11.7968C14.6483 10.8276 13.8597 10.039 12.8905 10.039H5.54684C4.57759 10.039 3.78905 10.8276 3.78905 11.7968V18.828H1.75783C1.43475 18.828 1.1719 18.5651 1.1719 18.2421V1.75791C1.1719 1.43483 1.43475 1.17198 1.75783 1.17198H3.78905V5.00005C3.78905 5.9693 4.57759 6.75784 5.54684 6.75784H12.8905C13.8597 6.75784 14.6483 5.9693 14.6483 5.00005V1.17198H14.7571L18.8279 5.24278V18.2421Z" fill="#023DFE" fill-opacity="0.6"/>
</g>
<defs>
<clipPath id="clip0_7302_4149">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,21 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.7802 9.0399L20.0667 9.18046C19.7057 9.25157 19.4663 9.5894 19.5103 9.95466C19.6254 10.9106 19.5871 11.9137 19.3549 12.9433C18.5334 16.5849 15.4143 19.3394 11.6982 19.6957C6.22309 20.2206 1.65927 15.6884 2.13085 10.223C2.48684 6.09727 5.78343 2.73681 9.90242 2.3098C12.864 2.00274 15.5631 3.17762 17.3531 5.18175L18.396 4.25096C16.4588 2.08197 13.6036 0.750365 10.4397 0.87082C5.29437 1.06665 1.04625 5.19944 0.720226 10.3382C0.34608 16.2355 5.01846 21.1352 10.8352 21.1352C16.4331 21.1352 20.9712 16.5971 20.9712 10.9992C20.9712 10.3288 20.9044 9.674 20.7802 9.0399Z" fill="#FFF0D2"/>
<path d="M10.8355 12.7451C11.8006 12.7451 12.583 11.9627 12.583 10.9976C12.583 10.0324 11.8006 9.25 10.8355 9.25C9.8703 9.25 9.08789 10.0324 9.08789 10.9976C9.08789 11.9627 9.8703 12.7451 10.8355 12.7451Z" fill="#FFF0D2"/>
<path d="M10.8358 16.5911C10.6426 16.5911 10.4863 16.4346 10.4863 16.2416V10.9989C10.4863 10.9062 10.5232 10.8173 10.5887 10.7517L14.4334 6.90709C14.5699 6.77055 14.7911 6.77055 14.9276 6.90709C15.0642 7.04363 15.0642 7.26482 14.9276 7.40131L11.1854 11.1436V16.2416C11.1854 16.4347 11.029 16.5911 10.8358 16.5911Z" fill="#7A4646"/>
<path d="M10.8356 12.0463C11.4147 12.0463 11.8842 11.5769 11.8842 10.9978C11.8842 10.4187 11.4147 9.94922 10.8356 9.94922C10.2566 9.94922 9.78711 10.4187 9.78711 10.9978C9.78711 11.5769 10.2566 12.0463 10.8356 12.0463Z" fill="#AA6E4D"/>
<path d="M10.8358 4.35899C10.6426 4.35899 10.4863 4.20248 10.4863 4.00948V3.31045C10.4863 3.11745 10.6427 2.96094 10.8358 2.96094C11.0291 2.96094 11.1854 3.11745 11.1854 3.31045V4.00948C11.1854 4.20248 11.029 4.35899 10.8358 4.35899Z" fill="#DE966C"/>
<path d="M10.8358 19.0387C10.6426 19.0387 10.4863 18.8822 10.4863 18.6892V17.9901C10.4863 17.7971 10.6427 17.6406 10.8358 17.6406C11.0291 17.6406 11.1854 17.7971 11.1854 17.9901V18.6892C11.1854 18.8822 11.029 19.0387 10.8358 19.0387Z" fill="#DE966C"/>
<path d="M18.5251 11.3475H17.8261C17.6329 11.3475 17.4766 11.1909 17.4766 10.998C17.4766 10.805 17.6329 10.6484 17.8261 10.6484H18.5251C18.7183 10.6484 18.8746 10.805 18.8746 10.998C18.8746 11.1909 18.7183 11.3475 18.5251 11.3475Z" fill="#DE966C"/>
<path d="M3.84546 11.3475H3.14639C2.95318 11.3475 2.79688 11.1909 2.79688 10.998C2.79688 10.805 2.95322 10.6484 3.14639 10.6484H3.84541C4.03863 10.6484 4.19493 10.805 4.19493 10.998C4.19493 11.1909 4.03863 11.3475 3.84546 11.3475Z" fill="#DE966C"/>
<path d="M4.78099 7.85338C4.72161 7.85338 4.66151 7.83836 4.60657 7.80661L4.00108 7.4571C3.83382 7.36051 3.77651 7.14682 3.87309 6.9796C3.96968 6.81233 4.18371 6.75502 4.35059 6.85161L4.95608 7.20112C5.12335 7.29771 5.18066 7.5114 5.08407 7.67862C5.01923 7.79074 4.90178 7.85338 4.78099 7.85338Z" fill="#F7B97E"/>
<path d="M17.4939 15.1933C17.4345 15.1933 17.3744 15.1782 17.3195 15.1465L16.714 14.797C16.5467 14.7004 16.4894 14.4867 16.586 14.3195C16.6826 14.152 16.8966 14.0949 17.0635 14.1915L17.669 14.541C17.8362 14.6376 17.8935 14.8513 17.797 15.0185C17.7321 15.1306 17.6147 15.1933 17.4939 15.1933Z" fill="#F7B97E"/>
<path d="M14.3298 5.29299C14.2704 5.29299 14.2103 5.27796 14.1554 5.24622C13.9881 5.14964 13.9308 4.93594 14.0274 4.76872L14.3769 4.16323C14.4735 3.99579 14.6875 3.93866 14.8544 4.03524C15.0217 4.13182 15.079 4.34552 14.9824 4.51274L14.6329 5.11823C14.568 5.23035 14.4506 5.29299 14.3298 5.29299Z" fill="#F7B97E"/>
<path d="M6.98995 18.0077C6.93057 18.0077 6.87047 17.9927 6.81553 17.961C6.64827 17.8644 6.59096 17.6507 6.68755 17.4834L7.03706 16.878C7.13331 16.7107 7.34768 16.6536 7.51456 16.75C7.68183 16.8466 7.73913 17.0602 7.64255 17.2275L7.29304 17.833C7.2282 17.9451 7.11079 18.0077 6.98995 18.0077Z" fill="#F7B97E"/>
<path d="M16.8891 7.85337C16.7682 7.85337 16.6508 7.79073 16.586 7.67861C16.4894 7.51135 16.5467 7.2977 16.714 7.20111L17.3195 6.8516C17.486 6.75502 17.7004 6.81236 17.797 6.97959C17.8935 7.14685 17.8362 7.36051 17.669 7.45709L17.0635 7.8066C17.0085 7.83835 16.9485 7.85337 16.8891 7.85337Z" fill="#F7B97E"/>
<path d="M4.17617 15.1933C4.05533 15.1933 3.93792 15.1306 3.87308 15.0185C3.7765 14.8512 3.83385 14.6376 4.00107 14.541L4.60656 14.1915C4.77277 14.0949 4.98714 14.1521 5.08406 14.3195C5.18065 14.4867 5.1233 14.7004 4.95608 14.797L4.35059 15.1465C4.29565 15.1782 4.23555 15.1933 4.17617 15.1933Z" fill="#F7B97E"/>
<path d="M7.34013 5.29298C7.2193 5.29298 7.10189 5.23034 7.03705 5.11822L6.68754 4.51273C6.59095 4.34547 6.6483 4.13181 6.81553 4.03523C6.98207 3.93865 7.1961 3.99583 7.29303 4.16322L7.64254 4.76871C7.73912 4.93597 7.68178 5.14963 7.51455 5.24621C7.45962 5.27795 7.39956 5.29298 7.34013 5.29298Z" fill="#F7B97E"/>
<path d="M14.68 18.0077C14.5591 18.0077 14.4417 17.9451 14.3769 17.833L14.0274 17.2275C13.9308 17.0602 13.9881 16.8465 14.1554 16.75C14.3219 16.6535 14.5363 16.7107 14.6329 16.8779L14.9824 17.4834C15.079 17.6507 15.0216 17.8644 14.8544 17.9609C14.7994 17.9927 14.7394 18.0077 14.68 18.0077Z" fill="#F7B97E"/>
<path d="M10.8358 11.3475C11.0289 11.3475 11.1854 11.191 11.1854 10.998C11.1854 10.8049 11.0289 10.6484 10.8358 10.6484C10.6428 10.6484 10.4863 10.8049 10.4863 10.998C10.4863 11.191 10.6428 11.3475 10.8358 11.3475Z" fill="#7A4646"/>
<path d="M10.8356 1.56212C5.42443 1.56212 1.07697 6.11655 1.41743 11.6012C1.70913 16.3007 5.53397 20.1256 10.2335 20.4173C15.7181 20.7578 20.2726 16.4103 20.2726 10.9991C20.2726 10.2541 20.1854 9.5297 20.0217 8.83474C19.9829 8.66988 20.0623 8.5019 20.2172 8.43346C20.4105 8.34805 20.6773 8.24402 20.8922 8.16267C21.0866 8.08907 21.3059 8.19949 21.3557 8.40125C21.6326 9.52411 21.7356 10.7154 21.6299 11.9463C21.4062 14.551 20.2433 16.8986 18.4888 18.652C18.4888 18.652 14.9619 21.4157 11.4687 21.4157C4.94621 21.4157 0.410156 16.7271 0.410156 10.1916C0.410156 7.40625 3.18409 3.34816 3.18409 3.34816C5.04237 1.49153 7.56422 0.300058 10.3375 0.175287C13.4409 0.035659 16.2657 1.20796 18.3212 3.17781L18.9202 2.71389C19.1388 2.5446 19.4582 2.68418 19.4824 2.95967L19.7199 5.66482C19.7422 5.91826 19.4949 6.10982 19.2551 6.02483L16.6954 5.11791C16.4348 5.02556 16.3795 4.68142 16.5982 4.51212L17.2071 4.04055C15.5283 2.50215 13.2923 1.56212 10.8356 1.56212Z" fill="#FB5F7A"/>
<path d="M18.485 18.6485C18.2212 18.3848 17.7996 18.3723 17.5193 18.6183C15.5456 20.3511 12.893 21.3292 10.0123 21.102C5.09917 20.7145 1.11879 16.7339 0.731479 11.8208C0.50441 8.94025 1.48256 6.28788 3.21519 4.3143C3.46126 4.03403 3.44709 3.61138 3.18336 3.34766C1.37642 5.15274 0.197009 7.58634 0.0232257 10.2799C-0.397562 16.8019 4.95607 22.1858 11.468 21.8155C14.1882 21.6609 16.6595 20.4788 18.4881 18.6515L18.485 18.6485Z" fill="#F74455"/>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -0,0 +1,18 @@
<svg width="47" height="37" viewBox="0 0 47 37" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="1" width="41" height="25" rx="12.5" fill="#023DFE" fill-opacity="0.7"/>
<g filter="url(#filter0_d_6689_981)">
<circle cx="28.5" cy="13.5" r="10.5" fill="white"/>
</g>
<defs>
<filter id="filter0_d_6689_981" x="10" y="0" width="37" height="37" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="4"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_6689_981"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_6689_981" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 975 B

View File

@ -0,0 +1,23 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8194_10077)">
<path d="M17.6 18.673C17.3521 18.4251 17.3521 18.0231 17.6 17.7752C19.4054 15.9698 20.3996 13.5678 20.3996 11.0115C20.3996 8.45525 19.4054 6.05318 17.6 4.24784C17.3521 3.99994 17.3521 3.59795 17.6 3.35001C17.8479 3.10208 18.2499 3.10208 18.4978 3.35001C20.543 5.39516 21.6694 8.11606 21.6694 11.0115C21.6694 13.9069 20.543 16.6278 18.4978 18.673C18.2503 18.9205 17.8484 18.9213 17.6 18.673Z" fill="#7AFFE4"/>
<path d="M15.6781 16.7502C15.4302 16.5023 15.4302 16.1003 15.6781 15.8524C16.9704 14.5602 17.6821 12.8408 17.6821 11.011C17.6821 9.18128 16.9705 7.46194 15.6781 6.1697C15.4302 5.92176 15.4302 5.51981 15.6781 5.27187C15.926 5.02398 16.328 5.02394 16.576 5.27187C18.1081 6.80393 18.9519 8.84213 18.9519 11.0111C18.9519 13.18 18.1081 15.2182 16.576 16.7503C16.3279 16.9982 15.926 16.9981 15.6781 16.7502Z" fill="#00DDC1"/>
<path d="M13.7543 14.8285C13.5064 14.5805 13.5064 14.1785 13.7543 13.9306C14.5331 13.152 14.9619 12.1158 14.9619 11.0131C14.9619 9.91034 14.5331 8.87416 13.7543 8.09548C13.5064 7.84758 13.5064 7.44559 13.7543 7.19765C14.0022 6.94976 14.4042 6.94972 14.6521 7.19765C15.6707 8.21619 16.2317 9.5712 16.2317 11.0131C16.2317 12.455 15.6707 13.81 14.6521 14.8285C14.4042 15.0764 14.0022 15.0763 13.7543 14.8285Z" fill="#7AFFE4"/>
<path d="M17.6 18.6732C17.8484 18.9216 18.2503 18.9207 18.4978 18.6732C20.543 16.6281 21.6694 13.9072 21.6694 11.0117H20.3996C20.3996 13.568 19.4054 15.97 17.6 17.7754C17.3521 18.0233 17.3521 18.4253 17.6 18.6732Z" fill="#00DDC1"/>
<path d="M15.6781 16.7509C15.926 16.9988 16.3279 16.9989 16.5759 16.7509C18.1081 15.2189 18.9518 13.1807 18.9518 11.0117H17.6821C17.6821 12.8415 16.9704 14.5608 15.6781 15.8531C15.4302 16.101 15.4302 16.503 15.6781 16.7509Z" fill="#00B4BC"/>
<path d="M13.7543 14.8272C14.0022 15.0751 14.4041 15.0751 14.6521 14.8272C15.6707 13.8086 16.2316 12.4536 16.2316 11.0117H14.9619C14.9619 12.1144 14.533 13.1506 13.7543 13.9293C13.5064 14.1772 13.5064 14.5792 13.7543 14.8272Z" fill="#00DDC1"/>
<path d="M3.17152 18.673C1.12633 16.6278 0 13.9069 0 11.0115C0 8.11604 1.12633 5.39515 3.17152 3.35C3.41946 3.10206 3.82141 3.10211 4.06935 3.35C4.31728 3.59793 4.31728 3.99989 4.06935 4.24782C2.26396 6.05316 1.26973 8.45523 1.26973 11.0115C1.26973 13.5677 2.26396 15.9698 4.06935 17.7751C4.31728 18.023 4.31728 18.425 4.06935 18.673C3.82141 18.921 3.41937 18.9209 3.17152 18.673Z" fill="#7AFFE4"/>
<path d="M5.09462 16.7503C3.56253 15.2182 2.71875 13.18 2.71875 11.0111C2.71875 8.84212 3.56253 6.80391 5.09466 5.27186C5.3426 5.02396 5.74459 5.02396 5.99249 5.27186C6.24038 5.51979 6.24038 5.92175 5.99249 6.16968C4.70016 7.46197 3.98848 9.1813 3.98848 11.0111C3.98848 12.8408 4.70016 14.5602 5.99249 15.8524C6.24042 16.1003 6.24042 16.5023 5.99249 16.7502C5.74489 16.9978 5.34294 16.9985 5.09462 16.7503Z" fill="#00DDC1"/>
<path d="M7.01704 14.8285C5.99847 13.81 5.4375 12.455 5.4375 11.0131C5.4375 9.5712 5.99847 8.21619 7.01704 7.19765C7.26498 6.94972 7.66697 6.94976 7.91486 7.19765C8.1628 7.44559 8.16276 7.84758 7.91486 8.09548C7.1361 8.87416 6.70723 9.91034 6.70723 11.0131C6.70723 12.1158 7.1361 13.152 7.91486 13.9306C8.1628 14.1785 8.1628 14.5805 7.91486 14.8285C7.66727 15.0761 7.26531 15.0768 7.01704 14.8285Z" fill="#7AFFE4"/>
<path d="M4.06935 18.6732C4.31728 18.4253 4.31728 18.0233 4.06935 17.7754C2.26396 15.97 1.26973 13.568 1.26973 11.0117H0C0 13.9072 1.12633 16.6281 3.17152 18.6732C3.41937 18.9211 3.82141 18.9212 4.06935 18.6732Z" fill="#00DDC1"/>
<path d="M5.99249 16.7509C6.24038 16.5029 6.24038 16.101 5.99249 15.8531C4.70016 14.5609 3.98848 12.8415 3.98848 11.0117H2.71875C2.71875 13.1807 3.56253 15.2189 5.09466 16.7509C5.34294 16.9992 5.74489 16.9985 5.99249 16.7509Z" fill="#00B4BC"/>
<path d="M7.91486 14.8271C8.1628 14.5792 8.16276 14.1772 7.91486 13.9293C7.1361 13.1506 6.70723 12.1144 6.70723 11.0117H5.4375C5.4375 12.4536 5.99846 13.8086 7.01704 14.8272C7.26527 15.0754 7.66722 15.0747 7.91486 14.8271Z" fill="#00DDC1"/>
<path d="M10.835 13.6857C12.3123 13.6857 13.5099 12.4881 13.5099 11.0108C13.5099 9.53353 12.3123 8.33594 10.835 8.33594C9.35775 8.33594 8.16016 9.53353 8.16016 11.0108C8.16016 12.4881 9.35775 13.6857 10.835 13.6857Z" fill="#00DDC1"/>
<path d="M10.835 13.6866C12.31 13.6866 13.5099 12.4866 13.5099 11.0117H8.16016C8.16016 12.4867 9.36009 13.6866 10.835 13.6866Z" fill="#00B4BC"/>
</g>
<defs>
<clipPath id="clip0_8194_10077">
<rect width="21.67" height="21.67" fill="white" transform="translate(0 0.164062)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,10 @@
<svg width="107" height="100" viewBox="0 0 107 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M36.8625 65.1775C39.1819 62.9069 40.625 59.7444 40.625 56.25C40.625 49.3575 35.0175 43.75 28.125 43.75C21.2325 43.75 15.625 49.3575 15.625 56.25C15.625 59.7444 17.0681 62.9069 19.3875 65.1775C15.2348 67.9887 12.5 72.7435 12.5 78.125V84.375C12.5 86.1008 13.8992 87.5 15.625 87.5H40.625C42.3508 87.5 43.75 86.1008 43.75 84.375V78.125C43.75 72.7435 41.0152 67.9887 36.8625 65.1775ZM28.125 50C31.5712 50 34.375 52.8038 34.375 56.25C34.375 59.6962 31.5712 62.5 28.125 62.5C24.6788 62.5 21.875 59.6962 21.875 56.25C21.875 52.8038 24.6788 50 28.125 50ZM37.5 81.25H18.75V78.125C18.75 72.9556 22.9556 68.75 28.125 68.75C33.2944 68.75 37.5 72.9556 37.5 78.125V81.25Z" fill="#D5D5D5"/>
<path d="M72.291 62.5C74.0169 62.5 75.416 61.1009 75.416 59.375C75.416 57.6491 74.0169 56.25 72.291 56.25C70.5651 56.25 69.166 57.6491 69.166 59.375C69.166 61.1009 70.5651 62.5 72.291 62.5Z" fill="#D5D5D5"/>
<path d="M84.791 62.5C86.5169 62.5 87.916 61.1009 87.916 59.375C87.916 57.6491 86.5169 56.25 84.791 56.25C83.0651 56.25 81.666 57.6491 81.666 59.375C81.666 61.1009 83.0651 62.5 84.791 62.5Z" fill="#D5D5D5"/>
<path d="M59.791 62.5C61.5169 62.5 62.916 61.1009 62.916 59.375C62.916 57.6491 61.5169 56.25 59.791 56.25C58.0651 56.25 56.666 57.6491 56.666 59.375C56.666 61.1009 58.0651 62.5 59.791 62.5Z" fill="#D5D5D5"/>
<path d="M84.791 68.75H59.791C58.0652 68.75 56.666 70.1492 56.666 71.875C56.666 73.6008 58.0652 75 59.791 75H84.791C86.5168 75 87.916 73.6008 87.916 71.875C87.916 70.1492 86.5168 68.75 84.791 68.75Z" fill="#D5D5D5"/>
<path d="M84.791 81.25H59.791C58.0652 81.25 56.666 82.6492 56.666 84.375C56.666 86.1008 58.0652 87.5 59.791 87.5H84.791C86.5168 87.5 87.916 86.1008 87.916 84.375C87.916 82.6492 86.5168 81.25 84.791 81.25Z" fill="#D5D5D5"/>
<path d="M93.2507 16.5405C92.0305 15.3199 90.0517 15.3199 88.8315 16.5403L78.5411 26.8307L74.5007 22.7903C73.2805 21.5699 71.3017 21.5699 70.0813 22.7903C68.8609 24.0107 68.8609 25.9892 70.0813 27.2097L76.3313 33.4597C76.9415 34.0701 77.7413 34.3751 78.5411 34.3751C79.3409 34.3751 80.1407 34.0701 80.7507 33.4599L93.2507 20.9599C94.4711 19.7395 94.4711 17.7609 93.2507 16.5405Z" fill="#D5D5D5"/>
<path d="M81.6667 0C67.8817 0 56.6667 11.215 56.6667 25H9.375C4.20563 25 0 29.2056 0 34.375V90.625C0 95.7944 4.20563 100 9.375 100H91.0417C96.211 100 100.417 95.7944 100.417 90.625V41.5165C104.304 37.1085 106.667 31.3254 106.667 25C106.667 11.215 95.4517 0 81.6667 0ZM94.1667 90.625C94.1667 92.3481 92.7648 93.75 91.0417 93.75H9.375C7.65188 93.75 6.25 92.3481 6.25 90.625V34.375C6.25 32.6519 7.65188 31.25 9.375 31.25H57.4577C60.24 42.0206 70.039 50 81.6667 50C86.2173 50 90.4873 48.7773 94.1667 46.644V90.625ZM81.6667 43.75C71.3279 43.75 62.9167 35.3387 62.9167 25C62.9167 14.6613 71.3279 6.25 81.6667 6.25C92.0054 6.25 100.417 14.6613 100.417 25C100.417 35.3387 92.0054 43.75 81.6667 43.75Z" fill="#D5D5D5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
platform :ios, '15.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@ -1,155 +1,153 @@
PODS:
- device_info_plus (0.0.1):
- Flutter
- Firebase/Analytics (10.25.0):
- Firebase/Analytics (11.6.0):
- Firebase/Core
- Firebase/Core (10.25.0):
- Firebase/Core (11.6.0):
- Firebase/CoreOnly
- FirebaseAnalytics (~> 10.25.0)
- Firebase/CoreOnly (10.25.0):
- FirebaseCore (= 10.25.0)
- Firebase/Crashlytics (10.25.0):
- FirebaseAnalytics (~> 11.6.0)
- Firebase/CoreOnly (11.6.0):
- FirebaseCore (~> 11.6.0)
- Firebase/Crashlytics (11.6.0):
- Firebase/CoreOnly
- FirebaseCrashlytics (~> 10.25.0)
- Firebase/Database (10.25.0):
- FirebaseCrashlytics (~> 11.6.0)
- Firebase/Database (11.6.0):
- Firebase/CoreOnly
- FirebaseDatabase (~> 10.25.0)
- firebase_analytics (10.8.7):
- Firebase/Analytics (= 10.25.0)
- FirebaseDatabase (~> 11.6.0)
- firebase_analytics (11.4.0):
- Firebase/Analytics (= 11.6.0)
- firebase_core
- Flutter
- firebase_core (2.32.0):
- Firebase/CoreOnly (= 10.25.0)
- firebase_core (3.10.0):
- Firebase/CoreOnly (= 11.6.0)
- Flutter
- firebase_crashlytics (3.4.16):
- Firebase/Crashlytics (= 10.25.0)
- firebase_crashlytics (4.3.0):
- Firebase/Crashlytics (= 11.6.0)
- firebase_core
- Flutter
- firebase_database (10.5.7):
- Firebase/Database (= 10.25.0)
- firebase_database (11.3.0):
- Firebase/Database (= 11.6.0)
- firebase_core
- Flutter
- FirebaseAnalytics (10.25.0):
- FirebaseAnalytics/AdIdSupport (= 10.25.0)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (10.25.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleAppMeasurement (= 10.25.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseAppCheckInterop (10.29.0)
- FirebaseCore (10.25.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.12)
- GoogleUtilities/Logger (~> 7.12)
- FirebaseCoreExtension (10.29.0):
- FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.29.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseCrashlytics (10.25.0):
- FirebaseCore (~> 10.5)
- FirebaseInstallations (~> 10.0)
- FirebaseRemoteConfigInterop (~> 10.23)
- FirebaseSessions (~> 10.5)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/Environment (~> 7.8)
- nanopb (< 2.30911.0, >= 2.30908.0)
- PromisesObjC (~> 2.1)
- FirebaseDatabase (10.25.0):
- FirebaseAppCheckInterop (~> 10.17)
- FirebaseCore (~> 10.0)
- FirebaseSharedSwift (~> 10.0)
- GoogleUtilities/UserDefaults (~> 7.13)
- FirebaseAnalytics (11.6.0):
- FirebaseAnalytics/AdIdSupport (= 11.6.0)
- FirebaseCore (~> 11.6.0)
- FirebaseInstallations (~> 11.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- FirebaseAnalytics/AdIdSupport (11.6.0):
- FirebaseCore (~> 11.6.0)
- FirebaseInstallations (~> 11.0)
- GoogleAppMeasurement (= 11.6.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- FirebaseAppCheckInterop (11.6.0)
- FirebaseCore (11.6.0):
- FirebaseCoreInternal (~> 11.6.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Logger (~> 8.0)
- FirebaseCoreExtension (11.6.0):
- FirebaseCore (~> 11.6.0)
- FirebaseCoreInternal (11.6.0):
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- FirebaseCrashlytics (11.6.0):
- FirebaseCore (~> 11.6.0)
- FirebaseInstallations (~> 11.0)
- FirebaseRemoteConfigInterop (~> 11.0)
- FirebaseSessions (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/Environment (~> 8.0)
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- FirebaseDatabase (11.6.0):
- FirebaseAppCheckInterop (~> 11.0)
- FirebaseCore (~> 11.6.0)
- FirebaseSharedSwift (~> 11.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- leveldb-library (~> 1.22)
- FirebaseInstallations (10.29.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseRemoteConfigInterop (10.29.0)
- FirebaseSessions (10.29.0):
- FirebaseCore (~> 10.5)
- FirebaseCoreExtension (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/Environment (~> 7.13)
- GoogleUtilities/UserDefaults (~> 7.13)
- nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseInstallations (11.6.0):
- FirebaseCore (~> 11.6.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- FirebaseRemoteConfigInterop (11.6.0)
- FirebaseSessions (11.6.0):
- FirebaseCore (~> 11.6.0)
- FirebaseCoreExtension (~> 11.6.0)
- FirebaseInstallations (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- nanopb (~> 3.30910.0)
- PromisesSwift (~> 2.1)
- FirebaseSharedSwift (10.29.0)
- FirebaseSharedSwift (11.6.0)
- Flutter (1.0.0)
- flutter_secure_storage (6.0.0):
- Flutter
- GoogleAppMeasurement (10.25.0):
- GoogleAppMeasurement/AdIdSupport (= 10.25.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (10.25.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.25.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (10.25.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleDataTransport (9.4.1):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30911.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/AppDelegateSwizzler (7.13.3):
- GoogleAppMeasurement (11.6.0):
- GoogleAppMeasurement/AdIdSupport (= 11.6.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/AdIdSupport (11.6.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 11.6.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- GoogleAppMeasurement/WithoutAdIdSupport (11.6.0):
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
- GoogleUtilities/MethodSwizzler (~> 8.0)
- GoogleUtilities/Network (~> 8.0)
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- nanopb (~> 3.30910.0)
- GoogleDataTransport (10.1.0):
- nanopb (~> 3.30910.0)
- PromisesObjC (~> 2.4)
- GoogleUtilities/AppDelegateSwizzler (8.0.2):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (7.13.3):
- GoogleUtilities/Environment (8.0.2):
- GoogleUtilities/Privacy
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.13.3):
- GoogleUtilities/Logger (8.0.2):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/MethodSwizzler (7.13.3):
- GoogleUtilities/MethodSwizzler (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/Network (7.13.3):
- GoogleUtilities/Network (8.0.2):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.13.3)":
- "GoogleUtilities/NSData+zlib (8.0.2)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (7.13.3)
- GoogleUtilities/Reachability (7.13.3):
- GoogleUtilities/Privacy (8.0.2)
- GoogleUtilities/Reachability (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/UserDefaults (7.13.3):
- GoogleUtilities/UserDefaults (8.0.2):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- image_picker_ios (0.0.1):
- Flutter
- leveldb-library (1.22.5)
- nanopb (2.30910.0):
- nanopb/decode (= 2.30910.0)
- nanopb/encode (= 2.30910.0)
- nanopb/decode (2.30910.0)
- nanopb/encode (2.30910.0)
- leveldb-library (1.22.6)
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
- nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0)
- onesignal_flutter (5.2.0):
- Flutter
- OneSignalXCFramework (= 5.2.0)
@ -291,42 +289,42 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
Firebase: 0312a2352584f782ea56f66d91606891d4607f06
firebase_analytics: 3a9263fedec72970e6bd30a7132bbdd386de2c14
firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197
firebase_crashlytics: 0b7cb41f5fb3b6889d0fb408cfce3cc7a4247061
firebase_database: 2713033e426b176d4fe5e7195f3d19aa1b549a91
FirebaseAnalytics: ec00fe8b93b41dc6fe4a28784b8e51da0647a248
FirebaseAppCheckInterop: 6a1757cfd4067d8e00fccd14fcc1b8fd78cfac07
FirebaseCore: 7ec4d0484817f12c3373955bc87762d96842d483
FirebaseCoreExtension: 705ca5b14bf71d2564a0ddc677df1fc86ffa600f
FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934
FirebaseCrashlytics: 4b96efb0ce73b38b2a85e8b8bd1bd8f63f09d015
FirebaseDatabase: faa489a42f5f868d23a55dd442d6e2099348458e
FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd
FirebaseRemoteConfigInterop: 6efda51fb5e2f15b16585197e26eaa09574e8a4d
FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
Firebase: 374a441a91ead896215703a674d58cdb3e9d772b
firebase_analytics: 07bd7cfbac54bfcdccf2bb2530f9a65486f7ef3f
firebase_core: feb37e79f775c2bd08dd35e02d83678291317e10
firebase_crashlytics: 609a5f6f4a2f5af9e40a68182e0c1be3ca2a02f6
firebase_database: adc9efd0b70cdc8d1e6f3c9f6bb054a625c4f45d
FirebaseAnalytics: 7114c698cac995602e3b1b96663473e50d54d6e7
FirebaseAppCheckInterop: 347aa09a805219a31249b58fc956888e9fcb314b
FirebaseCore: 48b0dd707581cf9c1a1220da68223fb0a562afaa
FirebaseCoreExtension: 2d77d6430c16cf43ca2b04608302ed02b3598361
FirebaseCoreInternal: d98ab91e2d80a56d7b246856a8885443b302c0c2
FirebaseCrashlytics: b21c665fb50138766480bce73ebdb1aa30f7f300
FirebaseDatabase: ce3a83a39ab50559a85c5add54f6f285544433b8
FirebaseInstallations: efc0946fc756e4d22d8113f7c761948120322e8c
FirebaseRemoteConfigInterop: e75e348953352a000331eb77caf01e424248e176
FirebaseSessions: 9529d14180868e29a8da164b3a729c036204918b
FirebaseSharedSwift: a4e5dfca3e210633bb3a3dfb94176c019211948b
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
GoogleAppMeasurement: 9abf64b682732fed36da827aa2a68f0221fd2356
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
GoogleAppMeasurement: 6a9e6317b6a6d810ad03d4a66564ca6c4c5818a3
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
leveldb-library: e8eadf9008a61f9e1dde3978c086d2b6d9b9dc28
nanopb: 438bc412db1928dac798aa6fd75726007be04262
leveldb-library: cc8b8f8e013647a295ad3f8cd2ddf49a6f19be19
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
onesignal_flutter: 5ce68a29861960168e81101cb1bd685d264361de
OneSignalXCFramework: bdf74fdc06888f9466dc21e826fe1549ed143095
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
PODFILE CHECKSUM: 4243bd7f9184f79552dd731a7c9d5cad03bd2706
PODFILE CHECKSUM: deba6d843ff3cf709e6e9051ce6601a587b24105
COCOAPODS: 1.15.2
COCOAPODS: 1.16.2

View File

@ -547,6 +547,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -739,6 +740,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -769,6 +771,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -856,6 +859,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -959,6 +963,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -1057,6 +1062,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View File

@ -1,7 +1,7 @@
import UIKit
import Flutter
@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,

View File

@ -38,5 +38,10 @@
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sms</string>
<string>tel</string>
</array>
</dict>
</plist>

View File

@ -1,4 +1,5 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
@ -6,10 +7,11 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:share_plus/share_plus.dart';
import 'package:syncrow_app/features/app_layout/model/permission_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdown.dart';
import 'package:syncrow_app/features/auth/model/project_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/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
@ -20,32 +22,40 @@ import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_e
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/model/scene_settings_route_arguments.dart';
import 'package:syncrow_app/features/scene/view/scene_view.dart';
import 'package:syncrow_app/features/scene/view/routines_view.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/navigation_service.dart';
import 'package:syncrow_app/navigation/routing_constants.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/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
part 'home_state.dart';
class HomeCubit extends Cubit<HomeState> {
HomeCubit._() : super(HomeInitial()) {
// checkIfNotificationPermissionGranted();
fetchUserInfo();
if (selectedSpace == null) {
fetchUnitsByUserId();
// .then((value) {
// if (selectedSpace != null) {
// fetchRoomsByUnitId(selectedSpace!);
// }
// });
}
fetchUserInfo().then(
(value) {
if (selectedSpace == null) {
fetchUnitsByUserId();
fetchPermissions();
// .then((value) {
// if (selectedSpace != null) {
// fetchRoomsByUnitId(selectedSpace!);
// }
// });
}
},
);
}
static UserModel? user;
List<PermissionModel>? permissionModel = [];
static HomeCubit? _instance;
static HomeCubit getInstance() {
// If an instance already exists, return it
@ -55,14 +65,90 @@ class HomeCubit extends Cubit<HomeState> {
Future fetchUserInfo() async {
try {
var uuid=await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
emit(HomeLoading());
var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
user = await ProfileApi().fetchUserInfo(uuid);
emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info
project = user?.project;
emit(HomeUserInfoLoaded(user!));
} catch (e) {
return;
}
}
static bool manageSupSpace = false;
static bool manageScene = false;
static bool manageDeviceLocation = false;
static bool visitorPasswordManagement = false;
String errorMsg = '';
Future<void> fetchPermissions() async {
try {
emit(HomeLoading());
final response = await ProfileApi().fetchPermissions(user!.role!.uuid);
permissionModel = PermissionModel.fromJsonList(response);
hasViewPermission();
emit(PermissionsRoleLoaded(permissionModel!));
} catch (e) {
emit(HomeError(e.toString()));
}
}
void hasViewPermission() {
emit(HomeLoading());
manageSupSpace = hasPermission(
permissionModel!,
'SPACE_MANAGEMENT',
'MANAGE_SPACE',
'ASSIGN_USER_TO_SPACE',
);
manageScene = hasPermission(
permissionModel!,
'AUTOMATION_MANAGEMENT',
'MANAGE_SCENES',
'UPDATE',
);
manageDeviceLocation = hasPermission(
permissionModel!,
'DEVICE_MANAGEMENT',
'MANAGE_DEVICE',
'LOCATION_UPDATE',
);
visitorPasswordManagement = hasPermission(
permissionModel!,
'VISITOR_PASSWORD_MANAGEMENT',
'MANAGE_VISITOR_PASSWORD',
'VIEW',
);
emit(HomePermissionUpdated());
}
bool hasPermission(List<PermissionModel> permissions, String mainTitle,
String subTitle, String finalTitle) {
try {
final mainOption = permissions.firstWhere(
(perm) => perm.title == mainTitle,
);
final subOption = mainOption.subOptions.firstWhere(
(sub) => sub.title == subTitle,
);
if (subOption.subOptions == null) {
return false;
}
final finalOption = subOption.subOptions!.firstWhere(
(finalSub) => finalSub.title == finalTitle,
);
return finalOption.isChecked == true;
} catch (e) {
return false;
}
}
void emitSafe(HomeState newState) {
final cubit = this;
if (!cubit.isClosed) {
@ -87,12 +173,14 @@ class HomeCubit extends Cubit<HomeState> {
static HomeCubit get(context) => BlocProvider.of(context);
List<SpaceModel>? spaces;
List<SpaceModel> spaces = [];
SpaceModel? selectedSpace;
SubSpaceModel? selectedRoom;
Project? project;
PageController devicesPageController = PageController();
PageController roomsPageController = PageController();
@ -180,8 +268,10 @@ class HomeCubit extends Cubit<HomeState> {
if (index == 0) {
unselectRoom();
} else if (index == 1) {
unselectRoom1();
} else {
selectedRoom = selectedSpace!.subspaces[index - 1];
selectedRoom = selectedSpace!.subspaces[index - 2];
emitSafe(RoomSelected(selectedRoom!));
}
}
@ -195,8 +285,10 @@ class HomeCubit extends Cubit<HomeState> {
if (index <= 0) {
unselectRoom();
} else if (index == 1) {
unselectRoom1();
} else {
selectedRoom = selectedSpace!.subspaces[index - 1];
selectedRoom = selectedSpace!.subspaces[index - 2];
emitSafe(RoomSelected(selectedRoom!));
}
}
@ -218,11 +310,28 @@ class HomeCubit extends Cubit<HomeState> {
emitSafe(RoomUnSelected());
}
unselectRoom1() {
// selectedRoom = null;
devicesPageController.animateToPage(
1,
duration: duration,
curve: Curves.linear,
);
roomsPageController.animateToPage(
1,
duration: duration,
curve: Curves.linear,
);
emitSafe(RoomUnSelected());
}
//////////////////////////////////////// API ////////////////////////////////////////
generateInvitation(SpaceModel unit) async {
try {
final invitationCode =
await SpacesAPI.generateInvitationCode(unit.id, unit.community.uuid);
final invitationCode = await SpacesAPI.generateInvitationCode(unit.id,
unit.community.uuid, project?.uuid ?? TempConst.projectIdDev);
if (invitationCode.isNotEmpty) {
Share.share('The invitation code is $invitationCode');
CustomSnackBar.displaySnackBar(
@ -259,15 +368,16 @@ class HomeCubit extends Cubit<HomeState> {
emitSafe(GetSpacesLoading());
try {
spaces = await SpacesAPI.getSpacesByUserId();
emitSafe(GetSpacesSuccess(spaces));
} catch (failure) {
emitSafe(GetSpacesError("No units found"));
return;
}
if (spaces != null && spaces!.isNotEmpty) {
selectedSpace = spaces!.first;
if (spaces.isNotEmpty) {
selectedSpace = spaces.first;
await fetchRoomsByUnitId(selectedSpace!);
emitSafe(GetSpacesSuccess(spaces!));
emitSafe(GetSpacesSuccess(spaces));
} else {
emitSafe(GetSpacesError("No spaces found"));
}
@ -276,8 +386,10 @@ class HomeCubit extends Cubit<HomeState> {
fetchRoomsByUnitId(SpaceModel space) async {
emitSafe(GetSpaceRoomsLoading());
try {
space.subspaces =
await SpacesAPI.getSubSpaceBySpaceId(space.community.uuid, space.id);
space.subspaces = await SpacesAPI.getSubSpaceBySpaceId(
space.community.uuid,
space.id,
project?.uuid ?? TempConst.projectIdDev);
} catch (failure) {
emitSafe(GetSpaceRoomsError(failure.toString()));
return;
@ -289,36 +401,59 @@ class HomeCubit extends Cubit<HomeState> {
}
}
activationCode(activationCode) async {
try {
emitSafe(GetSpaceRoomsLoading());
var uuid =
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
var res = await SpacesAPI.activationCodeSpace(
activationCode: activationCode, userUuid: uuid);
if (res['success'] == true) {
fetchUserInfo();
fetchUnitsByUserId();
}
emitSafe(GetSpacesSuccess(spaces!));
return res['success'];
} on DioException catch (e) {
final errorMessage = e.response?.data['error']['message'];
errorMsg = e.response?.data['error']['message'];
emitSafe(ActivationError(errMessage: errorMsg));
return false;
}
}
/////////////////////////////////////// Nav ///////////////////////////////////////
static int pageIndex = 0;
static Map<String, List<Widget>> appBarActions = {
'Dashboard': [
// IconButton(
// icon: const Icon(
// Icons.add,
// size: 25,
// ),
// style: ButtonStyle(
// foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
// ),
// onPressed: () {
// Navigator.push(
// NavigationService.navigatorKey.currentContext!,
// CustomPageRoute(
// builder: (context) => CurtainView(
// curtain: DeviceModel(
// name: "Curtain",
// status: [StatusModel(code: "awd", value: 1)],
// productType: DeviceType.Curtain,
// ),
// ),
// ),
// );
// },
// ),
],
// 'Dashboard': [
// // IconButton(
// // icon: const Icon(
// // Icons.add,
// // size: 25,
// // ),
// // style: ButtonStyle(
// // foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
// // ),
// // onPressed: () {
// // Navigator.push(
// // NavigationService.navigatorKey.currentContext!,
// // CustomPageRoute(
// // builder: (context) => CurtainView(
// // curtain: DeviceModel(
// // name: "Curtain",
// // status: [StatusModel(code: "awd", value: 1)],
// // productType: DeviceType.Curtain,
// // ),
// // ),
// // ),
// // );
// // },
// // ),
// ],
'Devices': [
//TODO: to be checked
// IconButton(
@ -353,68 +488,70 @@ class HomeCubit extends Cubit<HomeState> {
// ),
// onPressed: () {},
// ),
IconButton(
icon: const Icon(
Icons.add,
size: 32,
),
style: ButtonStyle(
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
Navigator.pushNamed(
NavigationService.navigatorKey.currentContext!,
Routes.sceneTasksRoute,
arguments: SceneSettingsRouteArguments(
sceneType: '',
sceneId: '',
sceneName: '',
),
);
NavigationService.navigatorKey.currentContext!
.read<CreateSceneBloc>()
.add(const ClearTaskListEvent());
NavigationService.navigatorKey.currentContext!
.read<CreateSceneBloc>()
.add(const SceneTypeEvent(CreateSceneEnum.none));
NavigationService.navigatorKey.currentContext!
.read<SmartSceneSelectBloc>()
.add(const SmartSceneClearEvent());
BlocProvider.of<EffectPeriodBloc>(
NavigationService.navigatorKey.currentState!.context)
.add(ResetEffectivePeriod());
NavigationService.navigatorKey.currentContext!
.read<CreateSceneBloc>()
.add(const ClearTabToRunSetting());
},
),
IconButton(
icon: const Icon(
Icons.more_vert,
size: 28,
),
style: ButtonStyle(
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {},
),
manageScene
? IconButton(
icon: const Icon(
Icons.add,
size: 32,
),
style: ButtonStyle(
foregroundColor:
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
),
onPressed: () {
Navigator.pushNamed(
NavigationService.navigatorKey.currentContext!,
Routes.sceneTasksRoute,
arguments: SceneSettingsRouteArguments(
sceneType: '',
sceneId: '',
sceneName: '',
),
);
NavigationService.navigatorKey.currentContext!
.read<CreateSceneBloc>()
.add(const ClearTaskListEvent());
NavigationService.navigatorKey.currentContext!
.read<CreateSceneBloc>()
.add(const SceneTypeEvent(CreateSceneEnum.none));
NavigationService.navigatorKey.currentContext!
.read<SmartSceneSelectBloc>()
.add(const SmartSceneClearEvent());
BlocProvider.of<EffectPeriodBloc>(
NavigationService.navigatorKey.currentState!.context)
.add(ResetEffectivePeriod());
NavigationService.navigatorKey.currentContext!
.read<CreateSceneBloc>()
.add(const ClearTabToRunSetting());
},
)
: const SizedBox(),
// IconButton(
// icon: const Icon(
// Icons.more_vert,
// size: 28,
// ),
// style: ButtonStyle(
// foregroundColor:
// WidgetStateProperty.all(ColorsManager.textPrimaryColor),
// ),
// onPressed: () {},
// ),
],
'Menu': [
IconButton(
icon: SvgPicture.asset(
Assets.assetsIconsScan,
height: 20,
width: 20,
),
onPressed: () {},
),
// IconButton(
// icon: SvgPicture.asset(
// Assets.assetsIconsScan,
// height: 20,
// width: 20,
// ),
// onPressed: () {},
// ),
],
};
static Map<String, Widget?> appBarLeading = {
'Dashboard': const AppBarHomeDropdown(),
// 'Dashboard': const AppBarHomeDropdown(),
'Devices': const AppBarHomeDropdown(),
'Routine': const AppBarHomeDropdown(),
'Menu': Padding(
@ -429,8 +566,7 @@ class HomeCubit extends Cubit<HomeState> {
};
static var bottomNavItems = [
defaultBottomNavBarItem(
icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
// defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
@ -438,13 +574,13 @@ class HomeCubit extends Cubit<HomeState> {
];
final List<Widget> pages = [
const DashboardView(),
// const DashboardView(),
// const LayoutPage(),
BlocProvider(
create: (context) => DevicesCubit.getInstance(),
child: const DevicesViewBody(),
),
const SceneView(),
const RoutinesView(),
const MenuView(),
];
@ -479,3 +615,28 @@ BottomNavigationBarItem defaultBottomNavBarItem(
label: label,
);
}
// class PermissionUtils {
// // Check if the "VIEW" permission exists in "MANAGE_SUBSPACE"
// static bool hasViewPermission(List<dynamic> permissions) {
// return _hasPermission(permissions, 'MANAGE_SUBSPACE', 'VIEW');
// }
// // Generalized permission checker
// static bool _hasPermission(
// List<dynamic> permissions, String mainTitle, String subTitle) {
// final mainOption = permissions.firstWhere(
// (perm) => perm['title'] == mainTitle,
// orElse: () => null,
// );
// if (mainOption != null) {
// final subOption = mainOption['subOptions'].firstWhere(
// (sub) => sub['title'] == subTitle,
// orElse: () => null,
// );
// return subOption != null && subOption['isChecked'] == true;
// }
// return false;
// }
// }

View File

@ -15,8 +15,8 @@ class HomeError extends HomeState {
class HomeSuccess extends HomeState {}
///specific states
//get spaces
class ActivationSuccess extends HomeState {}
class GetSpacesLoading extends HomeLoading {}
class GetSpacesSuccess extends HomeSuccess {
@ -32,6 +32,12 @@ class GetSpacesError extends HomeError {
//get rooms
class GetSpaceRoomsLoading extends HomeLoading {}
class ActivationError extends HomeLoading {
final String errMessage;
ActivationError({this.errMessage = ''});
}
class GetSpaceRoomsSuccess extends HomeSuccess {
final List<SubSpaceModel> rooms;
@ -58,9 +64,16 @@ class RoomSelected extends HomeState {
class RoomUnSelected extends HomeState {}
class NavChangePage extends HomeState {}
// Define new state classes
class HomePermissionUpdated extends HomeState {}
class HomeUserInfoLoaded extends HomeState {
final UserModel user;
HomeUserInfoLoaded(this.user);
}
class PermissionsRoleLoaded extends HomeState {
final List<PermissionModel> permissionModel;
PermissionsRoleLoaded(this.permissionModel);
}

View File

@ -0,0 +1,39 @@
class PermissionModel {
final String title;
final List<PermissionAttributes> subOptions;
PermissionModel({required this.title, required this.subOptions});
factory PermissionModel.fromJson(Map<String, dynamic> json) {
return PermissionModel(
title: json['title'],
subOptions: (json['subOptions'] as List)
.map((e) => PermissionAttributes.fromJson(e))
.toList(),
);
}
static List<PermissionModel> fromJsonList(List<dynamic> jsonList) {
return jsonList.map((json) => PermissionModel.fromJson(json)).toList();
}
}
class PermissionAttributes {
final String title;
final List<PermissionAttributes>? subOptions;
final bool? isChecked;
PermissionAttributes({required this.title, this.subOptions, this.isChecked});
factory PermissionAttributes.fromJson(Map<String, dynamic> json) {
return PermissionAttributes(
title: json['title'],
isChecked: json['isChecked'],
subOptions: json['subOptions'] != null
? (json['subOptions'] as List)
.map((e) => PermissionAttributes.fromJson(e))
.toList()
: null,
);
}
}

View File

@ -17,7 +17,10 @@ class AppLayout extends StatelessWidget {
child: BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) {
return DefaultScaffold(
appBar: HomeCubit.getInstance().spaces != null ? const DefaultAppBar() : null,
appBar: HomeCubit.getInstance().spaces != null &&
HomeCubit.getInstance().spaces!.isNotEmpty
? const DefaultAppBar()
: null,
bottomNavBar: const DefaultNavBar(),
child: const AppBody(),
);

View File

@ -12,62 +12,65 @@ class AppBarHomeDropdown extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) {
return Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: DropdownButton(
icon: const Icon(
Icons.expand_more,
color: ColorsManager.textPrimaryColor,
size: 16,
),
underline: const SizedBox.shrink(),
padding: EdgeInsets.zero,
borderRadius: BorderRadius.circular(20),
value: HomeCubit.getInstance().selectedSpace!.id,
items: HomeCubit.getInstance().spaces!.map((space) {
return DropdownMenuItem(
alignment: AlignmentDirectional.centerStart,
value: space.id,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SvgPicture.asset(
Assets.assetsIconsHome,
width: 25,
height: 25,
colorFilter: const ColorFilter.mode(
ColorsManager.textPrimaryColor,
BlendMode.srcIn,
return HomeCubit.getInstance().spaces != null || HomeCubit.getInstance().spaces!.isNotEmpty
? BlocBuilder<HomeCubit, HomeState>(
builder: (context, state) {
return Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: DropdownButton(
icon: const Icon(
Icons.expand_more,
color: ColorsManager.textPrimaryColor,
size: 16,
),
underline: const SizedBox.shrink(),
padding: EdgeInsets.zero,
borderRadius: BorderRadius.circular(20),
value: HomeCubit.getInstance().selectedSpace?.id ?? '',
items: HomeCubit.getInstance().spaces!.map((space) {
return DropdownMenuItem(
alignment: AlignmentDirectional.centerStart,
value: space.id,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SvgPicture.asset(
Assets.assetsIconsHome,
width: 25,
height: 25,
colorFilter: const ColorFilter.mode(
ColorsManager.textPrimaryColor,
BlendMode.srcIn,
),
),
const SizedBox(width: 5),
Flexible(
child: BodyMedium(
text: space.name,
style: context.bodyMedium.copyWith(
fontSize: 15,
color: ColorsManager.textPrimaryColor,
overflow: TextOverflow.ellipsis,
),
),
),
const SizedBox(width: 5),
],
),
),
const SizedBox(width: 5),
Flexible(
child: BodyMedium(
text: space.name,
style: context.bodyMedium.copyWith(
fontSize: 15,
color: ColorsManager.textPrimaryColor,
overflow: TextOverflow.ellipsis,
),
),
),
const SizedBox(width: 5),
],
);
}).toList(),
onChanged: (value) {
if (value != null) {
HomeCubit.getInstance().changeSelectedSpace(HomeCubit.getInstance()
.spaces!
.firstWhere((element) => element.id == value));
}
},
),
);
}).toList(),
onChanged: (value) {
if (value != null) {
HomeCubit.getInstance().changeSelectedSpace(
HomeCubit.getInstance().spaces!.firstWhere((element) => element.id == value));
}
},
),
);
},
);
)
: Container();
}
}

View File

@ -1,7 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.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/constants.dart';
class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
@ -19,10 +22,23 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
backgroundColor: Colors.transparent,
leadingWidth: 200,
toolbarHeight: Constants.appBarHeight,
leading: HomeCubit.getInstance().spaces!.isNotEmpty
? HomeCubit.appBarLeading[HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]!
leading: InkWell(
onTap: () {
final spaces = HomeCubit.getInstance().spaces!;
showSpaceBottomSheet(context, spaces);
},
child: HomeCubit.getInstance().spaces!.isNotEmpty
? AbsorbPointer(
absorbing: true,
child: HomeCubit.appBarLeading[HomeCubit
.bottomNavItems[HomeCubit.pageIndex].label]!,
)
: null,
),
actions: HomeCubit.manageScene
? HomeCubit.appBarActions[
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]
: null,
actions: HomeCubit.appBarActions[HomeCubit.bottomNavItems[HomeCubit.pageIndex].label],
));
},
);
@ -31,3 +47,83 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Size get preferredSize => Size.fromHeight(Constants.appBarHeight);
}
void showSpaceBottomSheet(BuildContext context, List<SpaceModel> spaces) {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setModalState) {
String? selectedSpaceId = HomeCubit.getInstance().selectedSpace?.id;
final bool shouldLimitHeight = spaces.length > 5;
return Container(
constraints: shouldLimitHeight
? BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.5,
)
: const BoxConstraints(),
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 10),
Container(
decoration: const BoxDecoration(color: Colors.black12),
height: 5,
width: 50,
),
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: spaces.length,
itemBuilder: (BuildContext context, int index) {
final space = spaces[index];
return Padding(
padding: const EdgeInsets.only(left: 30, right: 30),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Text(space.name),
],
),
Radio<String>(
value: space.id,
groupValue: selectedSpaceId,
onChanged: (String? newValue) {
if (newValue != null) {
setModalState(() {
selectedSpaceId = newValue;
});
HomeCubit.getInstance().changeSelectedSpace(
spaces.firstWhere((s) => s.id == newValue),
);
Navigator.of(context).pop();
}
},
),
],
),
);
},
separatorBuilder: (BuildContext context, int index) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 50),
child: const Divider(
color: Colors.grey,
thickness: 0.5,
),
);
},
),
],
),
),
);
},
);
},
);
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncrow_app/features/auth/model/login_with_email_model.dart';
import 'package:syncrow_app/features/auth/model/signup_model.dart';
@ -204,6 +205,7 @@ class AuthCubit extends Cubit<AuthState> {
const FlutterSecureStorage().write(
key: UserModel.userUuidKey,
value: Token.decodeToken(token.accessToken)['uuid'].toString());
user = UserModel.fromToken(token);
emailController.clear();
passwordController.clear();
@ -216,10 +218,24 @@ class AuthCubit extends Cubit<AuthState> {
signUp() async {
emit(AuthLoginLoading());
final response;
final clientId = dotenv.env['CLIENT_ID'] ?? '';
final clientSecret = dotenv.env['CLIENT_SECRET'] ?? '';
try {
List<String> userFullName = fullName.split(' ');
final clientToken = await AuthenticationAPI.fetchClientToken(
clientId: clientId,
clientSecret: clientSecret,
);
final accessToken = clientToken['accessToken'];
response = await AuthenticationAPI.signUp(
accessToken: accessToken,
model: SignUpModel(
hasAcceptedAppAgreement: true,
email: email.toLowerCase(),
password: signUpPassword,
firstName: userFullName[0],

View File

@ -0,0 +1,27 @@
class Project {
final String uuid;
final String name;
final String description;
const Project({
required this.uuid,
required this.name,
required this.description,
});
factory Project.fromJson(Map<String, dynamic> json) {
return Project(
uuid: json['uuid'] as String,
name: json['name'] as String,
description: json['description'] as String,
);
}
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'name': name,
'description': description,
};
}
}

View File

@ -3,10 +3,12 @@ class SignUpModel {
final String password;
final String firstName;
final String lastName;
final bool hasAcceptedAppAgreement;
SignUpModel(
{required this.email,
required this.password,
required this.hasAcceptedAppAgreement,
required this.firstName,
required this.lastName});
@ -15,7 +17,8 @@ class SignUpModel {
email: json['email'],
password: json['password'],
firstName: json['firstName'],
lastName: json['lastName']);
lastName: json['lastName'],
hasAcceptedAppAgreement: true);
}
Map<String, dynamic> toJson() {
@ -24,6 +27,7 @@ class SignUpModel {
'password': password,
'firstName': firstName,
'lastName': lastName,
"hasAcceptedAppAgreement": hasAcceptedAppAgreement
};
}
}

View File

@ -1,6 +1,6 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/auth/model/token.dart';
class UserModel {
@ -14,7 +14,14 @@ class UserModel {
final bool? isEmailVerified;
final String? regionName;
final String? timeZone;
final String? regionUuid;
final bool? isAgreementAccepted;
final bool? hasAcceptedWebAgreement;
final DateTime? webAgreementAcceptedAt;
final bool? hasAcceptedAppAgreement;
final DateTime? appAgreementAcceptedAt;
final Role? role;
final Project? project;
UserModel({
required this.uuid,
@ -24,10 +31,16 @@ class UserModel {
required this.profilePicture,
required this.phoneNumber,
required this.isEmailVerified,
required this.regionUuid,
required this.isAgreementAccepted,
required this.regionName, // Add this line
required this.timeZone, // Add this line
required this.regionName,
required this.timeZone,
required this.hasAcceptedWebAgreement,
required this.webAgreementAcceptedAt,
required this.hasAcceptedAppAgreement,
required this.appAgreementAcceptedAt,
required this.role,
required this.project,
});
factory UserModel.fromJson(Map<String, dynamic> json) {
@ -40,26 +53,47 @@ class UserModel {
phoneNumber: json['phoneNumber'],
isEmailVerified: json['isEmailVerified'],
isAgreementAccepted: json['isAgreementAccepted'],
regionName: json['region']?['regionName'], // Extract regionName
timeZone: json['timeZone']?['timeZoneOffset'], // Extract regionName
regionName: json['region']?['regionName'],
timeZone: json['timeZone']?['timeZoneOffset'],
regionUuid: json['region']?['uuid'],
hasAcceptedWebAgreement: json['hasAcceptedWebAgreement'],
webAgreementAcceptedAt: json['webAgreementAcceptedAt'] != null
? DateTime.parse(json['webAgreementAcceptedAt'])
: null,
hasAcceptedAppAgreement: json['hasAcceptedAppAgreement'],
appAgreementAcceptedAt: json['appAgreementAcceptedAt'] != null
? DateTime.parse(json['appAgreementAcceptedAt'])
: null,
role: json['role'] != null ? Role.fromJson(json['role']) : null,
project:
json['project'] != null ? Project.fromJson(json['project']) : null,
);
}
//uuid to json
//from token
factory UserModel.fromToken(Token token) {
factory UserModel.fromToken(Token token) {
Map<String, dynamic> tempJson = Token.decodeToken(token.accessToken);
return UserModel(
uuid: tempJson['uuid'].toString(),
email: tempJson['email'],
lastName: tempJson['lastName'],
firstName:tempJson['firstName'] ,
profilePicture: UserModel.decodeBase64Image(tempJson['profilePicture']),
phoneNumber: null,
isEmailVerified: null,
isAgreementAccepted: null,
regionName: tempJson['region']?['regionName'],
timeZone: tempJson['timezone']?['timeZoneOffset'],
);
uuid: tempJson['uuid'].toString(),
email: tempJson['email'],
lastName: tempJson['lastName'],
firstName: tempJson['firstName'],
profilePicture: UserModel.decodeBase64Image(tempJson['profilePicture']),
phoneNumber: null,
isEmailVerified: null,
isAgreementAccepted: null,
regionUuid: null,
regionName: tempJson['region']?['regionName'],
timeZone: tempJson['timezone']?['timeZoneOffset'],
hasAcceptedWebAgreement: tempJson['hasAcceptedWebAgreement'],
webAgreementAcceptedAt: tempJson['webAgreementAcceptedAt'] != null
? DateTime.parse(tempJson['webAgreementAcceptedAt'])
: null,
hasAcceptedAppAgreement: tempJson['hasAcceptedAppAgreement'],
appAgreementAcceptedAt: tempJson['appAgreementAcceptedAt'] != null
? DateTime.parse(tempJson['appAgreementAcceptedAt'])
: null,
role: tempJson['role'] != null ? Role.fromJson(tempJson['role']) : null,
project: null);
}
static Uint8List? decodeBase64Image(String? base64String) {
@ -71,14 +105,57 @@ class UserModel {
Map<String, dynamic> toJson() {
return {
'id': uuid,
'uuid': uuid,
'email': email,
'lastName': lastName,
'firstName': firstName,
'photoUrl': profilePicture,
'lastName': lastName,
'profilePicture':
profilePicture != null ? base64.encode(profilePicture!) : null,
'phoneNumber': phoneNumber,
'isEmailVerified': isEmailVerified,
'regionUuid': regionUuid,
'isAgreementAccepted': isAgreementAccepted,
'regionName': regionName,
'timeZone': timeZone,
'hasAcceptedWebAgreement': hasAcceptedWebAgreement,
'webAgreementAcceptedAt': webAgreementAcceptedAt?.toIso8601String(),
'hasAcceptedAppAgreement': hasAcceptedAppAgreement,
'appAgreementAcceptedAt': appAgreementAcceptedAt?.toIso8601String(),
'role': role?.toJson(),
};
}
}
class Role {
final String? uuid;
final DateTime? createdAt;
final DateTime? updatedAt;
final String? type;
Role({
required this.uuid,
required this.createdAt,
required this.updatedAt,
required this.type,
});
factory Role.fromJson(Map<String, dynamic> json) {
return Role(
uuid: json['uuid'],
createdAt:
json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt:
json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
type: json['type'],
);
}
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'type': type,
};
}
}

View File

@ -31,8 +31,7 @@ class LoginView extends StatelessWidget {
// content: Text(state.message),
// ),
// );
}
else if (state is AuthLoginSuccess) {
} else if (state is AuthLoginSuccess) {
Navigator.popAndPushNamed(context, Routes.homeRoute);
}
},
@ -96,8 +95,8 @@ class LoginView extends StatelessWidget {
height: 20,
),
const LoginForm(),
const LoginDivider(),
const LoginWithGoogleFacebook(),
// const LoginDivider(),
// const LoginWithGoogleFacebook(),
const DontHaveAnAccount(),
],
),

View File

@ -3,12 +3,15 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/menu/bloc/privacy_policy.dart';
import 'package:syncrow_app/features/menu/bloc/user_agreement.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/routing_constants.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/constants.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:syncrow_app/utils/resource_manager/styles_manager.dart';
@ -202,6 +205,93 @@ class SignUpView extends StatelessWidget {
hint: "At least 8 characters"),
),
const SizedBox(height: 40),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0),
child: Text.rich(
TextSpan(
text:
'By signing up you agree to our ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
fontSize: 16,
color: ColorsManager
.onPrimaryColor,
),
children: [
WidgetSpan(
child: GestureDetector(
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(
builder: (context) =>
const UserAgreement(),
));
},
child: BodyMedium(
text: 'Terms & Conditions',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(
decoration:
TextDecoration
.underline,
decorationColor:
ColorsManager
.onPrimaryColor,
color: ColorsManager
.onPrimaryColor,
fontSize: 16),
),
),
),
TextSpan(
text: ' and ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
fontSize: 16,
color: ColorsManager
.onPrimaryColor,
)),
WidgetSpan(
child: GestureDetector(
onTap: () {
Navigator.of(context)
.push(MaterialPageRoute(
builder: (context) =>
const PrivacyPolicy(),
));
},
child: BodyMedium(
text: 'Privacy Policy',
style: Theme.of(context)
.textTheme
.bodySmall
?.copyWith(
decoration:
TextDecoration
.underline,
decorationColor:
Colors.white,
color: ColorsManager
.onPrimaryColor,
fontSize: 16),
),
),
),
],
),
textAlign: TextAlign.center,
),
),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

View File

@ -0,0 +1,19 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class ProjectCubit extends Cubit<String?> {
final FlutterSecureStorage storage;
static const String projectKey = "selected_project_uuid";
ProjectCubit(this.storage) : super(null);
Future<void> setProjectUUID(String newUUID) async {
await storage.write(key: projectKey, value: newUUID);
emit(newUUID);
}
Future<void> clearProjectUUID() async {
await storage.delete(key: projectKey);
emit(null);
}
}

View File

@ -7,7 +7,7 @@ import 'package:syncrow_app/features/shared_widgets/create_unit.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
import 'widgets/energy_usage.dart';
// import 'widgets/energy_usage.dart';
class DashboardView extends StatelessWidget {
const DashboardView({super.key});
@ -29,7 +29,7 @@ class DashboardView extends StatelessWidget {
),
const LiveMonitorTab(),
const SizedBox(height: 10),
const EnergyUsage(),
// const EnergyUsage(),
Container(
padding: const EdgeInsets.only(top: 20),
constraints: const BoxConstraints(

View File

@ -1,178 +1,178 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/dashboard/view/widgets/energy_usage_header.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
// import 'package:fl_chart/fl_chart.dart';
// import 'package:flutter/material.dart';
// import 'package:syncrow_app/features/dashboard/view/widgets/energy_usage_header.dart';
// import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
// import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class EnergyUsage extends StatelessWidget {
const EnergyUsage({
super.key,
});
// class EnergyUsage extends StatelessWidget {
// const EnergyUsage({
// super.key,
// });
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const EnergyUsageHeader(),
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 150,
minHeight: 150,
),
child: LineChart(
LineChartData(
gridData: FlGridData(
show: true,
drawHorizontalLine: true,
horizontalInterval: 2,
drawVerticalLine: false,
getDrawingHorizontalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(.5),
strokeWidth: 1,
);
},
),
titlesData: FlTitlesData(
show: true,
rightTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
interval: 1,
getTitlesWidget: leftTitleWidgets,
reservedSize: 25,
),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 30,
interval: 12,
getTitlesWidget: (value, meta) {
switch (value.toInt()) {
case 0:
return SideTitleWidget(
axisSide: meta.axisSide,
child: const BodySmall(text: '1'),
);
// @override
// Widget build(BuildContext context) {
// return DecoratedBox(
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(15),
// ),
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
// child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// const EnergyUsageHeader(),
// ConstrainedBox(
// constraints: const BoxConstraints(
// maxHeight: 150,
// minHeight: 150,
// ),
// child: LineChart(
// LineChartData(
// gridData: FlGridData(
// show: true,
// drawHorizontalLine: true,
// horizontalInterval: 2,
// drawVerticalLine: false,
// getDrawingHorizontalLine: (value) {
// return FlLine(
// color: Colors.grey.withOpacity(.5),
// strokeWidth: 1,
// );
// },
// ),
// titlesData: FlTitlesData(
// show: true,
// rightTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: true,
// interval: 1,
// getTitlesWidget: leftTitleWidgets,
// reservedSize: 25,
// ),
// ),
// topTitles: const AxisTitles(
// sideTitles: SideTitles(showTitles: false),
// ),
// bottomTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: true,
// reservedSize: 30,
// interval: 12,
// getTitlesWidget: (value, meta) {
// switch (value.toInt()) {
// case 0:
// return SideTitleWidget(
// axisSide: meta.axisSide,
// child: const BodySmall(text: '1'),
// );
case 11:
return SideTitleWidget(
axisSide: meta.axisSide,
child: const BodySmall(text: '28'),
);
default:
return Container();
}
},
),
),
leftTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
),
minX: 0,
maxX: 11,
minY: 0,
maxY: 6,
lineBarsData: [
LineChartBarData(
spots: const [
FlSpot(0, 3),
FlSpot(2.6, 2),
FlSpot(4.9, 5),
FlSpot(6.8, 3.1),
FlSpot(8, 4),
FlSpot(9.5, 3),
FlSpot(11, 4),
],
isCurved: true,
gradient: LinearGradient(
colors: [
ColorsManager.primaryColor,
ColorsManager.primaryColor.withOpacity(0.3),
],
),
barWidth: 5,
isStrokeCapRound: true,
dotData: const FlDotData(
show: false,
),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: [
ColorsManager.primaryColor.withOpacity(0.5),
ColorsManager.primaryColor.withOpacity(0.1),
],
),
),
),
],
),
),
)
],
),
),
);
}
// case 11:
// return SideTitleWidget(
// axisSide: meta.axisSide,
// child: const BodySmall(text: '28'),
// );
// default:
// return Container();
// }
// },
// ),
// ),
// leftTitles: const AxisTitles(
// sideTitles: SideTitles(showTitles: false),
// ),
// ),
// minX: 0,
// maxX: 11,
// minY: 0,
// maxY: 6,
// lineBarsData: [
// LineChartBarData(
// spots: const [
// FlSpot(0, 3),
// FlSpot(2.6, 2),
// FlSpot(4.9, 5),
// FlSpot(6.8, 3.1),
// FlSpot(8, 4),
// FlSpot(9.5, 3),
// FlSpot(11, 4),
// ],
// isCurved: true,
// gradient: LinearGradient(
// colors: [
// ColorsManager.primaryColor,
// ColorsManager.primaryColor.withOpacity(0.3),
// ],
// ),
// barWidth: 5,
// isStrokeCapRound: true,
// dotData: const FlDotData(
// show: false,
// ),
// belowBarData: BarAreaData(
// show: true,
// gradient: LinearGradient(
// colors: [
// ColorsManager.primaryColor.withOpacity(0.5),
// ColorsManager.primaryColor.withOpacity(0.1),
// ],
// ),
// ),
// ),
// ],
// ),
// ),
// )
// ],
// ),
// ),
// );
// }
Widget leftTitleWidgets(double value, TitleMeta meta) {
String text;
switch (value.toInt()) {
case 1:
text = '1K';
break;
case 3:
text = '3k';
break;
case 5:
text = '5k';
break;
default:
return Container();
}
// Widget leftTitleWidgets(double value, TitleMeta meta) {
// String text;
// switch (value.toInt()) {
// case 1:
// text = '1K';
// break;
// case 3:
// text = '3k';
// break;
// case 5:
// text = '5k';
// break;
// default:
// return Container();
// }
return Center(child: BodySmall(text: text));
}
// return Center(child: BodySmall(text: text));
// }
Widget bottomTitleWidgets(double value, TitleMeta meta) {
// const style = TextStyle(
// fontWeight: FontWeight.bold,
// fontSize: 16,
// );
// Widget text;
// switch (value.toInt()) {
// case 2:
// text = const Text('MAR', style: style);
// break;
// case 5:
// text = const Text('JUN', style: style);
// break;
// case 8:
// text = const Text('SEP', style: style);
// break;
// default:
// text = const Text('', style: style);
// break;
// }
// Widget bottomTitleWidgets(double value, TitleMeta meta) {
// // const style = TextStyle(
// // fontWeight: FontWeight.bold,
// // fontSize: 16,
// // );
// // Widget text;
// // switch (value.toInt()) {
// // case 2:
// // text = const Text('MAR', style: style);
// // break;
// // case 5:
// // text = const Text('JUN', style: style);
// // break;
// // case 8:
// // text = const Text('SEP', style: style);
// // break;
// // default:
// // text = const Text('', style: style);
// // break;
// // }
return SideTitleWidget(
axisSide: meta.axisSide,
child: const BodySmall(text: 'Feb'),
);
}
}
// return SideTitleWidget(
// axisSide: meta.axisSide,
// child: const BodySmall(text: 'Feb'),
// );
// }
// }

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/6_scene_switch_bloc/6_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
@ -16,6 +17,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
@ -112,8 +114,9 @@ class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
FetchRoomsEvent event, Emitter<SixSceneState> emit) async {
try {
emit(SixSceneLoadingState());
Project? project = HomeCubit.getInstance().project;
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid, event.unit.id, project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(SixSceneFailedState(errorMessage: e.toString()));
@ -125,12 +128,14 @@ class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
try {
emit(SixSceneLoadingState());
if (_hasSelectionChanged) {
Project? project = HomeCubit.getInstance().project;
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, sixSceneId);
event.unit.community.uuid, event.unit.id, event.roomId, sixSceneId, project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
allDevices.forEach((element) {
allDevicesIds.add(element.uuid!);
@ -341,8 +346,10 @@ class SixSceneBloc extends Bloc<SixSceneEvent, SixSceneState> {
emit(SixSceneLoadingState());
try {
Project? project = HomeCubit.getInstance().project;
allScenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
event.unitId, event.unit.community.uuid, project?.uuid ?? TempConst.projectIdDev,
showInDevice: event.showInDevice);
filteredScenes = allScenes;

View File

@ -14,6 +14,7 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
class ACsBloc extends Bloc<AcsEvent, AcsState> {
final String acId;
AcStatusModel deviceStatus = AcStatusModel(
countdown1: 0,
uuid: '',
acSwitch: true,
modeString: 'hot',
@ -26,7 +27,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
bool allAcsPage = false;
bool allAcsOn = true;
bool allTempSame = true;
int globalTemp = 25;
int globalTemp = 250;
Timer? _timer;
ACsBloc({required this.acId}) : super(AcsInitialState()) {
@ -41,6 +42,12 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
on<IncreaseAllTemp>(_increaseAllTemp);
on<DecreaseAllTemp>(_decreaseAllTemp);
on<AcUpdated>(_onAcUpdated);
on<OnClose>(_onClose);
on<GetCounterEvent>(_getCounterValue);
on<SetCounterValue>(_setCounterValue);
on<TickTimer>(_onTickTimer);
// on<SetTimeOutValue>(_setTimeOutAlarm);
}
void _fetchAcsStatus(AcsInitial event, Emitter<AcsState> emit) async {
@ -64,7 +71,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
emit(GetAcStatusState(acStatusModel: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges(acId);
}
} catch (e) {
emit(AcsFailedState(errorMessage: e.toString()));
@ -72,25 +79,38 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(acId) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$acId');
_streamSubscription?.cancel();
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>;
_streamSubscription = 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);
deviceStatus = AcStatusModel.fromJson(usersMap['productUuid'], statusList);
add(AcUpdated());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_onAcUpdated(AcUpdated event, Emitter<AcsState> emit) {
emit(GetAcStatusState(acStatusModel: deviceStatus));
}
@ -102,13 +122,16 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'AC');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
_listenToChanges(devicesList[i].uuid);
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatusList.add(AcStatusModel.fromJson(response['productUuid'], statusModelList));
deviceStatusList.add(AcStatusModel.fromJson(devicesList[i].uuid ?? '', statusModelList));
}
_setAllAcsTempsAndSwitches();
}
@ -117,10 +140,11 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.acSwitch = acSwitchValue;
}
}
_setAllAcsTempsAndSwitches();
_emitAcsStatus(emit);
} else {
@ -206,7 +230,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.tempSet = value;
}
}
@ -234,7 +258,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.tempSet = value;
}
}
@ -254,7 +278,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.modeString = getACModeString(tempMode);
ac.acMode = AcStatusModel.getACMode(getACModeString(tempMode));
}
@ -279,7 +303,7 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
if (allAcsPage) {
emit(AcsLoadingState());
for (AcStatusModel ac in deviceStatusList) {
if (ac.uuid == event.productId) {
if (ac.uuid == event.deviceId) {
ac.fanSpeedsString = getNextFanSpeedKey(fanSpeed);
ac.acFanSpeed = AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed));
}
@ -312,17 +336,15 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
allAcsOn = true;
allTempSame = true;
if (deviceStatusList.isNotEmpty) {
int temp = deviceStatusList[0].tempSet;
deviceStatusList.firstWhere((element) {
int temp = deviceStatusList.first.tempSet;
for (var element in deviceStatusList) {
if (!element.acSwitch) {
allAcsOn = false;
}
if (element.tempSet != temp) {
allTempSame = false;
}
return true;
});
}
if (allTempSame) {
globalTemp = temp;
}
@ -396,4 +418,74 @@ class ACsBloc extends Bloc<AcsEvent, AcsState> {
allTempSame: allTempSame,
temp: globalTemp));
}
void _setCounterValue(SetCounterValue event, Emitter<AcsState> emit) async {
emit(AcsLoadingState());
int seconds = 0;
try {
seconds = event.seconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: acId, code: 'countdown_time', value: event.duration), acId);
if (response['success'] ?? false) {
deviceStatus.countdown1 = seconds;
} else {
emit(const AcsFailedState(errorMessage: 'Something went wrong'));
return;
}
} catch (e) {
emit(AcsFailedState(errorMessage: e.toString()));
return;
}
if (event.duration > 0) {
_onStartTimer(seconds);
} else {
_timer?.cancel();
emit(TimerRunComplete());
}
}
void _getCounterValue(GetCounterEvent event, Emitter<AcsState> emit) async {
emit(AcsLoadingState());
var response = await DevicesAPI.getDeviceStatus(acId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = AcStatusModel.fromJson(response['productUuid'], statusModelList);
deviceStatus.countdown1;
var duration;
if (deviceStatus.countdown1 == 5) {
duration = const Duration(minutes: 30);
var countNum = duration.inSeconds;
_onStartTimer(countNum);
} else if (deviceStatus.countdown1 > 5) {
duration = Duration(minutes: deviceStatus.countdown1 * 6);
var countNum = duration.inSeconds;
_onStartTimer(countNum);
} else {
_timer?.cancel();
emit(TimerRunComplete());
}
}
void _onStartTimer(int seconds) {
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
add(TickTimer(remainingTime: seconds - timer.tick));
});
}
void _onTickTimer(TickTimer event, Emitter<AcsState> emit) {
if (event.remainingTime > 0) {
emit(TimerRunInProgress(event.remainingTime));
} else {
_timer?.cancel();
emit(TimerRunComplete());
}
}
void _onClose(OnClose event, Emitter<AcsState> emit) {
_timer?.cancel(); // Cancel the timer
}
}

View File

@ -14,7 +14,8 @@ class AcSwitch extends AcsEvent {
final bool acSwitch;
final String deviceId;
final String productId;
const AcSwitch({required this.acSwitch, this.deviceId = '', this.productId = ''});
const AcSwitch(
{required this.acSwitch, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [acSwitch, deviceId, productId];
@ -35,7 +36,8 @@ class IncreaseCoolToTemp extends AcsEvent {
final double value;
final String deviceId;
final String productId;
const IncreaseCoolToTemp({required this.value, this.deviceId = '', this.productId = ''});
const IncreaseCoolToTemp(
{required this.value, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [value, deviceId];
@ -46,7 +48,8 @@ class DecreaseCoolToTemp extends AcsEvent {
final String deviceId;
final String productId;
const DecreaseCoolToTemp({required this.value, this.deviceId = '', this.productId = ''});
const DecreaseCoolToTemp(
{required this.value, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [value, deviceId];
@ -56,7 +59,8 @@ class ChangeAcMode extends AcsEvent {
final TempModes tempModes;
final String deviceId;
final String productId;
const ChangeAcMode({required this.tempModes, this.deviceId = '', this.productId = ''});
const ChangeAcMode(
{required this.tempModes, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [tempModes, deviceId, productId];
@ -67,7 +71,8 @@ class ChangeFanSpeed extends AcsEvent {
final String deviceId;
final String productId;
const ChangeFanSpeed({required this.fanSpeeds, this.deviceId = '', this.productId = ''});
const ChangeFanSpeed(
{required this.fanSpeeds, this.deviceId = '', this.productId = ''});
@override
List<Object> get props => [fanSpeeds, deviceId, productId];
@ -104,3 +109,52 @@ class DecreaseAllTemp extends AcsEvent {
@override
List<Object> get props => [value];
}
class SetCounterValue extends AcsEvent {
final int duration;
final String deviceCode;
final int seconds;
const SetCounterValue(
{required this.duration,
required this.deviceCode,
required this.seconds});
@override
List<Object> get props => [duration, deviceCode, seconds];
}
class SetTimeOutValue extends AcsEvent {
final Duration duration;
final String deviceCode;
const SetTimeOutValue({required this.duration, required this.deviceCode});
@override
List<Object> get props => [duration, deviceCode];
}
class StartTimer extends AcsEvent {
final int duration;
const StartTimer(this.duration);
@override
List<Object> get props => [duration];
}
class TickTimer extends AcsEvent {
final int remainingTime;
const TickTimer({required this.remainingTime});
@override
List<Object> get props => [remainingTime];
}
class StopTimer extends AcsEvent {}
class GetCounterEvent extends AcsEvent {
final String deviceCode;
const GetCounterEvent({required this.deviceCode});
@override
List<Object> get props => [deviceCode];
}
class OnClose extends AcsEvent {}

View File

@ -63,3 +63,22 @@ class AcsFailedState extends AcsState {
@override
List<Object> get props => [errorMessage];
}
class UpdateTimerState extends AcsState {
final int seconds;
const UpdateTimerState({required this.seconds});
@override
List<Object> get props => [seconds];
}
class TimerRunInProgress extends AcsState {
final int remainingTime;
const TimerRunInProgress(this.remainingTime);
@override
List<Object> get props => [remainingTime];
}
class TimerRunComplete extends AcsState {}

View File

@ -1,3 +1,6 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
@ -5,6 +8,7 @@ import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_st
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.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_report_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
@ -17,9 +21,11 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
on<InitialEvent>(_fetchCeilingSensorStatus);
on<ChangeValueEvent>(_changeValue);
on<CeilingSensorUpdated>(_onCeilingSensorUpdated);
on<ReportLogsInitial>(fetchLogsForLastMonth);
}
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<CeilingSensorState> emit) async {
void _fetchCeilingSensorStatus(
InitialEvent event, Emitter<CeilingSensorState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -29,46 +35,105 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
}
deviceStatus = CeilingSensorModel.fromJson(statusModelList);
emit(UpdateState(ceilingSensorModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
Timer? _timer;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
_streamSubscription?.cancel();
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>;
_streamSubscription = 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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = CeilingSensorModel.fromJson(statusList);
add(CeilingSensorUpdated());
if (!isClosed) {
add(CeilingSensorUpdated());
}
});
} catch (_) {}
}
_onCeilingSensorUpdated(CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_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));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: event.code, value: event.value), deviceId);
DeviceControlModel(
deviceId: deviceId, code: event.code, value: event.value),
deviceId);
if (response['success'] ?? false) {
deviceStatus.sensitivity = event.value;
}
if (event.type == 'Sensitivity') {
deviceStatus.sensitivity = event.value;
} else if (event.type == 'Maximum Distance') {
deviceStatus.movingMaxDis = event.value;
} else if (event.type == 'Nobody Time') {
deviceStatus.nobodyTime = event.value;
} else if (event.type == 'Space Type') {
deviceStatus.spaceType = SpaceTypes.values.firstWhere(
(e) => e.name == event.value,
orElse: () => SpaceTypes.none,
);
}
} //scene
emit(UpdateState(ceilingSensorModel: deviceStatus));
} catch (_) {}
emit(UpdateState(ceilingSensorModel: deviceStatus));
}
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<CeilingSensorState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
int startTime = lastMonth.millisecondsSinceEpoch;
int endTime = now.millisecondsSinceEpoch;
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getReportLogs(
startTime: startTime.toString(),
endTime: endTime.toString(),
deviceUuid: deviceId,
code: 'presence_state',
);
recordGroups = response;
// print('---${jsonEncode(recordGroups.data.first.)}');
emit(FitchData());
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FailedState(error: errorMessage));
}
}
}

View File

@ -14,10 +14,16 @@ class InitialEvent extends CeilingSensorEvent {}
class CeilingSensorUpdated extends CeilingSensorEvent {}
class ChangeValueEvent extends CeilingSensorEvent {
final int value;
final dynamic value;
final String code;
const ChangeValueEvent({required this.value, required this.code});
final String type;
const ChangeValueEvent({required this.value, required this.code,required this.type});
@override
List<Object> get props => [value, code];
List<Object> get props => [value, code,type];
}
class ReportLogsInitial extends CeilingSensorEvent {
const ReportLogsInitial();
}

View File

@ -10,6 +10,8 @@ class CeilingSensorState extends Equatable {
class InitialState extends CeilingSensorState {}
class FitchData extends CeilingSensorState {}
class LoadingInitialState extends CeilingSensorState {}
class UpdateState extends CeilingSensorState {

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dart';
@ -30,6 +32,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
on<InitialWizardEvent>(_fetchWizardStatus);
on<GroupAllOffEvent>(_groupAllOff);
on<GroupAllOnEvent>(_groupAllOn);
on<UpdateCurtainEvent>(_updateCurtain);
}
Future<void> _onOpenCurtain(
@ -161,7 +164,10 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async {
try {
emit(CurtainLoadingState());
_listenToChanges(curtainId);
var response = await DevicesAPI.getDeviceStatus(curtainId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -169,7 +175,6 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
openPercentage = double.tryParse(statusModelList[1].value.toString())!;
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
@ -181,6 +186,76 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
}
}
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(curtainId) {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$curtainId');
Stream<DatabaseEvent> stream = ref.onValue;
_streamSubscription = 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']));
});
openPercentage = double.tryParse(statusList[1].value.toString())!;
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
add(UpdateCurtainEvent());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
// _listenToChanges(curtainId) {
// try {
// print('curtainId=$curtainId');
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$curtainId');
// 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> statusModelList = [];
// for (var status in usersMap['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// print('statusModelList==${statusModelList}');
// }
// openPercentage = double.tryParse(statusModelList[1].value.toString())!;
// curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
// blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
// add(UpdateCurtainEvent());
// });
// } catch (_) {}
// }
_updateCurtain(UpdateCurtainEvent event, Emitter<CurtainState> emit) {
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
emit(CurtainsOpening(
curtainWidth: curtainWidth,
blindHeight: blindHeight,
openPercentage: openPercentage,
));
}
List<GroupCurtainModel> groupList = [];
bool allSwitchesOn = true;
List<DeviceModel> devicesList = [];

View File

@ -33,6 +33,7 @@ class InitCurtain extends CurtainEvent {}
class PauseCurtain extends CurtainEvent {}
class useCurtainEvent extends CurtainEvent {}
class InitialWizardEvent extends CurtainEvent {}
class UpdateCurtainEvent extends CurtainEvent {}
class ChangeFirstWizardSwitchStatusEvent extends CurtainEvent {

View File

@ -2,13 +2,18 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
DeviceManagerBloc() : super(DeviceManagerState.initial()) {
@ -29,10 +34,13 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
emit(state.copyWith(loading: true));
try {
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId();
emit(state.copyWith(devices: allDevices, loading: false));
Project? project = HomeCubit.getInstance().project;
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId(
project?.uuid ?? TempConst.projectIdDev);
emit(state.copyWith(
devices: _getOnlyImplementedDevices(allDevices), loading: false));
} catch (e) {
print(e);
emit(state.copyWith(error: e.toString(), loading: false));
}
}
@ -41,12 +49,16 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
FetchDevicesByRoomId event, Emitter<DeviceManagerState> emit) async {
emit(state.copyWith(loading: true));
try {
Project? project = HomeCubit.getInstance().project;
final devices = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId,
);
emit(state.copyWith(devices: devices, loading: false));
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
emit(state.copyWith(
devices: _getOnlyImplementedDevices(devices), loading: false));
} catch (e) {
emit(state.copyWith(error: e.toString(), loading: false));
}
@ -156,4 +168,23 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
emit(state.copyWith(functionsLoading: false, error: e.toString()));
}
}
List<DeviceModel> _getOnlyImplementedDevices(List<DeviceModel> devices) {
const allowedDeviceTypes = {
DeviceType.AC,
DeviceType.DoorLock,
DeviceType.Gateway,
DeviceType.WallSensor,
DeviceType.CeilingSensor,
DeviceType.ThreeGang,
DeviceType.OneGang,
DeviceType.TwoGang,
DeviceType.WH,
DeviceType.FlushMountedSensor,
};
return devices
.where((device) => allowedDeviceTypes.contains(device.productType))
.toList();
}
}

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/device_settings_bloc/device_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/device_settings_bloc/device_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
@ -18,6 +19,7 @@ import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class DeviceSettingBloc extends Bloc<DeviceSettingEvent, DeviceSettingState> {
@ -349,13 +351,20 @@ class DeviceSettingBloc extends Bloc<DeviceSettingEvent, DeviceSettingState> {
AssignRoomEvent event, Emitter<DeviceSettingState> emit) async {
try {
emit(DeviceSettingLoadingState());
Project? project = HomeCubit.getInstance().project;
if (_hasSelectionChanged) {
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, deviceId);
event.unit.community.uuid,
event.unit.id,
event.roomId,
deviceId,
project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
allDevices.forEach((element) {
allDevicesIds.add(element.uuid!);
@ -375,8 +384,12 @@ class DeviceSettingBloc extends Bloc<DeviceSettingEvent, DeviceSettingState> {
FetchRoomsEvent event, Emitter<DeviceSettingState> emit) async {
try {
emit(DeviceSettingLoadingState());
Project? project = HomeCubit.getInstance().project;
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid,
event.unit.id,
project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(

View File

@ -1,10 +1,14 @@
// ignore_for_file: constant_identifier_names, unused_import
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.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/model/space_model.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
@ -19,6 +23,7 @@ import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/network_exception.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
part 'devices_state.dart';
@ -31,6 +36,7 @@ class DevicesCubit extends Cubit<DevicesState> {
// Fetch groups based on the selected space ID
await fetchGroups(selectedSpace.id);
await fetchAllDevices(selectedSpace);
}
DevicesCubit._() : super(DevicesInitial()) {
@ -60,6 +66,43 @@ class DevicesCubit extends Cubit<DevicesState> {
}
}
Timer? _timer;
final Map<String, StreamSubscription<DatabaseEvent>> _deviceSubscriptions =
{};
void _listenToChanges(deviceId) {
try {
if (_deviceSubscriptions.containsKey(deviceId)) {
_deviceSubscriptions[deviceId]?.cancel();
_deviceSubscriptions.remove(deviceId);
}
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
final subscription = 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>;
// print('object-----${usersMap['status']}');
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
emitSafe(GetDevicesLoading());
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceId);
if (deviceIndex != -1) {
allDevices[deviceIndex].status = statusList;
}
emitSafe(GetDevicesSuccess(allDevices));
});
_deviceSubscriptions[deviceId] = subscription;
} catch (_) {}
}
static DevicesCubit get(context) => BlocProvider.of(context);
List<DevicesCategoryModel>? allCategories;
@ -109,17 +152,6 @@ class DevicesCubit extends Cubit<DevicesState> {
}
// Getter to retrieve all devices from HomeCubit
List<DeviceModel> get allDevices {
List<DeviceModel> devices = [];
if (HomeCubit.getInstance().selectedSpace != null) {
for (var room in HomeCubit.getInstance().selectedSpace!.subspaces) {
if (room.devices != null) {
devices.addAll(room.devices!);
}
}
}
return devices;
}
// DevicesCategoryModel? get chosenCategory {
// for (var category in allCategories!) {
@ -267,36 +299,36 @@ class DevicesCubit extends Cubit<DevicesState> {
}
///////////////////////// API CALLS //////////////////////////
deviceControl(DeviceControlModel control, String deviceId) async {
emitSafe(DeviceControlLoading(
code: control.code,
));
try {
var response = await DevicesAPI.controlDevice(control, deviceId);
// deviceControl(DeviceControlModel control, String deviceId) async {
// emitSafe(DeviceControlLoading(
// code: control.code,
// ));
// try {
// var response = await DevicesAPI.controlDevice(control, deviceId);
if (response['success'] ?? false) {
emitSafe(DeviceControlSuccess(code: control.code));
//this delay is to give tuya server time to update the status
// Future.delayed(const Duration(milliseconds: 400), () {
fetchDevicesStatues(
deviceId,
HomeCubit.getInstance()
.selectedSpace!
.subspaces
.indexOf(HomeCubit.getInstance().selectedRoom!),
code: control.code);
// });
} else {
emitSafe(DeviceControlError('Failed to control the device'));
}
} catch (failure) {
emitSafe(DeviceControlError(failure.toString()));
return;
}
}
// if (response['success'] ?? false) {
// emitSafe(DeviceControlSuccess(code: control.code));
// //this delay is to give tuya server time to update the status
// // Future.delayed(const Duration(milliseconds: 400), () {
// fetchDevicesStatues(
// deviceId,
// HomeCubit.getInstance()
// .selectedSpace!
// .subspaces
// .indexOf(HomeCubit.getInstance().selectedRoom!),
// code: control.code);
// // });
// } else {
// emitSafe(DeviceControlError('Failed to control the device'));
// }
// } catch (failure) {
// emitSafe(DeviceControlError(failure.toString()));
// return;
// }
// }
fetchGroups(String spaceId) async {
emitSafe(DevicesCategoriesLoading());
emitSafe(GetDevicesLoading());
try {
allCategories = await DevicesAPI.fetchGroups(spaceId);
} catch (e) {
@ -319,14 +351,20 @@ class DevicesCubit extends Cubit<DevicesState> {
.subspaces
.indexWhere((element) => element.id == roomId);
try {
Project? project = HomeCubit.getInstance().project;
HomeCubit.getInstance().selectedSpace!.subspaces[roomIndex].devices =
await DevicesAPI.getDevicesByRoomId(
communityUuid: unit!.community.uuid, spaceUuid: unit.id, roomId: roomId);
communityUuid: unit!.community.uuid,
spaceUuid: unit.id,
roomId: roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
} catch (e) {
emitSafe(GetDevicesError(e.toString()));
return;
}
final devices = HomeCubit.getInstance().selectedSpace!.subspaces[roomIndex].devices;
final devices =
HomeCubit.getInstance().selectedSpace!.subspaces[roomIndex].devices;
emitSafe(GetDevicesSuccess(devices));
//get status for each device
@ -356,8 +394,11 @@ class DevicesCubit extends Cubit<DevicesState> {
emitSafe(GetDeviceStatusError(e.toString()));
return;
}
HomeCubit.getInstance().selectedSpace!.subspaces[roomIndex].devices![deviceIndex].status =
statuses;
HomeCubit.getInstance()
.selectedSpace!
.subspaces[roomIndex]
.devices![deviceIndex]
.status = statuses;
emitSafe(GetDeviceStatusSuccess(code: code));
}
@ -406,6 +447,365 @@ class DevicesCubit extends Cubit<DevicesState> {
// emitSafe(LightBrightnessChanged(value));
// }
// }
// List<DeviceModel> _fetchedDevices = [];
// List<DeviceModel> get allDevices => _fetchedDevices;
List<DeviceModel> allDevices = [];
Future<void> fetchAllDevices(SpaceModel? unit) async {
emitSafe(GetDevicesLoading());
try {
Project? project = HomeCubit.getInstance().project;
final devices = await DevicesAPI.getAllDevices(
communityUuid: unit!.community.uuid,
spaceUuid: unit.id,
projectId: project?.uuid ?? TempConst.projectIdDev);
allDevices = devices;
for (var deviceId in allDevices) {
if (deviceId.type == "3G" ||
deviceId.type == "2G" ||
deviceId.type == "1G" ||
deviceId.type == "3GT" ||
deviceId.type == "2GT" ||
deviceId.type == "1GT" ||
deviceId.type == "WH" ||
deviceId.type == "CUR" ||
deviceId.type == "AC") {
_listenToChanges(deviceId.uuid);
}
}
emitSafe(GetDevicesSuccess(allDevices));
} catch (e) {
emitSafe(GetDevicesError(e.toString()));
}
}
bool isDeviceOn(DeviceModel device) {
final switchStatuses = device.status.where(
(s) => (s.code?.startsWith('switch') ?? false),
);
final anySwitchFalse = switchStatuses.any((s) => s.value == false);
return !anySwitchFalse;
}
void updateDeviceStatus(String deviceId, bool newToggleStatus) {
emitSafe(GetDevicesLoading());
// Create a fresh copy of the device list.
final updatedDevices = List<DeviceModel>.from(allDevices);
for (int i = 0; i < updatedDevices.length; i++) {
final device = updatedDevices[i];
if (device.uuid == deviceId) {
updatedDevices[i] = DeviceModel(
activeTime: device.activeTime,
localKey: device.localKey,
model: device.model,
name: device.name,
icon: device.icon,
categoryName: device.categoryName,
type: device.type,
isOnline: device.isOnline,
status: device.status, // Make sure to keep the same status list
productName: device.productName,
timeZone: device.timeZone,
updateTime: device.updateTime,
uuid: device.uuid,
productUuid: device.productUuid,
productType: device.productType,
subspace: device.subspace,
toggleStatus: newToggleStatus,
);
break;
}
}
emit(GetDevicesSuccess(updatedDevices));
}
Future<void> threeGangToggle(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final switches = ['switch_1', 'switch_2', 'switch_3'];
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
final targetState = anySwitchOff ? true : false;
for (final switchCode in switches) {
final statusIndex =
device.status.indexWhere((s) => s.code == switchCode);
if (statusIndex != -1) {
final currentValue = device.status[statusIndex].value ?? false;
if (!targetState && !currentValue) {
continue;
}
final controlRequest = DeviceControlModel(
code: switchCode, value: targetState, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
if (response['success'] != true) {
throw Exception('Failed to toggle $switchCode');
}
device.status[statusIndex].value = targetState;
}
}
device.toggleStatus = device.status.every(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == true),
);
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} catch (failure) {
emit(DeviceControlError(failure.toString()));
}
}
Future<void> towGangToggle(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final switches = [
'switch_1',
'switch_2',
];
for (final switchCode in switches) {
final statusIndex =
device.status.indexWhere((s) => s.code == switchCode);
if (statusIndex != -1) {
final toggledValue = control.value;
final controlRequest = DeviceControlModel(
code: switchCode, value: toggledValue, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
device.status[statusIndex].value = response['result'];
}
}
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} catch (failure) {
emit(DeviceControlError(failure.toString()));
}
}
Future<void> towGTGangToggle(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final switches = [
'switch_1',
'switch_2',
];
for (final switchCode in switches) {
final statusIndex =
device.status.indexWhere((s) => s.code == switchCode);
if (statusIndex != -1) {
final toggledValue = control.value;
final controlRequest = DeviceControlModel(
code: switchCode, value: toggledValue, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
device.status[statusIndex].value = response['result'];
}
}
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} catch (failure) {
emit(DeviceControlError(failure.toString()));
}
}
Future<void> oneGangToggle(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final statusIndex = device.status.indexWhere((s) => s.code == 'switch_1');
if (statusIndex != -1) {
final toggledValue = control.value;
final controlRequest = DeviceControlModel(
code: 'switch_1', value: toggledValue, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
if (response['result'] != true) {
throw Exception('Failed to toggle switch_1');
}
device.status[statusIndex].value = response['result'];
}
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} catch (failure) {
emit(DeviceControlError(failure.toString()));
}
}
Future<void> oneGTGangToggle(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final statusIndex = device.status.indexWhere((s) => s.code == 'switch_1');
if (statusIndex != -1) {
final currentValue = device.status[statusIndex].value ?? false;
final toggledValue = !currentValue;
final controlRequest = DeviceControlModel(
code: 'switch_1', value: toggledValue, deviceId: deviceUuid);
final response =
await DevicesAPI.controlDevice(controlRequest, deviceUuid);
if (response['result'] != true) {
throw Exception('Failed to toggle switch_1');
}
device.status[statusIndex].value = response['result'];
}
final anySwitchOff = device.status.any(
(s) => (s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} catch (failure) {
emit(DeviceControlError(failure.toString()));
}
}
Future<void> deviceControl(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final response = await DevicesAPI.controlDevice(control, deviceUuid);
if (response['success'] == true) {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex != -1) {
final device = allDevices[deviceIndex];
final statusIndex =
device.status.indexWhere((s) => s.code == control.code);
if (statusIndex != -1) {
device.status[statusIndex].value = control.value;
}
final anySwitchOff = device.status.any(
(s) =>
(s.code?.startsWith('switch_') ?? false) && (s.value == false),
);
device.toggleStatus = !anySwitchOff;
allDevices[deviceIndex] = device;
}
emit(DeviceControlSuccess(code: control.code));
} else {
emit(DeviceControlError('Failed to control the device'));
}
} catch (failure) {
emit(DeviceControlError(failure.toString()));
}
}
Future<void> changeCurtainSwitch(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final isOpen = control.value == "open";
final newValue = isOpen ? 0 : 100;
final response = await DevicesAPI.deviceBatchController(
code: 'percent_control',
devicesUuid: [deviceUuid],
value: newValue,
);
if (response['success'] == true) {
final statusIndex =
device.status.indexWhere((s) => s.code == 'percent_control');
if (statusIndex != -1) {
device.status[statusIndex].value = newValue;
}
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} else {
emit(DeviceControlError('Failed to toggle curtain.'));
}
} catch (error) {
emit(DeviceControlError(error.toString()));
}
}
Future<void> changeGarageSwitch(
DeviceControlModel control, String deviceUuid) async {
emit(SwitchControlLoading(code: control.code));
try {
final deviceIndex = allDevices.indexWhere((d) => d.uuid == deviceUuid);
if (deviceIndex == -1) {
throw Exception('Device not found');
}
final device = allDevices[deviceIndex];
final isOpen = control.value == "open";
final newValue = isOpen ? 0 : 100;
final response = await DevicesAPI.deviceBatchController(
code: 'percent_control',
devicesUuid: [deviceUuid],
value: newValue,
);
if (response['success'] == true) {
final statusIndex =
device.status.indexWhere((s) => s.code == 'percent_control');
if (statusIndex != -1) {
device.status[statusIndex].value = newValue;
}
allDevices[deviceIndex] = device;
emit(DeviceControlSuccess(code: control.code));
} else {
emit(DeviceControlError('Failed to toggle curtain.'));
}
} catch (error) {
emit(DeviceControlError(error.toString()));
}
}
}
enum LightMode {

View File

@ -34,6 +34,7 @@ class GetDeviceStatusError extends DevicesState {
}
class GetDevicesLoading extends DevicesState {}
class RoomLoading extends DevicesState {}
class GetDevicesSuccess extends DevicesState {
GetDevicesSuccess(this.devices);
@ -55,10 +56,16 @@ class DeviceSwitchChanged extends DevicesState {}
class DeviceSelected extends DevicesState {}
// Device Control
class DeviceControlLoading extends DevicesState {
final String? code;
// class DeviceControlLoading extends DevicesState {
// final String? code;
DeviceControlLoading({this.code});
// DeviceControlLoading({this.code});
// }
class SwitchControlLoading extends DevicesState {
final String? code;
final String? deviceId;
SwitchControlLoading({this.deviceId, this.code});
}
class DeviceControlSuccess extends DevicesState {

View File

@ -21,13 +21,14 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
}
Timer? _timer;
bool lowBattery = false;
bool closingReminder = false;
bool doorAlarm = false;
DoorSensorModel deviceStatus = DoorSensorModel(doorContactState: false, batteryPercentage: 0);
DoorSensorModel deviceStatus =
DoorSensorModel(doorContactState: false, batteryPercentage: 0);
void _fetchStatus(DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
void _fetchStatus(
DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
emit(DoorSensorLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(DSId);
@ -40,7 +41,7 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
);
emit(UpdateState(doorSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(DoorSensorFailedState(errorMessage: e.toString()));
return;
@ -48,7 +49,8 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
// Toggle functions for each switch
void _toggleLowBattery(ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
void _toggleLowBattery(
ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
lowBattery = event.isLowBatteryEnabled;
@ -89,7 +91,8 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
}
void _toggleDoorAlarm(ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
void _toggleDoorAlarm(
ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
doorAlarm = event.isDoorAlarmEnabled;
@ -108,9 +111,11 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
}
DeviceReport recordGroups = DeviceReport(startTime: '0', endTime: '0', data: []);
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
DateTime now = DateTime.now();
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
@ -133,22 +138,27 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
}
}
_listenToChanges() {
// real-time database
Timer? _timer;
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$DSId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$DSId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = 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>;
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: true));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = DoorSensorModel.fromJson(statusList);
if (!isClosed) {
add(
@ -158,4 +168,11 @@ class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
}

View File

@ -0,0 +1,178 @@
import 'dart:async';
import 'dart:developer';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/flush_sensor_bloc/flush_sensor_event.dart';
import 'package:syncrow_app/features/devices/bloc/flush_sensor_bloc/flush_sensor_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_info_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/flush_sensor_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
class FlushSensorBloc extends Bloc<FlushSensorEvent, FlushSensorState> {
final String deviceId;
late DeviceModel deviceModel;
late FlushSensorModel deviceStatus;
FlushSensorBloc({required this.deviceId}) : super(FlushSensorInitialState()) {
on<FlushSensorInitialEvent>(_fetchFlushSensorStatus);
on<FlushSensorChangeIndicatorEvent>(_changeIndicator);
on<FlushSensorChangeValueEvent>(_changeValue);
on<FlushSensorUpdatedEvent>(_flushSensorUpdated);
on<FlushSensorGetDeviceReportsEvent>(_getDeviceReports);
on<FlushSensorInitialDeviseInfo>(fetchDeviceInfo);
}
void _fetchFlushSensorStatus(
FlushSensorInitialEvent event, Emitter<FlushSensorState> emit) async {
emit(FlushSensorLoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(deviceId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = FlushSensorModel.fromJson(statusModelList);
emit(FlushSensorUpdateState(flushSensorModel: deviceStatus));
_listenToChanges();
} catch (e) {
emit(FlushSensorFailedState(error: e.toString()));
return;
}
}
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$deviceId');
Stream<DatabaseEvent> stream = ref.onValue;
_streamSubscription = stream.listen((DatabaseEvent event) async {
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 = FlushSensorModel.fromJson(statusList);
if (!isClosed) {
add(FlushSensorUpdatedEvent());
}
});
} catch (_) {
log(
'Error listening to changes',
name: 'FlushMountedPresenceSensorBloc._listenToChanges',
);
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_flushSensorUpdated(
FlushSensorUpdatedEvent event, Emitter<FlushSensorState> emit) {
emit(FlushSensorUpdateState(flushSensorModel: deviceStatus));
}
void _changeIndicator(FlushSensorChangeIndicatorEvent event,
Emitter<FlushSensorState> emit) async {
emit(FlushSensorLoadingNewSate(flushSensorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: deviceId, code: 'indicator', value: !event.value),
deviceId);
} catch (e) {
emit(FlushSensorFailedState(error: e.toString()));
return;
}
emit(FlushSensorUpdateState(flushSensorModel: deviceStatus));
}
void _changeValue(
FlushSensorChangeValueEvent event, Emitter<FlushSensorState> emit) async {
emit(FlushSensorLoadingNewSate(flushSensorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: deviceId, code: event.code, value: event.value),
deviceId);
} catch (e) {
emit(FlushSensorFailedState(error: e.toString()));
return;
}
emit(FlushSensorUpdateState(flushSensorModel: deviceStatus));
}
void _getDeviceReports(FlushSensorGetDeviceReportsEvent event,
Emitter<FlushSensorState> emit) async {
emit(FlushSensorLoadingInitialState());
try {
await DevicesAPI.getReports(deviceId, event.code).then((value) {
emit(FlushSensorDeviceReportsState(
deviceReport: value, code: event.code));
});
} catch (e) {
emit(FlushSensorFailedState(error: e.toString()));
return;
}
}
DeviceInfoModel deviceInfo = DeviceInfoModel(
activeTime: 0,
category: "",
categoryName: "",
createTime: 0,
gatewayId: "",
icon: "",
ip: "",
lat: "",
localKey: "",
lon: "",
model: "",
name: "",
nodeId: "",
online: false,
ownerId: "",
productName: "",
sub: false,
timeZone: "",
updateTime: 0,
uuid: "",
productUuid: "",
productType: "",
permissionType: "",
macAddress: "",
subspace: Subspace(
uuid: "",
createdAt: "",
updatedAt: "",
subspaceName: "",
),
);
static String deviceName = '';
void fetchDeviceInfo(FlushSensorInitialDeviseInfo event,
Emitter<FlushSensorState> emit) async {
try {
emit(FlushSensorLoadingInitialState());
var response = await DevicesAPI.getDeviceInfo(deviceId);
deviceInfo = DeviceInfoModel.fromJson(response);
deviceName = deviceInfo.name;
emit(FlushSensorLoadingDeviceInfo(deviceInfo: deviceInfo));
} catch (e) {
emit(FlushSensorFailedState(error: e.toString()));
}
}
}

View File

@ -0,0 +1,45 @@
import 'package:equatable/equatable.dart';
abstract class FlushSensorEvent extends Equatable {
const FlushSensorEvent();
@override
List<Object> get props => [];
}
class FlushSensorLoadingEvent extends FlushSensorEvent {}
class FlushSensorInitialEvent extends FlushSensorEvent {}
class FlushSensorInitialDeviseInfo extends FlushSensorEvent {}
class FlushSensorUpdatedEvent extends FlushSensorEvent {}
class FlushSensorChangeIndicatorEvent extends FlushSensorEvent {
final bool value;
const FlushSensorChangeIndicatorEvent({required this.value});
@override
List<Object> get props => [value];
}
class FlushSensorChangeValueEvent extends FlushSensorEvent {
final dynamic value;
final String code;
const FlushSensorChangeValueEvent({required this.value, required this.code});
@override
List<Object> get props => [value, code];
}
class FlushSensorGetDeviceReportsEvent extends FlushSensorEvent {
final String deviceUuid;
final String code;
const FlushSensorGetDeviceReportsEvent({
required this.deviceUuid,
required this.code,
});
@override
List<Object> get props => [deviceUuid, code];
}

View File

@ -0,0 +1,52 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_info_model.dart';
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/flush_sensor_model.dart';
class FlushSensorState extends Equatable {
const FlushSensorState();
@override
List<Object> get props => [];
}
class FlushSensorInitialState extends FlushSensorState {}
class FlushSensorLoadingInitialState extends FlushSensorState {}
class FlushSensorUpdateState extends FlushSensorState {
final FlushSensorModel flushSensorModel;
const FlushSensorUpdateState({required this.flushSensorModel});
@override
List<Object> get props => [flushSensorModel];
}
class FlushSensorLoadingNewSate extends FlushSensorState {
final FlushSensorModel flushSensorModel;
const FlushSensorLoadingNewSate({required this.flushSensorModel});
@override
List<Object> get props => [flushSensorModel];
}
class FlushSensorFailedState extends FlushSensorState {
final String error;
const FlushSensorFailedState({required this.error});
@override
List<Object> get props => [error];
}
class FlushSensorDeviceReportsState extends FlushSensorState {
final DeviceReport deviceReport;
final String code;
const FlushSensorDeviceReportsState(
{required this.deviceReport, required this.code});
}
class FlushSensorLoadingDeviceInfo extends FlushSensorState {
final DeviceInfoModel? deviceInfo;
const FlushSensorLoadingDeviceInfo({this.deviceInfo});
}

View File

@ -1,6 +1,8 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_event.dart';
import 'package:syncrow_app/features/devices/bloc/four_scene_bloc/four_scene_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
@ -14,6 +16,7 @@ import 'package:syncrow_app/features/devices/model/subspace_model.dart';
import 'package:syncrow_app/features/scene/model/scenes_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/scene_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
@ -230,6 +233,7 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
deviceStatus = FourSceneModelState.fromJson(
statusModelList,
);
// _listenToChanges();
add(const FourSceneSwitchInitial());
} catch (e) {
emit(FourSceneFailedState(errorMessage: e.toString()));
@ -299,9 +303,11 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
LoadScenes event, Emitter<FourSceneState> emit) async {
emit(FourSceneLoadingState());
try {
Project? project = HomeCubit.getInstance().project;
if (event.unitId.isNotEmpty) {
allScenes = await SceneApi.getScenesByUnitId(
event.unitId, event.unit.community.uuid,
event.unitId, event.unit.community.uuid, project?.uuid ?? TempConst.projectIdDev,
showInDevice: event.showInDevice);
filteredScenes = allScenes;
@ -327,4 +333,33 @@ class FourSceneBloc extends Bloc<FourSceneEvent, FourSceneState> {
}).toList();
emit(SearchResultsState());
}
// Real-time database
// Timer? _timer;
// _listenToChanges() {
// try {
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$fourSceneId');
// 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: true));
// });
// deviceStatus = FourSceneModelState.fromJson(statusList);
// // if (!isClosed) {
// // add(
// // DoorSensorSwitch(switchD: deviceStatus.doorContactState),
// // );
// // }
// });
// } catch (_) {}
// }
}

View File

@ -42,7 +42,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<ToggleAlarmEvent>(_toggleAlarmEvent);
on<DeleteScheduleEvent>(deleteSchedule);
//_toggleAlarmEvent
on<UpdateStateEvent>(_updateState);
}
void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) {
_timer?.cancel();
@ -65,7 +66,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
batteryPercentage: 0,
);
void _fetchStatus(GarageDoorInitial event, Emitter<GarageDoorSensorState> emit) async {
void _fetchStatus(
GarageDoorInitial event, Emitter<GarageDoorSensorState> emit) async {
emit(GarageDoorLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(GDId);
@ -80,7 +82,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
toggleDoor = deviceStatus.switch1;
emit(UpdateState(garageSensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(GarageDoorFailedState(errorMessage: e.toString()));
return;
@ -113,8 +115,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _toggleClosingReminder(
ToggleClosingReminderEvent event, Emitter<GarageDoorSensorState> emit) async {
void _toggleClosingReminder(ToggleClosingReminderEvent event,
Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
closingReminder = event.isClosingReminderEnabled;
@ -132,7 +134,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _toggleDoorAlarm(ToggleDoorAlarmEvent event, Emitter<GarageDoorSensorState> emit) async {
void _toggleDoorAlarm(
ToggleDoorAlarmEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
doorAlarm = event.isDoorAlarmEnabled;
@ -150,7 +153,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
DeviceReport recordGroups = DeviceReport(startTime: '0', endTime: '0', data: []);
DeviceReport recordGroups =
DeviceReport(startTime: '0', endTime: '0', data: []);
Future<void> fetchLogsForLastMonth(
ReportLogsInitial event, Emitter<GarageDoorSensorState> emit) async {
@ -177,31 +181,59 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
_listenToChanges() {
// Real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$GDId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$GDId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 1));
}
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: true));
});
deviceStatus = GarageDoorModel.fromJson(statusList);
if (!isClosed) {
// add(
// DoorSensorSwitch(switchD: deviceStatus.doorContactState),
// );
if (event.snapshot.value != null) {
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.tr_timecon = statusList
.firstWhere((status) => status.code == "tr_timecon",
orElse: () => StatusModel(code: "tr_timecon", value: 0))
.value as int;
deviceStatus.switch1 = statusList
.firstWhere((status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false))
.value as bool;
secondSelected = deviceStatus.tr_timecon;
toggleDoor = deviceStatus.switch1;
add(UpdateStateEvent());
}
});
} catch (_) {}
}
Future<void> _updateState(
UpdateStateEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(GarageDoorLoadingState());
emit(UpdateState(garageSensor: deviceStatus));
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"},
@ -261,7 +293,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
deviceId: GDId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(UpdateState(garageSensor: deviceStatus));
} on DioException catch (e) {
final errorData = e.response!.data;
@ -272,12 +305,13 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<GarageDoorSensorState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<GarageDoorSensorState> emit) async {
try {
emit(GarageDoorLoadingState());
final response = await DevicesAPI.changeSchedule(
@ -295,7 +329,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<GarageDoorSensorState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<GarageDoorSensorState> emit) async {
try {
emit(GarageDoorLoadingState());
final response = await DevicesAPI.deleteSchedule(
@ -314,13 +349,15 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<GarageDoorSensorState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<GarageDoorSensorState> emit) {
emit(GarageDoorLoadingState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<GarageDoorSensorState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<GarageDoorSensorState> emit) {
emit(GarageDoorLoadingState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -337,13 +374,16 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
int secondSelected = 0;
bool toggleDoor = false;
Future<void> selectSeconds(SelectSecondsEvent event, Emitter<GarageDoorSensorState> emit) async {
Future<void> selectSeconds(
SelectSecondsEvent event, Emitter<GarageDoorSensorState> emit) async {
try {
emit(GarageDoorLoadingState());
secondSelected = event.seconds;
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: GDId, code: 'tr_timecon', value: secondSelected), GDId);
DeviceControlModel(
deviceId: GDId, code: 'tr_timecon', value: secondSelected),
GDId);
emit(UpdateState(garageSensor: deviceStatus));
} on DioException catch (e) {
final errorData = e.response!.data;
@ -352,12 +392,15 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
openCloseGarageDoor(ToggleDoorEvent event, Emitter<GarageDoorSensorState> emit) async {
openCloseGarageDoor(
ToggleDoorEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(GarageDoorLoadingState());
try {
toggleDoor = !event.toggle;
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: GDId, code: 'switch_1', value: toggleDoor), GDId);
DeviceControlModel(
deviceId: GDId, code: 'switch_1', value: toggleDoor),
GDId);
add(const GarageDoorInitial());
emit(UpdateState(garageSensor: deviceStatus));
} on DioException catch (e) {
@ -367,13 +410,16 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _setCounterValue(SetCounterValue event, Emitter<GarageDoorSensorState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: GDId, code: 'countdown_1', value: seconds), GDId);
DeviceControlModel(
deviceId: GDId, code: 'countdown_1', value: seconds),
GDId);
if (response['success'] ?? false) {
deviceStatus.countdown1 = seconds;
@ -393,7 +439,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<GarageDoorSensorState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(GDId);
@ -434,7 +481,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
List<GroupGarageModel> groupList = [];
bool allSwitchesOn = true;
void _fetchWizardStatus(InitialWizardEvent event, Emitter<GarageDoorSensorState> emit) async {
void _fetchWizardStatus(
InitialWizardEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -444,7 +492,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'GD');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -473,7 +522,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _groupAllOn(GroupAllOnEvent event, Emitter<GarageDoorSensorState> emit) async {
void _groupAllOn(
GroupAllOnEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
@ -485,7 +535,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
emit(UpdateGroupState(garageList: groupList, allSwitches: true));
// Get a list of all device IDs
List<String> allDeviceIds = groupList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(
@ -505,7 +556,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<GarageDoorSensorState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
@ -517,7 +569,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
emit(UpdateGroupState(garageList: groupList, allSwitches: false));
// Get a list of all device IDs
List<String> allDeviceIds = groupList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(
@ -538,8 +591,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<GarageDoorSensorState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
try {
bool allSwitchesValue = true;
@ -552,7 +605,8 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
});
emit(UpdateGroupState(garageList: groupList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
garageList: groupList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -568,13 +622,16 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
}
}
void _setTimeOutAlarm(SetTimeOutValue event, Emitter<GarageDoorSensorState> emit) async {
void _setTimeOutAlarm(
SetTimeOutValue event, Emitter<GarageDoorSensorState> emit) async {
emit(LoadingNewSate(doorSensor: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: GDId, code: 'countdown_alarm', value: seconds), GDId);
DeviceControlModel(
deviceId: GDId, code: 'countdown_alarm', value: seconds),
GDId);
if (response['success'] ?? false) {
deviceStatus.countdownAlarm = seconds;

View File

@ -109,6 +109,8 @@ class GetScheduleEvent extends GarageDoorEvent {}
class ScheduleSaveapp extends GarageDoorEvent {}
class UpdateStateEvent extends GarageDoorEvent {}
class ToggleScheduleEvent extends GarageDoorEvent {
final String id;
final bool toggle;

View File

@ -26,7 +26,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
bool oneGangGroup = false;
List<DeviceModel> devicesList = [];
OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) {
OneGangBloc({required this.oneGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchOneGangStatus);
on<OneGangUpdated>(_oneGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -49,7 +50,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
on<GroupAllOffEvent>(_groupAllOff);
}
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
void _fetchOneGangStatus(
InitialEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneGangId);
@ -59,42 +61,51 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
deviceStatus = OneGangModel.fromJson(statusModelList);
emit(UpdateState(oneGangModel: deviceStatus));
// _listenToChanges();
_listenToChanges(oneGangId);
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
// Real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneGangId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
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>;
_streamSubscription = 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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = OneGangModel.fromJson(statusList);
if (!isClosed) {
add(OneGangUpdated());
}
add(OneGangUpdated());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_oneGangUpdated(OneGangUpdated event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
emit(UpdateState(oneGangModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -119,17 +130,20 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<OneGangState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneGangId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: oneGangId, code: event.deviceCode, value: seconds),
oneGangId);
if (response['success'] ?? false) {
@ -152,7 +166,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<OneGangState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneGangId);
@ -241,7 +256,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
deviceId: oneGangId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -252,12 +268,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -276,7 +293,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -296,7 +314,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -325,7 +344,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneGangState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
@ -334,7 +354,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
List<GroupOneGangModel> groupOneGangList = [];
bool allSwitchesOn = true;
void _fetchOneGangWizardStatus(InitialWizardEvent event, Emitter<OneGangState> emit) async {
void _fetchOneGangWizardStatus(
InitialWizardEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -344,7 +365,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -365,15 +387,16 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
return true;
});
}
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneGangState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -386,7 +409,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
});
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -414,7 +438,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(
@ -446,7 +471,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(

View File

@ -30,7 +30,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
bool oneTouchGroup = false;
List<DeviceModel> devicesList = [];
OneTouchBloc({required this.oneTouchId, required this.switchCode}) : super(InitialState()) {
OneTouchBloc({required this.oneTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchOneTouchStatus);
on<OneTouchUpdated>(_oneTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -53,7 +54,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
on<ChangeStatusEvent>(_changeStatus);
}
void _fetchOneTouchStatus(InitialEvent event, Emitter<OneTouchState> emit) async {
void _fetchOneTouchStatus(
InitialEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
@ -62,43 +64,59 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = OneTouchModel.fromJson(statusModelList);
_listenToChanges(oneTouchId);
emit(UpdateState(oneTouchModel: deviceStatus));
// _listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneTouchId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
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 = [];
_streamSubscription = stream.listen((DatabaseEvent event) {
if (event.snapshot.value != null) {
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']));
});
usersMap['status'].forEach((element) {
statusList.add(
StatusModel(code: element['code'], value: element['value']));
});
var switchStatus = statusList.firstWhere(
(status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false));
deviceStatus = OneTouchModel.fromJson(statusList);
if (!isClosed) {
deviceStatus.firstSwitch = switchStatus.value as bool;
add(OneTouchUpdated());
}
});
} catch (_) {}
} catch (_) {
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_oneTouchUpdated(OneTouchUpdated event, Emitter<OneTouchState> emit) {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
emit(UpdateState(oneTouchModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -123,17 +141,20 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<OneTouchState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneTouchId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: oneTouchId, code: event.deviceCode, value: seconds),
oneTouchId);
if (response['success'] ?? false) {
@ -156,7 +177,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<OneTouchState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
@ -245,7 +267,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
deviceId: oneTouchId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -256,12 +279,13 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<OneTouchState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<OneTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -280,7 +304,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -300,7 +325,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -329,7 +355,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
@ -338,7 +365,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
List<GroupOneTouchModel> groupOneTouchList = [];
bool allSwitchesOn = true;
void _fetchOneTouchWizardStatus(InitialWizardEvent event, Emitter<OneTouchState> emit) async {
void _fetchOneTouchWizardStatus(
InitialWizardEvent event, Emitter<OneTouchState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -348,7 +376,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '1GT');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -369,15 +398,16 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
return true;
});
}
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<OneTouchState> emit) async {
emit(LoadingNewSate(oneTouchModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -395,7 +425,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
value: !event.value,
);
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
if (response['success']) {
add(InitialEvent(groupScreen: oneTouchGroup));
}
@ -413,10 +444,12 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
// Emit the state with updated values
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
emit(
UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneTouchList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneTouchList.map((device) => device.deviceId).toList();
// First call for switch_1
final response1 = await DevicesAPI.deviceBatchController(
@ -445,10 +478,12 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
}
// Emit the state with updated values
emit(UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: false));
emit(UpdateGroupState(
oneTouchList: groupOneTouchList, allSwitches: false));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneTouchList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupOneTouchList.map((device) => device.deviceId).toList();
// First call for switch_1
final response1 = await DevicesAPI.deviceBatchController(
@ -472,7 +507,8 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
String statusSelected = '';
String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
try {
emit(LoadingInitialState());
@ -497,7 +533,10 @@ class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: oneTouchId, code: optionSelected, value: selectedControl),
DeviceControlModel(
deviceId: oneTouchId,
code: optionSelected,
value: selectedControl),
oneTouchId,
);
} else {

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:math';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
@ -37,7 +38,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
on<SelectTimeEvent>(selectTimeOfLinePassword);
on<SelectTimeOnlinePasswordEvent>(selectTimeOnlinePassword);
on<DeletePasswordEvent>(deletePassword);
on<GenerateAndSavePasswordTimeLimitEvent>(generateAndSavePasswordTimeLimited);
on<GenerateAndSavePasswordTimeLimitEvent>(
generateAndSavePasswordTimeLimited);
on<GenerateAndSavePasswordOneTimeEvent>(generateAndSavePasswordOneTime);
on<ToggleDaySelectionEvent>(toggleDaySelection);
on<RenamePasswordEvent>(_renamePassword);
@ -59,7 +61,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
List<OfflinePasswordModel>? oneTimePasswords = [];
List<OfflinePasswordModel>? timeLimitPasswords = [];
Future generate7DigitNumber(GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async {
Future generate7DigitNumber(
GeneratePasswordEvent event, Emitter<SmartDoorState> emit) async {
emit(LoadingInitialState());
passwordController.clear();
Random random = Random();
@ -71,7 +74,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
Future generateAndSavePasswordOneTime(
GenerateAndSavePasswordOneTimeEvent event, Emitter<SmartDoorState> emit) async {
GenerateAndSavePasswordOneTimeEvent event,
Emitter<SmartDoorState> emit) async {
try {
if (isSavingPassword) return;
isSavingPassword = true;
@ -92,7 +96,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
void _fetchSmartDoorStatus(InitialEvent event, Emitter<SmartDoorState> emit) async {
void _fetchSmartDoorStatus(
InitialEvent event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -102,42 +107,63 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
deviceStatus = SmartDoorModel.fromJson(statusModelList);
emit(UpdateState(smartDoorModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
Timer? _timer;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
_streamSubscription?.cancel();
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>;
_streamSubscription = 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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = SmartDoorModel.fromJson(statusList);
add(DoorLockUpdated());
if (!isClosed) {
add(DoorLockUpdated());
}
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_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 {
emit(LoadingInitialState());
await DevicesAPI.renamePass(
name: passwordNameController.text, doorLockUuid: deviceId, passwordId: passwordId);
name: passwordNameController.text,
doorLockUuid: deviceId,
passwordId: passwordId);
add(InitialOneTimePassword());
add(InitialTimeLimitPassword());
emit(UpdateState(smartDoorModel: deviceStatus));
@ -147,46 +173,58 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
void getTemporaryPasswords(InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
void getTemporaryPasswords(
InitialPasswordsPage event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getTemporaryPasswords(
deviceId,
);
if (response is List) {
temporaryPasswords = response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords =
(response['data'] as List).map((item) => TemporaryPassword.fromJson(item)).toList();
response.map((item) => TemporaryPassword.fromJson(item)).toList();
} else if (response is Map && response.containsKey('data')) {
temporaryPasswords = (response['data'] as List)
.map((item) => TemporaryPassword.fromJson(item))
.toList();
}
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
}
void getOneTimePasswords(InitialOneTimePassword event, Emitter<SmartDoorState> emit) async {
void getOneTimePasswords(
InitialOneTimePassword event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getOneTimePasswords(deviceId);
if (response is List) {
oneTimePasswords = response.map((item) => OfflinePasswordModel.fromJson(item)).toList();
oneTimePasswords = response
.map((item) => OfflinePasswordModel.fromJson(item))
.toList();
}
emit(TemporaryPasswordsLoadedState(temporaryPassword: temporaryPasswords!));
emit(TemporaryPasswordsLoadedState(
temporaryPassword: temporaryPasswords!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
}
}
void getTimeLimitPasswords(InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async {
void getTimeLimitPasswords(
InitialTimeLimitPassword event, Emitter<SmartDoorState> emit) async {
try {
emit(LoadingInitialState());
var response = await DevicesAPI.getTimeLimitPasswords(deviceId);
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) {
emit(FailedState(errorMessage: e.toString()));
}
@ -207,7 +245,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
return repeat;
}
bool setStartEndTime(SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
bool setStartEndTime(
SetStartEndTimeEvent event, Emitter<SmartDoorState> emit) {
emit(LoadingInitialState());
isStartEndTime = event.val;
emit(IsStartEndState(isStartEndTime: isStartEndTime));
@ -230,7 +269,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
emit(UpdateState(smartDoorModel: deviceStatus));
}
Future<void> selectTimeOfLinePassword(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,
@ -260,20 +300,27 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
).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.');
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
effectiveTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp;
}
} else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
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
expirationTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp;
}
}
@ -329,20 +376,27 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
).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.');
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
effectiveTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp;
}
} else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
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
expirationTime = selectedDateTime
.toString()
.split('.')
.first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp;
}
}
@ -351,7 +405,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
}
Future<void> savePassword(SavePasswordEvent event, Emitter<SmartDoorState> emit) async {
Future<void> savePassword(
SavePasswordEvent event, Emitter<SmartDoorState> emit) async {
if (_validateInputs() || isSavingPassword) return;
try {
isSavingPassword = true;
@ -381,7 +436,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
Future<void> generateAndSavePasswordTimeLimited(
GenerateAndSavePasswordTimeLimitEvent event, Emitter<SmartDoorState> emit) async {
GenerateAndSavePasswordTimeLimitEvent event,
Emitter<SmartDoorState> emit) async {
if (timeLimitValidate() || isSavingPassword) return;
try {
isSavingPassword = true;
@ -407,10 +463,12 @@ 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 {
emit(LoadingInitialState());
await DevicesAPI.deletePassword(deviceId: deviceId, passwordId: event.passwordId)
await DevicesAPI.deletePassword(
deviceId: deviceId, passwordId: event.passwordId)
.then((value) async {
add(InitialPasswordsPage());
});
@ -445,7 +503,8 @@ class SmartDoorBloc extends Bloc<SmartDoorEvent, SmartDoorState> {
}
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 false;

View File

@ -1,10 +1,12 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.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/model/community_model.dart';
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_event.dart';
import 'package:syncrow_app/features/devices/bloc/sos_bloc/sos_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
@ -19,6 +21,7 @@ import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/services/api/spaces_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class SosBloc extends Bloc<SosEvent, SosState> {
@ -171,6 +174,7 @@ class SosBloc extends Bloc<SosEvent, SosState> {
);
emit(UpdateState(sensor: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
} catch (e) {
emit(SosFailedState(errorMessage: e.toString()));
return;
@ -184,8 +188,12 @@ class SosBloc extends Bloc<SosEvent, SosState> {
FetchRoomsEvent event, Emitter<SosState> emit) async {
try {
emit(SosLoadingState());
Project? project = HomeCubit.getInstance().project;
roomsList = await SpacesAPI.getSubSpaceBySpaceId(
event.unit.community.uuid, event.unit.id);
event.unit.community.uuid,
event.unit.id,
project?.uuid ?? TempConst.projectIdDev);
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
} catch (e) {
emit(const SosFailedState(errorMessage: 'Something went wrong'));
@ -223,13 +231,19 @@ class SosBloc extends Bloc<SosEvent, SosState> {
void _assignDevice(AssignRoomEvent event, Emitter<SosState> emit) async {
try {
emit(SosLoadingState());
Project? project = HomeCubit.getInstance().project;
await HomeManagementAPI.assignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, sosId);
event.unit.community.uuid,
event.unit.id,
event.roomId,
sosId,
project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -249,13 +263,16 @@ class SosBloc extends Bloc<SosEvent, SosState> {
void _unassignDevice(UnassignRoomEvent event, Emitter<SosState> emit) async {
try {
Map<String, bool> roomDevicesId = {};
Project? project = HomeCubit.getInstance().project;
emit(SosLoadingState());
await HomeManagementAPI.unAssignDeviceToRoom(
event.unit.community.uuid, event.unit.id, event.roomId, sosId);
event.unit.community.uuid, event.unit.id, event.roomId, sosId, project?.uuid ?? TempConst.projectIdDev);
final devicesList = await DevicesAPI.getDevicesByRoomId(
communityUuid: event.unit.community.uuid,
spaceUuid: event.unit.id,
roomId: event.roomId);
roomId: event.roomId,
projectId: project?.uuid ?? TempConst.projectIdDev);
List<String> allDevicesIds = [];
@ -419,4 +436,39 @@ class SosBloc extends Bloc<SosEvent, SosState> {
emit(SosFailedState(errorMessage: e.toString()));
}
}
//real-time db
// StreamSubscription<DatabaseEvent>? _streamSubscription;
// Timer? _timer;
// void _listenToChanges() {
// try {
// _streamSubscription?.cancel();
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$sosId');
// Stream<DatabaseEvent> stream = ref.onValue;
// _streamSubscription = 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 = SosModel.fromJson(statusList);
// });
// } catch (_) {}
// }
// @override
// Future<void> close() async {
// _streamSubscription?.cancel();
// _streamSubscription = null;
// return super.close();
// }
}

View File

@ -31,7 +31,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
List<GroupThreeGangModel> groupThreeGangList = [];
bool allSwitchesOn = true;
ThreeGangBloc({required this.threeGangId, required this.switchCode}) : super(InitialState()) {
ThreeGangBloc({required this.threeGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchThreeGangStatus);
on<ThreeGangUpdated>(_threeGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -57,7 +58,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
}
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
void _fetchThreeGangStatus(
InitialEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState());
try {
threeGangGroup = event.groupScreen;
@ -69,7 +71,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '3G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -86,13 +89,16 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (groupThreeGangList.isNotEmpty) {
groupThreeGangList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
} else {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
List<StatusModel> statusModelList = [];
@ -101,7 +107,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
deviceStatus = ThreeGangModel.fromJson(statusModelList);
emit(UpdateState(threeGangModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));
@ -109,22 +115,26 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$threeGangId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 1));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = ThreeGangModel.fromJson(statusList);
if (!isClosed) {
add(ThreeGangUpdated());
@ -133,11 +143,19 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_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));
try {
if (threeGangGroup) {
@ -146,11 +164,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else {
deviceStatus.firstSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus));
@ -187,11 +208,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else {
deviceStatus.secondSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus));
@ -217,7 +241,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
void _changeThirdSwitch(
ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
if (threeGangGroup) {
@ -226,11 +251,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
if (element.deviceId == event.deviceId) {
element.thirdSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
} else {
deviceStatus.thirdSwitch = !event.value;
emit(UpdateState(threeGangModel: deviceStatus));
@ -269,15 +297,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeGangId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeGangId),
]);
@ -303,15 +337,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeGangId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeGangId),
]);
@ -333,9 +373,11 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
groupThreeGangList[i].secondSwitch = true;
groupThreeGangList[i].thirdSwitch = true;
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: true));
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: true));
List<String> allDeviceIds = groupThreeGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupThreeGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -365,7 +407,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
try {
for (int i = 0; i < groupThreeGangList.length; i++) {
@ -373,8 +416,10 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
groupThreeGangList[i].secondSwitch = false;
groupThreeGangList[i].thirdSwitch = false;
}
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: false));
List<String> allDeviceIds = groupThreeGangList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeGangList: groupThreeGangList, allSwitches: false));
List<String> allDeviceIds =
groupThreeGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -404,17 +449,20 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<ThreeGangState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<ThreeGangState> emit) async {
emit(LoadingNewSate(threeGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeGangId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: threeGangId, code: event.deviceCode, value: seconds),
threeGangId);
if (response['success'] ?? false) {
@ -441,7 +489,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<ThreeGangState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<ThreeGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(threeGangId);
@ -551,7 +600,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
deviceId: threeGangId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -562,12 +612,13 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -586,7 +637,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -606,13 +658,15 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();

View File

@ -38,7 +38,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
List<GroupThreeTouchModel> groupThreeTouchList = [];
bool allSwitchesOn = true;
ThreeTouchBloc({required this.threeTouchId, required this.switchCode}) : super(InitialState()) {
ThreeTouchBloc({required this.threeTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchThreeTouchStatus);
on<ThreeTouchUpdated>(_threeTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -63,7 +64,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
on<ChangeStatusEvent>(_changeStatus);
}
void _fetchThreeTouchStatus(InitialEvent event, Emitter<ThreeTouchState> emit) async {
void _fetchThreeTouchStatus(
InitialEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingInitialState());
try {
threeTouchGroup = event.groupScreen;
@ -75,7 +77,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '3GT');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -92,13 +95,16 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (groupThreeTouchList.isNotEmpty) {
groupThreeTouchList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
} else {
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
List<StatusModel> statusModelList = [];
@ -107,7 +113,7 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
emit(UpdateState(threeTouchModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));
@ -117,18 +123,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
_listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeTouchId');
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$threeTouchId');
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>;
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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = ThreeTouchModel.fromJson(statusList);
@ -143,7 +152,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
emit(UpdateState(threeTouchModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
if (threeTouchGroup) {
@ -152,11 +162,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else {
deviceStatus.firstSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus));
@ -183,8 +197,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _changeSecondSwitch(
ChangeSecondSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event,
Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
if (threeTouchGroup) {
@ -193,11 +207,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else {
deviceStatus.secondSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus));
@ -223,7 +241,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
void _changeThirdSwitch(
ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
if (threeTouchGroup) {
@ -232,11 +251,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
if (element.deviceId == event.deviceId) {
element.thirdSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
if (!element.firstSwitch ||
!element.secondSwitch ||
!element.thirdSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList,
allSwitches: allSwitchesValue));
} else {
deviceStatus.thirdSwitch = !event.value;
emit(UpdateState(threeTouchModel: deviceStatus));
@ -275,15 +298,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeTouchId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeTouchId),
]);
@ -309,15 +338,21 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: threeTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: threeTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
threeTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: threeTouchId, code: 'switch_3', value: deviceStatus.thirdSwitch),
deviceId: threeTouchId,
code: 'switch_3',
value: deviceStatus.thirdSwitch),
threeTouchId),
]);
@ -339,8 +374,10 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
groupThreeTouchList[i].secondSwitch = true;
groupThreeTouchList[i].thirdSwitch = true;
}
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: true));
List<String> allDeviceIds = groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: true));
List<String> allDeviceIds =
groupThreeTouchList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
@ -369,7 +406,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
try {
for (int i = 0; i < groupThreeTouchList.length; i++) {
@ -377,8 +415,10 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
groupThreeTouchList[i].secondSwitch = false;
groupThreeTouchList[i].thirdSwitch = false;
}
List<String> allDeviceIds = groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(threeTouchList: groupThreeTouchList, allSwitches: false));
List<String> allDeviceIds =
groupThreeTouchList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
threeTouchList: groupThreeTouchList, allSwitches: false));
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
@ -407,17 +447,20 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<ThreeTouchState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<ThreeTouchState> emit) async {
emit(LoadingNewSate(threeTouchModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeTouchId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: threeTouchId, code: event.deviceCode, value: seconds),
threeTouchId);
if (response['success'] ?? false) {
@ -444,7 +487,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
@ -554,7 +598,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
deviceId: threeTouchId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -565,12 +610,13 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -589,7 +635,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -609,13 +656,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
}
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -633,7 +682,8 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
String statusSelected = '';
String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
try {
emit(LoadingInitialState());
final Map<String, Map<String, String>> controlMap = {
@ -667,11 +717,15 @@ class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: threeTouchId, code: optionSelected, value: selectedControl),
DeviceControlModel(
deviceId: threeTouchId,
code: optionSelected,
value: selectedControl),
threeTouchId,
);
} else {
emit(const FailedState(error: 'Invalid statusSelected or optionSelected'));
emit(const FailedState(
error: 'Invalid statusSelected or optionSelected'));
}
} on DioException catch (e) {
final errorData = e.response!.data;

View File

@ -35,7 +35,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
bool createSchedule = false;
List<ScheduleModel> listSchedule = [];
TwoGangBloc({required this.twoGangId, required this.switchCode}) : super(InitialState()) {
TwoGangBloc({required this.twoGangId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchTwoGangStatus);
on<TwoGangUpdated>(_twoGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -65,13 +66,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -79,7 +82,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(UpdateCreateScheduleState(createSchedule));
}
void _fetchTwoGangStatus(InitialEvent event, Emitter<TwoGangState> emit) async {
void _fetchTwoGangStatus(
InitialEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(twoGangId);
@ -89,42 +93,50 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
deviceStatus = TwoGangModel.fromJson(statusModelList);
emit(UpdateState(twoGangModel: deviceStatus));
// _listenToChanges();
_listenToChanges(twoGangId);
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges(String id) {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$twoGangId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$id');
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>;
_streamSubscription = 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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = TwoGangModel.fromJson(statusList);
if (!isClosed) {
add(TwoGangUpdated());
}
add(TwoGangUpdated());
});
} catch (_) {}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_twoGangUpdated(TwoGangUpdated event, Emitter<TwoGangState> emit) {
emit(LoadingNewSate(twoGangModel: deviceStatus));
emit(UpdateState(twoGangModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -135,7 +147,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
_timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: 'switch_1', value: !event.value),
DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: !event.value),
twoGangId);
if (!response['success']) {
@ -147,7 +160,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeSecondSwitch(
ChangeSecondSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
deviceStatus.secondSwitch = !event.value;
@ -157,7 +171,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
_timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: 'switch_2', value: !event.value),
DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: !event.value),
twoGangId);
if (!response['success']) {
@ -180,11 +195,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: twoGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: twoGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoGangId),
]);
@ -207,11 +226,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: twoGangId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoGangId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: twoGangId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoGangId),
]);
if (response.every((element) => !element['success'])) {
@ -232,7 +255,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
groupTwoGangList[i].secondSwitch = true;
}
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: true));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -267,7 +291,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: false));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -292,17 +317,20 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<TwoGangState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<TwoGangState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<TwoGangState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoGangId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: twoGangId, code: event.deviceCode, value: seconds),
twoGangId);
if (response['success'] ?? false) {
@ -327,7 +355,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<TwoGangState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
add(GetScheduleEvent());
@ -435,7 +464,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
deviceId: twoGangId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -446,12 +476,13 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleRepeat(ToggleScheduleEvent event, Emitter<TwoGangState> emit) async {
Future toggleRepeat(
ToggleScheduleEvent event, Emitter<TwoGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -470,7 +501,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<TwoGangState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<TwoGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -490,7 +522,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _fetchTwoGangWizardStatus(InitialWizardEvent event, Emitter<TwoGangState> emit) async {
void _fetchTwoGangWizardStatus(
InitialWizardEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -500,7 +533,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -523,15 +557,16 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
return true;
});
}
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -544,9 +579,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
});
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
@ -561,8 +598,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
}
}
void _changeSecondWizardSwitch(
ChangeSecondWizardSwitchStatusEvent event, Emitter<TwoGangState> emit) async {
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -574,9 +611,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
allSwitchesValue = false;
}
});
List<String> allDeviceIds = groupTwoGangList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_2',

View File

@ -40,7 +40,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
bool createSchedule = false;
List<ScheduleModel> listSchedule = [];
TwoTouchBloc({required this.twoTouchId, required this.switchCode}) : super(InitialState()) {
TwoTouchBloc({required this.twoTouchId, required this.switchCode})
: super(InitialState()) {
on<InitialEvent>(_fetchTwoTouchStatus);
on<TwoTouchUpdated>(_twoTouchUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -71,13 +72,15 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
int selectedTabIndex = 0;
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<TwoTouchState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<TwoTouchState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<TwoTouchState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<TwoTouchState> emit) {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -85,7 +88,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
emit(UpdateCreateScheduleState(createSchedule));
}
void _fetchTwoTouchStatus(InitialEvent event, Emitter<TwoTouchState> emit) async {
void _fetchTwoTouchStatus(
InitialEvent event, Emitter<TwoTouchState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(twoTouchId);
@ -95,42 +99,66 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
deviceStatus = TwoTouchModel.fromJson(statusModelList);
emit(UpdateState(twoTouchModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$twoTouchId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$twoTouchId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 1));
}
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
if (event.snapshot.value != null) {
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']));
});
usersMap['status'].forEach((element) {
statusList.add(
StatusModel(code: element['code'], value: element['value']));
});
var switch1Status = statusList.firstWhere(
(status) => status.code == "switch_1",
orElse: () => StatusModel(code: "switch_1", value: false));
var switch2Status = statusList.firstWhere(
(status) => status.code == "switch_2",
orElse: () => StatusModel(code: "switch_2", value: false));
deviceStatus.firstSwitch = switch1Status.value as bool;
deviceStatus.secondSwitch = switch2Status.value as bool;
deviceStatus = TwoTouchModel.fromJson(statusList);
if (!isClosed) {
add(TwoTouchUpdated());
}
});
} catch (_) {}
} catch (_) {
}
}
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_twoTouchUpdated(TwoTouchUpdated event, Emitter<TwoTouchState> emit) {
emit(LoadingInitialState());
emit(UpdateState(twoTouchModel: deviceStatus));
}
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
void _changeFirstSwitch(
ChangeFirstSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
emit(LoadingNewSate(twoTouchModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.value;
@ -141,7 +169,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
_timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoTouchId, code: 'switch_1', value: !event.value),
DeviceControlModel(
deviceId: twoTouchId, code: 'switch_1', value: !event.value),
twoTouchId);
if (!response['success']) {
@ -153,7 +182,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
}
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
void _changeSecondSwitch(
ChangeSecondSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
emit(LoadingNewSate(twoTouchModel: deviceStatus));
try {
deviceStatus.secondSwitch = !event.value;
@ -163,7 +193,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
_timer = Timer(const Duration(milliseconds: 100), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoTouchId, code: 'switch_2', value: !event.value),
DeviceControlModel(
deviceId: twoTouchId, code: 'switch_2', value: !event.value),
twoTouchId);
if (!response['success']) {
@ -186,11 +217,15 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoTouchId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: twoTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoTouchId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: twoTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoTouchId),
]);
@ -213,11 +248,15 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoTouchId, code: 'switch_1', value: deviceStatus.firstSwitch),
deviceId: twoTouchId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
twoTouchId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoTouchId, code: 'switch_2', value: deviceStatus.secondSwitch),
deviceId: twoTouchId,
code: 'switch_2',
value: deviceStatus.secondSwitch),
twoTouchId),
]);
if (response.every((element) => !element['success'])) {
@ -237,8 +276,10 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
groupTwoTouchList[i].firstSwitch = true;
groupTwoTouchList[i].secondSwitch = true;
}
emit(UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: true));
List<String> allDeviceIds = groupTwoTouchList.map((device) => device.deviceId).toList();
emit(
UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: true));
List<String> allDeviceIds =
groupTwoTouchList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -271,9 +312,11 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
groupTwoTouchList[i].secondSwitch = false;
}
emit(UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: false));
emit(UpdateGroupState(
twoTouchList: groupTwoTouchList, allSwitches: false));
List<String> allDeviceIds = groupTwoTouchList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupTwoTouchList.map((device) => device.deviceId).toList();
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -298,17 +341,20 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
}
void _changeSliding(ChangeSlidingSegment event, Emitter<TwoTouchState> emit) async {
void _changeSliding(
ChangeSlidingSegment event, Emitter<TwoTouchState> emit) async {
emit(ChangeSlidingSegmentState(value: event.value));
}
void _setCounterValue(SetCounterValue event, Emitter<TwoTouchState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<TwoTouchState> emit) async {
emit(LoadingNewSate(twoTouchModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoTouchId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: twoTouchId, code: event.deviceCode, value: seconds),
twoTouchId);
if (response['success'] ?? false) {
@ -333,7 +379,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<TwoTouchState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<TwoTouchState> emit) async {
emit(LoadingInitialState());
try {
add(GetScheduleEvent());
@ -441,7 +488,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
deviceId: twoTouchId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -452,12 +500,13 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleRepeat(ToggleScheduleEvent event, Emitter<TwoTouchState> emit) async {
Future toggleRepeat(
ToggleScheduleEvent event, Emitter<TwoTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
@ -476,7 +525,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<TwoTouchState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<TwoTouchState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
@ -496,7 +546,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
}
void _fetchTwoTouchWizardStatus(InitialWizardEvent event, Emitter<TwoTouchState> emit) async {
void _fetchTwoTouchWizardStatus(
InitialWizardEvent event, Emitter<TwoTouchState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
@ -506,7 +557,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', '2GT');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -529,15 +581,16 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
return true;
});
}
emit(UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<TwoTouchState> emit) async {
emit(LoadingNewSate(twoTouchModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -550,7 +603,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
});
emit(UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: [event.deviceId],
@ -565,8 +619,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
}
void _changeSecondWizardSwitch(
ChangeSecondWizardSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
Emitter<TwoTouchState> emit) async {
emit(LoadingNewSate(twoTouchModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -579,7 +633,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
}
});
emit(UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_2',
@ -598,7 +653,8 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
String statusSelected = '';
String optionSelected = '';
Future<void> _changeStatus(ChangeStatusEvent event, Emitter<TwoTouchState> emit) async {
Future<void> _changeStatus(
ChangeStatusEvent event, Emitter<TwoTouchState> emit) async {
try {
emit(LoadingInitialState());
final Map<String, Map<String, String>> controlMap = {
@ -627,11 +683,15 @@ class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
final selectedControl = controlMap[optionSelected]?[statusSelected];
if (selectedControl != null) {
await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: twoTouchId, code: optionSelected, value: selectedControl),
DeviceControlModel(
deviceId: twoTouchId,
code: optionSelected,
value: selectedControl),
twoTouchId,
);
} else {
emit(const FailedState(error: 'Invalid statusSelected or optionSelected'));
emit(const FailedState(
error: 'Invalid statusSelected or optionSelected'));
}
} on DioException catch (e) {
final errorData = e.response!.data;

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/wall_sensor_bloc/wall_sensor_state.dart';
@ -18,9 +20,11 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
on<ChangeIndicatorEvent>(_changeIndicator);
on<ChangeValueEvent>(_changeValue);
on<WallSensorUpdatedEvent>(_wallSensorUpdated);
on<GetDeviceReportsEvent>(_getDeviceReports);
}
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<WallSensorState> emit) async {
void _fetchCeilingSensorStatus(
InitialEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingInitialState());
try {
var response = await DevicesAPI.getDeviceStatus(deviceId);
@ -30,41 +34,62 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
}
deviceStatus = WallSensorModel.fromJson(statusModelList);
emit(UpdateState(wallSensorModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
_listenToChanges() {
Timer? _timer;
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
_streamSubscription?.cancel();
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>;
_streamSubscription = 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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = WallSensorModel.fromJson(statusList);
add(WallSensorUpdatedEvent());
if (!isClosed) {
add(WallSensorUpdatedEvent());
}
});
} catch (_) {}
}
_wallSensorUpdated(WallSensorUpdatedEvent event, Emitter<WallSensorState> emit) {
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_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));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: 'indicator', value: !event.value), deviceId);
DeviceControlModel(
deviceId: deviceId, code: 'indicator', value: !event.value),
deviceId);
if (response['success'] ?? false) {
deviceStatus.indicator = !event.value;
@ -73,11 +98,14 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
emit(UpdateState(wallSensorModel: deviceStatus));
}
void _changeValue(ChangeValueEvent event, Emitter<WallSensorState> emit) async {
void _changeValue(
ChangeValueEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingNewSate(wallSensorModel: deviceStatus));
try {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: deviceId, code: event.code, value: event.value), deviceId);
DeviceControlModel(
deviceId: deviceId, code: event.code, value: event.value),
deviceId);
if (response['success'] ?? false) {
if (event.code == 'far_detection') {
@ -91,4 +119,18 @@ class WallSensorBloc extends Bloc<WallSensorEvent, WallSensorState> {
} catch (_) {}
emit(UpdateState(wallSensorModel: deviceStatus));
}
void _getDeviceReports(
GetDeviceReportsEvent event, Emitter<WallSensorState> emit) async {
emit(LoadingInitialState());
try {
await DevicesAPI.getDeviceReports(deviceId, event.code).then((value) {
emit(DeviceReportsState(deviceReport: value, code: event.code));
});
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
}

View File

@ -29,3 +29,15 @@ class ChangeValueEvent extends WallSensorEvent {
@override
List<Object> get props => [value, code];
}
class GetDeviceReportsEvent extends WallSensorEvent {
final String deviceUuid;
final String code;
const GetDeviceReportsEvent({
required this.deviceUuid,
required this.code,
});
@override
List<Object> get props => [deviceUuid, code];
}

View File

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/wall_sensor_model.dart';
class WallSensorState extends Equatable {
@ -36,3 +37,9 @@ class FailedState extends WallSensorState {
@override
List<Object> get props => [error];
}
class DeviceReportsState extends WallSensorState {
final DeviceReport deviceReport;
final String code;
const DeviceReportsState({required this.deviceReport, required this.code});
}

View File

@ -35,7 +35,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<ScheduleModel> listSchedule = [];
DateTime? selectedTime = DateTime.now();
WaterHeaterBloc({required this.whId, required this.switchCode}) : super(WHInitialState()) {
WaterHeaterBloc({required this.whId, required this.switchCode})
: super(WHInitialState()) {
on<WaterHeaterInitial>(_fetchWaterHeaterStatus);
on<WaterHeaterSwitch>(_changeFirstSwitch);
on<SetCounterValue>(_setCounterValue);
@ -60,7 +61,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
on<WaterHeaterUpdated>(_waterHeaterUpdated);
}
void _fetchWaterHeaterStatus(WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
void _fetchWaterHeaterStatus(
WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(whId);
@ -72,29 +74,33 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
statusModelList,
);
emit(UpdateState(whModel: deviceStatus));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(WHFailedState(errorMessage: e.toString()));
return;
}
}
_listenToChanges() {
//real-time db
StreamSubscription<DatabaseEvent>? _streamSubscription;
void _listenToChanges() {
try {
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$whId');
_streamSubscription?.cancel();
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$whId');
Stream<DatabaseEvent> stream = ref.onValue;
stream.listen((DatabaseEvent event) async {
_streamSubscription = 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>;
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']));
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = WHModel.fromJson(statusList);
if (!isClosed) {
add(WaterHeaterUpdated());
@ -103,12 +109,21 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
} catch (_) {}
}
_waterHeaterUpdated(WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
@override
Future<void> close() async {
_streamSubscription?.cancel();
_streamSubscription = null;
return super.close();
}
_waterHeaterUpdated(
WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
emit(UpdateState(whModel: deviceStatus));
}
void _changeFirstSwitch(WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
void _changeFirstSwitch(
WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.whSwitch;
@ -118,7 +133,10 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: 'switch_1', value: deviceStatus.firstSwitch),
DeviceControlModel(
deviceId: whId,
code: 'switch_1',
value: deviceStatus.firstSwitch),
whId);
if (!response['success']) {
@ -132,13 +150,16 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
//=====================---------- timer ----------------------------------------
void _setCounterValue(SetCounterValue event, Emitter<WaterHeaterState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: event.deviceCode, value: seconds), whId);
DeviceControlModel(
deviceId: whId, code: event.deviceCode, value: seconds),
whId);
if (response['success'] ?? false) {
if (event.deviceCode == 'countdown_1') {
@ -160,7 +181,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(whId);
@ -250,7 +272,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
deviceId: whId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(WHInitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -261,12 +284,13 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds =
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(ToggleScheduleEvent event, Emitter<WaterHeaterState> emit) async {
Future toggleChange(
ToggleScheduleEvent event, Emitter<WaterHeaterState> emit) async {
try {
emit(WHLoadingState());
final response = await DevicesAPI.changeSchedule(
@ -284,7 +308,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
Future deleteSchedule(DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async {
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async {
try {
emit(WHLoadingState());
final response = await DevicesAPI.deleteSchedule(
@ -303,7 +328,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _toggleCreateCirculate(ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
void _toggleCreateCirculate(
ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
createCirculate = !createCirculate;
selectedDays.clear();
@ -311,13 +337,15 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
emit(UpdateCreateScheduleState(createCirculate));
}
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -366,8 +394,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<GroupWHModel> groupWaterHeaterList = [];
bool allSwitchesOn = true;
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<WaterHeaterState> emit) async {
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
bool allSwitchesValue = true;
@ -379,7 +407,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -394,7 +423,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _fetchWHWizardStatus(InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
void _fetchWHWizardStatus(
InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
devicesList = [];
@ -404,7 +434,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
HomeCubit.getInstance().selectedSpace?.id ?? '', 'WH');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
@ -426,23 +457,27 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
return true;
});
}
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
} catch (e) {
// emit(FailedState(error: e.toString()));
return;
}
}
void _groupAllOn(GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async {
void _groupAllOn(
GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = true;
}
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: true));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: true));
List<String> allDeviceIds = groupWaterHeaterList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
@ -460,15 +495,18 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async {
void _groupAllOff(
GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = false;
}
emit(UpdateGroupState(twoGangList: groupWaterHeaterList, allSwitches: false));
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: false));
List<String> allDeviceIds = groupWaterHeaterList.map((device) => device.deviceId).toList();
List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_event.dart';
import 'package:syncrow_app/features/devices/bloc/water_leak_bloc/water_leak_state.dart';
@ -21,7 +20,6 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
on<ToggleWaterLeakAlarmEvent>(_toggleWaterLeakAlarm);
}
Timer? _timer;
bool lowBattery = false;
bool closingReminder = false;
bool waterAlarm = false;
@ -134,32 +132,42 @@ class WaterLeakBloc extends Bloc<WaterLeakEvent, WaterLeakState> {
emit(WaterLeakFailedState(errorMessage: errorMessage));
}
}
// Timer? _timer;
// StreamSubscription<DatabaseEvent>? _streamSubscription;
// void _listenToChanges() {
// try {
// _streamSubscription?.cancel();
// DatabaseReference ref =
// FirebaseDatabase.instance.ref('device-status/$WLId');
// Stream<DatabaseEvent> stream = ref.onValue;
_listenToChanges() {
try {
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$WLId');
Stream<DatabaseEvent> stream = ref.onValue;
// _streamSubscription = 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 = WaterLeakModel.fromJson(statusList);
// if (!isClosed) {
// add(
// WaterLeakSwitch(switchD: deviceStatus.waterContactState),
// );
// }
// });
// } catch (_) {}
// }
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 = [];
// @override
// Future<void> close() async {
// _streamSubscription?.cancel();
// _streamSubscription = null;
// return super.close();
// }
usersMap['status'].forEach((element) {
statusList.add(StatusModel(code: element['code'], value: true));
});
deviceStatus = WaterLeakModel.fromJson(statusList);
if (!isClosed) {
add(
WaterLeakSwitch(switchD: deviceStatus.waterContactState),
);
}
});
} catch (_) {}
}
}

View File

@ -11,12 +11,14 @@ class AcStatusModel {
bool childLock;
late TempModes acMode;
late FanSpeeds acFanSpeed;
int countdown1;
AcStatusModel(
{required this.uuid,
required this.acSwitch,
required this.modeString,
required this.tempSet,
required this.countdown1,
required this.currentTemp,
required this.fanSpeedsString,
required this.childLock}) {
@ -25,25 +27,28 @@ class AcStatusModel {
}
factory AcStatusModel.fromJson(String id, List<StatusModel> jsonList) {
late bool _acSwitch;
late String _mode;
late int _tempSet;
late int _currentTemp;
late String _fanSpeeds;
late bool _childLock;
bool _acSwitch = false;
String _mode = '';
int _tempSet = 210;
int _currentTemp = 210;
String _fanSpeeds = '';
int _countdown1 = 0;
bool _childLock = false;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch') {
_acSwitch = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'mode') {
_mode = jsonList[i].value ?? TempModes.cold;
_mode = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'temp_set') {
_tempSet = jsonList[i].value ?? 210;
} else if (jsonList[i].code == 'temp_current') {
_currentTemp = jsonList[i].value ?? 210;
} else if (jsonList[i].code == 'level') {
_fanSpeeds = jsonList[i].value ?? 210;
_fanSpeeds = jsonList[i].value ?? '';
} else if (jsonList[i].code == 'child_lock') {
_childLock = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'countdown_time') {
_countdown1 = jsonList[i].value ?? 0;
}
}
return AcStatusModel(
@ -53,6 +58,7 @@ class AcStatusModel {
tempSet: _tempSet,
currentTemp: _currentTemp,
fanSpeedsString: _fanSpeeds,
countdown1: _countdown1,
childLock: _childLock);
}

View File

@ -7,23 +7,31 @@ class CeilingSensorModel {
int presenceRange;
int sportsPara;
String bodyMovement;
String nobodyTime;
int movingMaxDis;
SpaceTypes spaceType;
CeilingSensorModel(
{required this.presenceState,
required this.sensitivity,
required this.nobodyTime,
required this.spaceType,
required this.checkingResult,
required this.presenceRange,
required this.sportsPara,
required this.movingMaxDis,
required this.bodyMovement});
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
late String _presenceState;
late int _sensitivity;
late String _checkingResult;
String _presenceState = 'none';
int _sensitivity = 1;
String _checkingResult = '';
int _presenceRange = 1;
int _sportsPara = 1;
int _moving_max_dis = 0;
String _bodyMovement = 'none';
String _nobody_time = 'none';
SpaceTypes _spaceType = SpaceTypes.none;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'presence_state') {
_presenceState = jsonList[i].value ?? 'none';
@ -37,14 +45,46 @@ class CeilingSensorModel {
_sportsPara = jsonList[i].value ?? 0;
} else if (jsonList[i].code == 'body_movement') {
_bodyMovement = jsonList[i].value ?? '';
}
} else if (jsonList[i].code == 'nobody_time') {
_nobody_time = jsonList[i].value ?? 'none';
} else if (jsonList[i].code == 'moving_max_dis') {
_moving_max_dis = jsonList[i].value ?? 0;
} else if (jsonList[i].code == 'scene')
_spaceType = getSpaceType(jsonList[i].value ?? 'none');
}
return CeilingSensorModel(
spaceType: _spaceType,
movingMaxDis: _moving_max_dis,
presenceState: _presenceState,
sensitivity: _sensitivity,
checkingResult: _checkingResult,
presenceRange: _presenceRange,
sportsPara: _sportsPara,
nobodyTime: _nobody_time,
bodyMovement: _bodyMovement);
}
}
enum SpaceTypes {
none,
parlour,
area,
toilet,
bedroom,
}
SpaceTypes getSpaceType(String value) {
switch (value) {
case 'parlour':
return SpaceTypes.parlour;
case 'area':
return SpaceTypes.area;
case 'toilet':
return SpaceTypes.toilet;
case 'bedroom':
return SpaceTypes.bedroom;
case 'none':
default:
return SpaceTypes.none;
}
}

View File

@ -10,11 +10,11 @@ class CurtainModel {
});
factory CurtainModel.fromJson(List<StatusModel> jsonList) {
late String _control;
late int _percent;
String _control = '';
int _percent = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'control') {
_control = jsonList[i].value ?? false;
_control = jsonList[i].value ?? '';
}
if (jsonList[i].code == 'percent_control') {
_percent = jsonList[i].value ?? 0;

View File

@ -1,5 +1,3 @@
import 'dart:convert';
class DeviceInfoModel {
final int activeTime;
final String category;
@ -79,7 +77,7 @@ class DeviceInfoModel {
uuid: json['uuid'],
productUuid: json['productUuid'],
productType: json['productType'],
permissionType: json['permissionType'],
permissionType: json['permissionType'] ?? '',
macAddress: json['macAddress'],
subspace: Subspace.fromJson(json['subspace']),
);

View File

@ -10,6 +10,9 @@ class DeviceModel {
String? model;
String? name;
String? icon;
String? categoryName;
bool? toggleStatus = false;
String? type;
bool? isOnline;
List<StatusModel> status = [];
@ -21,6 +24,8 @@ class DeviceModel {
DeviceType? productType;
bool isSelected = false;
late List<FunctionModel> functions;
DeviceSubspace? subspace;
DeviceModel(
{this.activeTime,
this.productUuid,
@ -34,6 +39,9 @@ class DeviceModel {
this.updateTime,
this.uuid,
this.productType,
this.categoryName,
this.subspace,
this.toggleStatus,
this.icon,
this.type}) {
functions = getFunctions(productType!);
@ -84,26 +92,79 @@ class DeviceModel {
tempIcon = Assets.sixSceneHomeIcon;
} else if (type == DeviceType.SOS) {
tempIcon = Assets.sosHomeIcon;
} else if (type == DeviceType.FlushMountedSensor) {
tempIcon = Assets.flushIcon;
} else {
tempIcon = Assets.assetsIconsLogo;
}
// Step 1: Parse `status` as before
final statusList = (json['status'] as List<dynamic>?)
?.map((st) => StatusModel.fromJson(st as Map<String, dynamic>))
.toList();
// Step 2: Check whether ANY status means "off"
final anyOff = statusList?.any((s) {
final code = s.code;
if (code == null) return false;
// 1) Handle "switch" or "switch_x"
if (code == 'switch' || code.startsWith('switch_')) {
// If it's false, we consider that "off"
return s.value == false;
}
// 2) If code == "control" and value == "stop", consider "off"
if (s.value == 'open') {
return true;
}
// 3) If code == "percent_control" and value == 0, maybe "off"
if (code == 'percent_control' && s.value == 0) {
return true;
}
// Add more conditions for other codes as needed
// Default: if none of the above apply, it's not "off"
return false;
});
// Step 3: Decide final toggleStatus (true = fully "on", false = partially/fully "off")
bool computedToggleStatus = !(anyOff ?? false);
return DeviceModel(
icon: tempIcon,
activeTime: json['activeTime'],
// id: json['id'],
localKey: json['localKey'],
model: json['model'],
name: json['name'],
isOnline: json['online'],
productName: json['productName'],
timeZone: json['timeZone'],
updateTime: json['updateTime'],
uuid: json['uuid'],
productType: type,
type: json['productType'],
status: [],
productUuid: json['productUuid']);
icon: tempIcon,
activeTime: json['activeTime'],
categoryName: json['categoryName'],
localKey: json['localKey'],
model: json['model'],
name: json['name'],
isOnline: json['online'],
productName: json['productName'],
timeZone: json['timeZone'],
updateTime: json['updateTime'],
uuid: json['uuid'],
productType: type,
type: json['productType'],
// Use the newly computed toggleStatus:
toggleStatus: computedToggleStatus,
// Or if you prefer to use the value returned by the backend when available:
// toggleStatus: json['toggleStatus'] ?? computedToggleStatus,
status: statusList ?? [],
subspace: json['subspace'] != null
? DeviceSubspace.fromJson(json['subspace'])
: DeviceSubspace(
createdAt: null,
disabled: false,
subspaceName: '',
updatedAt: null,
uuid: '',
),
productUuid: json['productUuid'],
);
}
Map<String, dynamic> toJson() {
@ -118,9 +179,50 @@ class DeviceModel {
'updateTime': updateTime,
'uuid': uuid,
'productType': productType,
'subspace': subspace?.toJson(), // serialize subspace
};
}
List<FunctionModel> getFunctions(DeviceType type) =>
devicesFunctionsMap[productType] ?? [];
}
class DeviceSubspace {
String? uuid;
DateTime? createdAt;
DateTime? updatedAt;
String? subspaceName;
bool? disabled;
DeviceSubspace({
this.uuid,
this.createdAt,
this.updatedAt,
this.subspaceName,
this.disabled,
});
factory DeviceSubspace.fromJson(Map<String, dynamic> json) {
return DeviceSubspace(
uuid: json['uuid'],
createdAt: json['createdAt'] != null
? DateTime.tryParse(json['createdAt'])
: null,
updatedAt: json['updatedAt'] != null
? DateTime.tryParse(json['updatedAt'])
: null,
subspaceName: json['subspaceName'],
disabled: json['disabled'],
);
}
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'createdAt': createdAt?.toIso8601String(),
'updatedAt': updatedAt?.toIso8601String(),
'subspaceName': subspaceName,
'disabled': disabled,
};
}
}

View File

@ -1,27 +1,22 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class DoorSensorModel {
bool doorContactState;
int batteryPercentage;
DoorSensorModel(
{required this.doorContactState,
required this.batteryPercentage,
});
DoorSensorModel({
required this.doorContactState,
required this.batteryPercentage,
});
factory DoorSensorModel.fromJson(List<StatusModel> jsonList) {
late bool _doorContactState;
late int _batteryPercentage;
bool _doorContactState = false;
int _batteryPercentage = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'doorcontact_state') {
_doorContactState = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'battery_percentage') {
} else if (jsonList[i].code == 'battery_percentage') {
_batteryPercentage = jsonList[i].value ?? 0;
}
}

View File

@ -0,0 +1,100 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class FlushSensorModel {
FlushSensorModel({
required this.presenceState,
required this.farDetection,
required this.illuminance,
required this.sensitivity,
required this.occurDistReduce,
required this.noneDelay,
required this.presenceDelay,
required this.nearDetection,
required this.sensiReduce,
required this.checkingResult,
});
static const String codePresenceState = 'presence_state';
static const String codeSensitivity = 'sensitivity';
static const String codeNearDetection = 'near_detection';
static const String codeFarDetection = 'far_detection';
static const String codeCheckingResult = 'checking_result';
static const String codePresenceDelay = 'presence_delay';
static const String codeNoneDelay = 'none_delay';
static const String codeOccurDistReduce = 'occur_dist_reduce';
static const String codeIlluminance = 'illum_value';
static const String codeSensiReduce = 'sensi_reduce';
String presenceState;
int sensitivity;
int nearDetection;
int farDetection;
String checkingResult;
int presenceDelay;
int noneDelay;
int occurDistReduce;
int illuminance;
int sensiReduce;
factory FlushSensorModel.fromJson(List<StatusModel> jsonList) {
String presenceState = 'none';
int sensitivity = 0;
int nearDetection = 0;
int farDetection = 0;
String checkingResult = 'none';
int presenceDelay = 0;
int noneDelay = 0;
int occurDistReduce = 0;
int illuminance = 0;
int sensiReduce = 0;
for (var status in jsonList) {
switch (status.code) {
case codePresenceState:
presenceState = status.value ?? 'presence';
break;
case codeSensitivity:
sensitivity = status.value ?? 0;
break;
case codeNearDetection:
nearDetection = status.value ?? 0;
break;
case codeFarDetection:
farDetection = status.value ?? 0;
break;
case codeCheckingResult:
checkingResult = status.value ?? 'check_success';
break;
case codePresenceDelay:
presenceDelay = status.value ?? 0;
break;
case codeNoneDelay:
noneDelay = status.value ?? 0;
break;
case codeOccurDistReduce:
occurDistReduce = status.value ?? 0;
break;
case codeIlluminance:
illuminance = status.value ?? 0;
break;
case codeSensiReduce:
sensiReduce = status.value ?? 0;
break;
}
}
return FlushSensorModel(
presenceState: presenceState,
sensitivity: sensitivity,
nearDetection: nearDetection,
farDetection: farDetection,
checkingResult: checkingResult,
presenceDelay: presenceDelay,
noneDelay: noneDelay,
occurDistReduce: occurDistReduce,
illuminance: illuminance,
sensiReduce: sensiReduce,
);
}
}

View File

@ -24,15 +24,15 @@ class GarageDoorModel {
});
factory GarageDoorModel.fromJson(List<StatusModel> jsonList) {
late bool _switch1 = false;
late bool _doorContactState = false;
late int _countdown1 = 0;
late int _countdownAlarm = 0;
late String _doorControl1 = "closed";
late bool _voiceControl1 = false;
late String _doorState1 = "closed";
late int _batteryPercentage = 0;
late int _tr_timecon = 0;
bool _switch1 = false;
bool _doorContactState = false;
int _countdown1 = 0;
int _countdownAlarm = 0;
String _doorControl1 = "closed";
bool _voiceControl1 = false;
String _doorState1 = "closed";
int _batteryPercentage = 0;
int _tr_timecon = 0;
for (var status in jsonList) {
switch (status.code) {

View File

@ -1,29 +1,27 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
class OneGangModel {
bool firstSwitch;
int firstCountDown;
OneGangModel(
{required this.firstSwitch,
required this.firstCountDown,
});
OneGangModel({
required this.firstSwitch,
required this.firstCountDown,
});
factory OneGangModel.fromJson(List<StatusModel> jsonList) {
late bool _switch;
late int _count;
bool _switch = false;
int _count = 0;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch_1') {
_switch = jsonList[i].value ?? false;
} else if (jsonList[i].code == 'countdown_1') {
} else if (jsonList[i].code == 'countdown_1') {
_count = jsonList[i].value ?? 0;
}
}
return OneGangModel(
firstSwitch: _switch,
firstSwitch: _switch,
firstCountDown: _count,
);
}

View File

@ -1,5 +1,3 @@
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
@ -15,15 +13,14 @@ class OneTouchModel {
required this.firstCountDown,
required this.light_mode,
required this.relay,
required this.relay_status_1
});
required this.relay_status_1});
factory OneTouchModel.fromJson(List<StatusModel> jsonList) {
late bool _switch;
late int _count;
late String _relay;
late String _light_mode;
late String relay_status_1;
bool _switch = false;
int _count = 0;
String _relay = '';
String _light_mode = '';
String relay_status_1 = '';
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch_1') {
@ -41,10 +38,8 @@ class OneTouchModel {
return OneTouchModel(
firstSwitch: _switch,
firstCountDown: _count,
light_mode: lightStatusExtension.fromString(_light_mode) ,
relay: StatusExtension.fromString(_relay ) ,
relay_status_1: StatusExtension.fromString(relay_status_1 )
);
light_mode: lightStatusExtension.fromString(_light_mode),
relay: StatusExtension.fromString(_relay),
relay_status_1: StatusExtension.fromString(relay_status_1));
}
}

View File

@ -22,14 +22,14 @@ class SixSceneModel {
});
factory SixSceneModel.fromJson(List<StatusModel> jsonList) {
late dynamic _scene_1;
late dynamic _scene_2;
late dynamic _scene_3;
late dynamic _scene_4;
late dynamic _scene_5;
late dynamic _scene_6;
late dynamic _scene_id_group_id;
late dynamic _switch_backlight;
dynamic _scene_1 = '';
dynamic _scene_2 = '';
dynamic _scene_3 = '';
dynamic _scene_4 = '';
dynamic _scene_5 = '';
dynamic _scene_6 = '';
dynamic _scene_id_group_id = 0;
dynamic _switch_backlight = false;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'scene_1') {

View File

@ -39,23 +39,23 @@ class SmartDoorModel {
required this.normalOpenSwitch});
factory SmartDoorModel.fromJson(List<StatusModel> jsonList) {
late int _unlockFingerprint;
late int _unlockPassword;
late int _unlockTemporary;
late int _unlockCard;
late String _unlockAlarm;
late int _unlockRequest;
late int _residualElectricity;
late bool _reverseLock;
late int _unlockApp;
late bool _hijack;
late bool _doorbell;
late String _unlockOfflinePd;
late String _unlockOfflineClear;
late String _unlockDoubleKit;
late String _remoteNoPdSetkey;
late String _remoteNoDpKey;
late bool _normalOpenSwitch;
int _unlockFingerprint = 0;
int _unlockPassword = 0;
int _unlockTemporary = 0;
int _unlockCard = 0;
String _unlockAlarm = '';
int _unlockRequest = 0;
int _residualElectricity = 0;
bool _reverseLock = false;
int _unlockApp = 0;
bool _hijack = false;
bool _doorbell = false;
String _unlockOfflinePd = '';
String _unlockOfflineClear = '';
String _unlockDoubleKit = '';
String _remoteNoPdSetkey = '';
String _remoteNoDpKey = '';
bool _normalOpenSwitch = false;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'unlock_fingerprint') {

Some files were not shown because too many files have changed in this diff Show More