Compare commits
39 Commits
bugfix/SP-
...
SP-630
Author | SHA1 | Date | |
---|---|---|---|
d9761168e6 | |||
cc7af3e4e6 | |||
b5af6add35 | |||
0d5492d626 | |||
908533dc9e | |||
d75d438106 | |||
b8b6ec67c7 | |||
fed39b7198 | |||
5030b3f313 | |||
c4ff19d471 | |||
e1cd9e55c2 | |||
3082148e8c | |||
2fb18965f4 | |||
8d784f1e95 | |||
bc1b92cd5c | |||
6e32f30970 | |||
781522d4b6 | |||
4e345db842 | |||
8508995108 | |||
e3a6579819 | |||
9d8c40e44e | |||
a811baca70 | |||
04e8131fb2 | |||
dfae04076f | |||
429009aefa | |||
62e80c89a2 | |||
d97efe229d | |||
58e13da887 | |||
7279215cdc | |||
e23210777a | |||
45ebd10980 | |||
0b3f9de162 | |||
a46cec9dc5 | |||
09d1ce5ccb | |||
c3273c729d | |||
42e76f1c6e | |||
64e2ba2fd9 | |||
54cce48b89 | |||
f0feb4021f |
31
.vscode/launch.json
vendored
@ -1,5 +1,6 @@
|
||||
{
|
||||
"configurations": [
|
||||
|
||||
|
||||
{
|
||||
|
||||
@ -11,9 +12,13 @@
|
||||
|
||||
"args": [
|
||||
|
||||
"--dart-define",
|
||||
|
||||
"FLAVOR=development"
|
||||
"--flavor",
|
||||
|
||||
"dev",
|
||||
|
||||
"-t",
|
||||
|
||||
"lib/main_dev.dart"
|
||||
|
||||
],
|
||||
|
||||
@ -29,9 +34,13 @@
|
||||
|
||||
"args": [
|
||||
|
||||
"--dart-define",
|
||||
|
||||
"FLAVOR=staging"
|
||||
"--flavor",
|
||||
|
||||
"prod",
|
||||
|
||||
"-t",
|
||||
|
||||
"lib/main.dart"
|
||||
|
||||
],
|
||||
|
||||
@ -47,9 +56,13 @@
|
||||
|
||||
"args": [
|
||||
|
||||
"--dart-define",
|
||||
|
||||
"FLAVOR=production"
|
||||
"--flavor",
|
||||
|
||||
"prod",
|
||||
|
||||
"-t",
|
||||
|
||||
"lib/main.dart"
|
||||
|
||||
],
|
||||
|
||||
|
@ -43,7 +43,7 @@ Open a pull request on the DEV branch and add a reviewer to it.
|
||||
|
||||
To test the app, we use Firebase Distribution to send testing builds of the app to the testers.
|
||||
|
||||
- Create an Android build for testing with the command: `flutter build apk --dart-define FLAVOR=staging --build-name={build_version}-qa --build-number={build_number}`.
|
||||
- Create an Android build for testing with the command: `flutter build apk --flavor prod -t lib/main.dart`.
|
||||
|
||||
- Upload the apk file to Firebase distribution
|
||||
|
||||
@ -61,7 +61,7 @@ To test the app, we use Firebase Distribution to send testing builds of the app
|
||||
|
||||
To test the app, we use Firebase Distribution to send testing builds of the app to the testers.
|
||||
|
||||
1- Create an iOS for testing with the command: `flutter build ios --dart-define FLAVOR=staging --build-name=1.0.0-qa --build-number=1`.
|
||||
1- Create an iOS for testing with the command: `flutter build ios --flavor prod -t lib/main.dart`.
|
||||
|
||||
2- Create an archive of your app: Open Xcode and go to the "Product" menu, then select "Archive" to create an archive of your app. Make sure to select the "Generic iOS Device" as the build destination.
|
||||
|
||||
@ -79,7 +79,7 @@ To test the app, we use Firebase Distribution to send testing builds of the app
|
||||
|
||||
You can also create an archive through these commands lines:
|
||||
|
||||
1- Create an iOS for testing with the command: `flutter build ios --dart-define FLAVOR=staging --build-name={build_version}-qa --build-number={build_number}`.
|
||||
1- Create an iOS for testing with the command: `flutter build ios --flavor prod -t lib/main.dart`.
|
||||
|
||||
2- Create an archive with this command: `xcodebuild -workspace Runner.xcworkspace -scheme Runner -archivePath "build/Runner.xcarchive" archive`.
|
||||
|
||||
|
@ -44,6 +44,18 @@ android {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
flavorDimensions "env"
|
||||
productFlavors {
|
||||
dev {
|
||||
dimension "env"
|
||||
applicationId "com.example.syncrow_application"
|
||||
}
|
||||
prod {
|
||||
dimension "env"
|
||||
applicationId "com.example.syncrow_application"
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.example.syncrow_application"
|
||||
|
@ -1,48 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "427332280600",
|
||||
"project_id": "test2-8a3d2",
|
||||
"storage_bucket": "test2-8a3d2.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:427332280600:android:550f67441246cb1a0c7e6d",
|
||||
"android_client_info": {
|
||||
"package_name": "com.example.syncrow_application"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:427332280600:android:bb6047adeeb80fb00c7e6d",
|
||||
"android_client_info": {
|
||||
"package_name": "com.example.syncrow_application"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
48
android/app/src/dev/google-services.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "427332280600",
|
||||
"project_id": "test2-8a3d2",
|
||||
"storage_bucket": "test2-8a3d2.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:427332280600:android:550f67441246cb1a0c7e6d",
|
||||
"android_client_info": {
|
||||
"package_name": "com.example.syncrow_application"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:427332280600:android:bb6047adeeb80fb00c7e6d",
|
||||
"android_client_info": {
|
||||
"package_name": "com.example.syncrow_application"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
30
android/app/src/prod/google-services.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "786692570726",
|
||||
"firebase_url": "https://syncrow-staging-default-rtdb.firebaseio.com",
|
||||
"project_id": "syncrow-staging",
|
||||
"storage_bucket": "syncrow-staging.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:786692570726:android:0ef7079c2b978d4417b7a7",
|
||||
"android_client_info": {
|
||||
"package_name": "com.example.syncrow_application"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyDP9GpYfLE8gHTj3kZ1hW8fx_FkJqOqSQk"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
47
assets/icons/closed_door.svg
Normal file
@ -0,0 +1,47 @@
|
||||
<svg width="201" height="260" viewBox="0 0 201 260" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_3851_4852)">
|
||||
<g filter="url(#filter1_i_3851_4852)">
|
||||
<path d="M1 32.5794C1 17.65 11.9782 4.87264 26.8261 3.31376C56.9938 0.146434 80.4127 0.288676 110.23 3.38644C125.15 4.93649 136.229 17.743 136.229 32.7433V219.157C136.229 233.932 125.474 246.635 110.8 248.355C80.8281 251.869 57.0283 251.901 26.4597 248.336C11.7726 246.623 1 233.917 1 219.131V32.5794Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M116.627 154.669C117.475 154.669 118.323 154.345 118.971 153.698C120.266 152.403 120.266 150.304 118.971 149.009C107.888 137.927 107.888 119.894 118.971 108.812C120.266 107.517 120.266 105.418 118.971 104.123C117.676 102.829 115.577 102.829 114.283 104.123C100.615 117.792 100.615 140.03 114.283 153.698C114.93 154.345 115.778 154.669 116.627 154.669Z" fill="#B3DAFE"/>
|
||||
<path d="M123.6 141.79C124.312 141.79 125.024 141.518 125.567 140.975C126.653 139.889 126.653 138.127 125.566 137.041C123.395 134.87 122.199 131.982 122.199 128.911C122.199 125.839 123.395 122.952 125.566 120.78C126.653 119.694 126.653 117.933 125.567 116.847C124.48 115.76 122.719 115.76 121.633 116.846C118.411 120.069 116.636 124.353 116.636 128.911C116.636 133.468 118.41 137.753 121.633 140.975C122.176 141.518 122.888 141.79 123.6 141.79Z" fill="#B3DAFE"/>
|
||||
<path d="M74.4947 201.887L74.4947 214.513C74.4947 217.026 72.4581 219.063 69.9447 219.063C67.4313 219.063 65.3948 217.026 65.3948 214.513L65.3948 201.887C65.3948 199.374 67.4313 197.337 69.9447 197.337C72.4581 197.337 74.4947 199.374 74.4947 201.887Z" fill="#B3DAFE"/>
|
||||
<g filter="url(#filter2_i_3851_4852)">
|
||||
<path d="M146.229 60.2459C146.229 53.612 150.555 47.5909 157.072 46.3483C165.305 44.7783 172.168 44.839 180.304 46.382C186.889 47.6306 191.305 53.6871 191.305 60.3888V203.89C191.305 210.378 187.172 216.307 180.833 217.686C172.408 219.518 165.306 219.531 156.73 217.674C150.379 216.299 146.229 210.366 146.229 203.867V60.2459Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M162.423 103.153C161.575 103.153 160.727 103.476 160.079 104.124C158.784 105.419 158.784 107.517 160.079 108.812C171.162 119.894 171.162 137.927 160.079 149.009C158.784 150.305 158.784 152.403 160.079 153.698C161.374 154.992 163.473 154.992 164.767 153.698C178.435 140.03 178.435 117.791 164.767 104.123C164.12 103.476 163.272 103.153 162.423 103.153Z" fill="#B3DAFE"/>
|
||||
<path d="M155.45 116.032C154.738 116.032 154.026 116.303 153.483 116.847C152.397 117.933 152.397 119.694 153.484 120.78C155.655 122.952 156.851 125.839 156.851 128.911C156.851 131.982 155.655 134.869 153.484 137.041C152.397 138.128 152.397 139.889 153.483 140.975C154.57 142.061 156.331 142.061 157.417 140.975C160.639 137.753 162.414 133.468 162.414 128.911C162.414 124.353 160.64 120.069 157.417 116.846C156.874 116.304 156.162 116.032 155.45 116.032Z" fill="#B3DAFE"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3851_4852" x="0" y="0" width="200.305" height="260" 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 dx="4" dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2.5"/>
|
||||
<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.2 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3851_4852"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3851_4852" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_i_3851_4852" x="0" y="1" width="136.229" height="250" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<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 dx="-1"/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4852"/>
|
||||
</filter>
|
||||
<filter id="filter2_i_3851_4852" x="144.229" y="45.1975" width="47.0764" height="173.866" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<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 dx="-2"/>
|
||||
<feGaussianBlur stdDeviation="5"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4852"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
10
assets/icons/door_notification_setting_icon.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="44" height="50" viewBox="0 0 44 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.9023 9.10478C24.0934 9.10478 23.4375 8.44893 23.4375 7.63994V4.39453C23.4375 3.58682 22.7804 2.92969 21.9727 2.92969C21.1649 2.92969 20.5078 3.58682 20.5078 4.39453V7.63994C20.5078 8.44893 19.852 9.10478 19.043 9.10478C18.234 9.10478 17.5781 8.44893 17.5781 7.63994V4.39453C17.5781 1.97139 19.5495 0 21.9727 0C24.3958 0 26.3672 1.97139 26.3672 4.39453V7.63994C26.3672 8.44893 25.7113 9.10478 24.9023 9.10478Z" fill="#FFB454"/>
|
||||
<path d="M23.4375 4.39453V7.63994C23.4375 8.44893 24.0934 9.10478 24.9023 9.10478C25.7113 9.10478 26.3672 8.44893 26.3672 7.63994V4.39453C26.3672 1.97139 24.3958 0 21.9727 0V2.92969C22.7805 2.92969 23.4375 3.58682 23.4375 4.39453Z" fill="#FF8E00"/>
|
||||
<path d="M21.9727 50C17.9341 50 14.6484 46.7144 14.6484 42.6758C14.6484 41.8668 15.3043 41.2109 16.1133 41.2109H27.832C28.641 41.2109 29.2969 41.8668 29.2969 42.6758C29.2969 46.7144 26.0113 50 21.9727 50Z" fill="#FFB454"/>
|
||||
<path d="M27.832 41.2109H21.9727V50C26.0112 50 29.2969 46.7144 29.2969 42.6758C29.2969 41.8668 28.641 41.2109 27.832 41.2109Z" fill="#FF8E00"/>
|
||||
<path d="M42.4805 44.1406H1.46486C0.877946 44.1406 0.34777 43.7903 0.117497 43.2505C-0.112777 42.7106 0.00138367 42.0855 0.407634 41.6619C4.55295 37.3389 6.83595 31.6595 6.83595 25.6701V20.9961C6.83595 12.6497 13.6263 5.85938 21.9727 5.85938C30.3191 5.85938 37.1094 12.6497 37.1094 20.9961V25.6701C37.1094 31.6596 39.3924 37.3389 43.5378 41.6619C43.944 42.0855 44.0581 42.7106 43.8279 43.2505C43.5977 43.7903 43.0674 44.1406 42.4805 44.1406Z" fill="#FFE278"/>
|
||||
<path d="M42.4805 44.1406C43.0674 44.1406 43.5976 43.7903 43.8278 43.2505C44.0581 42.7106 43.9439 42.0855 43.5378 41.6619C39.3924 37.3389 37.1094 31.6595 37.1094 25.6701V20.9961C37.1094 12.6497 30.319 5.85938 21.9727 5.85938V44.1406H42.4805Z" fill="#FFB454"/>
|
||||
<path d="M42.4803 22.4612C41.6713 22.4612 41.0154 21.8053 41.0154 20.9963C41.0154 15.9097 39.0347 11.1276 35.4379 7.53091C34.8658 6.95884 34.8658 6.0314 35.4379 5.45933C36.0099 4.88726 36.9374 4.88726 37.5095 5.45933C41.6596 9.60933 43.9451 15.1272 43.9451 20.9963C43.9451 21.8053 43.2893 22.4612 42.4803 22.4612Z" fill="#08475E"/>
|
||||
<path d="M1.46484 22.4612C0.655859 22.4612 0 21.8053 0 20.9963C0 15.1272 2.28555 9.60942 6.43564 5.45933C7.00762 4.88726 7.93516 4.88726 8.50723 5.45933C9.0793 6.0314 9.0793 6.95884 8.50723 7.53091C4.91055 11.1277 2.92969 15.9098 2.92969 20.9963C2.92969 21.8053 2.27383 22.4612 1.46484 22.4612Z" fill="#0A789B"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
18
assets/icons/door_records_icon.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.61102 32.55L0.0294905 14.2492C-0.0650406 13.9826 0.0752911 13.6874 0.341795 13.5901C8.9949 10.4779 18.7455 7.58334 27.0805 4.02691C27.453 3.79194 27.7453 4.02407 27.9057 4.46821L38.2465 31.1229L41.0545 38.9321C41.149 39.1986 41.0115 39.4967 40.745 39.5913L20.9575 46.707L13.2441 49.4811C12.9776 49.5786 12.6825 49.4381 12.5851 49.1716L6.61102 32.55Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.098 26.4772L8.81158 7.31083C8.76285 7.02997 8.95201 6.76347 9.22994 6.71474L31.8627 2.83448L37.046 1.98047C37.3297 1.85723 37.791 2.00049 37.8998 2.63389L43.4985 30.5925L44.8997 38.7715C44.9484 39.0495 44.7593 39.3189 44.4813 39.3676L23.7568 42.9212L15.6767 44.3082C15.3988 44.3541 15.1294 44.165 15.0807 43.8869L12.098 26.4772Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.439 20.8256V39.2527C18.439 39.5479 18.6797 39.7914 18.9748 39.7914H27.5276H40.1893H42.0088H49.4642C49.7593 39.7914 50 39.5479 50 39.2527V30.5952V6.68016V6.43085H44.556C44.0317 6.43085 42.9428 6.50536 42.9428 5.3161L42.9313 0H18.9747C18.6796 0 18.4389 0.240722 18.4389 0.535936V5.13554V7.08143V20.8256H18.439Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.35594 10.4889C6.29012 11.5206 3.25292 12.5436 0.341795 13.5896C0.0752911 13.6871 -0.0650406 13.9822 0.0294905 14.2487L6.61102 32.5497L12.5851 49.1712C12.6826 49.4377 12.9777 49.5781 13.2441 49.4807L20.9575 46.7066L38.5331 40.3875L9.35594 10.4889Z" fill="#B5C4CF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.4389 5.13535L9.22994 6.71435C8.95201 6.76308 8.76285 7.02958 8.81158 7.31044L9.35601 10.4886L12.0981 26.4768L15.0808 43.8864C15.1295 44.1645 15.3989 44.3535 15.6768 44.3077L23.7569 42.9207L38.5331 40.3873L42.0087 39.7912H40.1893L18.4389 5.13535Z" fill="#D7E7EC"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.9999 30.5952V6.68016V6.43085V6.34774C49.9999 6.19296 49.934 6.16718 49.6962 5.93505L43.8196 0.329589C43.5417 0.0659178 43.4959 0 43.3325 0H42.9313H18.9747C18.6796 0 18.4389 0.240722 18.4389 0.535936V39.2527C18.4389 39.5479 18.6796 39.7914 18.9747 39.7914H49.4641C49.7592 39.7914 49.9999 39.5479 49.9999 39.2527V30.5952Z" fill="#EDF3F4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.4389 5.13535L16.2814 5.50507V41.2328C16.2814 41.5309 16.5221 41.7716 16.8172 41.7716H25.37H30.4588L38.5331 40.3874L42.0087 39.7913H40.1893H37.9515H27.5276H18.9747C18.6796 39.7913 18.4389 39.5478 18.4389 39.2526C18.4389 27.881 18.4389 16.5067 18.4389 5.13535Z" fill="#B5C4CF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.098 26.4771L9.35591 10.4889C8.61383 10.7382 7.87457 10.9875 7.13815 11.2368L7.47916 13.2228L10.2212 29.2111L13.2069 46.6207C13.2527 46.8987 13.522 47.0878 13.7999 47.042L21.88 45.655L25.7138 44.9988L37.2608 40.8434L37.1233 40.6285L30.4587 41.7719L23.7569 42.9211L15.6768 44.3081C15.3989 44.354 15.1295 44.1649 15.0808 43.8868L12.098 26.4771Z" fill="#9AAFB7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.9999 30.5952V6.68016V6.43085C49.9999 6.14139 49.9053 6.13856 49.6962 5.93505L43.8195 0.329589C43.5416 0.0659178 43.4958 0 43.3324 0H42.9312H36.9685C44.255 9.75516 44.6704 27.3396 39.2637 38.3156C39.0143 38.8257 38.7536 39.3157 38.4814 39.7914H40.1891H42.0086H49.464C49.7591 39.7914 49.9999 39.5479 49.9999 39.2527V30.5952Z" fill="#D7E7EC"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.9427 5.3161C42.9427 6.50536 44.0315 6.43085 44.5559 6.43085H49.9999V6.34774C49.9999 6.19296 49.934 6.16718 49.6962 5.93505L43.8196 0.329589C43.5416 0.0659178 43.4958 0 43.3325 0H42.9313L42.9427 5.3161Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.6962 5.93505L43.8196 0.329589C43.5416 0.0659178 43.4958 0 43.3325 0H42.9313L42.9427 5.31601C42.9427 6.50526 44.0315 6.43075 44.5559 6.43075H49.9999V6.34764C49.9999 6.19296 49.934 6.16718 49.6962 5.93505Z" fill="#B5C4CF"/>
|
||||
<path d="M45.1576 11.7192H23.5849C23.1682 11.7192 22.8304 11.3813 22.8304 10.9644C22.8304 10.5475 23.1682 10.2096 23.5849 10.2096H45.1576C45.5742 10.2096 45.912 10.5475 45.912 10.9644C45.912 11.3813 45.5743 11.7192 45.1576 11.7192Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 17.0811H23.5849C23.1682 17.0811 22.8304 16.7432 22.8304 16.3263C22.8304 15.9095 23.1682 15.5716 23.5849 15.5716H45.1576C45.5742 15.5716 45.912 15.9095 45.912 16.3263C45.912 16.7432 45.5743 17.0811 45.1576 17.0811Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 22.4431H23.5849C23.1682 22.4431 22.8304 22.1052 22.8304 21.6883C22.8304 21.2714 23.1682 20.9335 23.5849 20.9335H45.1576C45.5742 20.9335 45.912 21.2714 45.912 21.6883C45.912 22.1052 45.5743 22.4431 45.1576 22.4431Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 27.805H23.5849C23.1682 27.805 22.8304 27.4671 22.8304 27.0502C22.8304 26.6333 23.1682 26.2954 23.5849 26.2954H45.1576C45.5742 26.2954 45.912 26.6333 45.912 27.0502C45.912 27.4671 45.5743 27.805 45.1576 27.805Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 33.1669H23.5849C23.1682 33.1669 22.8304 32.829 22.8304 32.4121C22.8304 31.9952 23.1682 31.6573 23.5849 31.6573H45.1576C45.5742 31.6573 45.912 31.9952 45.912 32.4121C45.912 32.829 45.5743 33.1669 45.1576 33.1669Z" fill="#9AAFB7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
23
assets/icons/door_sensor_icon.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<svg width="29" height="39" viewBox="0 0 29 39" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_3851_4689)">
|
||||
<path d="M0 5.33646C0 2.84823 1.82766 0.716451 4.30322 0.46559C8.74889 0.0150898 12.2724 0.0349553 16.6673 0.476887C19.1549 0.727017 21 2.86372 21 5.36377V33.7227C21 36.1852 19.2096 38.3047 16.7627 38.5821C12.3371 39.0837 8.75437 39.0879 4.2429 38.579C1.794 38.3027 0 36.1827 0 33.7182V5.33646Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M17.9558 24C18.0876 24 18.2194 23.9498 18.3199 23.8493C18.521 23.6481 18.521 23.3222 18.3199 23.1212C16.5988 21.4002 16.5988 18.5998 18.3199 16.8788C18.521 16.6777 18.521 16.3518 18.3199 16.1507C18.1188 15.9498 17.7929 15.9498 17.5918 16.1507C15.4693 18.2733 15.4693 21.7268 17.5918 23.8493C17.6923 23.9498 17.8241 24 17.9558 24Z" fill="#8AC9FE"/>
|
||||
<path d="M19.0387 22C19.1493 22 19.2598 21.9578 19.3442 21.8735C19.5129 21.7048 19.5129 21.4313 19.3441 21.2626C19.0069 20.9254 18.8212 20.477 18.8212 20C18.8212 19.523 19.0069 19.0747 19.3441 18.7374C19.5129 18.5687 19.5129 18.2952 19.3442 18.1265C19.1754 17.9578 18.9019 17.9579 18.7333 18.1265C18.2329 18.6269 17.9573 19.2923 17.9573 20C17.9573 20.7078 18.2329 21.3731 18.7333 21.8735C18.8176 21.9578 18.9282 22 19.0387 22Z" fill="#8AC9FE"/>
|
||||
<path d="M11.4131 31.3326L11.4131 33.2934C11.4131 33.6836 11.0969 34 10.7066 34C10.3163 34 10 33.6836 10 33.2934L10 31.3326C10 30.9423 10.3163 30.6261 10.7066 30.6261C11.0969 30.6261 11.4131 30.9423 11.4131 31.3326Z" fill="#B3DAFE"/>
|
||||
<path d="M22 9.09138C22 8.20685 22.5774 7.4095 23.4429 7.22709C24.914 6.91707 26.0828 6.92986 27.5356 7.23253C28.4104 7.41477 29 8.21687 29 9.11042V31.8825C29 32.7476 28.4479 33.5327 27.6064 33.733C26.117 34.0877 24.9156 34.0909 23.3975 33.7314C22.5543 33.5317 22 32.746 22 31.8795V9.09138Z" fill="#EAF6FF"/>
|
||||
<path d="M24.5149 24C24.3831 24 24.2514 23.9498 24.1508 23.8493C23.9497 23.6481 23.9497 23.3222 24.1508 23.1212C25.8719 21.4002 25.8719 18.5998 24.1508 16.8788C23.9497 16.6777 23.9497 16.3518 24.1508 16.1507C24.3519 15.9498 24.6778 15.9498 24.8789 16.1507C27.0014 18.2733 27.0014 21.7268 24.8789 23.8493C24.7784 23.9498 24.6466 24 24.5149 24Z" fill="#8AC9FE"/>
|
||||
<path d="M23.432 22C23.3214 22 23.2109 21.9578 23.1265 21.8735C22.9578 21.7048 22.9578 21.4313 23.1266 21.2626C23.4638 20.9254 23.6495 20.477 23.6495 20C23.6495 19.523 23.4638 19.0747 23.1266 18.7374C22.9578 18.5687 22.9578 18.2952 23.1265 18.1265C23.2953 17.9578 23.5688 17.9579 23.7374 18.1265C24.2378 18.6269 24.5134 19.2923 24.5134 20C24.5134 20.7078 24.2379 21.3731 23.7374 21.8735C23.6531 21.9578 23.5425 22 23.432 22Z" fill="#8AC9FE"/>
|
||||
<defs>
|
||||
<filter id="filter0_i_3851_4689" x="-1" y="0.136475" width="22" height="38.823" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<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 dx="-1"/>
|
||||
<feGaussianBlur stdDeviation="1.5"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.538295 0 0 0 0 0.538295 0 0 0 0 0.538295 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4689"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
47
assets/icons/opened_door.svg
Normal file
@ -0,0 +1,47 @@
|
||||
<svg width="241" height="260" viewBox="0 0 241 260" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_3851_4840)">
|
||||
<g filter="url(#filter1_i_3851_4840)">
|
||||
<path d="M1 32.5794C1 17.65 11.9782 4.87264 26.8261 3.31376C56.9938 0.146434 80.4127 0.288676 110.23 3.38644C125.15 4.93649 136.229 17.743 136.229 32.7433V219.157C136.229 233.932 125.474 246.635 110.8 248.355C80.8281 251.869 57.0283 251.901 26.4597 248.336C11.7726 246.623 1 233.917 1 219.131V32.5794Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M113.787 154.669C112.938 154.669 112.09 154.345 111.442 153.698C110.147 152.403 110.147 150.304 111.442 149.009C122.525 137.927 122.525 119.894 111.442 108.812C110.147 107.517 110.147 105.418 111.442 104.123C112.737 102.829 114.836 102.829 116.131 104.123C129.798 117.792 129.798 140.03 116.131 153.698C115.484 154.345 114.635 154.669 113.787 154.669Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
<path d="M106.813 141.79C106.101 141.79 105.39 141.518 104.846 140.975C103.76 139.889 103.76 138.127 104.847 137.041C107.018 134.87 108.214 131.982 108.214 128.911C108.214 125.839 107.018 122.952 104.847 120.78C103.76 119.694 103.76 117.933 104.846 116.847C105.933 115.76 107.694 115.76 108.78 116.846C112.002 120.069 113.777 124.353 113.777 128.911C113.777 133.468 112.003 137.753 108.78 140.975C108.237 141.518 107.525 141.79 106.813 141.79Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
<path d="M74.4946 201.887L74.4946 214.513C74.4946 217.026 72.4581 219.063 69.9447 219.063C67.4313 219.063 65.3948 217.026 65.3948 214.513L65.3948 201.887C65.3948 199.374 67.4313 197.337 69.9447 197.337C72.4581 197.337 74.4946 199.374 74.4946 201.887Z" fill="#B3DAFE"/>
|
||||
<g filter="url(#filter2_i_3851_4840)">
|
||||
<path d="M186.229 60.2459C186.229 53.612 190.555 47.5909 197.072 46.3483C205.305 44.7783 212.168 44.839 220.304 46.382C226.889 47.6306 231.305 53.6871 231.305 60.3888V203.89C231.305 210.378 227.172 216.307 220.833 217.686C212.408 219.518 205.306 219.531 196.73 217.674C190.379 216.299 186.229 210.366 186.229 203.867V60.2459Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M205.263 103.153C206.112 103.153 206.96 103.476 207.608 104.124C208.903 105.419 208.903 107.517 207.608 108.812C196.525 119.894 196.525 137.927 207.608 149.009C208.903 150.305 208.903 152.403 207.608 153.698C206.313 154.992 204.214 154.992 202.919 153.698C189.252 140.03 189.252 117.791 202.919 104.123C203.567 103.476 204.415 103.153 205.263 103.153Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
<path d="M212.237 116.032C212.949 116.032 213.66 116.303 214.204 116.847C215.29 117.933 215.29 119.694 214.203 120.78C212.032 122.952 210.836 125.839 210.836 128.911C210.836 131.982 212.032 134.869 214.203 137.041C215.29 138.128 215.29 139.889 214.204 140.975C213.117 142.061 211.356 142.061 210.27 140.975C207.048 137.753 205.273 133.468 205.273 128.911C205.273 124.353 207.047 120.069 210.27 116.846C210.813 116.304 211.525 116.032 212.237 116.032Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3851_4840" x="0" y="0" width="240.305" height="260" 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 dx="4" dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2.5"/>
|
||||
<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.2 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3851_4840"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3851_4840" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_i_3851_4840" x="0" y="1" width="136.229" height="250" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<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 dx="-1"/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4840"/>
|
||||
</filter>
|
||||
<filter id="filter2_i_3851_4840" x="184.229" y="45.1975" width="47.0763" height="173.866" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<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 dx="-2"/>
|
||||
<feGaussianBlur stdDeviation="5"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4840"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
10
assets/icons/schedule_Inching_icon.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="26" height="25" viewBox="0 0 26 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.5253 22.6799C15.3191 22.7313 15.1089 22.7769 14.9003 22.8154C14.355 22.9168 13.9944 23.4413 14.0953 23.9871C14.1451 24.2557 14.2976 24.4793 14.5047 24.6253C14.7181 24.7755 14.9897 24.8434 15.2665 24.7919C15.5149 24.7458 15.7653 24.6915 16.011 24.6302C16.5495 24.4962 16.8776 23.9506 16.7432 23.4124C16.6092 22.8736 16.0641 22.5458 15.5253 22.6799Z" fill="black"/>
|
||||
<path d="M22.9574 9.20888C23.0278 9.42105 23.1622 9.59425 23.332 9.71393C23.5837 9.89122 23.9131 9.95087 24.2274 9.84694C24.7544 9.67196 25.0399 9.10371 24.8656 8.577C24.7862 8.33689 24.698 8.09602 24.6042 7.8615C24.398 7.34613 23.8134 7.09522 23.2978 7.30137C22.7827 7.50741 22.5317 8.09216 22.738 8.60769C22.8169 8.80481 22.8907 9.00714 22.9574 9.20888Z" fill="black"/>
|
||||
<path d="M18.791 21.2451C18.6137 21.3621 18.4307 21.4754 18.2464 21.5815C17.7655 21.8589 17.6008 22.4737 17.8781 22.9544C17.9533 23.0851 18.0536 23.192 18.1691 23.2737C18.4791 23.4918 18.9002 23.5245 19.2507 23.3226C19.4699 23.1962 19.6878 23.0617 19.899 22.9221C20.3619 22.6162 20.4893 21.9927 20.1833 21.5296C19.8774 21.0663 19.2541 20.939 18.791 21.2451Z" fill="black"/>
|
||||
<path d="M25.4904 12.0161C25.4686 11.4614 25.0013 11.0297 24.4465 11.0513C23.8923 11.0732 23.4602 11.5406 23.482 12.0951C23.4903 12.3071 23.4925 12.5222 23.4876 12.734C23.4798 13.0819 23.6499 13.392 23.9143 13.5784C24.0718 13.6893 24.263 13.7564 24.4703 13.7611C25.025 13.7734 25.4847 13.3335 25.497 12.7785C25.5025 12.5254 25.5004 12.269 25.4904 12.0161Z" fill="black"/>
|
||||
<path d="M22.7934 18.6011C22.3486 18.2673 21.7193 18.3579 21.3862 18.8019C21.2586 18.972 21.1243 19.1399 20.9867 19.3016C20.6272 19.724 20.678 20.3585 21.1004 20.7183C21.1244 20.7387 21.1488 20.7574 21.174 20.7751C21.594 21.0711 22.1776 21.0031 22.5171 20.6047C22.6814 20.4117 22.8415 20.2111 22.994 20.008C23.3272 19.564 23.237 18.9343 22.7934 18.6011Z" fill="black"/>
|
||||
<path d="M24.2707 14.9682C23.741 14.8021 23.177 15.0969 23.0111 15.6265C22.9476 15.8289 22.8772 16.0322 22.8012 16.2313C22.6343 16.6696 22.7942 17.1519 23.1607 17.4103C23.2279 17.4575 23.302 17.4976 23.3824 17.528C23.901 17.7259 24.4816 17.4657 24.6793 16.9469C24.7695 16.7102 24.8533 16.4683 24.929 16.2278C25.0948 15.6981 24.8002 15.1342 24.2707 14.9682Z" fill="black"/>
|
||||
<path d="M11.1405 22.8243C10.242 22.663 9.38004 22.3883 8.56271 22.0051C8.55303 22 8.54438 21.9943 8.53422 21.9897C8.34162 21.899 8.14933 21.8019 7.96296 21.7004C7.96232 21.6997 7.96113 21.6992 7.96011 21.6988C7.61816 21.5105 7.28444 21.3021 6.96022 21.0739C2.23257 17.7436 1.09585 11.1879 4.42636 6.46031C5.15057 5.43269 6.02696 4.57537 7.00402 3.89587C7.01606 3.88749 7.02809 3.87916 7.04002 3.87072C10.483 1.49841 15.158 1.33853 18.814 3.7763L18.0288 4.91082C17.8105 5.22659 17.9448 5.45671 18.3269 5.42232L21.7376 5.11696C22.1203 5.08257 22.3491 4.75158 22.2462 4.38206L21.3303 1.08208C21.2278 0.712132 20.9652 0.66785 20.7467 0.983575L19.9597 2.12078C17.2768 0.319774 14.0588 -0.366975 10.8649 0.186874C10.5432 0.242549 10.226 0.310691 9.9132 0.390012C9.91078 0.390442 9.90885 0.390711 9.90691 0.391141C9.89482 0.394097 9.88257 0.39802 9.8708 0.401298C7.1166 1.10858 4.7136 2.71493 2.99891 5.00685C2.98445 5.02399 2.96957 5.04076 2.95592 5.05941C2.8989 5.1362 2.84231 5.21477 2.7869 5.29334C2.6963 5.4221 2.60698 5.55409 2.52153 5.68607C2.51084 5.70198 2.50267 5.71816 2.49332 5.73423C1.07833 7.92689 0.395831 10.4618 0.512877 13.0425C0.513146 13.051 0.512662 13.0596 0.512877 13.0683C0.524217 13.3204 0.544208 13.576 0.571347 13.8276C0.572798 13.8438 0.576398 13.8592 0.579139 13.8754C0.607192 14.1284 0.642392 14.382 0.686513 14.6356C1.13492 17.2225 2.35526 19.5504 4.18388 21.3617C4.18813 21.366 4.19254 21.3706 4.19683 21.375C4.19834 21.3767 4.20001 21.3775 4.20146 21.3791C4.69275 21.8637 5.22715 22.3118 5.80254 22.7171C7.30835 23.7782 8.9851 24.4795 10.7858 24.8027C11.3322 24.9008 11.8541 24.5371 11.9522 23.991C12.0501 23.4445 11.6867 22.9222 11.1405 22.8243Z" fill="black"/>
|
||||
<path d="M12.3833 4.38037C11.9339 4.38037 11.5698 4.74473 11.5698 5.19352V13.2947L18.979 17.1249C19.0983 17.1866 19.2259 17.2157 19.3516 17.2157C19.6459 17.2157 19.9301 17.0554 20.0746 16.7758C20.2807 16.3767 20.1248 15.8865 19.7257 15.6804L13.1958 12.3045V5.19352C13.1958 4.74473 12.8322 4.38037 12.3833 4.38037Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
12
assets/icons/schedule_celender_icon.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg width="26" height="25" viewBox="0 0 26 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.0488 11.1084H14.2695C14.674 11.1084 15.002 10.7805 15.002 10.376C15.002 9.97148 14.674 9.64355 14.2695 9.64355H13.0488C12.6443 9.64355 12.3164 9.97148 12.3164 10.376C12.3164 10.7805 12.6443 11.1084 13.0488 11.1084Z" fill="black"/>
|
||||
<path d="M9.92383 9.64355H8.70312C8.29863 9.64355 7.9707 9.97148 7.9707 10.376C7.9707 10.7805 8.29863 11.1084 8.70312 11.1084H9.92383C10.3283 11.1084 10.6562 10.7805 10.6562 10.376C10.6562 9.97148 10.3283 9.64355 9.92383 9.64355Z" fill="black"/>
|
||||
<path d="M17.3945 11.1084H18.6152C19.0197 11.1084 19.3477 10.7805 19.3477 10.376C19.3477 9.97148 19.0197 9.64355 18.6152 9.64355H17.3945C16.99 9.64355 16.6621 9.97148 16.6621 10.376C16.6621 10.7805 16.99 11.1084 17.3945 11.1084Z" fill="black"/>
|
||||
<path d="M5.57812 12.9395H4.35742C3.95293 12.9395 3.625 13.2674 3.625 13.6719C3.625 14.0764 3.95293 14.4043 4.35742 14.4043H5.57812C5.98262 14.4043 6.31055 14.0764 6.31055 13.6719C6.31055 13.2674 5.98262 12.9395 5.57812 12.9395Z" fill="black"/>
|
||||
<path d="M9.92383 12.9395H8.70312C8.29863 12.9395 7.9707 13.2674 7.9707 13.6719C7.9707 14.0764 8.29863 14.4043 8.70312 14.4043H9.92383C10.3283 14.4043 10.6562 14.0764 10.6562 13.6719C10.6562 13.2674 10.3283 12.9395 9.92383 12.9395Z" fill="black"/>
|
||||
<path d="M15.002 13.6719C15.002 13.2674 14.674 12.9395 14.2695 12.9395H13.0488C12.6443 12.9395 12.3164 13.2674 12.3164 13.6719C12.3164 14.0764 12.6443 14.4043 13.0488 14.4043H14.2695C14.674 14.4043 15.002 14.0764 15.002 13.6719Z" fill="black"/>
|
||||
<path d="M5.57812 16.2354H4.35742C3.95293 16.2354 3.625 16.5633 3.625 16.9678C3.625 17.3723 3.95293 17.7002 4.35742 17.7002H5.57812C5.98262 17.7002 6.31055 17.3723 6.31055 16.9678C6.31055 16.5633 5.98262 16.2354 5.57812 16.2354Z" fill="black"/>
|
||||
<path d="M9.92383 16.2354H8.70312C8.29863 16.2354 7.9707 16.5633 7.9707 16.9678C7.9707 17.3723 8.29863 17.7002 8.70312 17.7002H9.92383C10.3283 17.7002 10.6562 17.3723 10.6562 16.9678C10.6562 16.5633 10.3283 16.2354 9.92383 16.2354Z" fill="black"/>
|
||||
<path d="M22.4727 13.6268V4.15039C22.4727 2.66958 21.2679 1.46484 19.7871 1.46484H18.3711V0.732422C18.3711 0.32793 18.0432 0 17.6387 0C17.2342 0 16.9062 0.32793 16.9062 0.732422V1.46484H14.2695V0.732422C14.2695 0.32793 13.9416 0 13.5371 0C13.1326 0 12.8047 0.32793 12.8047 0.732422V1.46484H10.168V0.732422C10.168 0.32793 9.84004 0 9.43555 0C9.03105 0 8.70312 0.32793 8.70312 0.732422V1.46484H6.06641V0.732422C6.06641 0.32793 5.73848 0 5.33398 0C4.92949 0 4.60156 0.32793 4.60156 0.732422V1.46484H3.18555C1.70474 1.46484 0.5 2.66958 0.5 4.15039V18.7988C0.5 20.0104 1.48569 20.9961 2.69727 20.9961H13.6651C14.523 23.3303 16.7684 25 19.3965 25C22.762 25 25.5 22.262 25.5 18.8965C25.5 16.6521 24.2821 14.6871 22.4727 13.6268ZM1.96484 4.15039C1.96484 3.47729 2.51245 2.92969 3.18555 2.92969H4.60156V3.66211C4.60156 4.0666 4.92949 4.39453 5.33398 4.39453C5.73848 4.39453 6.06641 4.0666 6.06641 3.66211V2.92969H8.70312V3.66211C8.70312 4.0666 9.03105 4.39453 9.43555 4.39453C9.84004 4.39453 10.168 4.0666 10.168 3.66211V2.92969H12.8047V3.66211C12.8047 4.0666 13.1326 4.39453 13.5371 4.39453C13.9416 4.39453 14.2695 4.0666 14.2695 3.66211V2.92969H16.9062V3.66211C16.9062 4.0666 17.2342 4.39453 17.6387 4.39453C18.0432 4.39453 18.3711 4.0666 18.3711 3.66211V2.92969H19.7871C20.4602 2.92969 21.0078 3.47729 21.0078 4.15039V6.34766H1.96484V4.15039ZM2.69727 19.5312C2.29341 19.5312 1.96484 19.2027 1.96484 18.7988V7.8125H21.0078V13.0093C20.4943 12.8686 19.9541 12.793 19.3965 12.793C16.031 12.793 13.293 15.531 13.293 18.8965C13.293 19.1108 13.3042 19.3226 13.3259 19.5312H2.69727ZM19.3965 23.5352C16.8387 23.5352 14.7578 21.4542 14.7578 18.8965C14.7578 16.3387 16.8387 14.2578 19.3965 14.2578C21.9542 14.2578 24.0352 16.3387 24.0352 18.8965C24.0352 21.4542 21.9542 23.5352 19.3965 23.5352Z" fill="black"/>
|
||||
<path d="M21.8379 18.1641H20.1289V16.4551C20.1289 16.0506 19.801 15.7227 19.3965 15.7227C18.992 15.7227 18.6641 16.0506 18.6641 16.4551V18.8965C18.6641 19.301 18.992 19.6289 19.3965 19.6289H21.8379C22.2424 19.6289 22.5703 19.301 22.5703 18.8965C22.5703 18.492 22.2424 18.1641 21.8379 18.1641Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
4
assets/icons/schedule_circulate_icon.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="26" height="21" viewBox="0 0 26 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.0448 15.9465L20.2012 13.7273C19.4253 13.2794 18.4517 13.84 18.4517 14.7374V16.0844H7.87586C4.77052 16.0844 2.24415 13.558 2.24415 10.4526C2.24415 9.971 1.85367 9.58057 1.37207 9.58057C0.890431 9.58057 0.5 9.97105 0.5 10.4526C0.5 14.5197 3.80885 17.8285 7.87591 17.8285H18.4517V19.1756C18.4517 20.0714 19.424 20.6344 20.2012 20.1856L24.0448 17.9665C24.8207 17.5187 24.822 16.3952 24.0448 15.9465Z" fill="black"/>
|
||||
<path d="M18.1241 2.5148H7.54828V1.16772C7.54828 0.271867 6.57596 -0.291075 5.79881 0.157658L1.95519 2.37676C1.17936 2.82466 1.17799 3.94815 1.95519 4.39688L5.79881 6.61603C6.57469 7.06398 7.54828 6.50329 7.54828 5.60597V4.25894H18.1241C21.2295 4.25894 23.7559 6.78527 23.7559 9.89065C23.7559 10.3723 24.1463 10.7627 24.6279 10.7627C25.1096 10.7627 25.5 10.3722 25.5 9.89065C25.5001 5.8236 22.1912 2.5148 18.1241 2.5148Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 965 B |
4
assets/icons/schedule_time_icon.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="26" height="25" viewBox="0 0 26 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22.909 4.88394C20.8746 2.23694 17.9317 0.540767 14.6212 0.107633C11.3435 -0.321144 8.0947 0.540068 5.46148 2.53196L4.50937 1.5785C4.2377 1.30651 3.987 1.39746 3.95226 1.77993L3.63971 5.19304C3.60475 5.57551 3.88922 5.86057 4.27201 5.82604L7.68523 5.51763C8.06802 5.48321 8.15914 5.2323 7.8873 4.96031L6.89959 3.97136C9.06784 2.41766 11.7024 1.75282 14.3602 2.10054C17.1384 2.46397 19.6082 3.88751 21.3154 6.10884C23.0224 8.33002 23.7621 11.0829 23.3987 13.8605C23.1404 15.8332 22.3478 17.6507 21.1144 19.1504C20.6111 19.762 20.0345 20.3209 19.3905 20.8156C17.1694 22.5228 14.4165 23.2627 11.6385 22.8992C8.86087 22.5358 6.39126 21.1122 4.68401 18.8912C3.02091 16.7274 2.2727 14.0427 2.57691 11.3316C2.63882 10.7799 2.24183 10.2824 1.68999 10.2207C1.13853 10.1586 0.641285 10.5558 0.579647 11.1074C0.216595 14.3382 1.10846 17.5376 3.09019 20.116C5.12456 22.7629 8.06781 24.4593 11.3779 24.8924C14.6878 25.3253 17.9682 24.4433 20.6156 22.409C21.3823 21.82 22.0698 21.1538 22.6695 20.4247C24.1397 18.638 25.0842 16.4726 25.3919 14.1216C25.8249 10.8114 24.9432 7.53077 22.909 4.88394Z" fill="black"/>
|
||||
<path d="M12.5089 4.3645C12.0596 4.3645 11.6953 4.72874 11.6953 5.17801V13.2862L19.1104 17.1191C19.23 17.181 19.3577 17.2104 19.4833 17.2102C19.7781 17.2102 20.0624 17.0498 20.207 16.77C20.4135 16.3707 20.2571 15.8799 19.8579 15.6733L13.323 12.2949V5.17806C13.323 4.72879 12.9586 4.3645 12.5089 4.3645Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
22
assets/icons/water_heater_icon.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<svg width="27" height="40" viewBox="0 0 27 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.7445 35.1952C10.4209 35.1952 10.1586 35.4576 10.1586 35.7812V37.2605C10.1586 38.1249 9.45534 38.8282 8.59099 38.8282H7.12205C6.79847 38.8282 6.53613 39.0905 6.53613 39.4141C6.53613 39.7377 6.79847 40 7.12205 40H8.59099C10.1015 40 11.3304 38.7711 11.3304 37.2605V35.7812C11.3304 35.4576 11.0681 35.1952 10.7445 35.1952Z" fill="#72BBFF"/>
|
||||
<path d="M11.7906 32.7314H9.69835C9.37476 32.7314 9.11243 32.9937 9.11243 33.3173V34.7541C9.11243 35.6541 9.84459 36.3862 10.7445 36.3862C11.6444 36.3862 12.3765 35.654 12.3765 34.7541V33.3173C12.3765 32.9937 12.1142 32.7314 11.7906 32.7314Z" fill="#6B717D"/>
|
||||
<path d="M16.0857 35.1952C16.4093 35.1952 16.6716 35.4576 16.6716 35.7812V37.2605C16.6716 38.1249 17.3749 38.8282 18.2392 38.8282H19.7081C20.0317 38.8282 20.2941 39.0905 20.2941 39.4141C20.2941 39.7377 20.0317 40 19.7081 40H18.2392C16.7287 40 15.4998 38.7711 15.4998 37.2605V35.7812C15.4998 35.4576 15.7621 35.1952 16.0857 35.1952Z" fill="#FF6C6C"/>
|
||||
<path d="M15.0395 32.7314H17.1318C17.4554 32.7314 17.7177 32.9937 17.7177 33.3173V34.7541C17.7177 35.6541 16.9856 36.3862 16.0857 36.3862C15.1858 36.3862 14.4536 35.654 14.4536 34.7541V33.3173C14.4536 32.9937 14.7159 32.7314 15.0395 32.7314Z" fill="#6B717D"/>
|
||||
<path d="M2.38438 3.6581H0.585919C0.262336 3.6581 0 3.92043 0 4.24402C0 4.5676 0.262336 4.82993 0.585919 4.82993H2.38438C2.70796 4.82993 2.9703 4.5676 2.9703 4.24402C2.9703 3.92043 2.70796 3.6581 2.38438 3.6581Z" fill="#6B717D"/>
|
||||
<path d="M2.38438 6.3924H0.585919C0.262336 6.3924 0 6.65473 0 6.97831C0 7.3019 0.262336 7.56423 0.585919 7.56423H2.38438C2.70796 7.56423 2.9703 7.3019 2.9703 6.97831C2.9703 6.65473 2.70796 6.3924 2.38438 6.3924Z" fill="#6B717D"/>
|
||||
<path d="M26.2441 19.7208H24.4456C24.122 19.7208 23.8597 19.9831 23.8597 20.3067C23.8597 20.6303 24.122 20.8926 24.4456 20.8926H26.2441C26.5676 20.8926 26.83 20.6303 26.83 20.3067C26.83 19.9831 26.5676 19.7208 26.2441 19.7208Z" fill="#6B717D"/>
|
||||
<path d="M21.766 30.5576V33.2958C21.766 33.6193 21.5035 33.8818 21.1801 33.8818H5.65013C5.3267 33.8818 5.06421 33.6193 5.06421 33.2958V30.5576C5.06421 30.2342 5.3267 29.9717 5.65013 29.9717H21.1801C21.5035 29.9717 21.766 30.2342 21.766 30.5576Z" fill="#D6EAEC"/>
|
||||
<path d="M21.766 30.5576V33.2958C21.766 33.6193 21.5035 33.8818 21.18 33.8818H18.8364C19.1598 33.8818 19.4223 33.6193 19.4223 33.2958V30.5576C19.4223 30.2342 19.1598 29.9717 18.8364 29.9717H21.18C21.5035 29.9717 21.766 30.2342 21.766 30.5576Z" fill="#B5D9DD"/>
|
||||
<path d="M25.0315 1.84682V24.8047L22.6878 25.4437L13.4146 27.9741L1.79858 24.8047V1.84682C1.79858 0.828099 2.62668 0 3.6454 0H23.1846C24.2026 0 25.0315 0.828099 25.0315 1.84682Z" fill="#D6EAEC"/>
|
||||
<path d="M25.0314 1.84682V24.8047L22.6878 25.4437V1.84682C22.6878 0.828099 21.8589 0 20.8409 0H23.1846C24.2026 0 25.0314 0.828099 25.0314 1.84682Z" fill="#B5D9DD"/>
|
||||
<path d="M25.0315 24.8047V29.2967C25.0315 30.3155 24.2026 31.1436 23.1846 31.1436H3.6454C2.62668 31.1436 1.79858 30.3155 1.79858 29.2967V24.8047H25.0315Z" fill="#6B717D"/>
|
||||
<path d="M25.0314 24.8047V29.2967C25.0314 30.3155 24.2026 31.1436 23.1846 31.1436H20.8409C21.8589 31.1436 22.6878 30.3155 22.6878 29.2967V24.8047H25.0314Z" fill="#47505E"/>
|
||||
<path d="M13.8105 15.476C13.5866 15.2712 13.2434 15.2712 13.0195 15.476C12.9301 15.5578 10.8306 17.5023 10.8306 19.5649C10.8306 20.99 11.9899 22.1494 13.415 22.1494C14.8401 22.1494 15.9995 20.99 15.9995 19.5649C15.9994 17.5023 13.8998 15.5578 13.8105 15.476Z" fill="#72BBFF"/>
|
||||
<path d="M17.952 9.8444C18.9889 7.34275 17.8015 4.47417 15.2999 3.43723C12.7983 2.4003 9.92967 3.58768 8.89274 6.08932C7.8558 8.59096 9.04318 11.4595 11.5448 12.4965C14.0465 13.5334 16.915 12.346 17.952 9.8444Z" fill="#B5D9DD"/>
|
||||
<path d="M16.3638 7.96677C16.3638 10.0237 15.4716 11.6971 13.4147 11.6971C13.1053 11.6971 12.8045 11.6588 12.5163 11.587C10.8921 11.1846 9.68433 9.71437 9.68433 7.96677C9.68433 6.21917 10.8921 4.7489 12.5163 4.34657C12.8045 4.2747 13.1053 4.23642 13.4147 4.23642C15.4716 4.23642 16.3638 5.9098 16.3638 7.96677Z" fill="white"/>
|
||||
<path d="M17.1451 7.96677C17.1451 10.0237 15.4717 11.6971 13.4147 11.6971C13.1053 11.6971 12.8046 11.6588 12.5163 11.587C14.1405 11.1846 15.3482 9.71437 15.3482 7.96677C15.3482 6.21917 14.1405 4.7489 12.5163 4.34657C12.8046 4.2747 13.1053 4.23642 13.4147 4.23642C15.4717 4.23642 17.1451 5.9098 17.1451 7.96677Z" fill="#D6EAEC"/>
|
||||
<path d="M13.8294 7.55251C13.6005 7.3236 13.2295 7.32368 13.0008 7.55251L11.7521 8.80126C11.5233 9.03009 11.5233 9.4011 11.7521 9.62985C11.8665 9.74423 12.0165 9.80149 12.1664 9.80149C12.3163 9.80149 12.4663 9.74431 12.5807 9.62985L13.8294 8.3811C14.0582 8.15228 14.0582 7.78126 13.8294 7.55251Z" fill="#FF6C6C"/>
|
||||
<path d="M6.17188 28.5601C6.49548 28.5601 6.75781 28.2977 6.75781 27.9741C6.75781 27.6505 6.49548 27.3882 6.17188 27.3882C5.84827 27.3882 5.58594 27.6505 5.58594 27.9741C5.58594 28.2977 5.84827 28.5601 6.17188 28.5601Z" fill="#47505E"/>
|
||||
<path d="M20.6581 28.5601C20.9817 28.5601 21.2441 28.2977 21.2441 27.9741C21.2441 27.6505 20.9817 27.3882 20.6581 27.3882C20.3345 27.3882 20.0722 27.6505 20.0722 27.9741C20.0722 28.2977 20.3345 28.5601 20.6581 28.5601Z" fill="#47505E"/>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
29
assets/icons/water_heater_off.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<svg width="280" height="290" viewBox="0 0 280 290" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_3818_711)">
|
||||
<rect x="20" y="20" width="250" height="250" rx="100" fill="#EDEDED"/>
|
||||
<circle cx="128.778" cy="183.972" r="2.77778" stroke="white" stroke-width="3"/>
|
||||
<circle cx="144.778" cy="183.972" r="2.77778" stroke="white" stroke-width="3"/>
|
||||
<circle cx="160.778" cy="183.972" r="2.77778" stroke="white" stroke-width="3"/>
|
||||
<rect x="121" y="149" width="46.5278" height="26.3889" rx="5" stroke="white" stroke-width="3"/>
|
||||
<path d="M134.184 160.41H134.135C135.619 160.41 136.807 160.833 137.699 161.679C138.598 162.532 139.047 163.697 139.047 165.175C139.047 166.64 138.559 167.831 137.582 168.749C136.605 169.667 135.316 170.126 133.715 170.126C132.953 170.126 132.25 170.019 131.605 169.804C130.967 169.589 130.45 169.329 130.053 169.023C129.675 168.73 129.34 168.427 129.047 168.115C128.76 167.809 128.565 167.551 128.461 167.343L128.275 167.021L129.574 165.839C129.6 165.911 129.649 165.999 129.721 166.103C129.773 166.181 129.926 166.37 130.18 166.669C130.427 166.956 130.684 167.197 130.951 167.392C131.225 167.587 131.605 167.776 132.094 167.958C132.576 168.134 133.09 168.222 133.637 168.222C134.62 168.222 135.421 167.932 136.039 167.353C136.658 166.773 136.967 166.015 136.967 165.078C136.967 164.134 136.654 163.395 136.029 162.861C135.398 162.32 134.542 162.05 133.461 162.05C132.348 162.05 131.212 162.379 130.053 163.036L128.998 162.275L129.994 155.195H137.895V157.031H131.732L131.137 161.035C131.996 160.618 133.012 160.41 134.184 160.41ZM147.387 170.097H147.367C145.466 170.097 143.943 169.384 142.797 167.958C141.658 166.539 141.088 164.719 141.088 162.499C141.088 160.312 141.661 158.509 142.807 157.089C143.952 155.67 145.476 154.96 147.377 154.96C149.258 154.96 150.762 155.673 151.889 157.099C153.015 158.531 153.578 160.331 153.578 162.499C153.578 164.719 153.018 166.539 151.898 167.958C150.779 169.384 149.275 170.097 147.387 170.097ZM147.367 168.134C148.565 168.134 149.545 167.613 150.307 166.572C151.068 165.53 151.449 164.182 151.449 162.529C151.449 160.875 151.068 159.527 150.307 158.486C149.545 157.444 148.565 156.923 147.367 156.923C146.143 156.923 145.147 157.444 144.379 158.486C143.604 159.534 143.217 160.882 143.217 162.529C143.217 164.176 143.604 165.523 144.379 166.572C145.147 167.613 146.143 168.134 147.367 168.134Z" fill="white"/>
|
||||
<path d="M162.557 158.212L162.572 158.227C162.311 158.865 161.882 159.376 161.283 159.76C160.68 160.147 159.953 160.341 159.1 160.341C157.977 160.341 157.043 159.981 156.297 159.262C155.555 158.546 155.184 157.639 155.184 156.542C155.184 155.461 155.555 154.563 156.297 153.847C157.043 153.127 157.974 152.768 159.09 152.768C159.943 152.768 160.667 152.963 161.263 153.354C161.862 153.744 162.29 154.252 162.547 154.877L161.087 155.468C160.902 155.103 160.638 154.807 160.296 154.579C159.951 154.348 159.551 154.233 159.095 154.233C158.444 154.233 157.896 154.452 157.45 154.892C157.007 155.331 156.786 155.88 156.786 156.537C156.786 157.188 157.009 157.74 157.455 158.193C157.897 158.642 158.444 158.866 159.095 158.866C159.577 158.866 159.992 158.748 160.34 158.51C160.692 158.272 160.941 157.974 161.087 157.616L162.557 158.212Z" fill="white"/>
|
||||
<mask id="path-8-inside-1_3818_711" fill="white">
|
||||
<path d="M200.929 217.62C200.929 217.247 200.627 216.945 200.254 216.945C199.882 216.945 199.58 217.247 199.58 217.62C199.58 220.615 197.143 223.051 194.149 223.051C193.776 223.051 193.474 223.353 193.474 223.726C193.474 224.098 193.776 224.4 194.149 224.4C197.887 224.4 200.929 221.358 200.929 217.62Z"/>
|
||||
</mask>
|
||||
<path d="M194.149 224.4L194.149 222.4H194.149V224.4ZM202.929 217.62C202.929 216.143 201.731 214.945 200.254 214.945V218.945C199.522 218.945 198.929 218.352 198.929 217.62H202.929ZM200.254 214.945C198.777 214.945 197.58 216.143 197.58 217.62H201.58C201.58 218.352 200.986 218.945 200.254 218.945V214.945ZM197.58 217.62C197.58 219.51 196.039 221.051 194.149 221.051V225.051C198.248 225.051 201.58 221.719 201.58 217.62H197.58ZM194.149 221.051C192.672 221.051 191.474 222.248 191.474 223.726H195.474C195.474 224.458 194.88 225.051 194.149 225.051V221.051ZM191.474 223.726C191.474 225.203 192.672 226.4 194.149 226.4V222.4C194.88 222.4 195.474 222.993 195.474 223.726H191.474ZM194.149 226.4C198.992 226.4 202.929 222.463 202.929 217.62H198.929C198.929 220.254 196.783 222.4 194.149 222.4L194.149 226.4Z" fill="white" mask="url(#path-8-inside-1_3818_711)"/>
|
||||
<path d="M190.083 206.168L189.798 205.966L190.613 206.545L190.348 206.356L190.348 206.356L190.151 206.217L190.083 206.168ZM190.083 206.168C190.083 206.168 190.083 206.168 190.083 206.168L190.083 206.168ZM194.277 198.891L194.148 198.867L194.542 198.795L195.096 200.467C196.016 203.237 197.822 205.667 199.648 208.124C199.86 208.41 200.073 208.696 200.285 208.983C202.24 211.636 204.18 214.462 204.18 217.62C204.18 217.62 204.18 217.62 204.18 217.62C204.179 223.152 199.68 227.651 194.148 227.651C188.616 227.651 184.117 223.152 184.117 217.62C184.117 217.62 184.117 217.62 184.117 217.62C184.117 214.413 186.117 211.539 188.212 208.711C188.212 208.711 188.212 208.711 188.212 208.711L194.277 198.891ZM194.147 198.867L194.277 198.891C194.276 198.893 194.273 198.904 194.263 198.921C194.251 198.94 194.235 198.958 194.217 198.972C194.183 198.998 194.157 199 194.148 199C194.14 199 194.114 198.998 194.08 198.972C194.062 198.958 194.046 198.94 194.034 198.921C194.024 198.904 194.02 198.893 194.02 198.891L194.147 198.867ZM194.02 198.891C194.02 198.89 194.02 198.89 194.02 198.89C194.02 198.89 194.02 198.89 194.02 198.891L194.02 198.891Z" stroke="white" stroke-width="2"/>
|
||||
<path d="M194.306 183.891V69.3055C194.306 67.3878 192.751 65.8333 190.833 65.8333H95.0001C93.0824 65.8333 91.5278 67.3878 91.5278 69.3055V215.139C91.5278 217.056 93.0824 218.611 95.0001 218.611H166.438M223.472 212.708C223.472 228.625 210.569 241.528 194.653 241.528C178.736 241.528 165.833 228.625 165.833 212.708C165.833 196.792 178.736 183.889 194.653 183.889C210.569 183.889 223.472 196.792 223.472 212.708Z" stroke="white" stroke-width="3"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3818_711" x="0" y="0" width="290" height="290" 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/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<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.35 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3818_711"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3818_711" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 6.6 KiB |
29
assets/icons/water_heater_on.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<svg width="290" height="290" viewBox="0 0 290 290" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_3800_1033)">
|
||||
<rect x="20" y="20" width="250" height="250" rx="100" fill="#EDEDED"/>
|
||||
<circle cx="128.778" cy="183.972" r="2.77778" stroke="#023DFE" stroke-opacity="0.6" stroke-width="3"/>
|
||||
<circle cx="144.778" cy="183.972" r="2.77778" stroke="#023DFE" stroke-opacity="0.6" stroke-width="3"/>
|
||||
<circle cx="160.778" cy="183.972" r="2.77778" stroke="#023DFE" stroke-opacity="0.6" stroke-width="3"/>
|
||||
<rect x="121" y="149" width="46.5278" height="26.3889" rx="5" stroke="#023DFE" stroke-opacity="0.6" stroke-width="3"/>
|
||||
<path d="M134.184 160.409H134.135C135.619 160.409 136.807 160.833 137.699 161.679C138.598 162.532 139.047 163.697 139.047 165.175C139.047 166.64 138.559 167.831 137.582 168.749C136.605 169.667 135.316 170.126 133.715 170.126C132.953 170.126 132.25 170.019 131.605 169.804C130.967 169.589 130.45 169.329 130.053 169.023C129.675 168.73 129.34 168.427 129.047 168.115C128.76 167.809 128.565 167.551 128.461 167.343L128.275 167.021L129.574 165.839C129.6 165.911 129.649 165.999 129.721 166.103C129.773 166.181 129.926 166.37 130.18 166.669C130.427 166.956 130.684 167.197 130.951 167.392C131.225 167.587 131.605 167.776 132.094 167.958C132.576 168.134 133.09 168.222 133.637 168.222C134.62 168.222 135.421 167.932 136.039 167.353C136.658 166.773 136.967 166.015 136.967 165.077C136.967 164.133 136.654 163.395 136.029 162.861C135.398 162.32 134.542 162.05 133.461 162.05C132.348 162.05 131.212 162.379 130.053 163.036L128.998 162.275L129.994 155.195H137.895V157.031H131.732L131.137 161.034C131.996 160.618 133.012 160.409 134.184 160.409ZM147.387 170.097H147.367C145.466 170.097 143.943 169.384 142.797 167.958C141.658 166.539 141.088 164.719 141.088 162.499C141.088 160.312 141.661 158.508 142.807 157.089C143.952 155.67 145.476 154.96 147.377 154.96C149.258 154.96 150.762 155.673 151.889 157.099C153.015 158.531 153.578 160.331 153.578 162.499C153.578 164.719 153.018 166.539 151.898 167.958C150.779 169.384 149.275 170.097 147.387 170.097ZM147.367 168.134C148.565 168.134 149.545 167.613 150.307 166.572C151.068 165.53 151.449 164.182 151.449 162.529C151.449 160.875 151.068 159.527 150.307 158.486C149.545 157.444 148.565 156.923 147.367 156.923C146.143 156.923 145.147 157.444 144.379 158.486C143.604 159.534 143.217 160.881 143.217 162.529C143.217 164.176 143.604 165.523 144.379 166.572C145.147 167.613 146.143 168.134 147.367 168.134Z" fill="#023DFE" fill-opacity="0.6"/>
|
||||
<path d="M162.557 158.212L162.572 158.227C162.311 158.865 161.882 159.376 161.283 159.76C160.68 160.147 159.953 160.341 159.1 160.341C157.977 160.341 157.043 159.981 156.297 159.262C155.555 158.546 155.184 157.639 155.184 156.542C155.184 155.461 155.555 154.563 156.297 153.847C157.043 153.127 157.974 152.768 159.09 152.768C159.943 152.768 160.667 152.963 161.263 153.354C161.862 153.744 162.29 154.252 162.547 154.877L161.087 155.468C160.902 155.103 160.638 154.807 160.296 154.579C159.951 154.348 159.551 154.232 159.095 154.232C158.444 154.232 157.896 154.452 157.45 154.892C157.007 155.331 156.786 155.88 156.786 156.537C156.786 157.188 157.009 157.74 157.455 158.192C157.897 158.642 158.444 158.866 159.095 158.866C159.577 158.866 159.992 158.747 160.34 158.51C160.692 158.272 160.941 157.974 161.087 157.616L162.557 158.212Z" fill="#023DFE" fill-opacity="0.6"/>
|
||||
<mask id="path-8-inside-1_3800_1033" fill="white">
|
||||
<path d="M200.929 217.62C200.929 217.247 200.627 216.945 200.254 216.945C199.882 216.945 199.58 217.247 199.58 217.62C199.58 220.615 197.143 223.051 194.149 223.051C193.776 223.051 193.474 223.353 193.474 223.726C193.474 224.098 193.776 224.4 194.149 224.4C197.887 224.4 200.929 221.358 200.929 217.62Z"/>
|
||||
</mask>
|
||||
<path d="M194.149 224.4L194.149 222.4H194.149V224.4ZM202.929 217.62C202.929 216.143 201.731 214.945 200.254 214.945V218.945C199.522 218.945 198.929 218.352 198.929 217.62H202.929ZM200.254 214.945C198.777 214.945 197.58 216.143 197.58 217.62H201.58C201.58 218.352 200.986 218.945 200.254 218.945V214.945ZM197.58 217.62C197.58 219.51 196.039 221.051 194.149 221.051V225.051C198.248 225.051 201.58 221.719 201.58 217.62H197.58ZM194.149 221.051C192.672 221.051 191.474 222.248 191.474 223.726H195.474C195.474 224.458 194.88 225.051 194.149 225.051V221.051ZM191.474 223.726C191.474 225.203 192.672 226.4 194.149 226.4V222.4C194.88 222.4 195.474 222.993 195.474 223.726H191.474ZM194.149 226.4C198.992 226.4 202.929 222.463 202.929 217.62H198.929C198.929 220.254 196.783 222.4 194.149 222.4L194.149 226.4Z" fill="#023DFE" fill-opacity="0.6" mask="url(#path-8-inside-1_3800_1033)"/>
|
||||
<path d="M190.083 206.168L189.798 205.966L190.613 206.545L190.348 206.356L190.348 206.356L190.151 206.217L190.083 206.168ZM190.083 206.168C190.083 206.168 190.083 206.168 190.083 206.168L190.083 206.168ZM194.277 198.891L194.148 198.867L194.542 198.795L195.096 200.467C196.016 203.237 197.822 205.667 199.648 208.124C199.86 208.41 200.073 208.696 200.285 208.983C202.24 211.636 204.18 214.462 204.18 217.62C204.18 217.62 204.18 217.62 204.18 217.62C204.179 223.152 199.68 227.651 194.148 227.651C188.616 227.651 184.117 223.152 184.117 217.62C184.117 217.62 184.117 217.62 184.117 217.62C184.117 214.413 186.117 211.539 188.212 208.711C188.212 208.711 188.212 208.711 188.212 208.711L194.277 198.891ZM194.147 198.867L194.277 198.891C194.276 198.893 194.273 198.904 194.263 198.921C194.251 198.94 194.235 198.958 194.217 198.972C194.183 198.998 194.157 199 194.148 199C194.14 199 194.114 198.998 194.08 198.972C194.062 198.958 194.046 198.94 194.034 198.921C194.024 198.904 194.02 198.893 194.02 198.891L194.147 198.867ZM194.02 198.891C194.02 198.89 194.02 198.89 194.02 198.89C194.02 198.89 194.02 198.89 194.02 198.891L194.02 198.891Z" stroke="#023DFE" stroke-opacity="0.6" stroke-width="2"/>
|
||||
<path d="M194.306 183.891V69.3055C194.306 67.3878 192.751 65.8333 190.833 65.8333H95.0001C93.0824 65.8333 91.5278 67.3878 91.5278 69.3055V215.139C91.5278 217.056 93.0824 218.611 95.0001 218.611H166.438M223.472 212.708C223.472 228.625 210.569 241.528 194.653 241.528C178.736 241.528 165.833 228.625 165.833 212.708C165.833 196.792 178.736 183.889 194.653 183.889C210.569 183.889 223.472 196.792 223.472 212.708Z" stroke="#023DFE" stroke-opacity="0.6" stroke-width="3"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3800_1033" x="0" y="0" width="290" height="290" 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/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<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.35 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3800_1033"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3800_1033" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 6.8 KiB |
@ -1 +1 @@
|
||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:android:bb6047adeeb80fb00c7e6d","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:ios:373a65cce55a3af40c7e6d","uploadDebugSymbols":true,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"test2-8a3d2","configurations":{"android":"1:427332280600:android:bb6047adeeb80fb00c7e6d","ios":"1:427332280600:ios:373a65cce55a3af40c7e6d","web":"1:427332280600:web:ad50516a87a35a1a0c7e6d"}}}}}}
|
||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"syncrow-staging","appId":"1:786692570726:android:0ef7079c2b978d4417b7a7","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"syncrow-staging","appId":"1:786692570726:ios:455a6fcff77e130f17b7a7","uploadDebugSymbols":true,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"syncrow-staging","configurations":{"android":"1:786692570726:android:0ef7079c2b978d4417b7a7","ios":"1:786692570726:ios:455a6fcff77e130f17b7a7","web":"1:786692570726:web:93c931e6701797b317b7a7"}}}}}}
|
@ -88,8 +88,6 @@ PODS:
|
||||
- PromisesSwift (~> 2.1)
|
||||
- FirebaseSharedSwift (10.29.0)
|
||||
- Flutter (1.0.0)
|
||||
- flutter_localization (0.0.1):
|
||||
- Flutter
|
||||
- flutter_secure_storage (6.0.0):
|
||||
- Flutter
|
||||
- GoogleAppMeasurement (10.25.0):
|
||||
@ -227,7 +225,6 @@ DEPENDENCIES:
|
||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||
- firebase_database (from `.symlinks/plugins/firebase_database/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_localization (from `.symlinks/plugins/flutter_localization/ios`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- onesignal_flutter (from `.symlinks/plugins/onesignal_flutter/ios`)
|
||||
@ -274,8 +271,6 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/firebase_database/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_localization:
|
||||
:path: ".symlinks/plugins/flutter_localization/ios"
|
||||
flutter_secure_storage:
|
||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||
image_picker_ios:
|
||||
@ -314,7 +309,6 @@ SPEC CHECKSUMS:
|
||||
FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
|
||||
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
flutter_localization: f43b18844a2b3d2c71fd64f04ffd6b1e64dd54d4
|
||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
GoogleAppMeasurement: 9abf64b682732fed36da827aa2a68f0221fd2356
|
||||
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
||||
|
@ -12,7 +12,6 @@
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
611C662010675536F855E5CA /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 490AAF90B8FBFCC5BA996845 /* Pods_RunnerTests.framework */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
8BB48ED4ACF8DB5A4F5DB78C /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 90790D9750E58AEFF7247821 /* GoogleService-Info.plist */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
@ -43,18 +42,23 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
01BAAF935356ECBDD35AF0DB /* Pods-RunnerTests.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug-prod.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug-prod.xcconfig"; sourceTree = "<group>"; };
|
||||
12AD49A621BEBB053FD06115 /* Pods-Runner.release-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-prod.xcconfig"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
1F99043C7AC9BDABD8A4D41A /* Pods-Runner.profile-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-dev.xcconfig"; sourceTree = "<group>"; };
|
||||
210827A693936E5201C5E75C /* Pods-RunnerTests.profile-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile-dev.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile-dev.xcconfig"; sourceTree = "<group>"; };
|
||||
238CAAD9FFF9A0C9ED3CFAB2 /* Pods-RunnerTests.profile-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile-prod.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile-prod.xcconfig"; sourceTree = "<group>"; };
|
||||
25B37F5982CD6994FABA2CC1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
444D77D28A8CDF32047CD0AF /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
490AAF90B8FBFCC5BA996845 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5DE3E6D1EADE3D3859FC1B69 /* Pods-Runner.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-dev.xcconfig"; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
90790D9750E58AEFF7247821 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
949637473C534E1F68B19CC0 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
@ -63,9 +67,15 @@
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9B82456986D7FA25420A224F /* Pods-Runner.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-prod.xcconfig"; sourceTree = "<group>"; };
|
||||
A3D4DF5D9888DAC25E2380AA /* Pods-RunnerTests.release-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release-dev.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release-dev.xcconfig"; sourceTree = "<group>"; };
|
||||
AAC9129FD50E64509AD1B9AF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
BFD4DDED98208034B60B5311 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C41134CD2FDFC1A2BDF49283 /* Pods-Runner.release-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release-dev.xcconfig"; sourceTree = "<group>"; };
|
||||
C5DBBF9417E4F8A9A08DFF02 /* Pods-RunnerTests.release-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release-prod.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release-prod.xcconfig"; sourceTree = "<group>"; };
|
||||
D0F6245A5BF345FCC425515C /* Pods-Runner.profile-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile-prod.xcconfig"; sourceTree = "<group>"; };
|
||||
DFB6BB492A265F2BF6FDC8C0 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
EE971EFEA60AEDFDB361D9A3 /* Pods-RunnerTests.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug-dev.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug-dev.xcconfig"; sourceTree = "<group>"; };
|
||||
F323D632CA976B68DDB0E669 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -98,6 +108,18 @@
|
||||
DFB6BB492A265F2BF6FDC8C0 /* Pods-RunnerTests.debug.xcconfig */,
|
||||
F323D632CA976B68DDB0E669 /* Pods-RunnerTests.release.xcconfig */,
|
||||
AAC9129FD50E64509AD1B9AF /* Pods-RunnerTests.profile.xcconfig */,
|
||||
9B82456986D7FA25420A224F /* Pods-Runner.debug-prod.xcconfig */,
|
||||
5DE3E6D1EADE3D3859FC1B69 /* Pods-Runner.debug-dev.xcconfig */,
|
||||
12AD49A621BEBB053FD06115 /* Pods-Runner.release-prod.xcconfig */,
|
||||
C41134CD2FDFC1A2BDF49283 /* Pods-Runner.release-dev.xcconfig */,
|
||||
D0F6245A5BF345FCC425515C /* Pods-Runner.profile-prod.xcconfig */,
|
||||
1F99043C7AC9BDABD8A4D41A /* Pods-Runner.profile-dev.xcconfig */,
|
||||
01BAAF935356ECBDD35AF0DB /* Pods-RunnerTests.debug-prod.xcconfig */,
|
||||
EE971EFEA60AEDFDB361D9A3 /* Pods-RunnerTests.debug-dev.xcconfig */,
|
||||
C5DBBF9417E4F8A9A08DFF02 /* Pods-RunnerTests.release-prod.xcconfig */,
|
||||
A3D4DF5D9888DAC25E2380AA /* Pods-RunnerTests.release-dev.xcconfig */,
|
||||
238CAAD9FFF9A0C9ED3CFAB2 /* Pods-RunnerTests.profile-prod.xcconfig */,
|
||||
210827A693936E5201C5E75C /* Pods-RunnerTests.profile-dev.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@ -139,7 +161,6 @@
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
2F70EB4341A83C900EB253DC /* Pods */,
|
||||
876D3217A8BBDAF41961161F /* Frameworks */,
|
||||
90790D9750E58AEFF7247821 /* GoogleService-Info.plist */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@ -195,14 +216,15 @@
|
||||
buildPhases = (
|
||||
3DC878D0674AA34AEC9695FB /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
B07E4A152C9B8EA4001F6910 /* copy GoogleService.plist file to the correct location */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
315A05630CF83C532DBBCBF2 /* [CP] Embed Pods Frameworks */,
|
||||
0D61909C49A20C9AA28568EA /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
|
||||
3724F7A126D8469D5B04D144 /* [CP] Copy Pods Resources */,
|
||||
4768286A3BADB12BBB8C6996 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -268,31 +290,12 @@
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
8BB48ED4ACF8DB5A4F5DB78C /* GoogleService-Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0D61909C49A20C9AA28568EA /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\n#!/bin/bash\nPATH=${PATH}:$FLUTTER_ROOT/bin:$HOME/.pub-cache/bin\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=$PODS_ROOT/FirebaseCrashlytics/upload-symbols --platform=ios --apple-project-path=${SRCROOT} --env-platform-name=${PLATFORM_NAME} --env-configuration=${CONFIGURATION} --env-project-dir=${PROJECT_DIR} --env-built-products-dir=${BUILT_PRODUCTS_DIR} --env-dwarf-dsym-folder-path=${DWARF_DSYM_FOLDER_PATH} --env-dwarf-dsym-file-name=${DWARF_DSYM_FILE_NAME} --env-infoplist-path=${INFOPLIST_PATH} --default-config=default\n";
|
||||
};
|
||||
315A05630CF83C532DBBCBF2 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@ -387,6 +390,24 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
4768286A3BADB12BBB8C6996 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\n#!/bin/bash\nPATH=${PATH}:$FLUTTER_ROOT/bin:$HOME/.pub-cache/bin\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=$PODS_ROOT/FirebaseCrashlytics/upload-symbols --platform=ios --apple-project-path=${SRCROOT} --env-platform-name=${PLATFORM_NAME} --env-configuration=${CONFIGURATION} --env-project-dir=${PROJECT_DIR} --env-built-products-dir=${BUILT_PRODUCTS_DIR} --env-dwarf-dsym-folder-path=${DWARF_DSYM_FOLDER_PATH} --env-dwarf-dsym-file-name=${DWARF_DSYM_FILE_NAME} --env-infoplist-path=${INFOPLIST_PATH} --default-config=default\n";
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
@ -402,6 +423,24 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
B07E4A152C9B8EA4001F6910 /* copy GoogleService.plist file to the correct location */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "copy GoogleService.plist file to the correct location";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Get a reference to the destination location for the GoogleService-Info.plist\n# This is the default location where Firebase init code expects to find GoogleServices-Info.plist file.\nPLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app\n# We have named our Build Configurations as Debug-dev, Debug-prod etc.\n# Here, dev and prod are the scheme names. This kind of naming is required by Flutter for flavors to work.\n# We are using the $CONFIGURATION variable available in the XCode build environment to get the build configuration.\nif [ \"${CONFIGURATION}\" == \"Debug-prod\" ] || [ \"${CONFIGURATION}\" == \"Release-prod\" ] || [ \"${CONFIGURATION}\" == \"Profile-prod\" ] || [ \"${CONFIGURATION}\" == \"Release\" ]; then\ncp \"${PROJECT_DIR}/config/prod/GoogleService-Info.plist\" \"${PLIST_DESTINATION}/GoogleService-Info.plist\"\necho \"Production plist copied\"\nelif [ \"${CONFIGURATION}\" == \"Debug-dev\" ] || [ \"${CONFIGURATION}\" == \"Release-dev\" ] || [ \"${CONFIGURATION}\" == \"Profile-dev\" ] || [ \"${CONFIGURATION}\" == \"Debug\" ]; then\ncp \"${PROJECT_DIR}/config/dev/GoogleService-Info.plist\" \"${PLIST_DESTINATION}/GoogleService-Info.plist\"\necho \"Development plist copied\"\nfi\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@ -452,7 +491,7 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
249021D3217E4FDB00AE95B9 /* Profile-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
@ -503,9 +542,9 @@
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
name = "Profile-prod";
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
249021D4217E4FDB00AE95B9 /* Profile-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
@ -532,11 +571,11 @@
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
name = "Profile-prod";
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
331C8088294A63A400263BE5 /* Debug-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = DFB6BB492A265F2BF6FDC8C0 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
baseConfigurationReference = 01BAAF935356ECBDD35AF0DB /* Pods-RunnerTests.debug-prod.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@ -550,11 +589,11 @@
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
name = "Debug-prod";
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
331C8089294A63A400263BE5 /* Release-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = F323D632CA976B68DDB0E669 /* Pods-RunnerTests.release.xcconfig */;
|
||||
baseConfigurationReference = C5DBBF9417E4F8A9A08DFF02 /* Pods-RunnerTests.release-prod.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@ -566,11 +605,11 @@
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
name = "Release-prod";
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
331C808A294A63A400263BE5 /* Profile-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AAC9129FD50E64509AD1B9AF /* Pods-RunnerTests.profile.xcconfig */;
|
||||
baseConfigurationReference = 238CAAD9FFF9A0C9ED3CFAB2 /* Pods-RunnerTests.profile-prod.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@ -582,9 +621,9 @@
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
name = "Profile-prod";
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
97C147031CF9000F007C117D /* Debug-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
@ -640,9 +679,9 @@
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
name = "Debug-prod";
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
97C147041CF9000F007C117D /* Release-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
@ -695,9 +734,9 @@
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
name = "Release-prod";
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
97C147061CF9000F007C117D /* Debug-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
@ -725,9 +764,9 @@
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
name = "Debug-prod";
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
97C147071CF9000F007C117D /* Release-prod */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
@ -754,7 +793,311 @@
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
name = "Release-prod";
|
||||
};
|
||||
B07E4A0C2C9B8C45001F6910 /* Debug-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = "Debug-dev";
|
||||
};
|
||||
B07E4A0D2C9B8C45001F6910 /* Debug-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 48V27SBR8J;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = "Debug-dev";
|
||||
};
|
||||
B07E4A0E2C9B8C45001F6910 /* Debug-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = EE971EFEA60AEDFDB361D9A3 /* Pods-RunnerTests.debug-dev.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrowApp.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = "Debug-dev";
|
||||
};
|
||||
B07E4A0F2C9B8C52001F6910 /* Release-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = "Release-dev";
|
||||
};
|
||||
B07E4A102C9B8C52001F6910 /* Release-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 48V27SBR8J;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = "Release-dev";
|
||||
};
|
||||
B07E4A112C9B8C52001F6910 /* Release-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = A3D4DF5D9888DAC25E2380AA /* Pods-RunnerTests.release-dev.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrowApp.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = "Release-dev";
|
||||
};
|
||||
B07E4A122C9B8C5C001F6910 /* Profile-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = "Profile-dev";
|
||||
};
|
||||
B07E4A132C9B8C5C001F6910 /* Profile-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 48V27SBR8J;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Syncrow;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrow.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = "Profile-dev";
|
||||
};
|
||||
B07E4A142C9B8C5C001F6910 /* Profile-dev */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 210827A693936E5201C5E75C /* Pods-RunnerTests.profile-dev.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.syncrowApp.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = "Profile-dev";
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
@ -762,32 +1105,41 @@
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
331C8088294A63A400263BE5 /* Debug-prod */,
|
||||
B07E4A0E2C9B8C45001F6910 /* Debug-dev */,
|
||||
331C8089294A63A400263BE5 /* Release-prod */,
|
||||
B07E4A112C9B8C52001F6910 /* Release-dev */,
|
||||
331C808A294A63A400263BE5 /* Profile-prod */,
|
||||
B07E4A142C9B8C5C001F6910 /* Profile-dev */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
defaultConfigurationName = "Release-prod";
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
97C147031CF9000F007C117D /* Debug-prod */,
|
||||
B07E4A0C2C9B8C45001F6910 /* Debug-dev */,
|
||||
97C147041CF9000F007C117D /* Release-prod */,
|
||||
B07E4A0F2C9B8C52001F6910 /* Release-dev */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile-prod */,
|
||||
B07E4A122C9B8C5C001F6910 /* Profile-dev */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
defaultConfigurationName = "Release-prod";
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
97C147061CF9000F007C117D /* Debug-prod */,
|
||||
B07E4A0D2C9B8C45001F6910 /* Debug-dev */,
|
||||
97C147071CF9000F007C117D /* Release-prod */,
|
||||
B07E4A102C9B8C52001F6910 /* Release-dev */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile-prod */,
|
||||
B07E4A132C9B8C5C001F6910 /* Profile-dev */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
defaultConfigurationName = "Release-prod";
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
77
ios/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme
Normal file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1520"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug-dev"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug-dev"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release-dev"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug-dev">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release-dev"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
@ -23,7 +23,7 @@
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
buildConfiguration = "Debug-prod"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
@ -51,7 +51,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
buildConfiguration = "Debug-prod"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
@ -72,7 +72,7 @@
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
buildConfiguration = "Profile-prod"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
@ -89,10 +89,10 @@
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
buildConfiguration = "Debug-prod">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
buildConfiguration = "Release-prod"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
32
ios/config/prod/GoogleService-Info.plist
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>API_KEY</key>
|
||||
<string>AIzaSyAWlRiuJ75FMlf2_UDdri1voWKvkaSHtRg</string>
|
||||
<key>GCM_SENDER_ID</key>
|
||||
<string>786692570726</string>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>com.example.syncrow.app</string>
|
||||
<key>PROJECT_ID</key>
|
||||
<string>syncrow-staging</string>
|
||||
<key>STORAGE_BUCKET</key>
|
||||
<string>syncrow-staging.appspot.com</string>
|
||||
<key>IS_ADS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_ANALYTICS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_APPINVITE_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_GCM_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_SIGNIN_ENABLED</key>
|
||||
<true></true>
|
||||
<key>GOOGLE_APP_ID</key>
|
||||
<string>1:786692570726:ios:455a6fcff77e130f17b7a7</string>
|
||||
<key>DATABASE_URL</key>
|
||||
<string>https://syncrow-staging-default-rtdb.firebaseio.com</string>
|
||||
</dict>
|
||||
</plist>
|
@ -16,60 +16,55 @@ class AppBarHomeDropdown extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||
child: Center(
|
||||
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(
|
||||
fit: FlexFit.loose,
|
||||
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));
|
||||
}
|
||||
},
|
||||
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),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
HomeCubit.getInstance().changeSelectedSpace(
|
||||
HomeCubit.getInstance().spaces!.firstWhere((element) => element.id == value));
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -11,20 +11,18 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<HomeCubit, HomeState>(
|
||||
builder: (context, state) {
|
||||
return Padding(
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 20,
|
||||
),
|
||||
child: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
leadingWidth: 150,
|
||||
leadingWidth: 200,
|
||||
toolbarHeight: Constants.appBarHeight,
|
||||
leading: HomeCubit.getInstance().spaces!.isNotEmpty
|
||||
? HomeCubit.appBarLeading[
|
||||
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]
|
||||
? HomeCubit.appBarLeading[HomeCubit.bottomNavItems[HomeCubit.pageIndex].label]!
|
||||
: null,
|
||||
actions: HomeCubit.appBarActions[
|
||||
HomeCubit.bottomNavItems[HomeCubit.pageIndex].label],
|
||||
actions: HomeCubit.appBarActions[HomeCubit.bottomNavItems[HomeCubit.pageIndex].label],
|
||||
));
|
||||
},
|
||||
);
|
||||
|
@ -8,7 +8,6 @@ import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/services/api/authentication_api.dart';
|
||||
import 'package:syncrow_app/services/api/profile_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/shared_preferences_helper.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||
|
179
lib/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart
Normal file
@ -0,0 +1,179 @@
|
||||
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/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
|
||||
class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
|
||||
final String DSId;
|
||||
DoorSensorBloc({
|
||||
required this.DSId,
|
||||
}) : super(const DoorSensorState()) {
|
||||
on<DoorSensorInitial>(_fetchStatus);
|
||||
on<ReportLogsInitial>(fetchLogsForLastMonth);
|
||||
on<ToggleLowBatteryEvent>(_toggleLowBattery);
|
||||
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
|
||||
on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
|
||||
}
|
||||
Timer? _timer;
|
||||
bool lowBattery = false;
|
||||
bool closingReminder = false;
|
||||
bool doorAlarm = false;
|
||||
DoorSensorModel deviceStatus =
|
||||
DoorSensorModel(doorContactState: false, batteryPercentage: 0);
|
||||
|
||||
void _fetchStatus(
|
||||
DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
|
||||
emit(DoorSensorLoadingState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(DSId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = DoorSensorModel.fromJson(
|
||||
statusModelList,
|
||||
);
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
Future.delayed(const Duration(milliseconds: 500));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle functions for each switch
|
||||
void _toggleLowBattery(
|
||||
ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
lowBattery = event.isLowBatteryEnabled;
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
|
||||
// API call to update the state, if necessary
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: DSId,
|
||||
code: 'low_battery',
|
||||
value: lowBattery,
|
||||
),
|
||||
DSId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleClosingReminder(
|
||||
ToggleClosingReminderEvent event, Emitter<DoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
closingReminder = event.isClosingReminderEnabled;
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
|
||||
// API call to update the state, if necessary
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: DSId,
|
||||
code: 'closing_reminder',
|
||||
value: closingReminder,
|
||||
),
|
||||
DSId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleDoorAlarm(
|
||||
ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
doorAlarm = event.isDoorAlarmEnabled;
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
|
||||
// API call to update the state, if necessary
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: DSId,
|
||||
code: 'door_alarm',
|
||||
value: doorAlarm,
|
||||
),
|
||||
DSId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
DeviceReport recordGroups =
|
||||
DeviceReport(startTime: '0', endTime: '0', data: []);
|
||||
|
||||
Future<void> fetchLogsForLastMonth(
|
||||
ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
|
||||
// Get the current date and time
|
||||
DateTime now = DateTime.now();
|
||||
|
||||
// Calculate the date one month ago
|
||||
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
||||
|
||||
// Convert the date to milliseconds since epoch (Unix timestamp in milliseconds)
|
||||
int startTime = lastMonth.millisecondsSinceEpoch;
|
||||
int endTime = now.millisecondsSinceEpoch;
|
||||
try {
|
||||
emit(DoorSensorLoadingState());
|
||||
var response = await DevicesAPI.getReportLogs(
|
||||
startTime:
|
||||
startTime.toString(), // Convert to String if the API expects it
|
||||
endTime: endTime.toString(), // Convert to String if the API expects it
|
||||
deviceUuid: DSId,
|
||||
code: 'doorcontact_state',
|
||||
);
|
||||
print('response======${response}');
|
||||
recordGroups = response;
|
||||
// Process response here
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
// Handle error
|
||||
print('Error fetching logs: ${errorMessage}');
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$DSId');
|
||||
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 = DoorSensorModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
add(
|
||||
DoorSensorSwitch(switchD: deviceStatus.doorContactState),
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class DoorSensorEvent extends Equatable {
|
||||
const DoorSensorEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DoorSensorLoading extends DoorSensorEvent {}
|
||||
|
||||
class DoorSensorSwitch extends DoorSensorEvent {
|
||||
final bool switchD;
|
||||
final String deviceId;
|
||||
final String productId;
|
||||
const DoorSensorSwitch({required this.switchD, this.deviceId = '', this.productId = ''});
|
||||
|
||||
@override
|
||||
List<Object> get props => [switchD, deviceId, productId];
|
||||
}
|
||||
|
||||
class DoorSensorUpdated extends DoorSensorEvent {}
|
||||
|
||||
class DoorSensorInitial extends DoorSensorEvent {
|
||||
const DoorSensorInitial();
|
||||
}
|
||||
|
||||
class ReportLogsInitial extends DoorSensorEvent {
|
||||
const ReportLogsInitial();
|
||||
}
|
||||
|
||||
|
||||
class DoorSensorChangeStatus extends DoorSensorEvent {}
|
||||
|
||||
|
||||
class GetCounterEvent extends DoorSensorEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ToggleLowBatteryEvent extends DoorSensorEvent {
|
||||
final bool isLowBatteryEnabled;
|
||||
|
||||
const ToggleLowBatteryEvent(this.isLowBatteryEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isLowBatteryEnabled];
|
||||
}
|
||||
|
||||
class ToggleClosingReminderEvent extends DoorSensorEvent {
|
||||
final bool isClosingReminderEnabled;
|
||||
|
||||
const ToggleClosingReminderEvent(this.isClosingReminderEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isClosingReminderEnabled];
|
||||
}
|
||||
|
||||
class ToggleDoorAlarmEvent extends DoorSensorEvent {
|
||||
final bool isDoorAlarmEnabled;
|
||||
|
||||
const ToggleDoorAlarmEvent(this.isDoorAlarmEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isDoorAlarmEnabled];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class SetCounterValue extends DoorSensorEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends DoorSensorEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends DoorSensorEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends DoorSensorEvent {}
|
||||
|
||||
class OnClose extends DoorSensorEvent {}
|
@ -0,0 +1,128 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
||||
|
||||
class DoorSensorState extends Equatable {
|
||||
const DoorSensorState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DoorSensorInitialState extends DoorSensorState {}
|
||||
|
||||
class DoorSensorLoadingState extends DoorSensorState {}
|
||||
|
||||
class DoorSensorFailedState extends DoorSensorState {
|
||||
final String errorMessage;
|
||||
|
||||
const DoorSensorFailedState({required this.errorMessage});
|
||||
|
||||
@override
|
||||
List<Object> get props => [errorMessage];
|
||||
}
|
||||
|
||||
class UpdateState extends DoorSensorState {
|
||||
final DoorSensorModel doorSensor;
|
||||
const UpdateState({required this.doorSensor});
|
||||
|
||||
@override
|
||||
List<Object> get props => [doorSensor];
|
||||
}
|
||||
|
||||
|
||||
class LoadingNewSate extends DoorSensorState {
|
||||
final DoorSensorModel doorSensor;
|
||||
const LoadingNewSate({required this.doorSensor});
|
||||
|
||||
@override
|
||||
List<Object> get props => [doorSensor];
|
||||
}
|
||||
|
||||
// class WHModifyingState extends DoorSensorState {
|
||||
// final WHModel whStatusModel;
|
||||
// const WHModifyingState({required this.whStatusModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [whStatusModel];
|
||||
// }
|
||||
//
|
||||
// class GetWHStatusState extends DoorSensorState {
|
||||
// final WHModel whStatusModel;
|
||||
// const GetWHStatusState({required this.whStatusModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [whStatusModel];
|
||||
// }
|
||||
//
|
||||
//
|
||||
// class WHFailedState extends WaterHeaterState {
|
||||
// final String errorMessage;
|
||||
//
|
||||
// const WHFailedState({required this.errorMessage});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [errorMessage];
|
||||
// }
|
||||
|
||||
|
||||
// class LoadingNewSate extends WaterHeaterState {
|
||||
// final WHModel whModel;
|
||||
// const LoadingNewSate({required this.whModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [whModel];
|
||||
// }
|
||||
// class TimerRunComplete extends WaterHeaterState {}
|
||||
// class UpdateTimerState extends WaterHeaterState {
|
||||
// final int seconds;
|
||||
// const UpdateTimerState({required this.seconds});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [seconds];
|
||||
// }
|
||||
//
|
||||
// class TimerRunInProgress extends WaterHeaterState {
|
||||
// final int remainingTime;
|
||||
//
|
||||
// const TimerRunInProgress(this.remainingTime);
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [remainingTime];
|
||||
// }
|
||||
//
|
||||
// class SaveSchedule extends WaterHeaterState {}
|
||||
// class ChangeTimeState extends WaterHeaterState {}
|
||||
// class UpdateCreateScheduleState extends WaterHeaterState {
|
||||
// final bool createSchedule;
|
||||
// UpdateCreateScheduleState(this.createSchedule);
|
||||
// }
|
||||
// class IsToggleState extends WaterHeaterState {
|
||||
// final bool? onOff;
|
||||
// const IsToggleState({this.onOff});
|
||||
// }
|
||||
//
|
||||
//
|
||||
// class UpdateState extends WaterHeaterState {
|
||||
// final WHModel whModel;
|
||||
// const UpdateState({required this.whModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [WHModel];
|
||||
// }
|
||||
//
|
||||
// class ChangeSwitchStatusEvent extends WaterHeaterState {
|
||||
// final bool value;
|
||||
// final String deviceId;
|
||||
// const ChangeSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
// @override
|
||||
// List<Object> get props => [value, deviceId];
|
||||
// }
|
||||
//
|
||||
// class ChangeSlidingSegmentState extends WaterHeaterState {
|
||||
// final int value;
|
||||
//
|
||||
// const ChangeSlidingSegmentState({required this.value});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [value];
|
||||
// }
|
@ -2,9 +2,11 @@ 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/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.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/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
@ -24,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);
|
||||
@ -34,17 +37,21 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
|
||||
|
||||
|
||||
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ThreeGangSave>(saveSchedule);
|
||||
on<ScheduleSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<InitialWizardEvent>(_fetchOneGangWizardStatus);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
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);
|
||||
@ -63,18 +70,21 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$oneGangId');
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$oneGangId');
|
||||
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 = OneGangModel.fromJson(statusList);
|
||||
@ -89,7 +99,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
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;
|
||||
@ -114,18 +125,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) {
|
||||
@ -148,7 +161,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);
|
||||
@ -199,11 +213,14 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
{"day": "Sat", "key": "Sat"},
|
||||
];
|
||||
|
||||
Future<void> saveSchedule(ThreeGangSave event, Emitter<OneGangState> emit,) async {
|
||||
Future<void> saveSchedule(
|
||||
ScheduleSave event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
if(selectedDays.isNotEmpty) {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.postSchedule(
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: oneGangId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
@ -212,9 +229,10 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(ThreeGangSaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
}else{
|
||||
emit(SaveSchedule());
|
||||
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
@ -222,16 +240,19 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> getSchedule(GetScheduleEvent event, Emitter<OneGangState> emit,) async {
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: oneGangId ,
|
||||
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;
|
||||
@ -273,7 +294,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: oneGangId, );
|
||||
deviceUuid: oneGangId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
@ -287,24 +309,24 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
emit(ChangeSlidingSegmentState(value: 1));
|
||||
}
|
||||
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime=DateTime.now();
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
@ -312,15 +334,157 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<OneGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = index;
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
List<GroupOneGangModel> groupOneGangList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
void _fetchOneGangWizardStatus(
|
||||
InitialWizardEvent event, Emitter<OneGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupOneGangList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = OneGangModel.fromJson(statusModelList);
|
||||
groupOneGangList.add(GroupOneGangModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupOneGangList.isNotEmpty) {
|
||||
groupOneGangList.firstWhere((element) {
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<OneGangState> emit) async {
|
||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupOneGangList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
emit(UpdateGroupState(
|
||||
oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: [event.deviceId],
|
||||
value: !event.value,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
add(InitialEvent(groupScreen: oneGangGroup));
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: oneGangGroup));
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOn(GroupAllOnEvent event, Emitter<OneGangState> emit) async {
|
||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||
try {
|
||||
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||
for (int i = 0; i < groupOneGangList.length; i++) {
|
||||
groupOneGangList[i].firstSwitch = true;
|
||||
}
|
||||
|
||||
// Emit the state with updated values
|
||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds =
|
||||
groupOneGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
// First call for switch_1
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1', // Controls first switch for all devices
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
// Check if either response is unsuccessful, then reset to initial state
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
// In case of an error, delay and reset the screen to initial state
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOff(GroupAllOffEvent event, Emitter<OneGangState> emit) async {
|
||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||
try {
|
||||
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||
for (int i = 0; i < groupOneGangList.length; i++) {
|
||||
groupOneGangList[i].firstSwitch = false;
|
||||
}
|
||||
|
||||
// Emit the state with updated values
|
||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds =
|
||||
groupOneGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
// First call for switch_1
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1', // Controls first switch for all devices
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
|
||||
// Check if either response is unsuccessful, then reset to initial state
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
// In case of an error, delay and reset the screen to initial state
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,12 +29,12 @@ class ChangeFirstSwitchStatusEvent extends OneGangEvent {
|
||||
class ChangeSecondSwitchStatusEvent extends OneGangEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSecondSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
const ChangeSecondSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
|
||||
class AllOffEvent extends OneGangEvent {}
|
||||
|
||||
class AllOnEvent extends OneGangEvent {}
|
||||
@ -87,30 +87,55 @@ class StopTimer extends OneGangEvent {}
|
||||
|
||||
class OnClose extends OneGangEvent {}
|
||||
|
||||
|
||||
|
||||
class InitialWizardEvent extends OneGangEvent {}
|
||||
|
||||
//------------------- Schedule ----------=---------
|
||||
class GetScheduleEvent extends OneGangEvent {}
|
||||
class ThreeGangSave extends OneGangEvent {}
|
||||
|
||||
class ScheduleSave extends OneGangEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends OneGangEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle,required this.id});
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle,id];
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
class ToggleDaySelectionEvent extends OneGangEvent {
|
||||
|
||||
class ToggleDaySelectionEvent extends OneGangEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@override
|
||||
List<Object> get props => [key];
|
||||
}
|
||||
|
||||
class DeleteScheduleEvent extends OneGangEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends OneGangEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends OneGangEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends OneGangEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
|
||||
|
||||
class OneGangState extends Equatable {
|
||||
const OneGangState();
|
||||
|
||||
@ -32,13 +31,13 @@ class LoadingNewSate extends OneGangState {
|
||||
}
|
||||
|
||||
class UpdateGroupState extends OneGangState {
|
||||
final List<GroupTwoGangModel> twoGangList;
|
||||
final List<GroupOneGangModel> oneGangList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState({required this.twoGangList, required this.allSwitches});
|
||||
const UpdateGroupState({required this.oneGangList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [twoGangList, allSwitches];
|
||||
List<Object> get props => [oneGangList, allSwitches];
|
||||
}
|
||||
|
||||
class FailedState extends OneGangState {
|
||||
@ -77,13 +76,17 @@ class TimerRunInProgress extends OneGangState {
|
||||
}
|
||||
|
||||
class TimerRunComplete extends OneGangState {}
|
||||
class ThreeGangSaveSchedule extends OneGangState {}
|
||||
|
||||
class SaveSchedule extends OneGangState {}
|
||||
|
||||
class IsToggleState extends OneGangState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
class ChangeTimeState extends OneGangState {}
|
||||
|
||||
class UpdateCreateScheduleState extends OneGangState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
||||
}
|
||||
|
551
lib/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart
Normal file
@ -0,0 +1,551 @@
|
||||
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/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class OneTouchBloc extends Bloc<OneTouchEvent, OneTouchState> {
|
||||
final String oneTouchId;
|
||||
final String switchCode;
|
||||
OneTouchModel deviceStatus = OneTouchModel(
|
||||
firstSwitch: false,
|
||||
firstCountDown: 0,
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off);
|
||||
Timer? _timer;
|
||||
|
||||
bool oneTouchGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
|
||||
OneTouchBloc({required this.oneTouchId, required this.switchCode})
|
||||
: super(InitialState()) {
|
||||
on<InitialEvent>(_fetchOneTouchStatus);
|
||||
on<OneTouchUpdated>(_oneTouchUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
on<ChangeSlidingSegment>(_changeSliding);
|
||||
on<SetCounterValue>(_setCounterValue);
|
||||
on<GetCounterEvent>(_getCounterValue);
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ScheduleSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<InitialWizardEvent>(_fetchOneTouchWizardStatus);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
on<ChangeStatusEvent>(_changeStatus);
|
||||
}
|
||||
|
||||
void _fetchOneTouchStatus(
|
||||
InitialEvent event, Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = OneTouchModel.fromJson(statusModelList);
|
||||
emit(UpdateState(oneTouchModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$oneTouchId');
|
||||
Stream<DatabaseEvent> stream = ref.onValue;
|
||||
|
||||
stream.listen((DatabaseEvent event) async {
|
||||
if (_timer != null) {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
}
|
||||
Map<dynamic, dynamic> usersMap =
|
||||
event.snapshot.value as Map<dynamic, dynamic>;
|
||||
List<StatusModel> statusList = [];
|
||||
|
||||
usersMap['status'].forEach((element) {
|
||||
statusList
|
||||
.add(StatusModel(code: element['code'], value: element['value']));
|
||||
});
|
||||
|
||||
deviceStatus = OneTouchModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
add(OneTouchUpdated());
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
_oneTouchUpdated(OneTouchUpdated event, Emitter<OneTouchState> emit) {
|
||||
emit(UpdateState(oneTouchModel: deviceStatus));
|
||||
}
|
||||
|
||||
void _changeFirstSwitch(
|
||||
ChangeFirstSwitchStatusEvent event, Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||
try {
|
||||
deviceStatus.firstSwitch = !event.value;
|
||||
emit(UpdateState(oneTouchModel: deviceStatus));
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: oneTouchGroup ? event.deviceId : oneTouchId,
|
||||
code: 'switch_1',
|
||||
value: !event.value),
|
||||
oneTouchGroup ? event.deviceId : oneTouchId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSliding(
|
||||
ChangeSlidingSegment event, Emitter<OneTouchState> emit) async {
|
||||
emit(ChangeSlidingSegmentState(value: event.value));
|
||||
}
|
||||
|
||||
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),
|
||||
oneTouchId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown = seconds;
|
||||
}
|
||||
} else {
|
||||
emit(const FailedState(error: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
if (seconds > 0) {
|
||||
_onStartTimer(seconds);
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
void _getCounterValue(
|
||||
GetCounterEvent event, Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(oneTouchId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = OneTouchModel.fromJson(statusModelList);
|
||||
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown > 0
|
||||
? _onStartTimer(deviceStatus.firstCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _onClose(OnClose event, Emitter<OneTouchState> emit) {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
void _onStartTimer(int seconds) {
|
||||
_timer?.cancel();
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
add(TickTimer(seconds - timer.tick));
|
||||
});
|
||||
}
|
||||
|
||||
void _onTickTimer(TickTimer event, Emitter<OneTouchState> emit) {
|
||||
if (event.remainingTime > 0) {
|
||||
emit(TimerRunInProgress(event.remainingTime));
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, String>> days = [
|
||||
{"day": "Sun", "key": "Sun"},
|
||||
{"day": "Mon", "key": "Mon"},
|
||||
{"day": "Tue", "key": "Tue"},
|
||||
{"day": "Wed", "key": "Wed"},
|
||||
{"day": "Thu", "key": "Thu"},
|
||||
{"day": "Fri", "key": "Fri"},
|
||||
{"day": "Sat", "key": "Sat"},
|
||||
];
|
||||
|
||||
Future<void> saveSchedule(
|
||||
ScheduleSave event,
|
||||
Emitter<OneTouchState> emit,
|
||||
) async {
|
||||
try {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: oneTouchId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
code: switchCode,
|
||||
value: toggleSchedule,
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(SaveSchedule());
|
||||
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<OneTouchState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: oneTouchId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(InitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
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 {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id, deviceUuid: oneTouchId, enable: event.toggle);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
toggleSchedule = event.toggle;
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<OneTouchState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: oneTouchId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<OneTouchState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<OneTouchState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
} else {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<OneTouchState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
List<GroupOneTouchModel> groupOneTouchList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
void _fetchOneTouchWizardStatus(
|
||||
InitialWizardEvent event, Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupOneTouchList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '1GT');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = OneTouchModel.fromJson(statusModelList);
|
||||
groupOneTouchList.add(GroupOneTouchModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupOneTouchList.isNotEmpty) {
|
||||
groupOneTouchList.firstWhere((element) {
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
oneTouchList: groupOneTouchList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupOneTouchList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: [event.deviceId],
|
||||
value: !event.value,
|
||||
);
|
||||
|
||||
emit(UpdateGroupState(
|
||||
oneTouchList: groupOneTouchList, allSwitches: allSwitchesValue));
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: oneTouchGroup));
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOn(GroupAllOnEvent event, Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||
try {
|
||||
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||
for (int i = 0; i < groupOneTouchList.length; i++) {
|
||||
groupOneTouchList[i].firstSwitch = true;
|
||||
}
|
||||
|
||||
// Emit the state with updated values
|
||||
emit(
|
||||
UpdateGroupState(oneTouchList: groupOneTouchList, allSwitches: true));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds =
|
||||
groupOneTouchList.map((device) => device.deviceId).toList();
|
||||
|
||||
// First call for switch_1
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1', // Controls first switch for all devices
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
|
||||
// Second call for switch_2
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2', // Controls second switch for all devices
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
|
||||
// Check if either response is unsuccessful, then reset to initial state
|
||||
if (!response1['success'] || !response2['success']) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
// In case of an error, delay and reset the screen to initial state
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOff(GroupAllOffEvent event, Emitter<OneTouchState> emit) async {
|
||||
emit(LoadingNewSate(oneTouchModel: deviceStatus));
|
||||
try {
|
||||
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||
for (int i = 0; i < groupOneTouchList.length; i++) {
|
||||
groupOneTouchList[i].firstSwitch = false;
|
||||
}
|
||||
|
||||
// Emit the state with updated values
|
||||
emit(UpdateGroupState(
|
||||
oneTouchList: groupOneTouchList, allSwitches: false));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds =
|
||||
groupOneTouchList.map((device) => device.deviceId).toList();
|
||||
|
||||
// First call for switch_1
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1', // Controls first switch for all devices
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
|
||||
// Second call for switch_2
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2', // Controls second switch for all devices
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
// Check if either response is unsuccessful, then reset to initial state
|
||||
if (!response1['success'] || !response2['success']) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
// In case of an error, delay and reset the screen to initial state
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
}
|
||||
|
||||
String statusSelected = '';
|
||||
String optionSelected = '';
|
||||
|
||||
Future<void> _changeStatus(
|
||||
ChangeStatusEvent event, Emitter<OneTouchState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
|
||||
final Map<String, Map<String, String>> controlMap = {
|
||||
"relay_status": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
"light_mode": {
|
||||
'Off': 'none',
|
||||
'On/Off Status': 'relay',
|
||||
'Switch Position': 'pos',
|
||||
},
|
||||
"relay_status_1": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
};
|
||||
|
||||
final selectedControl = controlMap[optionSelected]?[statusSelected];
|
||||
if (selectedControl != null) {
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: oneTouchId, code: optionSelected, value: selectedControl),
|
||||
oneTouchId,
|
||||
);
|
||||
} else {
|
||||
print('Invalid statusSelected or optionSelected');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
}
|
148
lib/features/devices/bloc/one_touch_bloc/one_touch_event.dart
Normal file
@ -0,0 +1,148 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class OneTouchEvent extends Equatable {
|
||||
const OneTouchEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class LoadingEvent extends OneTouchEvent {}
|
||||
|
||||
class OneTouchUpdated extends OneTouchEvent {}
|
||||
|
||||
class InitialEvent extends OneTouchEvent {
|
||||
final bool groupScreen;
|
||||
const InitialEvent({required this.groupScreen});
|
||||
@override
|
||||
List<Object> get props => [groupScreen];
|
||||
}
|
||||
|
||||
class ChangeFirstSwitchStatusEvent extends OneTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeSecondSwitchStatusEvent extends OneTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSecondSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class AllOffEvent extends OneTouchEvent {}
|
||||
|
||||
class AllOnEvent extends OneTouchEvent {}
|
||||
|
||||
class GroupAllOnEvent extends OneTouchEvent {}
|
||||
|
||||
class GroupAllOffEvent extends OneTouchEvent {}
|
||||
|
||||
class ChangeSlidingSegment extends OneTouchEvent {
|
||||
final int value;
|
||||
const ChangeSlidingSegment({required this.value});
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class GetCounterEvent extends OneTouchEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
class SetCounterValue extends OneTouchEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends OneTouchEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends OneTouchEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends OneTouchEvent {}
|
||||
|
||||
class OnClose extends OneTouchEvent {}
|
||||
|
||||
class InitialWizardEvent extends OneTouchEvent {}
|
||||
|
||||
//------------------- Schedule ----------=---------
|
||||
class GetScheduleEvent extends OneTouchEvent {}
|
||||
|
||||
class ScheduleSave extends OneTouchEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends OneTouchEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
|
||||
class ToggleDaySelectionEvent extends OneTouchEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@override
|
||||
List<Object> get props => [key];
|
||||
}
|
||||
|
||||
class DeleteScheduleEvent extends OneTouchEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends OneTouchEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends OneTouchEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends OneTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeStatusEvent extends OneTouchEvent {
|
||||
final String deviceId;
|
||||
final BuildContext context;
|
||||
const ChangeStatusEvent({this.deviceId = '',required this.context});
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||
|
||||
|
||||
class OneTouchState extends Equatable {
|
||||
const OneTouchState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class InitialState extends OneTouchState {}
|
||||
|
||||
class LoadingInitialState extends OneTouchState {}
|
||||
|
||||
class UpdateState extends OneTouchState {
|
||||
final OneTouchModel oneTouchModel;
|
||||
const UpdateState({required this.oneTouchModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [oneTouchModel];
|
||||
}
|
||||
|
||||
class LoadingNewSate extends OneTouchState {
|
||||
final OneTouchModel oneTouchModel;
|
||||
const LoadingNewSate({required this.oneTouchModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [OneTouchModel];
|
||||
}
|
||||
|
||||
class UpdateGroupState extends OneTouchState {
|
||||
final List<GroupOneTouchModel> oneTouchList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState({required this.oneTouchList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [oneTouchList, allSwitches];
|
||||
}
|
||||
|
||||
class FailedState extends OneTouchState {
|
||||
final String error;
|
||||
|
||||
const FailedState({required this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class ChangeSlidingSegmentState extends OneTouchState {
|
||||
final int value;
|
||||
|
||||
const ChangeSlidingSegmentState({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class UpdateTimerState extends OneTouchState {
|
||||
final int seconds;
|
||||
const UpdateTimerState({required this.seconds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [seconds];
|
||||
}
|
||||
|
||||
class TimerRunInProgress extends OneTouchState {
|
||||
final int remainingTime;
|
||||
|
||||
const TimerRunInProgress(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class TimerRunComplete extends OneTouchState {}
|
||||
|
||||
class SaveSchedule extends OneTouchState {}
|
||||
|
||||
class IsToggleState extends OneTouchState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
class ChangeTimeState extends OneTouchState {}
|
||||
|
||||
class UpdateCreateScheduleState extends OneTouchState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
@ -14,7 +14,6 @@ import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
|
||||
|
||||
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
final String threeGangId;
|
||||
final String switchCode;
|
||||
@ -26,16 +25,13 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
secondCountDown: 0,
|
||||
thirdCountDown: 0);
|
||||
Timer? _timer;
|
||||
// Timer? _firstSwitchTimer;
|
||||
// Timer? _secondSwitchTimer;
|
||||
// Timer? _thirdSwitchTimer;
|
||||
|
||||
bool threeGangGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
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);
|
||||
@ -51,13 +47,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
|
||||
|
||||
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ThreeGangSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
}
|
||||
|
||||
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
|
||||
@ -117,7 +114,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId');
|
||||
Stream<DatabaseEvent> stream = ref.onValue;
|
||||
|
||||
stream.listen((DatabaseEvent event) async {
|
||||
stream.listen((DatabaseEvent event) async {
|
||||
if (_timer != null) {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
}
|
||||
@ -490,9 +487,6 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
List<Map<String, String>> days = [
|
||||
{"day": "Sun", "key": "Sun"},
|
||||
{"day": "Mon", "key": "Mon"},
|
||||
@ -504,9 +498,9 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
];
|
||||
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
@ -517,11 +511,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(ThreeGangSave event, Emitter<ThreeGangState> emit,) async {
|
||||
Future<void> saveSchedule(
|
||||
ThreeGangSave event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
if(selectedDays.isNotEmpty) {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.postSchedule(
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: threeGangId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
@ -531,8 +528,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(ThreeGangSaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
}else{
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
@ -540,13 +537,15 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> getSchedule(GetScheduleEvent event, Emitter<ThreeGangState> emit,) async {
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: threeGangId ,
|
||||
deviceId: threeGangId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
@ -560,13 +559,12 @@ 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(
|
||||
@ -585,13 +583,13 @@ 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(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: threeGangId, );
|
||||
scheduleId: event.id,
|
||||
deviceUuid: threeGangId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
@ -605,27 +603,24 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
emit(ChangeSlidingSegmentState(value: 1));
|
||||
}
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = index;
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime=DateTime.now();
|
||||
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
}
|
||||
|
@ -119,3 +119,22 @@ class DeleteScheduleEvent extends ThreeGangEvent {
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ToggleSelectedEvent extends ThreeGangEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
class ToggleCreateScheduleEvent extends ThreeGangEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class InitialWizardDevises extends ThreeGangEvent {}
|
||||
|
748
lib/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart
Normal file
@ -0,0 +1,748 @@
|
||||
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/devices/bloc/three_touch_bloc/three_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_state.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/group_three_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class ThreeTouchBloc extends Bloc<ThreeTouchEvent, ThreeTouchState> {
|
||||
final String threeTouchId;
|
||||
final String switchCode;
|
||||
ThreeTouchModel deviceStatus = ThreeTouchModel(
|
||||
firstSwitch: false,
|
||||
secondSwitch: false,
|
||||
thirdSwitch: false,
|
||||
firstCountDown: 0,
|
||||
secondCountDown: 0,
|
||||
thirdCountDown: 0,
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off,
|
||||
relay_status_2: status.off,
|
||||
relay_status_3: status.off,
|
||||
);
|
||||
Timer? _timer;
|
||||
|
||||
bool threeTouchGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
List<GroupThreeTouchModel> groupThreeTouchList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
ThreeTouchBloc({required this.threeTouchId, required this.switchCode})
|
||||
: super(InitialState()) {
|
||||
on<InitialEvent>(_fetchThreeTouchStatus);
|
||||
on<ThreeTouchUpdated>(_threeTouchUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
|
||||
on<ChangeThirdSwitchStatusEvent>(_changeThirdSwitch);
|
||||
on<AllOffEvent>(_allOff);
|
||||
on<AllOnEvent>(_allOn);
|
||||
on<ChangeSlidingSegment>(_changeSliding);
|
||||
on<SetCounterValue>(_setCounterValue);
|
||||
on<GetCounterEvent>(_getCounterValue);
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ThreeTouchSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<ChangeStatusEvent>(_changeStatus);
|
||||
}
|
||||
|
||||
void _fetchThreeTouchStatus(
|
||||
InitialEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
threeTouchGroup = event.groupScreen;
|
||||
if (threeTouchGroup) {
|
||||
devicesList = [];
|
||||
groupThreeTouchList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '3GT');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
|
||||
|
||||
groupThreeTouchList.add(GroupThreeTouchModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
secondSwitch: deviceStatus.secondSwitch,
|
||||
thirdSwitch: deviceStatus.thirdSwitch));
|
||||
}
|
||||
|
||||
if (groupThreeTouchList.isNotEmpty) {
|
||||
groupThreeTouchList.firstWhere((element) {
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList, allSwitches: allSwitchesOn));
|
||||
} else {
|
||||
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
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>;
|
||||
List<StatusModel> statusList = [];
|
||||
|
||||
usersMap['status'].forEach((element) {
|
||||
statusList
|
||||
.add(StatusModel(code: element['code'], value: element['value']));
|
||||
});
|
||||
|
||||
deviceStatus = ThreeTouchModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
add(ThreeTouchUpdated());
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
_threeTouchUpdated(ThreeTouchUpdated event, Emitter<ThreeTouchState> emit) {
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
}
|
||||
|
||||
void _changeFirstSwitch(
|
||||
ChangeFirstSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
try {
|
||||
if (threeTouchGroup) {
|
||||
bool allSwitchesValue = true;
|
||||
groupThreeTouchList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList,
|
||||
allSwitches: allSwitchesValue));
|
||||
} else {
|
||||
deviceStatus.firstSwitch = !event.value;
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
}
|
||||
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchGroup ? event.deviceId : threeTouchId,
|
||||
code: 'switch_1',
|
||||
value: !event.value),
|
||||
threeTouchGroup ? event.deviceId : threeTouchId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event,
|
||||
Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
try {
|
||||
if (threeTouchGroup) {
|
||||
bool allSwitchesValue = true;
|
||||
groupThreeTouchList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.secondSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList,
|
||||
allSwitches: allSwitchesValue));
|
||||
} else {
|
||||
deviceStatus.secondSwitch = !event.value;
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
}
|
||||
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchGroup ? event.deviceId : threeTouchId,
|
||||
code: 'switch_2',
|
||||
value: !event.value),
|
||||
threeTouchGroup ? event.deviceId : threeTouchId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||
}
|
||||
}
|
||||
|
||||
void _changeThirdSwitch(
|
||||
ChangeThirdSwitchStatusEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
try {
|
||||
if (threeTouchGroup) {
|
||||
bool allSwitchesValue = true;
|
||||
groupThreeTouchList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.thirdSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList,
|
||||
allSwitches: allSwitchesValue));
|
||||
} else {
|
||||
deviceStatus.thirdSwitch = !event.value;
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
}
|
||||
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchGroup ? event.deviceId : threeTouchId,
|
||||
code: 'switch_3',
|
||||
value: !event.value),
|
||||
threeTouchGroup ? event.deviceId : threeTouchId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: threeTouchGroup));
|
||||
}
|
||||
}
|
||||
|
||||
void _allOff(AllOffEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
|
||||
try {
|
||||
deviceStatus.firstSwitch = false;
|
||||
deviceStatus.secondSwitch = false;
|
||||
deviceStatus.thirdSwitch = false;
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
threeTouchId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: 'switch_2',
|
||||
value: deviceStatus.secondSwitch),
|
||||
threeTouchId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: 'switch_3',
|
||||
value: deviceStatus.thirdSwitch),
|
||||
threeTouchId),
|
||||
]);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
}
|
||||
}
|
||||
|
||||
void _allOn(AllOnEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
|
||||
try {
|
||||
deviceStatus.firstSwitch = true;
|
||||
deviceStatus.secondSwitch = true;
|
||||
deviceStatus.thirdSwitch = true;
|
||||
emit(UpdateState(threeTouchModel: deviceStatus));
|
||||
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
threeTouchId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: 'switch_2',
|
||||
value: deviceStatus.secondSwitch),
|
||||
threeTouchId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: 'switch_3',
|
||||
value: deviceStatus.thirdSwitch),
|
||||
threeTouchId),
|
||||
]);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOn(GroupAllOnEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
try {
|
||||
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||
groupThreeTouchList[i].firstSwitch = true;
|
||||
groupThreeTouchList[i].secondSwitch = true;
|
||||
groupThreeTouchList[i].thirdSwitch = true;
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList, allSwitches: true));
|
||||
|
||||
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeTouchList[i].deviceId,
|
||||
code: 'switch_1',
|
||||
value: true),
|
||||
groupThreeTouchList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeTouchList[i].deviceId,
|
||||
code: 'switch_2',
|
||||
value: true),
|
||||
groupThreeTouchList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeTouchList[i].deviceId,
|
||||
code: 'switch_3',
|
||||
value: true),
|
||||
groupThreeTouchList[i].deviceId),
|
||||
]);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOff(
|
||||
GroupAllOffEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingNewSate(threeTouchModel: deviceStatus));
|
||||
try {
|
||||
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||
groupThreeTouchList[i].firstSwitch = false;
|
||||
groupThreeTouchList[i].secondSwitch = false;
|
||||
groupThreeTouchList[i].thirdSwitch = false;
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList, allSwitches: false));
|
||||
|
||||
for (int i = 0; i < groupThreeTouchList.length; i++) {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeTouchList[i].deviceId,
|
||||
code: 'switch_1',
|
||||
value: false),
|
||||
groupThreeTouchList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeTouchList[i].deviceId,
|
||||
code: 'switch_2',
|
||||
value: false),
|
||||
groupThreeTouchList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeTouchList[i].deviceId,
|
||||
code: 'switch_3',
|
||||
value: false),
|
||||
groupThreeTouchList[i].deviceId),
|
||||
]);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSliding(
|
||||
ChangeSlidingSegment event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(ChangeSlidingSegmentState(value: event.value));
|
||||
}
|
||||
|
||||
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),
|
||||
threeTouchId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown = seconds;
|
||||
} else if (event.deviceCode == 'countdown_2') {
|
||||
deviceStatus.secondCountDown = seconds;
|
||||
} else if (event.deviceCode == 'countdown_3') {
|
||||
deviceStatus.thirdCountDown = seconds;
|
||||
}
|
||||
} else {
|
||||
emit(const FailedState(error: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
if (seconds > 0) {
|
||||
_onStartTimer(seconds);
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
void _getCounterValue(
|
||||
GetCounterEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(threeTouchId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = ThreeTouchModel.fromJson(statusModelList);
|
||||
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown > 0
|
||||
? _onStartTimer(deviceStatus.firstCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||
} else if (event.deviceCode == 'countdown_2') {
|
||||
deviceStatus.secondCountDown > 0
|
||||
? _onStartTimer(deviceStatus.secondCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.secondCountDown));
|
||||
} else if (event.deviceCode == 'countdown_3') {
|
||||
deviceStatus.thirdCountDown > 0
|
||||
? _onStartTimer(deviceStatus.thirdCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.thirdCountDown));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _onClose(OnClose event, Emitter<ThreeTouchState> emit) {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
void _onStartTimer(int seconds) {
|
||||
_timer?.cancel();
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
add(TickTimer(seconds - timer.tick));
|
||||
});
|
||||
}
|
||||
|
||||
void _onTickTimer(TickTimer event, Emitter<ThreeTouchState> emit) {
|
||||
if (event.remainingTime > 0) {
|
||||
emit(TimerRunInProgress(event.remainingTime));
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, String>> days = [
|
||||
{"day": "Sun", "key": "Sun"},
|
||||
{"day": "Mon", "key": "Mon"},
|
||||
{"day": "Tue", "key": "Tue"},
|
||||
{"day": "Wed", "key": "Wed"},
|
||||
{"day": "Thu", "key": "Thu"},
|
||||
{"day": "Fri", "key": "Fri"},
|
||||
{"day": "Sat", "key": "Sat"},
|
||||
];
|
||||
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<ThreeTouchState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
} else {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(
|
||||
ThreeTouchSave event,
|
||||
Emitter<ThreeTouchState> emit,
|
||||
) async {
|
||||
try {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: threeTouchId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
code: switchCode,
|
||||
value: toggleSchedule,
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(ThreeTouchSaveSchedule());
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<ThreeTouchState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: threeTouchId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(InitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
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 {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id, deviceUuid: threeTouchId, enable: event.toggle);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
toggleSchedule = event.toggle;
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: threeTouchId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<ThreeTouchState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<ThreeTouchState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
|
||||
String statusSelected = '';
|
||||
String optionSelected = '';
|
||||
|
||||
Future<void> _changeStatus(
|
||||
ChangeStatusEvent event, Emitter<ThreeTouchState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final Map<String, Map<String, String>> controlMap = {
|
||||
"relay_status": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
"light_mode": {
|
||||
'Off': 'none',
|
||||
'On/Off Status': 'relay',
|
||||
'Switch Position': 'pos',
|
||||
},
|
||||
"relay_status_1": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
"relay_status_2": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
"relay_status_3": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
};
|
||||
|
||||
final selectedControl = controlMap[optionSelected]?[statusSelected];
|
||||
if (selectedControl != null) {
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeTouchId,
|
||||
code: optionSelected,
|
||||
value: selectedControl),
|
||||
threeTouchId,
|
||||
);
|
||||
} else {
|
||||
print('Invalid statusSelected or optionSelected');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class ThreeTouchEvent extends Equatable {
|
||||
const ThreeTouchEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class LoadingEvent extends ThreeTouchEvent {}
|
||||
|
||||
class ThreeTouchUpdated extends ThreeTouchEvent {}
|
||||
|
||||
class InitialEvent extends ThreeTouchEvent {
|
||||
final bool groupScreen;
|
||||
const InitialEvent({required this.groupScreen});
|
||||
@override
|
||||
List<Object> get props => [groupScreen];
|
||||
}
|
||||
|
||||
class ChangeFirstSwitchStatusEvent extends ThreeTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeSecondSwitchStatusEvent extends ThreeTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSecondSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeThirdSwitchStatusEvent extends ThreeTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeThirdSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class AllOffEvent extends ThreeTouchEvent {}
|
||||
|
||||
class AllOnEvent extends ThreeTouchEvent {}
|
||||
|
||||
class GroupAllOnEvent extends ThreeTouchEvent {}
|
||||
|
||||
class GroupAllOffEvent extends ThreeTouchEvent {}
|
||||
|
||||
class ChangeSlidingSegment extends ThreeTouchEvent {
|
||||
final int value;
|
||||
const ChangeSlidingSegment({required this.value});
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class GetCounterEvent extends ThreeTouchEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
class SetCounterValue extends ThreeTouchEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends ThreeTouchEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends ThreeTouchEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends ThreeTouchEvent {}
|
||||
|
||||
class OnClose extends ThreeTouchEvent {}
|
||||
|
||||
//------------------- Schedule ----------=---------
|
||||
class GetScheduleEvent extends ThreeTouchEvent {}
|
||||
|
||||
class ThreeTouchSave extends ThreeTouchEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends ThreeTouchEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
|
||||
class ToggleDaySelectionEvent extends ThreeTouchEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@override
|
||||
List<Object> get props => [key];
|
||||
}
|
||||
|
||||
class DeleteScheduleEvent extends ThreeTouchEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends ThreeTouchEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends ThreeTouchEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class InitialWizardDevises extends ThreeTouchEvent {}
|
||||
|
||||
class ChangeStatusEvent extends ThreeTouchEvent {
|
||||
final String deviceId;
|
||||
final BuildContext context;
|
||||
const ChangeStatusEvent({this.deviceId = '', required this.context});
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_three_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||
|
||||
class ThreeTouchState extends Equatable {
|
||||
const ThreeTouchState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class InitialState extends ThreeTouchState {}
|
||||
|
||||
class LoadingInitialState extends ThreeTouchState {}
|
||||
|
||||
class UpdateState extends ThreeTouchState {
|
||||
final ThreeTouchModel threeTouchModel;
|
||||
const UpdateState({required this.threeTouchModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [threeTouchModel];
|
||||
}
|
||||
|
||||
class LoadingNewSate extends ThreeTouchState {
|
||||
final ThreeTouchModel threeTouchModel;
|
||||
const LoadingNewSate({required this.threeTouchModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [threeTouchModel];
|
||||
}
|
||||
|
||||
class UpdateGroupState extends ThreeTouchState {
|
||||
final List<GroupThreeTouchModel> threeTouchList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState(
|
||||
{required this.threeTouchList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [threeTouchList, allSwitches];
|
||||
}
|
||||
|
||||
class FailedState extends ThreeTouchState {
|
||||
final String error;
|
||||
|
||||
const FailedState({required this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class ChangeSlidingSegmentState extends ThreeTouchState {
|
||||
final int value;
|
||||
|
||||
const ChangeSlidingSegmentState({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class UpdateTimerState extends ThreeTouchState {
|
||||
final int seconds;
|
||||
const UpdateTimerState({required this.seconds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [seconds];
|
||||
}
|
||||
|
||||
class TimerRunInProgress extends ThreeTouchState {
|
||||
final int remainingTime;
|
||||
|
||||
const TimerRunInProgress(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class TimerRunComplete extends ThreeTouchState {}
|
||||
|
||||
class ThreeTouchSaveSchedule extends ThreeTouchState {}
|
||||
|
||||
class IsToggleState extends ThreeTouchState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
class ChangeTimeState extends ThreeTouchState {}
|
||||
|
||||
class UpdateCreateScheduleState extends ThreeTouchState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
||||
|
||||
class ChangeStateSetting extends ThreeTouchState {
|
||||
const ChangeStateSetting();
|
||||
}
|
@ -7,7 +7,7 @@ import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.d
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.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/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
@ -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);
|
||||
@ -54,75 +55,45 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleRepeat);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<InitialWizardEvent>(_fetchTwoGangWizardStatus);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
on<ChangeSecondWizardSwitchStatusEvent>(_changeSecondWizardSwitch);
|
||||
}
|
||||
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
emit(ChangeSlidingSegmentState(value: 1));
|
||||
}
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = index;
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void _fetchTwoGangStatus(InitialEvent event, Emitter<TwoGangState> emit) async {
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
void _fetchTwoGangStatus(
|
||||
InitialEvent event, Emitter<TwoGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
twoGangGroup = event.groupScreen;
|
||||
if (twoGangGroup) {
|
||||
devicesList = [];
|
||||
groupTwoGangList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoGangModel.fromJson(statusModelList);
|
||||
|
||||
groupTwoGangList.add(GroupTwoGangModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
secondSwitch: deviceStatus.secondSwitch,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupTwoGangList.isNotEmpty) {
|
||||
groupTwoGangList.firstWhere((element) {
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
|
||||
} else {
|
||||
var response = await DevicesAPI.getDeviceStatus(twoGangId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoGangModel.fromJson(statusModelList);
|
||||
emit(UpdateState(twoGangModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
var response = await DevicesAPI.getDeviceStatus(twoGangId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoGangModel.fromJson(statusModelList);
|
||||
emit(UpdateState(twoGangModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
@ -173,17 +144,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoGangGroup ? event.deviceId : twoGangId,
|
||||
code: 'switch_1',
|
||||
value: !event.value),
|
||||
twoGangGroup ? event.deviceId : twoGangId);
|
||||
deviceId: twoGangId, code: 'switch_1', value: !event.value),
|
||||
twoGangId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: twoGangGroup));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: twoGangGroup));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,17 +168,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoGangGroup ? event.deviceId : twoGangId,
|
||||
code: 'switch_2',
|
||||
value: !event.value),
|
||||
twoGangGroup ? event.deviceId : twoGangId);
|
||||
deviceId: twoGangId, code: 'switch_2', value: !event.value),
|
||||
twoGangId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(InitialEvent(groupScreen: twoGangGroup));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(InitialEvent(groupScreen: twoGangGroup));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,11 +205,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,11 +235,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
]);
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: false));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,32 +251,29 @@ 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();
|
||||
|
||||
for (int i = 0; i < groupTwoGangList.length; i++) {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupTwoGangList[i].deviceId,
|
||||
code: 'switch_1',
|
||||
value: true),
|
||||
groupTwoGangList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupTwoGangList[i].deviceId,
|
||||
code: 'switch_2',
|
||||
value: true),
|
||||
groupTwoGangList[i].deviceId),
|
||||
]);
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
break;
|
||||
}
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,33 +284,32 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
groupTwoGangList[i].firstSwitch = false;
|
||||
groupTwoGangList[i].secondSwitch = false;
|
||||
}
|
||||
|
||||
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: false));
|
||||
|
||||
for (int i = 0; i < groupTwoGangList.length; i++) {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupTwoGangList[i].deviceId,
|
||||
code: 'switch_1',
|
||||
value: false),
|
||||
groupTwoGangList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupTwoGangList[i].deviceId,
|
||||
code: 'switch_2',
|
||||
value: false),
|
||||
groupTwoGangList[i].deviceId),
|
||||
]);
|
||||
List<String> allDeviceIds =
|
||||
groupTwoGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
break;
|
||||
}
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,16 +326,13 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
seconds = event.duration.inSeconds;
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoGangId,
|
||||
code: event.deviceCode,
|
||||
value: seconds),
|
||||
deviceId: twoGangId, code: event.deviceCode, value: seconds),
|
||||
twoGangId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown = seconds;
|
||||
}
|
||||
else if (event.deviceCode == 'countdown_2') {
|
||||
} else if (event.deviceCode == 'countdown_2') {
|
||||
deviceStatus.secondCountDown = seconds;
|
||||
}
|
||||
} else {
|
||||
@ -459,14 +419,17 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(TwoGangSave event, Emitter<TwoGangState> emit,) async {
|
||||
Future<void> saveSchedule(
|
||||
TwoGangSave event,
|
||||
Emitter<TwoGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
if(selectedDays.isNotEmpty) {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.postSchedule(
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: twoGangId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
@ -476,8 +439,9 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(TwoGangSaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
}else{
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
// toggleCreateSchedule();
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
@ -485,7 +449,10 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(GetScheduleEvent event, Emitter<TwoGangState> emit,) async {
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<TwoGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
@ -493,7 +460,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;
|
||||
@ -514,9 +482,7 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: twoGangId,
|
||||
enable: event.toggle);
|
||||
scheduleId: event.id, deviceUuid: twoGangId, enable: event.toggle);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
toggleSchedule = event.toggle;
|
||||
@ -537,7 +503,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: twoGangId, );
|
||||
deviceUuid: twoGangId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
@ -550,4 +517,113 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _fetchTwoGangWizardStatus(
|
||||
InitialWizardEvent event, Emitter<TwoGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupTwoGangList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoGangModel.fromJson(statusModelList);
|
||||
|
||||
groupTwoGangList.add(GroupTwoGangModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
secondSwitch: deviceStatus.secondSwitch,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupTwoGangList.isNotEmpty) {
|
||||
groupTwoGangList.firstWhere((element) {
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<TwoGangState> emit) async {
|
||||
emit(LoadingNewSate(twoGangModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupTwoGangList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
emit(UpdateGroupState(
|
||||
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupTwoGangList.map((device) => device.deviceId).toList();
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: !event.value,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
|
||||
Emitter<TwoGangState> emit) async {
|
||||
emit(LoadingNewSate(twoGangModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupTwoGangList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.secondSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
List<String> allDeviceIds =
|
||||
groupTwoGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
emit(UpdateGroupState(
|
||||
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: !event.value,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,17 +10,20 @@ abstract class TwoGangEvent extends Equatable {
|
||||
class LoadingEvent extends TwoGangEvent {}
|
||||
|
||||
class TwoGangUpdated extends TwoGangEvent {}
|
||||
|
||||
class TwoGangSave extends TwoGangEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends TwoGangEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle,required this.id});
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle,id];
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
class errorMessage extends TwoGangEvent {}
|
||||
class ToggleDaySelectionEvent extends TwoGangEvent {
|
||||
|
||||
class errorMessage extends TwoGangEvent {}
|
||||
|
||||
class ToggleDaySelectionEvent extends TwoGangEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@ -29,10 +32,9 @@ class ToggleDaySelectionEvent extends TwoGangEvent {
|
||||
}
|
||||
|
||||
class InitialEvent extends TwoGangEvent {
|
||||
final bool groupScreen;
|
||||
const InitialEvent({required this.groupScreen});
|
||||
const InitialEvent();
|
||||
@override
|
||||
List<Object> get props => [groupScreen];
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ChangeFirstSwitchStatusEvent extends TwoGangEvent {
|
||||
@ -51,7 +53,6 @@ class ChangeSecondSwitchStatusEvent extends TwoGangEvent {
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
|
||||
class AllOffEvent extends TwoGangEvent {}
|
||||
|
||||
class AllOnEvent extends TwoGangEvent {}
|
||||
@ -60,12 +61,8 @@ class GroupAllOnEvent extends TwoGangEvent {}
|
||||
|
||||
class GroupAllOffEvent extends TwoGangEvent {}
|
||||
|
||||
|
||||
// two_gang_event.dart
|
||||
class ToggleCreateScheduleEvent extends TwoGangEvent {}
|
||||
|
||||
|
||||
|
||||
// class ToggleCreateScheduleEvent extends TwoGangEvent {}
|
||||
|
||||
class ChangeSlidingSegment extends TwoGangEvent {
|
||||
final int value;
|
||||
@ -111,20 +108,48 @@ class StopTimer extends TwoGangEvent {}
|
||||
|
||||
class OnClose extends TwoGangEvent {}
|
||||
|
||||
|
||||
class GetScheduleEvent extends TwoGangEvent {}
|
||||
|
||||
class DeleteScheduleEvent extends TwoGangEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class TabChangedEvent extends TwoGangEvent {
|
||||
final int index;
|
||||
TabChangedEvent({required this.index});
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends TwoGangEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends TwoGangEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class InitialWizardEvent extends TwoGangEvent {}
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends TwoGangEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeSecondWizardSwitchStatusEvent extends TwoGangEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSecondWizardSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
|
||||
|
||||
class TwoGangState extends Equatable {
|
||||
const TwoGangState();
|
||||
|
||||
@ -11,7 +10,9 @@ class TwoGangState extends Equatable {
|
||||
}
|
||||
|
||||
class InitialState extends TwoGangState {}
|
||||
|
||||
class TwoGangSaveSchedule extends TwoGangState {}
|
||||
|
||||
class ChangeTimeState extends TwoGangState {}
|
||||
|
||||
class LoadingInitialState extends TwoGangState {}
|
||||
@ -78,13 +79,12 @@ class TimerRunInProgress extends TwoGangState {
|
||||
}
|
||||
|
||||
class TimerRunComplete extends TwoGangState {}
|
||||
|
||||
class IsToggleState extends TwoGangState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// two_gang_state.dart
|
||||
class UpdateCreateScheduleState extends TwoGangState {
|
||||
final bool createSchedule;
|
||||
|
687
lib/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart
Normal file
@ -0,0 +1,687 @@
|
||||
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/app_layout/bloc/home_cubit.dart';
|
||||
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_state.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/group_two_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class TwoTouchBloc extends Bloc<TwoTouchEvent, TwoTouchState> {
|
||||
final String twoTouchId;
|
||||
final String switchCode;
|
||||
TwoTouchModel deviceStatus = TwoTouchModel(
|
||||
firstSwitch: false,
|
||||
secondSwitch: false,
|
||||
firstCountDown: 0,
|
||||
secondCountDown: 0,
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off,
|
||||
relay_status_2: status.off,
|
||||
);
|
||||
Timer? _timer;
|
||||
|
||||
bool twoTouchGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
List<GroupTwoTouchModel> groupTwoTouchList = [];
|
||||
bool allSwitchesOn = true;
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
|
||||
TwoTouchBloc({required this.twoTouchId, required this.switchCode})
|
||||
: super(InitialState()) {
|
||||
on<InitialEvent>(_fetchTwoTouchStatus);
|
||||
on<TwoTouchUpdated>(_twoTouchUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
on<ChangeSecondSwitchStatusEvent>(_changeSecondSwitch);
|
||||
on<AllOffEvent>(_allOff);
|
||||
on<AllOnEvent>(_allOn);
|
||||
on<ChangeSlidingSegment>(_changeSliding);
|
||||
on<SetCounterValue>(_setCounterValue);
|
||||
on<GetCounterEvent>(_getCounterValue);
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<TwoTouchSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleRepeat);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<InitialWizardEvent>(_fetchTwoTouchWizardStatus);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
on<ChangeSecondWizardSwitchStatusEvent>(_changeSecondWizardSwitch);
|
||||
on<ChangeStatusEvent>(_changeStatus);
|
||||
}
|
||||
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<TwoTouchState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<TwoTouchState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
void _fetchTwoTouchStatus(
|
||||
InitialEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(twoTouchId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoTouchModel.fromJson(statusModelList);
|
||||
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$twoTouchId');
|
||||
Stream<DatabaseEvent> stream = ref.onValue;
|
||||
|
||||
stream.listen((DatabaseEvent event) async {
|
||||
if (_timer != null) {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
}
|
||||
Map<dynamic, dynamic> usersMap =
|
||||
event.snapshot.value as Map<dynamic, dynamic>;
|
||||
List<StatusModel> statusList = [];
|
||||
|
||||
usersMap['status'].forEach((element) {
|
||||
statusList
|
||||
.add(StatusModel(code: element['code'], value: element['value']));
|
||||
});
|
||||
|
||||
deviceStatus = TwoTouchModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
add(TwoTouchUpdated());
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
_twoTouchUpdated(TwoTouchUpdated event, Emitter<TwoTouchState> emit) {
|
||||
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||
}
|
||||
|
||||
void _changeFirstSwitch(
|
||||
ChangeFirstSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
deviceStatus.firstSwitch = !event.value;
|
||||
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId, code: 'switch_1', value: !event.value),
|
||||
twoTouchId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(const InitialEvent());
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSecondSwitch(
|
||||
ChangeSecondSwitchStatusEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
deviceStatus.secondSwitch = !event.value;
|
||||
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId, code: 'switch_2', value: !event.value),
|
||||
twoTouchId);
|
||||
|
||||
if (!response['success']) {
|
||||
add(const InitialEvent());
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _allOff(AllOffEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
|
||||
try {
|
||||
deviceStatus.firstSwitch = false;
|
||||
deviceStatus.secondSwitch = false;
|
||||
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
twoTouchId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId,
|
||||
code: 'switch_2',
|
||||
value: deviceStatus.secondSwitch),
|
||||
twoTouchId),
|
||||
]);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _allOn(AllOnEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
deviceStatus.firstSwitch = true;
|
||||
deviceStatus.secondSwitch = true;
|
||||
emit(UpdateState(twoTouchModel: deviceStatus));
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
twoTouchId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId,
|
||||
code: 'switch_2',
|
||||
value: deviceStatus.secondSwitch),
|
||||
twoTouchId),
|
||||
]);
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOn(GroupAllOnEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
for (int i = 0; i < groupTwoTouchList.length; i++) {
|
||||
groupTwoTouchList[i].firstSwitch = true;
|
||||
groupTwoTouchList[i].secondSwitch = true;
|
||||
}
|
||||
emit(
|
||||
UpdateGroupState(twoTouchList: groupTwoTouchList, allSwitches: true));
|
||||
List<String> allDeviceIds =
|
||||
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOff(GroupAllOffEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
for (int i = 0; i < groupTwoTouchList.length; i++) {
|
||||
groupTwoTouchList[i].firstSwitch = false;
|
||||
groupTwoTouchList[i].secondSwitch = false;
|
||||
}
|
||||
|
||||
emit(UpdateGroupState(
|
||||
twoTouchList: groupTwoTouchList, allSwitches: false));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSliding(
|
||||
ChangeSlidingSegment event, Emitter<TwoTouchState> emit) async {
|
||||
emit(ChangeSlidingSegmentState(value: event.value));
|
||||
}
|
||||
|
||||
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),
|
||||
twoTouchId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown = seconds;
|
||||
} else if (event.deviceCode == 'countdown_2') {
|
||||
deviceStatus.secondCountDown = seconds;
|
||||
}
|
||||
} else {
|
||||
emit(const FailedState(error: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
if (seconds > 0) {
|
||||
_onStartTimer(seconds);
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
void _getCounterValue(
|
||||
GetCounterEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
add(GetScheduleEvent());
|
||||
var response = await DevicesAPI.getDeviceStatus(twoTouchId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoTouchModel.fromJson(statusModelList);
|
||||
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown > 0
|
||||
? _onStartTimer(deviceStatus.firstCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||
} else if (event.deviceCode == 'countdown_2') {
|
||||
deviceStatus.secondCountDown > 0
|
||||
? _onStartTimer(deviceStatus.secondCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.secondCountDown));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _onClose(OnClose event, Emitter<TwoTouchState> emit) {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
void _onStartTimer(int seconds) {
|
||||
_timer?.cancel();
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
add(TickTimer(seconds - timer.tick));
|
||||
});
|
||||
}
|
||||
|
||||
void _onTickTimer(TickTimer event, Emitter<TwoTouchState> emit) {
|
||||
if (event.remainingTime > 0) {
|
||||
emit(TimerRunInProgress(event.remainingTime));
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, String>> days = [
|
||||
{"day": "Sun", "key": "Sun"},
|
||||
{"day": "Mon", "key": "Mon"},
|
||||
{"day": "Tue", "key": "Tue"},
|
||||
{"day": "Wed", "key": "Wed"},
|
||||
{"day": "Thu", "key": "Thu"},
|
||||
{"day": "Fri", "key": "Fri"},
|
||||
{"day": "Sat", "key": "Sat"},
|
||||
];
|
||||
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<TwoTouchState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
} else {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(
|
||||
TwoTouchSave event,
|
||||
Emitter<TwoTouchState> emit,
|
||||
) async {
|
||||
try {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: twoTouchId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
code: switchCode,
|
||||
value: toggleSchedule,
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(TwoTouchSaveSchedule());
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
// toggleCreateSchedule();
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<TwoTouchState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: twoTouchId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(InitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
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 {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id, deviceUuid: twoTouchId, enable: event.toggle);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
toggleSchedule = event.toggle;
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<TwoTouchState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: twoTouchId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
add(const ChangeSlidingSegment(value: 1));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _fetchTwoTouchWizardStatus(
|
||||
InitialWizardEvent event, Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupTwoTouchList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '2GT');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = TwoTouchModel.fromJson(statusModelList);
|
||||
|
||||
groupTwoTouchList.add(GroupTwoTouchModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
secondSwitch: deviceStatus.secondSwitch,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupTwoTouchList.isNotEmpty) {
|
||||
groupTwoTouchList.firstWhere((element) {
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupTwoTouchList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
emit(UpdateGroupState(
|
||||
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: !event.value,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
|
||||
Emitter<TwoTouchState> emit) async {
|
||||
emit(LoadingNewSate(twoTouchModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupTwoTouchList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.secondSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
List<String> allDeviceIds =
|
||||
groupTwoTouchList.map((device) => device.deviceId).toList();
|
||||
|
||||
emit(UpdateGroupState(
|
||||
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: !event.value,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
String statusSelected = '';
|
||||
String optionSelected = '';
|
||||
|
||||
Future<void> _changeStatus(
|
||||
ChangeStatusEvent event, Emitter<TwoTouchState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final Map<String, Map<String, String>> controlMap = {
|
||||
"relay_status": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
"light_mode": {
|
||||
'Off': 'none',
|
||||
'On/Off Status': 'relay',
|
||||
'Switch Position': 'pos',
|
||||
},
|
||||
"relay_status_1": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
"relay_status_2": {
|
||||
'Power On': 'power_on',
|
||||
'Power Off': 'power_off',
|
||||
'Restart Memory': 'last',
|
||||
},
|
||||
};
|
||||
|
||||
final selectedControl = controlMap[optionSelected]?[statusSelected];
|
||||
if (selectedControl != null) {
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoTouchId,
|
||||
code: optionSelected,
|
||||
value: selectedControl),
|
||||
twoTouchId,
|
||||
);
|
||||
} else {
|
||||
print('Invalid statusSelected or optionSelected');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(FailedState(error: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
}
|
162
lib/features/devices/bloc/two_touch_bloc/two_touch_event.dart
Normal file
@ -0,0 +1,162 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class TwoTouchEvent extends Equatable {
|
||||
const TwoTouchEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class LoadingEvent extends TwoTouchEvent {}
|
||||
|
||||
class TwoTouchUpdated extends TwoTouchEvent {}
|
||||
|
||||
class TwoTouchSave extends TwoTouchEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends TwoTouchEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
|
||||
class errorMessage extends TwoTouchEvent {}
|
||||
|
||||
class ToggleDaySelectionEvent extends TwoTouchEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@override
|
||||
List<Object> get props => [key];
|
||||
}
|
||||
|
||||
class InitialEvent extends TwoTouchEvent {
|
||||
const InitialEvent();
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ChangeFirstSwitchStatusEvent extends TwoTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeSecondSwitchStatusEvent extends TwoTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSecondSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class AllOffEvent extends TwoTouchEvent {}
|
||||
|
||||
class AllOnEvent extends TwoTouchEvent {}
|
||||
|
||||
class GroupAllOnEvent extends TwoTouchEvent {}
|
||||
|
||||
class GroupAllOffEvent extends TwoTouchEvent {}
|
||||
|
||||
|
||||
class ChangeSlidingSegment extends TwoTouchEvent {
|
||||
final int value;
|
||||
const ChangeSlidingSegment({required this.value});
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class GetCounterEvent extends TwoTouchEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
class SetCounterValue extends TwoTouchEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends TwoTouchEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends TwoTouchEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends TwoTouchEvent {}
|
||||
|
||||
class OnClose extends TwoTouchEvent {}
|
||||
|
||||
class GetScheduleEvent extends TwoTouchEvent {}
|
||||
|
||||
class DeleteScheduleEvent extends TwoTouchEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class TabChangedEvent extends TwoTouchEvent {
|
||||
final int index;
|
||||
TabChangedEvent({required this.index});
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends TwoTouchEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends TwoTouchEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class InitialWizardEvent extends TwoTouchEvent {}
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends TwoTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeSecondWizardSwitchStatusEvent extends TwoTouchEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSecondWizardSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
class ChangeStatusEvent extends TwoTouchEvent {
|
||||
final String deviceId;
|
||||
final BuildContext context;
|
||||
const ChangeStatusEvent({this.deviceId = '',required this.context});
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||
|
||||
class TwoTouchState extends Equatable {
|
||||
const TwoTouchState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class InitialState extends TwoTouchState {}
|
||||
|
||||
class TwoTouchSaveSchedule extends TwoTouchState {}
|
||||
|
||||
class ChangeTimeState extends TwoTouchState {}
|
||||
|
||||
class LoadingInitialState extends TwoTouchState {}
|
||||
|
||||
class UpdateState extends TwoTouchState {
|
||||
final TwoTouchModel twoTouchModel;
|
||||
const UpdateState({required this.twoTouchModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [TwoTouchModel];
|
||||
}
|
||||
|
||||
class LoadingNewSate extends TwoTouchState {
|
||||
final TwoTouchModel twoTouchModel;
|
||||
const LoadingNewSate({required this.twoTouchModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [TwoTouchModel];
|
||||
}
|
||||
|
||||
class UpdateGroupState extends TwoTouchState {
|
||||
final List<GroupTwoTouchModel> twoTouchList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState({required this.twoTouchList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [twoTouchList, allSwitches];
|
||||
}
|
||||
|
||||
class FailedState extends TwoTouchState {
|
||||
final String error;
|
||||
|
||||
const FailedState({required this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
}
|
||||
|
||||
class ChangeSlidingSegmentState extends TwoTouchState {
|
||||
final int value;
|
||||
|
||||
const ChangeSlidingSegmentState({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class UpdateTimerState extends TwoTouchState {
|
||||
final int seconds;
|
||||
const UpdateTimerState({required this.seconds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [seconds];
|
||||
}
|
||||
|
||||
class TimerRunInProgress extends TwoTouchState {
|
||||
final int remainingTime;
|
||||
|
||||
const TimerRunInProgress(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class TimerRunComplete extends TwoTouchState {}
|
||||
|
||||
class IsToggleState extends TwoTouchState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
class UpdateCreateScheduleState extends TwoTouchState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
@ -0,0 +1,518 @@
|
||||
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/devices/bloc/water_heater_bloc/water_heater_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/GroupWHModel.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/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/water_heater.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
final String whId;
|
||||
final String switchCode;
|
||||
WHModel deviceStatus = WHModel(firstSwitch: false, firstCountDown: 0);
|
||||
List<WHModel> deviceStatusList = [];
|
||||
List<DeviceModel> devicesList = [];
|
||||
bool allAcsPage = false;
|
||||
bool allAcsOn = true;
|
||||
bool allTempSame = true;
|
||||
int globalTemp = 25;
|
||||
Timer? _timer;
|
||||
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
bool createCirculate = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
|
||||
WaterHeaterBloc({required this.whId, required this.switchCode})
|
||||
: super(WHInitialState()) {
|
||||
on<WaterHeaterInitial>(_fetchWaterHeaterStatus);
|
||||
on<WaterHeaterSwitch>(_changeFirstSwitch);
|
||||
on<SetCounterValue>(_setCounterValue);
|
||||
on<GetCounterEvent>(_getCounterValue);
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ScheduleSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
on<SelectTimeEvent>(showTime);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<InitialWizardEvent>(_fetchWHWizardStatus);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
on<ToggleCreateCirculate>(_toggleCreateCirculate);
|
||||
on<WaterHeaterUpdated>(_waterHeaterUpdated);
|
||||
}
|
||||
|
||||
void _fetchWaterHeaterStatus(
|
||||
WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(WHLoadingState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(whId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = WHModel.fromJson(
|
||||
statusModelList,
|
||||
);
|
||||
emit(UpdateState(whModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(WHFailedState(errorMessage: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$whId');
|
||||
Stream<DatabaseEvent> stream = ref.onValue;
|
||||
|
||||
stream.listen((DatabaseEvent event) async {
|
||||
if (_timer != null) {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
}
|
||||
Map<dynamic, dynamic> usersMap =
|
||||
event.snapshot.value as Map<dynamic, dynamic>;
|
||||
List<StatusModel> statusList = [];
|
||||
|
||||
usersMap['status'].forEach((element) {
|
||||
statusList
|
||||
.add(StatusModel(code: element['code'], value: element['value']));
|
||||
});
|
||||
|
||||
deviceStatus = WHModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
add(WaterHeaterUpdated());
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
_waterHeaterUpdated(
|
||||
WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(WHLoadingState());
|
||||
emit(UpdateState(whModel: deviceStatus));
|
||||
}
|
||||
|
||||
void _changeFirstSwitch(
|
||||
WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(LoadingNewSate(whModel: deviceStatus));
|
||||
try {
|
||||
deviceStatus.firstSwitch = !event.whSwitch;
|
||||
emit(UpdateState(whModel: deviceStatus));
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: whId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
whId);
|
||||
|
||||
if (!response['success']) {
|
||||
// add(InitialEvent(groupScreen: oneGangGroup));
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
emit(WHFailedState(errorMessage: _.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
//=====================---------- timer ----------------------------------------
|
||||
|
||||
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);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown = seconds;
|
||||
}
|
||||
} else {
|
||||
emit(const WHFailedState(errorMessage: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const WHFailedState(errorMessage: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
if (seconds > 0) {
|
||||
_onStartTimer(seconds);
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
void _getCounterValue(
|
||||
GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(WHLoadingState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(whId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = WHModel.fromJson(statusModelList);
|
||||
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown > 0
|
||||
? _onStartTimer(deviceStatus.firstCountDown)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.firstCountDown));
|
||||
}
|
||||
} catch (e) {
|
||||
WHFailedState(errorMessage: e.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _onClose(OnClose event, Emitter<WaterHeaterState> emit) {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
void _onStartTimer(int seconds) {
|
||||
_timer?.cancel();
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
add(TickTimer(seconds - timer.tick));
|
||||
});
|
||||
}
|
||||
|
||||
void _onTickTimer(TickTimer event, Emitter<WaterHeaterState> emit) {
|
||||
if (event.remainingTime > 0) {
|
||||
emit(TimerRunInProgress(event.remainingTime));
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
//=====================---------- Schedule ----------------------------------------
|
||||
|
||||
List<Map<String, String>> days = [
|
||||
{"day": "Sun", "key": "Sun"},
|
||||
{"day": "Mon", "key": "Mon"},
|
||||
{"day": "Tue", "key": "Tue"},
|
||||
{"day": "Wed", "key": "Wed"},
|
||||
{"day": "Thu", "key": "Thu"},
|
||||
{"day": "Fri", "key": "Fri"},
|
||||
{"day": "Sat", "key": "Sat"},
|
||||
];
|
||||
|
||||
Future<void> saveSchedule(
|
||||
ScheduleSave event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
try {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(WHLoadingState());
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: whId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
code: switchCode,
|
||||
value: toggleSchedule,
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(SaveSchedule());
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
emit(WHFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(WHLoadingState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: whId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(WHInitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(WHFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
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 {
|
||||
try {
|
||||
emit(WHLoadingState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id, deviceUuid: whId, enable: event.toggle);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
toggleSchedule = event.toggle;
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(WHFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
try {
|
||||
emit(WHLoadingState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: whId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
}
|
||||
emit(IsToggleState(onOff: toggleSchedule));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(WHFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleCreateCirculate(
|
||||
ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
|
||||
emit(WHLoadingState());
|
||||
createCirculate = !createCirculate;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createCirculate));
|
||||
}
|
||||
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
|
||||
emit(WHLoadingState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
|
||||
emit(WHLoadingState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
emit(WHLoadingState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
} else {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
}
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
showTime(SelectTimeEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
await showTimePicker(
|
||||
context: event.context,
|
||||
initialTime: TimeOfDay.now(),
|
||||
builder: (context, child) {
|
||||
return Theme(
|
||||
data: ThemeData.light().copyWith(
|
||||
colorScheme: const ColorScheme.light(
|
||||
primary: ColorsManager.primaryColor,
|
||||
onSurface: Colors.black,
|
||||
),
|
||||
buttonTheme: const ButtonThemeData(
|
||||
colorScheme: ColorScheme.light(
|
||||
primary: Colors.green,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child!,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<GroupWHModel> groupWaterHeaterList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<WaterHeaterState> emit) async {
|
||||
emit(LoadingNewSate(whModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupWaterHeaterList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(
|
||||
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: [event.deviceId],
|
||||
value: !event.value,
|
||||
);
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void _fetchWHWizardStatus(
|
||||
InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(WHLoadingState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupWaterHeaterList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', 'WH');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = WHModel.fromJson(statusModelList);
|
||||
|
||||
groupWaterHeaterList.add(GroupWHModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.firstSwitch,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupWaterHeaterList.isNotEmpty) {
|
||||
groupWaterHeaterList.firstWhere((element) {
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(
|
||||
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
// emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupWaterHeaterList.map((device) => device.deviceId).toList();
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
List<String> allDeviceIds =
|
||||
groupWaterHeaterList.map((device) => device.deviceId).toList();
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
if (response['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(InitialWizardEvent());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class WaterHeaterEvent extends Equatable {
|
||||
const WaterHeaterEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class WaterHeaterLoading extends WaterHeaterEvent {}
|
||||
|
||||
class WaterHeaterSwitch extends WaterHeaterEvent {
|
||||
final bool whSwitch;
|
||||
final String deviceId;
|
||||
final String productId;
|
||||
const WaterHeaterSwitch({required this.whSwitch, this.deviceId = '', this.productId = ''});
|
||||
|
||||
@override
|
||||
List<Object> get props => [whSwitch, deviceId, productId];
|
||||
}
|
||||
|
||||
class WaterHeaterUpdated extends WaterHeaterEvent {}
|
||||
|
||||
class WaterHeaterInitial extends WaterHeaterEvent {
|
||||
const WaterHeaterInitial();
|
||||
}
|
||||
|
||||
class WaterHeaterChangeStatus extends WaterHeaterEvent {}
|
||||
|
||||
class GetCounterEvent extends WaterHeaterEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
class SetCounterValue extends WaterHeaterEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends WaterHeaterEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends WaterHeaterEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends WaterHeaterEvent {}
|
||||
|
||||
class OnClose extends WaterHeaterEvent {}
|
||||
|
||||
//------------------- Schedule ----------=---------
|
||||
class GetScheduleEvent extends WaterHeaterEvent {}
|
||||
|
||||
class ScheduleSave extends WaterHeaterEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends WaterHeaterEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
|
||||
class ToggleDaySelectionEvent extends WaterHeaterEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@override
|
||||
List<Object> get props => [key];
|
||||
}
|
||||
|
||||
class DeleteScheduleEvent extends WaterHeaterEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class SelectTimeEvent extends WaterHeaterEvent {
|
||||
final BuildContext context;
|
||||
final bool isEffective;
|
||||
const SelectTimeEvent({required this.context, required this.isEffective});
|
||||
@override
|
||||
List<Object> get props => [context, isEffective];
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateCirculateEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
const ToggleCreateCirculateEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class InitialWizardEvent extends WaterHeaterEvent {}
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends WaterHeaterEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class GroupAllOnEvent extends WaterHeaterEvent {}
|
||||
|
||||
class GroupAllOffEvent extends WaterHeaterEvent {}
|
||||
|
||||
class ToggleCreateCirculate extends WaterHeaterEvent {}
|
@ -0,0 +1,122 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/GroupWHModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/water_heater.dart';
|
||||
|
||||
abstract class WaterHeaterState extends Equatable {
|
||||
const WaterHeaterState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class WHInitialState extends WaterHeaterState {}
|
||||
|
||||
class WHLoadingState extends WaterHeaterState {}
|
||||
|
||||
class WHChangeLoading extends WaterHeaterState {
|
||||
const WHChangeLoading(
|
||||
);
|
||||
}
|
||||
|
||||
class WHModifyingState extends WaterHeaterState {
|
||||
final WHModel whStatusModel;
|
||||
const WHModifyingState({required this.whStatusModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [whStatusModel];
|
||||
}
|
||||
|
||||
class GetWHStatusState extends WaterHeaterState {
|
||||
final WHModel whStatusModel;
|
||||
const GetWHStatusState({required this.whStatusModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [whStatusModel];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class WHFailedState extends WaterHeaterState {
|
||||
final String errorMessage;
|
||||
|
||||
const WHFailedState({required this.errorMessage});
|
||||
|
||||
@override
|
||||
List<Object> get props => [errorMessage];
|
||||
}
|
||||
|
||||
|
||||
class LoadingNewSate extends WaterHeaterState {
|
||||
final WHModel whModel;
|
||||
const LoadingNewSate({required this.whModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [whModel];
|
||||
}
|
||||
class TimerRunComplete extends WaterHeaterState {}
|
||||
class UpdateTimerState extends WaterHeaterState {
|
||||
final int seconds;
|
||||
const UpdateTimerState({required this.seconds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [seconds];
|
||||
}
|
||||
|
||||
class TimerRunInProgress extends WaterHeaterState {
|
||||
final int remainingTime;
|
||||
|
||||
const TimerRunInProgress(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class SaveSchedule extends WaterHeaterState {}
|
||||
class ChangeTimeState extends WaterHeaterState {}
|
||||
class UpdateCreateScheduleState extends WaterHeaterState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
||||
class IsToggleState extends WaterHeaterState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
|
||||
class UpdateState extends WaterHeaterState {
|
||||
final WHModel whModel;
|
||||
const UpdateState({required this.whModel});
|
||||
|
||||
@override
|
||||
List<Object> get props => [WHModel];
|
||||
}
|
||||
|
||||
class ChangeSwitchStatusEvent extends WaterHeaterState {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class ChangeSlidingSegmentState extends WaterHeaterState {
|
||||
final int value;
|
||||
|
||||
const ChangeSlidingSegmentState({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class UpdateGroupState extends WaterHeaterState {
|
||||
final List<GroupWHModel> twoGangList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState({required this.twoGangList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [twoGangList, allSwitches];
|
||||
}
|
11
lib/features/devices/model/GroupWHModel.dart
Normal file
@ -0,0 +1,11 @@
|
||||
class GroupWHModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
|
||||
GroupWHModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
});
|
||||
}
|
@ -42,7 +42,9 @@ class DevicesCategoryModel {
|
||||
: name = json['groupName'],
|
||||
// id = json['groupId'],
|
||||
type = devicesTypesMap[json['groupName']] ?? DeviceType.Other,
|
||||
icon = deviceTypeIconMap[devicesTypesMap[json['groupName']] ?? DeviceType.Other] ?? '',
|
||||
icon = deviceTypeIconMap[
|
||||
devicesTypesMap[json['groupName']] ?? DeviceType.Other] ??
|
||||
'',
|
||||
devices = [],
|
||||
isSelected = false;
|
||||
|
||||
@ -60,5 +62,12 @@ Map<DeviceType, String> deviceTypeIconMap = {
|
||||
DeviceType.CeilingSensor: Assets.assetsIconsSensors,
|
||||
DeviceType.WallSensor: Assets.assetsIconsSensors,
|
||||
DeviceType.ThreeGang: Assets.assetsIconsGang,
|
||||
DeviceType.OneGang: Assets.oneGang,
|
||||
DeviceType.TwoGang: Assets.twoGang,
|
||||
DeviceType.WH: Assets.waterHeaterIcon,
|
||||
DeviceType.DS: Assets.doorSensorIcon,
|
||||
DeviceType.Other: Assets.assetsIconsAC,
|
||||
DeviceType.OneTouch: Assets.oneGang,
|
||||
DeviceType.TowTouch: Assets.twoGang,
|
||||
DeviceType.ThreeTouch: Assets.assetsIconsGang,
|
||||
};
|
||||
|
@ -62,9 +62,20 @@ class DeviceModel {
|
||||
tempIcon = Assets.oneGang;
|
||||
} else if (type == DeviceType.TwoGang) {
|
||||
tempIcon = Assets.twoGang;
|
||||
} else if (type == DeviceType.WH) {
|
||||
tempIcon = Assets.waterHeaterIcon;
|
||||
} else if (type == DeviceType.DS) {
|
||||
tempIcon = Assets.doorSensorIcon;
|
||||
} else if (type == DeviceType.OneTouch) {
|
||||
tempIcon = Assets.oneGang;
|
||||
} else if (type == DeviceType.TowTouch) {
|
||||
tempIcon = Assets.twoGang;
|
||||
} else if (type == DeviceType.ThreeTouch) {
|
||||
tempIcon = Assets.assetsIcons3GangSwitch;
|
||||
} else {
|
||||
tempIcon = Assets.assetsIconsLogo;
|
||||
}
|
||||
|
||||
return DeviceModel(
|
||||
icon: tempIcon,
|
||||
activeTime: json['activeTime'],
|
||||
|
51
lib/features/devices/model/device_report_model.dart
Normal file
@ -0,0 +1,51 @@
|
||||
class DeviceReport {
|
||||
final dynamic deviceUuid;
|
||||
final dynamic startTime;
|
||||
final dynamic endTime;
|
||||
final List<DeviceEvent>? data;
|
||||
|
||||
DeviceReport({
|
||||
this.deviceUuid,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.data,
|
||||
});
|
||||
|
||||
DeviceReport.fromJson(Map<String, dynamic> json)
|
||||
: deviceUuid = json['deviceUuid'] as String?,
|
||||
startTime = json['startTime'] as String?,
|
||||
endTime = json['endTime'] as String?,
|
||||
data = (json['data'] as List<dynamic>?)
|
||||
?.map((e) => DeviceEvent.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'deviceUuid': deviceUuid,
|
||||
'startTime': startTime,
|
||||
'endTime': endTime,
|
||||
'data': data?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
class DeviceEvent {
|
||||
final String? code;
|
||||
final int? eventTime;
|
||||
final String? value;
|
||||
|
||||
DeviceEvent({
|
||||
this.code,
|
||||
this.eventTime,
|
||||
this.value,
|
||||
});
|
||||
|
||||
DeviceEvent.fromJson(Map<String, dynamic> json)
|
||||
: code = json['code'] as String?,
|
||||
eventTime = json['eventTime'] as int?,
|
||||
value = json['value'] as String?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'code': code,
|
||||
'eventTime': eventTime,
|
||||
'value': value,
|
||||
};
|
||||
}
|
33
lib/features/devices/model/door_sensor_model.dart
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
|
||||
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
|
||||
class DoorSensorModel {
|
||||
bool doorContactState;
|
||||
int batteryPercentage;
|
||||
|
||||
DoorSensorModel(
|
||||
{required this.doorContactState,
|
||||
required this.batteryPercentage,
|
||||
});
|
||||
|
||||
factory DoorSensorModel.fromJson(List<StatusModel> jsonList) {
|
||||
late bool _doorContactState;
|
||||
late int _batteryPercentage;
|
||||
|
||||
|
||||
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') {
|
||||
_batteryPercentage = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return DoorSensorModel(
|
||||
doorContactState: _doorContactState,
|
||||
batteryPercentage: _batteryPercentage,
|
||||
);
|
||||
}
|
||||
}
|
11
lib/features/devices/model/group_one_gang_model.dart
Normal file
@ -0,0 +1,11 @@
|
||||
class GroupOneGangModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
|
||||
GroupOneGangModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
});
|
||||
}
|
11
lib/features/devices/model/group_one_touch_model.dart
Normal file
@ -0,0 +1,11 @@
|
||||
class GroupOneTouchModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
|
||||
GroupOneTouchModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
});
|
||||
}
|
15
lib/features/devices/model/group_three_touch_model.dart
Normal file
@ -0,0 +1,15 @@
|
||||
class GroupThreeTouchModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
bool secondSwitch;
|
||||
bool thirdSwitch;
|
||||
|
||||
GroupThreeTouchModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
required this.secondSwitch,
|
||||
required this.thirdSwitch,
|
||||
});
|
||||
}
|
13
lib/features/devices/model/group_two_touch_model.dart
Normal file
@ -0,0 +1,13 @@
|
||||
class GroupTwoTouchModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
bool secondSwitch;
|
||||
|
||||
GroupTwoTouchModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
required this.secondSwitch,
|
||||
});
|
||||
}
|
50
lib/features/devices/model/one_touch_model.dart
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class OneTouchModel {
|
||||
bool firstSwitch;
|
||||
int firstCountDown;
|
||||
status relay;
|
||||
lightStatus light_mode;
|
||||
status relay_status_1;
|
||||
|
||||
OneTouchModel(
|
||||
{required this.firstSwitch,
|
||||
required this.firstCountDown,
|
||||
required this.light_mode,
|
||||
required this.relay,
|
||||
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;
|
||||
|
||||
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') {
|
||||
_count = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status') {
|
||||
_relay = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'light_mode') {
|
||||
_light_mode = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status_1') {
|
||||
relay_status_1 = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return OneTouchModel(
|
||||
firstSwitch: _switch,
|
||||
firstCountDown: _count,
|
||||
light_mode: lightStatusExtension.fromString(_light_mode) ,
|
||||
relay: StatusExtension.fromString(_relay ) ,
|
||||
relay_status_1: StatusExtension.fromString(relay_status_1 )
|
||||
|
||||
);
|
||||
}
|
||||
}
|
23
lib/features/devices/model/report_model.dart
Normal file
@ -0,0 +1,23 @@
|
||||
// Record model
|
||||
class Record {
|
||||
final String status;
|
||||
final String time;
|
||||
final bool isOpen;
|
||||
|
||||
Record({
|
||||
required this.status,
|
||||
required this.time,
|
||||
required this.isOpen,
|
||||
});
|
||||
}
|
||||
|
||||
// RecordGroup model to group records by date
|
||||
class RecordGroup {
|
||||
final DateTime date;
|
||||
final List<Record> records;
|
||||
|
||||
RecordGroup({
|
||||
required this.date,
|
||||
required this.records,
|
||||
});
|
||||
}
|
81
lib/features/devices/model/three_touch_model.dart
Normal file
@ -0,0 +1,81 @@
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class ThreeTouchModel {
|
||||
bool firstSwitch;
|
||||
bool secondSwitch;
|
||||
bool thirdSwitch;
|
||||
int firstCountDown;
|
||||
int secondCountDown;
|
||||
int thirdCountDown;
|
||||
status relay;
|
||||
lightStatus light_mode;
|
||||
status relay_status_1;
|
||||
status relay_status_2;
|
||||
status relay_status_3;
|
||||
|
||||
ThreeTouchModel(
|
||||
{required this.firstSwitch,
|
||||
required this.secondSwitch,
|
||||
required this.thirdSwitch,
|
||||
required this.firstCountDown,
|
||||
required this.secondCountDown,
|
||||
required this.thirdCountDown,
|
||||
required this.light_mode,
|
||||
required this.relay,
|
||||
required this.relay_status_1,
|
||||
required this.relay_status_2,
|
||||
required this.relay_status_3});
|
||||
|
||||
factory ThreeTouchModel.fromJson(List<StatusModel> jsonList) {
|
||||
late bool _firstSwitch;
|
||||
late bool _secondSwitch;
|
||||
late bool _thirdSwitch;
|
||||
late int _firstCount;
|
||||
late int _secondCount;
|
||||
late int _thirdCount;
|
||||
late String _relay;
|
||||
late String _light_mode;
|
||||
late String _relay_status_1;
|
||||
late String _relay_status_2;
|
||||
late String _relay_status_3;
|
||||
|
||||
for (int i = 0; i < jsonList.length; i++) {
|
||||
if (jsonList[i].code == 'switch_1') {
|
||||
_firstSwitch = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'switch_2') {
|
||||
_secondSwitch = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'switch_3') {
|
||||
_thirdSwitch = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'countdown_1') {
|
||||
_firstCount = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'countdown_2') {
|
||||
_secondCount = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'countdown_3') {
|
||||
_thirdCount = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status') {
|
||||
_relay = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'light_mode') {
|
||||
_light_mode = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status_1') {
|
||||
_relay_status_1 = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status_2') {
|
||||
_relay_status_2 = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status_3') {
|
||||
_relay_status_3 = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return ThreeTouchModel(
|
||||
firstSwitch: _firstSwitch,
|
||||
secondSwitch: _secondSwitch,
|
||||
thirdSwitch: _thirdSwitch,
|
||||
firstCountDown: _firstCount,
|
||||
secondCountDown: _secondCount,
|
||||
thirdCountDown: _thirdCount,
|
||||
light_mode: lightStatusExtension.fromString(_light_mode),
|
||||
relay: StatusExtension.fromString(_relay),
|
||||
relay_status_1: StatusExtension.fromString(_relay_status_1),
|
||||
relay_status_2: StatusExtension.fromString(_relay_status_2),
|
||||
relay_status_3: StatusExtension.fromString(_relay_status_3));
|
||||
}
|
||||
}
|
63
lib/features/devices/model/two_touch_model.dart
Normal file
@ -0,0 +1,63 @@
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class TwoTouchModel {
|
||||
bool firstSwitch;
|
||||
bool secondSwitch;
|
||||
int firstCountDown;
|
||||
int secondCountDown;
|
||||
status relay;
|
||||
lightStatus light_mode;
|
||||
status relay_status_1;
|
||||
status relay_status_2;
|
||||
|
||||
TwoTouchModel(
|
||||
{required this.firstSwitch,
|
||||
required this.secondSwitch,
|
||||
required this.firstCountDown,
|
||||
required this.secondCountDown,
|
||||
required this.light_mode,
|
||||
required this.relay,
|
||||
required this.relay_status_1,
|
||||
required this.relay_status_2});
|
||||
|
||||
factory TwoTouchModel.fromJson(List<StatusModel> jsonList) {
|
||||
late bool _firstSwitch;
|
||||
late bool _secondSwitch;
|
||||
late int _firstCount;
|
||||
late int _secondCount;
|
||||
late String _relay;
|
||||
late String _light_mode;
|
||||
late String _relay_status_1;
|
||||
late String _relay_status_2;
|
||||
|
||||
for (int i = 0; i < jsonList.length; i++) {
|
||||
if (jsonList[i].code == 'switch_1') {
|
||||
_firstSwitch = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'switch_2') {
|
||||
_secondSwitch = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'countdown_1') {
|
||||
_firstCount = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'countdown_2') {
|
||||
_secondCount = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status') {
|
||||
_relay = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'light_mode') {
|
||||
_light_mode = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status_1') {
|
||||
_relay_status_1 = jsonList[i].value ?? 0;
|
||||
} else if (jsonList[i].code == 'relay_status_2') {
|
||||
_relay_status_2 = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return TwoTouchModel(
|
||||
firstSwitch: _firstSwitch,
|
||||
secondSwitch: _secondSwitch,
|
||||
firstCountDown: _firstCount,
|
||||
secondCountDown: _secondCount,
|
||||
light_mode: lightStatusExtension.fromString(_light_mode),
|
||||
relay: StatusExtension.fromString(_relay),
|
||||
relay_status_1: StatusExtension.fromString(_relay_status_1),
|
||||
relay_status_2: StatusExtension.fromString(_relay_status_2));
|
||||
}
|
||||
}
|
141
lib/features/devices/model/water_heater.dart
Normal file
@ -0,0 +1,141 @@
|
||||
//
|
||||
//
|
||||
// import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
//
|
||||
// class WHModel {
|
||||
// final int activeTime;
|
||||
// final String category;
|
||||
// final String categoryName;
|
||||
// final int createTime;
|
||||
// final String gatewayId;
|
||||
// final String icon;
|
||||
// final String ip;
|
||||
// final String lat;
|
||||
// final String lon;
|
||||
// final String localKey;
|
||||
// final String model;
|
||||
// final String name;
|
||||
// final String nodeId;
|
||||
// final bool online;
|
||||
// final String ownerId;
|
||||
// final bool sub;
|
||||
// final String timeZone;
|
||||
// final int updateTime;
|
||||
// final String uuid;
|
||||
// final String productUuid;
|
||||
// final String productType;
|
||||
// final String permissionType;
|
||||
//
|
||||
// WHModel({
|
||||
// required this.activeTime,
|
||||
// required this.category,
|
||||
// required this.categoryName,
|
||||
// required this.createTime,
|
||||
// required this.gatewayId,
|
||||
// required this.icon,
|
||||
// required this.ip,
|
||||
// required this.lat,
|
||||
// required this.lon,
|
||||
// required this.localKey,
|
||||
// required this.model,
|
||||
// required this.name,
|
||||
// required this.nodeId,
|
||||
// required this.online,
|
||||
// required this.ownerId,
|
||||
// required this.sub,
|
||||
// required this.timeZone,
|
||||
// required this.updateTime,
|
||||
// required this.uuid,
|
||||
// required this.productUuid,
|
||||
// required this.productType,
|
||||
// required this.permissionType,
|
||||
// });
|
||||
//
|
||||
// // Factory method to create a SmartDevice object from JSON
|
||||
// factory WHModel.fromJson(Map<String, dynamic> json, List<StatusModel> statusModelList) {
|
||||
// return WHModel(
|
||||
// activeTime: json['activeTime'],
|
||||
// category: json['category'],
|
||||
// categoryName: json['categoryName'],
|
||||
// createTime: json['createTime'],
|
||||
// gatewayId: json['gatewayId'],
|
||||
// icon: json['icon'],
|
||||
// ip: json['ip'],
|
||||
// lat: json['lat'],
|
||||
// lon: json['lon'],
|
||||
// localKey: json['localKey'],
|
||||
// model: json['model'],
|
||||
// name: json['name'],
|
||||
// nodeId: json['nodeId'],
|
||||
// online: json['online'],
|
||||
// ownerId: json['ownerId'],
|
||||
// sub: json['sub'],
|
||||
// timeZone: json['timeZone'],
|
||||
// updateTime: json['updateTime'],
|
||||
// uuid: json['uuid'],
|
||||
// productUuid: json['productUuid'],
|
||||
// productType: json['productType'],
|
||||
// permissionType: json['permissionType'],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// // Method to convert SmartDevice object to JSON
|
||||
// Map<String, dynamic> toJson() {
|
||||
// return {
|
||||
// 'activeTime': activeTime,
|
||||
// 'category': category,
|
||||
// 'categoryName': categoryName,
|
||||
// 'createTime': createTime,
|
||||
// 'gatewayId': gatewayId,
|
||||
// 'icon': icon,
|
||||
// 'ip': ip,
|
||||
// 'lat': lat,
|
||||
// 'lon': lon,
|
||||
// 'localKey': localKey,
|
||||
// 'model': model,
|
||||
// 'name': name,
|
||||
// 'nodeId': nodeId,
|
||||
// 'online': online,
|
||||
// 'ownerId': ownerId,
|
||||
// 'sub': sub,
|
||||
// 'timeZone': timeZone,
|
||||
// 'updateTime': updateTime,
|
||||
// 'uuid': uuid,
|
||||
// 'productUuid': productUuid,
|
||||
// 'productType': productType,
|
||||
// 'permissionType': permissionType,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
|
||||
class WHModel {
|
||||
bool firstSwitch;
|
||||
int firstCountDown;
|
||||
|
||||
WHModel(
|
||||
{required this.firstSwitch,
|
||||
required this.firstCountDown,
|
||||
});
|
||||
|
||||
factory WHModel.fromJson(List<StatusModel> jsonList) {
|
||||
late bool _switch;
|
||||
late int _count;
|
||||
|
||||
|
||||
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') {
|
||||
_count = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return WHModel(
|
||||
firstSwitch: _switch,
|
||||
firstCountDown: _count,
|
||||
);
|
||||
}
|
||||
}
|
@ -71,44 +71,49 @@ class ParameterControlDialogState extends State<ParameterControlDialog> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_value = (_value - 1).clamp(widget.min, widget.max);
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.remove,
|
||||
color: Colors.grey,
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_value = (_value - 1).clamp(widget.min, widget.max);
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.remove,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
Slider(
|
||||
value: _value.toDouble(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_value = value.toInt();
|
||||
});
|
||||
},
|
||||
min: widget.min.toDouble(),
|
||||
max: widget.max.toDouble(),
|
||||
label: _value.toString(),
|
||||
inactiveColor: ColorsManager.greyColor,
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_value = (_value + 1).clamp(widget.min, widget.max);
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.add,
|
||||
color: Colors.grey,
|
||||
Flexible(
|
||||
child: Slider(
|
||||
value: _value.toDouble(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_value = value.toInt();
|
||||
});
|
||||
},
|
||||
min: widget.min.toDouble(),
|
||||
max: widget.max.toDouble(),
|
||||
label: _value.toString(),
|
||||
inactiveColor: ColorsManager.greyColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_value = (_value + 1).clamp(widget.min, widget.max);
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.add,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 1,
|
||||
|
88
lib/features/devices/view/widgets/circular_button.dart
Normal file
@ -0,0 +1,88 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class CircularButton extends StatelessWidget {
|
||||
const CircularButton({
|
||||
super.key,
|
||||
required this.device,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
required this.icons,
|
||||
});
|
||||
|
||||
final DeviceModel? device;
|
||||
final String label;
|
||||
final Function()? onTap;
|
||||
final IconData icons;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: label == 'All On'
|
||||
? BodySmall(
|
||||
text: "On",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
: label == 'All Off'
|
||||
? BodySmall(
|
||||
text: "Off",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color:
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
: Icon(
|
||||
icons,
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
// text: "Timer",
|
||||
text: label,
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
class CurtainList extends StatelessWidget {
|
||||
|
@ -20,16 +20,16 @@ class CurtainView extends StatelessWidget {
|
||||
child: BlocBuilder<CurtainBloc, CurtainState>(
|
||||
builder: (context, state) {
|
||||
double curtainWidth = 270;
|
||||
double blindHeight = 310;
|
||||
// double blindHeight = 310;
|
||||
if (state is CurtainsOpening) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
blindHeight = state.blindHeight;
|
||||
// blindHeight = state.blindHeight;
|
||||
} else if (state is CurtainsClosing) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
blindHeight = state.blindHeight;
|
||||
// blindHeight = state.blindHeight;
|
||||
} else if (state is CurtainsPaused) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
blindHeight = state.blindHeight;
|
||||
// blindHeight = state.blindHeight;
|
||||
}
|
||||
return DefaultScaffold(
|
||||
title: curtain.name,
|
||||
@ -58,7 +58,8 @@ class CurtainView extends StatelessWidget {
|
||||
width: curtainWidth,
|
||||
child: Stack(
|
||||
children: List.generate(
|
||||
10, (index) {
|
||||
10,
|
||||
(index) {
|
||||
double spacing = curtainWidth / 9;
|
||||
double leftMostPosition = index * spacing;
|
||||
return AnimatedPositioned(
|
||||
|
@ -1,5 +1,4 @@
|
||||
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/devices/view/widgets/popup_menu_widget.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
@ -11,30 +10,33 @@ class DeviceAppbar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final String deviceUuid;
|
||||
final double appBarHeight = 56.0;
|
||||
final void Function()? onPressed;
|
||||
const DeviceAppbar({super.key, required this.deviceName, required this.deviceUuid,this.onPressed});
|
||||
const DeviceAppbar(
|
||||
{super.key, required this.deviceName, required this.deviceUuid, this.onPressed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
return AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: BodyLarge(
|
||||
text: deviceName ?? "",
|
||||
text: deviceName,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
IconButton(onPressed: () {
|
||||
showPopupMenu(context: context, items: [
|
||||
PopupMenuItem(
|
||||
onTap: () async {
|
||||
HomeCubit.getInstance().updateDevice(deviceUuid);
|
||||
},
|
||||
value: 'Update',
|
||||
child: const Text('Update'),
|
||||
)
|
||||
]);
|
||||
}, icon: Icon(Icons.edit))
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showPopupMenu(context: context, items: [
|
||||
PopupMenuItem(
|
||||
onTap: () async {
|
||||
HomeCubit.getInstance().updateDevice(deviceUuid);
|
||||
},
|
||||
value: 'Update',
|
||||
child: const Text('Update'),
|
||||
)
|
||||
]);
|
||||
},
|
||||
icon: Icon(Icons.edit))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,114 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class NotificationSettingsPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Notification Settings',
|
||||
child: BlocProvider(
|
||||
create: (context) => DoorSensorBloc(DSId: '')..add(const DoorSensorInitial()),
|
||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
||||
|
||||
return state is DoorSensorLoadingState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
DefaultContainer(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyLarge(
|
||||
text: 'Low Battery',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: doorSensorBloc.lowBattery,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<DoorSensorBloc>()
|
||||
.add(ToggleLowBatteryEvent(value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyLarge(
|
||||
text: 'Closing Reminder',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: doorSensorBloc.closingReminder,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<DoorSensorBloc>()
|
||||
.add(ToggleClosingReminderEvent(value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyLarge(
|
||||
text: 'Door Alarm',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: doorSensorBloc.closingReminder,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<DoorSensorBloc>()
|
||||
.add(ToggleDoorAlarmEvent(value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class DoorRecordsScreen extends StatelessWidget {
|
||||
final String DSId;
|
||||
const DoorRecordsScreen({super.key, required this.DSId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Records',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
DoorSensorBloc(DSId: DSId)..add(const ReportLogsInitial()),
|
||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
||||
|
||||
if (state is DoorSensorLoadingState) {
|
||||
return const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
);
|
||||
} else if (state is UpdateState) {
|
||||
// Group records by formatted date
|
||||
final Map<String, List<DeviceEvent>> groupedRecords = {};
|
||||
|
||||
// Iterate over the data list in DeviceReport
|
||||
for (var record in doorSensorBloc.recordGroups.data!) {
|
||||
final DateTime eventDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(record.eventTime!);
|
||||
final String formattedDate =
|
||||
DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime);
|
||||
|
||||
// Group by formatted date
|
||||
if (groupedRecords.containsKey(formattedDate)) {
|
||||
groupedRecords[formattedDate]!.add(record);
|
||||
} else {
|
||||
groupedRecords[formattedDate] = [record];
|
||||
}
|
||||
}
|
||||
|
||||
// Build the ListView with grouped data
|
||||
return ListView.builder(
|
||||
itemCount: groupedRecords.length,
|
||||
itemBuilder: (context, index) {
|
||||
final String date = groupedRecords.keys.elementAt(index);
|
||||
final List<DeviceEvent> recordsForDate =
|
||||
groupedRecords[date]!;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Date header
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
date,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
// List of records for the specific date
|
||||
DefaultContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
...recordsForDate.asMap().entries.map((entry) {
|
||||
final int idx = entry.key;
|
||||
final DeviceEvent record = entry.value;
|
||||
final DateTime eventDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
record.eventTime!);
|
||||
final String formattedTime =
|
||||
DateFormat('HH:mm:ss').format(eventDateTime);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
record.value == 'true'
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_unchecked,
|
||||
color: record.value == 'true'
|
||||
? Colors.blue
|
||||
: Colors.grey,
|
||||
),
|
||||
title: Text(
|
||||
record.value == 'true'
|
||||
? "Opened"
|
||||
: "Closed",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
subtitle: Text('$formattedTime'),
|
||||
),
|
||||
),
|
||||
// Only add Divider if it's not the last item
|
||||
if (idx != recordsForDate.length - 1)
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return const Center(child: Text('No data available.'));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_notification_settings.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_records_screen.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/battery_bar.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class DoorSensorScreen extends StatelessWidget {
|
||||
final DeviceModel? device;
|
||||
|
||||
const DoorSensorScreen({super.key, this.device});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Door Sensor',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
DoorSensorBloc(DSId: device?.uuid ?? '')..add(const DoorSensorInitial()),
|
||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
||||
DoorSensorModel model = DoorSensorModel(batteryPercentage: 0, doorContactState: false);
|
||||
if (state is LoadingNewSate) {
|
||||
model = state.doorSensor;
|
||||
} else if (state is UpdateState) {
|
||||
model = state.doorSensor;
|
||||
}
|
||||
return state is DoorSensorLoadingState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
doorSensorBloc.add(const DoorSensorInitial());
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.sizeOf(context).height * 0.8,
|
||||
child: Column(
|
||||
children: [
|
||||
BatteryBar(
|
||||
batteryPercentage: model.batteryPercentage,
|
||||
),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: InkWell(
|
||||
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
onTap: () {},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
// color: Colors.white.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(890),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.white.withOpacity(0.1),
|
||||
blurRadius: 24,
|
||||
offset: const Offset(-5, -5),
|
||||
blurStyle: BlurStyle.outer,
|
||||
),
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.11),
|
||||
blurRadius: 25,
|
||||
offset: const Offset(5, 5),
|
||||
blurStyle: BlurStyle.outer,
|
||||
),
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.13),
|
||||
blurRadius: 30,
|
||||
offset: const Offset(5, 5),
|
||||
blurStyle: BlurStyle.inner,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
model.doorContactState
|
||||
? Assets.doorOpen
|
||||
: Assets.doorClose,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
DoorRecordsScreen(DSId: device!.uuid!)),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child: SvgPicture.asset(Assets.doorRecordsIcon),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Records',
|
||||
// doorLockButtons.keys.elementAt(index),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => NotificationSettingsPage()),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child:
|
||||
SvgPicture.asset(Assets.doorNotificationSetting),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Notification Settings',
|
||||
// doorLockButtons.keys.elementAt(index),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -8,12 +8,10 @@ import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_state.dar
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.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';
|
||||
|
||||
class GateWayView extends StatelessWidget {
|
||||
final DeviceModel gatewayObj;
|
||||
@ -38,9 +36,10 @@ class GateWayView extends StatelessWidget {
|
||||
backgroundColor: ColorsManager.backgroundColor,
|
||||
extendBodyBehindAppBar: true,
|
||||
extendBody: true,
|
||||
appBar:DeviceAppbar(
|
||||
deviceName: 'Gateway',
|
||||
deviceUuid: gatewayObj.uuid!,),
|
||||
appBar: DeviceAppbar(
|
||||
deviceName: 'Gateway',
|
||||
deviceUuid: gatewayObj.uuid!,
|
||||
),
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
@ -55,11 +54,11 @@ class GateWayView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
child: RefreshIndicator(
|
||||
onRefresh:()async {
|
||||
BlocProvider.of<GatewayBloc>(context).add(GatewayInitial(gatewayId: gatewayObj.uuid ?? ''));
|
||||
},
|
||||
child: ListView(
|
||||
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<GatewayBloc>(context)
|
||||
.add(GatewayInitial(gatewayId: gatewayObj.uuid ?? ''));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
@ -120,7 +119,8 @@ class GateWayView extends StatelessWidget {
|
||||
)
|
||||
: Expanded(
|
||||
child: GridView.builder(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
@ -141,8 +141,7 @@ class GateWayView extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
));
|
||||
)));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/lights/lights_list.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -7,7 +5,6 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_blo
|
||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/repeat_widget.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
||||
@ -29,14 +26,12 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
state.errorMessage
|
||||
);
|
||||
CustomSnackBar.displaySnackBar(state.errorMessage);
|
||||
}
|
||||
if (state is IsRepeatState){
|
||||
if (state is IsRepeatState) {
|
||||
isRepeat = state.repeat;
|
||||
}
|
||||
if (state is GeneratePasswordOneTimestate ){
|
||||
if (state is GeneratePasswordOneTimestate) {
|
||||
generated = state.generated;
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
@ -54,170 +49,173 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back)
|
||||
),
|
||||
icon: const Icon(Icons.arrow_back)),
|
||||
),
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children:smartDoorBloc.passwordController.text.isEmpty?
|
||||
List.generate(10, (index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.0,vertical: 15),
|
||||
child: Icon(
|
||||
Icons.circle,
|
||||
size: 20.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
}) :[
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
Expanded(
|
||||
child: BodyLarge(
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 8.0 ,
|
||||
fontSize: 25,
|
||||
wordSpacing: 2),
|
||||
textAlign: TextAlign.center,
|
||||
text: smartDoorBloc.passwordController.text,
|
||||
fontSize: 23,
|
||||
),),
|
||||
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(
|
||||
text: smartDoorBloc.passwordController.text));
|
||||
},
|
||||
icon: const Icon(Icons.copy)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
|
||||
],
|
||||
const BodyMedium(
|
||||
text:
|
||||
'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
if(smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
Column(
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Column(
|
||||
children: [
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: const BodyMedium(
|
||||
text: 'Password Name',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: smartDoorBloc.passwordController.text.isEmpty
|
||||
? List.generate(10, (index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 4.0, vertical: 15),
|
||||
child: Icon(
|
||||
Icons.circle,
|
||||
size: 20.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
})
|
||||
: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: BodyLarge(
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 8.0,
|
||||
fontSize: 25,
|
||||
wordSpacing: 2),
|
||||
textAlign: TextAlign.center,
|
||||
text: smartDoorBloc.passwordController.text,
|
||||
fontSize: 23,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(
|
||||
text: smartDoorBloc
|
||||
.passwordController.text));
|
||||
},
|
||||
icon: const Icon(Icons.copy)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.6,
|
||||
child: TextFormField(
|
||||
controller: BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter The Name',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14, color: ColorsManager.textGray)),
|
||||
)),
|
||||
],
|
||||
),
|
||||
|
||||
if (smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: const BodyMedium(
|
||||
text: 'Password Name',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.6,
|
||||
child: TextFormField(
|
||||
controller: BlocProvider.of<SmartDoorBloc>(context)
|
||||
.passwordNameController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter The Name',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14, color: ColorsManager.textGray)),
|
||||
)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
textAlign: TextAlign.center,
|
||||
text:
|
||||
'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
|
||||
// NameTimeWidget(type:type!),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 1.5,
|
||||
child: DoorLockButton(
|
||||
isDone: generated,
|
||||
isLoading: smartDoorBloc.isSavingPassword,
|
||||
borderRadius: 30,
|
||||
backgroundColor: ColorsManager.primaryColor,
|
||||
onPressed: () async {
|
||||
if (generated == false) {
|
||||
smartDoorBloc
|
||||
.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
||||
} else {
|
||||
if (smartDoorBloc.passwordNameController.text.isNotEmpty) {
|
||||
smartDoorBloc.add(RenamePasswordEvent());
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Obtain Password',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
textAlign: TextAlign.center,
|
||||
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
|
||||
// NameTimeWidget(type:type!),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width/1.5,
|
||||
child: DoorLockButton(
|
||||
isDone: generated,
|
||||
isLoading: smartDoorBloc.isSavingPassword ,
|
||||
borderRadius: 30,
|
||||
backgroundColor:ColorsManager.primaryColor ,
|
||||
onPressed: () async {
|
||||
if(generated==false){
|
||||
smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
||||
}else{
|
||||
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||
smartDoorBloc.add(RenamePasswordEvent());
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Obtain Password',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: Colors.white,
|
||||
),),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat? const RepeatWidget():const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
@ -0,0 +1,68 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
class OneGangList extends StatelessWidget {
|
||||
const OneGangList(
|
||||
{super.key, required this.oneGangList, required this.allSwitches});
|
||||
|
||||
final List<GroupOneGangModel> oneGangList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const BodySmall(text: 'All Lights'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: allSwitches,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: oneGangList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: oneGangList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: oneGangList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(
|
||||
ChangeFirstWizardSwitchStatusEvent(
|
||||
value: oneGangList[index].firstSwitch,
|
||||
deviceId: oneGangList[index].deviceId));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -20,10 +20,8 @@ class OneGangScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => OneGangBloc(
|
||||
switchCode: 'switch_1',
|
||||
oneGangId : device?.uuid ?? '')
|
||||
..add(const InitialEvent(groupScreen:false)),
|
||||
create: (context) => OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
|
||||
..add(const InitialEvent(groupScreen: false)),
|
||||
child: BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
OneGangModel oneGangModel = OneGangModel(
|
||||
@ -36,136 +34,132 @@ class OneGangScreen extends StatelessWidget {
|
||||
} else if (state is UpdateState) {
|
||||
oneGangModel = state.oneGangModel;
|
||||
}
|
||||
return state is LoadingInitialState ?
|
||||
const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
):
|
||||
RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<OneGangBloc>(context)
|
||||
.add(InitialEvent(groupScreen: device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<OneGangBloc>(context)
|
||||
.add(InitialEvent(groupScreen: device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: oneGangModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(
|
||||
ChangeFirstSwitchStatusEvent(
|
||||
value: oneGangModel.firstSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text:" Entrance Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: oneGangModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(
|
||||
ChangeFirstSwitchStatusEvent(
|
||||
value: oneGangModel.firstSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: " Entrance Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode:'switch_1' ,
|
||||
device: device!,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: 'switch_1',
|
||||
device: device!,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
color:
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "Timer",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "Timer",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -17,16 +17,15 @@ 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/font_manager.dart';
|
||||
|
||||
|
||||
class TimerScheduleScreen extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
final String deviceCode;
|
||||
final String switchCode;
|
||||
const TimerScheduleScreen(
|
||||
{required this.device,
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -37,9 +36,9 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
OneGangBloc(switchCode: switchCode, oneGangId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
OneGangBloc(switchCode: switchCode, oneGangId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
final oneGangBloc = BlocProvider.of<OneGangBloc>(context);
|
||||
@ -64,7 +63,7 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
},
|
||||
child: DefaultTabController(
|
||||
length: 2,
|
||||
child: DefaultScaffold(
|
||||
child: DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
@ -74,175 +73,213 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
oneGangBloc.createSchedule == true ?
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
oneGangBloc.add(ThreeGangSave());
|
||||
},
|
||||
child: const Text('Save')
|
||||
) :
|
||||
oneGangBloc.selectedTabIndex==1? IconButton(
|
||||
onPressed: () {
|
||||
oneGangBloc.toggleCreateSchedule();
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
):SizedBox(),
|
||||
oneGangBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
oneGangBloc.add(ScheduleSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: oneGangBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
oneGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
child:
|
||||
state is LoadingInitialState?
|
||||
const Center(child: CircularProgressIndicator()):
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if(value==0){
|
||||
if(oneGangBloc.createSchedule == true){
|
||||
oneGangBloc.toggleCreateSchedule();
|
||||
}
|
||||
oneGangBloc.toggleSelectedIndex(0);
|
||||
}else{
|
||||
oneGangBloc.toggleSelectedIndex(1);
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(countNum),
|
||||
fontColor:
|
||||
ColorsManager.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode: CupertinoTimerPickerMode.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
oneGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: Duration.zero));
|
||||
} else if (duration != Duration.zero) {
|
||||
oneGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment:oneGangBloc.listSchedule.isNotEmpty?
|
||||
MainAxisAlignment.start:MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
child: oneGangBloc.createSchedule == true ?
|
||||
CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
oneGangBloc.toggleSchedule = isOn;
|
||||
},
|
||||
onDateTimeChanged: (DateTime dateTime) {
|
||||
oneGangBloc.selectedTime=dateTime;
|
||||
},
|
||||
days: oneGangBloc.days,
|
||||
selectDays: (List<String> selectedDays) {
|
||||
oneGangBloc.selectedDays = selectedDays;
|
||||
},
|
||||
)
|
||||
:
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: oneGangBloc.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
oneGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
|
||||
oneGangBloc.add(DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
oneGangBloc.add(ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (oneGangBloc.createSchedule ==
|
||||
true) {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
oneGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
oneGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
oneGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 1));
|
||||
}
|
||||
},
|
||||
indicatorColor:
|
||||
Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
],
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: const NeverScrollableScrollPhysics(), // Disable swiping
|
||||
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(
|
||||
countNum),
|
||||
fontColor: ColorsManager
|
||||
.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode:
|
||||
CupertinoTimerPickerMode
|
||||
.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration
|
||||
newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state
|
||||
is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
oneGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
oneGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: oneGangBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
oneGangBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
oneGangBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: oneGangBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
oneGangBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: oneGangBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
oneGangBloc.listSchedule
|
||||
.removeWhere((schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
oneGangBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId, isEnabled) {
|
||||
oneGangBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
);
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
class OneGangWizard extends StatelessWidget {
|
||||
const OneGangWizard({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<GroupOneGangModel> groupOneGangModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Lights',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
OneGangBloc(switchCode: '', oneGangId: device?.uuid ?? '')
|
||||
..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupOneGangModel = state.oneGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: OneGangList(
|
||||
oneGangList: groupOneGangModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
class OneTouchList extends StatelessWidget {
|
||||
const OneTouchList(
|
||||
{super.key, required this.oneTouchList, required this.allSwitches});
|
||||
|
||||
final List<GroupOneTouchModel> oneTouchList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const BodySmall(text: 'All Lights'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: allSwitches,
|
||||
action: () {
|
||||
BlocProvider.of<OneTouchBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<OneTouchBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: oneTouchList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: oneTouchList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: oneTouchList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneTouchBloc>(context).add(
|
||||
ChangeFirstWizardSwitchStatusEvent(
|
||||
value: oneTouchList[index].firstSwitch,
|
||||
deviceId: oneTouchList[index].deviceId));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/circular_button.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_setting.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_timer_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.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';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class OneTouchScreen extends StatelessWidget {
|
||||
const OneTouchScreen({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnnotatedRegion(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||
statusBarIconBrightness: Brightness.light,
|
||||
),
|
||||
child: Scaffold(
|
||||
backgroundColor: ColorsManager.backgroundColor,
|
||||
extendBodyBehindAppBar: true,
|
||||
extendBody: true,
|
||||
appBar: device != null
|
||||
? DeviceAppbar(
|
||||
deviceName: device!.name!,
|
||||
deviceUuid: device!.uuid!,
|
||||
)
|
||||
: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: BodyLarge(
|
||||
text: device?.name ?? 'Lights',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
Assets.assetsImagesBackground,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.4,
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: Constants.defaultPadding,
|
||||
right: Constants.defaultPadding,
|
||||
bottom: Constants.bottomNavBarHeight,
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (context) => OneTouchBloc(
|
||||
switchCode: 'switch_1', oneTouchId: device?.uuid ?? '')
|
||||
..add(const InitialEvent(groupScreen: false)),
|
||||
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||
builder: (context, state) {
|
||||
OneTouchModel oneTouchModel = OneTouchModel(
|
||||
firstSwitch: false,
|
||||
firstCountDown: 0,
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off);
|
||||
|
||||
List<GroupOneTouchModel> groupOneTouchModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is LoadingNewSate) {
|
||||
oneTouchModel = state.oneTouchModel;
|
||||
} else if (state is UpdateState) {
|
||||
oneTouchModel = state.oneTouchModel;
|
||||
} else if (state is UpdateGroupState) {
|
||||
groupOneTouchModel = state.oneTouchList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<OneTouchBloc>(context).add(
|
||||
InitialEvent(
|
||||
groupScreen:
|
||||
device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value:
|
||||
oneTouchModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<
|
||||
OneTouchBloc>(
|
||||
context)
|
||||
.add(ChangeFirstSwitchStatusEvent(
|
||||
value: oneTouchModel
|
||||
.firstSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: " Entrance Light",
|
||||
fontColor: ColorsManager
|
||||
.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.access_time,
|
||||
label: 'Timer',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context,
|
||||
animation1,
|
||||
animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode:
|
||||
'switch_1',
|
||||
device: device!,
|
||||
deviceCode:
|
||||
'countdown_1',
|
||||
)));
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.settings,
|
||||
label: 'Setting',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context,
|
||||
animation1,
|
||||
animation2) =>
|
||||
OneTouchSetting(
|
||||
device: device,
|
||||
)));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,311 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class OneTouchSetting extends StatelessWidget {
|
||||
const OneTouchSetting({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Setting',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
OneTouchBloc(switchCode: '', oneTouchId: device?.uuid ?? '')
|
||||
..add(const InitialEvent(groupScreen: false)),
|
||||
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||
builder: (context, state) {
|
||||
final oneTouchBloc = BlocProvider.of<OneTouchBloc>(context);
|
||||
OneTouchModel? oneTouchModel = OneTouchModel(
|
||||
firstSwitch: false,
|
||||
firstCountDown: 0,
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off);
|
||||
|
||||
// if (state is UpdateState) {
|
||||
// oneTouchModel = state.oneTouchModel;
|
||||
// }
|
||||
if (state is UpdateState) {
|
||||
oneTouchModel = state.oneTouchModel;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
Container(
|
||||
child: DefaultContainer(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
oneTouchBloc.optionSelected =
|
||||
'relay_status';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel: oneTouchBloc
|
||||
.deviceStatus.relay.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
oneTouchBloc.add(ChangeStatusEvent(
|
||||
deviceId: device!.uuid!,
|
||||
context: context));
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
title: 'Restart Status',
|
||||
label1: 'Power Off',
|
||||
label2: 'Power On',
|
||||
label3: 'Restart Memory',
|
||||
onTapLabel1: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2),
|
||||
() async {
|
||||
oneTouchBloc.add(const InitialEvent(
|
||||
groupScreen: false));
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 10, top: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Restart Status',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: oneTouchBloc
|
||||
.deviceStatus.relay.value,
|
||||
fontColor:
|
||||
ColorsManager.textGray,
|
||||
),
|
||||
const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 10, top: 10),
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
oneTouchBloc.optionSelected =
|
||||
'light_mode';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
oneTouchModel!.light_mode.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
oneTouchBloc.add(
|
||||
ChangeStatusEvent(
|
||||
deviceId: device!.uuid!,
|
||||
context: context));
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
title: 'Indicator Status',
|
||||
label1: 'Off',
|
||||
label2: 'On/Off Status',
|
||||
label3: 'Switch Position',
|
||||
onTapLabel1: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() async {
|
||||
oneTouchBloc.add(const InitialEvent(
|
||||
groupScreen: false));
|
||||
});
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Indicator Status',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: oneTouchModel
|
||||
.light_mode.value,
|
||||
fontColor: ColorsManager.textGray,
|
||||
),
|
||||
const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 10, top: 10),
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
oneTouchBloc.optionSelected =
|
||||
'relay_status_1';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
oneTouchModel!
|
||||
.relay_status_1.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
oneTouchBloc.add(
|
||||
ChangeStatusEvent(
|
||||
deviceId: device!.uuid!,
|
||||
context: context));
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
title: 'Restart Status 1',
|
||||
label1: 'Power Off',
|
||||
label2: 'Power On',
|
||||
label3: 'Restart Memory',
|
||||
onTapLabel1: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
oneTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() async {
|
||||
oneTouchBloc.add(const InitialEvent(
|
||||
groupScreen: false));
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Restart Status 1',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: oneTouchModel
|
||||
.relay_status_1.value,
|
||||
fontColor:
|
||||
ColorsManager.textGray,
|
||||
),
|
||||
const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/generated/assets.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/font_manager.dart';
|
||||
|
||||
class TimerScheduleScreen extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
final String deviceCode;
|
||||
final String switchCode;
|
||||
const TimerScheduleScreen(
|
||||
{required this.device,
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnnotatedRegion(
|
||||
value: SystemUiOverlayStyle(
|
||||
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||
statusBarIconBrightness: Brightness.light,
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
OneTouchBloc(switchCode: switchCode, oneTouchId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||
builder: (context, state) {
|
||||
final oneTouchBloc = BlocProvider.of<OneTouchBloc>(context);
|
||||
Duration duration = Duration.zero;
|
||||
int countNum = 0;
|
||||
if (state is UpdateTimerState) {
|
||||
countNum = state.seconds;
|
||||
} else if (state is TimerRunInProgress) {
|
||||
countNum = state.remainingTime;
|
||||
} else if (state is TimerRunComplete) {
|
||||
countNum = 0;
|
||||
} else if (state is LoadingNewSate) {
|
||||
countNum = 0;
|
||||
}
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvoked: (didPop) {
|
||||
if (!didPop) {
|
||||
oneTouchBloc.add(OnClose());
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: DefaultTabController(
|
||||
length: 2,
|
||||
child: DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: const BodyLarge(
|
||||
text: 'Schedule',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
oneTouchBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
oneTouchBloc.add(ScheduleSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: oneTouchBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneTouchBloc.toggleCreateSchedule();
|
||||
oneTouchBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (oneTouchBloc.createSchedule ==
|
||||
true) {
|
||||
// oneTouchBloc.toggleCreateSchedule();
|
||||
oneTouchBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
oneTouchBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
oneTouchBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 1));
|
||||
}
|
||||
},
|
||||
indicatorColor:
|
||||
Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(), // Disable swiping
|
||||
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(
|
||||
countNum),
|
||||
fontColor: ColorsManager
|
||||
.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode:
|
||||
CupertinoTimerPickerMode
|
||||
.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration
|
||||
newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state
|
||||
is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
oneTouchBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
oneTouchBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: oneTouchBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
oneTouchBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
oneTouchBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: oneTouchBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
oneTouchBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: oneTouchBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
oneTouchBloc.listSchedule
|
||||
.removeWhere((schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
oneTouchBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId, isEnabled) {
|
||||
oneTouchBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _formatDuration(int seconds) {
|
||||
final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
|
||||
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
|
||||
final secs = (seconds % 60).toString().padLeft(2, '0');
|
||||
return '$hours:$minutes:$secs';
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_touch_bloc/one_touch_state.dart';
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_gang_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
class OneTouchWizard extends StatelessWidget {
|
||||
const OneTouchWizard({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<GroupOneTouchModel> groupOneTouchModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Lights',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
OneTouchBloc(switchCode: '', oneTouchId: device?.uuid ?? '')
|
||||
..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<OneTouchBloc, OneTouchState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupOneTouchModel = state.oneTouchList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: OneTouchList(
|
||||
oneTouchList: groupOneTouchModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
230
lib/features/devices/view/widgets/restart_status_dialog.dart
Normal file
@ -0,0 +1,230 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class RestartStatusDialog extends StatefulWidget {
|
||||
final String label1;
|
||||
final String label2;
|
||||
final String label3;
|
||||
final String title;
|
||||
|
||||
final Function(String)? onTapLabel1;
|
||||
final Function(String)? onTapLabel2;
|
||||
final Function(String)? onTapLabel3;
|
||||
final Function()? cancelTab;
|
||||
final Function()? confirmTab;
|
||||
|
||||
final String? initialSelectedLabel;
|
||||
|
||||
RestartStatusDialog({
|
||||
required this.label1,
|
||||
required this.label2,
|
||||
required this.label3,
|
||||
required this.title,
|
||||
this.onTapLabel1,
|
||||
this.onTapLabel2,
|
||||
this.onTapLabel3,
|
||||
required this.cancelTab,
|
||||
required this.confirmTab,
|
||||
this.initialSelectedLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
_RestartStatusDialogState createState() => _RestartStatusDialogState();
|
||||
}
|
||||
|
||||
class _RestartStatusDialogState extends State<RestartStatusDialog> {
|
||||
late String _selectedOption;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_selectedOption = widget.initialSelectedLabel ?? '';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
BodyLarge(
|
||||
text: widget.title,
|
||||
fontWeight: FontWeight.w700,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontSize: 16,
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(left: 15, right: 15),
|
||||
child: Divider(
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 15, right: 15),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildCheckboxOption(
|
||||
label: widget.label1,
|
||||
onTap: widget.onTapLabel1,
|
||||
),
|
||||
_buildCheckboxOption(
|
||||
label: widget.label2,
|
||||
onTap: widget.onTapLabel2,
|
||||
),
|
||||
_buildCheckboxOption(
|
||||
label: widget.label3,
|
||||
onTap: widget.onTapLabel3,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
right: BorderSide(
|
||||
color: ColorsManager.textGray,
|
||||
width: 0.5,
|
||||
),
|
||||
top: BorderSide(
|
||||
color: ColorsManager.textGray,
|
||||
width: 1.0,
|
||||
),
|
||||
)),
|
||||
child: SizedBox(
|
||||
child: InkWell(
|
||||
onTap: widget.cancelTab,
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(15),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: TextStyle(
|
||||
color: ColorsManager.textGray,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: ColorsManager.textGray,
|
||||
width: 0.5,
|
||||
),
|
||||
top: BorderSide(
|
||||
color: ColorsManager.textGray,
|
||||
width: 1.0,
|
||||
),
|
||||
)),
|
||||
child: InkWell(
|
||||
onTap: widget.confirmTab,
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(15),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Confirm',
|
||||
style: TextStyle(
|
||||
color: ColorsManager.primaryColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
),
|
||||
)),
|
||||
))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCheckboxOption(
|
||||
{required String label, Function(String)? onTap}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, top: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: label,
|
||||
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w400),
|
||||
),
|
||||
CircularCheckbox(
|
||||
value: _selectedOption == label,
|
||||
onChanged: (bool? value) {
|
||||
if (value == true) {
|
||||
setState(() {
|
||||
_selectedOption = label;
|
||||
});
|
||||
if (onTap != null) {
|
||||
onTap(label);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CircularCheckbox extends StatefulWidget {
|
||||
final bool value;
|
||||
final ValueChanged<bool?> onChanged;
|
||||
|
||||
CircularCheckbox({required this.value, required this.onChanged});
|
||||
|
||||
@override
|
||||
_CircularCheckboxState createState() => _CircularCheckboxState();
|
||||
}
|
||||
|
||||
class _CircularCheckboxState extends State<CircularCheckbox> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
widget.onChanged(!widget.value);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: widget.value
|
||||
? ColorsManager.primaryColorWithOpacity.withOpacity(0.01)
|
||||
: Colors.grey,
|
||||
width: 2.0,
|
||||
),
|
||||
color: widget.value
|
||||
? ColorsManager.primaryColorWithOpacity
|
||||
: Colors.transparent,
|
||||
),
|
||||
width: 24.0,
|
||||
height: 24.0,
|
||||
child: widget.value
|
||||
? const Icon(
|
||||
Icons.check,
|
||||
color: Colors.white,
|
||||
size: 16.0,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
|
||||
|
||||
|
@ -9,16 +9,19 @@ import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_sensor_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_Interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/door_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/water_heater/water_heater_page.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
||||
@ -31,7 +34,6 @@ class RoomPageSwitch extends StatelessWidget {
|
||||
});
|
||||
|
||||
final DeviceModel device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
@ -87,7 +89,8 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => ACsView(deviceModel: device)));
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
ACsView(deviceModel: device)));
|
||||
// navigateToInterface(ACsView(deviceModel: device), context);
|
||||
break;
|
||||
case DeviceType.WallSensor:
|
||||
@ -110,8 +113,9 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
CurtainView(curtain: device,)));
|
||||
pageBuilder: (context, animation1, animation2) => CurtainView(
|
||||
curtain: device,
|
||||
)));
|
||||
break;
|
||||
case DeviceType.Blind:
|
||||
break;
|
||||
@ -119,14 +123,16 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => DoorInterface(doorLock: device)));
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
DoorInterface(doorLock: device)));
|
||||
// navigateToInterface(DoorInterface(doorlock: device), context);
|
||||
break;
|
||||
case DeviceType.Gateway:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => GateWayView(gatewayObj: device)));
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
GateWayView(gatewayObj: device)));
|
||||
break;
|
||||
case DeviceType.LightBulb:
|
||||
navigateToInterface(LightInterface(light: device), context);
|
||||
@ -148,6 +154,39 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
ThreeGangInterface(gangSwitch: device)));
|
||||
|
||||
case DeviceType.WH:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
WaterHeaterPage(device: device)));
|
||||
case DeviceType.DS:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
DoorSensorScreen(device: device)));
|
||||
|
||||
case DeviceType.OneTouch:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
OneTouchScreen(device: device)));
|
||||
|
||||
case DeviceType.TowTouch:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
TwoTouchInterface(touchSwitch: device)));
|
||||
case DeviceType.ThreeTouch:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
ThreeTouchInterface(touchSwitch: device)));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class CreateTemporaryPassword extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isRepeat = false;
|
||||
bool generated = false;
|
||||
// bool generated = false;
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
@ -35,11 +35,11 @@ class CreateTemporaryPassword extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (state is IsRepeatState){
|
||||
if (state is IsRepeatState) {
|
||||
isRepeat = state.repeat;
|
||||
}
|
||||
if (state is GeneratePasswordOneTimestate ){
|
||||
generated = state.generated;
|
||||
if (state is GeneratePasswordOneTimestate) {
|
||||
// generated = state.generated;
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
@ -56,141 +56,142 @@ class CreateTemporaryPassword extends StatelessWidget {
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back)
|
||||
),
|
||||
actions:
|
||||
type == 'Online Password'?[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
smartDoorBloc.add(SavePasswordEvent(context: context));
|
||||
},
|
||||
child: const Text('Save')
|
||||
)
|
||||
]:null,
|
||||
icon: const Icon(Icons.arrow_back)),
|
||||
actions: type == 'Online Password'
|
||||
? [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
smartDoorBloc.add(SavePasswordEvent(context: context));
|
||||
},
|
||||
child: const Text('Save'))
|
||||
]
|
||||
: null,
|
||||
),
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: type == 'Online Password'?0:25),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: PinCodeTextField(
|
||||
onCompleted: (value) {
|
||||
if (value.split('').every((char) => char == '1')) {
|
||||
smartDoorBloc.passwordController.clear();
|
||||
CustomSnackBar.displaySnackBar('All characters cannot be 1.');
|
||||
}
|
||||
},
|
||||
autoDisposeControllers: false,
|
||||
keyboardType: TextInputType.phone,
|
||||
length: 7,
|
||||
// enabled:type == 'Online Password'? true:false,
|
||||
obscureText: false,
|
||||
animationType: AnimationType.fade,
|
||||
pinTheme: PinTheme(
|
||||
shape: PinCodeFieldShape.underline,
|
||||
fieldHeight: 45,
|
||||
fieldWidth: 20,
|
||||
activeFillColor: Colors.white,
|
||||
disabledColor: Colors.grey,
|
||||
activeColor: Colors.grey,
|
||||
errorBorderColor: Colors.grey,
|
||||
inactiveColor: Colors.grey,
|
||||
inactiveFillColor: Colors.grey,
|
||||
selectedColor: Colors.grey),
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
backgroundColor: Colors.white,
|
||||
enableActiveFill: false,
|
||||
controller: smartDoorBloc.passwordController,
|
||||
appContext: context,
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text:
|
||||
'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: type == 'Online Password' ? 0 : 25),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: PinCodeTextField(
|
||||
onCompleted: (value) {
|
||||
if (value.split('').every((char) => char == '1')) {
|
||||
smartDoorBloc.passwordController.clear();
|
||||
CustomSnackBar.displaySnackBar(
|
||||
'All characters cannot be 1.');
|
||||
}
|
||||
},
|
||||
autoDisposeControllers: false,
|
||||
keyboardType: TextInputType.phone,
|
||||
length: 7,
|
||||
// enabled:type == 'Online Password'? true:false,
|
||||
obscureText: false,
|
||||
animationType: AnimationType.fade,
|
||||
pinTheme: PinTheme(
|
||||
shape: PinCodeFieldShape.underline,
|
||||
fieldHeight: 45,
|
||||
fieldWidth: 20,
|
||||
activeFillColor: Colors.white,
|
||||
disabledColor: Colors.grey,
|
||||
activeColor: Colors.grey,
|
||||
errorBorderColor: Colors.grey,
|
||||
inactiveColor: Colors.grey,
|
||||
inactiveFillColor: Colors.grey,
|
||||
selectedColor: Colors.grey),
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
backgroundColor: Colors.white,
|
||||
enableActiveFill: false,
|
||||
controller: smartDoorBloc.passwordController,
|
||||
appContext: context,
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (type == 'Online Password')
|
||||
Flexible(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
smartDoorBloc.add(GeneratePasswordEvent());
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Generate Randomly',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if(type == 'Online Password')
|
||||
Flexible(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
smartDoorBloc.add(GeneratePasswordEvent());
|
||||
),
|
||||
if (smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(
|
||||
ClipboardData(text: smartDoorBloc.passwordController.text));
|
||||
},
|
||||
child: const Text('Copy')),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
NameTimeWidget(),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Repeat',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: smartDoorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
smartDoorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Generate Randomly',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if(smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(
|
||||
text: smartDoorBloc.passwordController.text));
|
||||
},
|
||||
child: const Text('Copy')
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
NameTimeWidget(),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Repeat',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: smartDoorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
smartDoorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
) ,
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat? const RepeatWidget():const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
@ -31,16 +31,18 @@ class DoorDialogState extends State<DoorDialog> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final effectiveTime = widget.temporaryPassword?.effectiveTime ??int.parse( widget.offline?.gmtStart);
|
||||
final invalidTime = widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired);
|
||||
final effectiveTime =
|
||||
widget.temporaryPassword?.effectiveTime ?? int.parse(widget.offline?.gmtStart);
|
||||
final invalidTime =
|
||||
widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired);
|
||||
|
||||
final DateTime effectiveDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(effectiveTime! * 1000, isUtc: false);
|
||||
DateTime.fromMillisecondsSinceEpoch(effectiveTime * 1000, isUtc: false);
|
||||
String formattedDateEffectiveTime = DateFormat('yyyy-MM-dd').format(effectiveDateTime);
|
||||
String formattedTimeEffectiveTime = DateFormat('hh:mm a').format(effectiveDateTime);
|
||||
|
||||
final DateTime expiredDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(invalidTime! * 1000, isUtc: false);
|
||||
DateTime.fromMillisecondsSinceEpoch(invalidTime * 1000, isUtc: false);
|
||||
String formattedDateExpiredDateTime = DateFormat('yyyy-MM-dd').format(expiredDateTime);
|
||||
String formattedTimeExpiredDateTime = DateFormat('hh:mm a').format(expiredDateTime);
|
||||
return Dialog(
|
||||
@ -116,60 +118,59 @@ class DoorDialogState extends State<DoorDialog> {
|
||||
width: double.infinity,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
widget.temporaryPassword?.effectiveTime!=null?
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
width: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context, 'delete');
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Delete Password',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
):
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Container(
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
widget.temporaryPassword?.effectiveTime != null
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
),
|
||||
|
||||
],
|
||||
)
|
||||
Container(
|
||||
height: 50,
|
||||
width: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context, 'delete');
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Delete Password',
|
||||
style: context.bodyMedium
|
||||
.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Container(
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/members_management_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/smart_linkage_view.dart';
|
||||
@ -10,9 +9,8 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class DoorLockGrid extends StatelessWidget {
|
||||
String uuid;
|
||||
DoorLockGrid({
|
||||
super.key,required this.uuid});
|
||||
final String uuid;
|
||||
const DoorLockGrid({super.key, required this.uuid});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -67,24 +65,24 @@ class DoorLockGrid extends StatelessWidget {
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> doorLockButtons({val}) => [
|
||||
{
|
||||
'title': 'Unlocking Records',
|
||||
'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords,
|
||||
'page': const UnlockingRecordsView(),
|
||||
},
|
||||
{
|
||||
'title': 'Members Management',
|
||||
'image': Assets.assetsIconsDoorlockAssetsMembersManagement,
|
||||
'page': const MembersManagementView(),
|
||||
},
|
||||
{
|
||||
'title': 'Temporary Password',
|
||||
'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword,
|
||||
'page': TemporaryPasswordPage(deviceId:val) ,
|
||||
},
|
||||
{
|
||||
'title': 'Smart Linkage',
|
||||
'image': Assets.assetsIconsDoorlockAssetsSmartLinkage,
|
||||
'page': const SmartLinkgeView()
|
||||
},
|
||||
];
|
||||
{
|
||||
'title': 'Unlocking Records',
|
||||
'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords,
|
||||
'page': const UnlockingRecordsView(),
|
||||
},
|
||||
{
|
||||
'title': 'Members Management',
|
||||
'image': Assets.assetsIconsDoorlockAssetsMembersManagement,
|
||||
'page': const MembersManagementView(),
|
||||
},
|
||||
{
|
||||
'title': 'Temporary Password',
|
||||
'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword,
|
||||
'page': TemporaryPasswordPage(deviceId: val),
|
||||
},
|
||||
{
|
||||
'title': 'Smart Linkage',
|
||||
'image': Assets.assetsIconsDoorlockAssetsSmartLinkage,
|
||||
'page': const SmartLinkgeView()
|
||||
},
|
||||
];
|
||||
|
@ -14,98 +14,103 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class OnetimePasswordPage extends StatelessWidget {
|
||||
final String? deviceId;
|
||||
const OnetimePasswordPage({super.key, this.deviceId,});
|
||||
const OnetimePasswordPage({
|
||||
super.key,
|
||||
this.deviceId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword( )),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||
listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.errorMessage),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => OfflineOneTimePasswordPage(deviceId: deviceId, )
|
||||
)).then((result) {
|
||||
if(result!=null){
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
}
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add)
|
||||
)
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.oneTimePasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.oneTimePasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text: 'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.oneTimePasswords![index],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
) : Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
);
|
||||
create: (BuildContext context) =>
|
||||
SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword()),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.errorMessage),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => OfflineOneTimePasswordPage(
|
||||
deviceId: deviceId,
|
||||
)))
|
||||
.then((result) {
|
||||
if (result != null) {
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
}
|
||||
});
|
||||
},
|
||||
));
|
||||
})
|
||||
);
|
||||
icon: const Icon(Icons.add))
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.oneTimePasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.oneTimePasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text:
|
||||
'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.oneTimePasswords![index],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -19,87 +19,88 @@ class TimeLimitedPasswordPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||
listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
state.errorMessage
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => CreateOfflineTimeLimitPasswordPage(deviceId: deviceId,)
|
||||
)).then((result) {
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add)
|
||||
)
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.timeLimitPasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.timeLimitPasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text: 'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.timeLimitPasswords![index],
|
||||
);
|
||||
},
|
||||
create: (BuildContext context) =>
|
||||
SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(state.errorMessage);
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => CreateOfflineTimeLimitPasswordPage(
|
||||
deviceId: deviceId,
|
||||
)))
|
||||
.then((result) {
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add))
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.timeLimitPasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.timeLimitPasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text:
|
||||
'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.timeLimitPasswords![index],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
) : Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
})
|
||||
);
|
||||
);
|
||||
},
|
||||
));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class GangSwitch extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
onTap: () {
|
||||
action();
|
||||
// var tempControl = DeviceControlModel(
|
||||
|
@ -63,17 +63,20 @@ class ScheduleScreen extends StatelessWidget {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode :"switch_1",
|
||||
device: device,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: "switch_1",
|
||||
device: device,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Bedside Light",
|
||||
@ -100,17 +103,20 @@ class ScheduleScreen extends StatelessWidget {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode :"switch_2",
|
||||
device: device,
|
||||
deviceCode: 'countdown_2',
|
||||
)));
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: "switch_2",
|
||||
device: device,
|
||||
deviceCode: 'countdown_2',
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Ceiling Light",
|
||||
@ -137,17 +143,20 @@ class ScheduleScreen extends StatelessWidget {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode :"switch_3",
|
||||
device: device,
|
||||
deviceCode: 'countdown_3',
|
||||
)));
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: "switch_3",
|
||||
device: device,
|
||||
deviceCode: 'countdown_3',
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Spotlight",
|
||||
|
@ -4,11 +4,9 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_blo
|
||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/schedule_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
@ -22,9 +20,7 @@ class ThreeGangScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => ThreeGangBloc(
|
||||
switchCode: '',
|
||||
threeGangId: device?.uuid ?? '')
|
||||
create: (context) => ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||
builder: (context, state) {
|
||||
@ -36,366 +32,354 @@ class ThreeGangScreen extends StatelessWidget {
|
||||
secondCountDown: 0,
|
||||
thirdCountDown: 0);
|
||||
|
||||
List<GroupThreeGangModel> groupThreeGangModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is LoadingNewSate) {
|
||||
threeGangModel = state.threeGangModel;
|
||||
} else if (state is UpdateState) {
|
||||
threeGangModel = state.threeGangModel;
|
||||
} else if (state is UpdateGroupState) {
|
||||
groupThreeGangModel = state.threeGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: device == null
|
||||
? ThreeGangList(
|
||||
threeGangList: groupThreeGangModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<ThreeGangBloc>(context)
|
||||
.add(InitialEvent(groupScreen: device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<ThreeGangBloc>(context)
|
||||
.add(InitialEvent(groupScreen: device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeGangModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(
|
||||
ChangeFirstSwitchStatusEvent(
|
||||
value: threeGangModel.firstSwitch));
|
||||
},
|
||||
// control: DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// // code: 'switch_1',
|
||||
// code: device.status[0].code,
|
||||
// // value: true,
|
||||
// value: device.status[0].value,
|
||||
// ),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Bedside Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeGangModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(
|
||||
ChangeFirstSwitchStatusEvent(
|
||||
value: threeGangModel.firstSwitch));
|
||||
},
|
||||
// control: DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// // code: 'switch_1',
|
||||
// code: device.status[0].code,
|
||||
// // value: true,
|
||||
// value: device.status[0].value,
|
||||
// ),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeGangModel.secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(
|
||||
ChangeSecondSwitchStatusEvent(
|
||||
value: threeGangModel.secondSwitch));
|
||||
},
|
||||
// control: DeviceControlModel(
|
||||
// // deviceId: 'bfe10693d4fd263206ocq9',
|
||||
// // code: 'switch_2',
|
||||
// // value: true,
|
||||
// deviceId: device.uuid,
|
||||
// code: device.status[1].code,
|
||||
// value: device.status[1].value,
|
||||
// ),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Ceiling Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeGangModel.thirdSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(
|
||||
ChangeThirdSwitchStatusEvent(
|
||||
value: threeGangModel.thirdSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Spotlight",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Bedside Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
Column(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_1',
|
||||
// value: true,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_2',
|
||||
// value: true,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_3',
|
||||
// value: true,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
BlocProvider.of<ThreeGangBloc>(context)
|
||||
.add(AllOnEvent());
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: BodySmall(
|
||||
text: "On",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager
|
||||
.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "All On",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeGangModel.secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(
|
||||
ChangeSecondSwitchStatusEvent(
|
||||
value: threeGangModel.secondSwitch));
|
||||
},
|
||||
// control: DeviceControlModel(
|
||||
// // deviceId: 'bfe10693d4fd263206ocq9',
|
||||
// // code: 'switch_2',
|
||||
// // value: true,
|
||||
// deviceId: device.uuid,
|
||||
// code: device.status[1].code,
|
||||
// value: device.status[1].value,
|
||||
// ),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Ceiling Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
ScheduleScreen(
|
||||
device: device!,
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeGangModel.thirdSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(
|
||||
ChangeThirdSwitchStatusEvent(
|
||||
value: threeGangModel.thirdSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Spotlight",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_1',
|
||||
// value: true,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_2',
|
||||
// value: true,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_3',
|
||||
// value: true,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
BlocProvider.of<ThreeGangBloc>(context)
|
||||
.add(AllOnEvent());
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: BodySmall(
|
||||
text: "On",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color:
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "Timer",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_1',
|
||||
// value: false,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_2',
|
||||
// value: false,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_3',
|
||||
// value: false,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
BlocProvider.of<ThreeGangBloc>(context)
|
||||
.add(AllOffEvent());
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: BodySmall(
|
||||
text: "Off",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager
|
||||
.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "All Off",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "All On",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
ScheduleScreen(
|
||||
device: device!,
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "Timer",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_1',
|
||||
// value: false,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_2',
|
||||
// value: false,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
// DevicesCubit.getInstance().deviceControl(
|
||||
// DeviceControlModel(
|
||||
// deviceId: device.uuid,
|
||||
// code: 'switch_3',
|
||||
// value: false,
|
||||
// ),
|
||||
// device.uuid!,
|
||||
// );
|
||||
BlocProvider.of<ThreeGangBloc>(context)
|
||||
.add(AllOffEvent());
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: BodySmall(
|
||||
text: "Off",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color:
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "All Off",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|