Compare commits
523 Commits
feature/sy
...
543be48cb1
| Author | SHA1 | Date | |
|---|---|---|---|
| 543be48cb1 | |||
| 297a381e67 | |||
| 542750207e | |||
| 46a3b69971 | |||
| 5aa8744ef4 | |||
| ce4879ac2b | |||
| 516bf394f8 | |||
| 5fe9704c36 | |||
| 2816b7c3d0 | |||
|
|
0a4086ec8c | ||
| a9acbd6cab | |||
| e121f46b61 | |||
| d57de9d10c | |||
| e4348a2144 | |||
| e608c6ea62 | |||
| 5403b6bd51 | |||
| a6cf43dbca | |||
| 074627f6e1 | |||
|
|
96e20f751f | ||
| 0daa4f6a2f | |||
| 035b392ece | |||
| 648c7277cf | |||
| 5006f5128b | |||
| 97b98a872d | |||
| 862a851e1c | |||
| 804030f5c0 | |||
| 08ab3c22ce | |||
| b58f836d8e | |||
| 9ed4630f9b | |||
| 70dab74528 | |||
| 7e5d2fa207 | |||
| 0e432fb332 | |||
|
|
c987144f4a | ||
| 897a236501 | |||
| 0cccecec77 | |||
| f1ed875256 | |||
| e82bd47aab | |||
| e9517f7378 | |||
| 12cc70a51a | |||
| fa670b19b7 | |||
| 45b100aad9 | |||
| 3c0c0b77ff | |||
| 66fa56ea62 | |||
| 951dabea8b | |||
| 76b9dd8bd9 | |||
| f68510f860 | |||
| 245b0eb4d6 | |||
| 4a0599fce4 | |||
| abbfe87260 | |||
| 3330014fa9 | |||
|
|
cc720e3dcb | ||
|
|
6e3d06cff9 | ||
|
|
d458cbd47a | ||
|
|
74ce269446 | ||
|
|
9eb8624863 | ||
|
|
c4bc301fb2 | ||
|
|
107c898f51 | ||
|
|
4a7d7ef490 | ||
|
|
13ecc2a386 | ||
|
|
2296a49999 | ||
|
|
303020a8c0 | ||
|
|
37219cb13f | ||
|
|
62d9d29e91 | ||
| 451b536e71 | |||
| 14dbf90c23 | |||
| 280a5ddceb | |||
| 22331ed364 | |||
| d0a45eb523 | |||
|
|
fec73af665 | ||
|
fc9cc423d0
|
|||
|
e7165d993f
|
|||
|
732ec1c70a
|
|||
|
e823cd5758
|
|||
| 46fe683d71 | |||
|
7f6248123c
|
|||
|
2024277ebe
|
|||
| c216fb01d6 | |||
|
7cb32f486b
|
|||
|
093591fbaf
|
|||
|
985234cdf3
|
|||
|
06090e238a
|
|||
|
e48452f724
|
|||
|
|
936986e110 | ||
|
|
4b3910aea8 | ||
|
|
10074ded32 | ||
|
|
1280e798d2
|
||
|
|
b09306e793
|
||
|
|
e30636a447
|
||
|
|
ad8738180c
|
||
|
|
08410c59d0
|
||
|
|
ab86cee70b | ||
|
|
3a0603605b
|
||
|
|
6a78b4d853 | ||
|
|
fe43b1435d | ||
|
|
12503b8a6d | ||
|
|
ef7f78bff0 | ||
|
|
53c208ded5 | ||
|
|
1bdc83e92f | ||
|
|
680c1cdc76 | ||
|
|
80916bac50 | ||
|
|
a5e3e9b3cf | ||
|
248ba50a8e
|
|||
|
|
45a82b3c2d
|
||
|
770d1293dc
|
|||
|
d10538e720
|
|||
|
02e9e2384e
|
|||
|
|
b627ff4413
|
||
|
|
0683ea43f4
|
||
|
08f77a5cae
|
|||
|
27df792775
|
|||
|
|
800f92f255
|
||
|
|
e06ed3ed7d | ||
|
|
3bb119c6ed | ||
|
|
0762699a86 | ||
|
|
8837326d44 | ||
|
|
481a3d5784 | ||
|
8eff782f54
|
|||
|
c590734c42
|
|||
|
7e7f68282b
|
|||
|
4bd5cee17b
|
|||
|
b2421dc8b1
|
|||
|
93363bff96
|
|||
|
d01044b203
|
|||
|
70fe513e52
|
|||
|
dee93fde8f
|
|||
|
f0ce05e06e
|
|||
|
4975ba2752
|
|||
|
ed8c60e52f
|
|||
|
|
7735247521 | ||
|
|
b32a6ad1b8 | ||
|
|
21a512ae71 | ||
|
|
b0944d3f1c | ||
|
|
8a9b719c50 | ||
|
|
ef7454ae75 | ||
|
|
b51f6abfce | ||
|
|
a013635224 | ||
|
|
a9f028a34b | ||
|
|
3b0fba12f5 | ||
|
|
4139f09fb7 | ||
|
|
248ff2ec62 | ||
|
|
cc7178eb21 | ||
|
6116ef9450
|
|||
|
8801960615
|
|||
|
b0a4284b66
|
|||
|
|
334dabb407 | ||
|
|
b2fc79a3ab | ||
|
|
f0e8643e6b | ||
|
|
5cd616f967 | ||
|
|
b53ef758ec | ||
|
|
5add03bf23 | ||
|
|
b465ee588b | ||
|
|
b9253d41ea | ||
|
|
ca0a9dd85f | ||
|
|
9951525cbe | ||
|
|
98b2c9cce2 | ||
|
|
19de2a2d1c | ||
|
|
80f783b669 | ||
|
|
761fe59c5e | ||
|
|
f58d8a52ff | ||
|
|
f4e5b68258 | ||
|
|
5df3ee0d61 | ||
|
|
25cff3d9b0 | ||
|
|
9f66a27b82 | ||
|
|
4bbb20e18e | ||
|
|
4f9ab6d263 | ||
|
|
af21fd25db | ||
|
|
35097e1263 | ||
|
|
8e4274d923 | ||
|
|
12649141b1 | ||
|
|
0526d37fbd | ||
|
|
b083899ec8 | ||
|
|
6b793c7c16 | ||
|
|
11ca993a75 | ||
|
|
7348ddeffa | ||
|
88df8d2552
|
|||
|
d4f4f8b4a9
|
|||
|
9ca1aa911a
|
|||
|
ba57ebad31
|
|||
|
|
e4d2c93a1d | ||
|
|
07065a60ad | ||
|
|
916cd76be1 | ||
|
8b55ffb147
|
|||
|
727e88b7b1
|
|||
|
f70d33878c
|
|||
|
6a55d3c01a
|
|||
|
69b5ed3a6d
|
|||
|
8b2adbf301
|
|||
|
88cc3a2a12
|
|||
|
26526a71a9
|
|||
|
11eb3713e5
|
|||
|
1df9cc7664
|
|||
|
|
499eb467cb | ||
|
|
9d4df73c56 | ||
|
|
d0f32dfa0a | ||
|
|
c609eceefc | ||
|
|
eb68220b8d | ||
|
|
f1a003fabf | ||
|
b76da35752
|
|||
|
abead88ceb
|
|||
|
908eb4ac99
|
|||
|
|
856a0726f7 | ||
|
|
df97b1fd4f | ||
|
71a05d598a
|
|||
|
2131fb3a3d
|
|||
|
1470dcd560
|
|||
| dc678e59df | |||
|
|
d95084500f | ||
|
6f7215b46f
|
|||
|
|
c423d2b3ca | ||
|
|
758fc56277 | ||
|
|
c7d1e92cae | ||
|
|
d24dcbf2ca | ||
|
|
579b33cc78 | ||
|
|
1a3e6315a1 | ||
|
|
7f4d06d15d | ||
|
|
b8033a6012 | ||
|
471f977209
|
|||
|
2ba5f5fb98
|
|||
|
4de67bd27a
|
|||
|
0bb82a48a5
|
|||
|
d5a5273607
|
|||
|
404671546c
|
|||
|
a94c6e8b9f
|
|||
|
da09df2dd1
|
|||
|
40a4d254f5
|
|||
|
177d01edd9
|
|||
|
9f5da7b4fe
|
|||
|
e42d41ef30
|
|||
|
5498ff8a87
|
|||
|
20dcc7929b
|
|||
|
1283cf979d
|
|||
|
0a493ff065
|
|||
|
16cd249bae
|
|||
|
d136572960
|
|||
|
318aa3c821
|
|||
|
73712e0d10
|
|||
| bf504641c6 | |||
|
ec1f0c5356
|
|||
|
2154d8c192
|
|||
|
961fb7618f
|
|||
|
11f726064a
|
|||
|
4c5a722dc5
|
|||
| ee39ff0eda | |||
| abced92a07 | |||
|
|
eeacc5eef8 | ||
|
|
16c65f19fd | ||
|
|
6a9c3a36eb | ||
|
|
99ccb44ad3 | ||
| fc402fd81b | |||
| f7c6bc716c | |||
| 2535347d5a | |||
|
|
8c0655c352 | ||
|
|
335f8c32fd | ||
|
|
f77c064722 | ||
|
|
8b0b757f04 | ||
| 13af054214 | |||
| fcbb586e80 | |||
| 458c9f3b15 | |||
| dfa74960b3 | |||
| f082842fbe | |||
| d4d818a085 | |||
|
|
f074d0331d | ||
|
|
f94bc62a94 | ||
|
|
428bf42e79 | ||
| b0097fa45e | |||
|
|
15fa1fea8c | ||
| 31368cff45 | |||
| b44dd96dd3 | |||
| 838e13f30c | |||
|
|
08fab0cd8d | ||
|
|
a142685d2e | ||
| a7a95f2030 | |||
|
|
d3c90481be | ||
| f9bb0d7d7b | |||
| f23a1bedee | |||
| dcf31ba115 | |||
| 0eae43fe55 | |||
| c0fcd4e763 | |||
| 79e2402c9d | |||
|
|
5409a324e8 | ||
|
|
504362e680 | ||
|
|
0ce2f8fae2 | ||
| 2fc6c67432 | |||
| 459cf02642 | |||
| 44cb64601f | |||
| 53c270ee12 | |||
| e4b16f6d59 | |||
| 3021e408a7 | |||
| 7649119db7 | |||
| b0a4f26e7a | |||
|
|
dd47d4cf08 | ||
|
|
8912a9d73c | ||
|
|
9bd1c6f685 | ||
|
|
e15e06034c | ||
|
|
a6180a5049 | ||
|
|
7c69b17e77 | ||
|
|
602a40a532 | ||
|
|
e00998f913 | ||
|
|
af5914c2db | ||
|
|
6c5f70638a | ||
|
|
ba88552919 | ||
|
|
8c90c4f68d | ||
|
|
08eb1a600d | ||
|
|
8ea0480d4a | ||
|
|
36ee39589e | ||
|
|
ac7a721940 | ||
|
|
b36ca8673a | ||
|
|
7cfac486f9 | ||
|
|
21dd413ab5 | ||
|
|
39e10638b5 | ||
| 0a95b6d2a0 | |||
| e6bcbb39ff | |||
| 90de1f3723 | |||
| 68740b4043 | |||
| b66a6ff717 | |||
| 7c1a91e35a | |||
| 366e9af167 | |||
| 03b02aaa06 | |||
|
|
180cf25ad3 | ||
| 3490cd183a | |||
|
|
0c292d1eaa | ||
| 0b256cb2c0 | |||
| cc03c48648 | |||
| 53e7ef2918 | |||
| 9609bee0f7 | |||
| 5b23a3f960 | |||
| d2d45991b0 | |||
| 25aeafb759 | |||
| 9045ae5c24 | |||
| 555873354c | |||
| 2a012619a7 | |||
| d1de3a852b | |||
| f04e37e905 | |||
| 825a5f2cb9 | |||
| 0de6896691 | |||
| 7187214282 | |||
|
|
9d4161a255 | ||
|
|
d82a3c145d | ||
|
|
a6cbd44e42 | ||
|
|
45c62b4ab2 | ||
|
|
d53312d261 | ||
|
|
c453810785 | ||
|
|
999057300b | ||
|
|
2245347e28 | ||
|
|
b79f7850ed | ||
|
|
4469f86e46 | ||
|
|
bdeddb149e | ||
|
|
3b12ec4bfe | ||
| ca4618579e | |||
| 2f13aba22c | |||
| dba5912ecd | |||
| 88b8663484 | |||
| 609886fd09 | |||
| a4db997e06 | |||
|
|
090216ccb7 | ||
|
|
472092d1bf | ||
|
|
6d3791de31 | ||
|
|
24a99d5791 | ||
|
|
6c631b1cf6 | ||
|
|
5d7677b354 | ||
|
|
22820f4f24 | ||
| 1d3bd48535 | |||
|
|
694446b7e3 | ||
|
|
20ae9d247e | ||
|
|
1943fac610 | ||
|
|
a07a50e635 | ||
|
|
8ccb9bbab1 | ||
|
|
743b8d26ad | ||
|
|
c47bd4c328 | ||
|
|
d84abc3a6a | ||
|
|
4ae85f1ec0 | ||
|
|
79d40d1d79 | ||
|
|
1902b8821e | ||
|
|
075542d605 | ||
|
|
0b5894ee6d | ||
|
|
92fb9dbdb6 | ||
|
|
1860abf532 | ||
|
|
3f4780c9fb | ||
|
|
d5d6e4616e | ||
|
|
18e267053d | ||
| 7ba9a7e4e7 | |||
| 5b8a7c39e2 | |||
| d40a5a89cd | |||
| 308d558347 | |||
| 9770ce187a | |||
| 535bc03b70 | |||
| 642e45af89 | |||
| 56d2307b75 | |||
| d875af8a8e | |||
| feeb4f057d | |||
| 1ad5c6b896 | |||
| baee3b9f86 | |||
| e6167baab1 | |||
|
|
1c15e7742e | ||
|
|
072ba63789 | ||
|
|
0fa0daa058 | ||
|
|
5a5ed3d631 | ||
|
|
3dfa376f59 | ||
|
|
7bf74634bb | ||
|
|
fc645a81bc | ||
|
|
35365bbdf3 | ||
|
|
779ef5dbee | ||
|
|
e82994c76b | ||
|
|
4e1d01d8d1 | ||
|
|
5de0fc86e5 | ||
| e26b643423 | |||
| 621534d610 | |||
| a01300e9c6 | |||
| ecb8ce105a | |||
| 32ef3c14f7 | |||
| 4972257635 | |||
| c98cb50baa | |||
| c331f34fa9 | |||
| a1aea532b5 | |||
| 43489aeb4c | |||
| 990c85aedd | |||
|
|
64337b9bee | ||
|
|
8bdfaa2434 | ||
|
|
5f6060858d | ||
| b62e436054 | |||
| bf63b4dbcf | |||
| a82d940bcc | |||
| ba59dc7ca9 | |||
| 181290a0f3 | |||
|
|
d553c2f3f2 | ||
|
|
7776093217 | ||
|
|
b27f3f8540 | ||
| eb041bf6b2 | |||
|
|
e3c53bf07f | ||
|
|
9ddab6ee59 | ||
|
|
2615795402 | ||
|
|
6531445d7f | ||
|
|
4fbf8a8ca2 | ||
|
|
707b2b4380 | ||
|
|
aae85c1170 | ||
|
|
c12a6c6a4d | ||
|
|
b15c02adbf | ||
|
|
9e24128675 | ||
|
|
66c61e2e6c | ||
|
|
7bddfbe5a7 | ||
|
|
8036b10ee6 | ||
|
|
71f400f587 | ||
|
|
79e302f922 | ||
|
|
af7f60fc4d | ||
|
|
7cc4b66dfd | ||
|
|
a9fddf9963 | ||
|
|
36c1504c6a | ||
|
|
d644170141 | ||
|
|
d38f83e961 | ||
|
|
c50c5af497 | ||
|
|
fa3774a32b | ||
|
|
fd124f2a6c | ||
|
|
265b65eb8a | ||
|
|
4c269c55d2 | ||
|
|
c03305120e | ||
|
|
29615b670b | ||
|
|
6ab4a696b6 | ||
|
|
23479c7765 | ||
|
|
6d98f7aafa | ||
| 75078ed52b | |||
| 2a0afedb1d | |||
| 66a2b41250 | |||
|
|
d6a7fa3d7a | ||
|
|
07e55f1c76 | ||
| 4ee5dd910b | |||
| 87f071b5b4 | |||
| bb0b5e8adf | |||
|
|
c79d1e82a5 | ||
|
|
4aebeedec6 | ||
|
|
7de94f2caf | ||
|
|
17ed85fc1b | ||
|
|
4355fb4d68 | ||
|
|
508200abeb | ||
|
|
a29943e783 | ||
|
|
3e6a9181d6 | ||
| 1fe3a3d1ca | |||
|
|
b2951a3475 | ||
|
|
9d3c63cf62 | ||
|
|
65d237254c | ||
|
|
fe1d5c66cb | ||
|
|
113a5028af | ||
|
|
1a56260757 | ||
|
|
697fffbc99 | ||
|
|
804edfa64e | ||
| 2ab6c396d0 | |||
| a55f467339 | |||
|
|
cf682f68c9 | ||
| 0e988e746c | |||
|
|
f119cbf8e7 | ||
|
|
056f5f6fce | ||
|
|
42f6125d5e | ||
|
|
3e20fc4d1d | ||
|
|
1f763feb69 | ||
|
|
6e7ad329fe | ||
|
|
5cb241475d | ||
|
|
27e76c7243 | ||
|
|
576ad04064 | ||
|
|
5f8187ef6d | ||
|
|
f16f919e27 | ||
|
|
736bb8a75e | ||
|
|
de9ad6d4a4 | ||
|
|
1d37ce54ea | ||
|
|
f88f1cfb54 | ||
|
|
fc1478645b | ||
|
|
ffab001b09 | ||
|
|
a58a8005e1 | ||
|
|
c884ada187 | ||
|
|
e3d46ad5a0 | ||
|
|
f4a2c03216 | ||
|
|
f2b8f2f98d | ||
|
|
2c5fd87a2a | ||
|
|
39768f7f04 | ||
|
|
cc3e1ced15 | ||
|
|
2e26cc104e | ||
|
|
42fd0926ef | ||
| ec202aa9a7 | |||
|
|
1fb56c8777 | ||
|
|
a5d4a37da8 | ||
|
|
4804a48549 | ||
|
|
c892a845b4 | ||
|
|
e98064b6a5 | ||
| 57f5f6ed5b | |||
| 79f5b8b7e8 |
6
.github/dependabot.yml
vendored
@@ -1,6 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "gradle"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "monthly"
|
|
||||||
65
.github/workflows/main.yml
vendored
@@ -1,65 +0,0 @@
|
|||||||
name: Build & Test
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
push:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
jobs:
|
|
||||||
Build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out source code
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install Java Development Kit 1.8
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: 1.8
|
|
||||||
|
|
||||||
- name: Build Project
|
|
||||||
run: ./build.sh build
|
|
||||||
|
|
||||||
- name: Upload Build Artifacts
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: uhabits-android
|
|
||||||
path: uhabits-android/build/outputs/
|
|
||||||
|
|
||||||
AndroidTest:
|
|
||||||
needs: Build
|
|
||||||
runs-on: macOS-10.15
|
|
||||||
timeout-minutes: 60
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
api: [
|
|
||||||
23,
|
|
||||||
24,
|
|
||||||
25,
|
|
||||||
26,
|
|
||||||
27,
|
|
||||||
28,
|
|
||||||
# 29, # Crashes constantly, see: https://issuetracker.google.com/issues/159732638
|
|
||||||
# 30, # Not available yet
|
|
||||||
# 31, # Not available yet
|
|
||||||
]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out source code
|
|
||||||
uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Download Previously Built APK
|
|
||||||
uses: actions/download-artifact@v2
|
|
||||||
with:
|
|
||||||
name: uhabits-android
|
|
||||||
path: uhabits-android/build/outputs/
|
|
||||||
|
|
||||||
- name: Install flock
|
|
||||||
run: |
|
|
||||||
brew install util-linux
|
|
||||||
echo "/usr/local/opt/util-linux/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Run Android Tests
|
|
||||||
run: ./build.sh android-tests ${{ matrix.api }}
|
|
||||||
|
|
||||||
6
.gitignore
vendored
@@ -12,13 +12,9 @@
|
|||||||
.idea
|
.idea
|
||||||
.secret
|
.secret
|
||||||
build
|
build
|
||||||
build/
|
|
||||||
captures
|
|
||||||
local.properties
|
local.properties
|
||||||
node_modules
|
node_modules
|
||||||
*xcuserdata*
|
*xcuserdata*
|
||||||
*.sketch
|
*.sketch
|
||||||
/design
|
|
||||||
/releases
|
|
||||||
/screenshots
|
|
||||||
crowdin.yml
|
crowdin.yml
|
||||||
|
kotlin-js-store
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
if [ -z "$GPG_PASSWORD" ]; then
|
|
||||||
echo Env variable GPG_PASSWORD must be defined
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
gpg \
|
|
||||||
--quiet \
|
|
||||||
--batch \
|
|
||||||
--yes \
|
|
||||||
--decrypt \
|
|
||||||
--passphrase="$GPG_PASSWORD" \
|
|
||||||
--output secret.tar.gz \
|
|
||||||
secret
|
|
||||||
tar -xzf secret.tar.gz
|
|
||||||
rm secret.tar.gz
|
|
||||||
BIN
.secret/secret
143
CHANGELOG.md
@@ -1,7 +1,131 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [2.0.3] - 2021-08-21
|
## [2.3.1] -- 2025-08-13
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add notes to exported CSV files (@iSoron)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Prevent some views from being obscured by system UI (@iSoron, #2171)
|
||||||
|
- Disable confetti if animations are disabled globally (@iSoron, #2170)
|
||||||
|
- Make symbols easier to distinguish in "pure black" dark mode (powerjungle, #2136)
|
||||||
|
- Trim unit labels when necessary (@hiqua, @iSoron, #2158)
|
||||||
|
|
||||||
|
## [2.3.0] -- 2025-06-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add support for Android 15 and 16 (@iSoron)
|
||||||
|
- Show confetti animation (@gokulk16, @iSoron, #1743)
|
||||||
|
- Show streaks for measurable habits (@teckwarz, #2059)
|
||||||
|
- Allow user to unset measurable habits (@leontodd, @kalina559, #1899, #2109)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Change background widget color for habits with implicit checks (@wobbba, #1915)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix notification when goal type is set to maximum (@manish99verma, #1931)
|
||||||
|
- Never mark "at most" habits as completed for the day (@kalina559, #2077)
|
||||||
|
- Increase minimum widget size (@iSoron, #2118)
|
||||||
|
- Improve Gradle configuration (@jimlyas, #2108)
|
||||||
|
|
||||||
|
## [2.2.0] -- 2024-01-30
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add support for Android 14 (@iSoron, @hiqua)
|
||||||
|
- Allow user to change app language (@leondzn)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Implement workaround to make notifications non-dismissible in Android 14 (@iSoron, #1872)
|
||||||
|
- Fix splash screen background color in dark mode (@SIKV, #1888)
|
||||||
|
|
||||||
|
## [2.1.3] -- 2023-08-28
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Use text input on Samsung devices (@iSoron, #1719)
|
||||||
|
- Prevent crash if alarm permission is revoked (@iSoron)
|
||||||
|
- Adjust widget colors (@iSoron)
|
||||||
|
- Fix bug preventing screens from updating at midnight (@iSoron)
|
||||||
|
- Fix skip button in locales that use comma instead of dot (@iSoron, #1721)
|
||||||
|
|
||||||
|
## [2.1.2] -- 2023-05-26
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix bug that caused widget to enter checkmark on wrong date (@iSoron, #1541)
|
||||||
|
- Fix widget corners on Android 12 (@iSoron)
|
||||||
|
- Fix bug that caused notes to be lost when editing a checkmark (@iSoron, #1566)
|
||||||
|
- Prevent soft keyboard from covering entry popup (@iSoron)
|
||||||
|
- Accept comma (instead of dot) in certain locales (@iSoron)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Remove update delay after entering a checkmark (@iSoron)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Remove stack widgets (@iSoron)
|
||||||
|
|
||||||
|
## [2.1.1] -- 2022-09-24
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix Tasker plugin (@iSoron, #1503)
|
||||||
|
|
||||||
|
## [2.1.0] -- 2022-09-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Allow user to add notes to specific dates (@vbh, #1103)
|
||||||
|
- Allow user to track "at most" numerical habits (@KristianTashkov, #1101)
|
||||||
|
- Allow user to add skips to measurable habits (@kalina559, #1319)
|
||||||
|
- Bring back custom frequencies (x times in y days) (@hiqua, #1079)
|
||||||
|
- Improve number picker (@hiqua, @iSoron, #1082, #1370)
|
||||||
|
- Add new checkmark and number picker (@iSoron, #1370)
|
||||||
|
- Allow user to import numerical habits from HabitBull (@hiqua, #1278)
|
||||||
|
- Add support for Android 13 themed icons (@cheeeeer, #1497)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Hide snooze button Android 12 notifications (@hiqua, #1226)
|
||||||
|
- Remove preference to set LED lights (@iSoron)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Hide failed habits along with completed ones (@hiqua, #1052)
|
||||||
|
- Cycle through all checkmark states when toggling (@iSoron)
|
||||||
|
- Add delay after toggling a habit (@hiqua, @kalina559, #1147)
|
||||||
|
- Small theme improvements (@KristianTashkov, #1113)
|
||||||
|
- Left-align habit notes (@iSoron)
|
||||||
|
- Increase target SDK to 31 (@hiqua)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix small dialog buttons (@kalina559, #1096)
|
||||||
|
- Fix invalid CSV files (@hiqua, #1177)
|
||||||
|
- Fix small issues in calendar chart (@kalina559, #1314)
|
||||||
|
- Resort habit list after edit (@hiqua, #1350)
|
||||||
|
- Fix marker scaling in frequency display (@eduebernal, #1425)
|
||||||
|
- Fix widgets not working correctly on API 33 (@iSoron, #1488)
|
||||||
|
|
||||||
|
### Refactoring & Testing
|
||||||
|
|
||||||
|
- Replace raster icons by vector assets (@kalina559)
|
||||||
|
- Remove JVM dependencies from uhabits-core module (@sgallese)
|
||||||
|
- Add various missing tests (@sgallese)
|
||||||
|
- Upgrade project dependencies (@hiqua, @sgallese)
|
||||||
|
|
||||||
|
## [2.0.3] - 2021-08-21
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
- Improve automatic checkmarks for monthly habits (@iSoron, #947)
|
- Improve automatic checkmarks for monthly habits (@iSoron, #947)
|
||||||
- Fix small theme issues (@iSoron)
|
- Fix small theme issues (@iSoron)
|
||||||
- Fix ANR on some Samsung phones (@iSoron, #962)
|
- Fix ANR on some Samsung phones (@iSoron, #962)
|
||||||
@@ -13,9 +137,11 @@
|
|||||||
## [2.0.2] - 2021-05-23
|
## [2.0.2] - 2021-05-23
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Make checkmark widget resizable
|
- Make checkmark widget resizable
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix crash caused by numerical habits with zero target (@iSoron, #903)
|
- Fix crash caused by numerical habits with zero target (@iSoron, #903)
|
||||||
- Fix small issues with font size (@iSoron)
|
- Fix small issues with font size (@iSoron)
|
||||||
- Allow fractional target values (@sumanabhi, #911)
|
- Allow fractional target values (@sumanabhi, #911)
|
||||||
@@ -26,18 +152,22 @@
|
|||||||
## [2.0.1] - 2021-05-09
|
## [2.0.1] - 2021-05-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Make midnight delay optional and disabled by default (@hiqua)
|
- Make midnight delay optional and disabled by default (@hiqua)
|
||||||
- Add arrows to sort menu (@iSoron)
|
- Add arrows to sort menu (@iSoron)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Temporarily remove experimental device sync functionality. This feature will be re-added in
|
- Temporarily remove experimental device sync functionality. This feature will be re-added in
|
||||||
Loop 2.1.
|
Loop 2.1.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Make implicit checkmarks easier to read (@iSoron)
|
- Make implicit checkmarks easier to read (@iSoron)
|
||||||
- Update and improve list of translators (@hiqua, @iSoron)
|
- Update and improve list of translators (@hiqua, @iSoron)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Disable transparency for stacked widgets (@hiqua)
|
- Disable transparency for stacked widgets (@hiqua)
|
||||||
- Fix various color issues on the dark theme (@hiqua, @iSoron)
|
- Fix various color issues on the dark theme (@hiqua, @iSoron)
|
||||||
- Fix "customize notifications" on older devices (@hiqua)
|
- Fix "customize notifications" on older devices (@hiqua)
|
||||||
@@ -46,6 +176,7 @@
|
|||||||
- Fix checkmark widget not rendering properly on some Samsung phones (@iSoron)
|
- Fix checkmark widget not rendering properly on some Samsung phones (@iSoron)
|
||||||
|
|
||||||
### Refactoring & Testing
|
### Refactoring & Testing
|
||||||
|
|
||||||
- Finish conversion of the entire project to Kotlin (@hiqua, @iSoron, @MarKco)
|
- Finish conversion of the entire project to Kotlin (@hiqua, @iSoron, @MarKco)
|
||||||
- Automatically run large tests on GitHub Actions (@iSoron)
|
- Automatically run large tests on GitHub Actions (@iSoron)
|
||||||
- Remove unused v21 resources (@hiqua)
|
- Remove unused v21 resources (@hiqua)
|
||||||
@@ -53,6 +184,7 @@
|
|||||||
## [2.0.0-alpha] - 2020-11-29
|
## [2.0.0-alpha] - 2020-11-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Track numeric habits (@iSoron, @namnl)
|
- Track numeric habits (@iSoron, @namnl)
|
||||||
- Skip days without breaking streak (@KristianTashkov)
|
- Skip days without breaking streak (@KristianTashkov)
|
||||||
- Sort habits by status (@hiqua)
|
- Sort habits by status (@hiqua)
|
||||||
@@ -63,15 +195,18 @@
|
|||||||
- Export backups daily (@iSoron)
|
- Export backups daily (@iSoron)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Drop support to devices older than Android 6.0 (API 23)
|
- Drop support to devices older than Android 6.0 (API 23)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Reset chart offset when switching scale (@alxmjo)
|
- Reset chart offset when switching scale (@alxmjo)
|
||||||
- Don't show reminders from archived habits (@KristianTashkov)
|
- Don't show reminders from archived habits (@KristianTashkov)
|
||||||
- Lapses on non-daily habits decrease the score too much (@iSoron)
|
- Lapses on non-daily habits decrease the score too much (@iSoron)
|
||||||
- Update widgets at midnight (@KristianTashkov)
|
- Update widgets at midnight (@KristianTashkov)
|
||||||
|
|
||||||
### Refactoring
|
### Refactoring
|
||||||
|
|
||||||
- Convert files to Kotlin (@olegivo)
|
- Convert files to Kotlin (@olegivo)
|
||||||
|
|
||||||
## [1.8.12] - 2021-01-30
|
## [1.8.12] - 2021-01-30
|
||||||
@@ -96,13 +231,15 @@
|
|||||||
|
|
||||||
## [1.8.8] - 2020-06-21
|
## [1.8.8] - 2020-06-21
|
||||||
|
|
||||||
- Make small changes to the habit scheduling algorithm, so that "1 time every x days" habits work more predictably.
|
- Make small changes to the habit scheduling algorithm, so that "1 time every x days" habits work
|
||||||
|
more predictably.
|
||||||
- Fix crash when saving habit
|
- Fix crash when saving habit
|
||||||
|
|
||||||
## [1.8.0] - 2020-01-01
|
## [1.8.0] - 2020-01-01
|
||||||
|
|
||||||
- New bar chart showing number of repetitions performed in each week, month, quarter or year.
|
- New bar chart showing number of repetitions performed in each week, month, quarter or year.
|
||||||
- Improved calculation of streaks for non-daily habits: performing habits on irregular weekdays will no longer break your streak.
|
- Improved calculation of streaks for non-daily habits: performing habits on irregular weekdays will
|
||||||
|
no longer break your streak.
|
||||||
- Many more colors to choose from (now 20 in total).
|
- Many more colors to choose from (now 20 in total).
|
||||||
- Ability to customize how transparent the widgets are on your home screen.
|
- Ability to customize how transparent the widgets are on your home screen.
|
||||||
- Ability to customize the first day of the week.
|
- Ability to customize the first day of the week.
|
||||||
|
|||||||
24
NOTICE.md
@@ -1,6 +1,6 @@
|
|||||||
# Copyright Notices
|
# Copyright Notices
|
||||||
|
|
||||||
### ActiveAndroid
|
## ActiveAndroid
|
||||||
|
|
||||||
<https://github.com/pardom/ActiveAndroid>
|
<https://github.com/pardom/ActiveAndroid>
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
### Android Open Source Project
|
## Android Open Source Project
|
||||||
|
|
||||||
<https://source.android.com/>
|
<https://source.android.com/>
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
### FontAwesome
|
## FontAwesome
|
||||||
|
|
||||||
<http://fontawesome.io>
|
<http://fontawesome.io>
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ under the SIL OFL 1.1.
|
|||||||
requirement for fonts to remain under this license does not apply
|
requirement for fonts to remain under this license does not apply
|
||||||
to any document created using the fonts or their derivatives.
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
### Material Design Icons
|
## Material Design Icons
|
||||||
|
|
||||||
<https://github.com/google/material-design-icons>
|
<https://github.com/google/material-design-icons>
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ Material design icons are the official icon set from Google that are designed
|
|||||||
under the material design guidelines. Available under the Creative Common
|
under the material design guidelines. Available under the Creative Common
|
||||||
Attribution 4.0 International License (CC-BY 4.0).
|
Attribution 4.0 International License (CC-BY 4.0).
|
||||||
|
|
||||||
### Android Flow Layout
|
## Android Flow Layout
|
||||||
|
|
||||||
<https://github.com/ApmeM/android-flowlayout>
|
<https://github.com/ApmeM/android-flowlayout>
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ Extended linear layout that wrap its content when there is no place in the curre
|
|||||||
License for the specific language governing permissions and limitations
|
License for the specific language governing permissions and limitations
|
||||||
under the License.
|
under the License.
|
||||||
|
|
||||||
### Dagger 2
|
## Dagger 2
|
||||||
|
|
||||||
<https://github.com/google/dagger>
|
<https://github.com/google/dagger>
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ A fast dependency injector for Android and Java.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
### AutoFactory
|
## AutoFactory
|
||||||
|
|
||||||
<https://github.com/google/auto/tree/master/factory>
|
<https://github.com/google/auto/tree/master/factory>
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ A source code generator for JSR-330-compatible factories.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
### Retrolambda
|
## Retrolambda
|
||||||
|
|
||||||
<https://github.com/orfjackal/retrolambda>
|
<https://github.com/orfjackal/retrolambda>
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ Backport of Java 8's lambda expressions to Java 7, 6 and 5
|
|||||||
This software is released under the Apache License 2.0.
|
This software is released under the Apache License 2.0.
|
||||||
The license text is at http://www.apache.org/licenses/LICENSE-2.0
|
The license text is at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
### PebbleKit SDK
|
## PebbleKit SDK
|
||||||
|
|
||||||
<https://github.com/pebble/pebble-android-sdk/>
|
<https://github.com/pebble/pebble-android-sdk/>
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ Android PebbleKit SDK to talk to the Pebble via Bluetooth
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
Copyright (c) 2014 - 2015 Pebble Technology
|
Copyright (c) 2014 - 2015 Pebble Technology
|
||||||
|
|
||||||
### AppIntro
|
## AppIntro
|
||||||
|
|
||||||
<https://github.com/PaoloRotolo/AppIntro>
|
<https://github.com/PaoloRotolo/AppIntro>
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ Make a cool intro for your Android app.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
### ButterKnife
|
## ButterKnife
|
||||||
|
|
||||||
<https://github.com/JakeWharton/butterknife>
|
<https://github.com/JakeWharton/butterknife>
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ Bind Android views and callbacks to fields and methods
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
### opencsv
|
## opencsv
|
||||||
|
|
||||||
<http://opencsv.sourceforge.net/>
|
<http://opencsv.sourceforge.net/>
|
||||||
|
|
||||||
|
|||||||
44
README.md
@@ -1,13 +1,10 @@
|
|||||||
<h1 align="center">Loop Habit Tracker</h1>
|
<h1 align="center">Loop Habit Tracker</h1>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/iSoron/uhabits/actions?query=workflow%3A%22Build+%26+Test%22">
|
|
||||||
<img src="https://github.com/iSoron/uhabits/workflows/Build%20&%20Test/badge.svg" />
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/iSoron/uhabits/releases/latest">
|
<a href="https://github.com/iSoron/uhabits/releases/latest">
|
||||||
<img src="https://img.shields.io/github/v/release/iSoron/uhabits" />
|
<img alt="release" src="https://img.shields.io/github/v/release/iSoron/uhabits" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/iSoron/uhabits/discussions">
|
<a href="https://github.com/iSoron/uhabits/discussions">
|
||||||
<img src="https://img.shields.io/badge/GitHub-Discussions-%23fc4ebc" />
|
<img alt="GitHub" src="https://img.shields.io/badge/GitHub-Discussions-%23fc4ebc" />
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -17,8 +14,8 @@ show you how your habits improved over time. It is completely ad-free and open
|
|||||||
source.
|
source.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://play.google.com/store/apps/details?id=org.isoron.uhabits&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-AC-global-none-all-co-pr-py-PartBadges-Oct1515-1"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/apps/en-play-badge-border.png" height="75px"/></a>
|
<a href="https://play.google.com/store/apps/details?id=org.isoron.uhabits&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-AC-global-none-all-co-pr-py-PartBadges-Oct1515-1"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" height="80px"/></a>
|
||||||
<a href="https://f-droid.org/app/org.isoron.uhabits"><img alt="Get it on F-Droid" src="https://i.imgur.com/baSPE7X.png" height="75px"/></a>
|
<a href="https://f-droid.org/app/org.isoron.uhabits"><img alt="Get it on F-Droid" src="https://f-droid.org/badge/get-it-on.png" height="80px"/></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
@@ -32,32 +29,23 @@ source.
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* <b>Beautiful, minimalistic and lightweight interface.</b>
|
* **Beautiful, minimalistic and lightweight interface.** Loop has an elegant and minimalistic interface that is very easy to use, even for first-time users. Highly optimized for speed, the app works well even on older phones.
|
||||||
Loop has an elegant and minimalistic interface that is very easy to use, even for first-time users. Highly optimized for speed, the app works well even on older phones.
|
|
||||||
|
|
||||||
* <b>Habit score.</b>
|
* **Habit score.** Loop has an advanced formula for calculating the strength of your habits. Every repetition makes your habit stronger and every missed day makes it weaker. A few missed days after a long streak, however, will not completely destroy your progress, unlike many other don't-break-the-chain apps.
|
||||||
Loop has an advanced formula for calculating the strength of your habits. Every repetition makes your habit stronger and every missed day makes it weaker. A few missed days after a long streak, however, will not completely destroy your progress, unlike many other don't-break-the-chain apps.
|
|
||||||
|
|
||||||
* <b>Flexible schedules.</b>
|
* **Flexible schedules.** In addition to daily habits, Loop supports habits with more complex schedules, such as 3 times per week or every other day.
|
||||||
In addition to daily habits, Loop supports habits with more complex schedules, such as 3 times per week or every other day.
|
|
||||||
|
|
||||||
* <b>Reminders.</b>
|
* **Reminders.** Schedule notifications to remind you of your habits. Each habit can have its own reminder, at a chosen time of the day. Easily check or dismiss your habit directly from the notification.
|
||||||
Schedule notifications to remind you of your habits. Each habit can have its own reminder, at a chosen time of the day. Easily check or dismiss your habit directly from the notification.
|
|
||||||
|
|
||||||
* <b>Widgets.</b>
|
* **Widgets.** Be reminded of your habits whenever you unlock your phone. Colorful widgets allow you to track your habits directly from your home screen, without even opening the app.
|
||||||
Be reminded of your habits whenever you unlock your phone. Colorful widgets allow you to track your habits directly from your home screen, without even opening the app.
|
|
||||||
|
|
||||||
* <b>Take control of your data.</b>
|
* **Take control of your data.** If you want to further analyze your data, or move it to another service, Loop allows you to export it to spreadsheets (CSV) or to a database file (SQLite). For power users, checkmarks can be added through other apps, such as Tasker.
|
||||||
If you want to further analyze your data, or move it to another service, Loop allows you to export it to spreadsheets (CSV) or to a database file (SQLite). For power users, checkmarks can be added through other apps, such as Tasker.
|
|
||||||
|
|
||||||
* <b>No limitations.</b>
|
* **No limitations.** Track as many habits as you wish. Loop imposes no artificial limits on how many habits you can have. All features are available to all users. There are no in-app purchases.
|
||||||
Track as many habits as you wish. Loop imposes no artificial limits on how many habits you can have. All features are available to all users. There are no in-app purchases.
|
|
||||||
|
|
||||||
* <b>Completely ad-free and open source.</b>
|
* **Completely ad-free and open source.** There are no advertisements, annoying notifications or intrusive permissions in this app, and there will never be. The app is completely open-source (GPLv3).
|
||||||
There are no advertisements, annoying notifications or intrusive permissions in this app, and there will never be. The app is completely open-source (GPLv3).
|
|
||||||
|
|
||||||
* <b>Works offline and respects your privacy.</b>
|
* **Works offline and respects your privacy.** Loop doesn't require an Internet connection or online account registration. Your confidential data is never sent to anyone. Neither the developers nor any third-parties have access to it.
|
||||||
Loop doesn't require an Internet connection or online account registration. Your confidential data is never sent to anyone. Neither the developers nor any third-parties have access to it.
|
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
@@ -90,13 +78,13 @@ contribute, even if you are not a software developer.
|
|||||||
is already completed, you are also very welcome to join and proofread it.
|
is already completed, you are also very welcome to join and proofread it.
|
||||||
|
|
||||||
* **Write some code.** If you are an Android developer, you are very welcome to
|
* **Write some code.** If you are an Android developer, you are very welcome to
|
||||||
contribute with code. Please see `docs/GUIDELINES.md`.
|
contribute with code. Please see the [guidelines](https://github.com/iSoron/uhabits/blob/dev/docs/GUIDELINES.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
<img align="right" src="https://www.gnu.org/graphics/gplv3-88x31.png">
|
<img align="right" alt="GPL v3" src="https://www.gnu.org/graphics/gplv3-88x31.png">
|
||||||
|
|
||||||
Copyright (C) 2016-2021 Álinson Santos Xavier <isoron@gmail.com>
|
Copyright (C) 2016-2025 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
|
||||||
Loop Habit Tracker is free software: you can redistribute it and/or modify
|
Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by the
|
it under the terms of the GNU General Public License as published by the
|
||||||
|
|||||||
@@ -1,25 +1,11 @@
|
|||||||
plugins {
|
plugins {
|
||||||
val kotlinVersion = "1.5.0"
|
alias(libs.plugins.agp) apply false
|
||||||
id("com.android.application") version ("4.2.0") apply (false)
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
id("org.jetbrains.kotlin.android") version kotlinVersion apply (false)
|
alias(libs.plugins.ksp) apply false
|
||||||
id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false)
|
alias(libs.plugins.ktlint.plugin) apply false
|
||||||
id("org.jetbrains.kotlin.android.extensions") version kotlinVersion apply (false)
|
alias(libs.plugins.shadow) apply false
|
||||||
id("org.jetbrains.kotlin.multiplatform") version kotlinVersion apply (false)
|
|
||||||
id("org.jlleitschuh.gradle.ktlint") version "10.1.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
from("translators.gradle.kts")
|
from("gradle/translators.gradle.kts")
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
jcenter()
|
|
||||||
mavenCentral()
|
|
||||||
maven(url = "https://plugins.gradle.org/m2/")
|
|
||||||
maven(url = "https://oss.sonatype.org/content/repositories/snapshots/")
|
|
||||||
maven(url = "https://kotlin.bintray.com/ktor")
|
|
||||||
maven(url = "https://kotlin.bintray.com/kotlin-js-wrappers")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
149
build.sh
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Copyright (C) 2016-2021 Álinson Santos Xavier <isoron@gmail.com>
|
# Copyright (C) 2016-2025 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
# This file is part of Loop Habit Tracker.
|
# This file is part of Loop Habit Tracker.
|
||||||
#
|
#
|
||||||
# Loop Habit Tracker is free software: you can redistribute it and/or modify
|
# Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
@@ -21,11 +21,12 @@ ADB="${ANDROID_HOME}/platform-tools/adb"
|
|||||||
ANDROID_OUTPUTS_DIR="uhabits-android/build/outputs"
|
ANDROID_OUTPUTS_DIR="uhabits-android/build/outputs"
|
||||||
AVDMANAGER="${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager"
|
AVDMANAGER="${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager"
|
||||||
AVD_PREFIX="uhabitsTest"
|
AVD_PREFIX="uhabitsTest"
|
||||||
EMULATOR="${ANDROID_HOME}/tools/emulator"
|
EMULATOR="${ANDROID_HOME}/emulator/emulator"
|
||||||
GRADLE="./gradlew --stacktrace --quiet"
|
GRADLE="./gradlew --stacktrace --quiet"
|
||||||
PACKAGE_NAME=org.isoron.uhabits
|
PACKAGE_NAME=org.isoron.uhabits
|
||||||
SDKMANAGER="${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager"
|
SDKMANAGER="${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager"
|
||||||
VERSION=$(grep versionName uhabits-android/build.gradle.kts | sed -e 's/.*"\([^"]*\)".*/\1/g')
|
VERSION=$(grep versionName uhabits-android/build.gradle.kts | sed -e 's/.*"\([^"]*\)".*/\1/g')
|
||||||
|
BOOT_TIMEOUT=360
|
||||||
|
|
||||||
if [ -z $VERSION ]; then
|
if [ -z $VERSION ]; then
|
||||||
echo "Could not parse app version from: uhabits-android/build.gradle.kts"
|
echo "Could not parse app version from: uhabits-android/build.gradle.kts"
|
||||||
@@ -37,6 +38,11 @@ if [ ! -f "${ANDROID_HOME}/platform-tools/adb" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$EMULATOR" ]; then
|
||||||
|
echo "Error: Not found: $EMULATOR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -63,14 +69,14 @@ fail() {
|
|||||||
core_build() {
|
core_build() {
|
||||||
log_info "Building uhabits-core..."
|
log_info "Building uhabits-core..."
|
||||||
$GRADLE ktlintCheck || fail
|
$GRADLE ktlintCheck || fail
|
||||||
|
$GRADLE lintDebug || fail
|
||||||
$GRADLE :uhabits-core:build || fail
|
$GRADLE :uhabits-core:build || fail
|
||||||
}
|
}
|
||||||
|
|
||||||
# Android
|
# Android
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
# shellcheck disable=SC2016
|
android_setup() {
|
||||||
android_test() {
|
|
||||||
API=$1
|
API=$1
|
||||||
AVDNAME=${AVD_PREFIX}${API}
|
AVDNAME=${AVD_PREFIX}${API}
|
||||||
|
|
||||||
@@ -85,25 +91,63 @@ android_test() {
|
|||||||
$AVDMANAGER delete avd --name $AVDNAME
|
$AVDMANAGER delete avd --name $AVDNAME
|
||||||
|
|
||||||
log_info "Creating new Android virtual device (API $API)..."
|
log_info "Creating new Android virtual device (API $API)..."
|
||||||
(echo "y" | $SDKMANAGER --install "system-images;android-$API;default;x86_64") || return 1
|
(echo "y" | $SDKMANAGER --install "system-images;android-$API;google_apis;x86_64") || return 1
|
||||||
$AVDMANAGER create avd \
|
$AVDMANAGER create avd \
|
||||||
--name $AVDNAME \
|
--name $AVDNAME \
|
||||||
--package "system-images;android-$API;default;x86_64" \
|
--package "system-images;android-$API;google_apis;x86_64" \
|
||||||
--device "Nexus 4" || return 1
|
--device "Nexus 4" || return 1
|
||||||
|
|
||||||
flock -u 10
|
flock -u 10
|
||||||
) 10>/tmp/uhabitsTest.lock
|
) 10>/tmp/uhabitsTest.lock
|
||||||
|
|
||||||
log_info "Launching emulator..."
|
log_info "Launching emulator..."
|
||||||
$EMULATOR -avd $AVDNAME -port 6${API}0 1>/dev/null 2>&1 &
|
$EMULATOR \
|
||||||
|
-avd $AVDNAME \
|
||||||
|
-port 6${API}0 \
|
||||||
|
1>/dev/null 2>&1 &
|
||||||
|
|
||||||
|
log_info "Waiting for emulator to boot..."
|
||||||
|
export ADB="$ADB -s emulator-6${API}0"
|
||||||
|
timeout $BOOT_TIMEOUT $ADB wait-for-device shell 'while [[ -z "$(getprop sys.boot_completed)" ]]; do echo Waiting...; sleep 1; done; input keyevent 82'
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
log_error "Emulator failed to boot after $BOOT_TIMEOUT seconds."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Saving snapshot..."
|
||||||
|
$ADB emu avd snapshot save fresh-install
|
||||||
|
}
|
||||||
|
|
||||||
|
android_boot_attempt() {
|
||||||
|
API=$1
|
||||||
|
AVDNAME=${AVD_PREFIX}${API}
|
||||||
|
|
||||||
|
log_info "Stopping Android emulator..."
|
||||||
|
while [[ -n $(pgrep -f ${AVDNAME}) ]]; do
|
||||||
|
pkill -9 -f ${AVDNAME}
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "Launching emulator..."
|
||||||
|
$EMULATOR \
|
||||||
|
-avd $AVDNAME \
|
||||||
|
-port 6${API}0 \
|
||||||
|
-snapshot fresh-install \
|
||||||
|
-no-snapshot-save \
|
||||||
|
-wipe-data \
|
||||||
|
1>/dev/null 2>&1 &
|
||||||
|
|
||||||
log_info "Waiting for emulator to boot..."
|
log_info "Waiting for emulator to boot..."
|
||||||
export ADB="$ADB -s emulator-6${API}0"
|
export ADB="$ADB -s emulator-6${API}0"
|
||||||
$ADB wait-for-device shell 'while [[ -z "$(getprop sys.boot_completed)" ]]; do echo Waiting...; sleep 1; done; input keyevent 82' || return 1
|
|
||||||
$ADB root || return 1
|
|
||||||
sleep 5
|
sleep 5
|
||||||
|
timeout $BOOT_TIMEOUT $ADB wait-for-device shell 'while [[ -z "$(getprop sys.boot_completed)" ]]; do echo Waiting...; sleep 1; done; input keyevent 82'
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
log_error "Emulator failed to boot after $BOOT_TIMEOUT seconds."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
log_info "Disabling animations..."
|
log_info "Disabling animations..."
|
||||||
|
$ADB root || return 1
|
||||||
|
sleep 5
|
||||||
$ADB shell settings put global window_animation_scale 0 || return 1
|
$ADB shell settings put global window_animation_scale 0 || return 1
|
||||||
$ADB shell settings put global transition_animation_scale 0 || return 1
|
$ADB shell settings put global transition_animation_scale 0 || return 1
|
||||||
$ADB shell settings put global animator_duration_scale 0 || return 1
|
$ADB shell settings put global animator_duration_scale 0 || return 1
|
||||||
@@ -111,6 +155,24 @@ android_test() {
|
|||||||
log_info "Acquiring wake lock..."
|
log_info "Acquiring wake lock..."
|
||||||
$ADB shell 'echo android-test > /sys/power/wake_lock' || return 1
|
$ADB shell 'echo android-test > /sys/power/wake_lock' || return 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
android_boot() {
|
||||||
|
for attempt in {1..5}; do
|
||||||
|
android_boot_attempt $1 && return 0
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
log_error "Too many failed attempts. Aborting."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
android_test() {
|
||||||
|
API=$1
|
||||||
|
AVDNAME=${AVD_PREFIX}${API}
|
||||||
|
|
||||||
|
android_boot $API || return 1
|
||||||
|
|
||||||
if [ -n "$RELEASE" ]; then
|
if [ -n "$RELEASE" ]; then
|
||||||
log_info "Installing release APK..."
|
log_info "Installing release APK..."
|
||||||
$ADB install -r ${ANDROID_OUTPUTS_DIR}/apk/release/uhabits-android-release.apk || return 1
|
$ADB install -r ${ANDROID_OUTPUTS_DIR}/apk/release/uhabits-android-release.apk || return 1
|
||||||
@@ -122,14 +184,25 @@ android_test() {
|
|||||||
$ADB install -r ${ANDROID_OUTPUTS_DIR}/apk/androidTest/debug/uhabits-android-debug-androidTest.apk || return 1
|
$ADB install -r ${ANDROID_OUTPUTS_DIR}/apk/androidTest/debug/uhabits-android-debug-androidTest.apk || return 1
|
||||||
|
|
||||||
for size in medium large; do
|
for size in medium large; do
|
||||||
log_info "Running $size instrumented tests..."
|
|
||||||
OUT_INSTRUMENT=${ANDROID_OUTPUTS_DIR}/instrument-${API}.txt
|
OUT_INSTRUMENT=${ANDROID_OUTPUTS_DIR}/instrument-${API}.txt
|
||||||
OUT_LOGCAT=${ANDROID_OUTPUTS_DIR}/logcat-${API}.txt
|
OUT_LOGCAT=${ANDROID_OUTPUTS_DIR}/logcat-${API}.txt
|
||||||
$ADB shell am instrument \
|
FAILED_TESTS=""
|
||||||
-r -e coverage true -e size $size \
|
for i in {1..10}; do
|
||||||
-w ${PACKAGE_NAME}.test/androidx.test.runner.AndroidJUnitRunner \
|
log_info "Running $size instrumented tests (attempt $i)..."
|
||||||
| tee $OUT_INSTRUMENT
|
$ADB shell am instrument \
|
||||||
if grep "\(INSTRUMENTATION_STATUS_CODE.*-1\|FAILURES\|ABORTED\|onError\|Error type\|crashed\)" $OUT_INSTRUMENT; then
|
-r -e coverage true -e size "$size" $FAILED_TESTS \
|
||||||
|
-w ${PACKAGE_NAME}.test/androidx.test.runner.AndroidJUnitRunner \
|
||||||
|
| ts "%.s" | tee "$OUT_INSTRUMENT"
|
||||||
|
|
||||||
|
FAILED_TESTS=$(tools/parseInstrument.py "$OUT_INSTRUMENT")
|
||||||
|
SUCCESS=$?
|
||||||
|
if [ $SUCCESS -eq 0 ]; then
|
||||||
|
log_info "$size tests passed."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $SUCCESS -ne 0 ]; then
|
||||||
log_error "Some $size instrumented tests failed."
|
log_error "Some $size instrumented tests failed."
|
||||||
log_error "Saving logcat: $OUT_LOGCAT..."
|
log_error "Saving logcat: $OUT_LOGCAT..."
|
||||||
$ADB logcat -d > $OUT_LOGCAT
|
$ADB logcat -d > $OUT_LOGCAT
|
||||||
@@ -138,26 +211,51 @@ android_test() {
|
|||||||
$ADB shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/
|
$ADB shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
log_info "$size tests passed."
|
|
||||||
done
|
done
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
android_test_parallel() {
|
android_test_parallel() {
|
||||||
|
# Launch background processes
|
||||||
|
PIDS=""
|
||||||
for API in $*; do
|
for API in $*; do
|
||||||
(
|
(
|
||||||
LOG=build/android-test-$API.log
|
LOG=build/android-test-$API.log
|
||||||
|
mkdir -p build
|
||||||
log_info "API $API: Running tests..."
|
log_info "API $API: Running tests..."
|
||||||
if android_test $API 1>$LOG 2>&1; then
|
android_test $API 1>$LOG 2>&1
|
||||||
|
ret_code=$?
|
||||||
|
if [ $ret_code = 0 ]; then
|
||||||
log_info "API $API: Passed"
|
log_info "API $API: Passed"
|
||||||
else
|
else
|
||||||
log_error "API $API: Failed. See $LOG for more details."
|
log_error "API $API: Failed"
|
||||||
fi
|
fi
|
||||||
pkill -9 -f ${AVD_PREFIX}${API}
|
pkill -9 -f ${AVD_PREFIX}${API}
|
||||||
|
exit $ret_code
|
||||||
)&
|
)&
|
||||||
|
PIDS+=" $!"
|
||||||
done
|
done
|
||||||
wait
|
|
||||||
|
# Check exit codes
|
||||||
|
success=0
|
||||||
|
for pid in $PIDS; do
|
||||||
|
wait $pid
|
||||||
|
ret_code=$?
|
||||||
|
if [ $ret_code != 0 ]; then
|
||||||
|
success=1
|
||||||
|
fi
|
||||||
|
echo pid=$pid ret_code=$ret_code success=$success
|
||||||
|
done
|
||||||
|
|
||||||
|
# Print all logs
|
||||||
|
for API in $*; do
|
||||||
|
echo "::group::Android Tests (API $API)"
|
||||||
|
cat build/android-test-$API.log
|
||||||
|
echo "::endgroup::"
|
||||||
|
done
|
||||||
|
|
||||||
|
return $success
|
||||||
}
|
}
|
||||||
|
|
||||||
android_build() {
|
android_build() {
|
||||||
@@ -229,12 +327,14 @@ CI/CD script for Loop Habit Tracker.
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
build.sh build [options]
|
build.sh build [options]
|
||||||
|
build.sh android-setup <API>
|
||||||
build.sh android-tests <API> [options]
|
build.sh android-tests <API> [options]
|
||||||
build.sh android-tests-parallel <API> <API>... [options]
|
build.sh android-tests-parallel <API> <API>... [options]
|
||||||
build.sh android-accept-images [options]
|
build.sh android-accept-images [options]
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
build Build the app and run small tests
|
build Build the app and run small tests
|
||||||
|
android-setup Create Android virtual machine
|
||||||
android-tests Run medium and large Android tests on an emulator
|
android-tests Run medium and large Android tests on an emulator
|
||||||
android-tests-parallel Tests multiple API levels simultaneously
|
android-tests-parallel Tests multiple API levels simultaneously
|
||||||
android-accept-images Copy fetched images to corresponding assets folder
|
android-accept-images Copy fetched images to corresponding assets folder
|
||||||
@@ -270,18 +370,17 @@ main() {
|
|||||||
core_build
|
core_build
|
||||||
android_build
|
android_build
|
||||||
;;
|
;;
|
||||||
|
android-setup)
|
||||||
|
shift; _parse_opts "$@"
|
||||||
|
android_setup $1
|
||||||
|
;;
|
||||||
android-tests)
|
android-tests)
|
||||||
shift; _parse_opts "$@"
|
shift; _parse_opts "$@"
|
||||||
if [ -z $1 ]; then
|
if [ -z $1 ]; then
|
||||||
_print_usage
|
_print_usage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
for attempt in {1..5}; do
|
android_test $1
|
||||||
log_info "Running Android tests (attempt $attempt)..."
|
|
||||||
android_test $1 && return 0
|
|
||||||
done
|
|
||||||
log_error "Maximum number of attempts reached. Failing."
|
|
||||||
return 1
|
|
||||||
;;
|
;;
|
||||||
android-tests-parallel)
|
android-tests-parallel)
|
||||||
shift; _parse_opts "$@"
|
shift; _parse_opts "$@"
|
||||||
|
|||||||
@@ -9,17 +9,17 @@ This pages describes how to download and build the app from the source code. If
|
|||||||
|
|
||||||
## Build using Android Studio
|
## Build using Android Studio
|
||||||
|
|
||||||
**Step 1: Install git**
|
### Step 1: Install git
|
||||||
|
|
||||||
The package `git` is required for downloading the source code of the app and submitting changes GitHub. Please see [the git book](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) for further instructions. If you are planning to submit pull requests in the future, it is recommended to [generate and configure your SSH keys](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
|
The package `git` is required for downloading the source code of the app and submitting changes GitHub. Please see [the git book](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) for further instructions. If you are planning to submit pull requests in the future, it is recommended to [generate and configure your SSH keys](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
|
||||||
|
|
||||||
**Step 2: Download and install Android Studio**
|
### Step 2: Download and install Android Studio
|
||||||
|
|
||||||
Although Android Studio can be downloaded [from their official website](https://developer.android.com/studio/), a much better option is to install it through [JetBrains Toolbox](https://www.jetbrains.com/toolbox-app/). This tool, developed by the same developers of Android Studio, allows you to easily upgrade and downgrade the IDE, or switch between stable, beta and canary versions. After downloading and installing JetBrains Toolbox, simply click the install button near Android Studio to install the newest stable version of IDE. Beta and canary versions have not been tested and may not work correctly.
|
Although Android Studio can be downloaded [from their official website](https://developer.android.com/studio/), a much better option is to install it through [JetBrains Toolbox](https://www.jetbrains.com/toolbox-app/). This tool, developed by the same developers of Android Studio, allows you to easily upgrade and downgrade the IDE, or switch between stable, beta and canary versions. After downloading and installing JetBrains Toolbox, simply click the install button near Android Studio to install the newest stable version of IDE. Beta and canary versions have not been tested and may not work correctly.
|
||||||
|
|
||||||
After installation, launch Android Studio. If this is the first time you launch it, you will need to go through a wizard to setup the IDE. The default options should work fine. The wizard will download all additional components necessary for development, including the emulator, so it may take a while.
|
After installation, launch Android Studio. If this is the first time you launch it, you will need to go through a wizard to setup the IDE. The default options should work fine. The wizard will download all additional components necessary for development, including the emulator, so it may take a while.
|
||||||
|
|
||||||
**Step 3: Download the source code**
|
### Step 3: Download the source code
|
||||||
|
|
||||||
To create a complete copy of the source code repository, open the terminal (Linux/macOS) or Git Bash (Windows), navigate to the desired folder, then run:
|
To create a complete copy of the source code repository, open the terminal (Linux/macOS) or Git Bash (Windows), navigate to the desired folder, then run:
|
||||||
```bash
|
```bash
|
||||||
@@ -27,13 +27,13 @@ git clone https://github.com/iSoron/uhabits.git
|
|||||||
```
|
```
|
||||||
The repository will be downloaded to the directory `uhabits`.
|
The repository will be downloaded to the directory `uhabits`.
|
||||||
|
|
||||||
**Step 4: Open and run the project on Android Studio**
|
### Step 4: Open and run the project on Android Studio
|
||||||
|
|
||||||
1. Launch Android Studio and select "Open an existing Android Studio project".
|
1. Launch Android Studio and select "Open an existing Android Studio project".
|
||||||
2. When the IDE asks you for the project location, select `uhabits` and click "Ok".
|
2. When the IDE asks you for the project location, select `uhabits` and click "Ok".
|
||||||
3. Android Studio will spend some time indexing the project. When this is complete, click the toolbar icon "Sync Project with Gradle File", located near the right corner of the top toolbar.
|
3. Android Studio will spend some time indexing the project. When this is complete, click the toolbar icon "Sync Project with Gradle File", located near the right corner of the top toolbar.
|
||||||
4. The operation will likely fail several times due to missing Android SDK components. Each time it fails, click the link "Install missing platforms", "Install build tools", etc, and try again.
|
4. The operation will likely fail several times due to missing Android SDK components. Each time it fails, click the link "Install missing platforms", "Install build tools", etc, and try again.
|
||||||
5. To test the application, create a virtual Android device using the menu "Tools" and "AVD Manager". The default options should work fine, but free to customize the device.
|
5. To test the application, create a virtual Android device using the menu "Tools" and "AVD Manager". The default options should work fine, but feel free to customize the device.
|
||||||
6. Click the menu "Run" and "uhabits-android". The application should launch.
|
6. Click the menu "Run" and "uhabits-android". The application should launch.
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ The repository will be downloaded to the directory `uhabits`.
|
|||||||
|
|
||||||
The following instructions were tested on **Ubuntu Linux 18.04 LTS** and may need to be modified for other operating systems.
|
The following instructions were tested on **Ubuntu Linux 18.04 LTS** and may need to be modified for other operating systems.
|
||||||
|
|
||||||
**Step 1: Install basic packages**
|
### Step 1: Install basic packages
|
||||||
|
|
||||||
To build the application, some basic packages are required. The package `git` is required to download the source code, while `openjdk-8-jdk-headless` is required for compiling Java and Kotlin files.
|
To build the application, some basic packages are required. The package `git` is required to download the source code, while `openjdk-8-jdk-headless` is required for compiling Java and Kotlin files.
|
||||||
|
|
||||||
@@ -53,14 +53,14 @@ sudo apt-get install -y git openjdk-8-jdk-headless
|
|||||||
**IMPORTANT:** Newer JDK versions have not been tested and may not work correctly.
|
**IMPORTANT:** Newer JDK versions have not been tested and may not work correctly.
|
||||||
|
|
||||||
|
|
||||||
**Step 2: Install Android SDK tools**
|
### Step 2: Install Android SDK tools
|
||||||
|
|
||||||
The Android SDK tools contains many necessary tools for developing and debugging Android applications. It can be obtained as part of Android Studio, but, for simple command line usage, it can also be downloaded individually.
|
The Android SDK tools contains many necessary tools for developing and debugging Android applications. It can be obtained as part of Android Studio, but, for simple command line usage, it can also be downloaded individually.
|
||||||
|
|
||||||
1. Download the file `sdk-tools-linux-4333796.zip` (or a newer version) from https://developer.android.com/studio/#downloads, and extract it somewhere. In this guide, we assume that it was extracted to `/opt/android-sdk/tools`; that is, the script `/opt/android-sdk/tools/bin/sdkmanager` should exist.
|
1. Download the file `sdk-tools-linux-4333796.zip` (or a newer version) from <https://developer.android.com/studio/#downloads>, and extract it somewhere. In this guide, we assume that it was extracted to `/opt/android-sdk/tools`; that is, the script `/opt/android-sdk/tools/bin/sdkmanager` should exist.
|
||||||
|
|
||||||
2. Append the following lines to `~/.profile`, so that other tools can locate your Android SDK installation. It is necessary to restart your terminal for these changes to take effect.
|
2. Append the following lines to `~/.profile`, so that other tools can locate your Android SDK installation. It is necessary to restart your terminal for these changes to take effect.
|
||||||
```
|
```bash
|
||||||
export PATH="$PATH:/opt/android-sdk/tools/bin"
|
export PATH="$PATH:/opt/android-sdk/tools/bin"
|
||||||
export PATH="$PATH:/opt/android-sdk/platform-tools"
|
export PATH="$PATH:/opt/android-sdk/platform-tools"
|
||||||
export ANDROID_HOME="/opt/android-sdk"
|
export ANDROID_HOME="/opt/android-sdk"
|
||||||
@@ -71,7 +71,7 @@ export ANDROID_HOME="/opt/android-sdk"
|
|||||||
yes | sdkmanager --licenses
|
yes | sdkmanager --licenses
|
||||||
```
|
```
|
||||||
|
|
||||||
**Step 3: Download the source code**
|
### Step 3: Download the source code
|
||||||
|
|
||||||
To create a complete copy of the source code repository, navigate to your home directory and run:
|
To create a complete copy of the source code repository, navigate to your home directory and run:
|
||||||
```bash
|
```bash
|
||||||
@@ -79,13 +79,11 @@ git clone https://github.com/iSoron/uhabits.git
|
|||||||
```
|
```
|
||||||
The repository will be downloaded to the directory `uhabits`.
|
The repository will be downloaded to the directory `uhabits`.
|
||||||
|
|
||||||
**Step 4: Compile the source code**
|
### Step 4: Compile the source code
|
||||||
|
|
||||||
1. Navigate to the directory `uhabits`
|
1. Navigate to the directory `uhabits`
|
||||||
2. Run `./gradlew assembleDebug --stacktrace`
|
2. Run `./gradlew assembleDebug --stacktrace`
|
||||||
|
|
||||||
If the compilation is successful, a debug APK will be generated somewhere inside the folder `uhabits-android/build/`. Currently, the full path is the following, but it may change in the future:
|
If the compilation is successful, a debug APK will be generated somewhere inside the folder `uhabits-android/build/`. Currently, the full path is `./uhabits-android/build/outputs/apk/debug/uhabits-android-debug.apk`, but it may change in the future.
|
||||||
|
|
||||||
./uhabits-android/build/outputs/apk/debug/uhabits-android-debug.apk
|
|
||||||
|
|
||||||
The APK can be installed using the tool `adb`, which should have been automatically installed at `/opt/android-sdk/platform-tools/adb` during compilation of the project.
|
The APK can be installed using the tool `adb`, which should have been automatically installed at `/opt/android-sdk/platform-tools/adb` during compilation of the project.
|
||||||
|
|||||||
@@ -12,17 +12,6 @@
|
|||||||
|
|
||||||
Please see `docs/BUILD.md` and `docs/TEST.md`
|
Please see `docs/BUILD.md` and `docs/TEST.md`
|
||||||
|
|
||||||
## Directory Layout
|
|
||||||
|
|
||||||
* `docs` Documentation for developers.
|
|
||||||
* `landing` Source code for our [landing page](http://loophabits.org/).
|
|
||||||
* `uhabits-android` Android-specific code.
|
|
||||||
* `uhabits-core` Common code used by all platforms (Android, iOS).
|
|
||||||
* `uhabits-core-legacy` Proof-of-concept module, developed to evaluate the feasibility of using Kotlin multiplatform for the app; not currently used, and it will be removed soon, once all useful code is ported to the other modules.
|
|
||||||
* `uhabits-ios` Experimental iOS port of Loop. Not currently used in production.
|
|
||||||
* `uhabits-server` Source code for any server-side components the app (for example, device sync).
|
|
||||||
* `uhabits-web` Experimental web port of Loop. Not currently used in production.
|
|
||||||
|
|
||||||
## Branching Policy
|
## Branching Policy
|
||||||
|
|
||||||
This repository uses the [git-flow branching model](https://nvie.com/posts/a-successful-git-branching-model/). Basically, there are two main branches, `dev` and `master`. All the development takes place in the `dev` branch. After the new features have been implemented and tested, they are merged into the `master` branch and a new version of the app is released. Please submit your pull requests against the `dev` branch.
|
This repository uses the [git-flow branching model](https://nvie.com/posts/a-successful-git-branching-model/). Basically, there are two main branches, `dev` and `master`. All the development takes place in the `dev` branch. After the new features have been implemented and tested, they are merged into the `master` branch and a new version of the app is released. Please submit your pull requests against the `dev` branch.
|
||||||
|
|||||||
54
docs/TEST.md
@@ -2,51 +2,25 @@
|
|||||||
|
|
||||||
Loop Habit Tracker has a fairly large number of automated tests to reduce the chance of bugs being silently introduced in our code base. The tests are divided into three categories:
|
Loop Habit Tracker has a fairly large number of automated tests to reduce the chance of bugs being silently introduced in our code base. The tests are divided into three categories:
|
||||||
|
|
||||||
* **Small tests:** These tests run very quickly on the developer's computer, inside a JVM, and do not need an Android emulator or device. They typically test the correctness of core functions of the application, such as the computation of scores and streaks.
|
- **Unit tests:** These tests run very quickly on the developer's computer, inside a JVM, and do not need an Android emulator or device. They typically test the correctness of core functions of the application, such as the computation of scores and streaks.
|
||||||
* **Medium tests:** These tests require an Android emulator or device, but they are still quite fast to run, since only individual classes are tested. The app itself does not need to be launched. Examples include *view tests*, which render our custom views on the device and compare them against prerendered images.
|
- **Instrumented tests:** These tests require an Android emulator or device. _Medium_ instrumented tests are still quite fast to run, since only individual classes are tested. The app itself does not need to be launched. Examples include _view tests_, which render our custom views on the device and compare them against prerendered images. _Large_ instrumented tests launch the application on an Android emulator and interact with it by touching the screen, much like a regular user.
|
||||||
* **Large tests:** These are end-to-end tests, which launch the application on an Android emulator and interact with it by touching the screen, much like a regular user.
|
|
||||||
|
|
||||||
## Running small tests
|
## Running unit tests
|
||||||
|
|
||||||
Small tests can be launched by running `./gradlew test` or by right-clicking a particular class/method in Android Studio and selecting "Run testMethod()" or "Run ClassTest". An alternative way is to use `build.sh`, the script used by our continuous integration server. By running `./build.sh build`, the script will automatically build and run all small tests.
|
Unit tests can be launched by running `./gradlew test` or by right-clicking a particular class/method in Android Studio and selecting "Run testMethod()" or "Run ClassTest". An alternative way is to use `build.sh`, the script used by our continuous integration server. By running `./build.sh build`, the script will automatically build and run all small tests.
|
||||||
|
|
||||||
## Running medium tests
|
## Running instrumented tests
|
||||||
|
|
||||||
To run medium tests, it is recommended to use the `build.sh` script:
|
To run medium tests, it is recommended to use the `build.sh` script.
|
||||||
|
|
||||||
./build.sh build
|
1. Run `./build.sh android-setup API` to create the emulator, where `API` is the desired API level.
|
||||||
./build.sh medium-tests
|
2. Run `./build.sh android-tests API` to run the tests on a single API.
|
||||||
|
3. Run `./build.sh android-tests-parallel API API...` to run the tests on multiple APIs in parallel.
|
||||||
|
|
||||||
|
Note that instrumented tests are designed to run on a clean install, inside an emulator. They will not work on actual devices. All tests are also designed for a particular screen size, namely the Nexus 4 configuration (4.7" 768x1280 xhdpi), and a particular locale, namely English (US). Furthermore:
|
||||||
|
|
||||||
For this script to succeed, make sure that an emulator is currently running, or that a device (with developer mode activated) is connected via USB.
|
- No additional apps should be installed on the device;
|
||||||
|
- The homescreen must look exactly like it was when the emulator was originally created, with no additional icons or widgets;
|
||||||
|
- All animations must be manually disabled.
|
||||||
|
|
||||||
**WARNING!** This script will uninstall the app prior to testing it, and therefore delete all user data!
|
If there are failing view tests (that is, if some custom views do not render exactly like the prerendered images we have), then both the actual and expected images will be automatically downloaded from the device to the folder `uhabits-android/build/outputs`. After verifying the differences, if you feel that the actual images are actually fine and should replace the prerendered ones, then run `./build.sh android-accept-images`.
|
||||||
|
|
||||||
|
|
||||||
If there are failing view tests (that is, if some custom views do not render exactly like the prerendered images we have), then the script `./build.sh fetch-images` can be used to download both the actual and the expected images from the device. The images will be downloaded from the device into the folder `tmp/`. After verifying the differences, if you feel that the actual images are actually fine and should replace the prerendered ones, then run `./build.sh accept-images`.
|
|
||||||
|
|
||||||
## Running large tests
|
|
||||||
|
|
||||||
Large tests are significantly more complicated to run. In particular, they require:
|
|
||||||
|
|
||||||
* An Android emulator; they will **not** work on actual devices;
|
|
||||||
* A vanilla x86 AOSP image; they will **not** work with Google API images;
|
|
||||||
* A particular screen size, namely the Nexus 4 configuration on Android Studio (4.7 768x1280 xhdpi);
|
|
||||||
* A particular locale, namely English (US).
|
|
||||||
|
|
||||||
Furthermore:
|
|
||||||
|
|
||||||
* No additional apps should be installed on the device;
|
|
||||||
* The homescreen must look exactly like it was when the emulator was originally created, with no additional icons or widgets;
|
|
||||||
* Developer mode must be activated, and all animations must be manually disabled.
|
|
||||||
|
|
||||||
Only the following Android versions are supported by our test suite:
|
|
||||||
|
|
||||||
* Android 7.0 (API 24)
|
|
||||||
* Android 7.1.1 (API 25)
|
|
||||||
* Android 8.0 (API 26)
|
|
||||||
* Android 8.1 (API 27)
|
|
||||||
* Android 9.0 (API 28)
|
|
||||||
* Android 10.0 (API 29)
|
|
||||||
|
|
||||||
After creating an emulator and configuring it exactly as described above, launch it, wait for it to finish booting up, then run `./build.sh large-tests`. As mentioned before, this script will uninstall the app before testing it, and therefore will delete all the user data.
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
org.gradle.parallel=false
|
org.gradle.parallel=false
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms2048m -Xmx2048m -XX:MaxPermSize=2048m
|
org.gradle.jvmargs=-Xms2048m -Xmx2048m
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
android.defaults.buildfeatures.buildconfig=true
|
||||||
|
android.nonTransitiveRClass=false
|
||||||
|
android.nonFinalResIds=false
|
||||||
|
org.gradle.configureondemand=true
|
||||||
|
org.gradle.warning.mode=all
|
||||||
|
org.gradle.caching=true
|
||||||
102
gradle/libs.versions.toml
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
[versions]
|
||||||
|
agp = "8.9.2"
|
||||||
|
annotation = "1.9.1"
|
||||||
|
appcompat = "1.7.0"
|
||||||
|
appintro = "6.3.1"
|
||||||
|
commonsCodec = "1.16.0"
|
||||||
|
commonsIo = "1.3.2"
|
||||||
|
commonsLang3 = "3.14.0"
|
||||||
|
dagger = "2.55"
|
||||||
|
desugar = "2.1.4"
|
||||||
|
dexmaker = "2.28.3"
|
||||||
|
espresso = "3.6.1"
|
||||||
|
guava = "33.2.1-android"
|
||||||
|
hamcrest = "2.2"
|
||||||
|
jsr250 = "1.0"
|
||||||
|
jsr305 = "3.0.2"
|
||||||
|
junit = "1.2.1"
|
||||||
|
junitJupiter = "5.10.1"
|
||||||
|
junitVersion = "4.13.2"
|
||||||
|
konfetti-xml = "2.0.2"
|
||||||
|
kotlin = "2.1.10"
|
||||||
|
kotlinxCoroutinesCoreCommon = "1.3.8"
|
||||||
|
ksp = "2.1.10-1.0.30"
|
||||||
|
ktlint-plugin = "11.6.1"
|
||||||
|
ktor = "1.6.8"
|
||||||
|
ktxCoroutine = "1.10.1"
|
||||||
|
legacy-support = "1.0.0"
|
||||||
|
material = "1.12.0"
|
||||||
|
mockito-kotlin = "5.4.0"
|
||||||
|
opencsv = "5.9"
|
||||||
|
rules = "1.6.1"
|
||||||
|
shadow = "8.1.1"
|
||||||
|
sqliteJdbc = "3.45.1.0"
|
||||||
|
uiautomator = "2.3.0"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
annotation = { group = "androidx.annotation", name = "annotation", version.ref = "annotation" }
|
||||||
|
appIntro = { group = "com.github.AppIntro", name = "AppIntro", version.ref = "appintro" }
|
||||||
|
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
|
commons-codec = { module = "commons-codec:commons-codec", version.ref = "commonsCodec" }
|
||||||
|
commons-io = { module = "org.apache.commons:commons-io", version.ref = "commonsIo" }
|
||||||
|
commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commonsLang3" }
|
||||||
|
dagger = { group = "com.google.dagger", name = "dagger", version.ref = "dagger" }
|
||||||
|
dagger-compiler = { group = "com.google.dagger", name = "dagger-compiler", version.ref = "dagger" }
|
||||||
|
desugar_jdk_libs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugar" }
|
||||||
|
dexmaker-mockito = { group = "com.linkedin.dexmaker", name = "dexmaker-mockito", version.ref = "dexmaker" }
|
||||||
|
espresso-contrib = { group = "androidx.test.espresso", name = "espresso-contrib", version.ref = "espresso" }
|
||||||
|
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
|
||||||
|
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
|
||||||
|
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
||||||
|
jsr250-api = { group = "javax.annotation", name = "jsr250-api", version.ref = "jsr250" }
|
||||||
|
jsr305 = { group = "com.google.code.findbugs", name = "jsr305", version.ref = "jsr305" }
|
||||||
|
junit = { group = "androidx.test.ext", name = "junit", version.ref = "junit" }
|
||||||
|
junit-junit = { module = "junit:junit", version.ref = "junitVersion" }
|
||||||
|
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junitJupiter" }
|
||||||
|
konfetti-xml = { group = "nl.dionsegijn", name = "konfetti-xml", version.ref = "konfetti-xml" }
|
||||||
|
kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
|
||||||
|
kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "ktxCoroutine" }
|
||||||
|
kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "ktxCoroutine" }
|
||||||
|
kotlinx-coroutines-core-common = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-common", version.ref = "kotlinxCoroutinesCoreCommon" }
|
||||||
|
kotlinx-coroutines-core-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "ktxCoroutine" }
|
||||||
|
ktor-client-android = { group = "io.ktor", name = "ktor-client-android", version.ref = "ktor" }
|
||||||
|
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
|
||||||
|
ktor-client-jackson = { group = "io.ktor", name = "ktor-client-jackson", version.ref = "ktor" }
|
||||||
|
ktor-client-json = { group = "io.ktor", name = "ktor-client-json", version.ref = "ktor" }
|
||||||
|
ktor-client-mock = { group = "io.ktor", name = "ktor-client-mock", version.ref = "ktor" }
|
||||||
|
ktor-jackson = { group = "io.ktor", name = "ktor-jackson", version.ref = "ktor" }
|
||||||
|
legacy-preference-v14 = { group = "androidx.legacy", name = "legacy-preference-v14", version.ref = "legacy-support" }
|
||||||
|
legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacy-support" }
|
||||||
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
|
mockito-kotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version.ref = "mockito-kotlin" }
|
||||||
|
opencsv = { group = "com.opencsv", name = "opencsv", version.ref = "opencsv" }
|
||||||
|
rules = { group = "androidx.test", name = "rules", version.ref = "rules" }
|
||||||
|
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqliteJdbc" }
|
||||||
|
uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" }
|
||||||
|
|
||||||
|
[bundles]
|
||||||
|
androidTest = [
|
||||||
|
"annotation",
|
||||||
|
"dagger",
|
||||||
|
"dexmaker-mockito",
|
||||||
|
"espresso-contrib",
|
||||||
|
"espresso-core",
|
||||||
|
"junit",
|
||||||
|
"ktor-client-mock",
|
||||||
|
"ktor-jackson",
|
||||||
|
"mockito-kotlin",
|
||||||
|
"rules",
|
||||||
|
"uiautomator"
|
||||||
|
]
|
||||||
|
test = [
|
||||||
|
"dagger",
|
||||||
|
"junit-junit",
|
||||||
|
"mockito-kotlin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
agp = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||||
|
ktlint-plugin = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-plugin" }
|
||||||
|
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
|
||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
2
landing/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
out/
|
|
||||||
.sass-cache
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
haml := src/*.haml
|
|
||||||
sass := src/*.sass
|
|
||||||
|
|
||||||
html := $(patsubst src/%, out/%, $(patsubst %.haml,%.html,$(wildcard $(haml))))
|
|
||||||
css := $(patsubst src/%, out/%, $(patsubst %.sass,%.css,$(wildcard $(sass))))
|
|
||||||
src := $(wildcard src/**)
|
|
||||||
|
|
||||||
compile: $(html) $(css)
|
|
||||||
@rsync -rupE assets/ out/
|
|
||||||
|
|
||||||
out/%.css: src/%.sass $(src)
|
|
||||||
@echo ' sass $<'
|
|
||||||
@mkdir -p `dirname $@`
|
|
||||||
@sass $< $@
|
|
||||||
|
|
||||||
out/%.html: src/%.haml $(src)
|
|
||||||
@echo ' haml $<'
|
|
||||||
@mkdir -p `dirname $@`
|
|
||||||
@haml -E UTF-8 $< $@
|
|
||||||
|
|
||||||
push:
|
|
||||||
rsync -avP out/ axavier.org:/www/loophabits.org/
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@rm -rfv out
|
|
||||||
@rm -rfv tmp
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
Loop Habit Tracker Landing Page
|
|
||||||
===============================
|
|
||||||
|
|
||||||
This folder contains the source code that generates the project landing page, currently hosted at https://loophabits.org/
|
|
||||||
|
|
||||||
Pull requests with ideas for improving it are very welcome.
|
|
||||||
|
|
||||||
Build instructions
|
|
||||||
------------------
|
|
||||||
|
|
||||||
1. Install `haml`:
|
|
||||||
```bash
|
|
||||||
sudo apt install ruby-haml
|
|
||||||
```
|
|
||||||
2. Install `pandoc-ruby`:
|
|
||||||
```bash
|
|
||||||
gem install pandoc-ruby
|
|
||||||
```
|
|
||||||
3. Run `Makefile`
|
|
||||||
```bash
|
|
||||||
make
|
|
||||||
```
|
|
||||||
4. View the results (using, for example, [npm serve](https://www.npmjs.com/package/serve))
|
|
||||||
```bash
|
|
||||||
npm serve out/
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<meta http-equiv="Refresh" content="0; url='https://github.com/iSoron/uhabits/discussions/689'" />
|
|
||||||
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 458 KiB |
7
landing/assets/lib/css/bootstrap.min.css
vendored
2
landing/assets/lib/js/jquery.min.js
vendored
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 116 KiB |
|
Before Width: | Height: | Size: 28 KiB |
@@ -1,106 +0,0 @@
|
|||||||
!!! 5
|
|
||||||
%html
|
|
||||||
%head
|
|
||||||
%meta(charset="UTF-8")
|
|
||||||
%link(href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" type="text/css")
|
|
||||||
%meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no")
|
|
||||||
%title Loop Habit Tracker
|
|
||||||
%link(rel="stylesheet" type="text/css" href="lib/css/bootstrap.min.css")
|
|
||||||
%link(rel="stylesheet" type="text/css" href="index.css")
|
|
||||||
|
|
||||||
%body
|
|
||||||
.navbar.navbar-expand-md.navbar-light.bg-light
|
|
||||||
%a.navbar-brand(href="/")
|
|
||||||
%b Loop
|
|
||||||
Habit Tracker
|
|
||||||
%button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation")
|
|
||||||
%span.navbar-toggler-icon
|
|
||||||
#navbar.collapse.navbar-collapse
|
|
||||||
%ul.navbar-nav.mr-auto.mt-2.mt-lg-0
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="faq.html") FAQ
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="privacy.html") Privacy
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="https://source.loophabits.org") Source Code
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="https://translate.loophabits.org") Translate
|
|
||||||
|
|
||||||
.jumbotron.jumbotron-fluid
|
|
||||||
.site-wrapper
|
|
||||||
.container
|
|
||||||
.row.vertical-align
|
|
||||||
.col-md
|
|
||||||
%h1.display-4
|
|
||||||
Get your life on track
|
|
||||||
%p.lead
|
|
||||||
With daily reminders, beautiful charts and insightful statistics,
|
|
||||||
Loop Habit Tracker™ helps you create and maintain great habits. Completely free and open-source.
|
|
||||||
|
|
||||||
.store-badges
|
|
||||||
%a(href="https://play.google.com/store/apps/details?id=org.isoron.uhabits")
|
|
||||||
%img(src="images/google-play.png")
|
|
||||||
%a(href="https://f-droid.org/en/packages/org.isoron.uhabits/")
|
|
||||||
%img(src="images/f-droid.png")
|
|
||||||
.col-md
|
|
||||||
.s2
|
|
||||||
%img.screenshot(src="screenshots/uhabits1.png")
|
|
||||||
.s1
|
|
||||||
%img.screenshot(src="screenshots/uhabits4.png")
|
|
||||||
|
|
||||||
.section.screenshots
|
|
||||||
%span
|
|
||||||
%a(href="screenshots/uhabits1.png")
|
|
||||||
%img(src="screenshots/uhabits1_th.png")
|
|
||||||
%a(href="screenshots/uhabits2.png")
|
|
||||||
%img(src="screenshots/uhabits2_th.png")
|
|
||||||
%a(href="screenshots/uhabits3.png")
|
|
||||||
%img(src="screenshots/uhabits3_th.png")
|
|
||||||
%span
|
|
||||||
%a(href="screenshots/uhabits4.png")
|
|
||||||
%img(src="screenshots/uhabits4_th.png")
|
|
||||||
%a(href="screenshots/uhabits5.png")
|
|
||||||
%img(src="screenshots/uhabits5_th.png")
|
|
||||||
|
|
||||||
.section
|
|
||||||
.feature-header
|
|
||||||
%h1
|
|
||||||
Features
|
|
||||||
.container
|
|
||||||
.row
|
|
||||||
.col-md
|
|
||||||
%ul
|
|
||||||
%li
|
|
||||||
%h3 Habit score
|
|
||||||
Loop has an advanced formula for calculating the strength of your habits. Every repetition makes your habit stronger and every missed day makes it weaker. A few missed days after a long streak, however, will not completely destroy your progress, unlike many other don't-break-the-chain apps.
|
|
||||||
|
|
||||||
%li
|
|
||||||
%h3 Flexible schedules
|
|
||||||
In addition to daily habits, Loop supports habits with more complex schedules, such as 3 times per week or every other day.
|
|
||||||
%li
|
|
||||||
%h3 Reminders
|
|
||||||
Schedule notifications to remind you of your habits. Each habit can have its own reminder, at a chosen time of the day. Easily check or dismiss your habit directly from the notification.
|
|
||||||
%li
|
|
||||||
%h3 Widgets
|
|
||||||
Be reminded of your habits whenever you unlock your phone. Colorful widgets allow you to track your habits directly from your home screen, without even opening the app.
|
|
||||||
.col-md
|
|
||||||
%ul
|
|
||||||
%li
|
|
||||||
%h3 Take control of your data
|
|
||||||
If you want to further analyze your data, or move it to another service, Loop allows you to export it to spreadsheets (CSV) or to a database file (SQLite). For power users, check marks can be added through task automation apps such as Tasker.
|
|
||||||
%li
|
|
||||||
%h3 No limitations
|
|
||||||
Track as many habits as you wish. Loop imposes no artificial limits on how many habits you can have. All features are available to all users, and there are no in-app purchases.
|
|
||||||
%li
|
|
||||||
%h3 Completely ad-free and open source
|
|
||||||
There are no advertisements, annoying notifications or intrusive permissions in this app, and there will never be. The app is completely open-source (GPLv3).
|
|
||||||
%li
|
|
||||||
%h3 Works offline and respects your privacy
|
|
||||||
Loop doesn't require an Internet connection or online account registration. Your confidential data is never sent to anyone. Neither the developers nor any third-parties have access to it.
|
|
||||||
|
|
||||||
.section.footer
|
|
||||||
Copyright © 2016–2020, Alinson Santos Xavier. All Rights Reserved.
|
|
||||||
|
|
||||||
|
|
||||||
%script(type="text/javascript" src="lib/js/jquery.min.js")
|
|
||||||
%script(type="text/javascript" src="lib/js/bootstrap.bundle.min.js")
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
html, body
|
|
||||||
max-width: 100%
|
|
||||||
overflow-x: hidden
|
|
||||||
|
|
||||||
body
|
|
||||||
font-family: 'Open Sans', sans-serif
|
|
||||||
padding-bottom: 0
|
|
||||||
|
|
||||||
a, a:hover
|
|
||||||
text-decoration: none
|
|
||||||
|
|
||||||
.navbar
|
|
||||||
box-shadow: rgba(0,0,0,0.4) 0px 0px 20px
|
|
||||||
background-color: white !important
|
|
||||||
|
|
||||||
.nav-link
|
|
||||||
margin: 0px 18px
|
|
||||||
|
|
||||||
.section
|
|
||||||
background-color: transparent
|
|
||||||
padding: 18px 0px
|
|
||||||
|
|
||||||
.container
|
|
||||||
ul
|
|
||||||
list-style-type: none
|
|
||||||
h3
|
|
||||||
font-size: 16px
|
|
||||||
font-weight: bold
|
|
||||||
margin: 18px 0px 0px 0px
|
|
||||||
|
|
||||||
.screenshots
|
|
||||||
text-align: center
|
|
||||||
background-color: #222
|
|
||||||
img
|
|
||||||
margin: 0.5%
|
|
||||||
border-radius: 10px
|
|
||||||
border: 3px solid #fff2
|
|
||||||
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5)
|
|
||||||
max-width: 17%
|
|
||||||
|
|
||||||
.footer
|
|
||||||
color: #888
|
|
||||||
background-color: #222
|
|
||||||
text-align: center
|
|
||||||
font-size: 12px
|
|
||||||
|
|
||||||
.jumbotron
|
|
||||||
background: linear-gradient(rgba(0,30,200,0.8),rgba(90,30,150,0.5)), url("images/hero-background-filter.jpg")
|
|
||||||
box-shadow: rgba(0,0,0,0.5) 0px 0px 20px
|
|
||||||
margin: 0
|
|
||||||
h1
|
|
||||||
max-width: 25rem
|
|
||||||
font-weight: bold
|
|
||||||
color: white
|
|
||||||
p
|
|
||||||
max-width: 40rem
|
|
||||||
color: white
|
|
||||||
.screenshot
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.5) 5px 5px 20px
|
|
||||||
padding: 0px 0px 0px 0px
|
|
||||||
border-radius: 10px
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.2)
|
|
||||||
background-color: transparent
|
|
||||||
max-width: 300px
|
|
||||||
.store-badges
|
|
||||||
margin: 2rem 1rem
|
|
||||||
img
|
|
||||||
opacity: 0.8
|
|
||||||
height: 75px
|
|
||||||
img:hover
|
|
||||||
opacity: 1.0
|
|
||||||
.s1
|
|
||||||
padding-bottom: 50px
|
|
||||||
padding-left: 50px
|
|
||||||
.s2
|
|
||||||
position: absolute
|
|
||||||
top: 50px
|
|
||||||
left: 175px
|
|
||||||
|
|
||||||
.feature-header
|
|
||||||
text-align: center
|
|
||||||
font-weight: bold
|
|
||||||
padding: 18px
|
|
||||||
|
|
||||||
.align-right
|
|
||||||
text-align: right
|
|
||||||
|
|
||||||
.vertical-align
|
|
||||||
display: flex
|
|
||||||
align-items: center
|
|
||||||
|
|
||||||
.content
|
|
||||||
max-width: 800px
|
|
||||||
margin: 18px auto
|
|
||||||
padding: 0px 18px
|
|
||||||
//padding-left: 120px
|
|
||||||
h2, h3, h4
|
|
||||||
margin: 27px 0px 9px 0px
|
|
||||||
h2, h3
|
|
||||||
//margin-left: -120px
|
|
||||||
h4
|
|
||||||
//margin-left: -60px
|
|
||||||
font-size: 16px
|
|
||||||
font-weight: bold
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
!!! 5
|
|
||||||
%html
|
|
||||||
%head
|
|
||||||
%meta(charset="UTF-8")
|
|
||||||
%link(href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" type="text/css")
|
|
||||||
%meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no")
|
|
||||||
%title Privacy | Loop Habit Tracker
|
|
||||||
%link(rel="stylesheet" type="text/css" href="lib/css/bootstrap.min.css")
|
|
||||||
%link(rel="stylesheet" type="text/css" href="index.css")
|
|
||||||
|
|
||||||
%body
|
|
||||||
.navbar.navbar-expand-md.navbar-light.bg-light
|
|
||||||
%a.navbar-brand(href="/")
|
|
||||||
%b Loop
|
|
||||||
Habit Tracker
|
|
||||||
%button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation")
|
|
||||||
%span.navbar-toggler-icon
|
|
||||||
#navbar.collapse.navbar-collapse
|
|
||||||
%ul.navbar-nav.mr-auto.mt-2.mt-lg-0
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="faq.html") FAQ
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="privacy.html") Privacy
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="https://source.loophabits.org") Source Code
|
|
||||||
%li.nav-item
|
|
||||||
%a.nav-link(href="https://translate.loophabits.org") Translate
|
|
||||||
|
|
||||||
%body
|
|
||||||
.content
|
|
||||||
:markdown
|
|
||||||
#{File.open("src/privacy.md").read}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
## Privacy Policy
|
|
||||||
|
|
||||||
- All data provided to Loop Habit Tracker is only stored locally in your
|
|
||||||
device. Loop Habit Tracker does not upload your data anywhere. The
|
|
||||||
developers of Loop Habit Tracker do not have access to your data.
|
|
||||||
|
|
||||||
- Your data is not shared with any 3rd parties. Loop Habit Tracker does not
|
|
||||||
include any advertisement libraries or any 3rd party tracking (analytics)
|
|
||||||
code, such as Google Analytics or Facebook SDK.
|
|
||||||
|
|
||||||
- If you have activated "backup & reset" in your phone settings (Settings /
|
|
||||||
Backup & Reset / Back up my data), you should be aware that Android itself
|
|
||||||
will periodically save a copy of your phone's data in Google's servers. The
|
|
||||||
developers of Loop Habit Tracker do not have access to this data.
|
|
||||||
@@ -1,14 +1,32 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
jcenter()
|
google {
|
||||||
google()
|
content {
|
||||||
}
|
includeGroupByRegex("com\\.android.*")
|
||||||
resolutionStrategy.eachPlugin {
|
includeGroupByRegex("com\\.google.*")
|
||||||
if (requested.id.id == "com.android.application") {
|
includeGroupByRegex("androidx.*")
|
||||||
useModule("com.android.tools.build:gradle:${requested.version}")
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
include(":uhabits-android", ":uhabits-core", ":uhabits-server")
|
include(":uhabits-android", ":uhabits-core")
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
@Suppress("UnstableApiUsage")
|
||||||
|
repositories {
|
||||||
|
google {
|
||||||
|
content {
|
||||||
|
includeGroupByRegex("com\\.android.*")
|
||||||
|
includeGroupByRegex("com\\.google.*")
|
||||||
|
includeGroupByRegex("androidx.*")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mavenCentral()
|
||||||
|
maven(url = "https://plugins.gradle.org/m2/")
|
||||||
|
maven(url = "https://oss.sonatype.org/content/repositories/snapshots/")
|
||||||
|
maven(url = "https://jitpack.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include(":uhabits-android", ":uhabits-core")
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
input=$1
|
|
||||||
locale_name=$2
|
|
||||||
|
|
||||||
cat <<END
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// THIS FILE WAS AUTOMATICALLY GENERATED
|
|
||||||
//
|
|
||||||
// Please do not submit pull request to modify it. Corrections to translations
|
|
||||||
// may be submitted at https://translate.loophabits.org/
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
package org.isoron.uhabits.i18n
|
|
||||||
|
|
||||||
END
|
|
||||||
|
|
||||||
prefix="override "
|
|
||||||
if [ "$locale_name" == "" ]; then
|
|
||||||
prefix="open "
|
|
||||||
echo "open class Strings() {"
|
|
||||||
else
|
|
||||||
echo "class Strings$locale_name : Strings() {"
|
|
||||||
fi
|
|
||||||
|
|
||||||
grep "<string name" "$1" | \
|
|
||||||
grep -v translatable | \
|
|
||||||
sed 's/&/\&/g' | \
|
|
||||||
sed 's/^.*name="\([^"]*\)">\([^<]*\)<.*/ '"$prefix"'val \1 = "\2"/'
|
|
||||||
|
|
||||||
echo "}"
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
INPUT_DIR=../android/uhabits-android/src/main/res/
|
|
||||||
OUTPUT_DIR=../core/src/commonMain/kotlin/org/isoron/uhabits/i18n/
|
|
||||||
|
|
||||||
convert() {
|
|
||||||
./androidStringsToKt.sh $INPUT_DIR/$1/strings.xml "$2" > $OUTPUT_DIR/Strings$2.kt
|
|
||||||
}
|
|
||||||
|
|
||||||
#convert values ""
|
|
||||||
convert values-ar Arabic
|
|
||||||
convert values-bg Bulgarian
|
|
||||||
convert values-ca Catalan
|
|
||||||
convert values-cs Czech
|
|
||||||
convert values-da Danish
|
|
||||||
convert values-de German
|
|
||||||
convert values-el Greek
|
|
||||||
convert values-eo Esperanto
|
|
||||||
convert values-es Spanish
|
|
||||||
convert values-eu Basque
|
|
||||||
convert values-fa Persian
|
|
||||||
convert values-fi Finnish
|
|
||||||
convert values-fr French
|
|
||||||
convert values-hi Hindi
|
|
||||||
convert values-hr Croatian
|
|
||||||
convert values-hu Hungarian
|
|
||||||
convert values-in Indonesian
|
|
||||||
convert values-it Italian
|
|
||||||
convert values-iw Hebrew
|
|
||||||
convert values-ja Japanese
|
|
||||||
convert values-ko Korean
|
|
||||||
convert values-nl Dutch
|
|
||||||
convert values-no-rNO Norwegian
|
|
||||||
convert values-pl Polish
|
|
||||||
convert values-pt-rBR PortugueseBR
|
|
||||||
convert values-pt-rPT PortuguesePT
|
|
||||||
convert values-ro Romanian
|
|
||||||
convert values-ru Russian
|
|
||||||
convert values-sl Slovak
|
|
||||||
convert values-sr Serbian
|
|
||||||
convert values-sv Swedish
|
|
||||||
convert values-tr Turkish
|
|
||||||
convert values-uk Ukrainian
|
|
||||||
convert values-vi Vietnamese
|
|
||||||
convert values-zh-rCN ChineseCN
|
|
||||||
convert values-zh-rTW ChineseTW
|
|
||||||
67
tools/parseInstrument.py
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Android Instrumentation Test Parser
|
||||||
|
|
||||||
|
Given a raw Android Instrumentation log (produced by "adb shell am instrument -r ...") this script
|
||||||
|
return zero if all tests pass and non-zero if some tests fail. In case of failure, this script
|
||||||
|
also prints arguments that, if passed to "am instrument", will cause it to re-run just the tests
|
||||||
|
that failed. This script additionally prints warnings about the tests on the STDERR; e.g. slow tests.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
STATUS_START = 1
|
||||||
|
STATUS_DISABLED = -3
|
||||||
|
SLOW_TEST_THRESHOLD = 5.0
|
||||||
|
|
||||||
|
COLOR_RED = '\033[91m'
|
||||||
|
COLOR_YELLOW = '\033[93m'
|
||||||
|
COLOR_END = '\033[0m'
|
||||||
|
|
||||||
|
def error(msg):
|
||||||
|
sys.stderr.write("%s%s%s\n" % (COLOR_RED, msg, COLOR_END))
|
||||||
|
|
||||||
|
def warning(msg):
|
||||||
|
sys.stderr.write("%s%s%s\n" % (COLOR_YELLOW, msg, COLOR_END))
|
||||||
|
|
||||||
|
log_filename = sys.argv[1]
|
||||||
|
current_class, current_method = None, None
|
||||||
|
failed_tests = []
|
||||||
|
am_args = "-e class "
|
||||||
|
exit_code = 1
|
||||||
|
|
||||||
|
for line in open(log_filename).readlines():
|
||||||
|
matches = re.findall('^([0-9.]*)', line)
|
||||||
|
current_time = float(matches[0])
|
||||||
|
|
||||||
|
matches = re.findall('INSTRUMENTATION_STATUS: class=(.*)', line)
|
||||||
|
if len(matches) > 0:
|
||||||
|
current_class = matches[0]
|
||||||
|
|
||||||
|
matches = re.findall('INSTRUMENTATION_STATUS: test=(.*)', line)
|
||||||
|
if len(matches) > 0:
|
||||||
|
current_method = matches[0]
|
||||||
|
|
||||||
|
matches = re.findall('OK \([0-9]* tests?\)', line)
|
||||||
|
if len(matches) > 0:
|
||||||
|
exit_code = 0
|
||||||
|
|
||||||
|
matches = re.findall('INSTRUMENTATION_STATUS_CODE: ([-0-9]*)', line)
|
||||||
|
if len(matches) > 0:
|
||||||
|
status_code = int(matches[0])
|
||||||
|
if (status_code < 0) and (status_code != STATUS_DISABLED):
|
||||||
|
am_args += f"{current_class}#{current_method},"
|
||||||
|
failed_tests.append(f"{current_class}#{current_method}")
|
||||||
|
if status_code == STATUS_START:
|
||||||
|
initial_time = current_time
|
||||||
|
else:
|
||||||
|
elapsed_time = current_time - initial_time
|
||||||
|
if(elapsed_time > SLOW_TEST_THRESHOLD):
|
||||||
|
warning("SLOW %s#%s (%.2f seconds)" % (current_class, current_method, elapsed_time))
|
||||||
|
|
||||||
|
if len(failed_tests) > 0:
|
||||||
|
for test in failed_tests:
|
||||||
|
error("FAIL %s" % test)
|
||||||
|
print(am_args[:-1])
|
||||||
|
|
||||||
|
sys.exit(exit_code)
|
||||||
@@ -1,377 +1,536 @@
|
|||||||
Name,Languages,"Translated (Words)","Target Words","Approved (Words)",Voted,"""+"" votes received","""-"" votes received","Winning (Words)",Joined
|
Name,Languages,"Translated (Words)","Target Words","Approved (Words)",Voted,"""+"" votes received","""-"" votes received","Winning (Words)",Joined
|
||||||
"Alinson Xavier (iSoron)","Portuguese, Brazilian; Japanese; Spanish; Portuguese; Italian; Chinese Simplified; French; Hungarian; German; Arabic; Hindi; Slovenian; Catalan; Greek; Korean; Bulgarian; Chinese Traditional; Polish; Russian; Serbian (Cyrillic); Turkish; Ukrainian; Czech; Indonesian; Croatian; Danish; Dutch; Romanian; Swedish; Basque; Persian; Finnish; Vietnamese; Telugu; Tamil; Afrikaans; Esperanto; Hebrew",14808,17227,1282,0,1779,80,4274,"2016-03-05 18:35:27"
|
"Alinson Xavier (iSoron)","Portuguese, Brazilian; Japanese; Chinese Simplified; Italian; Spanish; Portuguese; French; Hungarian; Chinese Traditional; Turkish; Russian; Arabic; Polish; German; Korean; Bulgarian; Catalan; Greek; Slovenian; Hindi; Serbian (Cyrillic); Ukrainian; Czech; Danish; Dutch; Indonesian; Croatian; Romanian; Swedish; Basque; Persian; Finnish; Vietnamese; Tamil; Telugu; Hebrew; Esperanto; Afrikaans; Norwegian; Armenian; Slovak; Serbian (Latin); Uyghur",15497,18825,1308,0,2094,111,4315,"2016-03-05 18:35:27"
|
||||||
"Slobodan Simić (Слободан Симић) (slsimic)","Serbian (Latin); Serbian (Cyrillic)",2054,1831,2114,12,33,0,1991,"2021-02-03 14:26:07"
|
"Slobodan Simić (Слободан Симић) (slsimic)","Serbian (Latin); Serbian (Cyrillic)",2072,1852,2139,12,30,0,2015,"2021-02-03 14:26:07"
|
||||||
"Oglaigh Rystard (oglaignaheireann)","Ukrainian; Portuguese; Catalan; Greek; Basque; Romanian; Italian",1103,1037,1327,1,13,6,954,"2017-03-31 09:13:19"
|
dukelc,Slovak,1107,1052,0,0,0,0,0,"2020-08-27 14:02:41"
|
||||||
"David (Cliff122)",Swedish,1040,1019,725,6,0,0,700,"2020-01-21 13:56:55"
|
"Oglaigh Rystard (oglaignaheireann)","Ukrainian; Portuguese; Catalan; Greek; Basque; Romanian; Italian",1103,1037,1327,1,22,13,954,"2017-03-31 09:13:19"
|
||||||
"Omer I.S. (omeritzics)",Hebrew,1000,900,1097,14,1,0,946,"2020-10-11 20:10:51"
|
Avalysion,Georgian,1057,895,0,0,0,0,0,"2023-06-30 20:05:15"
|
||||||
dukelc,Slovak,919,880,0,0,0,0,0,"2020-08-27 14:02:41"
|
"Mathew TK (mathew2006)",Malayalam,1057,1885,0,0,0,0,0,"2023-12-16 01:57:49"
|
||||||
"Intan Ayunda (Intan_Ayunda)",Indonesian,800,793,962,0,0,0,711,"2020-10-14 07:51:58"
|
REMOVED_USER,Hebrew,1051,944,1122,14,1,0,954,"2020-10-11 20:10:51"
|
||||||
|
"David (Cliff122)",Swedish,1040,1019,725,6,37,0,700,"2020-01-21 13:56:55"
|
||||||
|
"Intan Ayunda (Intan_Ayunda)",Indonesian,818,811,985,0,0,0,729,"2020-10-14 07:51:58"
|
||||||
|
dusanstrgar,Slovenian,770,730,0,0,0,0,0,"2017-03-31 10:30:28"
|
||||||
|
"Mihail Stefanov (MStefanov)",Bulgarian,755,794,3,0,2,4,2,"2017-03-31 16:09:02"
|
||||||
|
Osoitz,Basque,751,683,0,9,0,0,3,"2018-01-23 14:07:47"
|
||||||
KMakoto,"Chinese Traditional",745,1146,949,0,0,0,745,"2019-10-22 04:19:52"
|
KMakoto,"Chinese Traditional",745,1146,949,0,0,0,745,"2019-10-22 04:19:52"
|
||||||
"Evren (evrenkiymaz)",Turkish,688,604,0,71,5,1,0,"2020-10-04 03:39:16"
|
Tomairuka,Japanese,709,1842,1033,43,12,0,585,"2020-12-12 12:14:22"
|
||||||
|
"Evren (evrenkiymaz)",Turkish,688,604,0,71,31,22,0,"2020-10-04 03:39:16"
|
||||||
|
andaryon,Czech,681,606,0,108,21,0,0,"2021-11-25 10:20:45"
|
||||||
|
"Antti Kallio (antti.kallio)",Finnish,668,539,0,5,0,0,0,"2021-07-03 05:54:44"
|
||||||
"David Nos (david.nos)","Catalan; Spanish",667,731,0,0,1,0,0,"2020-01-04 10:15:36"
|
"David Nos (david.nos)","Catalan; Spanish",667,731,0,0,1,0,0,"2020-01-04 10:15:36"
|
||||||
"Antti Kallio (antti.kallio)",Finnish,650,525,0,0,0,0,0,"2021-07-03 05:54:44"
|
androide74,Italian,662,681,0,2,0,0,0,"2020-02-06 15:46:28"
|
||||||
androide74,Italian,644,659,0,2,0,0,0,"2020-02-06 15:46:28"
|
"Dmitriy Bogdanov (di72nn)",Russian,643,589,1197,0,50,0,515,"2017-03-31 10:00:48"
|
||||||
Tomairuka,Japanese,633,1636,909,43,0,0,564,"2020-12-12 12:14:22"
|
reyhoon,Persian,624,759,0,1,3,2,0,"2020-10-01 18:17:23"
|
||||||
"Dmitriy Bogdanov (di72nn)",Russian,625,572,1197,0,36,0,515,"2017-03-31 10:00:48"
|
"Saeed Esmaili (saaeed.es20)",Persian,586,795,0,5,4,0,0,"2020-11-26 15:41:15"
|
||||||
reyhoon,Persian,624,759,0,1,3,1,0,"2020-10-01 18:17:23"
|
fabian.bouchal,German,548,527,0,6,4,5,72,"2020-01-07 06:43:37"
|
||||||
Osoitz,Basque,610,545,0,9,0,0,3,"2018-01-23 14:07:47"
|
"Isti (eisti)",Hungarian,528,476,0,0,1,0,0,"2020-12-03 12:02:51"
|
||||||
"Saeed Esmaili (saaeed.es20)",Persian,568,774,0,5,4,0,0,"2020-11-26 15:41:15"
|
Aravinth_Earth,Tamil,511,961,0,12,0,0,0,"2024-02-23 12:37:28"
|
||||||
fabian.bouchal,German,548,527,0,6,0,3,72,"2020-01-07 06:43:37"
|
boban77,Czech,509,461,0,2,45,0,0,"2020-04-30 13:18:24"
|
||||||
boban77,Czech,509,461,0,2,0,0,0,"2020-04-30 13:18:24"
|
"Martim Parente (martimparente)",Portuguese,505,542,0,38,0,0,0,"2020-08-26 10:22:11"
|
||||||
"Yoav Argov (YoavArgov)",Hebrew,501,461,0,0,1,8,103,"2017-04-28 07:23:01"
|
"Yoav Argov (YoavArgov)",Hebrew,501,461,0,0,1,8,91,"2017-04-28 07:23:01"
|
||||||
REMOVED_USER,Norwegian,501,498,501,0,148,0,501,"2017-07-05 19:02:25"
|
REMOVED_USER,Norwegian,501,498,501,0,148,0,501,"2017-07-05 19:02:25"
|
||||||
"Martim Parente (Sharlimar)",Portuguese,497,534,0,38,0,0,0,"2020-08-26 10:22:11"
|
|
||||||
"chrrris1987 (Chrrris1987)",Dutch,467,478,0,23,0,0,0,"2020-02-03 05:26:04"
|
"chrrris1987 (Chrrris1987)",Dutch,467,478,0,23,0,0,0,"2020-02-03 05:26:04"
|
||||||
|
"黄克 (hk13127)","Chinese Simplified",461,765,0,1,0,0,22,"2020-01-17 23:16:03"
|
||||||
"Huy Ngo (huyngo)",Vietnamese,461,695,0,1,0,0,0,"2020-01-26 11:58:36"
|
"Huy Ngo (huyngo)",Vietnamese,461,695,0,1,0,0,0,"2020-01-26 11:58:36"
|
||||||
"黄克 (hk13127)","Chinese Simplified",461,765,0,1,0,0,24,"2020-01-17 23:16:03"
|
"Arkadiusz Bubak (epitek)",Polish,458,416,52,24,15,4,0,"2020-11-05 05:11:58"
|
||||||
"Arkadiusz Bubak (epitek)",Polish,458,416,29,24,0,3,0,"2020-11-05 05:11:58"
|
"Radek Kuklík (kuklik.radek)",Czech,453,392,0,100,0,0,0,"2022-10-08 10:04:24"
|
||||||
marco.baturan,Esperanto,452,452,0,0,0,0,0,"2020-06-23 02:49:46"
|
marco.baturan,Esperanto,452,452,0,0,0,0,0,"2020-06-23 02:49:46"
|
||||||
"Sief Tarek (sieftarek135)",Arabic,447,455,0,0,0,0,0,"2021-02-07 14:35:21"
|
"Sief Tarek (sieftarek135)",Arabic,447,455,0,0,1,4,0,"2021-02-07 14:35:21"
|
||||||
|
"Alparslan Şakçi (sakci)",Turkish,436,372,0,118,2,0,0,"2022-01-14 12:03:11"
|
||||||
|
JY3,"Chinese Simplified",432,741,298,0,2,0,227,"2021-03-08 08:53:35"
|
||||||
"Samuel Guay (SamGuay)",French,426,486,0,6,0,0,0,"2020-06-25 07:14:38"
|
"Samuel Guay (SamGuay)",French,426,486,0,6,0,0,0,"2020-06-25 07:14:38"
|
||||||
"Diana Karaseva (Sun_Dianka)",Russian,399,373,0,10,1,0,209,"2020-01-30 06:40:02"
|
"Diana Karaseva (Sun_Dianka)",Russian,399,373,0,10,1,0,209,"2020-01-30 06:40:02"
|
||||||
"Alexander Jansson (dalecarlian)",Swedish,396,406,507,0,0,3,399,"2017-06-21 01:37:32"
|
"Alexander Jansson (dalecarlian)",Swedish,396,406,507,0,29,6,399,"2017-06-21 01:37:32"
|
||||||
luiandresgonzalez,Spanish,383,403,0,1,28,0,0,"2020-07-11 14:20:44"
|
luiandresgonzalez,Spanish,383,403,0,1,28,0,0,"2020-07-11 14:20:44"
|
||||||
"Thamara Andrade (tkcandrade)","Portuguese, Brazilian",380,387,0,0,1,0,252,"2020-01-09 19:35:48"
|
"Thamara Andrade (tkcandrade)","Portuguese, Brazilian",380,387,0,0,1,0,239,"2020-01-09 19:35:48"
|
||||||
"Sølv Ræven (soelvraeven)",Danish,370,370,0,0,0,0,0,"2020-11-28 16:46:18"
|
"Sølv Ræven (soelvraeven)",Danish,370,370,0,0,0,0,0,"2020-11-28 16:46:18"
|
||||||
"Isti (eisti)",Hungarian,367,329,0,0,0,0,0,"2020-12-03 12:02:51"
|
strikeCunny2245,Icelandic,363,368,0,0,0,0,0,"2023-08-07 08:05:53"
|
||||||
"Anh Quân (dangquanuet)",Vietnamese,362,530,0,42,2,0,0,"2017-10-29 12:27:44"
|
"Anh Quân (dangquanuet)",Vietnamese,362,530,0,42,2,0,0,"2017-10-29 12:27:44"
|
||||||
|
"Alexander Haronitakis (kanakis)",Greek,349,372,0,0,0,0,0,"2023-09-13 04:10:43"
|
||||||
gapszi,Hungarian,348,301,0,86,0,0,0,"2019-04-08 01:35:54"
|
gapszi,Hungarian,348,301,0,86,0,0,0,"2019-04-08 01:35:54"
|
||||||
JY3,"Chinese Simplified",345,585,278,0,1,0,207,"2021-03-08 08:53:35"
|
|
||||||
"Mahdi Nasiri (mahdi.nasiri)",Persian,343,465,0,39,3,1,0,"2017-07-14 09:17:25"
|
"Mahdi Nasiri (mahdi.nasiri)",Persian,343,465,0,39,3,1,0,"2017-07-14 09:17:25"
|
||||||
Seoyul,Korean,339,825,0,0,27,0,0,"2017-06-21 08:11:39"
|
Seoyul,Korean,339,825,0,0,27,0,0,"2017-06-21 08:11:39"
|
||||||
"Magimai Prakasam (magimai)",Tamil,336,831,0,12,0,0,0,"2018-04-15 21:16:08"
|
"Magimai Prakasam (magimai)",Tamil,336,831,0,12,2,0,0,"2018-04-15 21:16:08"
|
||||||
"Michael Malak (MichaelKMalak)",Arabic,304,271,0,0,0,0,0,"2020-05-26 19:47:58"
|
"Star7 (Star7-crowdin)","Chinese Simplified",330,561,0,0,0,0,0,"2025-02-10 08:41:34"
|
||||||
|
Susanamesa,Spanish,306,342,0,11,0,0,0,"2023-01-01 23:56:35"
|
||||||
|
"Michael Malak (MichaelKMalak)",Arabic,304,271,0,0,4,2,0,"2020-05-26 19:47:58"
|
||||||
"Elina Salminen (salminen.elina.m)",Finnish,297,227,0,0,0,0,0,"2021-01-06 01:28:57"
|
"Elina Salminen (salminen.elina.m)",Finnish,297,227,0,0,0,0,0,"2021-01-06 01:28:57"
|
||||||
ayane.m,Japanese,292,863,0,1,3,0,22,"2019-11-20 03:28:26"
|
Blinkin,Dutch,297,334,0,5,1,0,0,"2021-06-14 10:30:05"
|
||||||
Blinkin,Dutch,284,318,0,1,0,0,0,"2021-06-14 10:30:05"
|
ayane.m,Japanese,292,863,0,1,8,0,23,"2019-11-20 03:28:26"
|
||||||
"Marius Teufelweich (teufelweich)",German,249,256,606,4,2,0,146,"2021-03-12 04:11:38"
|
c.m,Greek,276,293,0,124,0,0,0,"2024-07-13 14:49:43"
|
||||||
|
"Marius Teufelweich (teufelweich)",German,267,272,611,4,23,3,146,"2021-03-12 04:11:38"
|
||||||
|
"Sumin Son (todaypp)",Korean,266,221,0,7,0,0,0,"2023-06-09 05:28:30"
|
||||||
|
hypnotichemionus,"Chinese Simplified",249,430,0,0,8,0,19,"2020-03-08 01:46:25"
|
||||||
|
"Israa Z (sosozozo)",Arabic,240,266,0,81,14,0,3,"2017-11-27 14:10:50"
|
||||||
cobalt59,German,237,234,0,1,24,1,132,"2017-06-05 05:18:33"
|
cobalt59,German,237,234,0,1,24,1,132,"2017-06-05 05:18:33"
|
||||||
"QWERT (lurenjia01)","Chinese Simplified",236,407,0,0,8,0,19,"2020-03-08 01:46:25"
|
|
||||||
beriain,Basque,234,235,0,0,2,0,0,"2017-03-31 15:42:28"
|
beriain,Basque,234,235,0,0,2,0,0,"2017-03-31 15:42:28"
|
||||||
pnhpnh,Vietnamese,225,343,0,1,3,0,0,"2017-11-27 12:06:07"
|
pnhpnh,Vietnamese,225,343,0,1,3,0,0,"2017-11-27 12:06:07"
|
||||||
"Dika Fitrian Dwi Putra (OsamuDazai)",Indonesian,221,215,0,0,0,0,48,"2020-07-13 04:40:27"
|
"Dika Fitrian Dwi Putra (OsamuDazai)",Indonesian,221,215,0,0,0,0,48,"2020-07-13 04:40:27"
|
||||||
easyrepro,Telugu,214,297,0,0,0,0,0,"2020-06-12 12:52:10"
|
easyrepro,Telugu,214,297,0,0,4,0,0,"2020-06-12 12:52:10"
|
||||||
taras-ko,Ukrainian,211,183,0,1,4,0,19,"2017-10-26 16:52:22"
|
taras-ko,Ukrainian,211,183,0,1,4,0,19,"2017-10-26 16:52:22"
|
||||||
|
"vinayak sharma (vinayak0504)",Hindi,211,456,0,0,0,0,0,"2023-05-18 18:31:51"
|
||||||
sojusnik,German,207,200,1,0,30,0,66,"2017-04-03 17:11:56"
|
sojusnik,German,207,200,1,0,30,0,66,"2017-04-03 17:11:56"
|
||||||
axmed99,Ukrainian,203,177,0,40,0,0,53,"2021-04-01 03:56:20"
|
"Andrij Mizyk (andm)",Ukrainian,204,178,0,40,1,0,53,"2021-04-01 03:56:20"
|
||||||
"Heru Yen (heruyen)",Indonesian,201,201,0,0,0,0,25,"2020-06-29 18:39:15"
|
"Heru Yen (heruyen)",Indonesian,201,201,0,0,0,0,25,"2020-06-29 18:39:15"
|
||||||
"Vijaykumar Borkar (vjkumar)",Hindi,200,364,0,11,0,0,0,"2021-08-06 16:12:15"
|
"Vijaykumar Borkar (vjkumar)",Hindi,200,364,0,11,0,0,0,"2021-08-06 16:12:15"
|
||||||
Ishmaeel,Turkish,193,174,0,129,6,0,0,"2017-10-04 03:54:00"
|
_translator,French,199,227,0,11,0,0,0,"2021-07-06 07:54:12"
|
||||||
|
bearsdens,Romanian,198,210,0,0,0,0,0,"2022-08-28 17:08:33"
|
||||||
|
Ishmaeel,Turkish,193,174,0,129,17,6,0,"2017-10-04 03:54:00"
|
||||||
|
REMOVED_USER,Spanish,192,201,0,2,5,0,0,"2021-05-21 17:58:22"
|
||||||
|
bruhwut,Vietnamese,189,292,0,1,0,0,0,"2021-05-21 07:16:30"
|
||||||
"Aputsiak Niels Janussen (aputtu)",Danish,187,200,0,0,0,0,0,"2019-08-28 05:47:42"
|
"Aputsiak Niels Janussen (aputtu)",Danish,187,200,0,0,0,0,0,"2019-08-28 05:47:42"
|
||||||
_translator,French,181,206,0,11,0,0,0,"2021-07-06 07:54:12"
|
|
||||||
fbruna17,Danish,181,179,0,1,0,0,0,"2021-01-28 15:48:47"
|
fbruna17,Danish,181,179,0,1,0,0,0,"2021-01-28 15:48:47"
|
||||||
"Omry Cohen (omrycohen)",Hebrew,175,156,0,1,0,0,33,"2021-01-18 07:33:23"
|
Bryanx,Dutch,179,168,0,5,2,0,0,"2019-11-21 17:08:12"
|
||||||
Bryanx,Dutch,174,165,0,5,0,0,0,"2019-11-21 17:08:12"
|
"Ivan Vlahov (vlahovivan)",Croatian,179,176,0,0,0,0,0,"2024-01-25 08:12:11"
|
||||||
|
"Omry Cohen (omrycohen)",Hebrew,175,156,0,1,0,0,12,"2021-01-18 07:33:23"
|
||||||
"Pierre GALIEGUE (pierre.galiegue)",French,171,194,0,24,4,0,0,"2020-08-16 11:41:35"
|
"Pierre GALIEGUE (pierre.galiegue)",French,171,194,0,24,4,0,0,"2020-08-16 11:41:35"
|
||||||
bruhwut,Vietnamese,171,268,0,1,0,0,0,"2021-05-21 07:16:30"
|
plitwin,Polish,168,151,0,2,55,0,49,"2021-01-20 06:18:37"
|
||||||
DionysosDV,Greek,165,153,0,0,0,0,0,"2021-02-27 19:05:25"
|
DionysosDV,Greek,165,153,0,0,27,4,0,"2021-02-27 19:05:25"
|
||||||
"Gustavo Lima (GustavoLima)",Portuguese,158,177,0,1,4,10,0,"2020-08-26 10:35:05"
|
"Gustavo Lima (GustavoLima)",Portuguese,158,177,0,1,4,10,0,"2020-08-26 10:35:05"
|
||||||
oscfd,Spanish,155,166,0,1,4,0,0,"2021-05-21 17:58:22"
|
"Alex V. (elvitalex)",Romanian,154,166,0,24,0,0,0,"2022-08-03 17:40:00"
|
||||||
plitwin,Polish,145,128,0,1,16,0,26,"2021-01-20 06:18:37"
|
"Ravi Rami (ramiravi)",Hindi,151,248,0,0,0,0,0,"2021-10-10 09:19:40"
|
||||||
"Lương Vĩnh Khang (LuongVinhKhang)",Vietnamese,144,256,0,0,46,1,0,"2017-08-10 10:05:58"
|
"Lương Vĩnh Khang (LuongVinhKhang)",Vietnamese,144,256,0,0,46,1,0,"2017-08-10 10:05:58"
|
||||||
azzamsa,Indonesian,142,136,0,48,0,1,26,"2017-06-16 18:29:45"
|
azzamsa,Indonesian,142,136,0,48,0,1,26,"2017-06-16 18:29:45"
|
||||||
"yoding (yodingc)","Chinese Traditional; Chinese Simplified",141,271,0,10,0,0,0,"2021-07-07 01:45:45"
|
"yoding (yodingc)","Chinese Traditional; Chinese Simplified",141,271,0,10,0,0,0,"2021-07-07 01:45:45"
|
||||||
"Neysa Nasywa (neysanasywa)",Indonesian,140,141,0,0,0,0,60,"2020-11-18 10:32:10"
|
"Neysa Nasywa (neysanasywa)",Indonesian,140,141,0,0,0,0,60,"2020-11-18 10:32:10"
|
||||||
"Mohammed Imthath (mimthath4)",Tamil,136,274,0,0,11,0,0,"2018-02-15 22:41:15"
|
mohmans,Arabic,139,141,0,12,7,1,0,"2020-11-23 02:48:00"
|
||||||
|
"Eilif Adelvice (adelvice)",Spanish,139,154,0,96,6,0,0,"2021-08-05 07:20:21"
|
||||||
|
"Mohammed Imthath (mimthath4)",Tamil,136,274,0,0,13,1,0,"2018-02-15 22:41:15"
|
||||||
|
carllacan,Catalan,134,155,0,2,0,0,0,"2021-11-13 13:12:07"
|
||||||
roptat,French,132,154,0,112,89,5,0,"2017-04-19 16:54:47"
|
roptat,French,132,154,0,112,89,5,0,"2017-04-19 16:54:47"
|
||||||
"Trần Thái (tranhoangthai2001)",Vietnamese,127,186,0,8,1,0,0,"2018-03-01 10:51:39"
|
"Trần Thái (tranhoangthai2001)",Vietnamese,127,186,0,8,1,0,0,"2018-03-01 10:51:39"
|
||||||
"OP Smosher (teenwolffan44)","Serbian (Cyrillic)",124,122,0,0,0,0,18,"2020-11-05 09:41:35"
|
"OP Smosher (teenwolffan44)","Serbian (Cyrillic)",124,122,0,0,0,0,18,"2020-11-05 09:41:35"
|
||||||
|
"Tad Wohlrapp (TadWohlrapp)",German,124,122,0,0,2,0,0,"2022-06-28 04:55:41"
|
||||||
4001982248998,Esperanto,122,119,0,0,0,0,0,"2017-10-08 04:13:02"
|
4001982248998,Esperanto,122,119,0,0,0,0,0,"2017-10-08 04:13:02"
|
||||||
"StoP4Me (Lcqp)",Romanian,121,119,0,0,3,0,0,"2018-05-06 18:51:59"
|
"StoP4Me (Lcqp)",Romanian,121,119,0,0,6,0,0,"2018-05-06 18:51:59"
|
||||||
alalloush,Arabic,118,129,0,2,2,0,0,"2017-03-31 12:37:17"
|
alalloush,Arabic,118,129,0,2,17,6,0,"2017-03-31 12:37:17"
|
||||||
"Eilif Adelvice (adelvice)",Spanish,116,126,0,96,0,0,0,"2021-08-05 07:20:21"
|
"Brenda Correa (brenda.14)",Spanish,117,127,0,0,0,1,0,"2022-05-16 02:34:13"
|
||||||
Sebastian05067,Spanish,114,133,0,55,28,0,0,"2017-05-14 00:48:16"
|
Sebastian05067,Spanish,114,133,0,55,32,0,0,"2017-05-14 00:48:16"
|
||||||
"Tanya (MagicUnderHood)",Russian,114,98,0,19,0,0,54,"2019-04-21 10:44:03"
|
"Tanya (MagicUnderHood)",Russian,114,98,0,19,0,0,54,"2019-04-21 10:44:03"
|
||||||
REMOVED_USER,Arabic,111,106,0,22,21,2,0,"2018-01-05 07:01:45"
|
REMOVED_USER,Arabic,111,106,0,22,23,3,0,"2018-01-05 07:01:45"
|
||||||
mohmans,Arabic,109,103,0,2,0,0,0,"2020-11-23 02:48:00"
|
|
||||||
"Iabin Arteaga (iabin)",Spanish,108,111,0,4,21,0,0,"2017-08-26 21:08:54"
|
|
||||||
"Ivan Krušlin (krux3r)",Croatian,108,122,503,0,0,0,108,"2017-03-31 09:15:24"
|
"Ivan Krušlin (krux3r)",Croatian,108,122,503,0,0,0,108,"2017-03-31 09:15:24"
|
||||||
2kaafone,Finnish,105,90,0,0,0,0,0,"2019-08-12 06:58:48"
|
"Iabin Arteaga (iabin)",Spanish,108,111,0,4,21,1,0,"2017-08-26 21:08:54"
|
||||||
|
REMOVED_USER,Finnish,105,90,0,0,0,0,0,"2019-08-12 06:58:48"
|
||||||
"Adam Jurkiewicz (hasztagg)",Polish,104,105,529,0,0,0,104,"2017-03-31 09:50:51"
|
"Adam Jurkiewicz (hasztagg)",Polish,104,105,529,0,0,0,104,"2017-03-31 09:50:51"
|
||||||
|
"PILHA PARK (pilhaha)",Korean,101,88,0,0,0,0,0,"2023-06-30 23:51:41"
|
||||||
"just a name bro (justanamebr0)",Danish,98,109,0,0,1,0,0,"2019-06-19 11:57:55"
|
"just a name bro (justanamebr0)",Danish,98,109,0,0,1,0,0,"2019-06-19 11:57:55"
|
||||||
"Nam Nguyen (namnl2706)",Vietnamese,95,137,0,0,0,0,0,"2020-08-18 23:02:33"
|
"Nam Nguyen (namnl2706)",Vietnamese,95,137,0,0,0,0,0,"2020-08-18 23:02:33"
|
||||||
"손유정 (yuwon1213)",Korean,95,57,0,0,0,0,0,"2021-03-30 05:25:33"
|
"손유정 (yuwon1213)",Korean,95,57,0,0,1,3,0,"2021-03-30 05:25:33"
|
||||||
ranmagen,Hebrew,91,78,0,0,0,0,0,"2021-02-16 05:44:31"
|
ranmagen,Hebrew,91,78,0,0,0,0,0,"2021-02-16 05:44:31"
|
||||||
LoneWanderer,"Chinese Traditional",90,137,0,4,0,0,0,"2020-09-29 05:24:48"
|
LoneWanderer,"Chinese Traditional",90,137,0,4,0,0,0,"2020-09-29 05:24:48"
|
||||||
"Vo - (voyl)","Chinese Traditional",89,126,0,0,5,0,0,"2020-09-02 23:34:42"
|
|
||||||
ikkaz,Indonesian,89,84,0,5,0,0,4,"2019-09-02 19:58:54"
|
ikkaz,Indonesian,89,84,0,5,0,0,4,"2019-09-02 19:58:54"
|
||||||
"Irene K (Heaun)",Korean,88,75,0,25,0,0,0,"2020-03-16 11:31:12"
|
"Vo - (voyl)","Chinese Traditional",89,126,0,0,5,0,0,"2020-09-02 23:34:42"
|
||||||
|
"Irene K (Heaun)",Korean,88,75,0,25,2,0,0,"2020-03-16 11:31:12"
|
||||||
Prosta4ok_ua,Ukrainian,87,84,0,1,0,0,17,"2020-01-23 19:43:41"
|
Prosta4ok_ua,Ukrainian,87,84,0,1,0,0,17,"2020-01-23 19:43:41"
|
||||||
"Kumar Anand (kumar0500)",Hindi,87,125,0,0,0,0,0,"2020-11-07 02:46:09"
|
"Kumar Anand (kumar0500)",Hindi,87,125,0,0,0,0,0,"2020-11-07 02:46:09"
|
||||||
"Ohad Edri (ohadalte)",Hebrew,85,79,0,0,1,3,18,"2020-07-04 03:42:09"
|
G.kio,Russian,87,82,0,0,1,0,0,"2023-08-24 19:43:00"
|
||||||
helectron,Persian,84,102,0,1,0,0,0,"2021-03-02 04:10:51"
|
"Ohad Edri (ohadalte)",Hebrew,85,79,0,0,1,3,13,"2020-07-04 03:42:09"
|
||||||
"Radu Cebotari (wildProgrammer)",Romanian,84,92,0,1,0,0,0,"2020-02-05 01:20:00"
|
"Radu Cebotari (wildProgrammer)",Romanian,84,92,0,1,1,0,0,"2020-02-05 01:20:00"
|
||||||
"Sofia Neves (sofiasonev)","Portuguese, Brazilian",79,84,0,1,0,0,46,"2020-03-12 18:19:46"
|
helectron,Persian,84,102,0,1,1,0,0,"2021-03-02 04:10:51"
|
||||||
"Jacob Roller (jdr28070)",Korean,79,61,0,0,0,0,0,"2020-01-03 11:36:40"
|
"Bruces Lee (aplusbdesign)",Korean,82,66,0,0,2,0,0,"2021-08-23 11:27:18"
|
||||||
Tiralka,French,79,91,0,92,1,0,0,"2018-02-09 18:39:01"
|
Tiralka,French,79,91,0,92,1,0,0,"2018-02-09 18:39:01"
|
||||||
"Israa Z (sosozozo)",Arabic,79,87,0,43,12,0,3,"2017-11-27 14:10:50"
|
"Jacob Roller (jdr28070)",Korean,79,61,0,0,1,1,0,"2020-01-03 11:36:40"
|
||||||
"Toni Mustonen (toni.mustonen)",Finnish,78,72,0,0,0,0,0,"2017-09-02 05:34:12"
|
"Sofia Neves (sofiasonev)","Portuguese, Brazilian",79,84,0,1,0,0,46,"2020-03-12 18:19:46"
|
||||||
|
"Toni Mustonen (toni.mustonen)",Finnish,78,72,0,0,5,0,0,"2017-09-02 05:34:12"
|
||||||
"Fauz Aladeem (topfauz)",Arabic,76,77,0,0,0,1,0,"2020-02-21 22:46:12"
|
"Fauz Aladeem (topfauz)",Arabic,76,77,0,0,0,1,0,"2020-02-21 22:46:12"
|
||||||
"Michael (quelbs)",German,76,75,0,1,0,0,39,"2020-08-18 07:39:26"
|
"Michael (quelbs)",German,76,75,0,1,0,0,39,"2020-08-18 07:39:26"
|
||||||
"Oliver Gronowski (OliverGronowski)",German,70,69,0,5,0,0,0,"2021-05-14 16:37:10"
|
"Anna Maria Stålberg (stalberg.annamaria)",Swedish,76,77,0,111,4,0,0,"2023-01-16 04:08:25"
|
||||||
|
"Radoslaw Biernacki (radoslaw.biernacki)",Polish,70,74,0,56,5,0,1,"2020-12-15 17:55:31"
|
||||||
|
"Oliver Gronowski (OliverGronowski)",German,70,69,0,5,3,0,0,"2021-05-14 16:37:10"
|
||||||
|
mimizuk,Japanese,68,193,0,0,2,1,39,"2022-05-18 10:10:38"
|
||||||
|
Ryeore,Polish,68,61,0,66,0,0,0,"2022-07-27 12:22:33"
|
||||||
RealDonald,Dutch,67,69,0,121,10,0,0,"2017-06-23 20:10:12"
|
RealDonald,Dutch,67,69,0,121,10,0,0,"2017-06-23 20:10:12"
|
||||||
|
"Dpd Eng (dpdeng)",Korean,67,48,0,0,1,0,0,"2022-10-15 10:56:44"
|
||||||
sirekanyan,"Armenian; Russian",66,65,0,0,0,0,0,"2020-04-18 11:32:52"
|
sirekanyan,"Armenian; Russian",66,65,0,0,0,0,0,"2020-04-18 11:32:52"
|
||||||
"Константин К. (kocyak1991)",Russian,64,60,0,0,1,2,0,"2018-06-10 13:39:37"
|
"Константин К. (kocyak1991)",Russian,64,60,0,0,1,2,0,"2018-06-10 13:39:37"
|
||||||
|
yukitsubaki,Japanese,64,185,0,32,0,0,36,"2020-01-01 13:17:44"
|
||||||
|
Suuis,Hindi,64,110,0,0,0,0,0,"2023-07-02 11:50:22"
|
||||||
"Laura Sophie (laurasophie20)",German,62,67,0,4,0,0,0,"2018-01-06 14:21:24"
|
"Laura Sophie (laurasophie20)",German,62,67,0,4,0,0,0,"2018-01-06 14:21:24"
|
||||||
"Alparslan Sakci (sakci)",Turkish,61,55,0,11,0,0,0,"2021-06-10 11:59:22"
|
|
||||||
raden20,Indonesian,61,62,177,0,1,0,64,"2017-04-09 22:04:23"
|
raden20,Indonesian,61,62,177,0,1,0,64,"2017-04-09 22:04:23"
|
||||||
|
"y (veggente)",Korean,61,56,0,0,0,1,0,"2022-06-28 10:41:18"
|
||||||
"Jan Wojtecki (j4nw)",Polish,58,46,0,0,0,0,26,"2017-11-02 05:42:14"
|
"Jan Wojtecki (j4nw)",Polish,58,46,0,0,0,0,26,"2017-11-02 05:42:14"
|
||||||
"Deepak Bharathi (deepakbharathi1994)",Tamil,56,107,0,0,11,4,0,"2017-09-17 08:00:31"
|
"Deepak Bharathi (deepakbharathi1994)",Tamil,56,107,0,0,13,4,0,"2017-09-17 08:00:31"
|
||||||
"Peter Williams (williamspete001)",Japanese,55,147,0,2,0,0,3,"2020-01-01 13:17:44"
|
|
||||||
"Андрій Козицький (andriikozytskyi1108)",Ukrainian,52,52,0,0,1,0,0,"2018-10-22 01:45:08"
|
"Андрій Козицький (andriikozytskyi1108)",Ukrainian,52,52,0,0,1,0,0,"2018-10-22 01:45:08"
|
||||||
"Nil riera (nilriera2000)",Catalan,52,61,0,1,0,0,0,"2021-06-22 16:37:44"
|
"Nil riera (nilriera2000)",Catalan,52,61,0,1,2,0,0,"2021-06-22 16:37:44"
|
||||||
REMOVED_USER,Italian,51,52,0,2,0,0,0,"2017-08-21 05:15:31"
|
REMOVED_USER,Italian,51,52,0,2,0,0,0,"2017-08-21 05:15:31"
|
||||||
govindap,"Japanese; Hindi",51,114,0,6,1,0,0,"2020-06-02 20:15:52"
|
govindap,"Japanese; Hindi",51,114,0,6,3,1,0,"2020-06-02 20:15:52"
|
||||||
|
"Neoone (Neooneqq)",Romanian,51,54,0,0,0,0,0,"2022-05-05 20:42:11"
|
||||||
"Mare Geldenhuys (mare.geldenhuys)",Afrikaans,50,57,0,0,0,0,0,"2017-10-20 18:00:14"
|
"Mare Geldenhuys (mare.geldenhuys)",Afrikaans,50,57,0,0,0,0,0,"2017-10-20 18:00:14"
|
||||||
"Behnood HRazy (behnoodhr)",Persian,49,70,0,0,0,0,0,"2017-11-25 10:57:21"
|
"Behnood HRazy (behnoodhr)",Persian,49,70,0,0,0,0,0,"2017-11-25 10:57:21"
|
||||||
"tat bz (Tat_i)",German,48,56,0,55,0,0,27,"2021-03-26 05:12:54"
|
"Mahmoud Magdy (M7moudManson)",Arabic,49,60,0,6,12,6,0,"2021-08-21 09:01:38"
|
||||||
J3ll3nl,Dutch,48,48,0,0,17,1,3,"2017-03-31 11:56:09"
|
J3ll3nl,Dutch,48,48,0,0,17,1,3,"2017-03-31 11:56:09"
|
||||||
|
"tat bz (Tat_i)",German,48,56,0,55,0,1,27,"2021-03-26 05:12:54"
|
||||||
"Andrew Firnes (Anechan)",Russian,47,47,0,3,0,0,29,"2019-09-18 09:51:59"
|
"Andrew Firnes (Anechan)",Russian,47,47,0,3,0,0,29,"2019-09-18 09:51:59"
|
||||||
andowero,Czech,47,38,0,0,0,0,0,"2020-01-20 02:29:01"
|
andowero,Czech,47,38,0,0,8,0,0,"2020-01-20 02:29:01"
|
||||||
vach,Armenian,47,36,0,0,0,0,0,"2020-04-18 16:53:12"
|
vach,Armenian,47,36,0,0,0,0,0,"2020-04-18 16:53:12"
|
||||||
"Rahul Shishodia (rahul.shishodia.10)",Hindi,46,85,0,6,5,1,0,"2018-12-24 22:18:19"
|
"Rahul Shishodia (rahul.shishodia.10)",Hindi,46,85,0,6,5,1,0,"2018-12-24 22:18:19"
|
||||||
"Coni Ragni (coni2ragnii)",Spanish,46,46,0,0,0,0,0,"2021-02-28 20:18:37"
|
"Coni Ragni (coni2ragnii)",Spanish,46,46,0,0,0,0,0,"2021-02-28 20:18:37"
|
||||||
Cp0204,"Chinese Simplified",45,72,0,0,0,0,0,"2019-08-20 11:04:27"
|
Cp0204,"Chinese Simplified",45,72,0,0,0,0,0,"2019-08-20 11:04:27"
|
||||||
"cc (cavaz)",Italian,44,41,0,0,0,0,0,"2017-04-01 04:21:08"
|
"cc (cavaz)",Italian,44,41,0,0,0,0,0,"2017-04-01 04:21:08"
|
||||||
"Boban Jagertraum (boban40)",Czech,43,38,0,2,1,1,0,"2017-03-31 09:39:16"
|
"Andrej Šutovský (16andrej.s)",Slovak,44,41,0,0,0,0,0,"2022-06-12 18:01:16"
|
||||||
"Kamil Dziadek (prso94)",Polish,43,39,0,0,2,0,0,"2020-04-06 17:12:06"
|
"Boban Jagertraum (boban40)",Czech,43,38,0,2,31,1,0,"2017-03-31 09:39:16"
|
||||||
"Me Me (gentelwom)",Arabic,42,40,0,0,0,0,0,"2020-11-08 20:44:01"
|
"Kamil Dziadek (prso94)",Polish,43,39,0,0,11,0,0,"2020-04-06 17:12:06"
|
||||||
"Ali Elsheikh (aelsheikh1987)",Arabic,42,41,0,0,0,0,0,"2021-06-16 10:17:26"
|
|
||||||
"Balázs Keresztury (belidzs)",Hungarian,42,41,501,0,7,0,38,"2017-04-06 02:40:24"
|
"Balázs Keresztury (belidzs)",Hungarian,42,41,501,0,7,0,38,"2017-04-06 02:40:24"
|
||||||
andreea.muscalagiu,Romanian,42,52,0,1,0,0,0,"2017-10-22 07:19:49"
|
andreea.muscalagiu,Romanian,42,52,0,1,0,0,0,"2017-10-22 07:19:49"
|
||||||
"Mateusz Duda (MateuszDuda)",Polish,42,42,0,0,0,0,0,"2021-08-17 11:27:11"
|
"Me Me (gentelwom)",Arabic,42,40,0,0,0,0,0,"2020-11-08 20:44:01"
|
||||||
MStefanov,Bulgarian,41,55,2,0,2,0,2,"2017-03-31 16:09:02"
|
"Ali Elsheikh (aelsheikh1987)",Arabic,42,41,0,0,0,0,0,"2021-06-16 10:17:26"
|
||||||
|
"Mateusz Duda (MateuszDuda)",Polish,42,42,0,0,20,0,0,"2021-08-17 11:27:11"
|
||||||
|
"Mr Habti (donhabti)",Arabic,41,40,0,0,0,0,0,"2023-02-20 10:52:50"
|
||||||
"Sofia Veijonen (Suklaa) (sofia.veijonen)",Finnish,40,33,0,0,0,0,0,"2018-03-07 09:24:22"
|
"Sofia Veijonen (Suklaa) (sofia.veijonen)",Finnish,40,33,0,0,0,0,0,"2018-03-07 09:24:22"
|
||||||
|
"Neeraj Verma (verma.neeraj.in)",Hindi,40,65,0,0,1,0,0,"2018-07-23 07:16:41"
|
||||||
"Ali Zali (stm19951995)",Persian,40,60,0,0,0,0,0,"2020-03-23 19:57:26"
|
"Ali Zali (stm19951995)",Persian,40,60,0,0,0,0,0,"2020-03-23 19:57:26"
|
||||||
"Limin Lu (liminlu)","Chinese Simplified",39,79,503,0,0,0,39,"2017-03-31 09:49:35"
|
"Limin Lu (liminlu)","Chinese Simplified",39,79,503,0,0,0,39,"2017-03-31 09:49:35"
|
||||||
dusanstrgar,Slovenian,39,41,0,0,0,0,0,"2017-03-31 10:30:28"
|
Anshoe,Tamil,38,65,0,14,3,0,0,"2018-01-02 11:06:52"
|
||||||
Anshoe,Tamil,38,65,0,14,0,0,0,"2018-01-02 11:06:52"
|
"Pavel Protasov (pvphome)",Russian,38,33,0,0,0,0,0,"2024-02-09 03:40:33"
|
||||||
anasshm,Arabic,37,36,0,9,0,0,0,"2019-01-27 04:07:22"
|
anasshm,Arabic,37,36,0,9,0,0,0,"2019-01-27 04:07:22"
|
||||||
hrexen,Armenian,37,37,0,0,0,0,0,"2020-12-09 02:30:34"
|
hrexen,Armenian,37,37,0,0,0,0,0,"2020-12-09 02:30:34"
|
||||||
"Abdulrahman (D7M)",Arabic,36,39,0,0,0,0,0,"2020-01-29 18:55:30"
|
REMOVED_USER,Swedish,36,33,0,5,2,0,0,"2018-09-29 17:47:33"
|
||||||
|
"Abdulrahman (D7M)",Arabic,36,39,0,0,4,0,0,"2020-01-29 18:55:30"
|
||||||
"Maria Chushnyakova (maria.ch)",Russian,36,31,0,3,0,0,0,"2021-08-17 03:23:58"
|
"Maria Chushnyakova (maria.ch)",Russian,36,31,0,3,0,0,0,"2021-08-17 03:23:58"
|
||||||
REMOVED_USER,Swedish,36,33,0,5,1,0,0,"2018-09-29 17:47:33"
|
xphsis,Basque,36,31,0,0,0,0,0,"2022-01-02 08:16:19"
|
||||||
"長谷川知里 (chase0213)",Japanese,34,138,0,13,0,0,24,"2018-12-14 10:52:44"
|
"長谷川知里 (chase0213)",Japanese,34,138,0,13,0,0,32,"2018-12-14 10:52:44"
|
||||||
"Luis E. Perichon (luisperichon)",Spanish,33,40,0,104,0,0,0,"2017-09-04 13:46:06"
|
|
||||||
"Piotr Łuczyński (peterluczynski)",Polish,33,30,0,6,5,0,2,"2020-01-29 07:27:40"
|
|
||||||
"milad farahani (miladfarmahini90)",Persian,33,44,0,18,1,0,3,"2017-08-31 16:09:00"
|
"milad farahani (miladfarmahini90)",Persian,33,44,0,18,1,0,3,"2017-08-31 16:09:00"
|
||||||
andriikozytskyi2625,Ukrainian,31,23,0,0,0,0,0,"2019-07-08 00:16:41"
|
"Luis E. Perichon (luisperichon)",Spanish,33,40,0,104,0,0,0,"2017-09-04 13:46:06"
|
||||||
Moastafa,Arabic,31,25,0,0,0,0,0,"2020-07-06 11:37:53"
|
"Piotr Łuczyński (peterluczynski)",Polish,33,30,0,6,17,0,2,"2020-01-29 07:27:40"
|
||||||
"hamza gamal (hamzagamal4444)",Arabic,31,28,0,0,0,0,0,"2020-08-03 15:23:34"
|
|
||||||
REMOVED_USER,Russian,31,30,0,2,4,0,3,"2018-12-03 23:55:47"
|
|
||||||
JoeLi,"Chinese Traditional",31,70,0,12,0,0,24,"2017-06-25 05:32:48"
|
JoeLi,"Chinese Traditional",31,70,0,12,0,0,24,"2017-06-25 05:32:48"
|
||||||
|
REMOVED_USER,Russian,31,30,0,2,4,0,3,"2018-12-03 23:55:47"
|
||||||
|
andriikozytskyi2625,Ukrainian,31,23,0,0,0,0,0,"2019-07-08 00:16:41"
|
||||||
|
Moastafa,Arabic,31,25,0,0,0,4,0,"2020-07-06 11:37:53"
|
||||||
|
"hamza gamal (hamzagamal4444)",Arabic,31,28,0,0,1,0,0,"2020-08-03 15:23:34"
|
||||||
yancyn,"Chinese Simplified",30,40,0,0,0,0,1,"2020-05-18 20:06:03"
|
yancyn,"Chinese Simplified",30,40,0,0,0,0,1,"2020-05-18 20:06:03"
|
||||||
"비니몬youtube (khj01025276475)",Korean,29,25,0,0,0,0,0,"2020-02-09 20:44:35"
|
"Siniša Sabljić (ssabljic)",Croatian,30,37,0,0,0,0,0,"2023-11-13 15:51:00"
|
||||||
"Ruud Schouten (ruudschouten)",Dutch,29,32,0,41,3,0,0,"2017-07-22 17:49:17"
|
"Ruud Schouten (ruudschouten)",Dutch,29,32,0,41,3,0,0,"2017-07-22 17:49:17"
|
||||||
"Aaron Dalton (Perlkonig)",French,26,25,0,141,1,0,0,"2018-01-14 12:58:19"
|
"비니몬youtube (khj01025276475)",Korean,29,25,0,0,0,1,0,"2020-02-09 20:44:35"
|
||||||
|
avelneve,Indonesian,29,28,0,0,0,0,0,"2022-04-13 13:26:10"
|
||||||
|
bzhn,Ukrainian,29,26,0,0,4,0,0,"2022-06-18 17:09:13"
|
||||||
|
"Gergő Mihály (mihalygergo97)",Hungarian,28,69,0,0,0,0,0,"2024-02-13 08:35:57"
|
||||||
"Niraj Yadav (neverforgetniraj)",Hindi,26,48,0,0,0,0,0,"2017-04-11 02:26:50"
|
"Niraj Yadav (neverforgetniraj)",Hindi,26,48,0,0,0,0,0,"2017-04-11 02:26:50"
|
||||||
"Guillaume Collic (gcollic)",French,26,28,0,126,11,0,0,"2017-05-05 16:13:00"
|
"Guillaume Collic (gcollic)",French,26,28,0,126,11,0,0,"2017-05-05 16:13:00"
|
||||||
"Radoslaw Biernacki (radoslaw.biernacki)",Polish,26,24,0,8,0,0,1,"2020-12-15 17:55:31"
|
|
||||||
"Jonny I (jonny99dj)",Italian,26,26,0,5,0,0,0,"2017-10-07 07:35:34"
|
"Jonny I (jonny99dj)",Italian,26,26,0,5,0,0,0,"2017-10-07 07:35:34"
|
||||||
|
"Aaron Dalton (Perlkonig)",French,26,25,0,141,1,0,0,"2018-01-14 12:58:19"
|
||||||
|
Pan_Filuta,Czech,25,21,0,5,11,0,3,"2017-04-29 12:55:14"
|
||||||
"Eddie (eddieattaboy)","Chinese Traditional",25,34,0,1,0,0,0,"2020-11-04 21:48:05"
|
"Eddie (eddieattaboy)","Chinese Traditional",25,34,0,1,0,0,0,"2020-11-04 21:48:05"
|
||||||
Pan_Filuta,Czech,25,21,0,5,4,0,3,"2017-04-29 12:55:14"
|
REMOVED_USER,Catalan,24,25,0,2,0,0,0,"2019-06-26 14:59:47"
|
||||||
"eduard83 (barbany.eduard)",Catalan,24,25,0,2,0,0,0,"2019-06-26 14:59:47"
|
"Caner Başaran (basarancaner)",Turkish,23,21,0,0,26,1,0,"2017-04-09 06:34:59"
|
||||||
"Ľuboš Čaky (lubos.caky)",Slovak,23,22,0,0,0,0,0,"2019-07-02 16:51:44"
|
"Ľuboš Čaky (lubos.caky)",Slovak,23,22,0,0,0,0,0,"2019-07-02 16:51:44"
|
||||||
"Caner Başaran (basarancaner)",Turkish,23,21,0,0,21,0,0,"2017-04-09 06:34:59"
|
"A Aa (ylayzlmimashisafyoutub)",Arabic,23,33,0,34,3,2,0,"2021-09-27 15:34:26"
|
||||||
hodanli,Turkish,22,26,0,0,1,0,0,"2017-11-03 14:33:41"
|
hodanli,Turkish,22,26,0,0,1,0,0,"2017-11-03 14:33:41"
|
||||||
gnu-ewm,Polish,22,23,0,6,0,0,0,"2021-02-24 03:42:01"
|
REMOVED_USER,Polish,22,23,0,6,9,0,0,"2021-02-24 03:42:01"
|
||||||
"Neeraj Verma (verma.neeraj.in)",Hindi,22,37,0,0,1,0,0,"2018-07-23 07:16:41"
|
|
||||||
"Alcarkse (alexis.brusle)",French,21,25,0,7,11,0,0,"2017-08-06 09:32:29"
|
"Alcarkse (alexis.brusle)",French,21,25,0,7,11,0,0,"2017-08-06 09:32:29"
|
||||||
olbotta,Italian,20,25,0,2,0,0,0,"2021-06-06 04:22:55"
|
"Hugo Nogueira (hfrnogueira86)",Portuguese,21,22,0,0,0,0,0,"2023-01-09 22:51:24"
|
||||||
"Shashwat (goforgold)",Hindi,20,33,0,0,0,0,0,"2020-05-17 10:34:42"
|
"Shashwat (goforgold)",Hindi,20,33,0,0,0,0,0,"2020-05-17 10:34:42"
|
||||||
|
olbotta,Italian,20,25,0,2,0,0,0,"2021-06-06 04:22:55"
|
||||||
|
"İsa Eş (IsaEs)",Turkish,19,17,0,0,6,2,0,"2017-06-20 07:30:22"
|
||||||
"Magdalena Urbańczyk (madziia139)",Polish,19,19,0,0,0,0,0,"2017-10-21 03:01:04"
|
"Magdalena Urbańczyk (madziia139)",Polish,19,19,0,0,0,0,0,"2017-10-21 03:01:04"
|
||||||
sheeCesu,French,19,18,0,48,4,0,0,"2017-12-21 17:01:39"
|
sheeCesu,French,19,18,0,48,4,0,0,"2017-12-21 17:01:39"
|
||||||
can13,Turkish,19,14,0,8,0,0,0,"2021-01-03 10:39:03"
|
|
||||||
"İsa Eş (IsaEs)",Turkish,19,17,0,0,6,1,0,"2017-06-20 07:30:22"
|
|
||||||
"사자솥 (toke1597)",Korean,19,19,0,0,0,0,0,"2020-02-04 13:36:11"
|
"사자솥 (toke1597)",Korean,19,19,0,0,0,0,0,"2020-02-04 13:36:11"
|
||||||
|
can13,Turkish,19,14,0,8,0,0,0,"2021-01-03 10:39:03"
|
||||||
|
KenKailer,Arabic,19,25,0,0,0,0,0,"2022-05-10 06:16:54"
|
||||||
axikman11111,Uyghur,18,19,0,0,0,0,0,"2018-10-13 12:25:31"
|
axikman11111,Uyghur,18,19,0,0,0,0,0,"2018-10-13 12:25:31"
|
||||||
"Hoon Jung (hooni100)",Korean,17,10,0,0,0,0,0,"2021-01-03 02:26:54"
|
"Sanjay Krishna (sjaykh)",Malayalam,18,42,0,0,0,0,0,"2024-06-01 08:57:37"
|
||||||
|
"Chuang-Chen Chiu (peterChiu9952)","Chinese Traditional",18,28,0,0,0,0,0,"2024-07-02 09:36:59"
|
||||||
|
AlexanderS,German,18,16,0,8,0,0,0,"2025-02-02 16:58:09"
|
||||||
"Ceara Lopez (cealopez)",Spanish,17,18,0,0,5,1,0,"2017-08-22 22:56:13"
|
"Ceara Lopez (cealopez)",Spanish,17,18,0,0,5,1,0,"2017-08-22 22:56:13"
|
||||||
|
Adeline31,French,17,20,0,3,1,0,0,"2019-12-06 00:00:11"
|
||||||
takoyakibento,Korean,17,13,0,3,0,0,0,"2020-08-01 08:44:15"
|
takoyakibento,Korean,17,13,0,3,0,0,0,"2020-08-01 08:44:15"
|
||||||
Adeline31,French,17,20,0,3,0,0,0,"2019-12-06 00:00:11"
|
"Hoon Jung (hooni100)",Korean,17,10,0,0,0,0,0,"2021-01-03 02:26:54"
|
||||||
engineeringforgood,Russian,16,15,0,0,0,0,16,"2021-01-22 03:32:35"
|
Annelotte,Dutch,17,20,0,0,0,0,0,"2022-11-09 08:33:20"
|
||||||
bretzel15,German,16,20,0,0,0,0,0,"2020-04-06 02:49:14"
|
wppoqqqi,Korean,17,18,0,4,0,0,0,"2024-11-30 04:22:21"
|
||||||
"Şamil Ateşoğlu (m.samilatesoglu)",Turkish,16,22,0,11,6,3,0,"2017-07-05 18:37:08"
|
"Şamil Ateşoğlu (m.samilatesoglu)",Turkish,16,22,0,11,6,3,0,"2017-07-05 18:37:08"
|
||||||
DebatablySane,Bulgarian,16,15,0,48,0,0,0,"2017-07-10 15:13:18"
|
DebatablySane,Bulgarian,16,15,0,48,0,0,0,"2017-07-10 15:13:18"
|
||||||
|
bretzel15,German,16,20,0,0,1,0,0,"2020-04-06 02:49:14"
|
||||||
|
engineeringforgood,Russian,16,15,0,0,0,0,16,"2021-01-22 03:32:35"
|
||||||
|
"M7md Salahaddin (m7mdsalahaddin)",Arabic,16,16,0,1,0,0,0,"2024-07-17 18:49:07"
|
||||||
"Bhava Tharini (bhavidanush)",Tamil,15,37,0,0,0,0,0,"2019-10-09 05:43:11"
|
"Bhava Tharini (bhavidanush)",Tamil,15,37,0,0,0,0,0,"2019-10-09 05:43:11"
|
||||||
|
"Ch. (sftblw)",Korean,15,17,0,1,0,0,0,"2023-01-25 19:22:34"
|
||||||
|
iamsurajbobade,Hindi,14,30,0,0,0,0,0,"2018-05-21 11:23:27"
|
||||||
"Zeynep Esen (nezihaesen50)",Turkish,14,13,0,0,0,0,0,"2020-01-28 07:05:15"
|
"Zeynep Esen (nezihaesen50)",Turkish,14,13,0,0,0,0,0,"2020-01-28 07:05:15"
|
||||||
|
"Sanji Vinsmock (mukanzhanbolat4)",Russian,14,14,0,0,0,0,0,"2020-02-18 12:38:54"
|
||||||
|
"Anastasia Borchuk (al2.borchuk)",Russian,14,14,0,0,0,0,0,"2020-04-14 13:22:49"
|
||||||
"Fikret Bilici (fikretbilici)",Turkish,14,13,0,0,0,0,0,"2020-06-21 17:16:11"
|
"Fikret Bilici (fikretbilici)",Turkish,14,13,0,0,0,0,0,"2020-06-21 17:16:11"
|
||||||
"EuiHo Hwang (euiho.hwang)",Korean,14,16,0,0,0,0,0,"2020-06-23 02:40:01"
|
"EuiHo Hwang (euiho.hwang)",Korean,14,16,0,0,1,0,0,"2020-06-23 02:40:01"
|
||||||
"Zeeshan Rabbani (Zeera)",Hindi,14,25,0,0,0,0,0,"2020-09-15 11:32:01"
|
"Zeeshan Rabbani (Zeera)",Hindi,14,25,0,0,0,0,0,"2020-09-15 11:32:01"
|
||||||
"Faiz Ahamed (faiznewton)",Tamil,14,31,0,0,0,0,0,"2021-05-06 23:06:46"
|
"Faiz Ahamed (faiznewton)",Tamil,14,31,0,0,0,0,0,"2021-05-06 23:06:46"
|
||||||
"Anastasia Borchuk (al2.borchuk)",Russian,14,14,0,0,0,0,0,"2020-04-14 13:22:49"
|
|
||||||
iamsurajbobade,Hindi,14,30,0,0,0,0,0,"2018-05-21 11:23:27"
|
|
||||||
"Sanji Vinsmock (mukanzhanbolat4)",Russian,14,14,0,0,0,0,0,"2020-02-18 12:38:54"
|
|
||||||
"Maro Chr (caprisunglasses)",Greek,14,17,0,0,0,0,0,"2021-08-17 06:53:33"
|
"Maro Chr (caprisunglasses)",Greek,14,17,0,0,0,0,0,"2021-08-17 06:53:33"
|
||||||
|
"pi hobbes (uwe_silv)",Japanese,14,46,0,0,0,0,14,"2022-01-15 02:57:14"
|
||||||
|
"Mar Tous (mtousfernandez)",Catalan,14,18,0,0,0,0,0,"2022-08-16 17:55:28"
|
||||||
|
Ferhatt,Turkish,14,13,0,3,0,0,0,"2022-12-13 12:52:20"
|
||||||
|
alchemiker,German,14,13,0,0,0,0,0,"2024-09-03 10:16:04"
|
||||||
"Nenad Vukotic (vukotic.nenad)","Serbian (Cyrillic)",13,13,0,1,2,6,0,"2019-01-31 14:29:15"
|
"Nenad Vukotic (vukotic.nenad)","Serbian (Cyrillic)",13,13,0,1,2,6,0,"2019-01-31 14:29:15"
|
||||||
"Uwe Mönks (schirinowski)",German,13,12,0,0,0,0,0,"2021-02-18 04:00:41"
|
|
||||||
"Dave (xdave)",Hungarian,13,11,0,0,0,0,0,"2020-03-02 20:56:50"
|
"Dave (xdave)",Hungarian,13,11,0,0,0,0,0,"2020-03-02 20:56:50"
|
||||||
soura2,Arabic,12,13,0,0,0,0,0,"2020-01-13 19:23:47"
|
"Uwe Mönks (schirinowski)",German,13,12,0,0,0,0,0,"2021-02-18 04:00:41"
|
||||||
|
Herbie_23,Italian,13,15,0,0,0,0,0,"2022-01-17 17:35:40"
|
||||||
|
"Ana Kelly Vale (anakvale)","Portuguese, Brazilian",13,21,0,4,0,0,2,"2022-03-30 00:15:37"
|
||||||
|
"Minsu (cknblue)",Korean,13,10,0,1,0,0,0,"2022-05-18 00:26:54"
|
||||||
"shreyas (techiespace)",Hindi,12,20,0,0,0,0,0,"2018-06-10 01:14:26"
|
"shreyas (techiespace)",Hindi,12,20,0,0,0,0,0,"2018-06-10 01:14:26"
|
||||||
"Sonu Sharma (riteetude)",Hindi,11,23,0,0,0,0,0,"2021-05-30 19:38:00"
|
soura2,Arabic,12,13,0,0,0,0,0,"2020-01-13 19:23:47"
|
||||||
Vmrc,French,11,12,0,2,0,0,0,"2020-11-02 05:35:06"
|
"Ammar Naif (Ammar_Naif)",Arabic,12,12,0,6,0,0,0,"2022-01-15 05:16:41"
|
||||||
"Jo Chuang (josephch405)","Chinese Traditional",11,24,0,0,0,0,11,"2017-06-16 20:21:06"
|
"Jo Chuang (josephch405)","Chinese Traditional",11,24,0,0,0,0,11,"2017-06-16 20:21:06"
|
||||||
"sathvic k (sathvictripleseven)",Telugu,10,17,0,0,0,0,0,"2020-09-11 08:11:32"
|
Vmrc,French,11,12,0,2,0,0,0,"2020-11-02 05:35:06"
|
||||||
"Brian Camacho (bmcamacho)",Polish,10,11,0,0,1,0,0,"2020-08-03 02:27:28"
|
"Sonu Sharma (riteetude)",Hindi,11,23,0,0,0,0,0,"2021-05-30 19:38:00"
|
||||||
|
"Lucas Depetris (lucasdepetrisd)","Spanish; Catalan; Italian; French",11,12,0,12,0,0,0,"2023-10-24 21:16:21"
|
||||||
|
"Mihael Wagner (miha.wagner)",Slovenian,10,9,0,7,0,0,0,"2017-10-18 18:26:29"
|
||||||
"Anonymous edgy nerd (yamentaad)",Arabic,10,13,0,1,0,0,0,"2018-05-06 09:23:57"
|
"Anonymous edgy nerd (yamentaad)",Arabic,10,13,0,1,0,0,0,"2018-05-06 09:23:57"
|
||||||
"Edwin van Rooij (edwinvrooij)",Dutch,10,13,0,17,0,0,0,"2018-11-05 03:59:10"
|
"Edwin van Rooij (edwinvrooij)",Dutch,10,13,0,17,0,0,0,"2018-11-05 03:59:10"
|
||||||
"Mihael Wagner (miha.wagner)",Slovenian,10,9,0,7,0,0,0,"2017-10-18 18:26:29"
|
"Brian Camacho (bmcamacho)",Polish,10,11,0,0,1,1,0,"2020-08-03 02:27:28"
|
||||||
|
"sathvic k (sathvictripleseven)",Telugu,10,17,0,0,0,0,0,"2020-09-11 08:11:32"
|
||||||
"Ahmed Mosaad (ahmed.mosaad2018)",Arabic,10,12,0,6,0,0,0,"2021-02-03 18:45:43"
|
"Ahmed Mosaad (ahmed.mosaad2018)",Arabic,10,12,0,6,0,0,0,"2021-02-03 18:45:43"
|
||||||
"Suhaili Hassan (kucingsyg96)",Indonesian,9,10,0,0,0,0,0,"2018-06-10 11:55:09"
|
"Hrant Hakobian (hrastgh1)",Armenian,10,9,0,0,0,0,0,"2021-08-29 15:22:10"
|
||||||
"Martin Vostatek (martinvostatek)",Czech,9,8,0,32,2,0,0,"2019-01-21 13:52:36"
|
"Milan Siebenbürger (lennyd)",Czech,10,7,0,1,1,0,0,"2022-01-30 07:09:42"
|
||||||
"Seweryn Piotrowski (Draxxsx)",Polish,9,10,0,0,19,0,0,"2020-01-02 09:55:48"
|
"Zesar Cebrián (Txorrota)",Spanish,10,44,0,0,0,0,0,"2022-02-09 01:34:32"
|
||||||
|
"Слави Велчев (BRO36S) (gg13656)",Bulgarian,10,11,0,9,0,0,0,"2025-01-09 08:47:04"
|
||||||
"Sourire Lucide (sourire_lucide)",Russian,9,10,0,0,1,0,0,"2018-03-22 01:37:55"
|
"Sourire Lucide (sourire_lucide)",Russian,9,10,0,0,1,0,0,"2018-03-22 01:37:55"
|
||||||
|
"Suhaili Hassan (kucingsyg96)",Indonesian,9,10,0,0,0,0,0,"2018-06-10 11:55:09"
|
||||||
|
"Martin Vostatek (martinvostatek)",Czech,9,8,0,32,3,0,0,"2019-01-21 13:52:36"
|
||||||
|
"Seweryn Piotrowski (Draxxsx)",Polish,9,10,0,0,26,0,0,"2020-01-02 09:55:48"
|
||||||
|
omoise,French,9,11,0,1,0,0,0,"2023-12-26 14:27:17"
|
||||||
Rex123,Persian,8,8,0,0,0,0,0,"2017-07-01 00:47:42"
|
Rex123,Persian,8,8,0,0,0,0,0,"2017-07-01 00:47:42"
|
||||||
|
"Jakob Weickmann (jweickm)",Japanese,8,21,0,0,0,0,8,"2021-10-05 11:10:25"
|
||||||
"Andrey ZaXeLoN (waragaa)",Russian,7,7,0,8,1,0,0,"2017-09-18 21:37:42"
|
"Andrey ZaXeLoN (waragaa)",Russian,7,7,0,8,1,0,0,"2017-09-18 21:37:42"
|
||||||
|
"Vladimir Pavlychev (vovs03)",Russian,7,9,0,0,0,0,0,"2017-12-18 02:46:56"
|
||||||
"Konstantin (KZhidovinov)",Russian,7,7,0,0,0,0,0,"2020-01-29 13:35:12"
|
"Konstantin (KZhidovinov)",Russian,7,7,0,0,0,0,0,"2020-01-29 13:35:12"
|
||||||
"Андрій Козицький (andriikozytskyi3807)",Ukrainian,7,12,0,2,0,0,0,"2020-09-26 20:31:56"
|
pkorove,Greek,7,7,0,0,1,0,0,"2020-03-07 11:36:12"
|
||||||
ftfoi,Norwegian,7,6,0,0,0,0,0,"2020-04-11 20:42:35"
|
ftfoi,Norwegian,7,6,0,0,0,0,0,"2020-04-11 20:42:35"
|
||||||
"Vladimir Pavlychev (KeyJoo)",Russian,7,9,0,0,0,0,0,"2017-12-18 02:46:56"
|
"Андрій Козицький (andriikozytskyi3807)",Ukrainian,7,12,0,2,0,0,0,"2020-09-26 20:31:56"
|
||||||
pkorove,Greek,7,7,0,0,0,0,0,"2020-03-07 11:36:12"
|
"Felipe Chagas (chagretes)","Portuguese, Brazilian",7,8,0,0,3,0,5,"2022-01-10 12:20:25"
|
||||||
|
"Tomáš Miklovič (zyppi)",Slovak,7,7,0,0,0,0,0,"2022-09-11 15:12:06"
|
||||||
|
"Sam (SorodonSorodon)",German,6,6,0,13,0,0,0,"2017-04-14 11:09:27"
|
||||||
|
ChloeLiang,Japanese,6,22,0,0,1,0,3,"2017-08-08 05:02:59"
|
||||||
|
"닉닉 (seohu9466)",Korean,6,14,0,13,0,0,0,"2017-10-09 23:08:15"
|
||||||
erfan2927,Persian,6,6,0,0,0,0,0,"2018-04-09 02:12:44"
|
erfan2927,Persian,6,6,0,0,0,0,0,"2018-04-09 02:12:44"
|
||||||
"Burak Ceylan (7burakceylan)",Turkish,6,6,0,0,0,0,0,"2018-05-20 17:24:19"
|
"Burak Ceylan (7burakceylan)",Turkish,6,6,0,0,0,0,0,"2018-05-20 17:24:19"
|
||||||
"Sam (SorodonSorodon)",German,6,6,0,13,0,0,0,"2017-04-14 11:09:27"
|
|
||||||
"닉닉 (seohu9466)",Korean,6,14,0,13,0,0,0,"2017-10-09 23:08:15"
|
|
||||||
"Sarita Cajas (sarayanacajas)",Spanish,6,4,0,0,1,0,0,"2021-05-14 14:27:59"
|
"Sarita Cajas (sarayanacajas)",Spanish,6,4,0,0,1,0,0,"2021-05-14 14:27:59"
|
||||||
ChloeLiang,Japanese,6,22,0,0,1,0,3,"2017-08-08 05:02:59"
|
"خالد (mkhrafi1999)",Arabic,6,3,0,6,0,0,0,"2023-06-25 00:36:13"
|
||||||
"Manuel Tassi (Mannivu)",Italian,5,6,0,0,0,0,0,"2021-01-03 11:00:33"
|
|
||||||
"Tomáš Hrabáček (Hrabyyy)",Czech,5,3,0,0,0,0,0,"2021-05-27 11:58:11"
|
|
||||||
"Guerra Ivaneth (rossanaiva-04)",Spanish,5,7,0,0,0,0,0,"2019-02-03 16:48:59"
|
|
||||||
"Дмитрий Хапенков (d.khapenkov)",Russian,5,5,0,6,4,0,2,"2018-01-06 23:00:43"
|
|
||||||
"Matthias Joly (joly.matt12)",French,5,8,0,27,1,0,0,"2017-08-28 09:53:59"
|
"Matthias Joly (joly.matt12)",French,5,8,0,27,1,0,0,"2017-08-28 09:53:59"
|
||||||
"Micaela Pighin (micaelapiighin)",Spanish,5,6,0,1,0,0,0,"2019-10-09 23:32:42"
|
|
||||||
andriikozytskyi2018,Ukrainian,5,5,0,0,0,0,0,"2017-09-03 05:24:43"
|
andriikozytskyi2018,Ukrainian,5,5,0,0,0,0,0,"2017-09-03 05:24:43"
|
||||||
marmo,German,4,4,0,0,0,0,0,"2021-01-13 01:16:35"
|
"Дмитрий Хапенков (d.khapenkov)",Russian,5,5,0,6,4,0,2,"2018-01-06 23:00:43"
|
||||||
"Eli Besirov (elibesirov07)",Turkish,4,4,0,0,0,0,0,"2019-03-25 07:12:34"
|
"Guerra Ivaneth (rossanaiva-04)",Spanish,5,7,0,0,0,0,0,"2019-02-03 16:48:59"
|
||||||
|
"Micaela Pighin (micaelapiighin)",Spanish,5,6,0,1,0,0,0,"2019-10-09 23:32:42"
|
||||||
|
"Manuel (Mannivu)",Italian,5,6,0,0,0,0,0,"2021-01-03 11:00:33"
|
||||||
|
"Tomáš Hrabáček (Hrabyyy)",Czech,5,3,0,0,2,0,0,"2021-05-27 11:58:11"
|
||||||
|
"Vitor Henrique (vitorhcl)","Portuguese, Brazilian",5,8,0,1,0,0,0,"2022-03-08 20:00:59"
|
||||||
|
SubhamJena,Hindi,5,12,0,3,0,0,0,"2023-04-19 11:13:19"
|
||||||
"Lopo Isaac Fernández (rocapata)",Spanish,4,3,0,0,0,0,0,"2018-09-20 11:46:22"
|
"Lopo Isaac Fernández (rocapata)",Spanish,4,3,0,0,0,0,0,"2018-09-20 11:46:22"
|
||||||
bziuum,Polish,4,4,0,0,0,0,0,"2020-09-01 09:08:01"
|
"Eli Besirov (elibesirov07)",Turkish,4,4,0,0,0,0,0,"2019-03-25 07:12:34"
|
||||||
"Neko123 (emandic11)","Serbian (Cyrillic)",4,4,0,57,0,0,0,"2021-04-21 15:33:29"
|
bziuum,Polish,4,4,0,0,6,0,0,"2020-09-01 09:08:01"
|
||||||
Magidxz,Arabic,3,3,0,0,0,0,0,"2021-01-05 05:02:54"
|
marmo,German,4,4,0,0,0,0,0,"2021-01-13 01:16:35"
|
||||||
"mohammadali barati (mabaraty)",Persian,3,3,0,0,0,0,0,"2021-07-10 05:54:44"
|
"Neko123 (emandic11)","Serbian (Cyrillic)",4,4,0,57,0,0,1,"2021-04-21 15:33:29"
|
||||||
"Sarath S (CyberShark)",Tamil,3,7,0,0,0,0,0,"2020-08-27 22:43:16"
|
"Mo Heydari (Mrheydari)",Dutch,4,4,0,0,0,0,0,"2023-02-21 04:54:49"
|
||||||
"Unnie Here (Carb)",Hindi,3,8,0,0,0,0,0,"2020-03-18 23:34:35"
|
"Srekaravarshan N K (srekaravarshan)",Tamil,4,4,0,0,0,0,0,"2023-04-22 06:08:57"
|
||||||
REMOVED_USER,"Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-11-18 09:02:37"
|
|
||||||
"Thoum Ptrgnt (thomas.petrignet)",French,3,3,0,2,0,3,0,"2017-09-23 19:25:52"
|
"Thoum Ptrgnt (thomas.petrignet)",French,3,3,0,2,0,3,0,"2017-09-23 19:25:52"
|
||||||
"Oleg Kogut (kogut_oleg)",Ukrainian,3,3,0,0,0,0,0,"2018-12-28 14:31:02"
|
|
||||||
carsten_kafke,German,3,3,0,43,0,0,3,"2017-10-27 13:27:47"
|
carsten_kafke,German,3,3,0,43,0,0,3,"2017-10-27 13:27:47"
|
||||||
"Vagner Roberto (vagner.trompete)","Portuguese, Brazilian",3,3,0,0,0,0,0,"2017-12-30 17:54:26"
|
"Vagner Roberto (vagner.trompete)","Portuguese, Brazilian",3,3,0,0,0,0,0,"2017-12-30 17:54:26"
|
||||||
"Igor Piskun (i_piskun)",Ukrainian,3,3,0,0,0,0,0,"2018-01-19 15:20:27"
|
"Igor Piskun (i_piskun)",Ukrainian,3,3,0,0,0,0,0,"2018-01-19 15:20:27"
|
||||||
"Andrea Bianchi (andreawhite1597)",Italian,3,1,0,1,0,0,0,"2018-01-21 17:45:48"
|
"Andrea Bianchi (andreawhite1597)",Italian,3,1,0,1,0,0,0,"2018-01-21 17:45:48"
|
||||||
"Cláudio Bernardo (claudiobernardo.ti)","Portuguese, Brazilian",3,4,0,1,0,0,0,"2019-01-08 14:41:10"
|
|
||||||
"Hiohana Rilary (hiohanarilary)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2019-07-31 20:42:20"
|
|
||||||
"joabe gabriel (joabegabrielcma1)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-08-21 09:08:59"
|
|
||||||
"Péter Bernát (bernatp)",Hungarian,3,2,0,0,0,0,0,"2019-11-30 15:50:33"
|
|
||||||
"Martin Zimdahl (zimdahlmartin)",Swedish,3,2,0,0,1,0,3,"2018-09-15 04:39:22"
|
|
||||||
"Gabriel Cavalcante (gabrielc.alves14)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-08-06 22:24:54"
|
"Gabriel Cavalcante (gabrielc.alves14)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-08-06 22:24:54"
|
||||||
|
"joabe gabriel (joabegabrielcma1)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-08-21 09:08:59"
|
||||||
|
"Martin Zimdahl (zimdahlmartin)",Swedish,3,2,0,0,2,0,3,"2018-09-15 04:39:22"
|
||||||
|
REMOVED_USER,"Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-11-18 09:02:37"
|
||||||
|
"Oleg Kogut (kogut_oleg)",Ukrainian,3,3,0,0,0,0,0,"2018-12-28 14:31:02"
|
||||||
|
"Cláudio Bernardo (claudiobernardo.ti)","Portuguese, Brazilian",3,4,0,1,0,0,0,"2019-01-08 14:41:10"
|
||||||
atomjani,Hungarian,3,3,0,0,0,0,0,"2019-01-19 00:49:25"
|
atomjani,Hungarian,3,3,0,0,0,0,0,"2019-01-19 00:49:25"
|
||||||
"أم محمد تقي (souadboudia19)",Arabic,2,2,0,0,0,0,0,"2020-06-13 15:24:17"
|
"Hiohana Rilary (hiohanarilary)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2019-07-31 20:42:20"
|
||||||
"FAy FAy (fayfayfay52)","Chinese Traditional",2,5,0,0,0,0,0,"2017-10-06 08:53:21"
|
"Péter Bernát (bernatp)",Hungarian,3,2,0,0,0,0,0,"2019-11-30 15:50:33"
|
||||||
chavs1997,Russian,2,2,0,9,0,0,0,"2018-05-18 16:58:19"
|
"Unnie Here (Carb)",Hindi,3,8,0,0,0,0,0,"2020-03-18 23:34:35"
|
||||||
Soroor_SI,Persian,2,2,0,0,0,0,0,"2018-06-10 06:28:27"
|
"Sarath S (CyberShark)",Tamil,3,7,0,0,0,0,0,"2020-08-27 22:43:16"
|
||||||
"Ilyas Fekhar (il47yas)",Arabic,2,2,0,0,0,0,0,"2018-04-17 22:00:41"
|
Magidxz,Arabic,3,3,0,0,0,0,0,"2021-01-05 05:02:54"
|
||||||
"hesamiranii (esam.matouri)",Persian,2,2,0,0,0,0,0,"2018-09-22 16:33:36"
|
"mohammadali barati (mabaraty)",Persian,3,3,0,0,0,0,0,"2021-07-10 05:54:44"
|
||||||
"fatemeh s (fargolseifoori3)",Persian,2,2,0,0,0,0,0,"2019-01-31 12:06:57"
|
"Tejaswini Boppana (Tejaswini)",Telugu,3,1,0,0,0,0,0,"2021-08-27 23:48:55"
|
||||||
amei,"Portuguese, Brazilian",2,2,0,0,0,0,0,"2018-04-19 19:42:28"
|
"Craig Foobar (craig.foobar)",German,3,3,0,25,1,0,0,"2022-02-20 16:55:47"
|
||||||
"Naveen jai krishna (njsbpolymer1)",Tamil,2,5,0,0,0,0,0,"2020-01-10 14:19:41"
|
Katarin,Ukrainian,3,3,0,0,0,0,0,"2022-03-17 14:44:59"
|
||||||
"Danial Agh (danialagh)",Persian,2,3,0,0,0,0,0,"2019-03-30 13:24:16"
|
ayet,Arabic,3,3,0,0,0,0,0,"2023-08-16 20:18:12"
|
||||||
"Walid Baazia (walidbaazia2005)",Arabic,2,1,0,0,0,0,0,"2021-01-27 12:47:34"
|
|
||||||
"Ali Zaida (alizaeda92)",Arabic,2,2,0,0,0,0,0,"2019-12-01 11:47:00"
|
|
||||||
LNDDYL,"Chinese Traditional",2,4,0,0,0,0,2,"2018-04-22 04:00:19"
|
|
||||||
"Ño Bí Tã (pt614553)",Arabic,2,8,0,1,0,0,0,"2021-05-22 20:41:01"
|
|
||||||
"Judith Ayala (Azul1612)",Spanish,2,1,0,0,0,1,0,"2021-05-18 17:07:19"
|
|
||||||
REMOVED_USER,Ukrainian,2,2,0,0,0,0,0,"2017-06-15 12:24:44"
|
REMOVED_USER,Ukrainian,2,2,0,0,0,0,0,"2017-06-15 12:24:44"
|
||||||
"Valerij D (vala.dobler)",German,2,2,0,0,0,0,0,"2018-09-22 09:38:27"
|
|
||||||
"Alex Stein (diefaust1993)",Russian,2,2,0,4,4,0,2,"2017-07-13 06:56:17"
|
"Alex Stein (diefaust1993)",Russian,2,2,0,4,4,0,2,"2017-07-13 06:56:17"
|
||||||
"조화정 (yunjoo337)",Korean,2,2,0,0,0,0,0,"2019-06-16 22:25:31"
|
|
||||||
omerfarukbas,Turkish,2,3,0,19,2,0,0,"2017-08-14 16:10:35"
|
omerfarukbas,Turkish,2,3,0,19,2,0,0,"2017-08-14 16:10:35"
|
||||||
"Balthazar Aubard (Balatzar)",French,2,5,0,0,1,0,0,"2017-09-23 01:42:57"
|
"Balthazar Aubard (Balatzar)",French,2,5,0,0,1,0,0,"2017-09-23 01:42:57"
|
||||||
"Luca Gori (grolcu)",Italian,1,2,0,0,0,0,0,"2020-09-26 23:26:15"
|
"FAy FAy (fayfayfay52)","Chinese Traditional",2,5,0,0,0,0,0,"2017-10-06 08:53:21"
|
||||||
axd,Spanish,1,1,0,15,0,0,0,"2017-09-12 05:48:51"
|
"Ilyas Fekhar (il47yas)",Arabic,2,2,0,0,0,0,0,"2018-04-17 22:00:41"
|
||||||
|
amei,"Portuguese, Brazilian",2,2,0,0,0,0,0,"2018-04-19 19:42:28"
|
||||||
|
"Jimmy Young (Jimmyyoung)","Chinese Traditional",2,4,0,0,0,0,2,"2018-04-22 04:00:19"
|
||||||
|
chavs1997,Russian,2,2,0,9,0,0,0,"2018-05-18 16:58:19"
|
||||||
|
Soroor_SI,Persian,2,2,0,0,0,0,0,"2018-06-10 06:28:27"
|
||||||
|
"Valerij D (vala.dobler)",German,2,2,0,0,0,0,0,"2018-09-22 09:38:27"
|
||||||
|
"hesamiranii (esam.matouri)",Persian,2,2,0,0,0,0,0,"2018-09-22 16:33:36"
|
||||||
|
"fatemeh s (fargolseifoori3)",Persian,2,2,0,0,0,0,0,"2019-01-31 12:06:57"
|
||||||
|
"Danial Agh (danialagh)",Persian,2,3,0,0,0,0,0,"2019-03-30 13:24:16"
|
||||||
|
"조화정 (yunjoo337)",Korean,2,2,0,0,0,0,0,"2019-06-16 22:25:31"
|
||||||
|
"Ali Zaida (alizaeda92)",Arabic,2,2,0,0,0,0,0,"2019-12-01 11:47:00"
|
||||||
|
"Naveen jai krishna (njsbpolymer1)",Tamil,2,5,0,0,1,0,0,"2020-01-10 14:19:41"
|
||||||
|
"أم محمد تقي (souadboudia19)",Arabic,2,2,0,0,0,0,0,"2020-06-13 15:24:17"
|
||||||
|
"Walid Baazia (walidbaazia2005)",Arabic,2,1,0,0,0,0,0,"2021-01-27 12:47:34"
|
||||||
|
"Judith Ayala (Azul1612)",Spanish,2,1,0,0,0,1,0,"2021-05-18 17:07:19"
|
||||||
|
"Ño Bí Tã (pt614553)",Arabic,2,8,0,1,0,2,0,"2021-05-22 20:41:01"
|
||||||
|
"Héctor Mañas García (hectodium)",Catalan,2,3,0,0,0,0,0,"2021-10-02 20:32:09"
|
||||||
|
"Sidali Aymen (sidaliaymen950)",Arabic,2,2,0,0,0,0,0,"2022-01-31 18:50:59"
|
||||||
|
"Ahmed Bazazo (ahmedbazazo)",Arabic,2,2,0,0,0,0,0,"2022-02-19 20:11:09"
|
||||||
|
"HypemanKEK (rocasta.dodvi)",Russian,2,2,0,0,0,0,0,"2023-01-13 03:45:06"
|
||||||
|
"Gmas (gustmaes1)",Dutch,2,2,0,0,0,0,0,"2023-01-26 13:52:54"
|
||||||
|
"Катерина Ховалкина (katerina959)",Russian,2,2,0,1,0,0,0,"2023-05-18 14:50:30"
|
||||||
|
"Pratheba Devanathan (devprath05)",Tamil,2,2,0,0,1,0,0,"2023-06-05 12:35:45"
|
||||||
|
"Gordon James Campbell (gordonjamescampbell)",Catalan,2,2,0,0,0,0,0,"2023-06-23 23:23:46"
|
||||||
|
"Suren Airyanam (suren.airyanam)",Persian,2,2,0,0,0,0,0,"2023-10-21 18:01:41"
|
||||||
|
axq,German,2,1,0,1,0,0,0,"2024-02-29 17:14:13"
|
||||||
|
"Hades Mori (Hades_Mori)",Ukrainian,2,2,0,0,0,0,0,"2024-07-03 07:14:58"
|
||||||
iSoron2,"Portuguese, Brazilian",1,1,0,0,0,0,0,"2017-03-18 17:56:29"
|
iSoron2,"Portuguese, Brazilian",1,1,0,0,0,0,0,"2017-03-18 17:56:29"
|
||||||
REMOVED_USER,Russian,1,2,0,6,1,0,1,"2019-12-26 05:37:01"
|
|
||||||
"Wibi Cahyo (wbcahyoh)",Indonesian,1,3,0,0,0,0,0,"2017-12-14 06:35:58"
|
|
||||||
jonesses,German,1,1,0,1,0,0,1,"2021-01-01 08:03:18"
|
|
||||||
"Anton (tT0NG)","Chinese Traditional",1,2,0,0,0,0,1,"2017-07-06 14:18:39"
|
"Anton (tT0NG)","Chinese Traditional",1,2,0,0,0,0,1,"2017-07-06 14:18:39"
|
||||||
"박찌 (perpact20)",Korean,1,1,0,0,0,0,0,"2018-02-10 10:11:44"
|
axd,Spanish,1,1,0,15,1,0,0,"2017-09-12 05:48:51"
|
||||||
|
"Wibi Cahyo (wbcahyoh)",Indonesian,1,3,0,0,0,0,0,"2017-12-14 06:35:58"
|
||||||
"Alan Jeon (skyisle)",Korean,1,2,0,8,0,0,0,"2018-01-09 10:46:00"
|
"Alan Jeon (skyisle)",Korean,1,2,0,8,0,0,0,"2018-01-09 10:46:00"
|
||||||
|
"박찌 (perpact20)",Korean,1,1,0,0,0,0,0,"2018-02-10 10:11:44"
|
||||||
|
"Patrick Pimenta (trickap1)","Portuguese, Brazilian",1,1,0,0,0,0,0,"2018-12-01 14:31:21"
|
||||||
|
"Kan Black (kanblack.va)",Vietnamese,1,2,0,0,0,1,0,"2019-01-15 03:50:10"
|
||||||
"Maria Fefelova (mashafefel)",Russian,1,1,0,0,0,0,0,"2019-05-18 02:03:56"
|
"Maria Fefelova (mashafefel)",Russian,1,1,0,0,0,0,0,"2019-05-18 02:03:56"
|
||||||
"Anastasiia Bondarenko (nastasya.bondarenko.97)",Russian,1,1,0,0,0,0,0,"2019-06-07 17:43:08"
|
"Anastasiia Bondarenko (nastasya.bondarenko.97)",Russian,1,1,0,0,0,0,0,"2019-06-07 17:43:08"
|
||||||
"Kan Black (kanblack.va)",Vietnamese,1,2,0,0,0,1,0,"2019-01-15 03:50:10"
|
REMOVED_USER,Russian,1,2,0,6,1,0,1,"2019-12-26 05:37:01"
|
||||||
"Patrick Pimenta (trickap1)","Portuguese, Brazilian",1,1,0,0,0,0,0,"2018-12-01 14:31:21"
|
"Luca Gori (grolcu)",Italian,1,2,0,0,0,0,0,"2020-09-26 23:26:15"
|
||||||
"Dagna Q (dagnaq)",,0,0,0,0,0,0,0,"2017-08-06 01:42:52"
|
jonesses,German,1,1,0,1,0,0,1,"2021-01-01 08:03:18"
|
||||||
Kamalakannan,,0,0,0,0,0,0,0,"2017-05-14 11:40:23"
|
"monir s (ms.alam)",Persian,1,1,0,1,0,0,0,"2022-05-23 06:34:00"
|
||||||
"Éjbãss Übbeî (littlebittlebottle)",Norwegian,0,0,0,152,0,0,0,"2017-07-05 21:12:02"
|
"Daniel Luque (LuqueDaniel)",Spanish,1,1,0,0,0,0,0,"2022-06-30 20:37:07"
|
||||||
"Равиль Мифтахов (ravilmif47)",Russian,0,0,0,1,0,0,0,"2019-08-12 21:58:30"
|
Liboide,Spanish,1,1,0,0,0,0,0,"2022-11-03 23:57:45"
|
||||||
sanyoniket,,0,0,0,0,0,0,0,"2019-07-23 12:58:40"
|
"K RITE (kriteshojha5)",Hindi,1,1,0,1,0,0,0,"2024-08-14 17:28:55"
|
||||||
REMOVED_USER,,0,0,0,0,0,0,0,"2020-02-01 03:47:48"
|
"Angelos (angelos1993)",Arabic,1,1,0,0,0,0,0,"2024-11-20 07:38:18"
|
||||||
"vi ve (VimalV)",,0,0,0,0,0,0,0,"2021-02-08 02:35:45"
|
"Bora Atıcı (Brtc)",Turkish,1,2,0,0,0,0,0,"2025-03-07 20:33:19"
|
||||||
"George Merkulov (george142.emarket)",Russian,0,0,0,11,0,0,0,"2019-06-09 19:47:02"
|
EmanAmini,,0,0,0,0,0,0,0,"2017-03-31 13:27:43"
|
||||||
"Yasin Okumus (lacivert)",Turkish,0,0,0,1,0,0,0,"2018-02-07 04:13:51"
|
AnggaRifandi,,0,0,0,0,0,0,0,"2017-03-31 19:28:35"
|
||||||
"Petros Bleyan (coolbleyan)",Russian,0,0,0,14,0,0,0,"2017-08-18 18:37:18"
|
|
||||||
"LeMeD (LeMeS)",French,0,0,0,2,0,0,0,"2021-02-06 15:35:00"
|
|
||||||
ava_rfie,Persian,0,0,0,1,0,0,0,"2019-06-09 16:19:24"
|
|
||||||
"Mateusz Teteruk (mttet)",Polish,0,0,0,1,0,0,0,"2021-01-23 13:09:59"
|
|
||||||
EwanB,,0,0,0,0,0,0,0,"2019-11-19 10:04:38"
|
|
||||||
Fazy1380,,0,0,0,0,0,0,0,"2021-04-10 11:02:53"
|
|
||||||
"Lori Amico (lavodkaclyde2323)",Italian,0,0,0,1,0,0,0,"2017-04-09 10:08:13"
|
"Lori Amico (lavodkaclyde2323)",Italian,0,0,0,1,0,0,0,"2017-04-09 10:08:13"
|
||||||
"Florian Stuhlmann (stuhlmann)",German,0,0,0,10,0,0,0,"2017-04-15 04:04:00"
|
"Florian Stuhlmann (stuhlmann)",German,0,0,0,10,0,0,0,"2017-04-15 04:04:00"
|
||||||
"عبد الناصر سعيد الثبيتي (asaeed)",,0,0,0,0,0,0,0,"2018-03-13 02:09:35"
|
Kamalakannan,,0,0,0,0,0,0,0,"2017-05-14 11:40:23"
|
||||||
"Rivo Zängov (Eraser)",,0,0,0,0,0,0,0,"2020-10-13 04:38:26"
|
"Éjbãss Übbeî (littlebittlebottle)",Norwegian,0,0,0,152,0,0,0,"2017-07-05 21:12:02"
|
||||||
Hayder21,,0,0,0,0,0,0,0,"2019-12-31 10:56:24"
|
"Dagna Q (dagnaq)",,0,0,0,0,0,0,0,"2017-08-06 01:42:52"
|
||||||
T-v-Gerwen,Dutch,0,0,0,47,0,0,0,"2018-03-02 10:26:33"
|
"Petros Bleyan (coolbleyan)",Russian,0,0,0,14,0,0,0,"2017-08-18 18:37:18"
|
||||||
"Eduard Boboc (edi.boboc33)",Romanian,0,0,0,4,0,0,0,"2019-12-16 09:08:39"
|
|
||||||
"Samuel Przeździęk (samek22)",Polish,0,0,0,1,0,0,0,"2021-08-01 00:49:01"
|
|
||||||
"Saiprasath B (Saiprasath)",,0,0,0,0,0,0,0,"2021-07-11 11:10:41"
|
|
||||||
shuvo786,,0,0,0,0,0,0,0,"2019-11-13 00:18:12"
|
|
||||||
"Edmunds Edmundam (edmundam)",,0,0,0,0,0,0,0,"2020-06-01 14:18:18"
|
|
||||||
Itch,,0,0,0,0,0,0,0,"2017-10-16 09:18:42"
|
Itch,,0,0,0,0,0,0,0,"2017-10-16 09:18:42"
|
||||||
"Manny Farsangy (manifarsangi)",Persian,0,0,0,12,0,0,0,"2021-08-10 05:32:28"
|
"Muhammet Furkan ALMACI (furkan.almaci)",Turkish,0,0,0,1,0,0,0,"2017-10-29 13:44:56"
|
||||||
"Matus Zdansky (matuszdansky)",,0,0,0,0,0,0,0,"2019-10-20 13:52:24"
|
|
||||||
"Thomas Orlita (Thomas995)",Czech,0,0,0,1,0,0,0,"2017-12-24 04:08:27"
|
|
||||||
Irsgram,Russian,0,0,0,1,0,0,0,"2019-09-30 16:42:20"
|
|
||||||
EmanAmini,,0,0,0,0,0,0,0,"2017-03-31 13:27:43"
|
|
||||||
mushin,,0,0,0,0,0,0,0,"2020-02-02 04:08:05"
|
|
||||||
"Elmo (oberknecht)",,0,0,0,0,0,0,0,"2020-04-16 08:45:50"
|
|
||||||
AnggaRifandi,,0,0,0,0,0,0,0,"2017-03-31 19:28:35"
|
|
||||||
"darkkingredian (rediancool)",,0,0,0,0,0,0,0,"2021-07-27 16:04:32"
|
|
||||||
"Sri Harsha Bhogi (sriharshabhogi)",,0,0,0,0,0,0,0,"2018-09-02 05:31:53"
|
|
||||||
"Nat Fomicheva (natac)",Russian,0,0,0,3,0,0,0,"2019-01-25 14:35:02"
|
|
||||||
mdrobulis,,0,0,0,0,0,0,0,"2018-05-24 01:40:42"
|
|
||||||
"Sarah BCNN (fsarahboucenna)",French,0,0,0,16,0,0,0,"2018-02-11 11:07:36"
|
|
||||||
"Arjun K. (arjunkdot)",,0,0,0,0,0,0,0,"2020-09-20 11:16:18"
|
|
||||||
REMOVED_USER,Czech,0,0,0,18,0,0,0,"2018-03-27 06:19:52"
|
|
||||||
martyaberger,,0,0,0,0,0,0,0,"2019-01-01 18:48:08"
|
|
||||||
BongTran,Vietnamese,0,0,0,2,0,0,0,"2018-04-24 05:16:07"
|
|
||||||
"Arttu Ylhävuori (arttu.ylhavuori)",,0,0,0,0,0,0,0,"2019-07-24 15:03:42"
|
|
||||||
"Никита Карамов (nikita.karamoff)",Russian,0,0,0,10,0,0,0,"2018-10-29 03:57:21"
|
|
||||||
rooban23,,0,0,0,0,0,0,0,"2020-09-15 11:49:14"
|
|
||||||
"Eliška Roubalová (roubaeli)",Czech,0,0,0,6,0,0,0,"2019-12-31 12:47:29"
|
|
||||||
valney.faria,"Portuguese, Brazilian",0,0,0,1,0,0,0,"2020-02-02 14:45:02"
|
|
||||||
"Алтынбек Наурызғали (altinbeknaurizgali)",Russian,0,0,0,1,0,0,0,"2020-08-12 13:03:49"
|
|
||||||
REMOVED_USER,,0,0,0,0,0,0,0,"2018-10-27 15:34:36"
|
|
||||||
REMOVED_USER,,0,0,0,0,0,0,0,"2018-08-24 00:17:43"
|
|
||||||
Elham1361,,0,0,0,0,0,0,0,"2018-10-27 12:01:06"
|
|
||||||
dongchen.yue,German,0,0,0,4,0,0,0,"2020-09-12 15:05:59"
|
|
||||||
"Ahnaf Tajwar (atn4404)",,0,0,0,0,0,0,0,"2018-10-16 11:13:30"
|
|
||||||
AsadullahIlyas,,0,0,0,0,0,0,0,"2019-01-04 06:14:15"
|
|
||||||
droidahmed,Arabic,0,0,0,7,0,0,0,"2018-01-31 02:18:49"
|
|
||||||
philfr49,French,0,0,0,2,0,0,0,"2018-09-03 14:20:32"
|
|
||||||
"Ahmed Nazir (ahmednazir333)",,0,0,0,0,0,0,0,"2018-05-06 12:10:27"
|
|
||||||
"Balaji Jayaraman (jkbalaji1103)",,0,0,0,0,0,0,0,"2017-10-30 22:12:27"
|
"Balaji Jayaraman (jkbalaji1103)",,0,0,0,0,0,0,0,"2017-10-30 22:12:27"
|
||||||
"Wellington Ribeiro (wellington.rib)",,0,0,0,0,0,0,0,"2017-11-16 07:32:25"
|
"Wellington Ribeiro (wellington.rib)",,0,0,0,0,0,0,0,"2017-11-16 07:32:25"
|
||||||
"Javid IRAN (twitteriran98)",Persian,0,0,0,1,0,0,0,"2017-11-25 16:47:25"
|
"Javid IRAN (twitteriran98)",Persian,0,0,0,1,0,0,0,"2017-11-25 16:47:25"
|
||||||
"박인호 (wphestiraid)",Korean,0,0,0,2,0,0,0,"2018-01-05 00:33:14"
|
REMOVED_USER,Czech,0,0,0,1,0,0,0,"2017-12-24 04:08:27"
|
||||||
"Pumpith Ungsupanit (pumpithu)",,0,0,0,0,0,0,0,"2019-01-19 23:47:57"
|
|
||||||
Sandhu564.,,0,0,0,0,0,0,0,"2020-12-14 01:27:45"
|
|
||||||
"Quentin Hibon (hiq)",,0,0,0,0,0,0,0,"2021-02-07 16:39:31"
|
|
||||||
AhmedDz,Arabic,0,0,0,1,0,0,0,"2017-12-31 10:12:31"
|
AhmedDz,Arabic,0,0,0,1,0,0,0,"2017-12-31 10:12:31"
|
||||||
"Shuvashish Sahoo (shuvashish76)",,0,0,0,0,0,0,0,"2020-09-17 09:10:09"
|
"박인호 (wphestiraid)",Korean,0,0,0,2,0,0,0,"2018-01-05 00:33:14"
|
||||||
REMOVED_USER,,0,0,0,0,0,0,0,"2018-01-05 16:56:12"
|
REMOVED_USER,,0,0,0,0,0,0,0,"2018-01-05 16:56:12"
|
||||||
NairaDNV,Spanish,0,0,0,9,0,0,0,"2018-01-05 19:10:33"
|
NairaDNV,Spanish,0,0,0,9,0,0,0,"2018-01-05 19:10:33"
|
||||||
Raulbertassi,,0,0,0,0,0,0,0,"2018-01-07 17:23:18"
|
Raulbertassi,,0,0,0,0,0,0,0,"2018-01-07 17:23:18"
|
||||||
"Карлен Шаухаев (KarlenShaukhaev)",,0,0,0,0,0,0,0,"2020-04-27 08:53:49"
|
|
||||||
dimateos,,0,0,0,0,0,0,0,"2021-01-10 06:29:52"
|
|
||||||
"Katherine Alexandra Flórez Ramírez (katherine.florez12)",Spanish,0,0,0,46,0,0,0,"2018-01-20 02:18:32"
|
"Katherine Alexandra Flórez Ramírez (katherine.florez12)",Spanish,0,0,0,46,0,0,0,"2018-01-20 02:18:32"
|
||||||
"reza golestanzadeh (reza.golestanzadeh)",Persian,0,0,0,1,0,0,0,"2020-10-21 12:07:20"
|
|
||||||
farbod66,Persian,0,0,0,1,0,0,0,"2018-01-20 11:04:23"
|
farbod66,Persian,0,0,0,1,0,0,0,"2018-01-20 11:04:23"
|
||||||
"Muhammet Furkan ALMACI (furkan.almaci)",Turkish,0,0,0,1,0,0,0,"2017-10-29 13:44:56"
|
droidahmed,Arabic,0,0,0,7,0,0,0,"2018-01-31 02:18:49"
|
||||||
|
"Yasin Okumus (lacivert)",Turkish,0,0,0,1,0,0,0,"2018-02-07 04:13:51"
|
||||||
|
"Sarah BCNN (fsarahboucenna)",French,0,0,0,16,0,0,0,"2018-02-11 11:07:36"
|
||||||
|
T-v-Gerwen,Dutch,0,0,0,47,0,0,0,"2018-03-02 10:26:33"
|
||||||
|
"عبد الناصر سعيد الثبيتي (asaeed)",,0,0,0,0,0,0,0,"2018-03-13 02:09:35"
|
||||||
|
REMOVED_USER,Czech,0,0,0,18,0,0,0,"2018-03-27 06:19:52"
|
||||||
|
BongTran,Vietnamese,0,0,0,2,0,0,0,"2018-04-24 05:16:07"
|
||||||
|
"Ahmed Nazir (ahmednazir333)",,0,0,0,0,0,0,0,"2018-05-06 12:10:27"
|
||||||
|
mdrobulis,,0,0,0,0,0,0,0,"2018-05-24 01:40:42"
|
||||||
|
REMOVED_USER,,0,0,0,0,0,0,0,"2018-08-24 00:17:43"
|
||||||
|
"Sri Harsha Bhogi (sriharshabhogi)",,0,0,0,0,0,0,0,"2018-09-02 05:31:53"
|
||||||
|
philfr49,French,0,0,0,2,0,0,0,"2018-09-03 14:20:32"
|
||||||
|
"Ahnaf Tajwar (atn4404)",,0,0,0,0,0,0,0,"2018-10-16 11:13:30"
|
||||||
|
Elham1361,,0,0,0,0,0,0,0,"2018-10-27 12:01:06"
|
||||||
|
REMOVED_USER,,0,0,0,0,0,0,0,"2018-10-27 15:34:36"
|
||||||
|
"Никита Карамов (nikita.karamoff)",Russian,0,0,0,10,0,0,0,"2018-10-29 03:57:21"
|
||||||
|
martyaberger,,0,0,0,0,0,0,0,"2019-01-01 18:48:08"
|
||||||
|
AsadullahIlyas,,0,0,0,0,0,0,0,"2019-01-04 06:14:15"
|
||||||
|
"Pumpith Ungsupanit (pumpithu)",,0,0,0,0,0,0,0,"2019-01-19 23:47:57"
|
||||||
|
"Nat Fomicheva (natac)",Russian,0,0,0,3,0,0,0,"2019-01-25 14:35:02"
|
||||||
|
ava_rfie,Persian,0,0,0,1,0,0,0,"2019-06-09 16:19:24"
|
||||||
|
"George Merkulov (george142.emarket)",Russian,0,0,0,11,0,0,0,"2019-06-09 19:47:02"
|
||||||
|
sanyoniket,,0,0,0,0,0,0,0,"2019-07-23 12:58:40"
|
||||||
|
"Arttu Ylhävuori (arttu.ylhavuori)",,0,0,0,0,0,0,0,"2019-07-24 15:03:42"
|
||||||
|
"Равиль Мифтахов (ravilmif47)",Russian,0,0,0,1,0,0,0,"2019-08-12 21:58:30"
|
||||||
|
Irsgram,Russian,0,0,0,1,0,0,0,"2019-09-30 16:42:20"
|
||||||
|
"Matus Zdansky (matuszdansky)",,0,0,0,0,0,0,0,"2019-10-20 13:52:24"
|
||||||
|
shuvo786,,0,0,0,0,0,0,0,"2019-11-13 00:18:12"
|
||||||
|
EwanB,,0,0,0,0,0,0,0,"2019-11-19 10:04:38"
|
||||||
|
"Eduard Boboc (edi.boboc33)",Romanian,0,0,0,4,0,0,0,"2019-12-16 09:08:39"
|
||||||
|
Hayder21,,0,0,0,0,0,0,0,"2019-12-31 10:56:24"
|
||||||
|
"Eliška Roubalová (roubaeli)",Czech,0,0,0,6,0,0,0,"2019-12-31 12:47:29"
|
||||||
|
REMOVED_USER,,0,0,0,0,0,0,0,"2020-02-01 03:47:48"
|
||||||
|
mushin,,0,0,0,0,0,0,0,"2020-02-02 04:08:05"
|
||||||
|
valney.faria,"Portuguese, Brazilian",0,0,0,1,0,0,0,"2020-02-02 14:45:02"
|
||||||
|
"Elmo (oberknecht)",,0,0,0,0,0,0,0,"2020-04-16 08:45:50"
|
||||||
|
"Карлен Шаухаев (KarlenShaukhaev)",,0,0,0,0,0,0,0,"2020-04-27 08:53:49"
|
||||||
|
"Edmunds Edmundam (edmundam)",,0,0,0,0,0,0,0,"2020-06-01 14:18:18"
|
||||||
|
"Алтынбек Наурызғали (altinbeknaurizgali)",Russian,0,0,0,1,0,0,0,"2020-08-12 13:03:49"
|
||||||
|
dongchen.yue,German,0,0,0,4,0,0,0,"2020-09-12 15:05:59"
|
||||||
|
rooban23,,0,0,0,0,0,0,0,"2020-09-15 11:49:14"
|
||||||
|
REMOVED_USER,,0,0,0,0,0,0,0,"2020-09-17 09:10:09"
|
||||||
|
"Arjun K. (arjunkdot)",,0,0,0,0,0,0,0,"2020-09-20 11:16:18"
|
||||||
|
"Rivo Zängov (Eraser)",,0,0,0,0,0,0,0,"2020-10-13 04:38:26"
|
||||||
|
"reza golestanzadeh (reza.golestanzadeh)",Persian,0,0,0,1,0,0,0,"2020-10-21 12:07:20"
|
||||||
|
Sandhu564.,,0,0,0,0,0,0,0,"2020-12-14 01:27:45"
|
||||||
|
dimateos,,0,0,0,0,0,0,0,"2021-01-10 06:29:52"
|
||||||
|
"Mateusz Teteruk (mttet)",Polish,0,0,0,1,0,0,0,"2021-01-23 13:09:59"
|
||||||
|
"LeMeD (LeMeS)",French,0,0,0,2,0,0,0,"2021-02-06 15:35:00"
|
||||||
|
"Quentin Hibon (hiq)",,0,0,0,0,0,0,0,"2021-02-07 16:39:31"
|
||||||
|
"vi ve (VimalV)",,0,0,0,0,0,0,0,"2021-02-08 02:35:45"
|
||||||
|
Fazy1380,,0,0,0,0,0,0,0,"2021-04-10 11:02:53"
|
||||||
|
"Saiprasath B (Saiprasath)",,0,0,0,0,0,0,0,"2021-07-11 11:10:41"
|
||||||
|
"darkkingredian (rediancool)",,0,0,0,0,0,0,0,"2021-07-27 16:04:32"
|
||||||
|
"Samuel Przeździęk (samek22)",Polish,0,0,0,1,0,0,0,"2021-08-01 00:49:01"
|
||||||
|
"Manny Farsangy (manifarsangi)",Persian,0,0,0,12,0,0,0,"2021-08-10 05:32:28"
|
||||||
|
"Masataka Yakura (myakura)",Japanese,0,0,0,1,0,0,0,"2021-09-03 22:10:36"
|
||||||
|
"Said Tahsin Dane (tasomaniac)",,0,0,0,0,0,0,0,"2021-09-25 05:31:01"
|
||||||
|
"akmal shafiq (mohdakmalshafiq)",,0,0,0,0,0,0,0,"2021-11-01 01:04:50"
|
||||||
|
catemlitten,Japanese,0,0,0,1,0,0,0,"2021-11-17 15:06:02"
|
||||||
|
HemanthMeda,Telugu,0,0,0,4,0,0,0,"2021-12-01 14:02:14"
|
||||||
|
"Yunsu Kim (yunsukim86)",Korean,0,0,0,2,0,0,0,"2022-01-14 06:33:43"
|
||||||
|
"Sylwuskak (sylwuskak)",Polish,0,0,0,1,0,0,0,"2022-01-25 04:19:53"
|
||||||
|
"Pro AAA (pro1010)",Arabic,0,0,0,1,0,0,0,"2022-02-14 03:32:44"
|
||||||
|
"Baran Özavcı (n2141n)",Turkish,0,0,0,1,0,0,0,"2022-02-26 04:32:51"
|
||||||
|
deepbird,,0,0,0,0,0,0,0,"2022-04-11 03:21:05"
|
||||||
|
ashik8113,,0,0,0,0,0,0,0,"2022-04-13 11:58:26"
|
||||||
|
"manu (manuL96)",,0,0,0,0,0,0,0,"2022-05-06 23:34:55"
|
||||||
|
"Agnel (agnelwaghela)",,0,0,0,0,0,0,0,"2022-06-19 10:32:33"
|
||||||
|
"Ruslan Zaynetdinov (theRuslan)",Russian,0,0,0,6,0,0,0,"2022-07-06 10:48:31"
|
||||||
|
"Marcel (flaced)",German,0,0,0,1,0,0,0,"2022-08-19 15:19:26"
|
||||||
|
pixx1,German,0,0,0,6,0,0,0,"2022-08-22 00:38:13"
|
||||||
|
"Onder Nuray (ondernuray)",,0,0,0,0,0,0,0,"2022-08-30 08:16:27"
|
||||||
|
"Md Faridul Islam (mdfaridulislam509)",,0,0,0,0,0,0,0,"2022-09-04 06:25:20"
|
||||||
|
Felone,,0,0,0,0,0,0,0,"2022-09-10 08:04:02"
|
||||||
|
Sawwwwwplan,,0,0,0,0,0,0,0,"2022-09-10 11:35:14"
|
||||||
|
"Fatima (fatima.a)",Arabic,0,0,0,1,0,0,0,"2022-09-20 09:48:25"
|
||||||
|
DomiAlt,,0,0,0,0,0,0,0,"2022-10-02 15:44:26"
|
||||||
|
Erwindly,Polish,0,0,0,1,0,0,0,"2022-11-01 04:12:58"
|
||||||
|
"Deniz Çelik (DenizCelik)",,0,0,0,0,0,0,0,"2022-11-09 02:13:11"
|
||||||
|
Watashiwanilli,,0,0,0,0,0,0,0,"2022-11-14 10:12:21"
|
||||||
|
"Maxence LIGAN (Daddy_Caramel)",,0,0,0,0,0,0,0,"2022-12-23 04:43:30"
|
||||||
|
wstroobandt,Dutch,0,0,0,1,0,0,0,"2023-01-03 17:52:42"
|
||||||
|
"ニキホロブ蒼井 (abhigyahazra)",,0,0,0,0,0,0,0,"2023-01-08 21:37:53"
|
||||||
|
"Afrim Kamberi (afrimkamberi)",,0,0,0,0,0,0,0,"2023-01-17 05:20:06"
|
||||||
|
ViacheslavLabs,Ukrainian,0,0,0,5,0,0,0,"2023-01-21 15:34:40"
|
||||||
|
Basta,,0,0,0,0,0,0,0,"2023-03-04 16:13:57"
|
||||||
|
raselh,,0,0,0,0,0,0,0,"2023-03-15 03:33:21"
|
||||||
|
"Adrian Miozga (AdrianMiozga)",Polish,0,0,0,13,0,0,0,"2023-03-25 17:00:53"
|
||||||
|
"Atlas Steel (atlas.steel.erbil)",,0,0,0,0,0,0,0,"2023-05-16 05:23:32"
|
||||||
|
"Sathyakumar Ps (sathyakumar63)",,0,0,0,0,0,0,0,"2023-05-24 11:44:23"
|
||||||
|
"Abdul nafih (nafih_zain_)",,0,0,0,0,0,0,0,"2023-05-25 06:24:31"
|
||||||
|
"Bernhard (bernikr)",German,0,0,0,1,0,0,0,"2023-06-12 11:18:18"
|
||||||
|
"Anna Boda (annaboda08)",Hungarian,0,0,0,1,0,0,0,"2023-07-03 13:28:12"
|
||||||
|
"Rubén CH (chruben45)",Spanish,0,0,0,1,0,0,0,"2023-07-24 12:39:51"
|
||||||
|
"Vinicius (exteraDev)",,0,0,0,0,0,0,0,"2023-08-08 15:47:45"
|
||||||
|
"mugdad alhammad (alhammad5057)",,0,0,0,0,0,0,0,"2023-08-13 22:36:01"
|
||||||
|
"Arthur Waldes (arthurwaldes)",,0,0,0,0,0,0,0,"2023-08-22 15:38:12"
|
||||||
|
"Mahmoud Hatem (mahmoudhatem)",Arabic,0,0,0,1,0,0,0,"2023-09-12 05:12:34"
|
||||||
|
"Jacques Francky Salomon (jacquesfranckysalomon)",,0,0,0,0,0,0,0,"2023-10-14 20:55:30"
|
||||||
|
"Mohammad Hashem (hashemchattogram)",,0,0,0,0,0,0,0,"2023-10-27 02:15:39"
|
||||||
|
Aylinddd,Persian,0,0,0,1,0,0,0,"2023-11-07 22:50:37"
|
||||||
|
Dinock,German,0,0,0,1,0,0,0,"2023-11-10 07:08:23"
|
||||||
|
zelfoxx,German,0,0,0,12,0,0,0,"2023-11-22 11:11:44"
|
||||||
|
REMOVED_USER,,0,0,0,0,0,0,0,"2023-11-28 17:42:55"
|
||||||
|
"Dennis Li (Dennis_Li)","Chinese Simplified",0,0,0,1,0,0,0,"2023-12-24 21:12:43"
|
||||||
|
REMOVED_USER,Russian,0,0,0,5,0,0,0,"2024-01-01 17:15:06"
|
||||||
|
"Daniill l (daniill)",,0,0,0,0,0,0,0,"2024-01-12 02:42:52"
|
||||||
|
"NONE NAME (RagnarGraves)",Spanish,0,0,0,1,0,0,0,"2024-02-18 01:39:39"
|
||||||
|
lu21232512,,0,0,0,0,0,0,0,"2024-04-15 12:40:05"
|
||||||
|
"Oscariño (oscarinhooo)",,0,0,0,0,0,0,0,"2024-07-07 08:47:25"
|
||||||
|
"Vladimir Sveshnikov (proloxy)",Russian,0,0,0,6,0,0,0,"2024-07-12 03:27:39"
|
||||||
|
L0f3n,Swedish,0,0,0,2,0,0,0,"2024-08-06 17:13:50"
|
||||||
|
"Christer Fletcher (chrfle)",Swedish,0,0,0,2,0,0,0,"2024-08-15 04:15:49"
|
||||||
|
"Moaid alzawy (dodoalzawy200)",Arabic,0,0,0,1,0,0,0,"2024-09-18 12:17:31"
|
||||||
|
"Eduardo Ferreira (eduu)",,0,0,0,0,0,0,0,"2024-10-27 19:09:20"
|
||||||
|
"عبد الملك بلكم (aboodpvp555)",Arabic,0,0,0,1,0,0,0,"2024-12-12 02:42:14"
|
||||||
|
4Kio,Russian,0,0,0,1,0,0,0,"2024-12-12 12:31:25"
|
||||||
|
"رودينه (rwdynh874)",Arabic,0,0,0,1,0,0,0,"2024-12-24 18:31:33"
|
||||||
|
"zahra ghasemi (z.ghasemizahra)",Persian,0,0,0,1,0,0,0,"2024-12-29 04:36:27"
|
||||||
|
"Mustafa Işıksız (mustafalordon27)",Turkish,0,0,0,1,0,0,0,"2025-01-15 13:52:32"
|
||||||
|
"Ahlem Ben (ahlemben1513)",Arabic,0,0,0,1,0,0,0,"2025-02-12 11:09:57"
|
||||||
|
"Francisco Parra (Frn_7)",Spanish,0,0,0,1,0,0,0,"2025-02-18 22:57:05"
|
||||||
|
"mizumoto (yuta-mizumoto)",Japanese,0,0,0,2,0,0,0,"2025-03-03 18:35:56"
|
||||||
|
|||||||
|
@@ -1,7 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -20,29 +18,38 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.github.triplet.play") version "3.5.0"
|
alias(libs.plugins.agp)
|
||||||
id("com.android.application")
|
alias(libs.plugins.kotlin.android)
|
||||||
id("org.jetbrains.kotlin.android")
|
alias(libs.plugins.ksp)
|
||||||
id("org.jetbrains.kotlin.kapt")
|
alias(libs.plugins.ktlint.plugin)
|
||||||
id("org.jetbrains.kotlin.android.extensions")
|
|
||||||
id("org.jlleitschuh.gradle.ktlint")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.compileLint {
|
tasks.compileLint {
|
||||||
dependsOn("updateTranslators")
|
dependsOn("updateTranslators")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
/*
|
||||||
|
Added on top of kotlinOptions to work around this issue:
|
||||||
|
https://youtrack.jetbrains.com/issue/KTIJ-24311/task-current-target-is-17-and-kaptGenerateStubsProductionDebugKotlin-task-current-target-is-1.8-jvm-target-compatibility-should#focus=Comments-27-6798448.0-0
|
||||||
|
Updating gradle might fix this, so try again in the future to remove this and run:
|
||||||
|
./gradlew --rerun-tasks :uhabits-android:kaptGenerateStubsReleaseKotlin
|
||||||
|
If this doesn't produce any warning, try to remove it.
|
||||||
|
*/
|
||||||
|
kotlin {
|
||||||
|
jvmToolchain(17)
|
||||||
|
}
|
||||||
|
|
||||||
compileSdkVersion(30)
|
android {
|
||||||
|
namespace = "org.isoron.uhabits"
|
||||||
|
compileSdk = 36
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode(20003)
|
versionCode = 20301
|
||||||
versionName("2.0.3")
|
versionName = "2.3.1"
|
||||||
minSdkVersion(23)
|
minSdk = 28
|
||||||
targetSdkVersion(30)
|
targetSdk = 36
|
||||||
applicationId("org.isoron.uhabits")
|
applicationId = "org.isoron.uhabits"
|
||||||
testInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner")
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
@@ -57,85 +64,53 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
getByName("release") {
|
release {
|
||||||
minifyEnabled(true)
|
isMinifyEnabled = true
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt")
|
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt")
|
||||||
if (signingConfigs.findByName("release") != null) {
|
if (signingConfigs.findByName("release") != null) {
|
||||||
signingConfig = signingConfigs.getByName("release")
|
signingConfig = signingConfigs.getByName("release")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getByName("debug") {
|
debug {
|
||||||
isTestCoverageEnabled = true
|
enableUnitTestCoverage = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
isCheckReleaseBuilds = false
|
|
||||||
isAbortOnError = false
|
|
||||||
disable("GoogleAppIndexingWarning")
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
targetCompatibility(JavaVersion.VERSION_1_8)
|
targetCompatibility(JavaVersion.VERSION_17)
|
||||||
sourceCompatibility(JavaVersion.VERSION_1_8)
|
sourceCompatibility(JavaVersion.VERSION_17)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString()
|
||||||
viewBinding = true
|
buildFeatures.viewBinding = true
|
||||||
}
|
lint.abortOnError = false
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
val daggerVersion = "2.38.1"
|
compileOnly(libs.jsr250.api)
|
||||||
val kotlinVersion = "1.5.21"
|
coreLibraryDesugaring(libs.desugar.jdk.libs)
|
||||||
val kxCoroutinesVersion = "1.5.1"
|
implementation(libs.appIntro)
|
||||||
val ktorVersion = "1.6.2"
|
implementation(libs.jsr305)
|
||||||
val espressoVersion = "3.4.0"
|
implementation(libs.dagger)
|
||||||
|
implementation(libs.guava)
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion")
|
implementation(libs.ktor.client.android)
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion")
|
implementation(libs.ktor.client.core)
|
||||||
androidTestImplementation("com.google.dagger:dagger:$daggerVersion")
|
implementation(libs.ktor.client.jackson)
|
||||||
androidTestImplementation("com.linkedin.dexmaker:dexmaker-mockito:2.28.1")
|
implementation(libs.ktor.client.json)
|
||||||
androidTestImplementation("io.ktor:ktor-client-mock:$ktorVersion")
|
implementation(libs.kotlin.stdlib.jdk8)
|
||||||
androidTestImplementation("io.ktor:ktor-jackson:$ktorVersion")
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
androidTestImplementation("androidx.annotation:annotation:1.2.0")
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.3")
|
implementation(libs.appcompat)
|
||||||
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
|
implementation(libs.legacy.preference.v14)
|
||||||
androidTestImplementation("androidx.test:rules:1.4.0")
|
implementation(libs.legacy.support.v4)
|
||||||
androidTestImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
|
implementation(libs.material)
|
||||||
compileOnly("javax.annotation:jsr250-api:1.0")
|
implementation(libs.opencsv)
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
|
implementation(libs.konfetti.xml)
|
||||||
implementation("com.github.paolorotolo:appintro:4.1.0")
|
|
||||||
implementation("com.google.code.findbugs:jsr305:3.0.2")
|
|
||||||
implementation("com.google.dagger:dagger:$daggerVersion")
|
|
||||||
implementation("com.google.guava:guava:30.1.1-android")
|
|
||||||
implementation("io.ktor:ktor-client-android:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-client-core:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-client-jackson:$ktorVersion")
|
|
||||||
implementation("io.ktor:ktor-client-json:$ktorVersion")
|
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$kxCoroutinesVersion")
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kxCoroutinesVersion")
|
|
||||||
implementation("androidx.appcompat:appcompat:1.3.1")
|
|
||||||
implementation("androidx.legacy:legacy-preference-v14:1.0.0")
|
|
||||||
implementation("androidx.legacy:legacy-support-v4:1.0.0")
|
|
||||||
implementation("com.google.android.material:material:1.4.0")
|
|
||||||
implementation("com.opencsv:opencsv:5.5.1")
|
|
||||||
implementation(project(":uhabits-core"))
|
implementation(project(":uhabits-core"))
|
||||||
kapt("com.google.dagger:dagger-compiler:$daggerVersion")
|
ksp(libs.dagger.compiler)
|
||||||
kaptAndroidTest("com.google.dagger:dagger-compiler:$daggerVersion")
|
|
||||||
testImplementation("com.google.dagger:dagger:$daggerVersion")
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
|
||||||
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
|
|
||||||
}
|
|
||||||
|
|
||||||
kapt {
|
androidTestImplementation(libs.bundles.androidTest)
|
||||||
correctErrorTypes = true
|
testImplementation(libs.bundles.test)
|
||||||
}
|
|
||||||
|
|
||||||
play {
|
|
||||||
serviceAccountCredentials.set(file("../.secret/gcp-key.json"))
|
|
||||||
track.set("alpha")
|
|
||||||
}
|
}
|
||||||
|
|||||||
8248
uhabits-android/lint-baseline.xml
Normal file
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -39,6 +39,7 @@ open class BaseUserInterfaceTest {
|
|||||||
private lateinit var prefs: Preferences
|
private lateinit var prefs: Preferences
|
||||||
private lateinit var fixtures: HabitFixtures
|
private lateinit var fixtures: HabitFixtures
|
||||||
private lateinit var cache: HabitCardListCache
|
private lateinit var cache: HabitCardListCache
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -153,18 +153,22 @@ open class BaseViewTest : BaseAndroidTest() {
|
|||||||
var filename = filename
|
var filename = filename
|
||||||
var dir = getSDCardDir("test-screenshots")
|
var dir = getSDCardDir("test-screenshots")
|
||||||
if (dir == null) dir = AndroidDirFinder(targetContext).getFilesDir("test-screenshots")
|
if (dir == null) dir = AndroidDirFinder(targetContext).getFilesDir("test-screenshots")
|
||||||
if (dir == null) throw RuntimeException(
|
if (dir == null) {
|
||||||
"Could not find suitable dir for screenshots"
|
throw RuntimeException(
|
||||||
)
|
"Could not find suitable dir for screenshots"
|
||||||
|
)
|
||||||
|
}
|
||||||
filename = filename.replace("\\.png$".toRegex(), "$suffix.png")
|
filename = filename.replace("\\.png$".toRegex(), "$suffix.png")
|
||||||
val absolutePath = String.format("%s/%s", dir.absolutePath, filename)
|
val absolutePath = String.format("%s/%s", dir.absolutePath, filename)
|
||||||
val parent = File(absolutePath).parentFile
|
val parent = File(absolutePath).parentFile
|
||||||
if (!parent.exists() && !parent.mkdirs()) throw RuntimeException(
|
if (!parent.exists() && !parent.mkdirs()) {
|
||||||
String.format(
|
throw RuntimeException(
|
||||||
"Could not create dir: %s",
|
String.format(
|
||||||
parent.absolutePath
|
"Could not create dir: %s",
|
||||||
|
parent.absolutePath
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
val out = FileOutputStream(absolutePath)
|
val out = FileOutputStream(absolutePath)
|
||||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||||
return absolutePath
|
return absolutePath
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits
|
package org.isoron.uhabits
|
||||||
|
|
||||||
import com.nhaarman.mockitokotlin2.mock
|
|
||||||
import dagger.Component
|
import dagger.Component
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
@@ -35,6 +34,7 @@ import org.isoron.uhabits.inject.ActivityScope
|
|||||||
import org.isoron.uhabits.inject.HabitModule
|
import org.isoron.uhabits.inject.HabitModule
|
||||||
import org.isoron.uhabits.inject.HabitsActivityModule
|
import org.isoron.uhabits.inject.HabitsActivityModule
|
||||||
import org.isoron.uhabits.inject.HabitsApplicationComponent
|
import org.isoron.uhabits.inject.HabitsApplicationComponent
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
class TestModule {
|
class TestModule {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -55,6 +55,7 @@ import org.junit.runner.RunWith
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
class HabitsTest : BaseUserInterfaceTest() {
|
class HabitsTest : BaseUserInterfaceTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun shouldCreateHabit() {
|
fun shouldCreateHabit() {
|
||||||
@@ -180,6 +181,8 @@ class HabitsTest : BaseUserInterfaceTest() {
|
|||||||
longPressCheckmarks("Wake up early", count = 2)
|
longPressCheckmarks("Wake up early", count = 2)
|
||||||
clickText("Wake up early")
|
clickText("Wake up early")
|
||||||
verifyShowsScreen(SHOW_HABIT)
|
verifyShowsScreen(SHOW_HABIT)
|
||||||
|
// TODO: find a better way than sleeping in tests
|
||||||
|
Thread.sleep(2001L)
|
||||||
verifyDisplaysText("10%")
|
verifyDisplaysText("10%")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +197,8 @@ class HabitsTest : BaseUserInterfaceTest() {
|
|||||||
verifyDoesNotDisplayText("Track time")
|
verifyDoesNotDisplayText("Track time")
|
||||||
verifyDisplaysText("Wake up early")
|
verifyDisplaysText("Wake up early")
|
||||||
longPressCheckmarks("Wake up early", count = 1)
|
longPressCheckmarks("Wake up early", count = 1)
|
||||||
|
// TODO: find a better way than sleeping in tests
|
||||||
|
Thread.sleep(2001L)
|
||||||
verifyDoesNotDisplayText("Wake up early")
|
verifyDoesNotDisplayText("Wake up early")
|
||||||
clickMenu(TOGGLE_COMPLETED)
|
clickMenu(TOGGLE_COMPLETED)
|
||||||
verifyDisplaysText("Track time")
|
verifyDisplaysText("Track time")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
package org.isoron.uhabits.acceptance.steps
|
package org.isoron.uhabits.acceptance.steps
|
||||||
|
|
||||||
import android.os.Build.VERSION.SDK_INT
|
import android.os.Build.VERSION.SDK_INT
|
||||||
|
import android.os.SystemClock.sleep
|
||||||
import androidx.test.uiautomator.By
|
import androidx.test.uiautomator.By
|
||||||
import androidx.test.uiautomator.UiSelector
|
import androidx.test.uiautomator.UiSelector
|
||||||
import org.isoron.uhabits.BaseUserInterfaceTest.Companion.device
|
import org.isoron.uhabits.BaseUserInterfaceTest.Companion.device
|
||||||
@@ -39,7 +40,7 @@ fun exportFullBackup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clearDownloadFolder() {
|
fun clearDownloadFolder() {
|
||||||
device.executeShellCommand("rm -rf /sdcard/Download/")
|
device.executeShellCommand("rm -rf /sdcard/Download")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearBackupFolder() {
|
fun clearBackupFolder() {
|
||||||
@@ -86,6 +87,7 @@ fun importBackupFromDownloadFolder() {
|
|||||||
device.findObject(UiSelector().textContains("Loop")).click()
|
device.findObject(UiSelector().textContains("Loop")).click()
|
||||||
} else {
|
} else {
|
||||||
device.click(50, 90) // Click menu button
|
device.click(50, 90) // Click menu button
|
||||||
|
Thread.sleep(1000)
|
||||||
device.findObject(UiSelector().textContains("Download")).click()
|
device.findObject(UiSelector().textContains("Download")).click()
|
||||||
device.findObject(UiSelector().textContains("Loop")).click()
|
device.findObject(UiSelector().textContains("Loop")).click()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -18,7 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.acceptance.steps
|
package org.isoron.uhabits.acceptance.steps
|
||||||
|
|
||||||
import android.os.Build.VERSION
|
import android.os.Build
|
||||||
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.test.espresso.Espresso
|
import androidx.test.espresso.Espresso
|
||||||
@@ -31,11 +32,11 @@ import androidx.test.espresso.matcher.ViewMatchers
|
|||||||
import androidx.test.uiautomator.By
|
import androidx.test.uiautomator.By
|
||||||
import androidx.test.uiautomator.UiSelector
|
import androidx.test.uiautomator.UiSelector
|
||||||
import androidx.test.uiautomator.Until
|
import androidx.test.uiautomator.Until
|
||||||
import junit.framework.Assert.assertTrue
|
|
||||||
import org.hamcrest.CoreMatchers
|
import org.hamcrest.CoreMatchers
|
||||||
import org.isoron.uhabits.BaseUserInterfaceTest
|
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||||
import org.isoron.uhabits.R
|
import org.isoron.uhabits.R
|
||||||
import org.isoron.uhabits.activities.habits.list.ListHabitsActivity
|
import org.isoron.uhabits.activities.habits.list.ListHabitsActivity
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
|
||||||
object CommonSteps : BaseUserInterfaceTest() {
|
object CommonSteps : BaseUserInterfaceTest() {
|
||||||
fun pressBack() {
|
fun pressBack() {
|
||||||
@@ -72,7 +73,7 @@ object CommonSteps : BaseUserInterfaceTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun offsetHeaders() {
|
fun offsetHeaders() {
|
||||||
device.swipe(750, 160, 600, 160, 20)
|
device.swipe(500, 160, 350, 160, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scrollToText(text: String?) {
|
fun scrollToText(text: String?) {
|
||||||
@@ -131,9 +132,9 @@ object CommonSteps : BaseUserInterfaceTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun verifyOpensWebsite(url: String?) {
|
fun verifyOpensWebsite(url: String) {
|
||||||
var browserPkg = "org.chromium.webview_shell"
|
var browserPkg = "org.chromium.webview_shell"
|
||||||
if (VERSION.SDK_INT <= 23) {
|
if (SDK_INT <= Build.VERSION_CODES.M) {
|
||||||
browserPkg = "com.android.browser"
|
browserPkg = "com.android.browser"
|
||||||
}
|
}
|
||||||
assertTrue(device.wait(Until.hasObject(By.pkg(browserPkg)), 5000))
|
assertTrue(device.wait(Until.hasObject(By.pkg(browserPkg)), 5000))
|
||||||
@@ -146,15 +147,19 @@ object CommonSteps : BaseUserInterfaceTest() {
|
|||||||
Screen.LIST_HABITS ->
|
Screen.LIST_HABITS ->
|
||||||
Espresso.onView(ViewMatchers.withClassName(CoreMatchers.endsWith("ListHabitsRootView")))
|
Espresso.onView(ViewMatchers.withClassName(CoreMatchers.endsWith("ListHabitsRootView")))
|
||||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||||
|
|
||||||
Screen.SHOW_HABIT ->
|
Screen.SHOW_HABIT ->
|
||||||
Espresso.onView(ViewMatchers.withId(R.id.subtitleCard))
|
Espresso.onView(ViewMatchers.withId(R.id.subtitleCard))
|
||||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||||
|
|
||||||
Screen.EDIT_HABIT ->
|
Screen.EDIT_HABIT ->
|
||||||
Espresso.onView(ViewMatchers.withId(R.id.questionInput))
|
Espresso.onView(ViewMatchers.withId(R.id.questionInput))
|
||||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||||
|
|
||||||
Screen.SELECT_HABIT_TYPE ->
|
Screen.SELECT_HABIT_TYPE ->
|
||||||
Espresso.onView(ViewMatchers.withText(R.string.yes_or_no_example))
|
Espresso.onView(ViewMatchers.withText(R.string.yes_or_no_example))
|
||||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||||
|
|
||||||
else -> throw IllegalStateException()
|
else -> throw IllegalStateException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,6 +183,22 @@ object CommonSteps : BaseUserInterfaceTest() {
|
|||||||
EditHabitSteps.clickSave()
|
EditHabitSteps.clickSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun changeFrequencyToDaily(habitName: String) {
|
||||||
|
clickText(habitName)
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.action_edit_habit)).perform(ViewActions.click())
|
||||||
|
EditHabitSteps.pickDailyFrequency()
|
||||||
|
EditHabitSteps.clickSave()
|
||||||
|
pressBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeFrequencyToMonthly(habitName: String) {
|
||||||
|
clickText(habitName)
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.action_edit_habit)).perform(ViewActions.click())
|
||||||
|
EditHabitSteps.pickMonthFrequency()
|
||||||
|
EditHabitSteps.clickSave()
|
||||||
|
pressBack()
|
||||||
|
}
|
||||||
|
|
||||||
enum class Screen {
|
enum class Screen {
|
||||||
LIST_HABITS, SHOW_HABIT, EDIT_HABIT, SELECT_HABIT_TYPE
|
LIST_HABITS, SHOW_HABIT, EDIT_HABIT, SELECT_HABIT_TYPE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -36,6 +36,24 @@ object EditHabitSteps {
|
|||||||
Espresso.onView(ViewMatchers.withText("SAVE")).perform(ViewActions.click())
|
Espresso.onView(ViewMatchers.withText("SAVE")).perform(ViewActions.click())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun pickMonthFrequency() {
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.boolean_frequency_picker))
|
||||||
|
.perform(ViewActions.click())
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.xTimesPerMonthRadioButton))
|
||||||
|
.perform(ViewActions.click())
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.xTimesPerMonthTextView))
|
||||||
|
.perform(ViewActions.replaceText("1"))
|
||||||
|
Espresso.onView(ViewMatchers.withText("SAVE")).perform(ViewActions.click())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pickDailyFrequency() {
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.boolean_frequency_picker))
|
||||||
|
.perform(ViewActions.click())
|
||||||
|
Espresso.onView(ViewMatchers.withId(R.id.everyDayRadioButton))
|
||||||
|
.perform(ViewActions.click())
|
||||||
|
Espresso.onView(ViewMatchers.withText("SAVE")).perform(ViewActions.click())
|
||||||
|
}
|
||||||
|
|
||||||
fun pickColor(color: Int) {
|
fun pickColor(color: Int) {
|
||||||
Espresso.onView(ViewMatchers.withId(R.id.colorButton)).perform(ViewActions.click())
|
Espresso.onView(ViewMatchers.withId(R.id.colorButton)).perform(ViewActions.click())
|
||||||
BaseUserInterfaceTest.device.findObject(By.descStartsWith(String.format("Color %d", color)))
|
BaseUserInterfaceTest.device.findObject(By.descStartsWith(String.format("Color %d", color)))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -53,6 +53,7 @@ object ListHabitsSteps {
|
|||||||
clickViewWithId(R.id.action_filter)
|
clickViewWithId(R.id.action_filter)
|
||||||
CommonSteps.clickText(R.string.hide_completed)
|
CommonSteps.clickText(R.string.hide_completed)
|
||||||
}
|
}
|
||||||
|
else -> throw RuntimeException()
|
||||||
}
|
}
|
||||||
device.waitForIdle()
|
device.waitForIdle()
|
||||||
}
|
}
|
||||||
@@ -120,6 +121,12 @@ object ListHabitsSteps {
|
|||||||
BaseUserInterfaceTest.device.waitForIdle()
|
BaseUserInterfaceTest.device.waitForIdle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun changeSort(sortText: String) {
|
||||||
|
clickViewWithId(R.id.action_filter)
|
||||||
|
Espresso.onView(ViewMatchers.withText("Sort")).perform(ViewActions.click())
|
||||||
|
Espresso.onView(ViewMatchers.withText(sortText)).perform(ViewActions.click())
|
||||||
|
}
|
||||||
|
|
||||||
enum class MenuItem {
|
enum class MenuItem {
|
||||||
ABOUT, HELP, SETTINGS, EDIT, DELETE, ARCHIVE, TOGGLE_ARCHIVED, UNARCHIVE, TOGGLE_COMPLETED, ADD
|
ABOUT, HELP, SETTINGS, EDIT, DELETE, ARCHIVE, TOGGLE_ARCHIVED, UNARCHIVE, TOGGLE_COMPLETED, ADD
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -18,12 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.acceptance.steps
|
package org.isoron.uhabits.acceptance.steps
|
||||||
|
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import androidx.test.uiautomator.UiScrollable
|
import androidx.test.uiautomator.UiScrollable
|
||||||
import androidx.test.uiautomator.UiSelector
|
import androidx.test.uiautomator.UiSelector
|
||||||
import junit.framework.Assert.assertFalse
|
|
||||||
import junit.framework.Assert.assertTrue
|
|
||||||
import org.isoron.uhabits.BaseUserInterfaceTest
|
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
|
||||||
object WidgetSteps {
|
object WidgetSteps {
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
@@ -50,29 +50,21 @@ object WidgetSteps {
|
|||||||
private fun openWidgetScreen() {
|
private fun openWidgetScreen() {
|
||||||
val h = BaseUserInterfaceTest.device.displayHeight
|
val h = BaseUserInterfaceTest.device.displayHeight
|
||||||
val w = BaseUserInterfaceTest.device.displayWidth
|
val w = BaseUserInterfaceTest.device.displayWidth
|
||||||
if (VERSION.SDK_INT <= 21) {
|
val listId = "com.android.launcher3:id/widgets_list_view"
|
||||||
BaseUserInterfaceTest.device.pressHome()
|
BaseUserInterfaceTest.device.pressHome()
|
||||||
BaseUserInterfaceTest.device.waitForIdle()
|
BaseUserInterfaceTest.device.waitForIdle()
|
||||||
BaseUserInterfaceTest.device.findObject(UiSelector().description("Apps")).click()
|
BaseUserInterfaceTest.device.drag(w / 2, h / 2, w / 2, h / 2, 8)
|
||||||
BaseUserInterfaceTest.device.findObject(UiSelector().description("Apps")).click()
|
var button = BaseUserInterfaceTest.device.findObject(UiSelector().text("WIDGETS"))
|
||||||
BaseUserInterfaceTest.device.findObject(UiSelector().description("Widgets")).click()
|
if (!button.waitForExists(1000)) {
|
||||||
} else {
|
button = BaseUserInterfaceTest.device.findObject(UiSelector().text("Widgets"))
|
||||||
val listId = "com.android.launcher3:id/widgets_list_view"
|
|
||||||
BaseUserInterfaceTest.device.pressHome()
|
|
||||||
BaseUserInterfaceTest.device.waitForIdle()
|
|
||||||
BaseUserInterfaceTest.device.drag(w / 2, h / 2, w / 2, h / 2, 8)
|
|
||||||
var button = BaseUserInterfaceTest.device.findObject(UiSelector().text("WIDGETS"))
|
|
||||||
if (!button.waitForExists(1000)) {
|
|
||||||
button = BaseUserInterfaceTest.device.findObject(UiSelector().text("Widgets"))
|
|
||||||
}
|
|
||||||
button.click()
|
|
||||||
if (VERSION.SDK_INT >= 28) {
|
|
||||||
UiScrollable(UiSelector().resourceId(listId))
|
|
||||||
.scrollForward()
|
|
||||||
}
|
|
||||||
UiScrollable(UiSelector().resourceId(listId))
|
|
||||||
.scrollIntoView(UiSelector().text("Checkmark"))
|
|
||||||
}
|
}
|
||||||
|
button.click()
|
||||||
|
if (SDK_INT >= 28) {
|
||||||
|
UiScrollable(UiSelector().resourceId(listId))
|
||||||
|
.scrollForward()
|
||||||
|
}
|
||||||
|
UiScrollable(UiSelector().resourceId(listId))
|
||||||
|
.scrollIntoView(UiSelector().text("Checkmark"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.common.views
|
package org.isoron.uhabits.activities.common.views
|
||||||
|
|
||||||
|
import android.view.MotionEvent
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
@@ -52,7 +53,8 @@ class FrequencyChartTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withDataOffset() {
|
fun testRender_withDataOffset() {
|
||||||
view.onScroll(null, null, -dpToPixels(150), 0f)
|
val e = MotionEvent.obtain(0, 0, 0, 0f, 0f, 0)
|
||||||
|
view.onScroll(e, e, -dpToPixels(150), 0f)
|
||||||
view.invalidate()
|
view.invalidate()
|
||||||
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.activities.common.views
|
package org.isoron.uhabits.activities.common.views
|
||||||
|
|
||||||
|
import android.view.MotionEvent
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
@@ -44,7 +45,7 @@ class ScoreChartTest : BaseViewTest() {
|
|||||||
habit = habit,
|
habit = habit,
|
||||||
firstWeekday = prefs.firstWeekdayInt,
|
firstWeekday = prefs.firstWeekdayInt,
|
||||||
spinnerPosition = 0,
|
spinnerPosition = 0,
|
||||||
theme = LightTheme(),
|
theme = LightTheme()
|
||||||
)
|
)
|
||||||
view = ScoreChart(targetContext).apply {
|
view = ScoreChart(targetContext).apply {
|
||||||
setScores(state.scores)
|
setScores(state.scores)
|
||||||
@@ -63,7 +64,8 @@ class ScoreChartTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
@Throws(Throwable::class)
|
@Throws(Throwable::class)
|
||||||
fun testRender_withDataOffset() {
|
fun testRender_withDataOffset() {
|
||||||
view.onScroll(null, null, -dpToPixels(150), 0f)
|
val e = MotionEvent.obtain(0, 0, 0, 0f, 0f, 0)
|
||||||
|
view.onScroll(e, e, -dpToPixels(150), 0f)
|
||||||
view.invalidate()
|
view.invalidate()
|
||||||
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -30,6 +30,7 @@ import org.junit.runner.RunWith
|
|||||||
@MediumTest
|
@MediumTest
|
||||||
class StreakChartTest : BaseViewTest() {
|
class StreakChartTest : BaseViewTest() {
|
||||||
private lateinit var view: StreakChart
|
private lateinit var view: StreakChart
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -22,32 +22,35 @@ package org.isoron.uhabits.activities.habits.list.views
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.MediumTest
|
import androidx.test.filters.MediumTest
|
||||||
import org.isoron.uhabits.BaseViewTest
|
import org.isoron.uhabits.BaseViewTest
|
||||||
import org.junit.Before
|
import org.junit.Ignore
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@MediumTest
|
@MediumTest
|
||||||
class EmptyListViewTest : BaseViewTest() {
|
class EmptyListViewTest : BaseViewTest() {
|
||||||
|
init {
|
||||||
private val path = "habits/list/EmptyListView"
|
// TODO: fix rendering differences across APIs
|
||||||
private val view: EmptyListView = EmptyListView(targetContext)
|
similarityCutoff = 0.00035
|
||||||
|
|
||||||
@Before
|
|
||||||
override fun setUp() {
|
|
||||||
super.setUp()
|
|
||||||
measureView(view, dpToPixels(200), dpToPixels(200))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val path = "habits/list/EmptyListView"
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("non-deterministic failure")
|
||||||
fun testRender_done() {
|
fun testRender_done() {
|
||||||
|
val view = EmptyListView(targetContext)
|
||||||
view.showDone()
|
view.showDone()
|
||||||
|
measureView(view, dpToPixels(200), dpToPixels(200))
|
||||||
assertRenders(view, "$path/done.png")
|
assertRenders(view, "$path/done.png")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("non-deterministic failure")
|
||||||
fun testRender_empty() {
|
fun testRender_empty() {
|
||||||
|
val view = EmptyListView(targetContext)
|
||||||
view.showEmpty()
|
view.showEmpty()
|
||||||
|
measureView(view, dpToPixels(200), dpToPixels(200))
|
||||||
assertRenders(view, "$path/empty.png")
|
assertRenders(view, "$path/empty.png")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -36,6 +36,7 @@ class EntryButtonViewTest : BaseViewTest() {
|
|||||||
lateinit var view: CheckmarkButtonView
|
lateinit var view: CheckmarkButtonView
|
||||||
|
|
||||||
var toggled = false
|
var toggled = false
|
||||||
|
var edited = false
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -43,7 +44,8 @@ class EntryButtonViewTest : BaseViewTest() {
|
|||||||
view = component.getEntryButtonViewFactory().create().apply {
|
view = component.getEntryButtonViewFactory().create().apply {
|
||||||
value = Entry.NO
|
value = Entry.NO
|
||||||
color = PaletteUtils.getAndroidTestColor(5)
|
color = PaletteUtils.getAndroidTestColor(5)
|
||||||
onToggle = { toggled = true }
|
onToggle = { _, _ -> toggled = true }
|
||||||
|
onEdit = { edited = true }
|
||||||
}
|
}
|
||||||
measureView(view, dpToPixels(48), dpToPixels(48))
|
measureView(view, dpToPixels(48), dpToPixels(48))
|
||||||
}
|
}
|
||||||
@@ -70,20 +72,28 @@ class EntryButtonViewTest : BaseViewTest() {
|
|||||||
fun testClick_withShortToggleDisabled() {
|
fun testClick_withShortToggleDisabled() {
|
||||||
prefs.isShortToggleEnabled = false
|
prefs.isShortToggleEnabled = false
|
||||||
view.performClick()
|
view.performClick()
|
||||||
assertFalse(toggled)
|
assertTrue(!toggled and edited)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testClick_withShortToggleEnabled() {
|
fun testClick_withShortToggleEnabled() {
|
||||||
prefs.isShortToggleEnabled = true
|
prefs.isShortToggleEnabled = true
|
||||||
view.performClick()
|
view.performClick()
|
||||||
assertTrue(toggled)
|
assertTrue(toggled and !edited)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLongClick() {
|
fun testLongClick_withShortToggleDisabled() {
|
||||||
|
prefs.isShortToggleEnabled = false
|
||||||
view.performLongClick()
|
view.performLongClick()
|
||||||
assertTrue(toggled)
|
assertTrue(toggled and !edited)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLongClick_withShortToggleEnabled() {
|
||||||
|
prefs.isShortToggleEnabled = true
|
||||||
|
view.performLongClick()
|
||||||
|
assertTrue(!toggled and edited)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertRendersCheckedExplicitly() {
|
private fun assertRendersCheckedExplicitly() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
* Copyright (C) 2016-2025 Álinson Santos Xavier <git@axavier.org>
|
||||||
*
|
*
|
||||||
* This file is part of Loop Habit Tracker.
|
* This file is part of Loop Habit Tracker.
|
||||||
*
|
*
|
||||||
@@ -77,7 +77,7 @@ class EntryPanelViewTest : BaseViewTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun testToggle() {
|
fun testToggle() {
|
||||||
val timestamps = mutableListOf<Timestamp>()
|
val timestamps = mutableListOf<Timestamp>()
|
||||||
view.onToggle = { t, _ -> timestamps.add(t) }
|
view.onToggle = { t, _, _ -> timestamps.add(t) }
|
||||||
view.buttons[0].performLongClick()
|
view.buttons[0].performLongClick()
|
||||||
view.buttons[2].performLongClick()
|
view.buttons[2].performLongClick()
|
||||||
view.buttons[3].performLongClick()
|
view.buttons[3].performLongClick()
|
||||||
@@ -88,7 +88,7 @@ class EntryPanelViewTest : BaseViewTest() {
|
|||||||
fun testToggle_withOffset() {
|
fun testToggle_withOffset() {
|
||||||
val timestamps = mutableListOf<Timestamp>()
|
val timestamps = mutableListOf<Timestamp>()
|
||||||
view.dataOffset = 3
|
view.dataOffset = 3
|
||||||
view.onToggle = { t, _ -> timestamps += t }
|
view.onToggle = { t, _, _ -> timestamps += t }
|
||||||
view.buttons[0].performLongClick()
|
view.buttons[0].performLongClick()
|
||||||
view.buttons[2].performLongClick()
|
view.buttons[2].performLongClick()
|
||||||
view.buttons[3].performLongClick()
|
view.buttons[3].performLongClick()
|
||||||
|
|||||||