melhorar o streak

This commit is contained in:
MeuNome
2026-05-05 17:14:37 +01:00
parent 84dbdac0f2
commit 2c7d1a854f
8 changed files with 792 additions and 523 deletions

View File

@@ -10,7 +10,7 @@
<option name="id" value="A402SO" /> <option name="id" value="A402SO" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Sony" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2520" /> <option name="screenY" value="2520" />
@@ -34,7 +34,7 @@
<option name="id" value="OP535DL1" /> <option name="id" value="OP535DL1" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="OnePlus" /> <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="screenDensity" value="401" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2412" /> <option name="screenY" value="2412" />
@@ -46,7 +46,7 @@
<option name="id" value="OP5552L1" /> <option name="id" value="OP5552L1" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="OnePlus" /> <option name="manufacturer" value="OnePlus" />
<option name="name" value="CPH2415" /> <option name="name" value="10T 5G" />
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2412" /> <option name="screenY" value="2412" />
@@ -58,7 +58,7 @@
<option name="id" value="OP573DL1" /> <option name="id" value="OP573DL1" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="OPPO" /> <option name="manufacturer" value="OPPO" />
<option name="name" value="CPH2557" /> <option name="name" value="A79 5G" />
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -70,7 +70,7 @@
<option name="id" value="OP5759L1" /> <option name="id" value="OP5759L1" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="OPPO" /> <option name="manufacturer" value="OPPO" />
<option name="name" value="CPH2579" /> <option name="name" value="A38" />
<option name="screenDensity" value="320" /> <option name="screenDensity" value="320" />
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1612" /> <option name="screenY" value="1612" />
@@ -94,7 +94,7 @@
<option name="id" value="RMX3231" /> <option name="id" value="RMX3231" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="realme" /> <option name="manufacturer" value="realme" />
<option name="name" value="C11" /> <option name="name" value="RMX3231" />
<option name="screenDensity" value="320" /> <option name="screenDensity" value="320" />
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1600" /> <option name="screenY" value="1600" />
@@ -155,7 +155,7 @@
<option name="id" value="a05s" /> <option name="id" value="a05s" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="A05s" /> <option name="name" value="Galaxy A05s" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -191,7 +191,7 @@
<option name="id" value="a14m" /> <option name="id" value="a14m" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="SM-A145R" /> <option name="name" value="Galaxy A14" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2408" /> <option name="screenY" value="2408" />
@@ -227,7 +227,7 @@
<option name="id" value="a15" /> <option name="id" value="a15" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="A15" /> <option name="name" value="Galaxy A15" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -239,7 +239,7 @@
<option name="id" value="a15x" /> <option name="id" value="a15x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -251,7 +251,7 @@
<option name="id" value="a15x" /> <option name="id" value="a15x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -275,7 +275,7 @@
<option name="id" value="a16" /> <option name="id" value="a16" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="SM-A165M" /> <option name="name" value="Galaxy A16" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -287,7 +287,7 @@
<option name="id" value="a16x" /> <option name="id" value="a16x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -299,7 +299,7 @@
<option name="id" value="a16x" /> <option name="id" value="a16x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -311,7 +311,7 @@
<option name="id" value="a16xeea" /> <option name="id" value="a16xeea" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -335,7 +335,7 @@
<option name="id" value="a26x" /> <option name="id" value="a26x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -347,7 +347,7 @@
<option name="id" value="a34x" /> <option name="id" value="a34x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -359,7 +359,7 @@
<option name="id" value="a35x" /> <option name="id" value="a35x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="A35" /> <option name="name" value="Galaxy A35 5G" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -371,7 +371,7 @@
<option name="id" value="a35x" /> <option name="id" value="a35x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="A35" /> <option name="name" value="Galaxy A35 5G" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -383,7 +383,7 @@
<option name="id" value="a35x" /> <option name="id" value="a35x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="A35" /> <option name="name" value="Galaxy A35 5G" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -395,7 +395,7 @@
<option name="id" value="a36xq" /> <option name="id" value="a36xq" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -407,7 +407,7 @@
<option name="id" value="a36xq" /> <option name="id" value="a36xq" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -419,7 +419,7 @@
<option name="id" value="a56x" /> <option name="id" value="a56x" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -548,6 +548,7 @@
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="blazer" /> <option name="codename" value="blazer" />
<option name="default" value="true" />
<option name="id" value="blazer" /> <option name="id" value="blazer" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -555,6 +556,11 @@
<option name="screenDensity" value="420" /> <option name="screenDensity" value="420" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2410" /> <option name="screenY" value="2410" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="32" /> <option name="api" value="32" />
@@ -575,7 +581,7 @@
<option name="id" value="c1q" /> <option name="id" value="c1q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note 20 5G" /> <option name="name" value="Galaxy Note20 5G" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -587,7 +593,7 @@
<option name="id" value="c1qksw" /> <option name="id" value="c1qksw" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy Note 20 5G" /> <option name="name" value="Galaxy Note20 5G" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -632,7 +638,6 @@
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="comet" /> <option name="codename" value="comet" />
<option name="default" value="true" />
<option name="id" value="comet" /> <option name="id" value="comet" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -640,17 +645,11 @@
<option name="screenDensity" value="390" /> <option name="screenDensity" value="390" />
<option name="screenX" value="2076" /> <option name="screenX" value="2076" />
<option name="screenY" value="2152" /> <option name="screenY" value="2152" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="35" /> <option name="api" value="35" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="comet" /> <option name="codename" value="comet" />
<option name="default" value="true" />
<option name="id" value="comet" /> <option name="id" value="comet" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -658,11 +657,6 @@
<option name="screenDensity" value="390" /> <option name="screenDensity" value="390" />
<option name="screenX" value="2076" /> <option name="screenX" value="2076" />
<option name="screenY" value="2152" /> <option name="screenY" value="2152" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="35" /> <option name="api" value="35" />
@@ -671,7 +665,7 @@
<option name="id" value="cuscoi" /> <option name="id" value="cuscoi" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Motorola" /> <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="screenDensity" value="400" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -683,7 +677,7 @@
<option name="id" value="dm1q" /> <option name="id" value="dm1q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="S23" /> <option name="name" value="Galaxy S23" />
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -695,7 +689,7 @@
<option name="id" value="dm1q-SM-S911U" /> <option name="id" value="dm1q-SM-S911U" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="S23" /> <option name="name" value="Galaxy S23" />
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -719,7 +713,7 @@
<option name="id" value="dm2q" /> <option name="id" value="dm2q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="S23 Plus" /> <option name="name" value="Galaxy S23+" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -752,7 +746,6 @@
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
<option name="codename" value="e1q" /> <option name="codename" value="e1q" />
<option name="default" value="true" />
<option name="id" value="e1q" /> <option name="id" value="e1q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
@@ -760,17 +753,11 @@
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
<option name="codename" value="e1q" /> <option name="codename" value="e1q" />
<option name="default" value="true" />
<option name="id" value="e1q" /> <option name="id" value="e1q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
@@ -778,11 +765,6 @@
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
@@ -803,7 +785,7 @@
<option name="id" value="e2q" /> <option name="id" value="e2q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="Galaxy S24 +" /> <option name="name" value="Galaxy S24+" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -952,10 +934,23 @@
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1600" /> <option name="screenY" value="1600" />
</PersistentDeviceSelectionData> </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> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="frankel" /> <option name="codename" value="frankel" />
<option name="default" value="true" />
<option name="id" value="frankel" /> <option name="id" value="frankel" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -963,6 +958,11 @@
<option name="screenDensity" value="420" /> <option name="screenDensity" value="420" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2424" /> <option name="screenY" value="2424" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
@@ -971,7 +971,7 @@
<option name="id" value="g0q" /> <option name="id" value="g0q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="SM-S906U1" /> <option name="name" value="Galaxy S22+" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -983,7 +983,7 @@
<option name="id" value="g0q" /> <option name="id" value="g0q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="SM-S906U1" /> <option name="name" value="Galaxy S22+" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -1007,7 +1007,7 @@
<option name="id" value="gta9pwifi" /> <option name="id" value="gta9pwifi" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="240" />
<option name="screenX" value="1200" /> <option name="screenX" value="1200" />
<option name="screenY" value="1920" /> <option name="screenY" value="1920" />
@@ -1019,7 +1019,7 @@
<option name="id" value="gts7lwifi" /> <option name="id" value="gts7lwifi" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="340" />
<option name="screenX" value="1600" /> <option name="screenX" value="1600" />
<option name="screenY" value="2560" /> <option name="screenY" value="2560" />
@@ -1031,7 +1031,7 @@
<option name="id" value="gts7xllite" /> <option name="id" value="gts7xllite" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="340" />
<option name="screenX" value="1600" /> <option name="screenX" value="1600" />
<option name="screenY" value="2560" /> <option name="screenY" value="2560" />
@@ -1081,7 +1081,7 @@
<option name="id" value="gts9wifi" /> <option name="id" value="gts9wifi" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="340" />
<option name="screenX" value="1600" /> <option name="screenX" value="1600" />
<option name="screenY" value="2560" /> <option name="screenY" value="2560" />
@@ -1093,7 +1093,7 @@
<option name="id" value="guamna" /> <option name="id" value="guamna" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Motorola" /> <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="screenDensity" value="280" />
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1600" /> <option name="screenY" value="1600" />
@@ -1105,7 +1105,7 @@
<option name="id" value="guamp" /> <option name="id" value="guamp" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Motorola" /> <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="screenDensity" value="280" />
<option name="screenX" value="720" /> <option name="screenX" value="720" />
<option name="screenY" value="1600" /> <option name="screenY" value="1600" />
@@ -1258,6 +1258,7 @@
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="mustang" /> <option name="codename" value="mustang" />
<option name="default" value="true" />
<option name="id" value="mustang" /> <option name="id" value="mustang" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -1265,6 +1266,11 @@
<option name="screenDensity" value="390" /> <option name="screenDensity" value="390" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2404" /> <option name="screenY" value="2404" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
@@ -1273,7 +1279,7 @@
<option name="id" value="o1q" /> <option name="id" value="o1q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="421" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -1285,7 +1291,7 @@
<option name="id" value="o1q" /> <option name="id" value="o1q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="421" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -1309,7 +1315,7 @@
<option name="id" value="p3q" /> <option name="id" value="p3q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="600" />
<option name="screenX" value="1440" /> <option name="screenX" value="1440" />
<option name="screenY" value="3200" /> <option name="screenY" value="3200" />
@@ -1333,7 +1339,7 @@
<option name="id" value="pa2q" /> <option name="id" value="pa2q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="S25+" /> <option name="name" value="Galaxy S25+" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -1354,6 +1360,7 @@
<option name="api" value="35" /> <option name="api" value="35" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
<option name="codename" value="pa3q" /> <option name="codename" value="pa3q" />
<option name="default" value="true" />
<option name="id" value="pa3q" /> <option name="id" value="pa3q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
@@ -1361,11 +1368,17 @@
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
<option name="codename" value="pa3q" /> <option name="codename" value="pa3q" />
<option name="default" value="true" />
<option name="id" value="pa3q" /> <option name="id" value="pa3q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
@@ -1373,6 +1386,11 @@
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="33" /> <option name="api" value="33" />
@@ -1410,6 +1428,18 @@
<option name="screenX" value="1812" /> <option name="screenX" value="1812" />
<option name="screenY" value="2176" /> <option name="screenY" value="2176" />
</PersistentDeviceSelectionData> </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> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="samsung" /> <option name="brand" value="samsung" />
@@ -1441,7 +1471,7 @@
<option name="id" value="r0qcsx" /> <option name="id" value="r0qcsx" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="S22" /> <option name="name" value="Galaxy S22" />
<option name="screenDensity" value="480" /> <option name="screenDensity" value="480" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -1467,7 +1497,7 @@
<option name="id" value="r11q" /> <option name="id" value="r11q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -1479,7 +1509,7 @@
<option name="id" value="r11s" /> <option name="id" value="r11s" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2340" /> <option name="screenY" value="2340" />
@@ -1536,6 +1566,7 @@
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="rango" /> <option name="codename" value="rango" />
<option name="default" value="true" />
<option name="id" value="rango" /> <option name="id" value="rango" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -1543,6 +1574,11 @@
<option name="screenDensity" value="390" /> <option name="screenDensity" value="390" />
<option name="screenX" value="2076" /> <option name="screenX" value="2076" />
<option name="screenY" value="2152" /> <option name="screenY" value="2152" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="30" /> <option name="api" value="30" />
@@ -1592,7 +1628,7 @@
<option name="id" value="t2q" /> <option name="id" value="t2q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="394" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -1604,7 +1640,7 @@
<option name="id" value="t2q" /> <option name="id" value="t2q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="394" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2400" /> <option name="screenY" value="2400" />
@@ -1638,7 +1674,6 @@
<option name="api" value="34" /> <option name="api" value="34" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="tokay" /> <option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" /> <option name="id" value="tokay" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -1646,17 +1681,11 @@
<option name="screenDensity" value="420" /> <option name="screenDensity" value="420" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2424" /> <option name="screenY" value="2424" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="35" /> <option name="api" value="35" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="tokay" /> <option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" /> <option name="id" value="tokay" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -1664,17 +1693,11 @@
<option name="screenDensity" value="420" /> <option name="screenDensity" value="420" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2424" /> <option name="screenY" value="2424" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="36" /> <option name="api" value="36" />
<option name="brand" value="google" /> <option name="brand" value="google" />
<option name="codename" value="tokay" /> <option name="codename" value="tokay" />
<option name="default" value="true" />
<option name="id" value="tokay" /> <option name="id" value="tokay" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Google" /> <option name="manufacturer" value="Google" />
@@ -1682,11 +1705,6 @@
<option name="screenDensity" value="420" /> <option name="screenDensity" value="420" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2424" /> <option name="screenY" value="2424" />
<option name="tags">
<list>
<option value="dda-default" />
</list>
</option>
</PersistentDeviceSelectionData> </PersistentDeviceSelectionData>
<PersistentDeviceSelectionData> <PersistentDeviceSelectionData>
<option name="api" value="34" /> <option name="api" value="34" />
@@ -1695,7 +1713,7 @@
<option name="id" value="xcover7" /> <option name="id" value="xcover7" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <option name="manufacturer" value="Samsung" />
<option name="name" value="SM-G556B" /> <option name="name" value="Galaxy XCover7" />
<option name="screenDensity" value="450" /> <option name="screenDensity" value="450" />
<option name="screenX" value="1080" /> <option name="screenX" value="1080" />
<option name="screenY" value="2408" /> <option name="screenY" value="2408" />
@@ -1707,7 +1725,7 @@
<option name="id" value="y2q" /> <option name="id" value="y2q" />
<option name="labId" value="google" /> <option name="labId" value="google" />
<option name="manufacturer" value="Samsung" /> <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="screenDensity" value="600" />
<option name="screenX" value="1440" /> <option name="screenX" value="1440" />
<option name="screenY" value="3200" /> <option name="screenY" value="3200" />

View File

@@ -4,6 +4,7 @@ import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.ListenerRegistration; import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.QueryDocumentSnapshot; import com.google.firebase.firestore.QueryDocumentSnapshot;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -113,6 +114,15 @@ public class FirestoreManager {
updateUserStats(uid, updates, null); 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. * Regista um log de XP.
*/ */
@@ -245,9 +255,9 @@ public class FirestoreManager {
if (amount != null) { if (amount != null) {
dp.xp += amount.intValue(); dp.xp += amount.intValue();
} }
if ("focus_task".equals(type)) { if ("focus_task".equals(type) || "task_manual_completion".equals(type)) {
dp.completedTasks++; dp.completedTasks++;
dp.focusSessions++; if ("focus_task".equals(type)) dp.focusSessions++;
} }
} }
} }
@@ -264,4 +274,58 @@ public class FirestoreManager {
callback.accept(new java.util.HashMap<>()); 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));
});
}
} }

View File

@@ -35,14 +35,18 @@ import androidx.core.content.ContextCompat;
public class InicioFragment extends Fragment { 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 tvTodayStreak, tvTodayXP, tvTodayTasksCount, tvNoTasksIncentive;
private TextView tvDailyRewardGoal; private TextView tvDailyRewardGoal;
private ProgressBar pbDailyTasksProgress; private ProgressBar pbDailyTasksProgress;
private androidx.recyclerview.widget.RecyclerView rvTasks; private androidx.recyclerview.widget.RecyclerView rvTasks;
private TasksAdapter tasksAdapter; private TasksAdapter tasksAdapter;
private LinearLayout miniRankingContainer, layoutTasksSection; private LinearLayout miniRankingContainer, layoutTasksSection;
private Button btnStartFocus, btnAddTasks, btnClaimReward; private Button btnStartFocus, btnSecondaryFocus, btnAddTasks, btnClaimReward;
private androidx.cardview.widget.CardView btnStreakPage; private androidx.cardview.widget.CardView btnStreakPage;
private CountDownTimer countDownTimer; private CountDownTimer countDownTimer;
@@ -111,20 +115,13 @@ public class InicioFragment extends Fragment {
// Focus Mode // Focus Mode
tvTimer = view.findViewById(R.id.tvTimer); 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 = view.findViewById(R.id.btnStartFocus);
btnStartFocus.setOnClickListener(v -> { btnSecondaryFocus = view.findViewById(R.id.btnSecondaryFocus);
if (!isTimerRunning) {
if (selectedTaskForFocus == null) { btnStartFocus.setOnClickListener(v -> handleStartFocusClick());
if (getContext() != null) { btnSecondaryFocus.setOnClickListener(v -> handleSecondaryFocusClick());
Toast.makeText(getContext(), "Seleciona uma tarefa primeiro!", Toast.LENGTH_SHORT).show();
}
return;
}
startTimer();
} else {
pauseTimerWithWarning();
}
});
// Progress // Progress
progressPathContainer = view.findViewById(R.id.progressPathContainer); progressPathContainer = view.findViewById(R.id.progressPathContainer);
@@ -186,7 +183,7 @@ public class InicioFragment extends Fragment {
tvGreeting.setText("Olá, " + user.usuario + "!"); tvGreeting.setText("Olá, " + user.usuario + "!");
} }
if (tvTodayStreak != null) { if (tvTodayStreak != null) {
tvTodayStreak.setText(user.streak + " dias"); syncDailyStreak(user);
} }
refreshTodayStats(user); refreshTodayStats(user);
@@ -280,8 +277,12 @@ public class InicioFragment extends Fragment {
selectedTaskForFocus = task; selectedTaskForFocus = task;
timeLeftInMillis = task.duration * 60 * 1000; timeLeftInMillis = task.duration * 60 * 1000;
updateCountDownText(); updateCountDownText();
updateFocusUI(FocusState.NOT_STARTED);
if (tvFocusTitle != null) {
tvFocusTitle.setText(task.title);
}
if (getContext() != null) { 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(); 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) { private void updateTodayCard(Usuario user) {
if (user == null) return;
int completed = user.tasks_concluidas_hoje; int completed = user.tasks_concluidas_hoje;
int goal = user.meta_diaria_tarefas; int goal = user.meta_diaria_tarefas;
if (goal <= 0) goal = 3; // Default fallback if (goal <= 0) goal = 3; // Default fallback
// Sincronizar e mostrar streak
syncDailyStreak(user);
if (tvTodayTasksCount != null) { if (tvTodayTasksCount != null) {
tvTodayTasksCount.setText(completed + "/" + goal); 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("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
updates.put("total_tasks_concluidas", 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) { // Adicionar log de XP mesmo em manual para permitir recálculo se necessário
updates.put("streak", com.google.firebase.firestore.FieldValue.increment(1)); FirestoreManager.getInstance().addXpLog(uid, 0, "task_manual_completion");
if (user.streak + 1 > user.melhor_streak) {
updates.put("melhor_streak", user.streak + 1);
}
}
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() { private void startTimer() {
if (selectedTaskForFocus == null) return; if (selectedTaskForFocus == null) return;
if (countDownTimer != null) countDownTimer.cancel();
countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) { countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
@Override @Override
public void onTick(long millisUntilFinished) { public void onTick(long millisUntilFinished) {
timeLeftInMillis = millisUntilFinished; timeLeftInMillis = millisUntilFinished;
updateCountDownText(); updateCountDownText();
} }
@Override @Override
public void onFinish() { public void onFinish() {
handleFocusComplete(); handleFocusComplete();
} }
}.start(); }.start();
isTimerRunning = true; 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() { private void handleFocusComplete() {
@@ -738,14 +897,15 @@ public class InicioFragment extends Fragment {
android.util.Log.d("FLUXUP_DEBUG", "TIMER_CANCELLED"); android.util.Log.d("FLUXUP_DEBUG", "TIMER_CANCELLED");
} }
isTimerRunning = false;
if (btnStartFocus != null) btnStartFocus.setText("Começar Foco");
if (selectedTaskForFocus == null) { if (selectedTaskForFocus == null) {
android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: selectedTask null"); android.util.Log.e("FLUXUP_DEBUG", "FOCUS_COMPLETE_ERROR: selectedTask null");
isCompletingFocus = false; isCompletingFocus = false;
return; return;
} }
isTimerRunning = false;
updateFocusUI(FocusState.NOT_STARTED);
android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + selectedTaskForFocus.id); android.util.Log.d("FLUXUP_DEBUG", "SELECTED_TASK: " + selectedTaskForFocus.id);
FirebaseUser currentUser = AuthManager.getInstance().getCurrentUser(); 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("tasks_concluidas_hoje", com.google.firebase.firestore.FieldValue.increment(1));
updates.put("total_tasks_concluidas", 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 currentLevel = user.level;
int threshold = (currentLevel * (currentLevel + 1) / 2) * 100; int threshold = (currentLevel * (currentLevel + 1) / 2) * 100;
if (user.xp + 50 >= threshold) { if (user.xp + 50 >= threshold) {
@@ -816,6 +969,7 @@ public class InicioFragment extends Fragment {
selectedTaskForFocus = null; selectedTaskForFocus = null;
timeLeftInMillis = 25 * 60 * 1000; timeLeftInMillis = 25 * 60 * 1000;
updateCountDownText(); updateCountDownText();
updateFocusUI(FocusState.NOT_STARTED);
android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_SUCCESS"); android.util.Log.d("FLUXUP_DEBUG", "FOCUS_COMPLETE_SUCCESS");
} }
isCompletingFocus = false; 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() { private void updateCountDownText() {
int minutes = (int) (timeLeftInMillis / 1000) / 60; int minutes = (int) (timeLeftInMillis / 1000) / 60;

View File

@@ -14,19 +14,25 @@ import android.widget.ProgressBar;
import java.util.Calendar; import java.util.Calendar;
import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.ListenerRegistration; import com.google.firebase.firestore.ListenerRegistration;
import android.graphics.Color;
public class TrophiesActivity extends AppCompatActivity { public class TrophiesActivity extends AppCompatActivity {
private TextView tvLeagueName, tvLeagueTimeRemaining, tvLeagueObjective; private TextView tvHeaderTimeLeft, tvHeaderXP;
private TextView tvUserRankingStatus, tvXPToNextPosition, tvPastPerformance; private ImageView ivHeaderLeagueIcon;
private ProgressBar pbWeeklyProgress; private ProgressBar pbHeaderProgress;
private LinearLayout rankingContainer;
private ImageButton btnBack; private TextView tvUserName, tvUserDivision;
private ProgressBar pbUserBottom;
private LinearLayout divisionsContainer, rankingContainer;
private ImageButton btnBack, btnHelp;
private Button btnEarnXpNow; private Button btnEarnXpNow;
private com.google.android.material.tabs.TabLayout tabLayout;
private View tabDivisoes, tabRanking;
private FirestoreManager firestoreManager; private FirestoreManager firestoreManager;
private FirebaseAuth mAuth; private FirebaseAuth mAuth;
private ListenerRegistration rankingListener, userListener; private ListenerRegistration userListener, rankingListener;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -39,63 +45,171 @@ public class TrophiesActivity extends AppCompatActivity {
initViews(); initViews();
setupListeners(); setupListeners();
observeUserData(); observeUserData();
observeRanking("global");
} }
private void initViews() { private void initViews() {
tvLeagueName = findViewById(R.id.tvLeagueName); ivHeaderLeagueIcon = findViewById(R.id.ivHeaderLeagueIcon);
tvLeagueTimeRemaining = findViewById(R.id.tvLeagueTimeRemaining); tvHeaderTimeLeft = findViewById(R.id.tvHeaderTimeLeft);
tvLeagueObjective = findViewById(R.id.tvLeagueObjective); tvHeaderXP = findViewById(R.id.tvHeaderXP);
tvUserRankingStatus = findViewById(R.id.tvUserRankingStatus); pbHeaderProgress = findViewById(R.id.pbHeaderProgress);
tvXPToNextPosition = findViewById(R.id.tvXPToNextPosition);
tvPastPerformance = findViewById(R.id.tvPastPerformance); tvUserName = findViewById(R.id.tvUserName);
pbWeeklyProgress = findViewById(R.id.pbWeeklyProgress); tvUserDivision = findViewById(R.id.tvUserDivision);
pbUserBottom = findViewById(R.id.pbUserBottom);
divisionsContainer = findViewById(R.id.divisionsContainer);
rankingContainer = findViewById(R.id.rankingContainer); rankingContainer = findViewById(R.id.rankingContainer);
btnBack = findViewById(R.id.btnBack); btnBack = findViewById(R.id.btnBack);
btnHelp = findViewById(R.id.btnHelp);
btnEarnXpNow = findViewById(R.id.btnEarnXpNow); btnEarnXpNow = findViewById(R.id.btnEarnXpNow);
tabLayout = findViewById(R.id.tabLayout);
tabDivisoes = findViewById(R.id.tabDivisoes);
tabRanking = findViewById(R.id.tabRanking);
updateTimeRemaining(); updateTimeRemaining();
} }
private void setupListeners() { private void setupListeners() {
btnBack.setOnClickListener(v -> finish()); 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")); tabLayout.addOnTabSelectedListener(new com.google.android.material.tabs.TabLayout.OnTabSelectedListener() {
findViewById(R.id.btnRankingAmigos).setOnClickListener(v -> observeRanking("friends")); @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() { private void updateTimeRemaining() {
// Simple logic for week end (Sunday 23:59)
Calendar now = Calendar.getInstance(); Calendar now = Calendar.getInstance();
int daysLeft = Calendar.SUNDAY - now.get(Calendar.DAY_OF_WEEK); int daysLeft = Calendar.SUNDAY - now.get(Calendar.DAY_OF_WEEK);
if (daysLeft < 0) daysLeft += 7; if (daysLeft < 0) daysLeft += 7;
int hoursLeft = 23 - now.get(Calendar.HOUR_OF_DAY); tvHeaderTimeLeft.setText("Termina em " + daysLeft + " dias");
tvLeagueTimeRemaining.setText(daysLeft + " dias " + hoursLeft + "h restantes");
int progress = (7 - daysLeft) * 100 / 7;
animateProgressBar(progress);
} }
private void observeUserData() { private void observeUserData() {
String uid = mAuth.getUid(); String uid = mAuth.getUid();
if (uid != null) { 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) { private void updateUI(Usuario user) {
if (user == null) return; LeagueHelper.LeagueInfo current = LeagueHelper.getCurrentLeague(user.xp);
tvLeagueName.setText("Divisão " + user.league); LeagueHelper.LeagueInfo next = LeagueHelper.getNextLeague(user.xp);
tvLeagueObjective.setText("Fica no TOP 3 para subir para " + getNextLeague(user.league));
// 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) { // Bottom Card
switch (current) { tvUserName.setText(user.usuario);
case "Bronze": return "Prata"; tvUserDivision.setText(current.name + "" + user.xp + " XP");
case "Prata": return "Ouro"; if (next != null) {
case "Ouro": return "Platina"; int bottomProgress = (user.xp - current.minXp) * 100 / (next.minXp - current.minXp);
default: return "Diamante"; 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; int position = 1;
String myUid = mAuth.getUid(); String myUid = mAuth.getUid();
Usuario me = null;
Usuario next = null;
int myPos = -1;
for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots.getDocuments()) { for (com.google.firebase.firestore.DocumentSnapshot doc : snapshots.getDocuments()) {
Usuario user = doc.toObject(Usuario.class); Usuario user = doc.toObject(Usuario.class);
if (user == null) continue; 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); 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) { private void addRankingItem(int pos, Usuario user, String myUid) {
View view = getLayoutInflater().inflate(R.layout.item_ranking_user, rankingContainer, false); View view = getLayoutInflater().inflate(R.layout.item_ranking_user, rankingContainer, false);
TextView tvPos = view.findViewById(R.id.tvRankPosition); TextView tvPos = view.findViewById(R.id.tvRankPosition);
TextView tvName = view.findViewById(R.id.tvRankingName); TextView tvName = view.findViewById(R.id.tvRankingName);
TextView tvXP = view.findViewById(R.id.tvRankingXP); TextView tvXP = view.findViewById(R.id.tvRankingXP);
TextView tvTu = view.findViewById(R.id.tvRankingLabelTu); TextView tvTu = view.findViewById(R.id.tvRankingLabelTu);
ImageView ivAvatar = view.findViewById(R.id.ivRankingAvatar);
androidx.cardview.widget.CardView card = view.findViewById(R.id.cardRankingUser); 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); tvPos.setText("#" + pos);
}
tvName.setText(user.usuario); tvName.setText(user.usuario);
tvXP.setText(user.xp_semanal + " XP"); tvXP.setText(user.xp_semanal + " XP");
if (user.id_usuario.equals(myUid)) { if (user.id_usuario.equals(myUid)) {
tvTu.setVisibility(View.VISIBLE); tvTu.setVisibility(View.VISIBLE);
card.setCardBackgroundColor(android.graphics.Color.parseColor("#F3E5F5")); // Light purple card.setCardBackgroundColor(Color.parseColor("#F3E5F5"));
card.setCardElevation(4f);
} }
rankingContainer.addView(view); 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 @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
if (rankingListener != null) rankingListener.remove();
if (userListener != null) userListener.remove(); if (userListener != null) userListener.remove();
if (rankingListener != null) rankingListener.remove();
} }
} }

View File

@@ -34,6 +34,7 @@ public class Usuario {
public int sessoes_foco_completas = 0; public int sessoes_foco_completas = 0;
public int dias_ativos = 1; public int dias_ativos = 1;
public String last_active_date = ""; // YYYY-MM-DD 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 last_reward_claim_date = ""; // YYYY-MM-DD
public String avatar_url = ""; public String avatar_url = "";

View File

@@ -1,19 +1,26 @@
<?xml version="1.0" encoding="utf-8"?> <?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" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/background_light"> android:background="@color/background_light">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/card_background" android:background="@color/card_background"
app:elevation="0dp"> app:elevation="0dp">
<RelativeLayout <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="64dp" android:layout_height="64dp"
app:contentInsetStart="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"> android:paddingHorizontal="16dp">
<ImageButton <ImageButton
@@ -26,7 +33,6 @@
app:tint="@color/text_primary" /> app:tint="@color/text_primary" />
<TextView <TextView
android:id="@+id/tvToolbarTitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_centerInParent="true"
@@ -34,97 +40,20 @@
android:textColor="@color/text_primary" android:textColor="@color/text_primary"
android:textSize="20sp" android:textSize="20sp"
android:textStyle="bold" /> 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> </RelativeLayout>
</com.google.android.material.appbar.AppBarLayout> </androidx.appcompat.widget.Toolbar>
<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">
<!-- Gamified Header Section -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -132,174 +61,214 @@
android:padding="20dp" android:padding="20dp"
android:gravity="center"> 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 <TextView
android:id="@+id/tvUserRankingStatus" android:id="@+id/tvHeaderTimeLeft"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="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:textColor="@color/text_primary"
android:textStyle="bold" android:textStyle="bold"
android:textAlignment="center" android:layout_marginTop="8dp"/>
android:textSize="16sp"/>
<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> </LinearLayout>
</androidx.cardview.widget.CardView>
<!-- 8. 👥 FILTRO DE RANKING --> <com.google.android.material.tabs.TabLayout
<com.google.android.material.button.MaterialButtonToggleGroup android:id="@+id/tabLayout"
android:id="@+id/toggleRankingFilter" 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_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:text="Divisões" />
android:layout_marginBottom="24dp"
app:singleSelection="true"
app:selectionRequired="true"
app:checkedButton="@+id/btnRankingGlobal">
<Button <com.google.android.material.tabs.TabItem
android:id="@+id/btnRankingGlobal" android:layout_width="wrap_content"
style="?attr/materialButtonOutlinedStyle" android:layout_height="wrap_content"
android:layout_width="120dp" android:text="Amigos" />
android:layout_height="50dp"
android:text="Global"
android:textStyle="bold"
android:textSize="14sp"/>
<Button <com.google.android.material.tabs.TabItem
android:id="@+id/btnRankingAmigos" android:layout_width="wrap_content"
style="?attr/materialButtonOutlinedStyle" android:layout_height="wrap_content"
android:layout_width="120dp" android:text="Ranking" />
android:layout_height="50dp"
android:text="Amigos" </com.google.android.material.tabs.TabLayout>
android:textStyle="bold"
android:textSize="14sp"/> </com.google.android.material.appbar.AppBarLayout>
</com.google.android.material.button.MaterialButtonToggleGroup>
<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 <LinearLayout
android:id="@+id/rankingContainer" android:id="@+id/rankingContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical" />
android:layout_marginBottom="32dp"/>
</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 <TextView
android:id="@+id/tvUserName"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Recompensas da semana" android:text="Utilizador"
android:textStyle="bold"
android:textSize="18sp"
android:textColor="@color/text_primary" 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 <TextView
android:id="@+id/tvPastPerformance" android:id="@+id/tvUserDivision"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Semana passada: 2º lugar (subiste)" android:text="Bronze • 0 XP"
android:textAlignment="center"
android:textColor="@color/text_secondary" android:textColor="@color/text_secondary"
android:textSize="14sp" android:textSize="14sp"/>
android:layout_marginBottom="32dp"
android:visibility="gone" /> <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 <Button
android:id="@+id/btnEarnXpNow" android:id="@+id/btnEarnXpNow"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="64dp" android:layout_height="56dp"
android:text="⚡ Ganhar XP Agora" android:layout_marginHorizontal="16dp"
android:layout_marginBottom="16dp"
android:text="Ganhar XP agora"
android:backgroundTint="@color/primary_purple" android:backgroundTint="@color/primary_purple"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="18sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:textAllCaps="false" android:textAllCaps="false"
app:cornerRadius="16dp" app:cornerRadius="12dp" />
android:layout_marginBottom="40dp"/>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </RelativeLayout>

View File

@@ -239,14 +239,25 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/tvFocusTitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="24dp" android:text="Seleciona uma tarefa"
android:text="Modo Foco"
android:textColor="@color/text_primary" android:textColor="@color/text_primary"
android:textSize="22sp" android:textSize="22sp"
android:textAlignment="center"
android:textStyle="bold" /> 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 <FrameLayout
android:id="@+id/timerBlock" android:id="@+id/timerBlock"
android:layout_width="200dp" android:layout_width="200dp"
@@ -281,10 +292,33 @@
</LinearLayout> </LinearLayout>
</FrameLayout> </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 <Button
android:id="@+id/btnStartFocus" android:id="@+id/btnStartFocus"
android:layout_width="200dp" android:layout_width="0dp"
android:layout_height="56dp" android:layout_height="56dp"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:background="@drawable/button_primary" android:background="@drawable/button_primary"
android:text="Começar Foco" android:text="Começar Foco"
android:textAllCaps="false" android:textAllCaps="false"
@@ -293,6 +327,7 @@
android:textStyle="bold" android:textStyle="bold"
app:backgroundTint="@null" /> app:backgroundTint="@null" />
</LinearLayout> </LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
<!-- 5. 📊 PROGRESSO DIÁRIO --> <!-- 5. 📊 PROGRESSO DIÁRIO -->

View File

@@ -1,3 +1,4 @@
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true
android.dependency.useConstraints=true android.dependency.useConstraints=true
android.r8.strictFullModeForKeepRules=false android.r8.strictFullModeForKeepRules=false