Compare commits
20 Commits
SP-496
...
garage_doo
| Author | SHA1 | Date | |
|---|---|---|---|
| b89053c1fb | |||
| 281414ac41 | |||
| 208fbd63f3 | |||
| 3454f0e28d | |||
| 2d54d52061 | |||
| 4b45257aff | |||
| 8476b51049 | |||
| 5e046b1deb | |||
| 487c7c5514 | |||
| d9761168e6 | |||
| cc7af3e4e6 | |||
| b5af6add35 | |||
| 0d5492d626 | |||
| 908533dc9e | |||
| d75d438106 | |||
| b8b6ec67c7 | |||
| fed39b7198 | |||
| 5030b3f313 | |||
| c4ff19d471 | |||
| e1cd9e55c2 |
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"Scheduleapp"
|
||||
]
|
||||
}
|
||||
148
assets/icons/closed_garage_door.svg
Normal file
@ -0,0 +1,148 @@
|
||||
<svg width="290" height="290" viewBox="0 0 290 290" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_4111_484)">
|
||||
<rect x="20" y="20" width="250" height="250" rx="100" fill="#EDEDED"/>
|
||||
<path d="M92.5676 124.459H197.432V204.459H92.5676V124.459Z" fill="url(#paint0_linear_4111_484)"/>
|
||||
<path d="M92.5908 149.353H130.176V205H92.5908V149.353Z" fill="url(#paint1_linear_4111_484)"/>
|
||||
<g clip-path="url(#clip0_4111_484)">
|
||||
<path d="M92.5908 145.541H197.409V177.658H92.5908V145.541Z" fill="url(#paint2_linear_4111_484)"/>
|
||||
<path d="M92.7646 122.838H197.471V135.308H92.7646V122.838Z" fill="url(#paint3_linear_4111_484)"/>
|
||||
<path d="M92.7646 132.72H197.471V145.191H92.7646V132.72Z" fill="url(#paint4_linear_4111_484)"/>
|
||||
<path d="M92.7646 142.838H197.471V155.308H92.7646V142.838Z" fill="url(#paint5_linear_4111_484)"/>
|
||||
<path d="M92.7646 152.568H197.471V165.038H92.7646V152.568Z" fill="url(#paint6_linear_4111_484)"/>
|
||||
<path d="M92.7646 162.45H197.471V174.921H92.7646V162.45Z" fill="url(#paint7_linear_4111_484)"/>
|
||||
<path d="M92.7646 172.568H197.471V185.038H92.7646V172.568Z" fill="url(#paint8_linear_4111_484)"/>
|
||||
<path d="M92.7646 182.45H197.471V194.921H92.7646V182.45Z" fill="url(#paint9_linear_4111_484)"/>
|
||||
<path d="M92.7646 192.332H197.471V204.803H92.7646V192.332Z" fill="url(#paint10_linear_4111_484)"/>
|
||||
</g>
|
||||
<path d="M199.649 114.801L156.765 88.0353C153.522 86.0118 149.261 85 145 85C140.739 85 136.478 86.0118 133.235 88.0353L90.3513 114.801C87.0226 116.879 85 120.525 85 124.449V197.537C85 201.659 88.3412 205 92.4628 205C94.58 205 96.2965 203.284 96.2965 201.166V134.999C96.2965 130.646 99.8252 127.118 104.178 127.118H185.822C190.175 127.118 193.704 130.646 193.704 134.999V201.166C193.704 203.284 195.42 205 197.537 205C201.659 205 205 201.659 205 197.537V124.449C205 120.525 202.977 116.879 199.649 114.801Z" fill="url(#paint11_linear_4111_484)"/>
|
||||
<path d="M199.649 114.801L156.765 88.0353C153.522 86.0118 149.261 85 145 85C140.739 85 136.478 86.0118 133.235 88.0353L90.3513 114.801C87.0226 116.879 85 120.525 85 124.449V135.743C85 131.819 87.0226 128.172 90.3513 126.095L133.235 99.3287C136.478 97.3052 140.739 96.2934 145 96.2934C149.261 96.2934 153.522 97.3052 156.765 99.3287L199.649 126.095C202.977 128.172 205 131.819 205 135.743V124.449C205 120.525 202.977 116.879 199.649 114.801Z" fill="url(#paint12_linear_4111_484)"/>
|
||||
<path d="M131.593 111.677H158.407C159.926 111.677 161.156 110.446 161.156 108.928C161.156 107.41 159.926 106.179 158.407 106.179H131.593C130.074 106.179 128.844 107.41 128.844 108.928C128.844 110.446 130.075 111.677 131.593 111.677Z" fill="url(#paint13_linear_4111_484)"/>
|
||||
<path d="M131.593 121.795H158.407C159.926 121.795 161.156 120.564 161.156 119.046C161.156 117.527 159.926 116.297 158.407 116.297H131.593C130.074 116.297 128.844 117.528 128.844 119.046C128.844 120.564 130.075 121.795 131.593 121.795Z" fill="url(#paint14_linear_4111_484)"/>
|
||||
<path d="M205 135.744V197.536C205 199.598 204.165 201.464 202.814 202.814C201.464 204.165 199.598 205 197.536 205C195.419 205 193.704 203.285 193.704 201.167V134.998C193.704 130.647 190.174 127.118 185.821 127.118H104.179C99.8259 127.118 96.2965 130.647 96.2965 134.998V201.167C96.2965 202.226 95.8682 203.184 95.1741 203.878C94.48 204.572 93.5224 205 92.4635 205C88.3412 205 85 201.659 85 197.536V135.744C85 131.819 87.0235 128.172 90.3506 126.094L133.235 99.3294C136.478 97.3059 140.739 96.2941 145 96.2941C149.261 96.2941 153.522 97.3059 156.765 99.3294L199.649 126.094C202.976 128.172 205 131.819 205 135.744Z" fill="url(#paint15_linear_4111_484)"/>
|
||||
<path d="M145.236 89.7092C138.367 89.7092 131.708 91.6861 125.979 95.4266C124.456 96.4207 124.028 98.4609 125.022 99.9835L130.442 105.42C130.241 106.14 130.336 106.937 130.775 107.613L135.816 112.723C135.627 113.301 135.689 113.956 136.044 114.508L141.425 119.781C141.068 121.102 141.404 122.572 142.442 123.61L145.949 127.118H185.822C190.175 127.118 193.704 130.646 193.704 134.999V174.872L205 186.168V135.955L164.492 95.4266C158.763 91.6864 152.104 89.7092 145.236 89.7092Z" fill="url(#paint16_linear_4111_484)"/>
|
||||
<path d="M153.562 111.378C151.008 109.737 148.047 108.87 145 108.87C141.953 108.87 138.992 109.737 136.438 111.377C135.465 112.003 135.183 113.299 135.808 114.273C136.433 115.246 137.73 115.528 138.703 114.903C140.58 113.697 142.757 113.06 145 113.06C147.243 113.06 149.42 113.697 151.297 114.903C151.647 115.128 152.039 115.236 152.427 115.236C153.117 115.236 153.792 114.896 154.192 114.273C154.817 113.3 154.535 112.003 153.562 111.378Z" fill="url(#paint17_linear_4111_484)"/>
|
||||
<path d="M158.669 103.651C154.599 101.007 149.872 99.6099 145 99.6099C140.128 99.6099 135.401 101.007 131.331 103.651C130.083 104.461 129.729 106.13 130.539 107.377C131.35 108.625 133.018 108.98 134.266 108.169C137.46 106.094 141.172 104.998 145 104.998C148.828 104.998 152.54 106.094 155.734 108.169C156.187 108.464 156.696 108.604 157.199 108.604C158.08 108.604 158.944 108.172 159.46 107.377C160.271 106.13 159.917 104.461 158.669 103.651Z" fill="url(#paint18_linear_4111_484)"/>
|
||||
<path d="M164.256 95.1913C158.528 91.4508 151.869 89.4736 145 89.4736C138.131 89.4736 131.472 91.4506 125.744 95.1911C124.221 96.1852 123.792 98.2254 124.787 99.748C125.781 101.271 127.821 101.699 129.344 100.705C133.999 97.6654 139.413 96.0588 145 96.0588C150.587 96.0588 156.001 97.6654 160.656 100.705C161.212 101.068 161.836 101.241 162.453 101.241C163.528 101.241 164.582 100.716 165.213 99.7482C166.208 98.2256 165.779 96.1854 164.256 95.1913Z" fill="url(#paint19_linear_4111_484)"/>
|
||||
<path d="M145 124.532C147.182 124.532 148.951 122.763 148.951 120.581C148.951 118.399 147.182 116.63 145 116.63C142.818 116.63 141.049 118.399 141.049 120.581C141.049 122.763 142.818 124.532 145 124.532Z" fill="url(#paint20_linear_4111_484)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_4111_484" 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_4111_484"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4111_484" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_4111_484" x1="145" y1="154.648" x2="145" y2="196.939" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#62DBFB"/>
|
||||
<stop offset="0.1912" stop-color="#57D5FA"/>
|
||||
<stop offset="0.5232" stop-color="#3BC5F7"/>
|
||||
<stop offset="0.954" stop-color="#0DABF2"/>
|
||||
<stop offset="1" stop-color="#08A9F1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_4111_484" x1="105.706" y1="177.176" x2="93.7059" y2="177.176" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0593FC" stop-opacity="0"/>
|
||||
<stop offset="0.6831" stop-color="#0389FC" stop-opacity="0.683"/>
|
||||
<stop offset="1" stop-color="#0182FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_4111_484" x1="145" y1="164.717" x2="145" y2="148.715" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0593FC" stop-opacity="0"/>
|
||||
<stop offset="0.6831" stop-color="#0389FC" stop-opacity="0.683"/>
|
||||
<stop offset="1" stop-color="#0182FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_4111_484" x1="145.118" y1="127.544" x2="145.118" y2="134.136" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_4111_484" x1="145.118" y1="137.426" x2="145.118" y2="144.019" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_4111_484" x1="145.118" y1="147.544" x2="145.118" y2="154.136" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_4111_484" x1="145.118" y1="157.273" x2="145.118" y2="163.866" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_4111_484" x1="145.118" y1="167.156" x2="145.118" y2="173.748" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_4111_484" x1="145.118" y1="177.273" x2="145.118" y2="183.866" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_4111_484" x1="145.118" y1="187.156" x2="145.118" y2="193.748" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_4111_484" x1="145.118" y1="197.038" x2="145.118" y2="203.631" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint11_linear_4111_484" x1="112.144" y1="101.95" x2="168.144" y2="201.715" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint12_linear_4111_484" x1="145" y1="67.5915" x2="145" y2="137.895" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint13_linear_4111_484" x1="145" y1="110.944" x2="145" y2="105.881" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint14_linear_4111_484" x1="145" y1="121.061" x2="145" y2="115.998" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint15_linear_4111_484" x1="126.473" y1="129.525" x2="115.65" y2="108.113" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint16_linear_4111_484" x1="175.367" y1="132.235" x2="141.72" y2="85.8824" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint17_linear_4111_484" x1="143.315" y1="108.32" x2="146.188" y2="116.541" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint18_linear_4111_484" x1="142.584" y1="97.1318" x2="145.857" y2="109.025" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint19_linear_4111_484" x1="142.471" y1="88.6965" x2="145.983" y2="101.547" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint20_linear_4111_484" x1="141.169" y1="116.749" x2="147.514" y2="123.095" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_4111_484">
|
||||
<rect width="104.88" height="81.9651" fill="white" transform="translate(92.5908 122.838)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
32
assets/icons/curtainsIcon/right_vertical_blade.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<svg width="33" height="319" viewBox="0 0 33 319" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M32.675 6.07198V318.219L30.535 319V5.29102L32.675 6.07198Z" fill="url(#paint0_linear_4847_2158)"/>
|
||||
<path d="M0.525162 315.619L30.5352 319V5.29102L0.525162 8.68132V315.619Z" fill="url(#paint1_linear_4847_2158)"/>
|
||||
<path d="M17.9751 0.0722656H13.0851V7.5144C13.0851 8.50669 13.9651 9.31522 15.0451 9.31522H16.0151C17.0951 9.31522 17.9751 8.50669 17.9751 7.5144V0.0722656Z" fill="url(#paint2_linear_4847_2158)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_4847_2158" x1="82.145" y1="20.5612" x2="-9.30122" y2="323.172" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#E9E9E9"/>
|
||||
<stop offset="0.26" stop-color="#E4E4E4"/>
|
||||
<stop offset="0.51" stop-color="#D8D8D8"/>
|
||||
<stop offset="0.77" stop-color="#C4C4C4"/>
|
||||
<stop offset="0.78" stop-color="#C4C4C4"/>
|
||||
<stop offset="1" stop-color="#C6C6C6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_4847_2158" x1="30.5352" y1="-18.0001" x2="0.525162" y2="-18.0001" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F5F5F5"/>
|
||||
<stop offset="0.22" stop-color="#F0F0F0"/>
|
||||
<stop offset="0.45" stop-color="#E4E4E4"/>
|
||||
<stop offset="0.67" stop-color="#D0D0D0"/>
|
||||
<stop offset="0.78" stop-color="#C4C4C4"/>
|
||||
<stop offset="1" stop-color="#C6C6C6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_4847_2158" x1="17.9751" y1="-18.0002" x2="13.0851" y2="-18.0002" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#C4C4C4"/>
|
||||
<stop offset="0.41" stop-color="#F8F8F8"/>
|
||||
<stop offset="0.49" stop-color="#F0F0F0"/>
|
||||
<stop offset="0.6" stop-color="#DCDCDC"/>
|
||||
<stop offset="0.75" stop-color="#BABABA"/>
|
||||
<stop offset="0.79" stop-color="#AEAEAE"/>
|
||||
<stop offset="1" stop-color="#BEBEBE"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
135
assets/icons/garageIcon.svg
Normal file
@ -0,0 +1,135 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.52252 13.1532H37.4775V39.8199H2.52252V13.1532Z" fill="url(#paint0_linear_4625_5577)"/>
|
||||
<path d="M2.53027 21.4509H15.0588V39.9999H2.53027V21.4509Z" fill="url(#paint1_linear_4625_5577)"/>
|
||||
<g clip-path="url(#clip0_4625_5577)">
|
||||
<path d="M2.53027 20.1802H37.4697V30.8861H2.53027V20.1802Z" fill="url(#paint2_linear_4625_5577)"/>
|
||||
<path d="M2.5882 12.6127H37.4902V16.7695H2.5882V12.6127Z" fill="url(#paint3_linear_4625_5577)"/>
|
||||
<path d="M2.5882 15.9067H37.4902V20.0636H2.5882V15.9067Z" fill="url(#paint4_linear_4625_5577)"/>
|
||||
<path d="M2.5882 19.2793H37.4902V23.4362H2.5882V19.2793Z" fill="url(#paint5_linear_4625_5577)"/>
|
||||
<path d="M2.5882 22.5226H37.4902V26.6794H2.5882V22.5226Z" fill="url(#paint6_linear_4625_5577)"/>
|
||||
<path d="M2.5882 25.8167H37.4902V29.9735H2.5882V25.8167Z" fill="url(#paint7_linear_4625_5577)"/>
|
||||
<path d="M2.5882 29.1892H37.4902V33.3461H2.5882V29.1892Z" fill="url(#paint8_linear_4625_5577)"/>
|
||||
<path d="M2.5882 32.4834H37.4902V36.6403H2.5882V32.4834Z" fill="url(#paint9_linear_4625_5577)"/>
|
||||
<path d="M2.5882 35.7775H37.4902V39.9343H2.5882V35.7775Z" fill="url(#paint10_linear_4625_5577)"/>
|
||||
</g>
|
||||
<path d="M38.2162 9.93373L23.9216 1.01176C22.8408 0.337255 21.4204 0 20 0C18.5796 0 17.1592 0.337255 16.0784 1.01176L1.78376 9.93373C0.674196 10.6263 0 11.8418 0 13.1498V37.5124C0 38.8863 1.11373 40 2.48761 40C3.19333 40 3.76549 39.4278 3.76549 38.7221V16.6663C3.76549 15.2154 4.94173 14.0392 6.39255 14.0392H33.6075C35.0584 14.0392 36.2345 15.2154 36.2345 16.6663V38.7221C36.2345 39.4278 36.8067 40 37.5124 40C38.8863 40 40 38.8863 40 37.5124V13.1498C40 11.8418 39.3258 10.6263 38.2162 9.93373Z" fill="url(#paint11_linear_4625_5577)"/>
|
||||
<path d="M38.2162 9.93373L23.9216 1.01177C22.8408 0.337255 21.4204 0 20 0C18.5796 0 17.1592 0.337255 16.0784 1.01177L1.78376 9.93373C0.674196 10.6263 0 11.8418 0 13.1498V16.9144C0 15.6064 0.674196 14.3908 1.78376 13.6983L16.0784 4.77624C17.1592 4.10173 18.5796 3.76447 20 3.76447C21.4204 3.76447 22.8408 4.10173 23.9216 4.77624L38.2162 13.6982C39.3258 14.3908 40 15.6064 40 16.9143V13.1498C40 11.8418 39.3258 10.6263 38.2162 9.93373Z" fill="url(#paint12_linear_4625_5577)"/>
|
||||
<path d="M15.5309 8.89232H24.4691C24.9752 8.89232 25.3855 8.48205 25.3855 7.97601C25.3855 7.46989 24.9752 7.05969 24.4691 7.05969H15.5309C15.0248 7.05969 14.6146 7.46997 14.6146 7.97601C14.6146 8.48205 15.0248 8.89232 15.5309 8.89232Z" fill="url(#paint13_linear_4625_5577)"/>
|
||||
<path d="M15.5309 12.2649H24.4691C24.9752 12.2649 25.3855 11.8546 25.3855 11.3486C25.3855 10.8424 24.9752 10.4323 24.4691 10.4323H15.5309C15.0248 10.4323 14.6146 10.8425 14.6146 11.3486C14.6146 11.8546 15.0248 12.2649 15.5309 12.2649Z" fill="url(#paint14_linear_4625_5577)"/>
|
||||
<path d="M40 16.9145V37.5121C40 38.1992 39.7216 38.8211 39.2714 39.2713C38.8212 39.7215 38.1992 39.9999 37.5122 39.9999C36.8063 39.9999 36.2345 39.4282 36.2345 38.7223V16.6658C36.2345 15.2156 35.058 14.0392 33.6071 14.0392H6.39294C4.94196 14.0392 3.76549 15.2156 3.76549 16.6658V38.7223C3.76549 39.0752 3.62275 39.3945 3.39137 39.6258C3.16 39.8572 2.84078 39.9999 2.48784 39.9999C1.11373 39.9999 0 38.8862 0 37.5121V16.9145C0 15.6062 0.67451 14.3905 1.78353 13.698L16.0784 4.77641C17.1592 4.1019 18.5796 3.76465 20 3.76465C21.4204 3.76465 22.8408 4.1019 23.9216 4.77641L38.2165 13.698C39.3255 14.3905 40 15.6062 40 16.9145Z" fill="url(#paint15_linear_4625_5577)"/>
|
||||
<path d="M20.0785 1.5697C17.7889 1.5697 15.5693 2.22868 13.6597 3.47551C13.1522 3.80688 13.0093 4.48696 13.3407 4.99449L15.1474 6.8068C15.0804 7.04649 15.112 7.31245 15.2582 7.53755L16.9387 9.24084C16.8755 9.43363 16.8963 9.65206 17.0145 9.83598L18.8084 11.5936C18.6893 12.034 18.8014 12.5241 19.1472 12.8699L20.3165 14.0392H33.6074C35.0583 14.0392 36.2345 15.2154 36.2345 16.6663V29.9572L40 33.7227V16.9851L26.4972 3.47551C24.5877 2.22876 22.3681 1.5697 20.0785 1.5697Z" fill="url(#paint16_linear_4625_5577)"/>
|
||||
<path d="M22.8539 8.79254C22.0027 8.24564 21.0158 7.95654 20 7.95654C18.9843 7.95654 17.9974 8.24564 17.1461 8.79246C16.8216 9.00101 16.7276 9.43309 16.936 9.75756C17.1445 10.082 17.5766 10.1761 17.9011 9.96768C18.5267 9.5658 19.2525 9.35333 20 9.35333C20.7476 9.35333 21.4734 9.5658 22.0989 9.96768C22.2158 10.0427 22.3465 10.0786 22.4758 10.0786C22.7056 10.0786 22.9306 9.96525 23.064 9.75756C23.2725 9.43317 23.1785 9.00101 22.8539 8.79254Z" fill="url(#paint17_linear_4625_5577)"/>
|
||||
<path d="M24.5563 6.21705C23.1995 5.3358 21.624 4.87 20 4.87C18.376 4.87 16.8005 5.3358 15.4437 6.21698C15.0278 6.48709 14.9096 7.04325 15.1798 7.45917C15.4499 7.87509 16.0061 7.99321 16.422 7.72309C17.4868 7.03149 18.7241 6.66592 20 6.66592C21.2759 6.66592 22.5133 7.03149 23.578 7.72309C23.7291 7.82121 23.8987 7.86811 24.0663 7.86811C24.3602 7.86811 24.6482 7.72396 24.8202 7.45917C25.0904 7.04325 24.9722 6.48717 24.5563 6.21705Z" fill="url(#paint18_linear_4625_5577)"/>
|
||||
<path d="M26.4188 3.39709C24.5093 2.15027 22.2897 1.49121 20 1.49121C17.7104 1.49121 15.4908 2.15019 13.5812 3.39702C13.0737 3.72839 12.9308 4.40847 13.2622 4.916C13.5936 5.42353 14.2737 5.56635 14.7812 5.23498C16.333 4.2218 18.1377 3.68627 20 3.68627C21.8624 3.68627 23.667 4.2218 25.2188 5.23505C25.4039 5.35592 25.612 5.41372 25.8178 5.41372C26.1761 5.41372 26.5273 5.23851 26.7378 4.91607C27.0692 4.40854 26.9264 3.72847 26.4188 3.39709Z" fill="url(#paint19_linear_4625_5577)"/>
|
||||
<path d="M20 13.1773C20.7274 13.1773 21.317 12.5876 21.317 11.8602C21.317 11.1329 20.7274 10.5432 20 10.5432C19.2726 10.5432 18.683 11.1329 18.683 11.8602C18.683 12.5876 19.2726 13.1773 20 13.1773Z" fill="url(#paint20_linear_4625_5577)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_4625_5577" x1="20" y1="23.2161" x2="20" y2="37.3131" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#62DBFB"/>
|
||||
<stop offset="0.1912" stop-color="#57D5FA"/>
|
||||
<stop offset="0.5232" stop-color="#3BC5F7"/>
|
||||
<stop offset="0.954" stop-color="#0DABF2"/>
|
||||
<stop offset="1" stop-color="#08A9F1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_4625_5577" x1="6.90196" y1="30.7254" x2="2.90196" y2="30.7254" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0593FC" stop-opacity="0"/>
|
||||
<stop offset="0.6831" stop-color="#0389FC" stop-opacity="0.683"/>
|
||||
<stop offset="1" stop-color="#0182FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_4625_5577" x1="20" y1="26.5723" x2="20" y2="21.2385" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0593FC" stop-opacity="0"/>
|
||||
<stop offset="0.6831" stop-color="#0389FC" stop-opacity="0.683"/>
|
||||
<stop offset="1" stop-color="#0182FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_4625_5577" x1="20.0392" y1="14.1813" x2="20.0392" y2="16.3788" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_4625_5577" x1="20.0392" y1="17.4754" x2="20.0392" y2="19.6729" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_4625_5577" x1="20.0392" y1="20.8479" x2="20.0392" y2="23.0454" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_4625_5577" x1="20.0392" y1="24.0912" x2="20.0392" y2="26.2887" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_4625_5577" x1="20.0392" y1="27.3853" x2="20.0392" y2="29.5828" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_4625_5577" x1="20.0392" y1="30.7578" x2="20.0392" y2="32.9553" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_4625_5577" x1="20.0392" y1="34.052" x2="20.0392" y2="36.2495" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_4625_5577" x1="20.0392" y1="37.3461" x2="20.0392" y2="39.5436" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint11_linear_4625_5577" x1="9.048" y1="5.64996" x2="27.7147" y2="38.9049" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint12_linear_4625_5577" x1="20" y1="-5.80283" x2="20" y2="17.6317" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint13_linear_4625_5577" x1="20" y1="8.64785" x2="20" y2="6.96024" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint14_linear_4625_5577" x1="20" y1="12.0204" x2="20" y2="10.3328" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint15_linear_4625_5577" x1="13.8244" y1="14.8416" x2="10.2165" y2="7.70434" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint16_linear_4625_5577" x1="30.1222" y1="15.7451" x2="18.9065" y2="0.294096" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint17_linear_4625_5577" x1="19.4383" y1="7.77317" x2="20.3961" y2="10.5136" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint18_linear_4625_5577" x1="19.1947" y1="4.04396" x2="20.2856" y2="8.00827" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint19_linear_4625_5577" x1="19.157" y1="1.23215" x2="20.3277" y2="5.51576" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint20_linear_4625_5577" x1="18.7229" y1="10.5831" x2="20.8381" y2="12.6984" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_4625_5577">
|
||||
<rect width="34.9599" height="27.3217" fill="white" transform="translate(2.53027 12.6127)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
29
assets/icons/garage_countdown.svg
Normal file
@ -0,0 +1,29 @@
|
||||
<svg width="50" height="49" viewBox="0 0 50 49" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25.0508 13.2076H14.9395C14.5289 13.2076 14.1961 12.8749 14.1961 12.4643C14.1961 12.0536 14.5288 11.7209 14.9395 11.7209H25.0508C25.4613 11.7209 25.7941 12.0536 25.7941 12.4643C25.7941 12.8749 25.4613 13.2076 25.0508 13.2076ZM9.98643 13.2076H0.743359C0.332812 13.2076 0 12.8749 0 12.4643C0 12.0536 0.332715 11.7209 0.743359 11.7209H9.98643C10.397 11.7209 10.7298 12.0536 10.7298 12.4643C10.7298 12.8749 10.397 13.2076 9.98643 13.2076Z" fill="#D9EEFF"/>
|
||||
<path d="M10.7028 18.4107H3.71571C3.30516 18.4107 2.97235 18.078 2.97235 17.6674C2.97235 17.2568 3.30507 16.924 3.71571 16.924H10.7028C11.1134 16.924 11.4462 17.2567 11.4462 17.6674C11.4461 18.078 11.1134 18.4107 10.7028 18.4107Z" fill="#D9EEFF"/>
|
||||
<path d="M5.97168 28.8144H0.743359C0.332812 28.8144 0 28.4817 0 28.0711C0 27.6604 0.332715 27.3277 0.743359 27.3277H5.97168C6.38223 27.3277 6.71504 27.6604 6.71504 28.0711C6.71504 28.4817 6.38223 28.8144 5.97168 28.8144Z" fill="#D9EEFF"/>
|
||||
<path d="M11.717 34.0177H3.1454C2.73485 34.0177 2.40204 33.685 2.40204 33.2743C2.40204 32.8638 2.73475 32.531 3.1454 32.531H11.717C12.1275 32.531 12.4603 32.8637 12.4603 33.2743C12.4603 33.6849 12.1276 34.0177 11.717 34.0177Z" fill="#D9EEFF"/>
|
||||
<path d="M8.94401 39.2209H5.30299C4.89244 39.2209 4.55963 38.8882 4.55963 38.4775C4.55963 38.067 4.89235 37.7342 5.30299 37.7342H8.94401C9.35455 37.7342 9.68737 38.0669 9.68737 38.4775C9.68727 38.8882 9.35455 39.2209 8.94401 39.2209Z" fill="#D9EEFF"/>
|
||||
<path d="M20.6715 44.4241H9.68855C9.278 44.4241 8.94519 44.0914 8.94519 43.6808C8.94519 43.2702 9.27791 42.9374 9.68855 42.9374H20.6715C21.082 42.9374 21.4148 43.2701 21.4148 43.6808C21.4148 44.0913 21.0821 44.4241 20.6715 44.4241Z" fill="#D9EEFF"/>
|
||||
<path d="M12.6245 23.6139H6.84828C6.43773 23.6139 6.10492 23.2812 6.10492 22.8706C6.10492 22.4599 6.43763 22.1272 6.84828 22.1272H12.6245C13.035 22.1272 13.3678 22.4599 13.3678 22.8706C13.3678 23.2812 13.035 23.6139 12.6245 23.6139Z" fill="#D9EEFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M35.1365 4.34468L32.7766 11.0594C33.9959 11.2112 35.218 11.4836 36.4288 11.8826C37.6396 12.2815 38.7859 12.7901 39.8563 13.3913L42.2163 6.67652L35.1365 4.34468Z" fill="#EFF6FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.1587 0.754188L32.2849 3.40634C32.0967 3.97948 32.4086 4.60321 32.9817 4.7914L34.6618 5.34208L41.7387 7.67401L43.416 8.22753C43.9891 8.41581 44.6128 8.10106 44.801 7.52792L45.6748 4.87577C45.863 4.30263 45.5483 3.67889 44.9753 3.49071L34.5437 0.0545788C33.9706 -0.133702 33.3468 0.181044 33.1587 0.754188Z" fill="#375E7D"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.4159 8.22741C43.9891 8.41569 44.6127 8.10095 44.801 7.5278L45.6747 4.87566C45.8629 4.30251 45.5482 3.67878 44.9752 3.4906L42.3905 2.63933C42.9637 2.82761 43.2783 3.45124 43.09 4.02439L42.2163 6.67654C42.0281 7.24968 41.4044 7.56433 40.8312 7.37614H40.8369L41.7388 7.674L43.4159 8.22741Z" fill="#2B4D66"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.75 47.3444C34.8387 50.6653 45.7084 45.1811 49.0292 35.0949C51.9538 26.2196 48.0571 16.7375 40.2075 12.3238C39.1371 11.7225 37.9909 11.214 36.78 10.8151C35.569 10.4162 34.347 10.1436 33.1277 9.99197C28.8714 9.46101 24.6545 10.3881 21.0864 12.4643C17.1673 14.7457 14.0319 18.4177 12.5036 23.0646C9.18007 33.1507 14.6641 44.0235 24.75 47.3444Z" fill="#375E7D"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M35.454 14.8466C27.5932 12.2563 19.1228 16.5324 16.5325 24.3934C13.945 32.2545 18.2181 40.7252 26.0789 43.3128C33.9398 45.9031 42.4102 41.6298 45.0005 33.7688L45.0089 33.7407C47.5795 25.8881 43.3064 17.4314 35.454 14.8466Z" fill="#EFF6FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M35.454 14.8467L31.5488 26.7028C31.0965 28.0739 31.9675 29.3662 33.1249 29.8271L45.0089 33.7407C47.5795 25.8881 43.3063 17.4314 35.454 14.8467Z" fill="#EB5468"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M45.0088 33.7407C47.2621 26.8574 44.2559 19.5106 38.1931 16.0605C39.2579 19.238 39.8451 22.733 39.8451 26.4023C39.8451 28.2847 39.6906 30.1221 39.3956 31.8921L45.0088 33.7407Z" fill="#E5384F"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.0292 35.0949C51.9538 26.2196 48.0571 16.7375 40.2075 12.3238C39.4209 11.8799 38.5921 11.4894 37.7267 11.1551C37.4149 11.0343 37.1003 10.9219 36.78 10.8151C36.4035 10.6915 36.027 10.5791 35.6477 10.4808C36.6647 12.189 37.5244 14.0629 38.1931 16.0604C44.2558 19.5105 47.2619 26.8574 45.0088 33.7407C45.0059 33.7491 45.0031 33.7576 45.0004 33.7688C43.3906 38.6518 39.5136 42.1496 34.9229 43.4785C33.6896 45.3271 32.2624 46.9567 30.6779 48.3137C38.7888 48.353 46.3546 43.2172 49.0292 35.0949Z" fill="#2B4D66"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M34.9229 43.4785C39.5135 42.1496 43.3906 38.6517 45.0004 33.7688L45.0088 33.7407L39.3955 31.8921C38.8729 35.0359 37.9121 37.9719 36.5972 40.5931C36.0888 41.6046 35.5297 42.5682 34.9229 43.4785Z" fill="#D9EEFF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.2076 12.3237L41.7387 7.67401L40.8313 7.37616L39.1541 6.82265L37.7268 11.155C38.5921 11.4893 39.4209 11.8799 40.2076 12.3237Z" fill="#D9EEFF"/>
|
||||
<path d="M26.0958 44.0056C26.0188 44.0056 25.9404 43.9935 25.8631 43.968C25.4732 43.8396 25.2612 43.4194 25.3898 43.0295L26.1905 40.5992C26.3188 40.2092 26.7386 39.9971 27.129 40.1258C27.519 40.2543 27.731 40.6745 27.6024 41.0644L26.8017 43.4947C26.6987 43.8075 26.408 44.0056 26.0958 44.0056Z" fill="#375E7D"/>
|
||||
<path d="M18.9963 25.9181C18.9192 25.9181 18.8407 25.906 18.7633 25.8804L16.336 25.0796C15.9461 24.9511 15.7343 24.5308 15.863 24.1408C15.9916 23.7511 16.4114 23.5388 16.8018 23.6679L19.2292 24.4687C19.619 24.5972 19.8308 25.0175 19.7021 25.4074C19.599 25.7199 19.3085 25.9181 18.9963 25.9181Z" fill="#375E7D"/>
|
||||
<path d="M25.1917 18.7256C24.9202 18.7256 24.6586 18.5762 24.5277 18.3175L23.373 16.0333C23.1877 15.667 23.3347 15.2198 23.701 15.0345C24.0674 14.8496 24.5146 14.9963 24.6997 15.3626L25.8545 17.6468C26.0398 18.0131 25.8928 18.4602 25.5265 18.6455C25.419 18.6998 25.3045 18.7256 25.1917 18.7256Z" fill="#375E7D"/>
|
||||
<path d="M37.5139 43.1515C37.2421 43.1515 36.9803 43.0019 36.8496 42.7428L35.6978 40.4586C35.5129 40.0921 35.6602 39.645 36.0268 39.4602C36.3932 39.2753 36.8403 39.4225 37.0251 39.7892L38.177 42.0734C38.3618 42.4399 38.2146 42.887 37.848 43.0718C37.7406 43.1259 37.6264 43.1515 37.5139 43.1515Z" fill="#375E7D"/>
|
||||
<path d="M17.4207 36.5353C17.1489 36.5353 16.8871 36.3857 16.7564 36.1265C16.5716 35.76 16.7188 35.313 17.0854 35.1281L19.3696 33.9762C19.736 33.791 20.1832 33.9385 20.368 34.3052C20.5528 34.6717 20.4056 35.1187 20.0389 35.3035L17.7548 36.4555C17.6474 36.5096 17.5333 36.5353 17.4207 36.5353Z" fill="#375E7D"/>
|
||||
<path d="M28.7476 28.1964C28.5688 28.1964 28.3896 28.1323 28.247 28.0025L22.85 23.0829C22.5467 22.8063 22.5249 22.3362 22.8014 22.0328C23.0779 21.7294 23.548 21.7077 23.8515 21.9842L29.2485 26.9037C29.5518 27.1804 29.5736 27.6504 29.297 27.9538C29.1505 28.1147 28.9494 28.1964 28.7476 28.1964Z" fill="#375E7D"/>
|
||||
<path d="M31.4073 35.0686C31.0354 35.0686 30.7143 34.79 30.67 34.4114L30.3441 31.6216C30.2965 31.2139 30.5884 30.8447 30.9962 30.7971C31.4024 30.7501 31.7731 31.0412 31.8207 31.4491L32.1466 34.239C32.1942 34.6467 31.9023 35.0158 31.4945 35.0635C31.4653 35.0668 31.4362 35.0686 31.4073 35.0686Z" fill="#375E7D"/>
|
||||
<path d="M30.7842 44.8168C29.1281 44.8168 27.4649 44.552 25.8462 44.0187C17.6097 41.3075 13.1147 32.3994 15.8264 24.1612C17.1414 20.1702 19.9313 16.93 23.6818 15.0373C27.4331 13.1443 31.6965 12.8261 35.6866 14.1409C43.9069 16.8469 48.4056 25.7377 45.7183 33.9632L45.7125 33.9826C45.7106 33.989 45.7086 33.9953 45.7066 34.0017C44.3916 37.9922 41.6018 41.2319 37.851 43.1239C35.6214 44.2482 33.2107 44.8168 30.7842 44.8168ZM30.7519 14.8303C28.554 14.8303 26.3711 15.3453 24.3517 16.3644C20.9554 18.0782 18.4292 21.0123 17.2384 24.6261C14.783 32.0855 18.853 40.1517 26.3112 42.6066C29.9246 43.7974 33.785 43.5096 37.1814 41.7964C40.5747 40.0847 43.0995 37.1548 44.2915 33.5454L44.297 33.5271C44.2987 33.5213 44.3006 33.5153 44.3025 33.5096C46.7413 26.0592 42.6677 18.0039 35.2216 15.5527C35.2215 15.5527 35.2214 15.5526 35.2213 15.5526C33.7565 15.0699 32.2507 14.8303 30.7519 14.8303Z" fill="#FFC250"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M31.5489 26.7028C30.2509 26.2758 28.8518 26.981 28.4247 28.279C27.9977 29.577 28.7029 30.9762 30.0008 31.4032C31.2988 31.8303 32.6979 31.1251 33.1249 29.8271C33.552 28.5291 32.8468 27.1299 31.5489 26.7028Z" fill="#FFE07D"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M33.1249 29.8271C33.552 28.5291 32.8468 27.1299 31.5489 26.7029C30.8718 26.4809 30.1666 26.5652 29.5851 26.8826C30.7847 27.3658 31.4197 28.706 31.0095 29.9534C30.8044 30.5715 30.3802 31.0575 29.8492 31.3497C29.8998 31.3694 29.9504 31.3863 30.0009 31.4031C31.2989 31.8303 32.698 31.1251 33.1249 29.8271Z" fill="#FFE07D"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.7 KiB |
11
assets/icons/garage_preferences_icon.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="46" height="50" viewBox="0 0 46 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.15027 2.12148V47.8785C4.15027 49.0502 5.10007 50 6.27175 50C7.44343 50 8.39324 49.0502 8.39324 47.8785V2.12148C8.39314 0.949805 7.44333 0 6.27175 0C5.10017 0 4.15027 0.949805 4.15027 2.12148Z" fill="#655E67"/>
|
||||
<path d="M20.7635 2.12148V47.8785C20.7635 49.0502 21.7134 50 22.885 50C24.0567 50 25.0065 49.0502 25.0065 47.8785V2.12148C25.0065 0.949805 24.0567 0 22.885 0C21.7134 0 20.7635 0.949805 20.7635 2.12148Z" fill="#655E67"/>
|
||||
<path d="M37.3768 2.12148V47.8785C37.3768 49.0502 38.3266 50 39.4983 50C40.67 50 41.6198 49.0502 41.6198 47.8785V2.12148C41.6198 0.949805 40.67 0 39.4983 0C38.3266 0 37.3768 0.949805 37.3768 2.12148Z" fill="#655E67"/>
|
||||
<path d="M0 15.1651V20.7505C0 21.3062 0.450391 21.7566 1.00605 21.7566H11.5375C12.0932 21.7566 12.5436 21.3062 12.5436 20.7505V15.1651C12.5436 14.6094 12.0932 14.159 11.5375 14.159H1.00605C0.450391 14.159 0 14.6094 0 15.1651Z" fill="#717ED4"/>
|
||||
<path d="M16.6133 29.2496V34.835C16.6133 35.3907 17.0637 35.8411 17.6193 35.8411H28.1508C28.7064 35.8411 29.1568 35.3907 29.1568 34.835V29.2496C29.1568 28.6939 28.7064 28.2435 28.1508 28.2435H17.6193C17.0638 28.2436 16.6133 28.694 16.6133 29.2496Z" fill="#F9BF64"/>
|
||||
<path d="M33.2266 15.1651V20.7505C33.2266 21.3062 33.677 21.7566 34.2327 21.7566H44.7641C45.3198 21.7566 45.7702 21.3062 45.7702 20.7505V15.1651C45.7702 14.6094 45.3198 14.159 44.7641 14.159H34.2326C33.677 14.159 33.2266 14.6094 33.2266 15.1651Z" fill="#DF646E"/>
|
||||
<path d="M44.7641 14.159H41.746C42.3017 14.159 42.7521 14.6094 42.7521 15.1651V20.7505C42.7521 21.3061 42.3017 21.7566 41.746 21.7566H44.7641C45.3198 21.7566 45.7702 21.3062 45.7702 20.7505V15.1651C45.7702 14.6094 45.3198 14.159 44.7641 14.159Z" fill="#D82F3C"/>
|
||||
<path d="M28.1508 28.2435H25.1327C25.6884 28.2435 26.1387 28.6939 26.1387 29.2496V34.835C26.1387 35.3907 25.6884 35.8411 25.1327 35.8411H28.1508C28.7064 35.8411 29.1568 35.3907 29.1568 34.835V29.2496C29.1568 28.6939 28.7063 28.2435 28.1508 28.2435Z" fill="#E9A761"/>
|
||||
<path d="M11.5375 14.159H8.51941C9.07507 14.159 9.52546 14.6094 9.52546 15.1651V20.7505C9.52546 21.3061 9.07507 21.7566 8.51941 21.7566H11.5375C12.0931 21.7566 12.5435 21.3062 12.5435 20.7505V15.1651C12.5434 14.6094 12.093 14.159 11.5375 14.159Z" fill="#5766CC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
28
assets/icons/garage_schedule.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.8179 47.6354C36.972 47.6354 47.6355 36.9719 47.6355 23.8178C47.6355 10.6636 36.972 9.15527e-05 23.8179 9.15527e-05C10.6637 9.15527e-05 0.000183105 10.6636 0.000183105 23.8178C0.000183105 36.9719 10.6637 47.6354 23.8179 47.6354Z" fill="#F07281"/>
|
||||
<path d="M24.8239 47.6147C24.4909 47.6287 24.1549 47.6357 23.8179 47.6357C10.664 47.6357 0 36.9718 0 23.8179C0 10.664 10.664 0 23.8179 0C24.1549 0 24.4909 0.00703125 24.8239 0.0210938C12.1367 0.548242 2.01201 11.001 2.01201 23.8179C2.01201 36.6348 12.1367 47.0875 24.8239 47.6147Z" fill="#EB5569"/>
|
||||
<path d="M23.8181 44.5108C35.2465 44.5108 44.5111 35.2463 44.5111 23.8178C44.5111 12.3894 35.2465 3.12488 23.8181 3.12488C12.3897 3.12488 3.12512 12.3894 3.12512 23.8178C3.12512 35.2463 12.3897 44.5108 23.8181 44.5108Z" fill="#EAF6FF"/>
|
||||
<path d="M25.3269 44.4567C24.8289 44.4929 24.3248 44.511 23.8178 44.511C12.3892 44.511 3.12463 35.2465 3.12463 23.8178C3.12463 12.3892 12.3893 3.12468 23.8179 3.12468C24.3249 3.12468 24.8289 3.14275 25.327 3.17898C14.6026 3.95173 6.1428 12.8964 6.1428 23.8178C6.1428 34.7393 14.6026 43.6841 25.3269 44.4567Z" fill="#D8ECFE"/>
|
||||
<path d="M22.5243 11.7706L23.448 11.1759C23.6734 11.0308 23.9627 11.0308 24.1881 11.1759L25.1119 11.7706C25.2793 11.8785 25.3806 12.0641 25.3806 12.2633V24.0946H22.2556V12.2633C22.2555 12.0641 22.3568 11.8786 22.5243 11.7706Z" fill="#5680A6"/>
|
||||
<path d="M24.8239 11.5855L24.2675 11.9437V24.0945H22.2554V12.3165C22.2554 12.0841 22.3735 11.8676 22.5689 11.7418L23.4476 11.176C23.673 11.0309 23.9625 11.0309 24.1879 11.176L24.8239 11.5855Z" fill="#497090"/>
|
||||
<path d="M33.5805 24.188L33.0147 25.0668C32.8888 25.2622 32.6724 25.3803 32.44 25.3803H23.8179V22.2556H32.44C32.6724 22.2556 32.8889 22.3737 33.0147 22.5691L33.5805 23.4479C33.7256 23.6733 33.7256 23.9626 33.5805 24.188Z" fill="#5680A6"/>
|
||||
<path d="M28.018 23.8179C28.018 24.3702 27.9114 24.8974 27.7162 25.3803H23.8177V22.2556H27.7162C27.9114 22.7385 28.018 23.2656 28.018 23.8179Z" fill="#497090"/>
|
||||
<path d="M23.818 26.0059C25.0265 26.0059 26.0061 25.0263 26.0061 23.8179C26.0061 22.6094 25.0265 21.6298 23.818 21.6298C22.6096 21.6298 21.6299 22.6094 21.6299 23.8179C21.6299 25.0263 22.6096 26.0059 23.818 26.0059Z" fill="#F07281"/>
|
||||
<path d="M24.8239 25.7606C24.5231 25.9175 24.181 26.0061 23.8178 26.0061C22.6096 26.0061 21.6298 25.0262 21.6298 23.818C21.6298 22.6098 22.6096 21.6299 23.8178 21.6299C24.181 21.6299 24.5231 21.7185 24.8239 21.8754C24.1217 22.2386 23.6418 22.973 23.6418 23.8181C23.6418 24.6632 24.1217 25.3974 24.8239 25.7606Z" fill="#EB5569"/>
|
||||
<path d="M49.3331 41.0217V39.4608C49.3331 39.1491 49.1221 38.8768 48.8203 38.7989L47.1254 38.3615C46.9368 37.6012 46.637 36.8848 46.2431 36.2311L47.1322 34.7235C47.2906 34.455 47.2471 34.1134 47.0267 33.8929L45.923 32.7891C45.7026 32.5687 45.3609 32.5253 45.0923 32.6837L43.5847 33.5727C42.9311 33.1788 42.2147 32.8791 41.4543 32.6904L41.0169 30.9956C40.939 30.6937 40.6667 30.4828 40.355 30.4828H38.7942C38.4825 30.4828 38.2102 30.6937 38.1323 30.9956L37.6949 32.6904C36.9345 32.8791 36.2181 33.1789 35.5645 33.5727L34.0569 32.6837C33.7883 32.5253 33.4467 32.5687 33.2262 32.7891L32.1225 33.8929C31.9021 34.1133 31.8587 34.455 32.017 34.7235L32.9061 36.2311C32.5122 36.8848 32.2124 37.6012 32.0238 38.3615L30.329 38.7989C30.0271 38.8768 29.8162 39.1491 29.8162 39.4608V41.0217C29.8162 41.3334 30.0271 41.6057 30.329 41.6836L32.0238 42.121C32.2124 42.8813 32.5123 43.5977 32.9061 44.2514L32.017 45.759C31.8586 46.0275 31.9021 46.3691 32.1225 46.5896L33.2262 47.6933C33.4466 47.9138 33.7883 47.9571 34.0569 47.7988L35.5645 46.9098C36.2181 47.3037 36.9345 47.6034 37.6949 47.7921L38.1323 49.4869C38.2102 49.7888 38.4825 49.9997 38.7942 49.9997H40.355C40.6667 49.9997 40.939 49.7888 41.0169 49.4869L41.4543 47.7921C42.2147 47.6034 42.9311 47.3036 43.5847 46.9098L45.0923 47.7988C45.3609 47.9572 45.7025 47.9138 45.923 47.6933L47.0267 46.5896C47.2471 46.3692 47.2905 46.0275 47.1322 45.759L46.2431 44.2514C46.6371 43.5977 46.9368 42.8813 47.1254 42.121L48.8203 41.6836C49.1221 41.6057 49.3331 41.3334 49.3331 41.0217Z" fill="#88B4F5"/>
|
||||
<path d="M31.8289 38.9315V41.5513L34.0362 42.1207C34.2243 42.8812 34.5241 43.5976 34.9185 44.2515L33.7606 46.2152L34.8662 47.3209L34.0568 47.7983C33.7882 47.9567 33.4465 47.9134 33.2261 47.6929L32.1229 46.5896C31.9025 46.3692 31.8591 46.0275 32.0174 45.7591L32.9064 44.2515C32.512 43.5976 32.2122 42.8812 32.0241 42.1207L30.3296 41.6836C30.0278 41.6058 29.8168 41.3334 29.8168 41.0217V39.4609C29.8168 39.1493 30.0277 38.877 30.3294 38.7991L32.0242 38.3611C32.2122 37.6016 32.512 36.8843 32.9065 36.2313L32.0174 34.7235C31.8591 34.4551 31.9025 34.1135 32.1228 33.8931L33.2262 32.7891C33.4466 32.5685 33.7884 32.5251 34.057 32.6835L34.8662 33.1608L33.7606 34.2676L34.9185 36.2313C34.5242 36.8843 34.2244 37.6016 34.0362 38.3611L31.8289 38.9315Z" fill="#6EA2F2"/>
|
||||
<path d="M39.7071 47.7918L40.2766 50H38.7941C38.4823 50 38.2101 49.7891 38.1322 49.4871L37.695 47.7918C37.3379 47.7043 36.9897 47.5906 36.6538 47.4538L37.5764 46.9096C38.2303 47.3038 38.9466 47.6036 39.7071 47.7918Z" fill="#6EA2F2"/>
|
||||
<path d="M38.7941 30.4829H40.2766L39.7071 32.6901C38.9466 32.8793 38.2303 33.1791 37.5764 33.5725L36.6538 33.0282C36.9898 32.8924 37.3379 32.7787 37.695 32.6902L38.1321 30.9958C38.2101 30.6938 38.4824 30.4829 38.7941 30.4829Z" fill="#6EA2F2"/>
|
||||
<path d="M39.5747 44.9442C42.1721 44.9442 44.2778 42.8386 44.2778 40.2412C44.2778 37.6438 42.1721 35.5382 39.5747 35.5382C36.9773 35.5382 34.8717 37.6438 34.8717 40.2412C34.8717 42.8386 36.9773 44.9442 39.5747 44.9442Z" fill="#5680A6"/>
|
||||
<path d="M41.0834 44.6971C40.6096 44.8581 40.1015 44.9446 39.5743 44.9446C36.9777 44.9446 34.8721 42.8389 34.8721 40.2414C34.8721 37.6438 36.9777 35.5382 39.5743 35.5382C40.1015 35.5382 40.6095 35.6247 41.0834 35.7856C39.2272 36.4144 37.8902 38.1719 37.8902 40.2414C37.8902 42.3108 39.2272 44.0683 41.0834 44.6971Z" fill="#497090"/>
|
||||
<path d="M23.8181 8.84687C23.4014 8.84687 23.0636 8.50908 23.0636 8.09238V6.14326C23.0636 5.72656 23.4014 5.38876 23.8181 5.38876C24.2348 5.38876 24.5726 5.72656 24.5726 6.14326V8.09228C24.5726 8.50898 24.2348 8.84687 23.8181 8.84687Z" fill="#88B4F5"/>
|
||||
<path d="M23.8181 42.2471C23.4014 42.2471 23.0636 41.9093 23.0636 41.4926V39.5435C23.0636 39.1268 23.4014 38.789 23.8181 38.789C24.2348 38.789 24.5726 39.1268 24.5726 39.5435V41.4926C24.5726 41.9092 24.2348 42.2471 23.8181 42.2471Z" fill="#88B4F5"/>
|
||||
<path d="M8.09249 24.5725H6.14347C5.72677 24.5725 5.38898 24.2347 5.38898 23.818C5.38898 23.4013 5.72677 23.0635 6.14347 23.0635H8.09249C8.50919 23.0635 8.84699 23.4013 8.84699 23.818C8.84699 24.2347 8.50919 24.5725 8.09249 24.5725Z" fill="#88B4F5"/>
|
||||
<path d="M41.4927 24.5725H39.5437C39.1269 24.5725 38.7892 24.2347 38.7892 23.818C38.7892 23.4013 39.127 23.0635 39.5437 23.0635H41.4927C41.9095 23.0635 42.2472 23.4013 42.2472 23.818C42.2472 24.2347 41.9094 24.5725 41.4927 24.5725Z" fill="#88B4F5"/>
|
||||
<path d="M8.51212 33.4099C8.25138 33.4099 7.99777 33.2746 7.85802 33.0325C7.64962 32.6716 7.77325 32.2101 8.13419 32.0018L9.82208 31.0273C10.1827 30.8191 10.6443 30.9425 10.8527 31.3035C11.0611 31.6643 10.9375 32.1258 10.5766 32.3341L8.88868 33.3086C8.76993 33.3773 8.64015 33.4099 8.51212 33.4099Z" fill="#88B4F5"/>
|
||||
<path d="M37.4376 16.7098C37.1769 16.7098 36.9233 16.5744 36.7835 16.3323C36.5751 15.9715 36.6989 15.51 37.0597 15.3017L38.7476 14.3272C39.1083 14.1189 39.5699 14.2424 39.7783 14.6033C39.9867 14.9642 39.8629 15.4257 39.5021 15.634L37.8142 16.6085C37.6954 16.6772 37.5656 16.7098 37.4376 16.7098Z" fill="#88B4F5"/>
|
||||
<path d="M10.1986 16.7097C10.0706 16.7097 9.94093 16.6771 9.82208 16.6085L8.13419 15.634C7.77325 15.4256 7.64962 14.9641 7.85802 14.6033C8.06632 14.2424 8.52775 14.1186 8.88868 14.3271L10.5766 15.3016C10.9375 15.51 11.0611 15.9715 10.8527 16.3323C10.713 16.5744 10.4594 16.7097 10.1986 16.7097Z" fill="#88B4F5"/>
|
||||
<path d="M14.9801 39.8791C14.8521 39.8791 14.7224 39.8465 14.6036 39.7779C14.2426 39.5695 14.119 39.108 14.3274 38.7472L15.3019 37.0593C15.5102 36.6984 15.9717 36.5746 16.3326 36.7831C16.6935 36.9915 16.8171 37.453 16.6087 37.8138L15.6342 39.5017C15.4945 39.7438 15.2409 39.8791 14.9801 39.8791Z" fill="#88B4F5"/>
|
||||
<path d="M31.6802 10.9538C31.5522 10.9538 31.4225 10.9212 31.3037 10.8525C30.9428 10.6442 30.8191 10.1827 31.0275 9.82184L32.002 8.13395C32.2103 7.77301 32.6716 7.64938 33.0327 7.85778C33.3935 8.06608 33.5172 8.5276 33.3088 8.88844L32.3343 10.5763C32.1946 10.8184 31.941 10.9538 31.6802 10.9538Z" fill="#88B4F5"/>
|
||||
<path d="M15.956 10.9538C15.6953 10.9538 15.4416 10.8184 15.3019 10.5763L14.3274 8.88845C14.119 8.52761 14.2426 8.06609 14.6036 7.85779C14.9643 7.64939 15.4259 7.77303 15.6342 8.13396L16.6087 9.82185C16.8171 10.1827 16.6935 10.6442 16.3326 10.8525C16.2138 10.9211 16.084 10.9538 15.956 10.9538Z" fill="#88B4F5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.7 KiB |
117
assets/icons/open_garage_door.svg
Normal file
@ -0,0 +1,117 @@
|
||||
<svg width="290" height="290" viewBox="0 0 290 290" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_4111_515)">
|
||||
<rect x="20" y="20" width="250" height="250" rx="100" fill="#EDEDED"/>
|
||||
<path d="M92.5676 124.459H197.432V204.459H92.5676V124.459Z" fill="url(#paint0_linear_4111_515)"/>
|
||||
<path d="M92.5908 149.353H130.176V205H92.5908V149.353Z" fill="url(#paint1_linear_4111_515)"/>
|
||||
<g clip-path="url(#clip0_4111_515)">
|
||||
<path d="M92.7646 117.568H197.471V130.038H92.7646V117.568Z" fill="url(#paint2_linear_4111_515)"/>
|
||||
<path d="M92.7646 127.45H197.471V139.921H92.7646V127.45Z" fill="url(#paint3_linear_4111_515)"/>
|
||||
<path d="M92.7646 137.332H197.471V149.803H92.7646V137.332Z" fill="url(#paint4_linear_4111_515)"/>
|
||||
</g>
|
||||
<path d="M199.649 114.801L156.765 88.0353C153.522 86.0118 149.261 85 145 85C140.739 85 136.478 86.0118 133.235 88.0353L90.3513 114.801C87.0226 116.879 85 120.525 85 124.449V197.537C85 201.659 88.3412 205 92.4628 205C94.58 205 96.2965 203.284 96.2965 201.166V134.999C96.2965 130.646 99.8252 127.118 104.178 127.118H185.822C190.175 127.118 193.704 130.646 193.704 134.999V201.166C193.704 203.284 195.42 205 197.537 205C201.659 205 205 201.659 205 197.537V124.449C205 120.525 202.977 116.879 199.649 114.801Z" fill="url(#paint5_linear_4111_515)"/>
|
||||
<path d="M199.649 114.801L156.765 88.0353C153.522 86.0118 149.261 85 145 85C140.739 85 136.478 86.0118 133.235 88.0353L90.3513 114.801C87.0226 116.879 85 120.525 85 124.449V135.743C85 131.819 87.0226 128.172 90.3513 126.095L133.235 99.3287C136.478 97.3052 140.739 96.2934 145 96.2934C149.261 96.2934 153.522 97.3052 156.765 99.3287L199.649 126.095C202.977 128.172 205 131.819 205 135.743V124.449C205 120.525 202.977 116.879 199.649 114.801Z" fill="url(#paint6_linear_4111_515)"/>
|
||||
<path d="M131.593 111.677H158.407C159.926 111.677 161.156 110.446 161.156 108.928C161.156 107.41 159.926 106.179 158.407 106.179H131.593C130.074 106.179 128.844 107.41 128.844 108.928C128.844 110.446 130.075 111.677 131.593 111.677Z" fill="url(#paint7_linear_4111_515)"/>
|
||||
<path d="M131.593 121.795H158.407C159.926 121.795 161.156 120.564 161.156 119.046C161.156 117.527 159.926 116.297 158.407 116.297H131.593C130.074 116.297 128.844 117.528 128.844 119.046C128.844 120.564 130.075 121.795 131.593 121.795Z" fill="url(#paint8_linear_4111_515)"/>
|
||||
<path d="M205 135.744V197.536C205 199.598 204.165 201.464 202.814 202.814C201.464 204.165 199.598 205 197.536 205C195.419 205 193.704 203.285 193.704 201.167V134.998C193.704 130.647 190.174 127.118 185.821 127.118H104.179C99.8259 127.118 96.2965 130.647 96.2965 134.998V201.167C96.2965 202.226 95.8682 203.184 95.1741 203.878C94.48 204.572 93.5224 205 92.4635 205C88.3412 205 85 201.659 85 197.536V135.744C85 131.819 87.0235 128.172 90.3506 126.094L133.235 99.3294C136.478 97.3059 140.739 96.2941 145 96.2941C149.261 96.2941 153.522 97.3059 156.765 99.3294L199.649 126.094C202.976 128.172 205 131.819 205 135.744Z" fill="url(#paint9_linear_4111_515)"/>
|
||||
<path d="M145.236 89.7092C138.367 89.7092 131.708 91.6861 125.979 95.4266C124.456 96.4207 124.028 98.4609 125.022 99.9835L130.442 105.42C130.241 106.14 130.336 106.937 130.775 107.613L135.816 112.723C135.627 113.301 135.689 113.956 136.044 114.508L141.425 119.781C141.068 121.102 141.404 122.572 142.442 123.61L145.949 127.118H185.822C190.175 127.118 193.704 130.646 193.704 134.999V174.872L205 186.168V135.955L164.492 95.4266C158.763 91.6864 152.104 89.7092 145.236 89.7092Z" fill="url(#paint10_linear_4111_515)"/>
|
||||
<path d="M153.562 111.378C151.008 109.737 148.047 108.87 145 108.87C141.953 108.87 138.992 109.737 136.438 111.377C135.465 112.003 135.183 113.299 135.808 114.273C136.433 115.246 137.73 115.528 138.703 114.903C140.58 113.697 142.757 113.06 145 113.06C147.243 113.06 149.42 113.697 151.297 114.903C151.647 115.128 152.039 115.236 152.427 115.236C153.117 115.236 153.792 114.896 154.192 114.273C154.817 113.3 154.535 112.003 153.562 111.378Z" fill="url(#paint11_linear_4111_515)"/>
|
||||
<path d="M158.669 103.651C154.599 101.007 149.872 99.6099 145 99.6099C140.128 99.6099 135.401 101.007 131.331 103.651C130.083 104.461 129.729 106.13 130.539 107.377C131.35 108.625 133.018 108.98 134.266 108.169C137.46 106.094 141.172 104.998 145 104.998C148.828 104.998 152.54 106.094 155.734 108.169C156.187 108.464 156.696 108.604 157.199 108.604C158.08 108.604 158.944 108.172 159.46 107.377C160.271 106.13 159.917 104.461 158.669 103.651Z" fill="url(#paint12_linear_4111_515)"/>
|
||||
<path d="M164.256 95.1913C158.528 91.4508 151.869 89.4736 145 89.4736C138.131 89.4736 131.472 91.4506 125.744 95.1911C124.221 96.1852 123.792 98.2254 124.787 99.748C125.781 101.271 127.821 101.699 129.344 100.705C133.999 97.6654 139.413 96.0588 145 96.0588C150.587 96.0588 156.001 97.6654 160.656 100.705C161.212 101.068 161.836 101.241 162.453 101.241C163.528 101.241 164.582 100.716 165.213 99.7482C166.208 98.2256 165.779 96.1854 164.256 95.1913Z" fill="url(#paint13_linear_4111_515)"/>
|
||||
<path d="M145 124.532C147.182 124.532 148.951 122.763 148.951 120.581C148.951 118.399 147.182 116.63 145 116.63C142.818 116.63 141.049 118.399 141.049 120.581C141.049 122.763 142.818 124.532 145 124.532Z" fill="url(#paint14_linear_4111_515)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_4111_515" 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_4111_515"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4111_515" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_4111_515" x1="145" y1="154.648" x2="145" y2="196.939" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#62DBFB"/>
|
||||
<stop offset="0.1912" stop-color="#57D5FA"/>
|
||||
<stop offset="0.5232" stop-color="#3BC5F7"/>
|
||||
<stop offset="0.954" stop-color="#0DABF2"/>
|
||||
<stop offset="1" stop-color="#08A9F1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_4111_515" x1="105.706" y1="177.176" x2="93.7059" y2="177.176" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0593FC" stop-opacity="0"/>
|
||||
<stop offset="0.6831" stop-color="#0389FC" stop-opacity="0.683"/>
|
||||
<stop offset="1" stop-color="#0182FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_4111_515" x1="145.118" y1="122.273" x2="145.118" y2="128.866" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_4111_515" x1="145.118" y1="132.156" x2="145.118" y2="138.748" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_4111_515" x1="145.118" y1="142.038" x2="145.118" y2="148.631" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#017297"/>
|
||||
<stop offset="1" stop-color="#024C67"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_4111_515" x1="112.144" y1="101.95" x2="168.144" y2="201.715" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_4111_515" x1="145" y1="67.5915" x2="145" y2="137.895" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_4111_515" x1="145" y1="110.944" x2="145" y2="105.881" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint8_linear_4111_515" x1="145" y1="121.061" x2="145" y2="115.998" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#EAF9FA"/>
|
||||
<stop offset="1" stop-color="#B3DAFE"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint9_linear_4111_515" x1="126.473" y1="129.525" x2="115.65" y2="108.113" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint10_linear_4111_515" x1="175.367" y1="132.235" x2="141.72" y2="85.8824" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#7BACDF" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#7BACDF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint11_linear_4111_515" x1="143.315" y1="108.32" x2="146.188" y2="116.541" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint12_linear_4111_515" x1="142.584" y1="97.1318" x2="145.857" y2="109.025" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint13_linear_4111_515" x1="142.471" y1="88.6965" x2="145.983" y2="101.547" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint14_linear_4111_515" x1="141.169" y1="116.749" x2="147.514" y2="123.095" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AEFFD1"/>
|
||||
<stop offset="0.1201" stop-color="#A3F9CB"/>
|
||||
<stop offset="0.3288" stop-color="#87EAB9"/>
|
||||
<stop offset="0.6012" stop-color="#59D19D"/>
|
||||
<stop offset="0.9235" stop-color="#19AF77"/>
|
||||
<stop offset="1" stop-color="#09A76D"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_4111_515">
|
||||
<rect width="104.88" height="81.9651" fill="white" transform="translate(92.5908 122.838)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
25
assets/images/window_img.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<svg width="311" height="345" viewBox="0 0 311 345" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M309.392 1.11133H0.715698V344.077H309.392V1.11133Z" fill="#EBEBEC"/>
|
||||
<path d="M309.392 344.817H0.715982C0.309099 344.817 0.0131836 344.484 0.0131836 344.114V1.11149C0.0131836 0.741596 0.346088 0.408691 0.715982 0.408691H309.392C309.799 0.408691 310.095 0.741596 310.095 1.11149V344.077C310.095 344.484 309.762 344.78 309.392 344.78V344.817ZM1.45577 343.374H308.689V1.85128H1.45577V343.411V343.374Z" fill="#CCCCCC"/>
|
||||
<path d="M309.392 344.817H309.244C309.244 344.817 308.911 344.743 308.763 344.632L293.561 331.501L154.481 173.075C154.259 172.816 154.259 172.409 154.481 172.114L293.524 13.799L308.948 0.593798C309.17 0.408851 309.466 0.371862 309.725 0.48283C309.984 0.593798 310.132 0.852723 310.132 1.14864V344.114C310.132 344.521 309.799 344.817 309.429 344.817H309.392ZM156.034 172.631L294.633 330.502L308.726 342.672V2.70219L294.559 14.8347L156.034 172.631Z" fill="#CCCCCC"/>
|
||||
<path d="M155.072 173.334C154.85 173.334 154.666 173.26 154.518 173.075L15.5115 14.7236L0.271872 1.66633C0.0129463 1.48138 -0.0610325 1.14848 0.0499357 0.889553C0.160904 0.593638 0.419829 0.408691 0.715744 0.408691H309.392C309.688 0.408691 309.947 0.593638 310.058 0.889553C310.169 1.18547 310.058 1.48138 309.836 1.66633L294.485 14.7976L155.553 173.075C155.553 173.075 155.22 173.334 154.998 173.334H155.072ZM2.67618 1.85128L16.5472 13.7249L155.072 171.522L293.524 13.7988L307.469 1.85128H2.67618Z" fill="#CCCCCC"/>
|
||||
<path d="M0.715982 344.817C0.715982 344.817 0.494045 344.817 0.420067 344.743C0.161141 344.632 0.0131836 344.373 0.0131836 344.077V1.11165C0.0131836 0.852723 0.161141 0.593798 0.420067 0.48283C0.678992 0.371862 0.974907 0.408851 1.19684 0.593798L16.5474 13.725L155.627 172.15C155.849 172.409 155.849 172.816 155.627 173.112L16.5844 331.427L1.15985 344.632C1.15985 344.632 0.863939 344.817 0.678992 344.817H0.715982ZM1.45577 2.70219V342.561L15.6227 330.428L154.148 172.631L15.5117 14.7237L1.45577 2.70219Z" fill="#CCCCCC"/>
|
||||
<path d="M309.281 344.817H0.71569C0.419775 344.817 0.160849 344.632 0.049881 344.336C-0.0610871 344.04 0.049881 343.744 0.271817 343.559L15.6224 330.428L154.554 172.151C154.813 171.855 155.368 171.855 155.627 172.151L294.633 330.502L309.762 343.559C309.984 343.744 310.058 344.077 309.947 344.336C309.836 344.632 309.577 344.817 309.281 344.817ZM2.67613 343.374H307.358L293.635 331.501L155.109 173.704L16.5841 331.427L2.63914 343.374H2.67613Z" fill="#CCCCCC"/>
|
||||
<path d="M294.078 14.2798H16.0659V330.983H294.078V14.2798Z" fill="#B2B4B6"/>
|
||||
<path d="M294.078 331.686H16.0661C15.6592 331.686 15.3633 331.353 15.3633 330.983V14.2799C15.3633 13.8731 15.6962 13.5771 16.0661 13.5771H294.078C294.485 13.5771 294.781 13.9101 294.781 14.2799V330.983C294.781 331.39 294.448 331.686 294.078 331.686ZM16.7689 330.243H293.338V14.9827H16.7689V330.243Z" fill="#CCCCCC"/>
|
||||
<path d="M290.305 17.8306H19.839V325.952H290.305V17.8306Z" fill="#D8D9DA"/>
|
||||
<path d="M290.305 326.655H19.8392C19.4323 326.655 19.1364 326.322 19.1364 325.952V17.8307C19.1364 17.4238 19.4693 17.1279 19.8392 17.1279H290.305C290.712 17.1279 291.008 17.4608 291.008 17.8307V325.952C291.008 326.359 290.675 326.655 290.305 326.655ZM20.5419 325.249H289.566V18.5705H20.5419V325.249Z" fill="#9E9FA0"/>
|
||||
<path d="M285.645 22.269H24.3519V321.772H285.645V22.269Z" fill="white"/>
|
||||
<path d="M279.985 28.3726H30.2701V315.595H279.985V28.3726Z" fill="url(#paint0_linear_4883_327)" fill-opacity="0.5"/>
|
||||
<path d="M279.986 316.298H30.2704C29.8635 316.298 29.5676 315.966 29.5676 315.596V28.3732C29.5676 27.9663 29.9005 27.6704 30.2704 27.6704H279.986C280.393 27.6704 280.688 28.0033 280.688 28.3732V315.596C280.688 316.003 280.356 316.298 279.986 316.298ZM30.9732 314.856H279.246V29.076H30.9732V314.856Z" fill="#D5D7D8"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_4883_327" x1="155.109" y1="384.21" x2="155.109" y2="-45.7172" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="0.15" stop-color="#FAFDFD"/>
|
||||
<stop offset="0.31" stop-color="#ECF7F8"/>
|
||||
<stop offset="0.49" stop-color="#D5EEF1"/>
|
||||
<stop offset="0.87" stop-color="#B4E1EB"/>
|
||||
<stop offset="1" stop-color="#A8DDE9"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@ -24,9 +24,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
on<PauseCurtain>(_onPauseCurtain);
|
||||
}
|
||||
|
||||
Future<void> _onOpenCurtain(
|
||||
OpenCurtain event,
|
||||
Emitter<CurtainState> emit) async {
|
||||
Future<void> _onOpenCurtain(OpenCurtain event, Emitter<CurtainState> emit) async {
|
||||
isMoving = true;
|
||||
while (openPercentage < 100.0) {
|
||||
if (state is CurtainsClosing) {
|
||||
@ -48,7 +46,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
_pauseCurtain(emit);
|
||||
}
|
||||
});
|
||||
if (openPercentage >=100.0) {
|
||||
if (openPercentage >= 100.0) {
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: curtainId,
|
||||
@ -73,8 +71,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onCloseCurtain(
|
||||
CloseCurtain event, Emitter<CurtainState> emit) async {
|
||||
Future<void> _onCloseCurtain(CloseCurtain event, Emitter<CurtainState> emit) async {
|
||||
isMoving = true;
|
||||
while (openPercentage > 0.0) {
|
||||
if (state is CurtainsOpening) {
|
||||
@ -121,8 +118,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onPauseCurtain(
|
||||
PauseCurtain event, Emitter<CurtainState> emit) async {
|
||||
Future<void> _onPauseCurtain(PauseCurtain event, Emitter<CurtainState> emit) async {
|
||||
_pauseCurtain(emit);
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
@ -132,7 +128,7 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
),
|
||||
curtainId,
|
||||
);
|
||||
await DevicesAPI.controlDevice(
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: curtainId,
|
||||
code: 'percent_control',
|
||||
@ -151,9 +147,6 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void _fetchStatus(InitCurtain event, Emitter<CurtainState> emit) async {
|
||||
try {
|
||||
emit(CurtainLoadingState());
|
||||
@ -166,10 +159,9 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
// Get the open percentage from the response
|
||||
openPercentage = double.tryParse(statusModelList[1].value.toString())!;
|
||||
// Calculate curtain width and blind height based on the open percentage
|
||||
if (openPercentage != null) {
|
||||
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
|
||||
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
|
||||
}
|
||||
curtainWidth = 270 - (openPercentage / 100) * curtainOpeningSpace;
|
||||
blindHeight = 310 - (openPercentage / 100) * blindOpeningSpace;
|
||||
|
||||
emit(CurtainsOpening(
|
||||
curtainWidth: curtainWidth,
|
||||
blindHeight: blindHeight,
|
||||
@ -180,5 +172,4 @@ class CurtainBloc extends Bloc<CurtainEvent, CurtainState> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
564
lib/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart
Normal file
@ -0,0 +1,564 @@
|
||||
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/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_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/device_report_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/garage_door_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_garage_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';
|
||||
|
||||
class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorSensorState> {
|
||||
final String GDId;
|
||||
GarageDoorBloc({
|
||||
required this.GDId,
|
||||
}) : super(const GarageDoorSensorState()) {
|
||||
on<GarageDoorInitial>(_fetchStatus);
|
||||
on<ReportLogsInitial>(fetchLogsForLastMonth);
|
||||
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
|
||||
on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ScheduleSaveapp>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
on<OnClose>(_onClose);
|
||||
on<SelectSecondsEvent>(selectSeconds);
|
||||
on<ToggleDoorEvent>(openCloseGarageDoor);
|
||||
on<GetCounterEvent>(_getCounterValue);
|
||||
on<SetCounterValue>(_setCounterValue);
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<InitialWizardEvent>(_fetchWizardStatus);
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
|
||||
}
|
||||
void _onClose(OnClose event, Emitter<GarageDoorSensorState> emit) {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
Timer? _timer;
|
||||
bool lowBattery = false;
|
||||
bool closingReminder = false;
|
||||
bool doorAlarm = false;
|
||||
|
||||
GarageDoorModel deviceStatus = GarageDoorModel(
|
||||
tr_timecon: 0,
|
||||
countdown1: 0,
|
||||
countdownAlarm: 0,
|
||||
doorContactState: false,
|
||||
doorControl1: '',
|
||||
doorState1: '',
|
||||
switch1: false,
|
||||
voiceControl1: false,
|
||||
batteryPercentage: 0,
|
||||
);
|
||||
|
||||
void _fetchStatus(
|
||||
GarageDoorInitial event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(GarageDoorLoadingState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(GDId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = GarageDoorModel.fromJson(
|
||||
statusModelList,
|
||||
);
|
||||
secondSelected = deviceStatus.tr_timecon;
|
||||
toggleDoor = deviceStatus.switch1;
|
||||
emit(UpdateState(garageSensor: deviceStatus));
|
||||
Future.delayed(const Duration(milliseconds: 500));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleClosingReminder(ToggleClosingReminderEvent event,
|
||||
Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
closingReminder = event.isClosingReminderEnabled;
|
||||
emit(UpdateState(garageSensor: deviceStatus));
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: GDId,
|
||||
code: 'closing_reminder',
|
||||
value: closingReminder,
|
||||
),
|
||||
GDId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleDoorAlarm(
|
||||
ToggleDoorAlarmEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
doorAlarm = event.isDoorAlarmEnabled;
|
||||
emit(UpdateState(garageSensor: deviceStatus));
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: GDId,
|
||||
code: 'door_alarm',
|
||||
value: doorAlarm,
|
||||
),
|
||||
GDId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
DeviceReport recordGroups =
|
||||
DeviceReport(startTime: '0', endTime: '0', data: []);
|
||||
|
||||
Future<void> fetchLogsForLastMonth(
|
||||
ReportLogsInitial event, Emitter<GarageDoorSensorState> emit) async {
|
||||
DateTime now = DateTime.now();
|
||||
|
||||
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
||||
int startTime = lastMonth.millisecondsSinceEpoch;
|
||||
int endTime = now.millisecondsSinceEpoch;
|
||||
try {
|
||||
emit(GarageDoorLoadingState());
|
||||
var response = await DevicesAPI.getReportLogs(
|
||||
startTime: startTime.toString(),
|
||||
endTime: endTime.toString(),
|
||||
deviceUuid: GDId,
|
||||
code: 'doorcontact_state',
|
||||
);
|
||||
recordGroups = response;
|
||||
emit(UpdateState(garageSensor: deviceStatus));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(GarageDoorFailedState(errorMessage: errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$GDId');
|
||||
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 = GarageDoorModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
// add(
|
||||
// DoorSensorSwitch(switchD: deviceStatus.doorContactState),
|
||||
// );
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
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<GarageDoorSensorState> emit,
|
||||
) async {
|
||||
emit(GarageDoorLoadingState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
} else {
|
||||
selectedDays.add(event.key);
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(
|
||||
ScheduleSaveapp event,
|
||||
Emitter<GarageDoorSensorState> emit,
|
||||
) async {
|
||||
try {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(GarageDoorLoadingState());
|
||||
await DevicesAPI.postSchedule(
|
||||
category: 'switch_1',
|
||||
deviceId: GDId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
code: 'switch_1',
|
||||
value: toggleSchedule,
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<GarageDoorSensorState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(GarageDoorLoadingState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: 'switch_1',
|
||||
deviceId: GDId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(GarageDoorFailedState(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<GarageDoorSensorState> emit) async {
|
||||
try {
|
||||
emit(GarageDoorLoadingState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id, deviceUuid: GDId, 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(GarageDoorFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
try {
|
||||
emit(GarageDoorLoadingState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: GDId,
|
||||
);
|
||||
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(GarageDoorFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<GarageDoorSensorState> emit) {
|
||||
emit(GarageDoorLoadingState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<GarageDoorSensorState> emit) {
|
||||
emit(GarageDoorLoadingState());
|
||||
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();
|
||||
|
||||
int secondSelected = 0;
|
||||
bool toggleDoor = false;
|
||||
Future<void> selectSeconds(
|
||||
SelectSecondsEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
try {
|
||||
emit(GarageDoorLoadingState());
|
||||
secondSelected = event.seconds;
|
||||
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: GDId, code: 'tr_timecon', value: secondSelected),
|
||||
GDId);
|
||||
emit(UpdateState(garageSensor: deviceStatus));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(GarageDoorFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
openCloseGarageDoor(
|
||||
ToggleDoorEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(GarageDoorLoadingState());
|
||||
try {
|
||||
toggleDoor = !event.toggle;
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: GDId, code: 'switch_1', value: toggleDoor),
|
||||
GDId);
|
||||
add(const GarageDoorInitial());
|
||||
emit(UpdateState(garageSensor: deviceStatus));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
emit(GarageDoorFailedState(errorMessage: errorMessage.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _setCounterValue(
|
||||
SetCounterValue event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
int seconds = 0;
|
||||
try {
|
||||
seconds = event.duration.inSeconds;
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: GDId, code: 'countdown_1', value: seconds),
|
||||
GDId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
deviceStatus.countdown1 = seconds;
|
||||
} else {
|
||||
emit(const GarageDoorFailedState(errorMessage: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
return;
|
||||
}
|
||||
if (seconds > 0) {
|
||||
_onStartTimer(seconds);
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
void _getCounterValue(
|
||||
GetCounterEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(GDId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = GarageDoorModel.fromJson(statusModelList);
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.countdown1 > 0
|
||||
? _onStartTimer(deviceStatus.countdown1)
|
||||
: emit(UpdateTimerState(seconds: deviceStatus.countdown1));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _onStartTimer(int seconds) {
|
||||
_timer?.cancel();
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
add(TickTimer(remainingTime: seconds - timer.tick));
|
||||
});
|
||||
}
|
||||
|
||||
void _onTickTimer(TickTimer event, Emitter<GarageDoorSensorState> emit) {
|
||||
if (event.remainingTime > 0) {
|
||||
emit(TimerRunInProgress(event.remainingTime));
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
emit(TimerRunComplete());
|
||||
}
|
||||
}
|
||||
|
||||
bool oneGangGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
List<GroupGarageModel> groupList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
void _fetchWizardStatus(
|
||||
InitialWizardEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
devicesList = [];
|
||||
groupList = [];
|
||||
allSwitchesOn = true;
|
||||
devicesList = await DevicesAPI.getDeviceByGroupName(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', 'GD');
|
||||
|
||||
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 = GarageDoorModel.fromJson(statusModelList);
|
||||
groupList.add(GroupGarageModel(
|
||||
deviceId: devicesList[i].uuid ?? '',
|
||||
deviceName: devicesList[i].name ?? '',
|
||||
firstSwitch: deviceStatus.switch1,
|
||||
));
|
||||
}
|
||||
|
||||
if (groupList.isNotEmpty) {
|
||||
groupList.firstWhere((element) {
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(garageList: groupList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(GarageDoorFailedState(errorMessage: e.toString()));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOn(
|
||||
GroupAllOnEvent event, Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||
for (int i = 0; i < groupList.length; i++) {
|
||||
groupList[i].firstSwitch = true;
|
||||
}
|
||||
|
||||
// Emit the state with updated values
|
||||
emit(UpdateGroupState(garageList: groupList, allSwitches: true));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds =
|
||||
groupList.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<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
|
||||
for (int i = 0; i < groupList.length; i++) {
|
||||
groupList[i].firstSwitch = false;
|
||||
}
|
||||
|
||||
// Emit the state with updated values
|
||||
emit(UpdateGroupState(garageList: groupList, allSwitches: false));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds =
|
||||
groupList.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));
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<GarageDoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
groupList.forEach((element) {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
|
||||
emit(UpdateGroupState(
|
||||
garageList: groupList, 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,175 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class GarageDoorEvent extends Equatable {
|
||||
const GarageDoorEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class GarageDoorLoading extends GarageDoorEvent {}
|
||||
|
||||
class GarageDoorSwitch extends GarageDoorEvent {
|
||||
final bool switchD;
|
||||
final String deviceId;
|
||||
final String productId;
|
||||
const GarageDoorSwitch(
|
||||
{required this.switchD, this.deviceId = '', this.productId = ''});
|
||||
|
||||
@override
|
||||
List<Object> get props => [switchD, deviceId, productId];
|
||||
}
|
||||
|
||||
class GarageDoorUpdated extends GarageDoorEvent {}
|
||||
|
||||
class GarageDoorInitial extends GarageDoorEvent {
|
||||
const GarageDoorInitial();
|
||||
}
|
||||
|
||||
class ReportLogsInitial extends GarageDoorEvent {
|
||||
const ReportLogsInitial();
|
||||
}
|
||||
|
||||
class GarageDoorChangeStatus extends GarageDoorEvent {}
|
||||
|
||||
class GetCounterEvent extends GarageDoorEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
class ToggleLowBatteryEvent extends GarageDoorEvent {
|
||||
final bool isLowBatteryEnabled;
|
||||
|
||||
const ToggleLowBatteryEvent(this.isLowBatteryEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isLowBatteryEnabled];
|
||||
}
|
||||
|
||||
class ToggleClosingReminderEvent extends GarageDoorEvent {
|
||||
final bool isClosingReminderEnabled;
|
||||
|
||||
const ToggleClosingReminderEvent(this.isClosingReminderEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isClosingReminderEnabled];
|
||||
}
|
||||
|
||||
class ToggleDoorAlarmEvent extends GarageDoorEvent {
|
||||
final bool isDoorAlarmEnabled;
|
||||
|
||||
const ToggleDoorAlarmEvent(this.isDoorAlarmEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isDoorAlarmEnabled];
|
||||
}
|
||||
|
||||
class SetCounterValue extends GarageDoorEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends GarageDoorEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends GarageDoorEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer({required this.remainingTime});
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends GarageDoorEvent {}
|
||||
|
||||
class OnClose extends GarageDoorEvent {}
|
||||
|
||||
//------------------- Schedule ----------=---------
|
||||
class GetScheduleEvent extends GarageDoorEvent {}
|
||||
|
||||
class ScheduleSaveapp extends GarageDoorEvent {}
|
||||
|
||||
class ToggleScheduleEvent extends GarageDoorEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
const ToggleScheduleEvent({required this.toggle, required this.id});
|
||||
@override
|
||||
List<Object> get props => [toggle, id];
|
||||
}
|
||||
|
||||
class ToggleDaySelectionEvent extends GarageDoorEvent {
|
||||
final String key;
|
||||
|
||||
const ToggleDaySelectionEvent({required this.key});
|
||||
@override
|
||||
List<Object> get props => [key];
|
||||
}
|
||||
|
||||
class DeleteScheduleEvent extends GarageDoorEvent {
|
||||
final String id;
|
||||
const DeleteScheduleEvent({required this.id});
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
class ToggleSelectedEvent extends GarageDoorEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ToggleCreateScheduleEvent extends GarageDoorEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
class ChangeFirstWizardSwitchStatusEvent extends GarageDoorEvent {
|
||||
final bool value;
|
||||
final String deviceId;
|
||||
const ChangeFirstWizardSwitchStatusEvent(
|
||||
{required this.value, this.deviceId = ''});
|
||||
@override
|
||||
List<Object> get props => [value, deviceId];
|
||||
}
|
||||
|
||||
class SelectSecondsEvent extends GarageDoorEvent {
|
||||
final int seconds;
|
||||
const SelectSecondsEvent({required this.seconds});
|
||||
@override
|
||||
List<Object> get props => [seconds];
|
||||
}
|
||||
|
||||
class ToggleDoorEvent extends GarageDoorEvent {
|
||||
final bool toggle;
|
||||
const ToggleDoorEvent({required this.toggle});
|
||||
@override
|
||||
List<Object> get props => [toggle];
|
||||
}
|
||||
|
||||
class InitialWizardEvent extends GarageDoorEvent {}
|
||||
|
||||
class GroupAllOnEvent extends GarageDoorEvent {}
|
||||
|
||||
class GroupAllOffEvent extends GarageDoorEvent {}
|
||||
|
||||
class InitialEvent extends GarageDoorEvent {
|
||||
final bool groupScreen;
|
||||
const InitialEvent({required this.groupScreen});
|
||||
@override
|
||||
List<Object> get props => [groupScreen];
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/garage_door_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_garage_model.dart';
|
||||
|
||||
class GarageDoorSensorState extends Equatable {
|
||||
const GarageDoorSensorState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class GarageDoorInitialState extends GarageDoorSensorState {}
|
||||
|
||||
class GarageDoorLoadingState extends GarageDoorSensorState {}
|
||||
|
||||
class GarageDoorFailedState extends GarageDoorSensorState {
|
||||
final String errorMessage;
|
||||
|
||||
const GarageDoorFailedState({required this.errorMessage});
|
||||
|
||||
@override
|
||||
List<Object> get props => [errorMessage];
|
||||
}
|
||||
|
||||
class UpdateState extends GarageDoorSensorState {
|
||||
final GarageDoorModel garageSensor;
|
||||
const UpdateState({required this.garageSensor});
|
||||
|
||||
@override
|
||||
List<Object> get props => [garageSensor];
|
||||
}
|
||||
|
||||
class LoadingNewSate extends GarageDoorSensorState {
|
||||
final GarageDoorModel doorSensor;
|
||||
const LoadingNewSate({required this.doorSensor});
|
||||
|
||||
@override
|
||||
List<Object> get props => [doorSensor];
|
||||
}
|
||||
|
||||
class ChangeSlidingSegmentState extends GarageDoorSensorState {
|
||||
final int value;
|
||||
|
||||
const ChangeSlidingSegmentState({required this.value});
|
||||
|
||||
@override
|
||||
List<Object> get props => [value];
|
||||
}
|
||||
|
||||
class UpdateTimerState extends GarageDoorSensorState {
|
||||
final int seconds;
|
||||
const UpdateTimerState({required this.seconds});
|
||||
|
||||
@override
|
||||
List<Object> get props => [seconds];
|
||||
}
|
||||
|
||||
class TimerRunInProgress extends GarageDoorSensorState {
|
||||
final int remainingTime;
|
||||
|
||||
const TimerRunInProgress(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class TimerRunComplete extends GarageDoorSensorState {}
|
||||
|
||||
class SaveSchedule extends GarageDoorSensorState {}
|
||||
|
||||
class IsToggleState extends GarageDoorSensorState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
class ChangeTimeState extends GarageDoorSensorState {}
|
||||
|
||||
class LoadingInitialState extends GarageDoorSensorState {}
|
||||
|
||||
class UpdateCreateScheduleState extends GarageDoorSensorState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
||||
|
||||
class UpdateGroupState extends GarageDoorSensorState {
|
||||
final List<GroupGarageModel> garageList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState(
|
||||
{required this.garageList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [garageList, allSwitches];
|
||||
}
|
||||
@ -26,7 +26,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
bool oneGangGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
|
||||
OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) {
|
||||
OneGangBloc({required this.oneGangId, required this.switchCode})
|
||||
: super(InitialState()) {
|
||||
on<InitialEvent>(_fetchOneGangStatus);
|
||||
on<OneGangUpdated>(_oneGangUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
@ -49,7 +50,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
}
|
||||
|
||||
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
|
||||
void _fetchOneGangStatus(
|
||||
InitialEvent event, Emitter<OneGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(oneGangId);
|
||||
@ -68,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);
|
||||
@ -94,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;
|
||||
@ -119,17 +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) {
|
||||
@ -152,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);
|
||||
@ -241,7 +251,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
deviceId: oneGangId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(InitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
@ -252,12 +263,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
DateTime dateTimeWithoutSeconds =
|
||||
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
|
||||
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||
dateTime.day, dateTime.hour, dateTime.minute);
|
||||
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
|
||||
Future toggleChange(ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
Future toggleChange(
|
||||
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
@ -276,7 +288,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
@ -296,8 +309,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
@ -326,7 +339,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<OneGangState> emit) {
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<OneGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
@ -335,7 +349,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
List<GroupOneGangModel> groupOneGangList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
void _fetchOneGangWizardStatus(InitialWizardEvent event, Emitter<OneGangState> emit) async {
|
||||
void _fetchOneGangWizardStatus(
|
||||
InitialWizardEvent event, Emitter<OneGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
devicesList = [];
|
||||
@ -345,7 +360,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
@ -366,15 +382,16 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
|
||||
emit(UpdateGroupState(
|
||||
oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _changeFirstWizardSwitch(
|
||||
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneGangState> emit) async {
|
||||
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
|
||||
Emitter<OneGangState> emit) async {
|
||||
emit(LoadingNewSate(oneGangModel: deviceStatus));
|
||||
try {
|
||||
bool allSwitchesValue = true;
|
||||
@ -387,7 +404,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
});
|
||||
|
||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
|
||||
emit(UpdateGroupState(
|
||||
oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
@ -415,7 +433,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
|
||||
List<String> allDeviceIds =
|
||||
groupOneGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
// First call for switch_1
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
@ -447,7 +466,8 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
|
||||
|
||||
// Get a list of all device IDs
|
||||
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
|
||||
List<String> allDeviceIds =
|
||||
groupOneGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
// First call for switch_1
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
|
||||
538
lib/features/devices/bloc/one_touch_bloc/one_touch_bloc.dart
Normal file
@ -0,0 +1,538 @@
|
||||
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_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
|
||||
);
|
||||
if (response1['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
emit(FailedState(error: _.toString()));
|
||||
// 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: false, // true (on) or false (off) depending on the event value
|
||||
);
|
||||
|
||||
// Check if either response is unsuccessful, then reset to initial state
|
||||
if (response1['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
emit(FailedState(error: _.toString()));
|
||||
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);
|
||||
}
|
||||
@ -31,7 +31,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
List<GroupThreeGangModel> groupThreeGangList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
ThreeGangBloc({required this.threeGangId, required this.switchCode}) : super(InitialState()) {
|
||||
ThreeGangBloc({required this.threeGangId, required this.switchCode})
|
||||
: super(InitialState()) {
|
||||
on<InitialEvent>(_fetchThreeGangStatus);
|
||||
on<ThreeGangUpdated>(_threeGangUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
@ -57,7 +58,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
}
|
||||
|
||||
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
|
||||
void _fetchThreeGangStatus(
|
||||
InitialEvent event, Emitter<ThreeGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
threeGangGroup = event.groupScreen;
|
||||
@ -69,7 +71,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '', '3G');
|
||||
|
||||
for (int i = 0; i < devicesList.length; i++) {
|
||||
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
var response =
|
||||
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
@ -86,13 +89,16 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
|
||||
if (groupThreeGangList.isNotEmpty) {
|
||||
groupThreeGangList.firstWhere((element) {
|
||||
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesOn = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
|
||||
emit(UpdateGroupState(
|
||||
threeGangList: groupThreeGangList, allSwitches: allSwitchesOn));
|
||||
} else {
|
||||
var response = await DevicesAPI.getDeviceStatus(threeGangId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
@ -101,7 +107,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
deviceStatus = ThreeGangModel.fromJson(statusModelList);
|
||||
emit(UpdateState(threeGangModel: deviceStatus));
|
||||
_listenToChanges();
|
||||
// _listenToChanges();
|
||||
}
|
||||
} catch (e) {
|
||||
emit(FailedState(error: e.toString()));
|
||||
@ -111,18 +117,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$threeGangId');
|
||||
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));
|
||||
}
|
||||
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
||||
Map<dynamic, dynamic> usersMap =
|
||||
event.snapshot.value as Map<dynamic, dynamic>;
|
||||
List<StatusModel> statusList = [];
|
||||
|
||||
usersMap['status'].forEach((element) {
|
||||
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
||||
statusList
|
||||
.add(StatusModel(code: element['code'], value: element['value']));
|
||||
});
|
||||
|
||||
deviceStatus = ThreeGangModel.fromJson(statusList);
|
||||
@ -137,7 +146,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
emit(UpdateState(threeGangModel: deviceStatus));
|
||||
}
|
||||
|
||||
void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
|
||||
void _changeFirstSwitch(
|
||||
ChangeFirstSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
|
||||
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
||||
try {
|
||||
if (threeGangGroup) {
|
||||
@ -146,11 +156,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.firstSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
|
||||
emit(UpdateGroupState(
|
||||
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
|
||||
} else {
|
||||
deviceStatus.firstSwitch = !event.value;
|
||||
emit(UpdateState(threeGangModel: deviceStatus));
|
||||
@ -187,11 +200,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.secondSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
|
||||
emit(UpdateGroupState(
|
||||
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
|
||||
} else {
|
||||
deviceStatus.secondSwitch = !event.value;
|
||||
emit(UpdateState(threeGangModel: deviceStatus));
|
||||
@ -217,7 +233,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
|
||||
void _changeThirdSwitch(
|
||||
ChangeThirdSwitchStatusEvent event, Emitter<ThreeGangState> emit) async {
|
||||
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
||||
try {
|
||||
if (threeGangGroup) {
|
||||
@ -226,11 +243,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
if (element.deviceId == event.deviceId) {
|
||||
element.thirdSwitch = !event.value;
|
||||
}
|
||||
if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) {
|
||||
if (!element.firstSwitch ||
|
||||
!element.secondSwitch ||
|
||||
!element.thirdSwitch) {
|
||||
allSwitchesValue = false;
|
||||
}
|
||||
});
|
||||
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
|
||||
emit(UpdateGroupState(
|
||||
threeGangList: groupThreeGangList, allSwitches: allSwitchesValue));
|
||||
} else {
|
||||
deviceStatus.thirdSwitch = !event.value;
|
||||
emit(UpdateState(threeGangModel: deviceStatus));
|
||||
@ -269,15 +289,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
|
||||
deviceId: threeGangId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
threeGangId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
|
||||
deviceId: threeGangId,
|
||||
code: 'switch_2',
|
||||
value: deviceStatus.secondSwitch),
|
||||
threeGangId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch),
|
||||
deviceId: threeGangId,
|
||||
code: 'switch_3',
|
||||
value: deviceStatus.thirdSwitch),
|
||||
threeGangId),
|
||||
]);
|
||||
|
||||
@ -303,15 +329,21 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: 'switch_1', value: deviceStatus.firstSwitch),
|
||||
deviceId: threeGangId,
|
||||
code: 'switch_1',
|
||||
value: deviceStatus.firstSwitch),
|
||||
threeGangId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: 'switch_2', value: deviceStatus.secondSwitch),
|
||||
deviceId: threeGangId,
|
||||
code: 'switch_2',
|
||||
value: deviceStatus.secondSwitch),
|
||||
threeGangId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: 'switch_3', value: deviceStatus.thirdSwitch),
|
||||
deviceId: threeGangId,
|
||||
code: 'switch_3',
|
||||
value: deviceStatus.thirdSwitch),
|
||||
threeGangId),
|
||||
]);
|
||||
|
||||
@ -333,29 +365,33 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
groupThreeGangList[i].secondSwitch = true;
|
||||
groupThreeGangList[i].thirdSwitch = true;
|
||||
}
|
||||
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: true));
|
||||
emit(UpdateGroupState(
|
||||
threeGangList: groupThreeGangList, allSwitches: true));
|
||||
|
||||
for (int i = 0; i < groupThreeGangList.length; i++) {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeGangList[i].deviceId, code: 'switch_1', value: true),
|
||||
groupThreeGangList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeGangList[i].deviceId, code: 'switch_2', value: true),
|
||||
groupThreeGangList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeGangList[i].deviceId, code: 'switch_3', value: true),
|
||||
groupThreeGangList[i].deviceId),
|
||||
]);
|
||||
List<String> allDeviceIds =
|
||||
groupThreeGangList.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: true,
|
||||
);
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
final response3 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_3',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]' ||
|
||||
response3['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
@ -363,7 +399,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _groupAllOff(GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
|
||||
void _groupAllOff(
|
||||
GroupAllOffEvent event, Emitter<ThreeGangState> emit) async {
|
||||
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
||||
try {
|
||||
for (int i = 0; i < groupThreeGangList.length; i++) {
|
||||
@ -371,29 +408,32 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
groupThreeGangList[i].secondSwitch = false;
|
||||
groupThreeGangList[i].thirdSwitch = false;
|
||||
}
|
||||
emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: false));
|
||||
emit(UpdateGroupState(
|
||||
threeGangList: groupThreeGangList, allSwitches: false));
|
||||
List<String> allDeviceIds =
|
||||
groupThreeGangList.map((device) => device.deviceId).toList();
|
||||
|
||||
for (int i = 0; i < groupThreeGangList.length; i++) {
|
||||
final response = await Future.wait([
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeGangList[i].deviceId, code: 'switch_1', value: false),
|
||||
groupThreeGangList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeGangList[i].deviceId, code: 'switch_2', value: false),
|
||||
groupThreeGangList[i].deviceId),
|
||||
DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: groupThreeGangList[i].deviceId, code: 'switch_3', value: false),
|
||||
groupThreeGangList[i].deviceId),
|
||||
]);
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
final response3 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_3',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
if (response.every((element) => !element['success'])) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
break;
|
||||
}
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]' ||
|
||||
response3['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} catch (_) {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
@ -401,17 +441,20 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _changeSliding(ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
|
||||
void _changeSliding(
|
||||
ChangeSlidingSegment event, Emitter<ThreeGangState> emit) async {
|
||||
emit(ChangeSlidingSegmentState(value: event.value));
|
||||
}
|
||||
|
||||
void _setCounterValue(SetCounterValue event, Emitter<ThreeGangState> emit) async {
|
||||
void _setCounterValue(
|
||||
SetCounterValue event, Emitter<ThreeGangState> emit) async {
|
||||
emit(LoadingNewSate(threeGangModel: deviceStatus));
|
||||
int seconds = 0;
|
||||
try {
|
||||
seconds = event.duration.inSeconds;
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(deviceId: threeGangId, code: event.deviceCode, value: seconds),
|
||||
DeviceControlModel(
|
||||
deviceId: threeGangId, code: event.deviceCode, value: seconds),
|
||||
threeGangId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
@ -438,7 +481,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _getCounterValue(GetCounterEvent event, Emitter<ThreeGangState> emit) async {
|
||||
void _getCounterValue(
|
||||
GetCounterEvent event, Emitter<ThreeGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(threeGangId);
|
||||
@ -548,7 +592,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
deviceId: threeGangId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(InitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
@ -559,12 +604,13 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
DateTime dateTimeWithoutSeconds =
|
||||
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
|
||||
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||
dateTime.day, dateTime.hour, dateTime.minute);
|
||||
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
|
||||
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
Future toggleChange(
|
||||
ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
@ -583,7 +629,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
@ -603,13 +650,15 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
|
||||
735
lib/features/devices/bloc/three_touch_bloc/three_touch_bloc.dart
Normal file
@ -0,0 +1,735 @@
|
||||
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/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));
|
||||
List<String> allDeviceIds =
|
||||
groupThreeTouchList.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,
|
||||
);
|
||||
final response3 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_3',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: true,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]' ||
|
||||
response3['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
List<String> allDeviceIds =
|
||||
groupThreeTouchList.map((device) => device.deviceId).toList();
|
||||
emit(UpdateGroupState(
|
||||
threeTouchList: groupThreeTouchList, allSwitches: false));
|
||||
final response1 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
final response2 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
final response3 = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_3',
|
||||
devicesUuid: allDeviceIds,
|
||||
value: false,
|
||||
);
|
||||
|
||||
if (response1['failedResults'].toString() != '[]' ||
|
||||
response2['failedResults'].toString() != '[]' ||
|
||||
response3['failedResults'].toString() != '[]') {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
add(const InitialEvent(groupScreen: true));
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
681
lib/features/devices/bloc/two_touch_bloc/two_touch_bloc.dart
Normal file
@ -0,0 +1,681 @@
|
||||
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));
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_1',
|
||||
devicesUuid: [event.deviceId],
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
emit(UpdateGroupState(
|
||||
twoTouchList: groupTwoTouchList, allSwitches: allSwitchesValue));
|
||||
|
||||
final response = await DevicesAPI.deviceBatchController(
|
||||
code: 'switch_2',
|
||||
devicesUuid: [event.deviceId],
|
||||
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);
|
||||
}
|
||||
@ -42,9 +42,7 @@ 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;
|
||||
|
||||
@ -67,4 +65,8 @@ Map<DeviceType, String> deviceTypeIconMap = {
|
||||
DeviceType.WH: Assets.waterHeaterIcon,
|
||||
DeviceType.DS: Assets.doorSensorIcon,
|
||||
DeviceType.Other: Assets.assetsIconsAC,
|
||||
DeviceType.OneTouch: Assets.oneGang,
|
||||
DeviceType.TowTouch: Assets.twoGang,
|
||||
DeviceType.ThreeTouch: Assets.assetsIconsGang,
|
||||
DeviceType.GarageDoor: Assets.garageIcon
|
||||
};
|
||||
|
||||
@ -66,7 +66,16 @@ class DeviceModel {
|
||||
tempIcon = Assets.waterHeaterIcon;
|
||||
} else if (type == DeviceType.DS) {
|
||||
tempIcon = Assets.doorSensorIcon;
|
||||
} else {
|
||||
} else if (type == DeviceType.OneTouch) {
|
||||
tempIcon = Assets.oneGang;
|
||||
} else if (type == DeviceType.TowTouch) {
|
||||
tempIcon = Assets.twoGang;
|
||||
} else if (type == DeviceType.GarageDoor) {
|
||||
tempIcon = Assets.garageIcon;
|
||||
} else if (type == DeviceType.ThreeTouch) {
|
||||
tempIcon = Assets.assetsIcons3GangSwitch;
|
||||
}
|
||||
else {
|
||||
tempIcon = Assets.assetsIconsLogo;
|
||||
}
|
||||
|
||||
|
||||
81
lib/features/devices/model/garage_door_model.dart
Normal file
@ -0,0 +1,81 @@
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
|
||||
class GarageDoorModel {
|
||||
bool switch1;
|
||||
bool doorContactState;
|
||||
int countdown1;
|
||||
int countdownAlarm;
|
||||
String doorControl1;
|
||||
bool voiceControl1;
|
||||
String doorState1;
|
||||
int batteryPercentage;
|
||||
int tr_timecon;
|
||||
|
||||
GarageDoorModel({
|
||||
required this.switch1,
|
||||
required this.doorContactState,
|
||||
required this.countdown1,
|
||||
required this.countdownAlarm,
|
||||
required this.doorControl1,
|
||||
required this.voiceControl1,
|
||||
required this.doorState1,
|
||||
required this.batteryPercentage,
|
||||
required this.tr_timecon,
|
||||
});
|
||||
|
||||
factory GarageDoorModel.fromJson(List<StatusModel> jsonList) {
|
||||
late bool _switch1 = false;
|
||||
late bool _doorContactState = false;
|
||||
late int _countdown1 = 0;
|
||||
late int _countdownAlarm = 0;
|
||||
late String _doorControl1 = "closed";
|
||||
late bool _voiceControl1 = false;
|
||||
late String _doorState1 = "closed";
|
||||
late int _batteryPercentage = 0;
|
||||
late int _tr_timecon = 0;
|
||||
|
||||
for (var status in jsonList) {
|
||||
switch (status.code) {
|
||||
case 'tr_timecon':
|
||||
_tr_timecon = status.value ?? "closed";
|
||||
break;
|
||||
case 'switch_1':
|
||||
_switch1 = status.value ?? false;
|
||||
break;
|
||||
case 'doorcontact_state':
|
||||
_doorContactState = status.value ?? false;
|
||||
break;
|
||||
case 'countdown_1':
|
||||
_countdown1 = status.value ?? 0;
|
||||
break;
|
||||
case 'countdown_alarm':
|
||||
_countdownAlarm = status.value ?? 0;
|
||||
break;
|
||||
case 'door_control_1':
|
||||
_doorControl1 = status.value ?? "closed";
|
||||
break;
|
||||
|
||||
case 'voice_control_1':
|
||||
_voiceControl1 = status.value ?? false;
|
||||
break;
|
||||
case 'door_state_1':
|
||||
_doorState1 = status.value ?? "closed";
|
||||
break;
|
||||
case 'battery_percentage':
|
||||
_batteryPercentage = status.value ?? 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GarageDoorModel(
|
||||
switch1: _switch1,
|
||||
doorContactState: _doorContactState,
|
||||
countdown1: _countdown1,
|
||||
countdownAlarm: _countdownAlarm,
|
||||
doorControl1: _doorControl1,
|
||||
voiceControl1: _voiceControl1,
|
||||
doorState1: _doorState1,
|
||||
batteryPercentage: _batteryPercentage,
|
||||
tr_timecon: _tr_timecon);
|
||||
}
|
||||
}
|
||||
11
lib/features/devices/model/group_garage_model.dart
Normal file
@ -0,0 +1,11 @@
|
||||
class GroupGarageModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
|
||||
GroupGarageModel({
|
||||
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 )
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
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,4 +1,3 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@ -17,8 +16,8 @@ class CurtainButtons extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_buildButton(
|
||||
onTap: () => context.read<CurtainBloc>().add(OpenCurtain(curtain.productType!)),
|
||||
iconPath: Assets.assetsIconsCurtainsIconOpenCurtain,
|
||||
onTap: () => context.read<CurtainBloc>().add(CloseCurtain(curtain.productType!)),
|
||||
iconPath: Assets.assetsIconsCurtainsIconCloseCurtain,
|
||||
),
|
||||
_buildButton(
|
||||
onTap: () => context.read<CurtainBloc>().add(PauseCurtain()),
|
||||
@ -26,8 +25,8 @@ class CurtainButtons extends StatelessWidget {
|
||||
isSvg: false,
|
||||
),
|
||||
_buildButton(
|
||||
onTap: () => context.read<CurtainBloc>().add(CloseCurtain(curtain.productType!)),
|
||||
iconPath: Assets.assetsIconsCurtainsIconCloseCurtain,
|
||||
onTap: () => context.read<CurtainBloc>().add(OpenCurtain(curtain.productType!)),
|
||||
iconPath: Assets.assetsIconsCurtainsIconOpenCurtain,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@ -6,6 +6,7 @@ import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_event.dar
|
||||
import 'package:syncrow_app/features/devices/bloc/curtain_bloc/curtain_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_buttons.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/generated/assets.dart';
|
||||
|
||||
@ -19,7 +20,7 @@ class CurtainView extends StatelessWidget {
|
||||
create: (context) => CurtainBloc(curtain.uuid!)..add(InitCurtain()),
|
||||
child: BlocBuilder<CurtainBloc, CurtainState>(
|
||||
builder: (context, state) {
|
||||
double curtainWidth = 270;
|
||||
double curtainWidth = MediaQuery.sizeOf(context).width * 0.6;
|
||||
// double blindHeight = 310;
|
||||
if (state is CurtainsOpening) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
@ -33,66 +34,117 @@ class CurtainView extends StatelessWidget {
|
||||
}
|
||||
return DefaultScaffold(
|
||||
title: curtain.name,
|
||||
child: Column(
|
||||
children: [
|
||||
Stack(
|
||||
alignment: Alignment.centerLeft,
|
||||
children: [
|
||||
Container(
|
||||
height: 340,
|
||||
width: 365,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
Assets.assetsImagesWindow,
|
||||
),
|
||||
child: state is CurtainLoadingState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<CurtainBloc>(context).add(InitCurtain());
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(40),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.linear,
|
||||
height: 310,
|
||||
width: curtainWidth,
|
||||
child: Stack(
|
||||
children: List.generate(
|
||||
10,
|
||||
(index) {
|
||||
double spacing = curtainWidth / 9;
|
||||
double leftMostPosition = index * spacing;
|
||||
return AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.linear,
|
||||
left: leftMostPosition,
|
||||
child: SizedBox(
|
||||
height: 320,
|
||||
width: 32,
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsIconsCurtainsIconVerticalBlade,
|
||||
fit: BoxFit.fill,
|
||||
Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.assetsImagesWindow,
|
||||
width: MediaQuery.sizeOf(context).width * 0.85,
|
||||
height: MediaQuery.sizeOf(context).height * 0.4,
|
||||
),
|
||||
SizedBox(
|
||||
height: MediaQuery.sizeOf(context).height * 0.4,
|
||||
child: Column(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.assetsIconsCurtainsIconCurtainHolder,
|
||||
width: MediaQuery.sizeOf(context).width * 0.75,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.75,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.025,
|
||||
),
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.linear,
|
||||
height: MediaQuery.sizeOf(context).height * 0.35,
|
||||
width: MediaQuery.sizeOf(context).width * 0.35,
|
||||
child: Stack(
|
||||
children: List.generate(
|
||||
4,
|
||||
(index) {
|
||||
double spacing = curtainWidth / 7.5;
|
||||
double leftMostPosition = index * spacing;
|
||||
return AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.linear,
|
||||
left: leftMostPosition,
|
||||
child: SizedBox(
|
||||
height:
|
||||
MediaQuery.sizeOf(context).height * 0.35,
|
||||
width: MediaQuery.sizeOf(context).width * 0.08,
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsIconsCurtainsIconVerticalBlade,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.linear,
|
||||
height: MediaQuery.sizeOf(context).height * 0.35,
|
||||
width: MediaQuery.sizeOf(context).width * 0.35,
|
||||
child: Stack(
|
||||
children: List.generate(
|
||||
4,
|
||||
(index) {
|
||||
double spacing = curtainWidth / 7.5;
|
||||
double rightMostPosition = index * spacing;
|
||||
return AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.linear,
|
||||
right: rightMostPosition,
|
||||
child: SizedBox(
|
||||
height: MediaQuery.sizeOf(context).height * 0.35,
|
||||
width: MediaQuery.sizeOf(context).width * 0.08,
|
||||
child: SvgPicture.asset(
|
||||
Assets.rightVerticalBlade,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.025,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 80),
|
||||
CurtainButtons(curtain: curtain),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 27,
|
||||
left: 43,
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsIconsCurtainsIconCurtainHolder,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 80),
|
||||
CurtainButtons(curtain: curtain),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@ -0,0 +1,204 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garagedialog.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class CreateGarageSchedule extends StatefulWidget {
|
||||
final List<Map<String, String>> days;
|
||||
final void Function(List<String> selectedDays)?
|
||||
selectDays;
|
||||
final Function(DateTime) onDateTimeChanged;
|
||||
final void Function(bool isOn)? onToggleChanged;
|
||||
|
||||
const CreateGarageSchedule({
|
||||
Key? key,
|
||||
required this.days,
|
||||
required this.selectDays,
|
||||
required this.onDateTimeChanged,
|
||||
this.onToggleChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CreateGarageScheduleState createState() => _CreateGarageScheduleState();
|
||||
}
|
||||
|
||||
class _CreateGarageScheduleState extends State<CreateGarageSchedule> {
|
||||
List<String> selectedDays = [];
|
||||
bool isOn = true;
|
||||
String selectedControlOption = 'Open';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
SizedBox(
|
||||
height: 110,
|
||||
child: CupertinoDatePicker(
|
||||
mode: CupertinoDatePickerMode.time,
|
||||
initialDateTime: DateTime.now(),
|
||||
onDateTimeChanged: widget.onDateTimeChanged,
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.08,
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: widget.days.map((day) {
|
||||
bool isSelected = selectedDays.contains(day['day']);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (isSelected) {
|
||||
selectedDays.remove(day['day']);
|
||||
} else {
|
||||
selectedDays.add(day['day']!);
|
||||
}
|
||||
if (widget.selectDays != null) {
|
||||
widget.selectDays!(selectedDays);
|
||||
}
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
width: 50,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 8),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? Colors.black
|
||||
: ColorsManager.grayColor,
|
||||
),
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
day['day']!,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: isSelected
|
||||
? Colors.black
|
||||
: ColorsManager.grayColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
DefaultContainer(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Notification',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: true,
|
||||
onChanged: (value) {
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return GarageDialog(
|
||||
label2: 'Close',
|
||||
initialSelectedLabel: selectedControlOption,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
setState(() {});
|
||||
if (selectedControlOption == "Open") {
|
||||
widget.onToggleChanged!(true);
|
||||
} else if (selectedControlOption == 'Close') {
|
||||
widget.onToggleChanged!(false);
|
||||
}
|
||||
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: 'Control',
|
||||
label1: 'Open',
|
||||
onTapLabel1: (selected) {
|
||||
setState(() {
|
||||
selectedControlOption = 'Open';
|
||||
});
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
setState(() {
|
||||
selectedControlOption = 'Close';
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Control',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: SizedBox(
|
||||
width: 70,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontColor: ColorsManager.textGray,
|
||||
text: selectedControlOption,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.textGray,
|
||||
size: 17,
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,399 @@
|
||||
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/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garage_preferences_settings.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garage_records_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/schedule_garage_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/timer_page.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 GarageDoorScreen extends StatelessWidget {
|
||||
final DeviceModel? device;
|
||||
|
||||
const GarageDoorScreen({super.key, this.device});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Garage Door Opener',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
GarageDoorBloc(GDId: device?.uuid ?? '')..add(const GarageDoorInitial()),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final garageBloc = BlocProvider.of<GarageDoorBloc>(context);
|
||||
// GarageDoorModel model = GarageDoorModel(
|
||||
// tr_timecon: 0,
|
||||
// countdown1: 0,
|
||||
// countdownAlarm: 0,
|
||||
// doorContactState: false,
|
||||
// doorControl1: '',
|
||||
// doorState1: '',
|
||||
// switch1: false,
|
||||
// voiceControl1: false,
|
||||
// batteryPercentage: 0,
|
||||
// );
|
||||
|
||||
// if (state is LoadingNewSate) {
|
||||
// model = state.doorSensor;
|
||||
// } else if (state is UpdateState) {
|
||||
// model = state.garageSensor;
|
||||
// }
|
||||
return state is GarageDoorLoadingState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
garageBloc.add(const GarageDoorInitial());
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.sizeOf(context).height * 0.8,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: InkWell(
|
||||
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
onTap: () {},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
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: InkWell(
|
||||
onTap: () {
|
||||
garageBloc.add(
|
||||
ToggleDoorEvent(toggle: garageBloc.toggleDoor));
|
||||
},
|
||||
child: GradientWidget(
|
||||
doorStatus: garageBloc.toggleDoor,
|
||||
seconds: garageBloc.secondSelected,
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TimerScheduleScreen(
|
||||
device: device!,
|
||||
switchCode: 'switch_1',
|
||||
deviceCode: 'countdown_1',
|
||||
)),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child: SvgPicture.asset(Assets.garageSchedule),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Schedule',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TimerPage(
|
||||
device: device!,
|
||||
switchCode: 'switch_1',
|
||||
deviceCode: 'countdown_1',
|
||||
)),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child: SvgPicture.asset(Assets.garageCountdown),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
GarageRecordsScreen(GDId: 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',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
PreferencesPage(GDId: device!.uuid!)),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child: SvgPicture.asset(Assets.garagePreferencesIcon),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Preferences',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GradientWidget extends StatefulWidget {
|
||||
const GradientWidget({required this.seconds, required this.doorStatus});
|
||||
final int seconds;
|
||||
final bool doorStatus;
|
||||
|
||||
@override
|
||||
State<GradientWidget> createState() => _GradientWidgetState();
|
||||
}
|
||||
|
||||
class _GradientWidgetState extends State<GradientWidget> with SingleTickerProviderStateMixin {
|
||||
late ScrollController _scrollController;
|
||||
late AnimationController _animationController;
|
||||
late Animation<double> _itemExtentAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scrollController = ScrollController();
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: Duration(seconds: widget.seconds),
|
||||
);
|
||||
_itemExtentAnimation =
|
||||
Tween<double>(begin: widget.doorStatus ? 0 : 15, end: widget.doorStatus ? 15 : 0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Curves.easeInOut,
|
||||
),
|
||||
)..addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (widget.doorStatus) {
|
||||
_openAnimation();
|
||||
} else {
|
||||
_closeAnimation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _openAnimation() {
|
||||
_animationController.forward();
|
||||
}
|
||||
|
||||
void _closeAnimation() {
|
||||
_animationController.reverse();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 300,
|
||||
height: 300,
|
||||
padding: EdgeInsets.only(right: 10),
|
||||
child: Stack(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.openGarageIcon,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Center(
|
||||
child: Container(
|
||||
height: 104,
|
||||
child: ListView.builder(
|
||||
itemExtent: _itemExtentAnimation.value,
|
||||
controller: _scrollController,
|
||||
itemCount: 4,
|
||||
itemBuilder: (context, index) {
|
||||
return Center(child: GradientWidget1());
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GradientWidget1 extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 97,
|
||||
height: 15,
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color(0xFF017297),
|
||||
Color(0xFF024C67),
|
||||
],
|
||||
stops: [0.0, 1.0],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_garage_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 GarageList extends StatelessWidget {
|
||||
const GarageList(
|
||||
{super.key, required this.garageList, required this.allSwitches});
|
||||
|
||||
final List<GroupGarageModel> garageList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
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<GarageDoorBloc>(context)
|
||||
.add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<GarageDoorBloc>(context)
|
||||
.add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: garageList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: garageList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: garageList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<GarageDoorBloc>(context).add(
|
||||
ChangeFirstWizardSwitchStatusEvent(
|
||||
value: garageList[index].firstSwitch,
|
||||
deviceId: garageList[index].deviceId));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,328 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_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/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class PreferencesPage extends StatelessWidget {
|
||||
final String GDId;
|
||||
const PreferencesPage({super.key, required this.GDId});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Preferences',
|
||||
child: BlocProvider(
|
||||
create: (context) => GarageDoorBloc(GDId: GDId)..add(const GarageDoorInitial()),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final garageDoorBloc = BlocProvider.of<GarageDoorBloc>(context);
|
||||
|
||||
return state is GarageDoorLoadingState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
const Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Warnings',
|
||||
fontColor: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
],
|
||||
),
|
||||
DefaultContainer(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Alarm when door is open',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Container(
|
||||
width: 100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Container(
|
||||
height: 30,
|
||||
width: 1,
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: garageDoorBloc.lowBattery,
|
||||
onChanged: (value) {
|
||||
// context
|
||||
// .read<GarageDoorBloc>()
|
||||
// .add(
|
||||
// ToggleLowBatteryEvent(
|
||||
// value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Other Settings',
|
||||
fontColor: ColorsManager.grayColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
],
|
||||
),
|
||||
DefaultContainer(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SecondDialog(
|
||||
label2: 'Close',
|
||||
initialSelectedLabel: garageDoorBloc.secondSelected.toString(),
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: (v) {
|
||||
garageDoorBloc.add(SelectSecondsEvent(seconds: v));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
title: 'Control',
|
||||
label1: 'Open',
|
||||
onTapLabel1: (selected) {},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Opening and Closing Time',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Container(
|
||||
height: 90,
|
||||
width: 120,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontColor: ColorsManager.textGray,
|
||||
text:
|
||||
'${garageDoorBloc.secondSelected.toString()} Seconds',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 15,
|
||||
color: ColorsManager.textGray,
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class SecondDialog extends StatefulWidget {
|
||||
final String label1;
|
||||
final String label2;
|
||||
final String title;
|
||||
|
||||
final Function(String)? onTapLabel1;
|
||||
final Function()? cancelTab;
|
||||
final Function(int selectedSecond)? confirmTab;
|
||||
|
||||
final String? initialSelectedLabel;
|
||||
|
||||
SecondDialog({
|
||||
required this.label1,
|
||||
required this.label2,
|
||||
required this.title,
|
||||
this.onTapLabel1,
|
||||
required this.cancelTab,
|
||||
required this.confirmTab,
|
||||
this.initialSelectedLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
_SecondDialogState createState() => _SecondDialogState();
|
||||
}
|
||||
|
||||
class _SecondDialogState extends State<SecondDialog> {
|
||||
// late String _selectedOption;
|
||||
late int selectedSecond;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Parse the initialSelectedLabel as an integer. Default to 10 if invalid or not provided.
|
||||
selectedSecond = int.tryParse(widget.initialSelectedLabel ?? '10') ?? 10;
|
||||
// _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, bottom: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 100,
|
||||
child: CupertinoPicker(
|
||||
itemExtent: 40.0,
|
||||
scrollController: FixedExtentScrollController(
|
||||
// Set the initial position based on selectedSecond
|
||||
initialItem: selectedSecond - 10,
|
||||
),
|
||||
onSelectedItemChanged: (int index) {
|
||||
setState(() {
|
||||
selectedSecond = index + 10;
|
||||
});
|
||||
},
|
||||
children: List<Widget>.generate(111, (int index) {
|
||||
return Center(
|
||||
child: BodyLarge(
|
||||
text: (index + 10).toString().padLeft(2, '0'),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w400, fontSize: 30, color: Colors.blue),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
const Text('Sec'),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
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?.call(selectedSecond);
|
||||
},
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(15),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Confirm',
|
||||
style: TextStyle(
|
||||
color: ColorsManager.primaryColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400),
|
||||
),
|
||||
),
|
||||
)),
|
||||
))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_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 GarageRecordsScreen extends StatelessWidget {
|
||||
final String GDId;
|
||||
const GarageRecordsScreen({super.key, required this.GDId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Records',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
GarageDoorBloc(GDId: GDId)..add(const ReportLogsInitial()),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final garageDoorBloc = BlocProvider.of<GarageDoorBloc>(context);
|
||||
final Map<String, List<DeviceEvent>> groupedRecords = {};
|
||||
|
||||
if (state is GarageDoorLoadingState) {
|
||||
return const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
);
|
||||
} else if (state is UpdateState) {
|
||||
for (var record in garageDoorBloc.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];
|
||||
}
|
||||
}
|
||||
}
|
||||
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: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 5, top: 10),
|
||||
child: Text(
|
||||
date,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
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'),
|
||||
),
|
||||
),
|
||||
if (idx != recordsForDate.length - 1)
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_garage_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garage_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
class GarageWizard extends StatelessWidget {
|
||||
const GarageWizard({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<GroupGarageModel> groupGarageModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Garage Door Opener',
|
||||
child: BlocProvider(
|
||||
create: (context) => GarageDoorBloc(GDId: device?.uuid ?? '')
|
||||
..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupGarageModel = state.garageList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: GarageList(
|
||||
garageList: groupGarageModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
221
lib/features/devices/view/widgets/garage_door/garagedialog.dart
Normal file
@ -0,0 +1,221 @@
|
||||
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 GarageDialog extends StatefulWidget {
|
||||
final String label1;
|
||||
final String label2;
|
||||
final String title;
|
||||
|
||||
final Function(String)? onTapLabel1;
|
||||
final Function(String)? onTapLabel2;
|
||||
final Function()? cancelTab;
|
||||
final Function()? confirmTab;
|
||||
|
||||
final String? initialSelectedLabel;
|
||||
|
||||
GarageDialog({
|
||||
required this.label1,
|
||||
required this.label2,
|
||||
required this.title,
|
||||
this.onTapLabel1,
|
||||
this.onTapLabel2,
|
||||
required this.cancelTab,
|
||||
required this.confirmTab,
|
||||
this.initialSelectedLabel,
|
||||
});
|
||||
|
||||
@override
|
||||
_GarageDialogState createState() => _GarageDialogState();
|
||||
}
|
||||
|
||||
class _GarageDialogState extends State<GarageDialog> {
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,142 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/create_schedule_garage.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/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) => GarageDoorBloc(GDId: device.uuid ?? '')..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final garageBloc = BlocProvider.of<GarageDoorBloc>(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) {
|
||||
garageBloc.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: [
|
||||
garageBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
garageBloc.add(ScheduleSaveapp());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: IconButton(
|
||||
onPressed: () {
|
||||
garageBloc.add(const ToggleCreateScheduleEvent(index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
],
|
||||
),
|
||||
child: state is GarageDoorLoading
|
||||
? 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)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
child: garageBloc.createSchedule == true
|
||||
? CreateGarageSchedule(
|
||||
onToggleChanged: (bool value) {
|
||||
garageBloc.toggleSchedule = value;
|
||||
},
|
||||
onDateTimeChanged: (DateTime dateTime) {
|
||||
garageBloc.selectedTime = dateTime;
|
||||
},
|
||||
days: garageBloc.days,
|
||||
selectDays: (List<String> selectedDays) {
|
||||
garageBloc.selectedDays = selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: garageBloc.listSchedule,
|
||||
onDismissed: (scheduleId) {
|
||||
garageBloc.listSchedule.removeWhere((schedule) =>
|
||||
schedule.scheduleId == scheduleId);
|
||||
garageBloc.add(DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
garageBloc.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';
|
||||
}
|
||||
}
|
||||
148
lib/features/devices/view/widgets/garage_door/timer_page.dart
Normal file
@ -0,0 +1,148 @@
|
||||
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/garage_door_bloc/garage_door_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/garage_door_bloc/garage_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/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';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class TimerPage extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
final String deviceCode;
|
||||
final String switchCode;
|
||||
const TimerPage(
|
||||
{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) => GarageDoorBloc(GDId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode)),
|
||||
child: BlocBuilder<GarageDoorBloc, GarageDoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final oneGangBloc = BlocProvider.of<GarageDoorBloc>(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) {
|
||||
oneGangBloc.add(OnClose());
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: DefaultTabController(
|
||||
length: 2,
|
||||
child: DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: const BodyLarge(
|
||||
text: 'Countdown',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
child: state is GarageDoorLoadingState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
),
|
||||
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(
|
||||
const SetCounterValue(
|
||||
deviceCode:
|
||||
'countdown_1',
|
||||
duration:
|
||||
Duration.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
oneGangBloc.add(SetCounterValue(
|
||||
deviceCode: 'countdown_1',
|
||||
duration: duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
}
|
||||
@ -19,28 +19,32 @@ class OneGangWizard extends StatelessWidget {
|
||||
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;
|
||||
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,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
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,203 @@
|
||||
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/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,310 @@
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -10,10 +10,14 @@ 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/garage_door/garage_door_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_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_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';
|
||||
@ -164,6 +168,34 @@ void showDeviceInterface(DeviceModel device, BuildContext 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)));
|
||||
|
||||
case DeviceType.GarageDoor:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
GarageDoorScreen(device: device)));
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
@ -17,29 +17,33 @@ class ThreeGangWizard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Lights',
|
||||
child: BlocProvider(
|
||||
create: (context) => ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||
builder: (context, state) {
|
||||
List<GroupThreeGangModel> groupThreeGangModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
create: (context) =>
|
||||
ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||
builder: (context, state) {
|
||||
List<GroupThreeGangModel> groupThreeGangModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupThreeGangModel = state.threeGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: ThreeGangList(
|
||||
threeGangList: groupThreeGangModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
if (state is UpdateGroupState) {
|
||||
groupThreeGangModel = state.threeGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: ThreeGangList(
|
||||
threeGangList: groupThreeGangModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
// import 'package:flutter/material.dart';
|
||||
// // import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
// import 'package:flutter_svg/svg.dart';
|
||||
// // import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/two_gang_bloc.dart';
|
||||
// // import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/two_gang_state.dart';
|
||||
// import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
// import 'package:syncrow_app/generated/assets.dart';
|
||||
// import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
// class GangSwitch extends StatelessWidget {
|
||||
// const GangSwitch(
|
||||
// {super.key, required this.threeGangSwitch, required this.value, required this.action});
|
||||
|
||||
// final DeviceModel threeGangSwitch;
|
||||
// final bool value;
|
||||
// final Function action;
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return InkWell(
|
||||
// overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
// onTap: () {
|
||||
// action();
|
||||
// // var tempControl = DeviceControlModel(
|
||||
// // deviceId: control.deviceId, code: control.code!, value: !control.value!);
|
||||
// // DevicesCubit.getInstance().deviceControl(
|
||||
// // tempControl,
|
||||
// // control.deviceId!,
|
||||
// // );
|
||||
// },
|
||||
// child: Stack(
|
||||
// alignment: value ? Alignment.topCenter : Alignment.bottomCenter,
|
||||
// children: [
|
||||
// Container(
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: const BorderRadius.all(Radius.circular(100.0)),
|
||||
// color: value ? ColorsManager.primaryColorWithOpacity : ColorsManager.switchOffColor,
|
||||
// ),
|
||||
// width: 60,
|
||||
// height: 115,
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(5.0),
|
||||
// child: SizedBox.square(
|
||||
// dimension: 60,
|
||||
// child: SvgPicture.asset(
|
||||
// value ? Assets.assetsIconsLightSwitchOn : Assets.assetsIconsLightSwitchOff,
|
||||
// fit: BoxFit.fill,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
@ -0,0 +1,186 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_touch/timer_screen.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/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class ScheduleScreen extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
const ScheduleScreen({required this.device, super.key});
|
||||
|
||||
@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: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: const BodyLarge(
|
||||
text: 'Schedule',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: 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: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 48,
|
||||
),
|
||||
DefaultContainer(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
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),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Bedside Light",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 18,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.dividerColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
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),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Ceiling Light",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 18,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.dividerColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
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),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Spotlight",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 18,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
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/three_touch/three_touch_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';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class ThreeTouchInterface extends StatelessWidget {
|
||||
const ThreeTouchInterface({super.key, this.touchSwitch});
|
||||
|
||||
final DeviceModel? touchSwitch;
|
||||
@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: touchSwitch != null
|
||||
? DeviceAppbar(
|
||||
deviceName: touchSwitch!.name!,
|
||||
deviceUuid: touchSwitch!.uuid!,
|
||||
)
|
||||
: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: BodyLarge(
|
||||
text: touchSwitch?.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: ThreeTouchScreen(device: touchSwitch),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.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/group_three_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 ThreeTouchList extends StatelessWidget {
|
||||
const ThreeTouchList({super.key, required this.threeTouchList, required this.allSwitches});
|
||||
|
||||
final List<GroupThreeTouchModel> threeTouchList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||
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<ThreeTouchBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: threeTouchList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: '${threeTouchList[index].deviceName} beside light'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: threeTouchList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context).add(ChangeFirstSwitchStatusEvent(
|
||||
value: threeTouchList[index].firstSwitch,
|
||||
deviceId: threeTouchList[index].deviceId));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: '${threeTouchList[index].deviceName} ceiling light'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: threeTouchList[index].secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context).add(ChangeSecondSwitchStatusEvent(
|
||||
value: threeTouchList[index].secondSwitch,
|
||||
deviceId: threeTouchList[index].deviceId));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: '${threeTouchList[index].deviceName} spotlight'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: threeTouchList[index].thirdSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context).add(ChangeThirdSwitchStatusEvent(
|
||||
value: threeTouchList[index].thirdSwitch,
|
||||
deviceId: threeTouchList[index].deviceId));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,228 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.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_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/three_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/circular_button.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_touch/schedule_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_setting.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/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class ThreeTouchScreen extends StatelessWidget {
|
||||
const ThreeTouchScreen({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) =>
|
||||
ThreeTouchBloc(switchCode: '', threeTouchId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||
builder: (context, state) {
|
||||
ThreeTouchModel threeTouchModel = ThreeTouchModel(
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off,
|
||||
relay_status_2: status.off,
|
||||
relay_status_3: status.off,
|
||||
firstSwitch: false,
|
||||
secondSwitch: false,
|
||||
thirdSwitch: false,
|
||||
firstCountDown: 0,
|
||||
secondCountDown: 0,
|
||||
thirdCountDown: 0);
|
||||
|
||||
if (state is LoadingNewSate) {
|
||||
threeTouchModel = state.threeTouchModel;
|
||||
} else if (state is UpdateState) {
|
||||
threeTouchModel = state.threeTouchModel;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<ThreeTouchBloc>(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: threeTouchModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context)
|
||||
.add(ChangeFirstSwitchStatusEvent(
|
||||
value: threeTouchModel
|
||||
.firstSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: "Bedside Light",
|
||||
fontColor:
|
||||
ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: threeTouchModel.secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeTouchBloc>( context) .add(
|
||||
ChangeSecondSwitchStatusEvent(
|
||||
value: threeTouchModel
|
||||
.secondSwitch));
|
||||
},
|
||||
),
|
||||
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: threeTouchModel.thirdSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(
|
||||
context)
|
||||
.add(ChangeThirdSwitchStatusEvent(
|
||||
value: threeTouchModel
|
||||
.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: [
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.u_turn_left,
|
||||
label: "All On",
|
||||
onTap: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context)
|
||||
.add(AllOnEvent());
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.access_time,
|
||||
label: "Timer",
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1,
|
||||
animation2) =>
|
||||
ScheduleScreen(
|
||||
device: device!,
|
||||
)));
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.access_time,
|
||||
label: "Setting",
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1,
|
||||
animation2) =>
|
||||
ThreeTouchSetting(
|
||||
device: device,
|
||||
)));
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.u_turn_left,
|
||||
label: "All Off",
|
||||
onTap: () {
|
||||
BlocProvider.of<ThreeTouchBloc>(context)
|
||||
.add(AllOffEvent());
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,403 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.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_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 ThreeTouchSetting extends StatelessWidget {
|
||||
const ThreeTouchSetting({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Setting',
|
||||
child: BlocProvider(
|
||||
create: (context) => ThreeTouchBloc(switchCode: '', threeTouchId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: false)),
|
||||
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||
builder: (context, state) {
|
||||
final threeTouchBloc = BlocProvider.of<ThreeTouchBloc>(context);
|
||||
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 {
|
||||
threeTouchBloc.optionSelected = 'relay_status';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
threeTouchBloc.deviceStatus.relay.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
threeTouchBloc.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) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
threeTouchBloc.add(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: threeTouchBloc.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 {
|
||||
threeTouchBloc.optionSelected = 'light_mode';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
threeTouchBloc.deviceStatus.light_mode.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
threeTouchBloc.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) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
threeTouchBloc.add(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: threeTouchBloc.deviceStatus.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 {
|
||||
threeTouchBloc.optionSelected = 'relay_status_1';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
threeTouchBloc.deviceStatus.relay_status_1.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
threeTouchBloc.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) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
threeTouchBloc
|
||||
.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: threeTouchBloc
|
||||
.deviceStatus.relay_status_1.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 {
|
||||
threeTouchBloc.optionSelected = 'relay_status_2';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
threeTouchBloc.deviceStatus.relay_status_2.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
threeTouchBloc.add(ChangeStatusEvent(
|
||||
deviceId: device!.uuid!, context: context));
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
title: 'Restart Status 2',
|
||||
label1: 'Power Off',
|
||||
label2: 'Power On',
|
||||
label3: 'Restart Memory',
|
||||
onTapLabel1: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
threeTouchBloc
|
||||
.add(const InitialEvent(groupScreen: false));
|
||||
threeTouchBloc
|
||||
.add(const InitialEvent(groupScreen: false));
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Restart Status 2',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: threeTouchBloc
|
||||
.deviceStatus.relay_status_2.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 {
|
||||
threeTouchBloc.optionSelected = 'relay_status_3';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
threeTouchBloc.deviceStatus.relay_status_3.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
threeTouchBloc.add(ChangeStatusEvent(
|
||||
deviceId: device!.uuid!, context: context));
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
title: 'Restart Status 3',
|
||||
label1: 'Power Off',
|
||||
label2: 'Power On',
|
||||
label3: 'Restart Memory',
|
||||
onTapLabel1: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
threeTouchBloc.statusSelected = selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
threeTouchBloc
|
||||
.add(const InitialEvent(groupScreen: false));
|
||||
threeTouchBloc
|
||||
.add(const InitialEvent(groupScreen: false));
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Restart Status 3',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: threeTouchBloc
|
||||
.deviceStatus.relay_status_3.value,
|
||||
fontColor: ColorsManager.textGray,
|
||||
),
|
||||
const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.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_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_three_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
class ThreeTouchWizard extends StatelessWidget {
|
||||
const ThreeTouchWizard({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Lights',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
ThreeTouchBloc(switchCode: '', threeTouchId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||
builder: (context, state) {
|
||||
List<GroupThreeTouchModel> groupThreeTouchModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupThreeTouchModel = state.threeTouchList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
:
|
||||
ThreeTouchList(
|
||||
threeTouchList: groupThreeTouchModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
320
lib/features/devices/view/widgets/three_touch/timer_screen.dart
Normal file
@ -0,0 +1,320 @@
|
||||
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/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_touch_bloc/three_touch_bloc.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_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) => ThreeTouchBloc(
|
||||
switchCode: switchCode, threeTouchId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<ThreeTouchBloc, ThreeTouchState>(
|
||||
builder: (context, state) {
|
||||
final threeTouchBloc = BlocProvider.of<ThreeTouchBloc>(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) {
|
||||
threeTouchBloc.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: [
|
||||
threeTouchBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
threeTouchBloc.add(ThreeTouchSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: threeTouchBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneTouchBloc.toggleCreateSchedule();
|
||||
threeTouchBloc.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 (threeTouchBloc.createSchedule ==
|
||||
// true) {
|
||||
// threeTouchBloc.toggleCreateSchedule();
|
||||
// }
|
||||
// threeTouchBloc.toggleSelectedIndex(0);
|
||||
// } else {
|
||||
// threeTouchBloc.toggleSelectedIndex(1);
|
||||
// }
|
||||
// },
|
||||
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (threeTouchBloc.createSchedule ==
|
||||
true) {
|
||||
// oneTouchBloc.toggleCreateSchedule();
|
||||
threeTouchBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
threeTouchBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
threeTouchBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 1));
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white,
|
||||
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) {
|
||||
threeTouchBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
threeTouchBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: threeTouchBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
threeTouchBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
threeTouchBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: threeTouchBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
threeTouchBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ScheduleListView(
|
||||
listSchedule: threeTouchBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed:
|
||||
(scheduleId) {
|
||||
threeTouchBloc
|
||||
.listSchedule
|
||||
.removeWhere(
|
||||
(schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
threeTouchBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId,
|
||||
isEnabled) {
|
||||
threeTouchBloc.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';
|
||||
}
|
||||
}
|
||||
@ -19,28 +19,32 @@ class TwoGangWizard extends StatelessWidget {
|
||||
List<GroupTwoGangModel> groupTwoGangModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Lights',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
TwoGangBloc(switchCode: '', twoGangId: device?.uuid ?? '')..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<TwoGangBloc, TwoGangState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
create: (context) =>
|
||||
TwoGangBloc(switchCode: '', twoGangId: device?.uuid ?? '')
|
||||
..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<TwoGangBloc, TwoGangState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupTwoGangModel = state.twoGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: TwoGangList(
|
||||
twoGangList: groupTwoGangModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
if (state is UpdateGroupState) {
|
||||
groupTwoGangModel = state.twoGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: TwoGangList(
|
||||
twoGangList: groupTwoGangModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,141 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_Touch/two_timer_screen.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/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class TwoTouchScheduleScreen extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
const TwoTouchScheduleScreen({required this.device, super.key});
|
||||
|
||||
@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: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: const BodyLarge(
|
||||
text: 'Schedule',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: 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: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 48,
|
||||
),
|
||||
DefaultContainer(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: Column(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
device: device,
|
||||
deviceCode: 'countdown_1',
|
||||
switchCode:'switch_1' ,
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Cove Light",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 18,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.dividerColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
device: device,
|
||||
deviceCode: 'countdown_2',
|
||||
switchCode:'switch_2' ,
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Chandelier",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 18,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,303 @@
|
||||
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/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.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_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) =>
|
||||
TwoTouchBloc(switchCode: switchCode, twoTouchId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||
builder: (context, state) {
|
||||
final twoTouchBloc = BlocProvider.of<TwoTouchBloc>(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) {
|
||||
twoTouchBloc.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: [
|
||||
twoTouchBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
twoTouchBloc.add(TwoTouchSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: twoTouchBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneTouchBloc.toggleCreateSchedule();
|
||||
twoTouchBloc.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 (twoTouchBloc.createSchedule ==
|
||||
true) {
|
||||
// oneTouchBloc.toggleCreateSchedule();
|
||||
twoTouchBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
twoTouchBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
twoTouchBloc.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: 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) {
|
||||
twoTouchBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
twoTouchBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: twoTouchBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
twoTouchBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
twoTouchBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: twoTouchBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
twoTouchBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ScheduleListView(
|
||||
listSchedule: twoTouchBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed:
|
||||
(scheduleId) {
|
||||
twoTouchBloc
|
||||
.listSchedule
|
||||
.removeWhere(
|
||||
(schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
twoTouchBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId,
|
||||
isEnabled) {
|
||||
twoTouchBloc.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,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
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/two_touch/two_touch_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';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class TwoTouchInterface extends StatelessWidget {
|
||||
const TwoTouchInterface({super.key, this.touchSwitch});
|
||||
|
||||
final DeviceModel? touchSwitch;
|
||||
@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: touchSwitch != null
|
||||
? DeviceAppbar(
|
||||
deviceName: touchSwitch!.name!,
|
||||
deviceUuid: touchSwitch!.uuid!,
|
||||
)
|
||||
: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: BodyLarge(
|
||||
text: touchSwitch?.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: TwoTouchScreen(device: touchSwitch),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.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/group_two_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 TwoTouchList extends StatelessWidget {
|
||||
const TwoTouchList(
|
||||
{super.key, required this.twoTouchList, required this.allSwitches});
|
||||
|
||||
final List<GroupTwoTouchModel> twoTouchList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||
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<TwoTouchBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: twoTouchList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: twoTouchList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: twoTouchList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context).add(
|
||||
ChangeFirstWizardSwitchStatusEvent(
|
||||
value: twoTouchList[index].firstSwitch,
|
||||
deviceId: twoTouchList[index].deviceId));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: twoTouchList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: twoTouchList[index].secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context).add(
|
||||
ChangeSecondWizardSwitchStatusEvent(
|
||||
value: twoTouchList[index].secondSwitch,
|
||||
deviceId: twoTouchList[index].deviceId));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,333 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.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_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/circular_button.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_setting.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_schedule_screen.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/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
class TwoTouchScreen extends StatelessWidget {
|
||||
const TwoTouchScreen({super.key, this.device, this.switchCode});
|
||||
final DeviceModel? device;
|
||||
final String? switchCode;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => TwoTouchBloc(
|
||||
switchCode: switchCode ?? '', twoTouchId: device?.uuid ?? '')
|
||||
..add(const InitialEvent()),
|
||||
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||
builder: (context, state) {
|
||||
TwoTouchModel twoTouchModel = 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,
|
||||
);
|
||||
|
||||
if (state is LoadingNewSate) {
|
||||
twoTouchModel = state.twoTouchModel;
|
||||
} else if (state is UpdateState) {
|
||||
twoTouchModel = state.twoTouchModel;
|
||||
}
|
||||
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<TwoTouchBloc>(context)
|
||||
.add(const InitialEvent());
|
||||
},
|
||||
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: twoTouchModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context)
|
||||
.add(ChangeFirstSwitchStatusEvent(
|
||||
value: twoTouchModel
|
||||
.firstSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 77,
|
||||
child: BodySmall(
|
||||
text: "Cove Light",
|
||||
fontColor:
|
||||
ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: twoTouchModel.secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context)
|
||||
.add(
|
||||
ChangeSecondSwitchStatusEvent(
|
||||
value: twoTouchModel
|
||||
.secondSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 77,
|
||||
child: BodySmall(
|
||||
text: "Chandelier",
|
||||
fontColor:
|
||||
ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.u_turn_left,
|
||||
label: "All On",
|
||||
onTap: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context)
|
||||
.add(AllOnEvent());
|
||||
},
|
||||
),
|
||||
|
||||
// Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
|
||||
// Card(
|
||||
// elevation: 3,
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius:
|
||||
// BorderRadius.circular(100),
|
||||
// ),
|
||||
// child: GestureDetector(
|
||||
// onTap: () {
|
||||
// BlocProvider.of<TwoTouchBloc>(
|
||||
// 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,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.access_time,
|
||||
label: "Timer",
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1,
|
||||
animation2) =>
|
||||
TwoTouchScheduleScreen(
|
||||
device: device!,
|
||||
)));
|
||||
},
|
||||
),
|
||||
// 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) =>
|
||||
// TwoTouchScheduleScreen(
|
||||
// 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,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.access_time,
|
||||
label: "Setting",
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1,
|
||||
animation2) =>
|
||||
TwoTouchSetting(
|
||||
device: device,
|
||||
)));
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
CircularButton(
|
||||
device: device,
|
||||
icons: Icons.access_time,
|
||||
label: "All Off",
|
||||
onTap: () {
|
||||
BlocProvider.of<TwoTouchBloc>(context)
|
||||
.add(AllOffEvent());
|
||||
},
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,394 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.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_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_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 TwoTouchSetting extends StatelessWidget {
|
||||
const TwoTouchSetting({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Setting',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
TwoTouchBloc(switchCode: '', twoTouchId: device?.uuid ?? '')
|
||||
..add(const InitialEvent()),
|
||||
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||
builder: (context, state) {
|
||||
final twoTouchBloc = BlocProvider.of<TwoTouchBloc>(context);
|
||||
TwoTouchModel? twoTouchModel = TwoTouchModel(
|
||||
relay_status_2: status.off,
|
||||
secondCountDown: 0,
|
||||
secondSwitch: false,
|
||||
firstSwitch: false,
|
||||
firstCountDown: 0,
|
||||
light_mode: lightStatus.off,
|
||||
relay: status.off,
|
||||
relay_status_1: status.off);
|
||||
|
||||
// if (state is UpdateState) {
|
||||
// TwoTouchModel = state.TwoTouchModel;
|
||||
// }
|
||||
if (state is UpdateState) {
|
||||
twoTouchModel = state.twoTouchModel;
|
||||
}
|
||||
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 {
|
||||
twoTouchBloc.optionSelected =
|
||||
'relay_status';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
twoTouchModel!.relay.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
twoTouchBloc.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) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(const Duration(seconds: 2),
|
||||
() async {
|
||||
twoTouchBloc.add(const InitialEvent());
|
||||
});
|
||||
}
|
||||
},
|
||||
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: twoTouchModel.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 {
|
||||
twoTouchBloc.optionSelected =
|
||||
'light_mode';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
twoTouchModel!.light_mode.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
twoTouchBloc.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) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() async {
|
||||
twoTouchBloc
|
||||
.add(const InitialEvent());
|
||||
});
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Indicator Status',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: twoTouchBloc.deviceStatus
|
||||
.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 {
|
||||
twoTouchBloc.optionSelected =
|
||||
'relay_status_1';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
twoTouchModel!
|
||||
.relay_status_1.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
twoTouchBloc.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) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() async {
|
||||
twoTouchBloc
|
||||
.add(const InitialEvent());
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Restart Status 1',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: twoTouchBloc.deviceStatus
|
||||
.relay_status_1.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 {
|
||||
twoTouchBloc.optionSelected =
|
||||
'relay_status_2';
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return RestartStatusDialog(
|
||||
initialSelectedLabel:
|
||||
twoTouchModel!
|
||||
.relay_status_2.value,
|
||||
cancelTab: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
confirmTab: () {
|
||||
twoTouchBloc.add(
|
||||
ChangeStatusEvent(
|
||||
deviceId: device!.uuid!,
|
||||
context: context));
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
title: 'Restart Status 2',
|
||||
label1: 'Power Off',
|
||||
label2: 'Power On',
|
||||
label3: 'Restart Memory',
|
||||
onTapLabel1: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel2: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
onTapLabel3: (selected) {
|
||||
twoTouchBloc.statusSelected =
|
||||
selected;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == true) {
|
||||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() async {
|
||||
twoTouchBloc
|
||||
.add(const InitialEvent());
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const BodyLarge(
|
||||
fontSize: 15,
|
||||
text: 'Restart Status 2',
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
BodyMedium(
|
||||
fontSize: 13,
|
||||
text: twoTouchBloc.deviceStatus
|
||||
.relay_status_2.value,
|
||||
fontColor:
|
||||
ColorsManager.textGray,
|
||||
),
|
||||
const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
color: ColorsManager.textGray,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_touch_bloc/two_touch_bloc.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_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_touch_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
|
||||
class TwoTouchWizard extends StatelessWidget {
|
||||
const TwoTouchWizard({super.key, this.device});
|
||||
|
||||
final DeviceModel? device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<GroupTwoTouchModel> groupTwoTouchModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Lights',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
TwoTouchBloc(switchCode: '', twoTouchId: device?.uuid ?? '')
|
||||
..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<TwoTouchBloc, TwoTouchState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupTwoTouchModel = state.twoTouchList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: TwoTouchList(
|
||||
twoTouchList: groupTwoTouchModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -19,28 +19,29 @@ class WHWizard extends StatelessWidget {
|
||||
List<GroupWHModel> groupModel = [];
|
||||
|
||||
return DefaultScaffold(
|
||||
title: 'Water Heater',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
WaterHeaterBloc(switchCode: '', whId: device?.uuid ?? '')..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
create: (context) =>
|
||||
WaterHeaterBloc(switchCode: '', whId: device?.uuid ?? '')..add(InitialWizardEvent()),
|
||||
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
|
||||
builder: (context, state) {
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is UpdateGroupState) {
|
||||
groupModel = state.twoGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is WHLoadingState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: WHList(
|
||||
whList: groupModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
if (state is UpdateGroupState) {
|
||||
groupModel = state.twoGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is WHLoadingState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: WHList(
|
||||
whList: groupModel,
|
||||
allSwitches: allSwitchesOn,
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,13 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/garage_door/garage_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_touch/one_touch_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_touch/three_touch_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_touch/two_touch_wizard.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/water_heater/wh_wizard.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
@ -64,6 +68,38 @@ class WizardPage extends StatelessWidget {
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const WHWizard()));
|
||||
}
|
||||
|
||||
if (groupsList[index].name == '1GT') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const OneTouchWizard()));
|
||||
}
|
||||
|
||||
if (groupsList[index].name == '2GT') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const TwoTouchWizard()));
|
||||
}
|
||||
|
||||
if (groupsList[index].name == '3GT') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const ThreeTouchWizard()));
|
||||
}
|
||||
|
||||
if (groupsList[index].name == 'GD') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const GarageWizard()));
|
||||
}
|
||||
},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(15),
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/menu_cubit.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/menu_list.dart';
|
||||
@ -7,7 +8,6 @@ import 'package:syncrow_app/features/menu/view/widgets/profile/profile_tab.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_medium.dart';
|
||||
import 'package:syncrow_app/services/locator.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
|
||||
@ -34,7 +34,7 @@ class MenuView extends StatelessWidget {
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
BodyMedium(text: serviceLocator.get<String>()),
|
||||
BodyMedium(text: dotenv.env['ENV_NAME'] ?? ''),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
|
||||
@ -137,3 +137,5 @@ class _CreateScheduleState extends State<CreateSchedule> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -4,7 +4,10 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class DevicesDefaultSwitch extends StatelessWidget {
|
||||
const DevicesDefaultSwitch(
|
||||
{super.key, required this.switchValue, required this.action, this.secondAction});
|
||||
{super.key,
|
||||
required this.switchValue,
|
||||
required this.action,
|
||||
this.secondAction});
|
||||
|
||||
final bool switchValue;
|
||||
final Function action;
|
||||
@ -22,7 +25,9 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: switchValue ? ColorsManager.primaryColor : Colors.white,
|
||||
color: switchValue
|
||||
? ColorsManager.switchButton.withOpacity(0.6)
|
||||
: Colors.white,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(15),
|
||||
bottomLeft: Radius.circular(15),
|
||||
@ -30,9 +35,10 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
fontSize: 14,
|
||||
text: "ON",
|
||||
fontColor: switchValue ? Colors.white : null,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -50,7 +56,9 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
||||
child: Container(
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: switchValue ? Colors.white : ColorsManager.primaryColor,
|
||||
color: switchValue
|
||||
? Colors.white
|
||||
: ColorsManager.switchButton.withOpacity(0.6),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(15),
|
||||
bottomRight: Radius.circular(15),
|
||||
@ -58,9 +66,10 @@ class DevicesDefaultSwitch extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
fontSize: 14,
|
||||
text: "OFF",
|
||||
fontColor: switchValue ? null : Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@ -3,8 +3,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsFontsAftikaRegular
|
||||
/// assets/fonts/AftikaRegular.ttf
|
||||
static const String assetsFontsAftikaRegular =
|
||||
"assets/fonts/AftikaRegular.ttf";
|
||||
static const String assetsFontsAftikaRegular = "assets/fonts/AftikaRegular.ttf";
|
||||
|
||||
/// Assets for assetsIcons3GangSwitch
|
||||
/// assets/icons/3GangSwitch.svg
|
||||
@ -20,98 +19,82 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsAutomatedClock
|
||||
/// assets/icons/automated_clock.svg
|
||||
static const String assetsIconsAutomatedClock =
|
||||
"assets/icons/automated_clock.svg";
|
||||
static const String assetsIconsAutomatedClock = "assets/icons/automated_clock.svg";
|
||||
static const String acSwitchIcon = "assets/icons/ac_switch_ic.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOffpmOnstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOffpmOnstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOfflowOnpmOnstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOfflowOnpmOnstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOnlowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOnlowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOffstlowBatterydmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOffstlowBatterydmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff
|
||||
/// assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOffchargOnlowOnpmOnstlowpmdmOff =
|
||||
"assets/icons/battery/dmOff/perOffchargOnlowOnpmOnstlowpmdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOffpmOnstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOffpmOnstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOffstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOffstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOfflowOnpmOnstDefaultdmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOfflowOnpmOnstDefaultdmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOnlowOffpmOffstChargeddmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOnlowOffpmOffstChargeddmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff
|
||||
/// assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
|
||||
static const String assetsIconsBatteryDmOffPerOnchargOnlowOnpmOffstlowBatterydmOff =
|
||||
"assets/icons/battery/dmOff/perOnchargOnlowOnpmOffstlowBatterydmOff.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOffPerOnchargOnlowOnpmOnstlowpmdmOff
|
||||
@ -121,44 +104,37 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOffpmOnstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOffpmOnstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOfflowOnpmOnstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOfflowOnpmOnstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOnlowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOnlowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn
|
||||
/// assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOffchargOnlowOnpmOffstlowBatterydmOn =
|
||||
"assets/icons/battery/dmOn/perOffchargOnlowOnpmOffstlowBatterydmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOffchargOnlowOnpmOnstlowpmdmOn
|
||||
@ -168,44 +144,37 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOffpmOnstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOffpmOnstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOffstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOffstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOfflowOnpmOnstDefaultdmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOfflowOnpmOnstDefaultdmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOnlowOffpmOffstChargeddmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOnlowOffpmOffstChargeddmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn
|
||||
/// assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg
|
||||
static const String
|
||||
assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
|
||||
static const String assetsIconsBatteryDmOnPerOnchargOnlowOnpmOffstlowBatterydmOn =
|
||||
"assets/icons/battery/dmOn/perOnchargOnlowOnpmOffstlowBatterydmOn.svg";
|
||||
|
||||
/// Assets for assetsIconsBatteryDmOnPerOnchargOnlowOnpmOnstlowpmdmOn
|
||||
@ -247,7 +216,9 @@ class Assets {
|
||||
/// Assets for assetsIconsCurtainsIconVerticalBlade
|
||||
/// assets/icons/curtainsIcon/verticalBlade.svg
|
||||
static const String assetsIconsCurtainsIconVerticalBlade =
|
||||
"assets/icons/curtainsIcon/verticalBlade.svg";
|
||||
"assets/icons/curtainsIcon/left_vertical_blade.svg";
|
||||
|
||||
static const String rightVerticalBlade = "assets/icons/curtainsIcon/right_vertical_blade.svg";
|
||||
|
||||
/// Assets for assetsIconsDashboard
|
||||
/// assets/icons/dashboard.svg
|
||||
@ -257,8 +228,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsDashboardFill
|
||||
/// assets/icons/dashboard-fill.svg
|
||||
static const String assetsIconsDashboardFill =
|
||||
"assets/icons/dashboard-fill.svg";
|
||||
static const String assetsIconsDashboardFill = "assets/icons/dashboard-fill.svg";
|
||||
|
||||
/// Assets for assetsIconsDevices
|
||||
/// assets/icons/Devices.svg
|
||||
@ -274,8 +244,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsDoorLockLinkage
|
||||
/// assets/icons/DoorLockLinkage.svg
|
||||
static const String assetsIconsDoorLockLinkage =
|
||||
"assets/icons/DoorLockLinkage.svg";
|
||||
static const String assetsIconsDoorLockLinkage = "assets/icons/DoorLockLinkage.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorLockLock
|
||||
/// assets/icons/DoorLockLock.svg
|
||||
@ -283,18 +252,15 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsDoorLockMembers
|
||||
/// assets/icons/DoorLockMembers.svg
|
||||
static const String assetsIconsDoorLockMembers =
|
||||
"assets/icons/DoorLockMembers.svg";
|
||||
static const String assetsIconsDoorLockMembers = "assets/icons/DoorLockMembers.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorLockPassword
|
||||
/// assets/icons/DoorLockPassword.svg
|
||||
static const String assetsIconsDoorLockPassword =
|
||||
"assets/icons/DoorLockPassword.svg";
|
||||
static const String assetsIconsDoorLockPassword = "assets/icons/DoorLockPassword.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorLockRecords
|
||||
/// assets/icons/DoorLockRecords.svg
|
||||
static const String assetsIconsDoorLockRecords =
|
||||
"assets/icons/DoorLockRecords.svg";
|
||||
static const String assetsIconsDoorLockRecords = "assets/icons/DoorLockRecords.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorlockAssetsBatteryIndicator
|
||||
/// assets/icons/doorlock-assets/BatteryIndicator.svg
|
||||
@ -315,8 +281,7 @@ class Assets {
|
||||
/// assets/icons/doorlock-assets/lockIcon.svg
|
||||
static const String assetsIconsDoorlockAssetsLockIcon =
|
||||
"assets/icons/doorlock-assets/lockIcon.svg";
|
||||
static const String doorUnlockIcon =
|
||||
"assets/icons/doorlock-assets/door_un_look_ic.svg";
|
||||
static const String doorUnlockIcon = "assets/icons/doorlock-assets/door_un_look_ic.svg";
|
||||
|
||||
/// Assets for assetsIconsDoorlockAssetsMembersManagement
|
||||
/// assets/icons/doorlock-assets/members-management.svg
|
||||
@ -404,13 +369,11 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsLightSwitchOff
|
||||
/// assets/icons/lightSwitchOff.svg
|
||||
static const String assetsIconsLightSwitchOff =
|
||||
"assets/icons/lightSwitchOff.svg";
|
||||
static const String assetsIconsLightSwitchOff = "assets/icons/lightSwitchOff.svg";
|
||||
|
||||
/// Assets for assetsIconsLightSwitchOn
|
||||
/// assets/icons/lightSwitchOn.svg
|
||||
static const String assetsIconsLightSwitchOn =
|
||||
"assets/icons/lightSwitchOn.svg";
|
||||
static const String assetsIconsLightSwitchOn = "assets/icons/lightSwitchOn.svg";
|
||||
|
||||
/// Assets for assetsIconsLinkageIconsDoorLockAlarm
|
||||
/// assets/icons/linkageIcons/doorLockAlarm.svg
|
||||
@ -419,8 +382,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsLinkTimeLimitedPasswordIcon
|
||||
/// assets/icons/timeLimitedPasswordIcon.svg
|
||||
static const String timeLimitedPasswordIcon =
|
||||
"assets/icons/timeLimitedPasswordIcon.svg";
|
||||
static const String timeLimitedPasswordIcon = "assets/icons/timeLimitedPasswordIcon.svg";
|
||||
|
||||
/// Assets for assetsIconsoneTimePassword
|
||||
/// assets/icons/oneTimePassword.svg
|
||||
@ -428,8 +390,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsTimeLimitedPassword
|
||||
/// assets/icons/timeLimitedPassword.svg
|
||||
static const String timeLimitedPassword =
|
||||
"assets/icons/timeLimitedPassword.svg";
|
||||
static const String timeLimitedPassword = "assets/icons/timeLimitedPassword.svg";
|
||||
|
||||
/// Assets for assetsIconsNoValidPasswords
|
||||
/// assets/icons/noValidPasswords.svg
|
||||
@ -598,13 +559,11 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
|
||||
/// assets/icons/presence-sensor-assets/space_type_icon.svg
|
||||
static const String spaceTypeIcon =
|
||||
"assets/icons/presence-sensor-assets/space_type_icon.svg";
|
||||
static const String spaceTypeIcon = "assets/icons/presence-sensor-assets/space_type_icon.svg";
|
||||
|
||||
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
|
||||
/// assets/icons/presence-sensor-assets/space_type_icon.svg
|
||||
static const String sensitivityIcon =
|
||||
"assets/icons/presence-sensor-assets/Sensitivity.svg";
|
||||
static const String sensitivityIcon = "assets/icons/presence-sensor-assets/Sensitivity.svg";
|
||||
|
||||
/// Assets for assetsIconsPresenceSensorAssetsParameterSettings
|
||||
/// assets/icons/presence-sensor-assets/maximum_distance.svg
|
||||
@ -637,8 +596,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsRoutinesFill
|
||||
/// assets/icons/Routines-fill.svg
|
||||
static const String assetsIconsRoutinesFill =
|
||||
"assets/icons/Routines-fill.svg";
|
||||
static const String assetsIconsRoutinesFill = "assets/icons/Routines-fill.svg";
|
||||
|
||||
/// Assets for assetsIconsScan
|
||||
/// assets/icons/Scan.svg
|
||||
@ -670,8 +628,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsIconsSustainability
|
||||
/// assets/icons/sustainability.svg
|
||||
static const String assetsIconsSustainability =
|
||||
"assets/icons/sustainability.svg";
|
||||
static const String assetsIconsSustainability = "assets/icons/sustainability.svg";
|
||||
|
||||
/// Assets for assetsIconsUnlockingMethodsIconsFace
|
||||
/// assets/icons/unlockingMethodsIcons/face.svg
|
||||
@ -767,8 +724,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsImagesHorizintalBlade
|
||||
/// assets/images/HorizintalBlade.png
|
||||
static const String assetsImagesHorizintalBlade =
|
||||
"assets/images/HorizintalBlade.png";
|
||||
static const String assetsImagesHorizintalBlade = "assets/images/HorizintalBlade.png";
|
||||
|
||||
/// Assets for assetsImagesLogo
|
||||
/// assets/images/Logo.svg
|
||||
@ -776,8 +732,7 @@ class Assets {
|
||||
|
||||
/// Assets for assetsImagesLogoHorizontal
|
||||
/// assets/images/logo_horizontal.png
|
||||
static const String assetsImagesLogoHorizontal =
|
||||
"assets/images/logo_horizontal.png";
|
||||
static const String assetsImagesLogoHorizontal = "assets/images/logo_horizontal.png";
|
||||
|
||||
/// Assets for assetsImagesPause
|
||||
/// assets/images/Pause.png
|
||||
@ -805,10 +760,9 @@ class Assets {
|
||||
|
||||
/// Assets for assetsImagesWindow
|
||||
/// assets/images/Window.png
|
||||
static const String assetsImagesWindow = "assets/images/Window.png";
|
||||
static const String assetsImagesWindow = "assets/images/window_img.svg";
|
||||
|
||||
static const String assetsSensitivityFunction =
|
||||
"assets/icons/functions_icons/sensitivity.svg";
|
||||
static const String assetsSensitivityFunction = "assets/icons/functions_icons/sensitivity.svg";
|
||||
|
||||
//assets/icons/functions_icons/sesitivity_operation_icon.svg
|
||||
static const String assetsSensitivityOperationIcon =
|
||||
@ -816,73 +770,59 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/ac_power.svg
|
||||
|
||||
static const String assetsAcPower =
|
||||
"assets/icons/functions_icons/ac_power.svg";
|
||||
static const String assetsAcPower = "assets/icons/functions_icons/ac_power.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_power_off.svg
|
||||
|
||||
static const String assetsAcPowerOFF =
|
||||
"assets/icons/functions_icons/ac_power_off.svg";
|
||||
static const String assetsAcPowerOFF = "assets/icons/functions_icons/ac_power_off.svg";
|
||||
|
||||
//assets/icons/functions_icons/child_lock.svg
|
||||
|
||||
static const String assetsChildLock =
|
||||
"assets/icons/functions_icons/child_lock.svg";
|
||||
static const String assetsChildLock = "assets/icons/functions_icons/child_lock.svg";
|
||||
|
||||
//assets/icons/functions_icons/cooling.svg
|
||||
|
||||
static const String assetsFreezing =
|
||||
"assets/icons/functions_icons/freezing.svg";
|
||||
static const String assetsFreezing = "assets/icons/functions_icons/freezing.svg";
|
||||
|
||||
//assets/icons/functions_icons/fan_speed.svg
|
||||
|
||||
static const String assetsFanSpeed =
|
||||
"assets/icons/functions_icons/fan_speed.svg";
|
||||
static const String assetsFanSpeed = "assets/icons/functions_icons/fan_speed.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_cooling.svg
|
||||
|
||||
static const String assetsAcCooling =
|
||||
"assets/icons/functions_icons/ac_cooling.svg";
|
||||
static const String assetsAcCooling = "assets/icons/functions_icons/ac_cooling.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_heating.svg
|
||||
|
||||
static const String assetsAcHeating =
|
||||
"assets/icons/functions_icons/ac_heating.svg";
|
||||
static const String assetsAcHeating = "assets/icons/functions_icons/ac_heating.svg";
|
||||
|
||||
//assets/icons/functions_icons/celsius_degrees.svg
|
||||
|
||||
static const String assetsCelsiusDegrees =
|
||||
"assets/icons/functions_icons/celsius_degrees.svg";
|
||||
static const String assetsCelsiusDegrees = "assets/icons/functions_icons/celsius_degrees.svg";
|
||||
|
||||
//assets/icons/functions_icons/tempreture.svg
|
||||
|
||||
static const String assetsTempreture =
|
||||
"assets/icons/functions_icons/tempreture.svg";
|
||||
static const String assetsTempreture = "assets/icons/functions_icons/tempreture.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_low.svg
|
||||
|
||||
static const String assetsAcFanLow =
|
||||
"assets/icons/functions_icons/ac_fan_low.svg";
|
||||
static const String assetsAcFanLow = "assets/icons/functions_icons/ac_fan_low.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_middle.svg
|
||||
|
||||
static const String assetsAcFanMiddle =
|
||||
"assets/icons/functions_icons/ac_fan_middle.svg";
|
||||
static const String assetsAcFanMiddle = "assets/icons/functions_icons/ac_fan_middle.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_high.svg
|
||||
|
||||
static const String assetsAcFanHigh =
|
||||
"assets/icons/functions_icons/ac_fan_high.svg";
|
||||
static const String assetsAcFanHigh = "assets/icons/functions_icons/ac_fan_high.svg";
|
||||
|
||||
//assets/icons/functions_icons/ac_fan_auto.svg
|
||||
|
||||
static const String assetsAcFanAuto =
|
||||
"assets/icons/functions_icons/ac_fan_auto.svg";
|
||||
static const String assetsAcFanAuto = "assets/icons/functions_icons/ac_fan_auto.svg";
|
||||
|
||||
//assets/icons/functions_icons/scene_child_lock.svg
|
||||
|
||||
static const String assetsSceneChildLock =
|
||||
"assets/icons/functions_icons/scene_child_lock.svg";
|
||||
static const String assetsSceneChildLock = "assets/icons/functions_icons/scene_child_lock.svg";
|
||||
|
||||
//assets/icons/functions_icons/scene_child_unlock.svg
|
||||
|
||||
@ -891,18 +831,15 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/scene_refresh.svg
|
||||
|
||||
static const String assetsSceneRefresh =
|
||||
"assets/icons/functions_icons/scene_refresh.svg";
|
||||
static const String assetsSceneRefresh = "assets/icons/functions_icons/scene_refresh.svg";
|
||||
|
||||
//assets/icons/functions_icons/light_countdown.svg
|
||||
|
||||
static const String assetsLightCountdown =
|
||||
"assets/icons/functions_icons/light_countdown.svg";
|
||||
static const String assetsLightCountdown = "assets/icons/functions_icons/light_countdown.svg";
|
||||
|
||||
//assets/icons/functions_icons/far_detection.svg
|
||||
|
||||
static const String assetsFarDetection =
|
||||
"assets/icons/functions_icons/far_detection.svg";
|
||||
static const String assetsFarDetection = "assets/icons/functions_icons/far_detection.svg";
|
||||
|
||||
//assets/icons/functions_icons/far_detection_function.svg
|
||||
|
||||
@ -911,13 +848,11 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/indicator.svg
|
||||
|
||||
static const String assetsIndicator =
|
||||
"assets/icons/functions_icons/indicator.svg";
|
||||
static const String assetsIndicator = "assets/icons/functions_icons/indicator.svg";
|
||||
|
||||
//assets/icons/functions_icons/motion_detection.svg
|
||||
|
||||
static const String assetsMotionDetection =
|
||||
"assets/icons/functions_icons/motion_detection.svg";
|
||||
static const String assetsMotionDetection = "assets/icons/functions_icons/motion_detection.svg";
|
||||
|
||||
//assets/icons/functions_icons/motionless_detection.svg
|
||||
|
||||
@ -926,18 +861,15 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/nobody_time.svg
|
||||
|
||||
static const String assetsNobodyTime =
|
||||
"assets/icons/functions_icons/nobody_time.svg";
|
||||
static const String assetsNobodyTime = "assets/icons/functions_icons/nobody_time.svg";
|
||||
|
||||
//assets/icons/functions_icons/factory_reset.svg
|
||||
|
||||
static const String assetsFactoryReset =
|
||||
"assets/icons/functions_icons/factory_reset.svg";
|
||||
static const String assetsFactoryReset = "assets/icons/functions_icons/factory_reset.svg";
|
||||
|
||||
//assets/icons/functions_icons/master_state.svg
|
||||
|
||||
static const String assetsMasterState =
|
||||
"assets/icons/functions_icons/master_state.svg";
|
||||
static const String assetsMasterState = "assets/icons/functions_icons/master_state.svg";
|
||||
|
||||
//assets/icons/functions_icons/switch_alarm_sound.svg
|
||||
|
||||
@ -946,8 +878,7 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/reset_off.svg
|
||||
|
||||
static const String assetsResetOff =
|
||||
"assets/icons/functions_icons/reset_off.svg";
|
||||
static const String assetsResetOff = "assets/icons/functions_icons/reset_off.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/card_unlock.svg
|
||||
|
||||
@ -1021,8 +952,7 @@ class Assets {
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/motion.svg
|
||||
|
||||
static const String assetsMotion =
|
||||
"assets/icons/functions_icons/automation_functions/motion.svg";
|
||||
static const String assetsMotion = "assets/icons/functions_icons/automation_functions/motion.svg";
|
||||
|
||||
//assets/icons/functions_icons/automation_functions/current_temp.svg
|
||||
|
||||
@ -1044,19 +974,22 @@ class Assets {
|
||||
static const String waterHeaterOn = "assets/icons/water_heater_on.svg";
|
||||
static const String waterHeaterOff = "assets/icons/water_heater_off.svg";
|
||||
|
||||
static const String scheduleCelenderIcon =
|
||||
"assets/icons/schedule_celender_icon.svg";
|
||||
static const String scheduleCirculateIcon =
|
||||
"assets/icons/schedule_circulate_icon.svg";
|
||||
static const String scheduleInchingIcon =
|
||||
"assets/icons/schedule_Inching_icon.svg";
|
||||
static const String scheduleCelenderIcon = "assets/icons/schedule_celender_icon.svg";
|
||||
static const String scheduleCirculateIcon = "assets/icons/schedule_circulate_icon.svg";
|
||||
static const String scheduleInchingIcon = "assets/icons/schedule_Inching_icon.svg";
|
||||
static const String scheduleTimeIcon = "assets/icons/schedule_time_icon.svg";
|
||||
static const String waterHeaterIcon = "assets/icons/water_heater_icon.svg";
|
||||
|
||||
static const String doorOpen = "assets/icons/opened_door.svg";
|
||||
static const String doorClose = "assets/icons/closed_door.svg";
|
||||
static const String doorNotificationSetting =
|
||||
"assets/icons/door_notification_setting_icon.svg";
|
||||
static const String doorNotificationSetting = "assets/icons/door_notification_setting_icon.svg";
|
||||
static const String doorRecordsIcon = "assets/icons/door_records_icon.svg";
|
||||
static const String doorSensorIcon = "assets/icons/door_sensor_icon.svg";
|
||||
static const String closedGarageIcon = "assets/icons/closed_garage_door.svg";
|
||||
static const String openGarageIcon = "assets/icons/open_garage_door.svg";
|
||||
static const String garageCountdown = "assets/icons/garage_countdown.svg";
|
||||
static const String garagePreferencesIcon = "assets/icons/garage_preferences_icon.svg";
|
||||
static const String garageSchedule = "assets/icons/garage_schedule.svg";
|
||||
|
||||
static const String garageIcon = "assets/icons/garageIcon.svg";
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ void main() {
|
||||
// });
|
||||
|
||||
//to initialize the locator
|
||||
initialSetup(envName: 'prod');
|
||||
initialSetup();
|
||||
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptionsStaging.currentPlatform,
|
||||
|
||||
@ -30,7 +30,7 @@ void main() {
|
||||
// });
|
||||
|
||||
//to initialize the locator
|
||||
initialSetup(envName: 'dev');
|
||||
initialSetup();
|
||||
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptionsDev.currentPlatform,
|
||||
|
||||
@ -33,10 +33,11 @@ class DevicesAPI {
|
||||
static Future<Map<String, dynamic>> controlDevice(
|
||||
DeviceControlModel controlModel, String deviceId) async {
|
||||
try {
|
||||
print(controlModel.toJson());
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.controlDevice.replaceAll('{deviceUuid}', deviceId),
|
||||
body: controlModel.toJson(),
|
||||
showServerMessage: false,
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
@ -72,7 +73,8 @@ class DevicesAPI {
|
||||
|
||||
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId),
|
||||
path: ApiEndpoints.deviceFunctionsStatus
|
||||
.replaceAll('{deviceUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@ -82,7 +84,9 @@ class DevicesAPI {
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> renamePass(
|
||||
{required String name, required String doorLockUuid, required String passwordId}) async {
|
||||
{required String name,
|
||||
required String doorLockUuid,
|
||||
required String passwordId}) async {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.renamePassword
|
||||
.replaceAll('{doorLockUuid}', doorLockUuid)
|
||||
@ -107,7 +111,8 @@ class DevicesAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDeviceByGroupName(String unitId, String groupName) async {
|
||||
static Future<List<DeviceModel>> getDeviceByGroupName(
|
||||
String unitId, String groupName) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.devicesByGroupName
|
||||
.replaceAll('{unitUuid}', unitId)
|
||||
@ -146,7 +151,8 @@ class DevicesAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
|
||||
static Future<List<DeviceModel>> getDevicesByGatewayId(
|
||||
String gatewayId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
|
||||
showServerMessage: false,
|
||||
@ -168,7 +174,8 @@ class DevicesAPI {
|
||||
String deviceId,
|
||||
) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.getTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@ -179,7 +186,8 @@ class DevicesAPI {
|
||||
|
||||
static Future getOneTimePasswords(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.getOneTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@ -190,7 +198,8 @@ class DevicesAPI {
|
||||
|
||||
static Future getTimeLimitPasswords(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.getMultipleTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@ -215,10 +224,12 @@ class DevicesAPI {
|
||||
"invalidTime": invalidTime,
|
||||
};
|
||||
if (scheduleList != null) {
|
||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||
body["scheduleList"] =
|
||||
scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||
}
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.addTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
body: body,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json,
|
||||
@ -229,7 +240,8 @@ class DevicesAPI {
|
||||
static Future generateOneTimePassword({deviceId}) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.addOneTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@ -241,10 +253,12 @@ class DevicesAPI {
|
||||
}
|
||||
}
|
||||
|
||||
static Future generateMultiTimePassword({deviceId, effectiveTime, invalidTime}) async {
|
||||
static Future generateMultiTimePassword(
|
||||
{deviceId, effectiveTime, invalidTime}) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.addMultipleTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: true,
|
||||
body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
|
||||
expectedResponseModel: (json) {
|
||||
@ -371,11 +385,13 @@ class DevicesAPI {
|
||||
String? code,
|
||||
bool? value,
|
||||
}) async {
|
||||
print({"devicesUuid": devicesUuid, "code": code, "value": value});
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.controlBatch,
|
||||
body: {"devicesUuid": devicesUuid, "code": code, "value": value},
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('json===$json');
|
||||
return json;
|
||||
},
|
||||
);
|
||||
|
||||
@ -5,9 +5,8 @@ import 'package:syncrow_app/services/api/http_service.dart';
|
||||
|
||||
final GetIt serviceLocator = GetIt.instance;
|
||||
// setupLocator() // to search for dependency injection in flutter
|
||||
initialSetup({required String envName}) {
|
||||
initialSetup() {
|
||||
serviceLocator.registerSingleton<HTTPInterceptor>(HTTPInterceptor());
|
||||
//Base classes
|
||||
serviceLocator.registerSingleton<Dio>(HTTPService.setupDioClient());
|
||||
serviceLocator.registerSingleton<String>(envName);
|
||||
}
|
||||
|
||||
@ -5,7 +5,8 @@ abstract class ColorsManager {
|
||||
static const Color switchOffColor = Color(0x7F8D99AE);
|
||||
static const Color primaryColor = Color(0xFF0030CB);
|
||||
static const Color secondaryTextColor = Color(0xFF848484);
|
||||
static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6);
|
||||
static Color primaryColorWithOpacity =
|
||||
const Color(0xFF023DFE).withOpacity(0.6);
|
||||
static const Color onPrimaryColor = Colors.white;
|
||||
static const Color secondaryColor = Color(0xFF023DFE);
|
||||
static const Color onSecondaryColor = Color(0xFF023DFE);
|
||||
@ -27,4 +28,5 @@ abstract class ColorsManager {
|
||||
static const Color red = Colors.red;
|
||||
static const Color graysColor = Color(0xffEBEBEB);
|
||||
static const Color textGray = Color(0xffD5D5D5);
|
||||
static const Color switchButton = Color(0xff023DFE);
|
||||
}
|
||||
|
||||
@ -50,6 +50,11 @@ enum DeviceType {
|
||||
WallSensor,
|
||||
WH,
|
||||
DS,
|
||||
OneTouch,
|
||||
TowTouch,
|
||||
ThreeTouch,
|
||||
GarageDoor,
|
||||
|
||||
Other,
|
||||
}
|
||||
|
||||
@ -76,6 +81,10 @@ Map<String, DeviceType> devicesTypesMap = {
|
||||
"CUR": DeviceType.Curtain,
|
||||
"WH": DeviceType.WH,
|
||||
"DS": DeviceType.DS,
|
||||
"1GT": DeviceType.OneTouch,
|
||||
"2GT": DeviceType.TowTouch,
|
||||
"3GT": DeviceType.ThreeTouch,
|
||||
"GD": DeviceType.GarageDoor,
|
||||
};
|
||||
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
DeviceType.AC: [
|
||||
@ -284,13 +293,180 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
FunctionModel(
|
||||
code: 'doorcontact_state',
|
||||
type: functionTypesMap['Raw'],
|
||||
values: ValueModel.fromJson({})
|
||||
),
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'battery_percentage',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({})
|
||||
),
|
||||
values: ValueModel.fromJson({})),
|
||||
],
|
||||
DeviceType.OneTouch: [
|
||||
FunctionModel(
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'relay_status',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'light_mode',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['none', 'relay', 'pos']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'relay_status_1',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
],
|
||||
DeviceType.TowTouch: [
|
||||
FunctionModel(
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_2',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_2',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'relay_status',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'light_mode',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['none', 'relay', 'pos']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'relay_status_1',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'relay_status_2',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
],
|
||||
DeviceType.ThreeTouch: [
|
||||
FunctionModel(
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_2',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_3',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_2',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_3',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'relay_status',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'light_mode',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['none', 'relay', 'pos']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'relay_status_1',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'relay_status_2',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'relay_status_3',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['power_off', 'power_on', 'last']
|
||||
})),
|
||||
],
|
||||
DeviceType.GarageDoor: [
|
||||
FunctionModel(
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'tr_timecon',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 120, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_alarm',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'door_control_1',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ['open', 'open']
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'voice_control_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'door_state_1',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson({
|
||||
"range": ["unclosed_time", "close_time_alarm", "none"]
|
||||
})),
|
||||
],
|
||||
};
|
||||
|
||||
@ -589,3 +765,67 @@ List<Map<String, Object>> members = [
|
||||
'role': MemberRole.FamilyMember,
|
||||
},
|
||||
];
|
||||
|
||||
enum status {
|
||||
on,
|
||||
off,
|
||||
restart,
|
||||
}
|
||||
|
||||
extension StatusExtension on status {
|
||||
String get value {
|
||||
switch (this) {
|
||||
case status.off:
|
||||
return "Power Off";
|
||||
case status.on:
|
||||
return "Power On";
|
||||
case status.restart:
|
||||
return "Restart Memory";
|
||||
}
|
||||
}
|
||||
|
||||
static status fromString(String value) {
|
||||
switch (value) {
|
||||
case "power_off":
|
||||
return status.off;
|
||||
case "power_on":
|
||||
return status.on;
|
||||
case "last":
|
||||
return status.restart;
|
||||
default:
|
||||
throw ArgumentError("Invalid access type: $value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum lightStatus {
|
||||
off,
|
||||
on_off,
|
||||
switchPosition,
|
||||
}
|
||||
|
||||
extension lightStatusExtension on lightStatus {
|
||||
String get value {
|
||||
switch (this) {
|
||||
case lightStatus.off:
|
||||
return "Off";
|
||||
case lightStatus.switchPosition:
|
||||
return "On/Off Status";
|
||||
case lightStatus.on_off:
|
||||
return "Restart Memory";
|
||||
}
|
||||
}
|
||||
|
||||
static lightStatus fromString(String value) {
|
||||
switch (value) {
|
||||
case "none":
|
||||
return lightStatus.off;
|
||||
case "relay":
|
||||
return lightStatus.switchPosition;
|
||||
case "pos":
|
||||
return lightStatus.on_off;
|
||||
default:
|
||||
throw ArgumentError("Invalid access type: $value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ description: This is the mobile application project, developed with Flutter for
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
version: 1.0.3+22
|
||||
version: 1.0.3+25
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.6 <4.0.0"
|
||||
|
||||