melhorar o streak
This commit is contained in:
194
.idea/caches/deviceStreaming.xml
generated
194
.idea/caches/deviceStreaming.xml
generated
@@ -10,7 +10,7 @@
|
||||
<option name="id" value="A402SO" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Sony" />
|
||||
<option name="name" value="Xperia 10" />
|
||||
<option name="name" value="Xperia 10 VI" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2520" />
|
||||
@@ -34,7 +34,7 @@
|
||||
<option name="id" value="OP535DL1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OnePlus" />
|
||||
<option name="name" value="CPH2409" />
|
||||
<option name="name" value="Nord CE 2 Lite 5G" />
|
||||
<option name="screenDensity" value="401" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2412" />
|
||||
@@ -46,7 +46,7 @@
|
||||
<option name="id" value="OP5552L1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OnePlus" />
|
||||
<option name="name" value="CPH2415" />
|
||||
<option name="name" value="10T 5G" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2412" />
|
||||
@@ -58,7 +58,7 @@
|
||||
<option name="id" value="OP573DL1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OPPO" />
|
||||
<option name="name" value="CPH2557" />
|
||||
<option name="name" value="A79 5G" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -70,7 +70,7 @@
|
||||
<option name="id" value="OP5759L1" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="OPPO" />
|
||||
<option name="name" value="CPH2579" />
|
||||
<option name="name" value="A38" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1612" />
|
||||
@@ -94,7 +94,7 @@
|
||||
<option name="id" value="RMX3231" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="realme" />
|
||||
<option name="name" value="C11" />
|
||||
<option name="name" value="RMX3231" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
@@ -155,7 +155,7 @@
|
||||
<option name="id" value="a05s" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A05s" />
|
||||
<option name="name" value="Galaxy A05s" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -191,7 +191,7 @@
|
||||
<option name="id" value="a14m" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A145R" />
|
||||
<option name="name" value="Galaxy A14" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2408" />
|
||||
@@ -227,7 +227,7 @@
|
||||
<option name="id" value="a15" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A15" />
|
||||
<option name="name" value="Galaxy A15" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -239,7 +239,7 @@
|
||||
<option name="id" value="a15x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A15 5G" />
|
||||
<option name="name" value="Galaxy A15 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -251,7 +251,7 @@
|
||||
<option name="id" value="a15x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A15 5G" />
|
||||
<option name="name" value="Galaxy A15 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -275,7 +275,7 @@
|
||||
<option name="id" value="a16" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A165M" />
|
||||
<option name="name" value="Galaxy A16" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -287,7 +287,7 @@
|
||||
<option name="id" value="a16x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A16 5G" />
|
||||
<option name="name" value="Galaxy A16 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -299,7 +299,7 @@
|
||||
<option name="id" value="a16x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A16 5G" />
|
||||
<option name="name" value="Galaxy A16 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -311,7 +311,7 @@
|
||||
<option name="id" value="a16xeea" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A16 5G" />
|
||||
<option name="name" value="Galaxy A16 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -335,7 +335,7 @@
|
||||
<option name="id" value="a26x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A266B" />
|
||||
<option name="name" value="Galaxy A26 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -347,7 +347,7 @@
|
||||
<option name="id" value="a34x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A346N" />
|
||||
<option name="name" value="Galaxy A34 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -359,7 +359,7 @@
|
||||
<option name="id" value="a35x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A35" />
|
||||
<option name="name" value="Galaxy A35 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -371,7 +371,7 @@
|
||||
<option name="id" value="a35x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A35" />
|
||||
<option name="name" value="Galaxy A35 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -383,7 +383,7 @@
|
||||
<option name="id" value="a35x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A35" />
|
||||
<option name="name" value="Galaxy A35 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -395,7 +395,7 @@
|
||||
<option name="id" value="a36xq" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A366E" />
|
||||
<option name="name" value="Galaxy A36 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -407,7 +407,7 @@
|
||||
<option name="id" value="a36xq" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A366E" />
|
||||
<option name="name" value="Galaxy A36 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -419,7 +419,7 @@
|
||||
<option name="id" value="a56x" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-A566E" />
|
||||
<option name="name" value="Galaxy A56 5G" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -548,6 +548,7 @@
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="blazer" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="blazer" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -555,6 +556,11 @@
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2410" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="32" />
|
||||
@@ -632,7 +638,6 @@
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="comet" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="comet" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -640,17 +645,11 @@
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="2076" />
|
||||
<option name="screenY" value="2152" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="comet" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="comet" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -658,11 +657,6 @@
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="2076" />
|
||||
<option name="screenY" value="2152" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
@@ -671,7 +665,7 @@
|
||||
<option name="id" value="cuscoi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="edge 50 fusion" />
|
||||
<option name="name" value="moto g96 5G" />
|
||||
<option name="screenDensity" value="400" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -683,7 +677,7 @@
|
||||
<option name="id" value="dm1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S23" />
|
||||
<option name="name" value="Galaxy S23" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -695,7 +689,7 @@
|
||||
<option name="id" value="dm1q-SM-S911U" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S23" />
|
||||
<option name="name" value="Galaxy S23" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -719,7 +713,7 @@
|
||||
<option name="id" value="dm2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S23 Plus" />
|
||||
<option name="name" value="Galaxy S23+" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -752,7 +746,6 @@
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="e1q" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="e1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
@@ -760,17 +753,11 @@
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="e1q" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="e1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
@@ -778,11 +765,6 @@
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="36" />
|
||||
@@ -952,10 +934,23 @@
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="fogos" />
|
||||
<option name="id" value="fogos" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g34 5G" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="frankel" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="frankel" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -963,6 +958,11 @@
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
@@ -971,7 +971,7 @@
|
||||
<option name="id" value="g0q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S906U1" />
|
||||
<option name="name" value="Galaxy S22+" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -983,7 +983,7 @@
|
||||
<option name="id" value="g0q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S906U1" />
|
||||
<option name="name" value="Galaxy S22+" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -1007,7 +1007,7 @@
|
||||
<option name="id" value="gta9pwifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-X210" />
|
||||
<option name="name" value="Galaxy Tab A9+" />
|
||||
<option name="screenDensity" value="240" />
|
||||
<option name="screenX" value="1200" />
|
||||
<option name="screenY" value="1920" />
|
||||
@@ -1019,7 +1019,7 @@
|
||||
<option name="id" value="gts7lwifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-T870" />
|
||||
<option name="name" value="Galaxy Tab S7" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
@@ -1031,7 +1031,7 @@
|
||||
<option name="id" value="gts7xllite" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-T738U" />
|
||||
<option name="name" value="Galaxy Tab S7 FE 5G" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
@@ -1081,7 +1081,7 @@
|
||||
<option name="id" value="gts9wifi" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-X710" />
|
||||
<option name="name" value="Galaxy Tab S9" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
@@ -1093,7 +1093,7 @@
|
||||
<option name="id" value="guamna" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="Moto XT2093-3" />
|
||||
<option name="name" value="moto g play (2021)" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
@@ -1105,7 +1105,7 @@
|
||||
<option name="id" value="guamp" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="Moto XT2083-1" />
|
||||
<option name="name" value="moto g(9) play" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
@@ -1258,6 +1258,7 @@
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="mustang" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="mustang" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -1265,6 +1266,11 @@
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2404" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
@@ -1273,7 +1279,7 @@
|
||||
<option name="id" value="o1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21" />
|
||||
<option name="name" value="Galaxy S21 5G" />
|
||||
<option name="screenDensity" value="421" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -1285,7 +1291,7 @@
|
||||
<option name="id" value="o1q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21" />
|
||||
<option name="name" value="Galaxy S21 5G" />
|
||||
<option name="screenDensity" value="421" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -1309,7 +1315,7 @@
|
||||
<option name="id" value="p3q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21 Ultra" />
|
||||
<option name="name" value="Galaxy S21 Ultra 5G" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3200" />
|
||||
@@ -1333,7 +1339,7 @@
|
||||
<option name="id" value="pa2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S25+" />
|
||||
<option name="name" value="Galaxy S25+" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -1354,6 +1360,7 @@
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="pa3q" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="pa3q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
@@ -1361,11 +1368,17 @@
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="pa3q" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="pa3q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
@@ -1373,6 +1386,11 @@
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
@@ -1410,6 +1428,18 @@
|
||||
<option name="screenX" value="1812" />
|
||||
<option name="screenY" value="2176" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="q5qksx" />
|
||||
<option name="id" value="q5qksx" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Z Fold5" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1812" />
|
||||
<option name="screenY" value="2176" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
@@ -1441,7 +1471,7 @@
|
||||
<option name="id" value="r0qcsx" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S22" />
|
||||
<option name="name" value="Galaxy S22" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -1467,7 +1497,7 @@
|
||||
<option name="id" value="r11q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S711U" />
|
||||
<option name="name" value="Galaxy S23 FE" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -1479,7 +1509,7 @@
|
||||
<option name="id" value="r11s" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S711N" />
|
||||
<option name="name" value="Galaxy S23 FE" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
@@ -1536,6 +1566,7 @@
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="rango" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="rango" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -1543,6 +1574,11 @@
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="2076" />
|
||||
<option name="screenY" value="2152" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
@@ -1592,7 +1628,7 @@
|
||||
<option name="id" value="t2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21 Plus" />
|
||||
<option name="name" value="Galaxy S21+ 5G" />
|
||||
<option name="screenDensity" value="394" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -1604,7 +1640,7 @@
|
||||
<option name="id" value="t2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21 Plus" />
|
||||
<option name="name" value="Galaxy S21+ 5G" />
|
||||
<option name="screenDensity" value="394" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
@@ -1638,7 +1674,6 @@
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -1646,17 +1681,11 @@
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -1664,17 +1693,11 @@
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="36" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="default" value="true" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
@@ -1682,11 +1705,6 @@
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
<option name="tags">
|
||||
<list>
|
||||
<option value="dda-default" />
|
||||
</list>
|
||||
</option>
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
@@ -1695,7 +1713,7 @@
|
||||
<option name="id" value="xcover7" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-G556B" />
|
||||
<option name="name" value="Galaxy XCover7" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2408" />
|
||||
@@ -1707,7 +1725,7 @@
|
||||
<option name="id" value="y2q" />
|
||||
<option name="labId" value="google" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S20 Plus 5G" />
|
||||
<option name="name" value="Galaxy S20+ 5G" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3200" />
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.firebase.firestore.FirebaseFirestore;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
import com.google.firebase.firestore.QueryDocumentSnapshot;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
@@ -113,6 +114,15 @@ public class FirestoreManager {
|
||||
updateUserStats(uid, updates, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atualiza um campo específico do utilizador.
|
||||
*/
|
||||
public void updateUserField(String uid, String field, Object value) {
|
||||
java.util.Map<String, Object> updates = new java.util.HashMap<>();
|
||||
updates.put(field, value);
|
||||
updateUserStats(uid, updates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regista um log de XP.
|
||||
*/
|
||||
@@ -245,9 +255,9 @@ public class FirestoreManager {
|
||||
if (amount != null) {
|
||||
dp.xp += amount.intValue();
|
||||
}
|
||||
if ("focus_task".equals(type)) {
|
||||
if ("focus_task".equals(type) || "task_manual_completion".equals(type)) {
|
||||
dp.completedTasks++;
|
||||
dp.focusSessions++;
|
||||
if ("focus_task".equals(type)) dp.focusSessions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -264,4 +274,58 @@ public class FirestoreManager {
|
||||
callback.accept(new java.util.HashMap<>());
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Recalculates the streak based on completed days in xp_logs.
|
||||
*/
|
||||
public void recalculateStreakFromCompletedDays(String uid, int dailyGoal, Consumer<Integer> callback) {
|
||||
if (uid == null) {
|
||||
callback.accept(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// We'll query logs from the last 100 days to find the current consecutive streak
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DAY_OF_YEAR, -100);
|
||||
java.util.Date startDate = cal.getTime();
|
||||
java.util.Date endDate = new java.util.Date();
|
||||
|
||||
getDailyProgress(uid, startDate, endDate, dailyGoal, progressMap -> {
|
||||
List<String> sortedDates = new java.util.ArrayList<>(progressMap.keySet());
|
||||
java.util.Collections.sort(sortedDates, java.util.Collections.reverseOrder());
|
||||
|
||||
int streak = 0;
|
||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault());
|
||||
Calendar checkCal = Calendar.getInstance();
|
||||
|
||||
// Check today
|
||||
String todayStr = sdf.format(checkCal.getTime());
|
||||
DailyProgress todayDp = progressMap.get(todayStr);
|
||||
boolean isTodayComplete = todayDp != null && todayDp.completedTasks >= dailyGoal;
|
||||
|
||||
if (isTodayComplete) {
|
||||
streak = 1;
|
||||
} else {
|
||||
// If today is not complete, check if yesterday was complete to continue the streak
|
||||
checkCal.add(Calendar.DAY_OF_YEAR, -1);
|
||||
}
|
||||
|
||||
// Go backwards from yesterday or today
|
||||
while (true) {
|
||||
String dateStr = sdf.format(checkCal.getTime());
|
||||
DailyProgress dp = progressMap.get(dateStr);
|
||||
if (dp != null && dp.completedTasks >= dailyGoal) {
|
||||
if (!dateStr.equals(todayStr)) streak++;
|
||||
checkCal.add(Calendar.DAY_OF_YEAR, -1);
|
||||
} else {
|
||||
break; // Streak broken
|
||||
}
|
||||
}
|
||||
|
||||
// Update streak in DB
|
||||
final int finalStreak = streak;
|
||||
Map<String, Object> updates = new java.util.HashMap<>();
|
||||
updates.put("streak", finalStreak);
|
||||
updateUserStats(uid, updates, () -> callback.accept(finalStreak));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,14 +35,18 @@ import androidx.core.content.ContextCompat;
|
||||
|
||||
public class InicioFragment extends Fragment {
|
||||
|
||||
private TextView tvTimer, tvGreeting, tvMotivationalSubtitle;
|
||||
// Focus Mode
|
||||
private enum FocusState { NOT_STARTED, RUNNING, PAUSED }
|
||||
private FocusState currentFocusState = FocusState.NOT_STARTED;
|
||||
|
||||
private TextView tvTimer, tvGreeting, tvMotivationalSubtitle, tvFocusStatus, tvFocusTitle;
|
||||
private TextView tvTodayStreak, tvTodayXP, tvTodayTasksCount, tvNoTasksIncentive;
|
||||
private TextView tvDailyRewardGoal;
|
||||
private ProgressBar pbDailyTasksProgress;
|
||||
private androidx.recyclerview.widget.RecyclerView rvTasks;
|
||||
private TasksAdapter tasksAdapter;
|
||||
private LinearLayout miniRankingContainer, layoutTasksSection;
|
||||
private Button btnStartFocus, btnAddTasks, btnClaimReward;
|
||||
private Button btnStartFocus, btnSecondaryFocus, btnAddTasks, btnClaimReward;
|
||||
private androidx.cardview.widget.CardView btnStreakPage;
|
||||
|
||||
private CountDownTimer countDownTimer;
|
||||
@@ -111,20 +115,13 @@ public class InicioFragment extends Fragment {
|
||||
|
||||
// Focus Mode
|
||||
tvTimer = view.findViewById(R.id.tvTimer);
|
||||
tvFocusStatus = view.findViewById(R.id.tvFocusStatus);
|
||||
tvFocusTitle = view.findViewById(R.id.tvFocusTitle);
|
||||
btnStartFocus = view.findViewById(R.id.btnStartFocus);
|
||||
btnStartFocus.setOnClickListener(v -> {
|
||||
if (!isTimerRunning) {
|
||||
if (selectedTaskForFocus == null) {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Seleciona uma tarefa primeiro!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
startTimer();
|
||||
} else {
|
||||
pauseTimerWithWarning();
|
||||
}
|
||||
});
|
||||
btnSecondaryFocus = view.findViewById(R.id.btnSecondaryFocus);
|
||||
|
||||
btnStartFocus.setOnClickListener(v -> handleStartFocusClick());
|
||||
btnSecondaryFocus.setOnClickListener(v -> handleSecondaryFocusClick());
|
||||
|
||||
// Progress
|
||||
progressPathContainer = view.findViewById(R.id.progressPathContainer);
|
||||
@@ -186,7 +183,7 @@ public class InicioFragment extends Fragment {
|
||||
tvGreeting.setText("Olá, " + user.usuario + "!");
|
||||
}
|
||||
if (tvTodayStreak != null) {
|
||||
tvTodayStreak.setText(user.streak + " dias");
|
||||
syncDailyStreak(user);
|
||||
}
|
||||
refreshTodayStats(user);
|
||||
|
||||
@@ -280,8 +277,12 @@ public class InicioFragment extends Fragment {
|
||||
selectedTaskForFocus = task;
|
||||
timeLeftInMillis = task.duration * 60 * 1000;
|
||||
updateCountDownText();
|
||||
updateFocusUI(FocusState.NOT_STARTED);
|
||||
if (tvFocusTitle != null) {
|
||||
tvFocusTitle.setText(task.title);
|
||||
}
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), "Modo Foco: " + task.title, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), "Tarefa selecionada: " + task.title, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,11 +334,66 @@ public class InicioFragment extends Fragment {
|
||||
refreshTodayStats();
|
||||
}
|
||||
|
||||
private void syncDailyStreak(Usuario user) {
|
||||
if (user == null) return;
|
||||
|
||||
String today = new java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()).format(new java.util.Date());
|
||||
int completedTasksToday = user.tasks_concluidas_hoje;
|
||||
int dailyTaskGoal = user.meta_diaria_tarefas > 0 ? user.meta_diaria_tarefas : 3;
|
||||
int currentStreak = user.streak;
|
||||
String lastStreakDate = user.last_streak_completed_date;
|
||||
|
||||
boolean willIncrement = (completedTasksToday >= dailyTaskGoal) && !today.equals(lastStreakDate);
|
||||
int displayedStreak = 0;
|
||||
|
||||
if (completedTasksToday < dailyTaskGoal) {
|
||||
displayedStreak = 0;
|
||||
} else {
|
||||
if (willIncrement) {
|
||||
int newStreak = Math.max(currentStreak, 0) + 1;
|
||||
displayedStreak = newStreak;
|
||||
|
||||
// Salvar no backend
|
||||
Map<String, Object> updates = new HashMap<>();
|
||||
updates.put("streak", newStreak);
|
||||
updates.put("last_streak_completed_date", today);
|
||||
if (newStreak > user.melhor_streak) {
|
||||
updates.put("melhor_streak", newStreak);
|
||||
}
|
||||
FirestoreManager.getInstance().updateUserStats(user.id_usuario, updates);
|
||||
|
||||
// Atualizar objeto local para evitar loops ou UI atrasada
|
||||
user.streak = newStreak;
|
||||
user.last_streak_completed_date = today;
|
||||
} else {
|
||||
displayedStreak = currentStreak;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug Logs solicitados
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "--- syncDailyStreak ---");
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "completedTasksToday = " + completedTasksToday);
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "dailyTaskGoal = " + dailyTaskGoal);
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "currentStreak = " + currentStreak);
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "lastStreakDate = " + lastStreakDate);
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "today = " + today);
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "willIncrement = " + willIncrement);
|
||||
android.util.Log.d("FLUXUP_STREAK_DEBUG", "displayedStreak = " + displayedStreak);
|
||||
|
||||
if (tvTodayStreak != null) {
|
||||
tvTodayStreak.setText(displayedStreak + " dias");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTodayCard(Usuario user) {
|
||||
if (user == null) return;
|
||||
int completed = user.tasks_concluidas_hoje;
|
||||
int goal = user.meta_diaria_tarefas;
|
||||
if (goal <= 0) goal = 3; // Default fallback
|
||||
|
||||
// Sincronizar e mostrar streak
|
||||
syncDailyStreak(user);
|
||||
|
||||
if (tvTodayTasksCount != null) {
|
||||
tvTodayTasksCount.setText(completed + "/" + goal);
|
||||
}
|
||||
@@ -587,14 +643,12 @@ public class InicioFragment extends Fragment {
|
||||
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
||||
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
||||
|
||||
if (user.tasks_concluidas_hoje == 0) {
|
||||
updates.put("streak", com.google.firebase.firestore.FieldValue.increment(1));
|
||||
if (user.streak + 1 > user.melhor_streak) {
|
||||
updates.put("melhor_streak", user.streak + 1);
|
||||
}
|
||||
}
|
||||
// Adicionar log de XP mesmo em manual para permitir recálculo se necessário
|
||||
FirestoreManager.getInstance().addXpLog(uid, 0, "task_manual_completion");
|
||||
|
||||
FirestoreManager.getInstance().updateUserStats(uid, updates);
|
||||
FirestoreManager.getInstance().updateUserStats(uid, updates, () -> {
|
||||
if (isAdded()) refreshTodayStats();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -709,21 +763,126 @@ public class InicioFragment extends Fragment {
|
||||
}
|
||||
|
||||
|
||||
private void handleStartFocusClick() {
|
||||
if (currentFocusState == FocusState.NOT_STARTED) {
|
||||
if (selectedTaskForFocus == null) {
|
||||
if (getContext() != null) Toast.makeText(getContext(), "Seleciona uma tarefa primeiro!", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
startTimer();
|
||||
} else if (currentFocusState == FocusState.RUNNING) {
|
||||
pauseTimer();
|
||||
} else if (currentFocusState == FocusState.PAUSED) {
|
||||
startTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSecondaryFocusClick() {
|
||||
if (currentFocusState == FocusState.RUNNING) {
|
||||
showFinishEarlyWarning();
|
||||
} else if (currentFocusState == FocusState.PAUSED) {
|
||||
cancelTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFocusUI(FocusState state) {
|
||||
if (!isAdded()) return;
|
||||
currentFocusState = state;
|
||||
|
||||
if (selectedTaskForFocus == null) {
|
||||
tvFocusTitle.setText("Seleciona uma tarefa");
|
||||
tvFocusStatus.setText("Foca no teu objetivo");
|
||||
} else {
|
||||
tvFocusTitle.setText(selectedTaskForFocus.title);
|
||||
tvFocusStatus.setText("Sessão de foco");
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case NOT_STARTED:
|
||||
tvFocusStatus.setTextColor(ContextCompat.getColor(getContext(), R.color.text_secondary));
|
||||
btnStartFocus.setText("Começar Foco");
|
||||
btnSecondaryFocus.setVisibility(View.GONE);
|
||||
break;
|
||||
case RUNNING:
|
||||
tvFocusStatus.setText("• EM FOCO");
|
||||
tvFocusStatus.setTextColor(ContextCompat.getColor(getContext(), R.color.primary_purple));
|
||||
btnStartFocus.setText("Pausar");
|
||||
btnSecondaryFocus.setText("Concluir");
|
||||
btnSecondaryFocus.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case PAUSED:
|
||||
tvFocusStatus.setText("• PAUSADO");
|
||||
tvFocusStatus.setTextColor(android.graphics.Color.parseColor("#FFA000"));
|
||||
btnStartFocus.setText("Continuar");
|
||||
btnSecondaryFocus.setText("Cancelar");
|
||||
btnSecondaryFocus.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
if (selectedTaskForFocus == null) return;
|
||||
|
||||
if (countDownTimer != null) countDownTimer.cancel();
|
||||
|
||||
countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
timeLeftInMillis = millisUntilFinished;
|
||||
updateCountDownText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
handleFocusComplete();
|
||||
}
|
||||
}.start();
|
||||
|
||||
isTimerRunning = true;
|
||||
btnStartFocus.setText("Pausar Foco");
|
||||
updateFocusUI(FocusState.RUNNING);
|
||||
}
|
||||
|
||||
private void pauseTimer() {
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
isTimerRunning = false;
|
||||
updateFocusUI(FocusState.PAUSED);
|
||||
}
|
||||
|
||||
private void cancelTimer() {
|
||||
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
||||
.setTitle("Cancelar Foco")
|
||||
.setMessage("Tens a certeza que queres cancelar? Não ganharás XP.")
|
||||
.setNegativeButton("Não", null)
|
||||
.setPositiveButton("Sim, cancelar", (dialog, which) -> {
|
||||
if (countDownTimer != null) countDownTimer.cancel();
|
||||
isTimerRunning = false;
|
||||
selectedTaskForFocus = null;
|
||||
timeLeftInMillis = 25 * 60 * 1000;
|
||||
updateCountDownText();
|
||||
updateFocusUI(FocusState.NOT_STARTED);
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showFinishEarlyWarning() {
|
||||
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
||||
.setTitle("Concluir cedo?")
|
||||
.setMessage("Ainda não terminaste o tempo. Se concluíres agora, não ganharás o bónus de XP.")
|
||||
.setNegativeButton("Continuar Foco", null)
|
||||
.setPositiveButton("Concluir sem bónus", (dialog, which) -> {
|
||||
// Similar to cancel but maybe we still mark task as done?
|
||||
// User said "concluir → só dá XP se terminar o tempo".
|
||||
// I'll just reset for now as per "XP: sessão cancelada → 0 XP"
|
||||
if (countDownTimer != null) countDownTimer.cancel();
|
||||
isTimerRunning = false;
|
||||
selectedTaskForFocus = null;
|
||||
timeLeftInMillis = 25 * 60 * 1000;
|
||||
updateCountDownText();
|
||||
updateFocusUI(FocusState.NOT_STARTED);
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void handleFocusComplete() {
|
||||
@@ -738,14 +897,15 @@ public class InicioFragment extends Fragment {
|
||||
android.util.Log.d("FLUXUP_DEBUG", "TIMER_CANCELLED");
|
||||
}
|
||||
|
||||
isTimerRunning = false;
|
||||
if (btnStartFocus != null) btnStartFocus.setText("Começar Foco");
|
||||
|
||||
if (selectedTaskForFocus == null) {
|
||||
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: selectedTask null");
|
||||
isCompletingFocus = false;
|
||||
return;
|
||||
}
|
||||
|
||||
isTimerRunning = false;
|
||||
updateFocusUI(FocusState.NOT_STARTED);
|
||||
|
||||
android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + selectedTaskForFocus.id);
|
||||
|
||||
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser();
|
||||
@@ -790,13 +950,6 @@ public class InicioFragment extends Fragment {
|
||||
updates.put("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
|
||||
updates.put("total_tasks_concluidas", com.google.firebase.firestore.FieldValue.increment(1));
|
||||
|
||||
if (user.tasks_concluidas_hoje == 0) {
|
||||
updates.put("streak", com.google.firebase.firestore.FieldValue.increment(1));
|
||||
if (user.streak + 1 > user.melhor_streak) {
|
||||
updates.put("melhor_streak", user.streak + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int currentLevel = user.level;
|
||||
int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
|
||||
if (user.xp + 50 >= threshold) {
|
||||
@@ -816,6 +969,7 @@ public class InicioFragment extends Fragment {
|
||||
selectedTaskForFocus = null;
|
||||
timeLeftInMillis = 25 * 60 * 1000;
|
||||
updateCountDownText();
|
||||
updateFocusUI(FocusState.NOT_STARTED);
|
||||
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_SUCCESS");
|
||||
}
|
||||
isCompletingFocus = false;
|
||||
@@ -833,21 +987,6 @@ public class InicioFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private void pauseTimerWithWarning() {
|
||||
new com.google.android.material.dialog.MaterialAlertDialogBuilder(getContext())
|
||||
.setTitle("Sair do Foco?")
|
||||
.setMessage("Se saíres agora, não ganharás o XP de foco.")
|
||||
.setNegativeButton("Continuar Focado", null)
|
||||
.setPositiveButton("Sair", (dialog, which) -> {
|
||||
if (countDownTimer != null) countDownTimer.cancel();
|
||||
isTimerRunning = false;
|
||||
btnStartFocus.setText("Começar Foco");
|
||||
timeLeftInMillis = 25 * 60 * 1000;
|
||||
updateCountDownText();
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
private void updateCountDownText() {
|
||||
int minutes = (int) (timeLeftInMillis / 1000) / 60;
|
||||
|
||||
@@ -14,19 +14,25 @@ import android.widget.ProgressBar;
|
||||
import java.util.Calendar;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
import android.graphics.Color;
|
||||
|
||||
public class TrophiesActivity extends AppCompatActivity {
|
||||
|
||||
private TextView tvLeagueName, tvLeagueTimeRemaining, tvLeagueObjective;
|
||||
private TextView tvUserRankingStatus, tvXPToNextPosition, tvPastPerformance;
|
||||
private ProgressBar pbWeeklyProgress;
|
||||
private LinearLayout rankingContainer;
|
||||
private ImageButton btnBack;
|
||||
private TextView tvHeaderTimeLeft, tvHeaderXP;
|
||||
private ImageView ivHeaderLeagueIcon;
|
||||
private ProgressBar pbHeaderProgress;
|
||||
|
||||
private TextView tvUserName, tvUserDivision;
|
||||
private ProgressBar pbUserBottom;
|
||||
private LinearLayout divisionsContainer, rankingContainer;
|
||||
private ImageButton btnBack, btnHelp;
|
||||
private Button btnEarnXpNow;
|
||||
private com.google.android.material.tabs.TabLayout tabLayout;
|
||||
private View tabDivisoes, tabRanking;
|
||||
|
||||
private FirestoreManager firestoreManager;
|
||||
private FirebaseAuth mAuth;
|
||||
private ListenerRegistration rankingListener, userListener;
|
||||
private ListenerRegistration userListener, rankingListener;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -39,63 +45,171 @@ public class TrophiesActivity extends AppCompatActivity {
|
||||
initViews();
|
||||
setupListeners();
|
||||
observeUserData();
|
||||
observeRanking("global");
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
tvLeagueName = findViewById(R.id.tvLeagueName);
|
||||
tvLeagueTimeRemaining = findViewById(R.id.tvLeagueTimeRemaining);
|
||||
tvLeagueObjective = findViewById(R.id.tvLeagueObjective);
|
||||
tvUserRankingStatus = findViewById(R.id.tvUserRankingStatus);
|
||||
tvXPToNextPosition = findViewById(R.id.tvXPToNextPosition);
|
||||
tvPastPerformance = findViewById(R.id.tvPastPerformance);
|
||||
pbWeeklyProgress = findViewById(R.id.pbWeeklyProgress);
|
||||
ivHeaderLeagueIcon = findViewById(R.id.ivHeaderLeagueIcon);
|
||||
tvHeaderTimeLeft = findViewById(R.id.tvHeaderTimeLeft);
|
||||
tvHeaderXP = findViewById(R.id.tvHeaderXP);
|
||||
pbHeaderProgress = findViewById(R.id.pbHeaderProgress);
|
||||
|
||||
tvUserName = findViewById(R.id.tvUserName);
|
||||
tvUserDivision = findViewById(R.id.tvUserDivision);
|
||||
pbUserBottom = findViewById(R.id.pbUserBottom);
|
||||
|
||||
divisionsContainer = findViewById(R.id.divisionsContainer);
|
||||
rankingContainer = findViewById(R.id.rankingContainer);
|
||||
btnBack = findViewById(R.id.btnBack);
|
||||
btnHelp = findViewById(R.id.btnHelp);
|
||||
btnEarnXpNow = findViewById(R.id.btnEarnXpNow);
|
||||
|
||||
tabLayout = findViewById(R.id.tabLayout);
|
||||
tabDivisoes = findViewById(R.id.tabDivisoes);
|
||||
tabRanking = findViewById(R.id.tabRanking);
|
||||
|
||||
updateTimeRemaining();
|
||||
}
|
||||
|
||||
private void setupListeners() {
|
||||
btnBack.setOnClickListener(v -> finish());
|
||||
btnEarnXpNow.setOnClickListener(v -> finish()); // Go back to Home
|
||||
btnHelp.setOnClickListener(v -> {
|
||||
// Show help dialog or info
|
||||
});
|
||||
btnEarnXpNow.setOnClickListener(v -> finish());
|
||||
|
||||
findViewById(R.id.btnRankingGlobal).setOnClickListener(v -> observeRanking("global"));
|
||||
findViewById(R.id.btnRankingAmigos).setOnClickListener(v -> observeRanking("friends"));
|
||||
tabLayout.addOnTabSelectedListener(new com.google.android.material.tabs.TabLayout.OnTabSelectedListener() {
|
||||
@Override
|
||||
public void onTabSelected(com.google.android.material.tabs.TabLayout.Tab tab) {
|
||||
int position = tab.getPosition();
|
||||
if (position == 0) {
|
||||
tabDivisoes.setVisibility(View.VISIBLE);
|
||||
tabRanking.setVisibility(View.GONE);
|
||||
} else if (position == 1) {
|
||||
tabDivisoes.setVisibility(View.GONE);
|
||||
tabRanking.setVisibility(View.VISIBLE);
|
||||
observeRanking("friends");
|
||||
} else if (position == 2) {
|
||||
tabDivisoes.setVisibility(View.GONE);
|
||||
tabRanking.setVisibility(View.VISIBLE);
|
||||
observeRanking("global");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onTabUnselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
|
||||
@Override
|
||||
public void onTabReselected(com.google.android.material.tabs.TabLayout.Tab tab) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateTimeRemaining() {
|
||||
// Simple logic for week end (Sunday 23:59)
|
||||
Calendar now = Calendar.getInstance();
|
||||
int daysLeft = Calendar.SUNDAY - now.get(Calendar.DAY_OF_WEEK);
|
||||
if (daysLeft < 0) daysLeft += 7;
|
||||
int hoursLeft = 23 - now.get(Calendar.HOUR_OF_DAY);
|
||||
tvLeagueTimeRemaining.setText(daysLeft + " dias " + hoursLeft + "h restantes");
|
||||
|
||||
int progress = (7 - daysLeft) * 100 / 7;
|
||||
animateProgressBar(progress);
|
||||
tvHeaderTimeLeft.setText("Termina em " + daysLeft + " dias");
|
||||
}
|
||||
|
||||
private void observeUserData() {
|
||||
String uid = mAuth.getUid();
|
||||
if (uid != null) {
|
||||
userListener = firestoreManager.observeUser(uid, this::updateUserUI);
|
||||
userListener = firestoreManager.observeUser(uid, user -> {
|
||||
if (user != null) {
|
||||
updateUI(user);
|
||||
populateDivisionsPath(user.xp);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUserUI(Usuario user) {
|
||||
if (user == null) return;
|
||||
tvLeagueName.setText("Divisão " + user.league);
|
||||
tvLeagueObjective.setText("Fica no TOP 3 para subir para " + getNextLeague(user.league));
|
||||
private void updateUI(Usuario user) {
|
||||
LeagueHelper.LeagueInfo current = LeagueHelper.getCurrentLeague(user.xp);
|
||||
LeagueHelper.LeagueInfo next = LeagueHelper.getNextLeague(user.xp);
|
||||
|
||||
// Header
|
||||
ivHeaderLeagueIcon.setImageResource(current.iconRes);
|
||||
if (next != null) {
|
||||
int progress = (user.xp - current.minXp) * 100 / (next.minXp - current.minXp);
|
||||
pbHeaderProgress.setProgress(progress);
|
||||
tvHeaderXP.setText(user.xp + " / " + next.minXp + " XP");
|
||||
} else {
|
||||
pbHeaderProgress.setProgress(100);
|
||||
tvHeaderXP.setText(user.xp + " XP (Lenda)");
|
||||
}
|
||||
|
||||
private String getNextLeague(String current) {
|
||||
switch (current) {
|
||||
case "Bronze": return "Prata";
|
||||
case "Prata": return "Ouro";
|
||||
case "Ouro": return "Platina";
|
||||
default: return "Diamante";
|
||||
// Bottom Card
|
||||
tvUserName.setText(user.usuario);
|
||||
tvUserDivision.setText(current.name + " • " + user.xp + " XP");
|
||||
if (next != null) {
|
||||
int bottomProgress = (user.xp - current.minXp) * 100 / (next.minXp - current.minXp);
|
||||
pbUserBottom.setProgress(bottomProgress);
|
||||
} else {
|
||||
pbUserBottom.setProgress(100);
|
||||
}
|
||||
|
||||
// Update user league in Firestore if it changed
|
||||
if (!current.name.equals(user.league)) {
|
||||
firestoreManager.updateUserField(user.id_usuario, "league", current.name);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateDivisionsPath(int totalXp) {
|
||||
divisionsContainer.removeAllViews();
|
||||
LeagueHelper.LeagueInfo current = LeagueHelper.getCurrentLeague(totalXp);
|
||||
|
||||
for (LeagueHelper.LeagueInfo league : LeagueHelper.LEAGUES) {
|
||||
View view = getLayoutInflater().inflate(R.layout.item_division_card, divisionsContainer, false);
|
||||
|
||||
TextView tvStatus = view.findViewById(R.id.tvDivisionStatus);
|
||||
ImageView ivIcon = view.findViewById(R.id.ivDivisionIcon);
|
||||
TextView tvName = view.findViewById(R.id.tvDivisionName);
|
||||
TextView tvXP = view.findViewById(R.id.tvDivisionXP);
|
||||
TextView tvProgressText = view.findViewById(R.id.tvDivisionProgressText);
|
||||
TextView tvPercentage = view.findViewById(R.id.tvDivisionPercentage);
|
||||
TextView tvRewards = view.findViewById(R.id.tvRewardsList);
|
||||
LinearLayout llBg = view.findViewById(R.id.llDivisionBg);
|
||||
com.google.android.material.card.MaterialCardView card = view.findViewById(R.id.cardDivision);
|
||||
|
||||
ivIcon.setImageResource(league.iconRes);
|
||||
tvName.setText(league.name);
|
||||
tvXP.setText(league.minXp + (league.maxXp < 100000 ? " - " + league.maxXp : "+") + " XP");
|
||||
tvRewards.setText(league.rewards);
|
||||
|
||||
if (league.name.equals(current.name)) {
|
||||
// Current League
|
||||
tvStatus.setVisibility(View.VISIBLE);
|
||||
tvStatus.setText("Liga Atual");
|
||||
tvProgressText.setVisibility(View.VISIBLE);
|
||||
tvPercentage.setVisibility(View.VISIBLE);
|
||||
|
||||
LeagueHelper.LeagueInfo next = LeagueHelper.getNextLeague(totalXp);
|
||||
if (next != null) {
|
||||
int needed = next.minXp - totalXp;
|
||||
tvProgressText.setText("Faltam " + needed + " XP para " + next.name);
|
||||
int perc = (totalXp - league.minXp) * 100 / (next.minXp - league.minXp);
|
||||
tvPercentage.setText(perc + "% até à próxima divisão");
|
||||
} else {
|
||||
tvProgressText.setText("Nível máximo atingido! 🔥");
|
||||
tvPercentage.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
card.setCardElevation(8f);
|
||||
card.setStrokeWidth(4);
|
||||
card.setStrokeColor(Color.parseColor(league.colorHex));
|
||||
llBg.setBackgroundColor(Color.parseColor("#15" + league.colorHex.substring(1))); // ~8% opacity
|
||||
} else if (totalXp > league.maxXp) {
|
||||
// Completed
|
||||
tvStatus.setVisibility(View.VISIBLE);
|
||||
tvStatus.setText("Concluída ✅");
|
||||
tvStatus.setTextColor(Color.GRAY);
|
||||
card.setAlpha(0.6f);
|
||||
} else {
|
||||
// Locked
|
||||
tvStatus.setVisibility(View.VISIBLE);
|
||||
tvStatus.setText("Bloqueada 🔒");
|
||||
tvStatus.setTextColor(Color.GRAY);
|
||||
card.setAlpha(0.4f);
|
||||
}
|
||||
|
||||
divisionsContainer.addView(view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,110 +227,38 @@ public class TrophiesActivity extends AppCompatActivity {
|
||||
|
||||
int position = 1;
|
||||
String myUid = mAuth.getUid();
|
||||
Usuario me = null;
|
||||
Usuario next = null;
|
||||
int myPos = -1;
|
||||
|
||||
for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots.getDocuments()) {
|
||||
Usuario user = doc.toObject(Usuario.class);
|
||||
if (user == null) continue;
|
||||
|
||||
if (user.id_usuario.equals(myUid)) {
|
||||
me = user;
|
||||
myPos = position;
|
||||
} else if (me == null) {
|
||||
next = user; // The one above me
|
||||
}
|
||||
|
||||
addRankingItem(position++, user, myUid);
|
||||
|
||||
// Add zone separators
|
||||
if (position == 4) addZoneSeparator("🟢 ZONA DE PROMOÇÃO", R.color.success_green);
|
||||
if (position == 11) addZoneSeparator("⚪ ZONA DE MANUTENÇÃO", R.color.text_secondary);
|
||||
if (position == 16) addZoneSeparator("🔴 ZONA DE DESPROMOÇÃO", R.color.error_red);
|
||||
}
|
||||
|
||||
if (me != null) {
|
||||
updateUserProgressCard(myPos, me, next);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void animateProgressBar(int progress) {
|
||||
android.animation.ObjectAnimator animation = android.animation.ObjectAnimator.ofInt(pbWeeklyProgress, "progress", 0, progress);
|
||||
animation.setDuration(1500);
|
||||
animation.setInterpolator(new android.view.animation.DecelerateInterpolator());
|
||||
animation.start();
|
||||
}
|
||||
|
||||
private void addRankingItem(int pos, Usuario user, String myUid) {
|
||||
View view = getLayoutInflater().inflate(R.layout.item_ranking_user, rankingContainer, false);
|
||||
|
||||
TextView tvPos = view.findViewById(R.id.tvRankPosition);
|
||||
TextView tvName = view.findViewById(R.id.tvRankingName);
|
||||
TextView tvXP = view.findViewById(R.id.tvRankingXP);
|
||||
TextView tvTu = view.findViewById(R.id.tvRankingLabelTu);
|
||||
ImageView ivAvatar = view.findViewById(R.id.ivRankingAvatar);
|
||||
androidx.cardview.widget.CardView card = view.findViewById(R.id.cardRankingUser);
|
||||
|
||||
if (pos == 1) {
|
||||
tvPos.setText("🥇");
|
||||
tvPos.setTextSize(18f);
|
||||
card.setCardBackgroundColor(android.graphics.Color.parseColor("#FFFDE7")); // Light gold
|
||||
} else if (pos == 2) {
|
||||
tvPos.setText("🥈");
|
||||
tvPos.setTextSize(18f);
|
||||
} else if (pos == 3) {
|
||||
tvPos.setText("🥉");
|
||||
tvPos.setTextSize(18f);
|
||||
} else {
|
||||
tvPos.setText("#" + pos);
|
||||
}
|
||||
|
||||
tvName.setText(user.usuario);
|
||||
tvXP.setText(user.xp_semanal + " XP");
|
||||
|
||||
if (user.id_usuario.equals(myUid)) {
|
||||
tvTu.setVisibility(View.VISIBLE);
|
||||
card.setCardBackgroundColor(android.graphics.Color.parseColor("#F3E5F5")); // Light purple
|
||||
card.setCardElevation(4f);
|
||||
card.setCardBackgroundColor(Color.parseColor("#F3E5F5"));
|
||||
}
|
||||
|
||||
rankingContainer.addView(view);
|
||||
}
|
||||
|
||||
private void addZoneSeparator(String text, int colorRes) {
|
||||
TextView tv = new TextView(this);
|
||||
tv.setText(text);
|
||||
tv.setTextSize(10);
|
||||
tv.setPadding(0, 24, 0, 8);
|
||||
tv.setTextColor(getResources().getColor(colorRes));
|
||||
tv.setGravity(android.view.Gravity.CENTER);
|
||||
tv.setAlpha(0.7f);
|
||||
rankingContainer.addView(tv);
|
||||
}
|
||||
|
||||
private void updateUserProgressCard(int myPos, Usuario me, Usuario aboveMe) {
|
||||
androidx.cardview.widget.CardView cardUserProgress = findViewById(R.id.cardUserProgress);
|
||||
|
||||
if (myPos <= 3) {
|
||||
tvUserRankingStatus.setText("🎉 Estás na zona de promoção!");
|
||||
tvUserRankingStatus.setTextColor(getResources().getColor(R.color.success_green));
|
||||
tvXPToNextPosition.setText("Mantém o foco para subir de divisão e ganhar recompensas!");
|
||||
cardUserProgress.setCardBackgroundColor(android.graphics.Color.parseColor("#E8F5E9")); // Light green
|
||||
} else {
|
||||
int needed = (aboveMe != null) ? (aboveMe.xp_semanal - me.xp_semanal + 1) : 0;
|
||||
tvUserRankingStatus.setText("Faltam " + needed + " XP para subires de posição");
|
||||
tvUserRankingStatus.setTextColor(getResources().getColor(R.color.text_primary));
|
||||
tvXPToNextPosition.setText("Estás em #" + myPos + " com " + me.xp_semanal + " XP");
|
||||
cardUserProgress.setCardBackgroundColor(getResources().getColor(R.color.white));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (rankingListener != null) rankingListener.remove();
|
||||
if (userListener != null) userListener.remove();
|
||||
if (rankingListener != null) rankingListener.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public class Usuario {
|
||||
public int sessoes_foco_completas = 0;
|
||||
public int dias_ativos = 1;
|
||||
public String last_active_date = ""; // YYYY-MM-DD
|
||||
public String last_streak_completed_date = ""; // YYYY-MM-DD
|
||||
public String last_reward_claim_date = ""; // YYYY-MM-DD
|
||||
public String avatar_url = "";
|
||||
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background_light">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/card_background"
|
||||
app:elevation="0dp">
|
||||
|
||||
<RelativeLayout
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
app:contentInsetStart="0dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<ImageButton
|
||||
@@ -26,7 +33,6 @@
|
||||
app:tint="@color/text_primary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvToolbarTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
@@ -34,97 +40,20 @@
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnHelp"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@android:drawable/ic_menu_help"
|
||||
app:tint="@color/text_primary" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- 1. 🥇 HEADER DA LIGA -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardCornerRadius="20dp"
|
||||
app:cardBackgroundColor="@color/primary_purple"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivLeagueBadge"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@drawable/ic_trophy_bronze"
|
||||
android:layout_marginBottom="12dp"
|
||||
app:tint="@color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeagueName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Divisão Bronze"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="26sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLeagueTimeRemaining"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="2 dias 14h restantes"
|
||||
android:textColor="#E0E0E0"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbWeeklyProgress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="12dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:max="100"
|
||||
android:progress="60"
|
||||
android:progressTint="@color/reward_yellow"
|
||||
android:progressBackgroundTint="#4DFFFFFF" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 2. 🎯 OBJETIVO DA LIGA -->
|
||||
<TextView
|
||||
android:id="@+id/tvLeagueObjective"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="🚀 Fica no TOP 3 para subir para Prata"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/primary_purple"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginBottom="24dp"/>
|
||||
|
||||
<!-- 5. ⚡ PROGRESSO DO UTILIZADOR -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardUserProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/white">
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<!-- Gamified Header Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -132,174 +61,214 @@
|
||||
android:padding="20dp"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivHeaderLeagueIcon"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@drawable/ic_trophy_bronze"
|
||||
android:layout_marginBottom="12dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUserRankingStatus"
|
||||
android:id="@+id/tvHeaderTimeLeft"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Faltam 120 XP para entrares no TOP 3"
|
||||
android:text="Termina em 3 dias"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbHeaderProgress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="12dp"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:progressTint="@color/primary_purple"
|
||||
android:progressBackgroundTint="#E0E0E0" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvHeaderXP"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="6415 / 10000 XP"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textStyle="bold"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp"/>
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvXPToNextPosition"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Diferença para o próximo: 45 XP"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textAlignment="center"
|
||||
android:textSize="14sp"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 8. 👥 FILTRO DE RANKING -->
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/toggleRankingFilter"
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorColor="@color/primary_purple"
|
||||
app:tabSelectedTextColor="@color/primary_purple"
|
||||
app:tabTextColor="@color/text_secondary">
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true"
|
||||
app:checkedButton="@+id/btnRankingGlobal">
|
||||
android:text="Divisões" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnRankingGlobal"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="50dp"
|
||||
android:text="Global"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp"/>
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Amigos" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnRankingAmigos"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="50dp"
|
||||
android:text="Amigos"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14sp"/>
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Ranking" />
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/appBar"
|
||||
android:layout_above="@id/bottomWrapper">
|
||||
|
||||
<!-- DIVISÕES TAB -->
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/tabDivisoes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/divisionsContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<!-- RANKING / AMIGOS TAB -->
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/tabRanking"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:clipToPadding="false"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 3. 📊 RANKING DA SEMANA -->
|
||||
<LinearLayout
|
||||
android:id="@+id/rankingContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="32dp"/>
|
||||
android:orientation="vertical" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomWrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/card_background"
|
||||
android:elevation="12dp">
|
||||
|
||||
<!-- Fixed User Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardUserProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="0dp"
|
||||
app:cardBackgroundColor="@color/card_background">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cvAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
app:cardCornerRadius="24dp"
|
||||
app:cardElevation="0dp">
|
||||
<ImageView
|
||||
android:id="@+id/ivUserAvatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_nav_profile" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/cvAvatar"
|
||||
android:layout_toStartOf="@id/ivUserExpand"
|
||||
android:layout_marginStart="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 6. 🎁 RECOMPENSAS DA SEMANA -->
|
||||
<TextView
|
||||
android:id="@+id/tvUserName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recompensas da semana"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:text="Utilizador"
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="3"
|
||||
android:layout_marginBottom="32dp">
|
||||
|
||||
<!-- 1º Lugar -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="4dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardBackgroundColor="#FFF8E1"
|
||||
app:cardElevation="1dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:gravity="center">
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="🥇" android:textSize="32sp" android:layout_marginBottom="8dp"/>
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1º Lugar" android:textStyle="bold" android:textSize="14sp" android:textColor="#FF8F00"/>
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+300 XP\nBadge" android:textAlignment="center" android:textSize="12sp" android:textColor="#FF8F00"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 2º Lugar -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardBackgroundColor="#F5F5F5"
|
||||
app:cardElevation="1dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:gravity="center">
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="🥈" android:textSize="28sp" android:layout_marginBottom="8dp"/>
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2º Lugar" android:textStyle="bold" android:textSize="14sp" android:textColor="#757575"/>
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+200 XP" android:textAlignment="center" android:textSize="12sp" android:textColor="#757575"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 3º Lugar -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="4dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardBackgroundColor="#EFEBE9"
|
||||
app:cardElevation="1dp">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:gravity="center">
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="🥉" android:textSize="28sp" android:layout_marginBottom="8dp"/>
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="3º Lugar" android:textStyle="bold" android:textSize="14sp" android:textColor="#8D6E63"/>
|
||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+100 XP" android:textAlignment="center" android:textSize="12sp" android:textColor="#8D6E63"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 7. 📈 HISTÓRICO DE PERFORMANCE -->
|
||||
<TextView
|
||||
android:id="@+id/tvPastPerformance"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/tvUserDivision"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Semana passada: 2º lugar (subiste)"
|
||||
android:textAlignment="center"
|
||||
android:text="Bronze • 0 XP"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:visibility="gone" />
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbUserBottom"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:progressTint="@color/primary_purple"
|
||||
android:progressBackgroundTint="#E0E0E0" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivUserExpand"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/ic_arrow_right"
|
||||
app:tint="@color/text_secondary" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 9. 🔘 BOTÃO DE ACÇÃO -->
|
||||
<Button
|
||||
android:id="@+id/btnEarnXpNow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:text="⚡ Ganhar XP Agora"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="Ganhar XP agora"
|
||||
android:backgroundTint="@color/primary_purple"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18sp"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textAllCaps="false"
|
||||
app:cornerRadius="16dp"
|
||||
android:layout_marginBottom="40dp"/>
|
||||
app:cornerRadius="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -239,14 +239,25 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvFocusTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="Modo Foco"
|
||||
android:text="Seleciona uma tarefa"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="22sp"
|
||||
android:textAlignment="center"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvFocusStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="Sessão de foco"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:visibility="visible" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/timerBlock"
|
||||
android:layout_width="200dp"
|
||||
@@ -281,10 +292,33 @@
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSecondaryFocus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/button_secondary"
|
||||
android:text="Cancelar"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@null" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnStartFocus"
|
||||
android:layout_width="200dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/button_primary"
|
||||
android:text="Começar Foco"
|
||||
android:textAllCaps="false"
|
||||
@@ -293,6 +327,7 @@
|
||||
android:textStyle="bold"
|
||||
app:backgroundTint="@null" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 5. 📊 PROGRESSO DIÁRIO -->
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.dependency.useConstraints=true
|
||||
android.r8.strictFullModeForKeepRules=false
|
||||
|
||||
Reference in New Issue
Block a user