Compare commits
511 Commits
v2.0.1
...
a5e3e9b3cf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
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 | |||
| f15c660d33 | |||
| 1866743c47 | |||
| 6b9a7917b4 | |||
| 2a5725f382 | |||
| edeabb6ee3 | |||
| 24a9fbe414 | |||
| e5b8c4c3c4 | |||
|
|
a781a1f947 | ||
|
|
13e57b5026 | ||
|
|
f8c7abfff4 | ||
|
|
7fe3ce970c | ||
| 9c395243f4 | |||
|
|
b9eb244b0b | ||
|
|
420a99f1cf | ||
| e756a639ae | |||
|
|
91ff5f7a0c | ||
|
|
67b55a4ecf | ||
|
|
a5ae2eaa63 | ||
|
|
0bc2a8b6d4 | ||
|
|
95a1786c4a | ||
|
|
caa1c9d72e | ||
|
|
a7afe0b309 | ||
|
|
9c03174eef | ||
|
|
da02926fa6 | ||
|
|
250dabfe58 | ||
|
|
0bba3b76bc | ||
|
|
c2479278ba | ||
|
|
499a403a06 | ||
|
|
af5d622339 | ||
|
|
5eeb54bc47 | ||
|
|
e09e899aad | ||
| 69f0fc6c3a | |||
| 705dfb9cbd | |||
| d0ef749f19 | |||
| b54711243f | |||
| 37f03aca37 | |||
|
|
271de59a94 | ||
|
|
0ab55f6f5a | ||
|
|
43921721d4 | ||
|
|
33c88cded3 | ||
|
|
aecce891ea | ||
|
|
2ea98a7756 | ||
|
|
e667872d83 | ||
|
|
3602a614c4 | ||
|
|
d8c5f4d93c | ||
|
|
c9f4df9dae | ||
|
|
feb384bca6 | ||
|
|
71e9160460 | ||
|
|
64966d3c86 | ||
|
|
4787df4074 | ||
| 92291fd919 | |||
| be51538704 | |||
| 89b24911ba | |||
| 1cf71b3973 | |||
| 2fe3b15806 | |||
| 33468bfc1c | |||
|
|
5908692a5c | ||
|
|
693dce8719 | ||
| b232827dfd | |||
|
|
02f9f411ce | ||
| bbf9da44e1 | |||
|
|
ee896fb4f9 | ||
|
|
4d7d8b6206 | ||
|
|
55b841a8b4 | ||
| 7fac86b617 | |||
|
|
c31d42be2d | ||
| 31c09b9c0b | |||
|
|
db91dce57f | ||
| 12c76245e6 | |||
| 2163a2b93b | |||
| afad56ab91 | |||
| ece1b93f8d | |||
| 10416e40fa | |||
| 88f8581acc | |||
| b33dd2a994 | |||
| d87961d800 | |||
| 38d2606d6d | |||
| 0a91c097e8 | |||
|
|
b1c53bd820 | ||
| c973f93424 | |||
| fcadbe7c38 | |||
| 59a4d7552c | |||
| 9d7840bdd1 | |||
|
|
32db4e363b | ||
|
|
004bb8d71c | ||
|
|
21a1e88c47 | ||
|
|
86fb718896 | ||
|
|
a4e9b2f874 | ||
|
|
ac924470b8 |
18
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -6,11 +6,16 @@ labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
<!--
|
||||
Please use the template below for your bug report. Issues that do not follow this
|
||||
template, or that do not contain all necessary information (namely, description of
|
||||
the problem, steps to reproduce, phone, phone operating system, and app version)
|
||||
will be closed without further consideration.
|
||||
-->
|
||||
|
||||
## Pre-submission checklist
|
||||
- [ ] I am submitting a bug report, not a feature request.
|
||||
- [ ] I am running the latest version of Loop Habit Tracker.
|
||||
- [ ] I have have searched for similar issues, but did not find any matches.
|
||||
- [ ] I have searched for similar issues, but did not find any matches.
|
||||
|
||||
## Description
|
||||
A clear and concise description of what the problem is.
|
||||
@@ -21,10 +26,11 @@ A clear and concise description of what the problem is.
|
||||
3. Scroll down to ....
|
||||
4. See error
|
||||
|
||||
## Screenshots
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
## System information
|
||||
- Phone: [e.g. Google Pixel 4]
|
||||
- Phone Operating System: [e.g. Android 10]
|
||||
- App version: [e.g. 1.8.9]
|
||||
- App version: [e.g. 2.0.2]
|
||||
|
||||
## Screenshots
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
|
||||
7
.github/dependabot.yml
vendored
@@ -3,4 +3,9 @@ updates:
|
||||
- package-ecosystem: "gradle"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
|
||||
59
.github/workflows/main.yml
vendored
@@ -7,54 +7,25 @@ on:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: ubuntu-latest
|
||||
Test:
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Check out source code
|
||||
uses: actions/checkout@v1
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Java Development Kit 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Build Project
|
||||
- name: Build project
|
||||
run: ./build.sh build
|
||||
|
||||
- name: Upload Build Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
- name: Run Android tests
|
||||
run: ./build.sh android-tests-parallel 28 29 30 32 33 34
|
||||
|
||||
- name: Upload artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: uhabits-android
|
||||
path: uhabits-android/build/outputs/
|
||||
|
||||
AndroidTest:
|
||||
needs: Build
|
||||
runs-on: macOS-10.15
|
||||
timeout-minutes: 45
|
||||
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: Run Android Tests
|
||||
run: ./build.sh android-tests ${{ matrix.api }}
|
||||
name: build
|
||||
path: |
|
||||
build/*log
|
||||
uhabits-android/build/outputs
|
||||
|
||||
|
||||
6
.gitignore
vendored
@@ -12,13 +12,9 @@
|
||||
.idea
|
||||
.secret
|
||||
build
|
||||
build/
|
||||
captures
|
||||
local.properties
|
||||
node_modules
|
||||
*xcuserdata*
|
||||
*.sketch
|
||||
/design
|
||||
/releases
|
||||
/screenshots
|
||||
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
96
CHANGELOG.md
@@ -1,5 +1,101 @@
|
||||
# Changelog
|
||||
|
||||
## [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)
|
||||
- Fix small theme issues (@iSoron)
|
||||
- Fix ANR on some Samsung phones (@iSoron, #962)
|
||||
- Fix dates before the year 2000 (@iSoron, #967)
|
||||
- Fix notification adding checkmarks to the wrong day (@hiqua, #969)
|
||||
- Fix crashes in widgets (@hiqua, @iSoron, #907, #966, #965)
|
||||
- Fix crash when moving habits (@hiqua, #968)
|
||||
|
||||
## [2.0.2] - 2021-05-23
|
||||
|
||||
### Changed
|
||||
- Make checkmark widget resizable
|
||||
|
||||
### Fixed
|
||||
- Fix crash caused by numerical habits with zero target (@iSoron, #903)
|
||||
- Fix small issues with font size (@iSoron)
|
||||
- Allow fractional target values (@sumanabhi, #911)
|
||||
- Fix IllegalStateException in androidx.customview.view (@iSoron, #906)
|
||||
- Fix crash when selecting habit frequency in some languages (@iSoron, #926)
|
||||
- Fix IllegalArgumentException in RingView (@iSoron, #904)
|
||||
|
||||
## [2.0.1] - 2021-05-09
|
||||
|
||||
### Added
|
||||
|
||||
12
README.md
@@ -17,8 +17,8 @@ show you how your habits improved over time. It is completely ad-free and open
|
||||
source.
|
||||
|
||||
<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="http://f-droid.org/app/org.isoron.uhabits"><img alt="Get it on F-Droid" src="http://i.imgur.com/baSPE7X.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://f-droid.org/badge/get-it-on.png" height="80px"/></a>
|
||||
</p>
|
||||
|
||||
## Screenshots
|
||||
@@ -90,7 +90,7 @@ contribute, even if you are not a software developer.
|
||||
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
|
||||
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
|
||||
|
||||
@@ -109,7 +109,7 @@ contribute, even if you are not a software developer.
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
[screen1]: screenshots/1.png
|
||||
[screen2]: screenshots/2.png
|
||||
@@ -123,9 +123,9 @@ contribute, even if you are not a software developer.
|
||||
[screen4th]: screenshots/4.thumb.png
|
||||
[screen5th]: screenshots/5.thumb.png
|
||||
[screen6th]: screenshots/6.thumb.png
|
||||
[poedit]: http://translate.loophabits.org
|
||||
[poedit]: https://translate.loophabits.org
|
||||
[playstore]: https://play.google.com/store/apps/details?id=org.isoron.uhabits
|
||||
[releases]: https://github.com/iSoron/uhabits/releases
|
||||
[fdroid]: http://f-droid.org/app/org.isoron.uhabits
|
||||
[fdroid]: https://f-droid.org/app/org.isoron.uhabits
|
||||
[build]: https://github.com/iSoron/uhabits/blob/dev/docs/BUILD.md
|
||||
[beta]: https://play.google.com/apps/testing/org.isoron.uhabits
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
plugins {
|
||||
val kotlinVersion = "1.4.21"
|
||||
id("com.android.application") version ("4.1.0") apply (false)
|
||||
val kotlinVersion = "1.9.21"
|
||||
id("com.android.application") version "8.1.4" apply (false)
|
||||
id("org.jetbrains.kotlin.android") version kotlinVersion apply (false)
|
||||
id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false)
|
||||
id("org.jetbrains.kotlin.android.extensions") version kotlinVersion apply (false)
|
||||
id("org.jetbrains.kotlin.multiplatform") version kotlinVersion apply (false)
|
||||
id("org.jlleitschuh.gradle.ktlint") version "10.0.0"
|
||||
id("org.jlleitschuh.gradle.ktlint") version "11.6.1"
|
||||
}
|
||||
|
||||
apply {
|
||||
@@ -15,11 +14,9 @@ apply {
|
||||
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")
|
||||
maven(url = "https://jitpack.io")
|
||||
}
|
||||
}
|
||||
|
||||
157
build.sh
@@ -26,6 +26,7 @@ GRADLE="./gradlew --stacktrace --quiet"
|
||||
PACKAGE_NAME=org.isoron.uhabits
|
||||
SDKMANAGER="${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager"
|
||||
VERSION=$(grep versionName uhabits-android/build.gradle.kts | sed -e 's/.*"\([^"]*\)".*/\1/g')
|
||||
BOOT_TIMEOUT=360
|
||||
|
||||
if [ -z $VERSION ]; then
|
||||
echo "Could not parse app version from: uhabits-android/build.gradle.kts"
|
||||
@@ -69,8 +70,7 @@ core_build() {
|
||||
# Android
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
android_test() {
|
||||
android_setup() {
|
||||
API=$1
|
||||
AVDNAME=${AVD_PREFIX}${API}
|
||||
|
||||
@@ -85,25 +85,63 @@ android_test() {
|
||||
$AVDMANAGER delete avd --name $AVDNAME
|
||||
|
||||
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 \
|
||||
--name $AVDNAME \
|
||||
--package "system-images;android-$API;default;x86_64" \
|
||||
--package "system-images;android-$API;google_apis;x86_64" \
|
||||
--device "Nexus 4" || return 1
|
||||
|
||||
flock -u 10
|
||||
) 10>/tmp/uhabitsTest.lock
|
||||
|
||||
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..."
|
||||
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
|
||||
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..."
|
||||
$ADB root || return 1
|
||||
sleep 5
|
||||
$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 animator_duration_scale 0 || return 1
|
||||
@@ -111,6 +149,24 @@ android_test() {
|
||||
log_info "Acquiring wake lock..."
|
||||
$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
|
||||
log_info "Installing release APK..."
|
||||
$ADB install -r ${ANDROID_OUTPUTS_DIR}/apk/release/uhabits-android-release.apk || return 1
|
||||
@@ -122,39 +178,77 @@ android_test() {
|
||||
$ADB install -r ${ANDROID_OUTPUTS_DIR}/apk/androidTest/debug/uhabits-android-debug-androidTest.apk || return 1
|
||||
|
||||
for size in medium large; do
|
||||
log_info "Running $size instrumented tests..."
|
||||
OUT_INSTRUMENT=${ANDROID_OUTPUTS_DIR}/instrument-${API}.txt
|
||||
OUT_LOGCAT=${ANDROID_OUTPUTS_DIR}/logcat-${API}.txt
|
||||
$ADB shell am instrument \
|
||||
-r -e coverage true -e size $size \
|
||||
-w ${PACKAGE_NAME}.test/androidx.test.runner.AndroidJUnitRunner \
|
||||
| tee $OUT_INSTRUMENT
|
||||
if grep "\(INSTRUMENTATION_STATUS_CODE.*-1\|FAILURES\|ABORTED\|onError\|Error type\|crashed\)" $OUT_INSTRUMENT; then
|
||||
FAILED_TESTS=""
|
||||
for i in {1..10}; do
|
||||
log_info "Running $size instrumented tests (attempt $i)..."
|
||||
$ADB shell am instrument \
|
||||
-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 "Saving logcat: $OUT_LOGCAT..."
|
||||
$ADB logcat -d > $OUT_LOGCAT
|
||||
log_error "Fetching test screenshots..."
|
||||
$ADB pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots ${ANDROID_OUTPUTS_DIR}/
|
||||
$ADB shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/
|
||||
return 1
|
||||
fi
|
||||
log_info "$size tests passed."
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
android_test_parallel() {
|
||||
# Launch background processes
|
||||
PIDS=""
|
||||
for API in $*; do
|
||||
(
|
||||
LOG=build/android-test-$API.log
|
||||
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"
|
||||
else
|
||||
log_error "API $API: Failed. See $LOG for more details."
|
||||
log_error "API $API: Failed"
|
||||
fi
|
||||
pkill -9 -f ${AVD_PREFIX}${API}
|
||||
exit $ret_code
|
||||
)&
|
||||
PIDS+=" $!"
|
||||
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() {
|
||||
@@ -198,13 +292,6 @@ android_build() {
|
||||
return 0
|
||||
}
|
||||
|
||||
android_fetch_images() {
|
||||
log_info "Fetching images"
|
||||
rm -rf ${ANDROID_OUTPUTS_DIR}/test-screenshots
|
||||
$ADB pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots ${ANDROID_OUTPUTS_DIR}/
|
||||
$ADB shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/
|
||||
}
|
||||
|
||||
android_accept_images() {
|
||||
find ${ANDROID_OUTPUTS_DIR}/test-screenshots -name '*.expected*' -delete
|
||||
rsync -av ${ANDROID_OUTPUTS_DIR}/test-screenshots/ uhabits-android/src/androidTest/assets/
|
||||
@@ -233,18 +320,16 @@ CI/CD script for Loop Habit Tracker.
|
||||
|
||||
Usage:
|
||||
build.sh build [options]
|
||||
build.sh clean [options]
|
||||
build.sh android-setup <API>
|
||||
build.sh android-tests <API> [options]
|
||||
build.sh android-tests-parallel <API> <API>... [options]
|
||||
build.sh android-fetch-images [options]
|
||||
build.sh android-accept-images [options]
|
||||
|
||||
Commands:
|
||||
build Build the app and run small tests
|
||||
clean Remove all build directories
|
||||
android-setup Create Android virtual machine
|
||||
android-tests Run medium and large Android tests on an emulator
|
||||
android-tests-parallel Tests multiple API levels simultaneously
|
||||
android-fetch-images Fetch failed view test images from device
|
||||
android-accept-images Copy fetched images to corresponding assets folder
|
||||
|
||||
Options:
|
||||
@@ -274,11 +359,13 @@ main() {
|
||||
case "$1" in
|
||||
build)
|
||||
shift; _parse_opts "$@"
|
||||
clean
|
||||
core_build
|
||||
android_build
|
||||
;;
|
||||
clean)
|
||||
clean
|
||||
android-setup)
|
||||
shift; _parse_opts "$@"
|
||||
android_setup $1
|
||||
;;
|
||||
android-tests)
|
||||
shift; _parse_opts "$@"
|
||||
@@ -286,20 +373,12 @@ main() {
|
||||
_print_usage
|
||||
exit 1
|
||||
fi
|
||||
for attempt in {1..3}; do
|
||||
log_info "Running Android tests (attempt $attempt)..."
|
||||
android_test $1 && return 0
|
||||
done
|
||||
log_error "Maximum number of attempts reached. Failing."
|
||||
return 1
|
||||
android_test $1
|
||||
;;
|
||||
android-tests-parallel)
|
||||
shift; _parse_opts "$@"
|
||||
android_test_parallel $*
|
||||
;;
|
||||
android-fetch-images)
|
||||
android_fetch_images
|
||||
;;
|
||||
android-accept-images)
|
||||
android_accept_images
|
||||
;;
|
||||
|
||||
@@ -33,7 +33,7 @@ The repository will be downloaded to the directory `uhabits`.
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
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:
|
||||
|
||||
* **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.
|
||||
* **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.
|
||||
* **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.
|
||||
- **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.
|
||||
- **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.
|
||||
|
||||
## 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
|
||||
./build.sh medium-tests
|
||||
1. Run `./build.sh android-setup API` to create the emulator, where `API` is the desired API level.
|
||||
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 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.
|
||||
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`.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
org.gradle.parallel=false
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xms2048m -Xmx2048m -XX:MaxPermSize=2048m
|
||||
org.gradle.jvmargs=-Xms2048m -Xmx2048m
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonFinalResIds=false
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
||||
#Sat Nov 28 09:55:24 CST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip
|
||||
|
||||
2
gradlew
vendored
@@ -82,6 +82,7 @@ esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
@@ -129,6 +130,7 @@ fi
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
|
||||
25
gradlew.bat
vendored
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -51,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@@ -61,28 +64,14 @@ echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
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,7 +1,6 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
resolutionStrategy.eachPlugin {
|
||||
|
||||
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,350 +1,415 @@
|
||||
Name,Languages,"Translated (Words)","Target Words","Approved (Words)",Voted,"""+"" votes received","""-"" votes received","Winning (Words)"
|
||||
"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; Vietnamese; Telugu; Finnish; Tamil; Afrikaans; Esperanto; Hebrew",14790,17211,1272,0,1707,70,4259
|
||||
"Slobodan Simić (Слободан Симић) (slsimic)","Serbian (Latin); Serbian (Cyrillic)",2053,1830,2105,12,33,0,1982
|
||||
"Oglaigh Rystard (oglaignaheireann)","Ukrainian; Portuguese; Catalan; Greek; Basque; Romanian; Italian",1103,1037,1327,1,13,6,954
|
||||
"David (Cliff122)",Swedish,1040,1019,725,6,0,0,700
|
||||
dukelc,Slovak,919,880,0,0,0,0,0
|
||||
KMakoto,"Chinese Traditional",745,1146,949,0,0,0,745
|
||||
"Evren (evrenkiymaz)",Turkish,688,604,0,71,4,0,0
|
||||
"David Nos (david.nos)","Catalan; Spanish",667,731,0,0,0,0,0
|
||||
androide74,Italian,644,659,0,2,0,0,0
|
||||
Tomairuka,Japanese,633,1636,909,43,0,0,564
|
||||
"Dmitriy Bogdanov (di72nn)",Russian,625,572,1175,0,34,0,519
|
||||
reyhoon,Persian,624,759,0,1,1,0,0
|
||||
Osoitz,Basque,610,545,0,9,0,0,3
|
||||
fabian.bouchal,German,548,527,0,6,0,3,72
|
||||
boban77,Czech,509,461,0,2,0,0,0
|
||||
"Yoav Argov (YoavArgov)",Hebrew,501,461,0,0,1,8,3
|
||||
REMOVED_USER,Norwegian,501,498,501,0,148,0,501
|
||||
"Martim Parente (Sharlimar)",Portuguese,497,534,0,38,0,0,0
|
||||
"chrrris1987 (Chrrris1987)",Dutch,467,478,0,23,0,0,0
|
||||
"Huy Ngo (huyngo)",Vietnamese,461,695,0,1,0,0,0
|
||||
"黄克 (hk13127)","Chinese Simplified",461,765,0,1,0,0,0
|
||||
"Arkadiusz Bubak (epitek)",Polish,458,416,29,24,0,3,0
|
||||
marco.baturan,Esperanto,452,452,0,0,0,0,0
|
||||
"Sief Tarek (sieftarek135)",Arabic,447,455,0,0,0,0,0
|
||||
"Omer I.S. (omeritzics)",Hebrew,428,366,0,14,1,0,0
|
||||
"Samuel Guay (SamGuay)",French,426,486,0,6,0,0,0
|
||||
"Diana Karaseva (Sun_Dianka)",Russian,399,373,0,10,1,0,221
|
||||
"Alexander Jansson (dalecarlian)",Swedish,396,406,507,0,0,3,399
|
||||
luiandresgonzalez,Spanish,383,403,0,1,0,0,0
|
||||
"Thamara Andrade (tkcandrade)","Portuguese, Brazilian",380,387,0,0,1,0,252
|
||||
"Sølv Ræven (soelvraeven)",Danish,370,370,0,0,0,0,0
|
||||
"Isti (eisti)",Hungarian,367,329,0,0,0,0,0
|
||||
"Anh Quân (dangquanuet)",Vietnamese,362,530,0,42,1,0,0
|
||||
gapszi,Hungarian,348,301,0,86,0,0,0
|
||||
"Mahdi Nasiri (mahdi.nasiri)",Persian,343,465,0,39,3,0,0
|
||||
Seoyul,Korean,339,825,0,0,27,0,0
|
||||
"Magimai Prakasam (magimai)",Tamil,336,831,0,12,0,0,0
|
||||
"Michael Malak (MichaelKMalak)",Arabic,304,271,0,0,0,0,0
|
||||
"Elina Salminen (salminen.elina.m)",Finnish,297,227,0,0,0,0,0
|
||||
ayane.m,Japanese,292,863,0,1,2,0,22
|
||||
"Marius Teufelweich (teufelweich)",German,249,256,606,4,0,0,146
|
||||
cobalt59,German,237,234,0,1,23,1,132
|
||||
"QWERT (lurenjia01)","Chinese Simplified",236,407,0,0,0,0,0
|
||||
beriain,Basque,234,235,0,0,2,0,0
|
||||
"Intan Ayunda (Intan_Ayunda)",Indonesian,228,239,336,0,0,0,135
|
||||
pnhpnh,Vietnamese,225,343,0,1,3,0,0
|
||||
"Dika Fitrian Dwi Putra (OsamuDazai)",Indonesian,221,215,0,0,0,0,33
|
||||
easyrepro,Telugu,214,297,0,0,0,0,0
|
||||
taras-ko,Ukrainian,211,183,0,1,4,0,19
|
||||
sojusnik,German,207,200,1,0,30,0,66
|
||||
axmed99,Ukrainian,203,177,0,40,0,0,53
|
||||
"Heru Yen (heruyen)",Indonesian,201,201,0,0,0,0,2
|
||||
Ishmaeel,Turkish,193,174,0,129,6,0,0
|
||||
fbruna17,Danish,181,179,0,1,0,0,0
|
||||
"Omry Cohen (omrycohen)",Hebrew,175,156,0,1,0,0,0
|
||||
Bryanx,Dutch,174,165,0,5,0,0,0
|
||||
"Pierre GALIEGUE (pierre.galiegue)",French,171,194,0,24,2,0,0
|
||||
DionysosDV,Greek,165,153,0,0,0,0,0
|
||||
"Gustavo Lima (GustavoLima)",Portuguese,158,177,0,1,4,10,0
|
||||
"Aputsiak Niels Janussen (aputtu)",Danish,153,171,0,0,0,0,0
|
||||
plitwin,Polish,145,128,0,1,16,0,26
|
||||
"Lương Vĩnh Khang (LuongVinhKhang)",Vietnamese,144,256,0,0,46,1,0
|
||||
azzamsa,Indonesian,142,136,0,48,0,1,50
|
||||
"Neysa Nasywa (neysanasywa)",Indonesian,140,141,0,0,0,0,35
|
||||
JY3,"Chinese Simplified",136,217,80,0,0,0,80
|
||||
"Mohammed Imthath (mimthath4)",Tamil,136,274,0,0,11,0,0
|
||||
roptat,French,132,154,0,112,88,5,0
|
||||
"Trần Thái (tranhoangthai2001)",Vietnamese,127,186,0,8,1,0,0
|
||||
"OP Smosher (teenwolffan44)","Serbian (Cyrillic)",124,122,0,0,0,0,18
|
||||
4001982248998,Esperanto,122,119,0,0,0,0,0
|
||||
"StoP4Me (Lcqp)",Romanian,121,119,0,0,3,0,0
|
||||
Sebastian05067,Spanish,114,133,0,55,18,0,0
|
||||
"Tanya (MagicUnderHood)",Russian,114,98,0,19,0,0,32
|
||||
REMOVED_USER,Arabic,111,106,0,22,21,2,0
|
||||
mohmans,Arabic,109,103,0,2,0,0,0
|
||||
"Ivan Krušlin (krux3r)",Croatian,108,122,503,0,0,0,108
|
||||
"Iabin Arteaga (iabin)",Spanish,108,111,0,4,20,0,0
|
||||
2kaafone,Finnish,105,90,0,0,0,0,0
|
||||
"Adam Jurkiewicz (hasztagg)",Polish,104,105,529,0,0,0,104
|
||||
"Saeed Esmaili (saaeed.es20)",Persian,104,141,0,0,0,0,0
|
||||
"just a name bro (justanamebr0)",Danish,98,109,0,0,1,0,0
|
||||
"Nam Nguyen (namnl2706)",Vietnamese,95,137,0,0,0,0,0
|
||||
"손유정 (yuwon1213)",Korean,95,57,0,0,0,0,0
|
||||
ranmagen,Hebrew,91,78,0,0,0,0,0
|
||||
LoneWanderer,"Chinese Traditional",90,137,0,4,0,0,0
|
||||
"Vo - (voyl)","Chinese Traditional",89,126,0,0,5,0,0
|
||||
ikkaz,Indonesian,89,84,0,5,0,0,4
|
||||
"Irene K (Heaun)",Korean,88,75,0,25,0,0,0
|
||||
"Kumar Anand (kumar0500)",Hindi,87,125,0,0,0,0,0
|
||||
Prosta4ok_ua,Ukrainian,87,84,0,1,0,0,17
|
||||
"Ohad Edri (ohadalte)",Hebrew,85,79,0,0,1,3,0
|
||||
helectron,Persian,84,102,0,1,0,0,0
|
||||
"Radu Cebotari (wildProgrammer)",Romanian,84,92,0,1,0,0,0
|
||||
"Israa Z (sosozozo)",Arabic,79,87,0,43,11,0,3
|
||||
"Sofia Neves (sofiasonev)","Portuguese, Brazilian",79,84,0,1,0,0,46
|
||||
Tiralka,French,79,91,0,92,1,0,0
|
||||
"Jacob Roller (jdr28070)",Korean,79,61,0,0,0,0,0
|
||||
"Toni Mustonen (toni.mustonen)",Finnish,78,72,0,0,0,0,0
|
||||
"Michael (quelbs)",German,76,75,0,1,0,0,39
|
||||
"Fauz Aladeem (topfauz)",Arabic,76,77,0,0,0,1,0
|
||||
RealDonald,Dutch,67,69,0,121,10,0,0
|
||||
sirekanyan,"Armenian; Russian",66,65,0,0,0,0,0
|
||||
"Константин К. (kocyak1991)",Russian,64,60,0,0,1,2,0
|
||||
"Laura Sophie (laurasophie20)",German,62,67,0,4,0,0,0
|
||||
raden20,Indonesian,61,62,177,0,1,0,64
|
||||
"Jan Wojtecki (j4nw)",Polish,58,46,0,0,0,0,26
|
||||
"Deepak Bharathi (deepakbharathi1994)",Tamil,56,107,0,0,11,4,0
|
||||
"Андрій Козицький (andriikozytskyi1108)",Ukrainian,52,52,0,0,1,0,0
|
||||
REMOVED_USER,Italian,51,52,0,2,0,0,0
|
||||
govindap,"Japanese; Hindi",51,114,0,6,1,0,0
|
||||
"Mare Geldenhuys (mare.geldenhuys)",Afrikaans,50,57,0,0,0,0,0
|
||||
"Peter Williams (williamspete001)",Japanese,49,133,0,1,0,0,3
|
||||
"Behnood HRazy (behnoodhr)",Persian,49,70,0,0,0,0,0
|
||||
J3ll3nl,Dutch,48,48,0,0,17,1,3
|
||||
"tat bz (Tat_i)",German,48,56,0,55,0,0,27
|
||||
vach,Armenian,47,36,0,0,0,0,0
|
||||
andowero,Czech,47,38,0,0,0,0,0
|
||||
"Andrew Firnes (Anechan)",Russian,47,47,0,3,0,0,29
|
||||
"Coni Ragni (coni2ragnii)",Spanish,46,46,0,0,0,0,0
|
||||
"Rahul Shishodia (rahul.shishodia.10)",Hindi,46,85,0,6,0,0,0
|
||||
Cp0204,"Chinese Simplified",45,72,0,0,0,0,0
|
||||
"cc (cavaz)",Italian,44,41,0,0,0,0,0
|
||||
"Kamil Dziadek (prso94)",Polish,43,39,0,0,2,0,0
|
||||
"Boban Jagertraum (boban40)",Czech,43,38,0,2,1,1,0
|
||||
andreea.muscalagiu,Romanian,42,52,0,1,0,0,0
|
||||
"Me Me (gentelwom)",Arabic,42,40,0,0,0,0,0
|
||||
"Balázs Keresztury (belidzs)",Hungarian,42,41,501,0,7,0,38
|
||||
MStefanov,Bulgarian,41,55,2,0,2,0,2
|
||||
"Ali Zali (stm19951995)",Persian,40,60,0,0,0,0,0
|
||||
"Sofia Veijonen (Suklaa) (sofia.veijonen)",Finnish,40,33,0,0,0,0,0
|
||||
dusanstrgar,Slovenian,39,41,0,0,0,0,0
|
||||
"Limin Lu (liminlu)","Chinese Simplified",39,79,503,0,0,0,39
|
||||
Anshoe,Tamil,38,65,0,14,0,0,0
|
||||
anasshm,Arabic,37,36,0,9,0,0,0
|
||||
hrexen,Armenian,37,37,0,0,0,0,0
|
||||
REMOVED_USER,Swedish,36,33,0,5,1,0,0
|
||||
"Abdulrahman (D7M)",Arabic,36,39,0,0,0,0,0
|
||||
"長谷川知里 (chase0213)",Japanese,34,138,0,13,0,0,24
|
||||
"Piotr Łuczyński (peterluczynski)",Polish,33,30,0,6,5,0,2
|
||||
"milad farahani (miladfarmahini90)",Persian,33,44,0,18,0,0,3
|
||||
"Luis E. Perichon (luisperichon)",Spanish,33,40,0,104,0,0,0
|
||||
andriikozytskyi2625,Ukrainian,31,23,0,0,0,0,0
|
||||
JoeLi,"Chinese Traditional",31,70,0,12,0,0,24
|
||||
Moastafa,Arabic,31,25,0,0,0,0,0
|
||||
REMOVED_USER,Russian,31,30,0,2,4,0,3
|
||||
"hamza gamal (hamzagamal4444)",Arabic,31,28,0,0,0,0,0
|
||||
yancyn,"Chinese Simplified",30,40,0,0,0,0,0
|
||||
"비니몬youtube (khj01025276475)",Korean,29,25,0,0,0,0,0
|
||||
"Ruud Schouten (ruudschouten)",Dutch,29,32,0,41,3,0,0
|
||||
"Guillaume Collic (gcollic)",French,26,28,0,126,11,0,0
|
||||
"Niraj Yadav (neverforgetniraj)",Hindi,26,48,0,0,0,0,0
|
||||
"Radoslaw Biernacki (radoslaw.biernacki)",Polish,26,24,0,8,0,0,1
|
||||
"Jonny I (jonny99dj)",Italian,26,26,0,5,0,0,0
|
||||
"Aaron Dalton (Perlkonig)",French,26,25,0,141,1,0,0
|
||||
"Eddie (eddieattaboy)","Chinese Traditional",25,34,0,1,0,0,0
|
||||
Pan_Filuta,Czech,25,21,0,5,4,0,3
|
||||
"eduard83 (barbany.eduard)",Catalan,24,25,0,2,0,0,0
|
||||
"Ľuboš Čaky (lubos.caky)",Slovak,23,22,0,0,0,0,0
|
||||
"Caner Başaran (basarancaner)",Turkish,23,21,0,0,20,0,0
|
||||
hodanli,Turkish,22,26,0,0,1,0,0
|
||||
"Neeraj Verma (verma.neeraj.in)",Hindi,22,37,0,0,1,0,0
|
||||
"Alcarkse (alexis.brusle)",French,21,25,0,7,11,0,0
|
||||
"Shashwat (goforgold)",Hindi,20,33,0,0,0,0,0
|
||||
"사자솥 (toke1597)",Korean,19,19,0,0,0,0,0
|
||||
"İsa Eş (IsaEs)",Turkish,19,17,0,0,6,1,0
|
||||
sheeCesu,French,19,18,0,48,2,0,0
|
||||
can13,Turkish,19,14,0,8,0,0,0
|
||||
"Magdalena Urbańczyk (madziia139)",Polish,19,19,0,0,0,0,0
|
||||
axikman11111,Uyghur,18,19,0,0,0,0,0
|
||||
Adeline31,French,17,20,0,3,0,0,0
|
||||
"Hoon Jung (hooni100)",Korean,17,10,0,0,0,0,0
|
||||
"Ceara Lopez (cealopez)",Spanish,17,18,0,0,5,1,0
|
||||
takoyakibento,Korean,17,13,0,3,0,0,0
|
||||
bretzel15,German,16,20,0,0,0,0,0
|
||||
engineeringforgood,Russian,16,15,0,0,0,0,0
|
||||
"Şamil Ateşoğlu (m.samilatesoglu)",Turkish,16,22,0,11,6,3,0
|
||||
DebatablySane,Bulgarian,16,15,0,48,0,0,0
|
||||
"Bhava Tharini (bhavidanush)",Tamil,15,37,0,0,0,0,0
|
||||
"Anastasia Borchuk (al2.borchuk)",Russian,14,14,0,0,0,0,0
|
||||
"EuiHo Hwang (euiho.hwang)",Korean,14,16,0,0,0,0,0
|
||||
iamsurajbobade,Hindi,14,30,0,0,0,0,0
|
||||
"Zeynep Esen (nezihaesen50)",Turkish,14,13,0,0,0,0,0
|
||||
"Fikret Bilici (fikretbilici)",Turkish,14,13,0,0,0,0,0
|
||||
"Zeeshan Rabbani (Zeera)",Hindi,14,25,0,0,0,0,0
|
||||
"Sanji Vinsmock (mukanzhanbolat4)",Russian,14,14,0,0,0,0,0
|
||||
"Nenad Vukotic (vukotic.nenad)","Serbian (Cyrillic)",13,13,0,1,2,6,0
|
||||
"Uwe Mönks (schirinowski)",German,13,12,0,0,0,0,0
|
||||
"Dave (xdave)",Hungarian,13,11,0,0,0,0,0
|
||||
soura2,Arabic,12,13,0,0,0,0,0
|
||||
"shreyas (techiespace)",Hindi,12,20,0,0,0,0,0
|
||||
"Jo Chuang (josephch405)","Chinese Traditional",11,24,0,0,0,0,11
|
||||
Vmrc,French,11,12,0,2,0,0,0
|
||||
"sathvic k (sathvictripleseven)",Telugu,10,17,0,0,0,0,0
|
||||
"Edwin van Rooij (edwinvrooij)",Dutch,10,13,0,17,0,0,0
|
||||
"Brian Camacho (bmcamacho)",Polish,10,11,0,0,1,0,0
|
||||
"Ahmed Mosaad (ahmed.mosaad2018)",Arabic,10,12,0,6,0,0,0
|
||||
"Mihael Wagner (miha.wagner)",Slovenian,10,9,0,7,0,0,0
|
||||
"Anonymous edgy nerd (yamentaad)",Arabic,10,13,0,1,0,0,0
|
||||
"Martin Vostatek (martinvostatek)",Czech,9,8,0,32,2,0,0
|
||||
"Sourire Lucide (sourire_lucide)",Russian,9,10,0,0,1,0,0
|
||||
"Suhaili Hassan (kucingsyg96)",Indonesian,9,10,0,0,0,0,0
|
||||
"Seweryn Piotrowski (Draxxsx)",Polish,9,10,0,0,19,0,0
|
||||
Rex123,Persian,8,8,0,0,0,0,0
|
||||
"Konstantin (KZhidovinov)",Russian,7,7,0,0,0,0,0
|
||||
pkorove,Greek,7,7,0,0,0,0,0
|
||||
ftfoi,Norwegian,7,6,0,0,0,0,0
|
||||
"Андрій Козицький (andriikozytskyi3807)",Ukrainian,7,12,0,2,0,0,0
|
||||
"Vladimir Pavlychev (KeyJoo)",Russian,7,9,0,0,0,0,0
|
||||
"Andrey ZaXeLoN (waragaa)",Russian,7,7,0,8,1,0,0
|
||||
erfan2927,Persian,6,6,0,0,0,0,0
|
||||
dragnus,Arabic,6,6,0,1,1,0,0
|
||||
"Sam (SorodonSorodon)",German,6,6,0,13,0,0,0
|
||||
ChloeLiang,Japanese,6,22,0,0,1,0,3
|
||||
"Burak Ceylan (7burakceylan)",Turkish,6,6,0,0,0,0,0
|
||||
"닉닉 (seohu9466)",Korean,6,14,0,13,0,0,0
|
||||
"Matthias Joly (joly.matt12)",French,5,8,0,27,1,0,0
|
||||
"Guerra Ivaneth (rossanaiva-04)",Spanish,5,7,0,0,0,0,0
|
||||
"Manuel Tassi (Mannivu)",Italian,5,6,0,0,0,0,0
|
||||
"Micaela Pighin (micaelapiighin)",Spanish,5,6,0,1,0,0,0
|
||||
"Дмитрий Хапенков (d.khapenkov)",Russian,5,5,0,6,4,0,2
|
||||
andriikozytskyi2018,Ukrainian,5,5,0,0,0,0,0
|
||||
"Neko123 (emandic11)","Serbian (Cyrillic)",4,4,0,57,0,0,0
|
||||
marmo,German,4,4,0,0,0,0,0
|
||||
"Eli Besirov (elibesirov07)",Turkish,4,4,0,0,0,0,0
|
||||
"Lopo Isaac Fernández (rocapata)",Spanish,4,3,0,0,0,0,0
|
||||
bziuum,Polish,4,4,0,0,0,0,0
|
||||
"Thoum Ptrgnt (thomas.petrignet)",French,3,3,0,2,0,3,0
|
||||
"Vagner Roberto (vagner.trompete)","Portuguese, Brazilian",3,3,0,0,0,0,0
|
||||
"Unnie Here (Carb)",Hindi,3,8,0,0,0,0,0
|
||||
carsten_kafke,German,3,3,0,43,0,0,3
|
||||
Magidxz,Arabic,3,3,0,0,0,0,0
|
||||
atomjani,Hungarian,3,3,0,0,0,0,0
|
||||
"Péter Bernát (bernatp)",Hungarian,3,2,0,0,0,0,0
|
||||
"Igor Piskun (i_piskun)",Ukrainian,3,3,0,0,0,0,0
|
||||
"joabe gabriel (joabegabrielcma1)","Portuguese, Brazilian",3,4,0,0,0,0,0
|
||||
"Oleg Kogut (kogut_oleg)",Ukrainian,3,3,0,0,0,0,0
|
||||
"Andrea Bianchi (andreawhite1597)",Italian,3,1,0,1,0,0,0
|
||||
"Gabriel Cavalcante (gabrielc.alves14)","Portuguese, Brazilian",3,4,0,0,0,0,0
|
||||
REMOVED_USER,"Portuguese, Brazilian",3,4,0,0,0,0,0
|
||||
"Martin Zimdahl (zimdahlmartin)",Swedish,3,2,0,0,1,0,3
|
||||
"Hiohana Rilary (hiohanarilary)","Portuguese, Brazilian",3,4,0,0,0,0,0
|
||||
"Sarath S (CyberShark)",Tamil,3,7,0,0,0,0,0
|
||||
"Cláudio Bernardo (claudiobernardo.ti)","Portuguese, Brazilian",3,4,0,1,0,0,0
|
||||
"hesamiranii (esam.matouri)",Persian,2,2,0,0,0,0,0
|
||||
"조화정 (yunjoo337)",Korean,2,2,0,0,0,0,0
|
||||
"Walid Baazia (walidbaazia2005)",Arabic,2,1,0,0,0,0,0
|
||||
LNDDYL,"Chinese Traditional",2,4,0,0,0,0,2
|
||||
REMOVED_USER,Ukrainian,2,2,0,0,0,0,0
|
||||
"fatemeh s (fargolseifoori3)",Persian,2,2,0,0,0,0,0
|
||||
"أم محمد تقي (souadboudia19)",Arabic,2,2,0,0,0,0,0
|
||||
"Alex Stein (diefaust1993)",Russian,2,2,0,4,4,0,2
|
||||
"Danial Agh (danialagh)",Persian,2,3,0,0,0,0,0
|
||||
omerfarukbas,Turkish,2,3,0,19,2,0,0
|
||||
"Valerij D (vala.dobler)",German,2,2,0,0,0,0,0
|
||||
"Naveen jai krishna (njsbpolymer1)",Tamil,2,5,0,0,0,0,0
|
||||
"Balthazar Aubard (Balatzar)",French,2,5,0,0,1,0,0
|
||||
"FAy FAy (fayfayfay52)","Chinese Traditional",2,5,0,0,0,0,0
|
||||
Soroor_SI,Persian,2,2,0,0,0,0,0
|
||||
chavs1997,Russian,2,2,0,9,0,0,0
|
||||
amei,"Portuguese, Brazilian",2,2,0,0,0,0,0
|
||||
"Ilyas Fekhar (il47yas)",Arabic,2,2,0,0,0,0,0
|
||||
"Ali Zaida (alizaeda92)",Arabic,2,2,0,0,0,0,0
|
||||
gnu-ewm,Polish,1,1,0,6,0,0,0
|
||||
"Luca Gori (grolcu)",Italian,1,2,0,0,0,0,0
|
||||
"Alan Jeon (skyisle)",Korean,1,2,0,8,0,0,0
|
||||
iSoron2,"Portuguese, Brazilian",1,1,0,0,0,0,0
|
||||
"Anastasiia Bondarenko (nastasya.bondarenko.97)",Russian,1,1,0,0,0,0,0
|
||||
"Patrick Pimenta (trickap1)","Portuguese, Brazilian",1,1,0,0,0,0,0
|
||||
axd,Spanish,1,1,0,15,0,0,0
|
||||
jonesses,German,1,1,0,1,0,0,1
|
||||
"박찌 (perpact20)",Korean,1,1,0,0,0,0,0
|
||||
"Kan Black (kanblack.va)",Vietnamese,1,2,0,0,0,1,0
|
||||
REMOVED_USER,Russian,1,2,0,6,1,0,1
|
||||
"Wibi Cahyo (wbcahyoh)",Indonesian,1,3,0,0,0,0,0
|
||||
"Anton (tT0NG)","Chinese Traditional",1,2,0,0,0,0,1
|
||||
"Maria Fefelova (mashafefel)",Russian,1,1,0,0,0,0,0
|
||||
Itch,,0,0,0,0,0,0,0
|
||||
"Muhammet Furkan ALMACI (furkan.almaci)",Turkish,0,0,0,1,0,0,0
|
||||
Sandhu564.,,0,0,0,0,0,0,0
|
||||
"Quentin Hibon (hiq)",,0,0,0,0,0,0,0
|
||||
mushin,,0,0,0,0,0,0,0
|
||||
"Balaji Jayaraman (jkbalaji1103)",,0,0,0,0,0,0,0
|
||||
"Wellington Ribeiro (wellington.rib)",,0,0,0,0,0,0,0
|
||||
"Javid IRAN (twitteriran98)",Persian,0,0,0,1,0,0,0
|
||||
"박인호 (wphestiraid)",Korean,0,0,0,2,0,0,0
|
||||
"Ahmed Nazir (ahmednazir333)",,0,0,0,0,0,0,0
|
||||
dimateos,,0,0,0,0,0,0,0
|
||||
AhmedDz,Arabic,0,0,0,1,0,0,0
|
||||
"reza golestanzadeh (reza.golestanzadeh)",Persian,0,0,0,1,0,0,0
|
||||
"Petros Bleyan (coolbleyan)",Russian,0,0,0,14,0,0,0
|
||||
Kamalakannan,,0,0,0,0,0,0,0
|
||||
"Dagna Q (dagnaq)",,0,0,0,0,0,0,0
|
||||
"Thomas Orlita (Thomas995)",Czech,0,0,0,1,0,0,0
|
||||
Fazy1380,,0,0,0,0,0,0,0
|
||||
"Rivo Zängov (Eraser)",,0,0,0,0,0,0,0
|
||||
T-v-Gerwen,Dutch,0,0,0,47,0,0,0
|
||||
"عبد الناصر سعيد الثبيتي (asaeed)",,0,0,0,0,0,0,0
|
||||
"Edmunds Edmundam (edmundam)",,0,0,0,0,0,0,0
|
||||
"vi ve (VimalV)",,0,0,0,0,0,0,0
|
||||
"LeMeD (LeMeS)",French,0,0,0,2,0,0,0
|
||||
"Éjbãss Übbeî (littlebittlebottle)",Norwegian,0,0,0,152,0,0,0
|
||||
EmanAmini,,0,0,0,0,0,0,0
|
||||
AnggaRifandi,,0,0,0,0,0,0,0
|
||||
"Mateusz Teteruk (mttet)",Polish,0,0,0,1,0,0,0
|
||||
"Lori Amico (lavodkaclyde2323)",Italian,0,0,0,1,0,0,0
|
||||
"Florian Stuhlmann (stuhlmann)",German,0,0,0,10,0,0,0
|
||||
"Yasin Okumus (lacivert)",Turkish,0,0,0,1,0,0,0
|
||||
NairaDNV,Spanish,0,0,0,9,0,0,0
|
||||
REMOVED_USER,,0,0,0,0,0,0,0
|
||||
farbod66,Persian,0,0,0,1,0,0,0
|
||||
Raulbertassi,,0,0,0,0,0,0,0
|
||||
"Равиль Мифтахов (ravilmif47)",Russian,0,0,0,1,0,0,0
|
||||
"Pumpith Ungsupanit (pumpithu)",,0,0,0,0,0,0,0
|
||||
"Nat Fomicheva (natac)",Russian,0,0,0,3,0,0,0
|
||||
EwanB,,0,0,0,0,0,0,0
|
||||
ava_rfie,Persian,0,0,0,1,0,0,0
|
||||
"George Merkulov (george142.emarket)",Russian,0,0,0,11,0,0,0
|
||||
REMOVED_USER,,0,0,0,0,0,0,0
|
||||
sanyoniket,,0,0,0,0,0,0,0
|
||||
"Shuvashish Sahoo (shuvashish76)",,0,0,0,0,0,0,0
|
||||
martyaberger,,0,0,0,0,0,0,0
|
||||
"Карлен Шаухаев (KarlenShaukhaev)",,0,0,0,0,0,0,0
|
||||
"Elmo (oberknecht)",,0,0,0,0,0,0,0
|
||||
Irsgram,Russian,0,0,0,1,0,0,0
|
||||
"Matus Zdansky (matuszdansky)",,0,0,0,0,0,0,0
|
||||
shuvo786,,0,0,0,0,0,0,0
|
||||
"Eduard Boboc (edi.boboc33)",Romanian,0,0,0,4,0,0,0
|
||||
Hayder21,,0,0,0,0,0,0,0
|
||||
AsadullahIlyas,,0,0,0,0,0,0,0
|
||||
"Никита Карамов (nikita.karamoff)",Russian,0,0,0,10,0,0,0
|
||||
"Katherine Alexandra Flórez Ramírez (katherine.florez12)",Spanish,0,0,0,46,0,0,0
|
||||
mdrobulis,,0,0,0,0,0,0,0
|
||||
"Eliška Roubalová (roubaeli)",Czech,0,0,0,6,0,0,0
|
||||
droidahmed,Arabic,0,0,0,7,0,0,0
|
||||
"Arjun K. (arjunkdot)",,0,0,0,0,0,0,0
|
||||
"Sarah BCNN (fsarahboucenna)",French,0,0,0,16,0,0,0
|
||||
REMOVED_USER,Czech,0,0,0,18,0,0,0
|
||||
BongTran,Vietnamese,0,0,0,2,0,0,0
|
||||
"Arttu Ylhävuori (arttu.ylhavuori)",,0,0,0,0,0,0,0
|
||||
valney.faria,"Portuguese, Brazilian",0,0,0,1,0,0,0
|
||||
REMOVED_USER,,0,0,0,0,0,0,0
|
||||
rooban23,,0,0,0,0,0,0,0
|
||||
REMOVED_USER,,0,0,0,0,0,0,0
|
||||
"Алтынбек Наурызғали (altinbeknaurizgali)",Russian,0,0,0,1,0,0,0
|
||||
"Sri Harsha Bhogi (sriharshabhogi)",,0,0,0,0,0,0,0
|
||||
"Ahnaf Tajwar (atn4404)",,0,0,0,0,0,0,0
|
||||
Elham1361,,0,0,0,0,0,0,0
|
||||
dongchen.yue,German,0,0,0,4,0,0,0
|
||||
philfr49,French,0,0,0,2,0,0,0
|
||||
Name,Languages,"Translated (Words)","Target Words","Approved (Words)",Voted,"""+"" votes received","""-"" votes received","Winning (Words)",Joined
|
||||
"Alinson Xavier (iSoron)","Portuguese, Brazilian; Japanese; Chinese Simplified; Italian; Spanish; Portuguese; French; Hungarian; Chinese Traditional; Turkish; Russian; Polish; Arabic; German; Korean; Greek; Catalan; Bulgarian; Hindi; Slovenian; Ukrainian; Serbian (Cyrillic); Czech; Indonesian; Croatian; Danish; Dutch; Romanian; Swedish; Basque; Persian; Finnish; Vietnamese; Tamil; Telugu; Hebrew; Esperanto; Norwegian; Afrikaans; Slovak; Armenian; Serbian (Latin); Uyghur",15497,18825,1308,0,1896,84,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"
|
||||
"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,1046,993,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"
|
||||
"Omer I.S. (omeritzics)",Hebrew,1040,927,1122,14,1,0,975,"2020-10-11 20:10:51"
|
||||
"Intan Ayunda (Intan_Ayunda)",Indonesian,818,811,985,0,0,0,729,"2020-10-14 07:51:58"
|
||||
"Mihail Stefanov (MStefanov)",Bulgarian,755,794,3,0,2,0,2,"2017-03-31 16:09:02"
|
||||
KMakoto,"Chinese Traditional",745,1146,949,0,0,0,745,"2019-10-22 04:19:52"
|
||||
"Evren (evrenkiymaz)",Turkish,688,604,0,71,28,22,0,"2020-10-04 03:39:16"
|
||||
andaryon,Czech,681,606,0,108,0,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"
|
||||
androide74,Italian,662,681,0,2,0,0,0,"2020-02-06 15:46:28"
|
||||
Osoitz,Basque,655,595,0,9,0,0,3,"2018-01-23 14:07:47"
|
||||
"Dmitriy Bogdanov (di72nn)",Russian,643,589,1197,0,36,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,1,0,"2020-10-01 18:17:23"
|
||||
"Saeed Esmaili (saaeed.es20)",Persian,586,795,0,5,4,0,0,"2020-11-26 15:41:15"
|
||||
fabian.bouchal,German,548,527,0,6,0,3,72,"2020-01-07 06:43:37"
|
||||
"Isti (eisti)",Hungarian,528,476,0,0,0,0,0,"2020-12-03 12:02:51"
|
||||
boban77,Czech,509,461,0,2,29,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,91,"2017-04-28 07:23:01"
|
||||
REMOVED_USER,Norwegian,501,498,501,0,148,0,501,"2017-07-05 19:02:25"
|
||||
"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,24,"2020-01-17 23:16:03"
|
||||
"Huy Ngo (huyngo)",Vietnamese,461,695,0,1,0,0,0,"2020-01-26 11:58:36"
|
||||
"Arkadiusz Bubak (epitek)",Polish,458,416,52,24,9,4,0,"2020-11-05 05:11:58"
|
||||
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"
|
||||
"Alparslan Şakçi (sakci)",Turkish,436,372,0,118,1,0,0,"2022-01-14 12:03:11"
|
||||
JY3,"Chinese Simplified",427,727,295,0,1,0,222,"2021-03-08 08:53:35"
|
||||
"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"
|
||||
"Alexander Jansson (dalecarlian)",Swedish,396,406,507,0,0,3,399,"2017-06-21 01:37:32"
|
||||
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,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"
|
||||
"Anh Quân (dangquanuet)",Vietnamese,362,530,0,42,2,0,0,"2017-10-29 12:27:44"
|
||||
gapszi,Hungarian,348,301,0,86,0,0,0,"2019-04-08 01:35:54"
|
||||
"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"
|
||||
"Magimai Prakasam (magimai)",Tamil,336,831,0,12,0,0,0,"2018-04-15 21:16:08"
|
||||
"Michael Malak (MichaelKMalak)",Arabic,304,271,0,0,1,0,0,"2020-05-26 19:47:58"
|
||||
Blinkin,Dutch,297,334,0,5,0,0,0,"2021-06-14 10:30:05"
|
||||
"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,5,0,22,"2019-11-20 03:28:26"
|
||||
"Marius Teufelweich (teufelweich)",German,267,272,611,4,13,1,146,"2021-03-12 04:11:38"
|
||||
hypnotichemionus,"Chinese Simplified",249,430,0,0,8,0,19,"2020-03-08 01:46:25"
|
||||
cobalt59,German,237,234,0,1,24,1,132,"2017-06-05 05:18:33"
|
||||
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"
|
||||
"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,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"
|
||||
sojusnik,German,207,200,1,0,30,0,66,"2017-04-03 17:11:56"
|
||||
"Andrij Mizyk (andmizyk)",Ukrainian,204,178,0,40,0,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"
|
||||
"Vijaykumar Borkar (vjkumar)",Hindi,200,364,0,11,0,0,0,"2021-08-06 16:12:15"
|
||||
_translator,French,199,227,0,11,0,0,0,"2021-07-06 07:54:12"
|
||||
Ishmaeel,Turkish,193,174,0,129,17,6,0,"2017-10-04 03:54:00"
|
||||
oscfd,Spanish,192,201,0,2,4,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"
|
||||
fbruna17,Danish,181,179,0,1,0,0,0,"2021-01-28 15:48:47"
|
||||
Bryanx,Dutch,179,168,0,5,2,0,0,"2019-11-21 17:08:12"
|
||||
"Omry Cohen (omrycohen)",Hebrew,175,156,0,1,0,0,33,"2021-01-18 07:33:23"
|
||||
"Pierre GALIEGUE (pierre.galiegue)",French,171,194,0,24,4,0,0,"2020-08-16 11:41:35"
|
||||
plitwin,Polish,168,151,0,2,31,0,49,"2021-01-20 06:18:37"
|
||||
DionysosDV,Greek,165,153,0,0,0,0,0,"2021-02-27 19:05:25"
|
||||
"Gustavo Lima (GustavoLima)",Portuguese,158,177,0,1,4,10,0,"2020-08-26 10:35:05"
|
||||
"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"
|
||||
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"
|
||||
"Neysa Nasywa (neysanasywa)",Indonesian,140,141,0,0,0,0,60,"2020-11-18 10:32:10"
|
||||
mohmans,Arabic,139,141,0,12,1,0,0,"2020-11-23 02:48:00"
|
||||
"Eilif Adelvice (adelvice)",Spanish,139,154,0,96,1,0,0,"2021-08-05 07:20:21"
|
||||
"Mohammed Imthath (mimthath4)",Tamil,136,274,0,0,11,0,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"
|
||||
"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"
|
||||
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"
|
||||
alalloush,Arabic,118,129,0,2,14,3,0,"2017-03-31 12:37:17"
|
||||
"Tanya (MagicUnderHood)",Russian,114,98,0,19,0,0,54,"2019-04-21 10:44:03"
|
||||
Sebastian05067,Spanish,114,133,0,55,28,0,0,"2017-05-14 00:48:16"
|
||||
REMOVED_USER,Arabic,111,106,0,22,22,2,0,"2018-01-05 07:01:45"
|
||||
"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"
|
||||
2kaafone,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"
|
||||
"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"
|
||||
"손유정 (yuwon1213)",Korean,95,57,0,0,1,0,0,"2021-03-30 05:25:33"
|
||||
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"
|
||||
ikkaz,Indonesian,89,84,0,5,0,0,4,"2019-09-02 19:58:54"
|
||||
"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,0,0,0,"2020-03-16 11:31:12"
|
||||
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"
|
||||
"Ohad Edri (ohadalte)",Hebrew,85,79,0,0,1,3,13,"2020-07-04 03:42:09"
|
||||
helectron,Persian,84,102,0,1,0,0,0,"2021-03-02 04:10:51"
|
||||
"Radu Cebotari (wildProgrammer)",Romanian,84,92,0,1,0,0,0,"2020-02-05 01:20:00"
|
||||
"Bruces Lee (aplusbdesign)",Korean,82,66,0,0,0,0,0,"2021-08-23 11:27:18"
|
||||
"Israa Z (sosozozo)",Arabic,79,87,0,43,14,0,3,"2017-11-27 14:10:50"
|
||||
"Sofia Neves (sofiasonev)","Portuguese, Brazilian",79,84,0,1,0,0,46,"2020-03-12 18:19:46"
|
||||
"Jacob Roller (jdr28070)",Korean,79,61,0,0,1,0,0,"2020-01-03 11:36:40"
|
||||
Tiralka,French,79,91,0,92,1,0,0,"2018-02-09 18:39:01"
|
||||
"Toni Mustonen (toni.mustonen)",Finnish,78,72,0,0,5,0,0,"2017-09-02 05:34:12"
|
||||
"Michael (quelbs)",German,76,75,0,1,0,0,39,"2020-08-18 07:39:26"
|
||||
"Fauz Aladeem (topfauz)",Arabic,76,77,0,0,0,1,0,"2020-02-21 22:46:12"
|
||||
"Radoslaw Biernacki (radoslaw.biernacki)",Polish,70,74,0,56,1,0,1,"2020-12-15 17:55:31"
|
||||
"Oliver Gronowski (OliverGronowski)",German,70,69,0,5,2,0,0,"2021-05-14 16:37:10"
|
||||
RealDonald,Dutch,67,69,0,121,10,0,0,"2017-06-23 20:10:12"
|
||||
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"
|
||||
"Laura Sophie (laurasophie20)",German,62,67,0,4,0,0,0,"2018-01-06 14:21:24"
|
||||
raden20,Indonesian,61,62,177,0,1,0,64,"2017-04-09 22:04:23"
|
||||
"Peter Williams (williamspete001)",Japanese,60,173,0,2,0,0,3,"2020-01-01 13:17:44"
|
||||
"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"
|
||||
"Андрій Козицький (andriikozytskyi1108)",Ukrainian,52,52,0,0,1,0,0,"2018-10-22 01:45:08"
|
||||
"Nil riera (nilriera2000)",Catalan,52,61,0,1,2,0,0,"2021-06-22 16:37:44"
|
||||
"Neoone (Neooneqq)",Romanian,51,54,0,0,0,0,0,"2022-05-05 20:42:11"
|
||||
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"
|
||||
"Mare Geldenhuys (mare.geldenhuys)",Afrikaans,50,57,0,0,0,0,0,"2017-10-20 18:00:14"
|
||||
"Mahmoud Magdy (M7moudManson)",Arabic,49,60,0,6,8,1,0,"2021-08-21 09:01:38"
|
||||
"Behnood HRazy (behnoodhr)",Persian,49,70,0,0,0,0,0,"2017-11-25 10:57:21"
|
||||
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"
|
||||
vach,Armenian,47,36,0,0,0,0,0,"2020-04-18 16:53:12"
|
||||
"Andrew Firnes (Anechan)",Russian,47,47,0,3,0,0,29,"2019-09-18 09:51:59"
|
||||
andowero,Czech,47,38,0,0,3,0,0,"2020-01-20 02:29:01"
|
||||
"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"
|
||||
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"
|
||||
"Boban Jagertraum (boban40)",Czech,43,38,0,2,18,1,0,"2017-03-31 09:39:16"
|
||||
"Kamil Dziadek (prso94)",Polish,43,39,0,0,6,0,0,"2020-04-06 17:12:06"
|
||||
andreea.muscalagiu,Romanian,42,52,0,1,0,0,0,"2017-10-22 07:19:49"
|
||||
"Me Me (gentelwom)",Arabic,42,40,0,0,0,0,0,"2020-11-08 20:44:01"
|
||||
"Balázs Keresztury (belidzs)",Hungarian,42,41,501,0,7,0,38,"2017-04-06 02:40:24"
|
||||
"Mateusz Duda (MateuszDuda)",Polish,42,42,0,0,6,0,0,"2021-08-17 11:27:11"
|
||||
"Ali Elsheikh (aelsheikh1987)",Arabic,42,41,0,0,0,0,0,"2021-06-16 10:17:26"
|
||||
"Ali Zali (stm19951995)",Persian,40,60,0,0,0,0,0,"2020-03-23 19:57:26"
|
||||
"Sofia Veijonen (Suklaa) (sofia.veijonen)",Finnish,40,33,0,0,0,0,0,"2018-03-07 09:24:22"
|
||||
dusanstrgar,Slovenian,39,41,0,0,0,0,0,"2017-03-31 10:30:28"
|
||||
"Limin Lu (liminlu)","Chinese Simplified",39,79,503,0,0,0,39,"2017-03-31 09:49:35"
|
||||
Anshoe,Tamil,38,65,0,14,0,0,0,"2018-01-02 11:06:52"
|
||||
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"
|
||||
"Abdulrahman (D7M)",Arabic,36,39,0,0,0,0,0,"2020-01-29 18:55:30"
|
||||
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"
|
||||
"Maria Chushnyakova (maria.ch)",Russian,36,31,0,3,0,0,0,"2021-08-17 03:23:58"
|
||||
"長谷川知里 (chase0213)",Japanese,34,138,0,13,0,0,24,"2018-12-14 10:52:44"
|
||||
"Piotr Łuczyński (peterluczynski)",Polish,33,30,0,6,10,0,2,"2020-01-29 07:27:40"
|
||||
"Luis E. Perichon (luisperichon)",Spanish,33,40,0,104,0,0,0,"2017-09-04 13:46:06"
|
||||
"milad farahani (miladfarmahini90)",Persian,33,44,0,18,1,0,3,"2017-08-31 16:09:00"
|
||||
JoeLi,"Chinese Traditional",31,70,0,12,0,0,24,"2017-06-25 05:32:48"
|
||||
andriikozytskyi2625,Ukrainian,31,23,0,0,0,0,0,"2019-07-08 00:16:41"
|
||||
REMOVED_USER,Russian,31,30,0,2,4,0,3,"2018-12-03 23:55:47"
|
||||
Moastafa,Arabic,31,25,0,0,0,0,0,"2020-07-06 11:37:53"
|
||||
"hamza gamal (hamzagamal4444)",Arabic,31,28,0,0,0,0,0,"2020-08-03 15:23:34"
|
||||
yancyn,"Chinese Simplified",30,40,0,0,0,0,1,"2020-05-18 20:06:03"
|
||||
"Ruud Schouten (ruudschouten)",Dutch,29,32,0,41,3,0,0,"2017-07-22 17:49:17"
|
||||
"비니몬youtube (khj01025276475)",Korean,29,25,0,0,0,0,0,"2020-02-09 20:44:35"
|
||||
avelneve,Indonesian,29,28,0,0,0,0,0,"2022-04-13 13:26:10"
|
||||
"Niraj Yadav (neverforgetniraj)",Hindi,26,48,0,0,0,0,0,"2017-04-11 02:26:50"
|
||||
"Aaron Dalton (Perlkonig)",French,26,25,0,141,1,0,0,"2018-01-14 12:58:19"
|
||||
"Jonny I (jonny99dj)",Italian,26,26,0,5,0,0,0,"2017-10-07 07:35:34"
|
||||
"Guillaume Collic (gcollic)",French,26,28,0,126,11,0,0,"2017-05-05 16:13:00"
|
||||
Pan_Filuta,Czech,25,21,0,5,8,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"
|
||||
"eduard83 (barbany.eduard)",Catalan,24,25,0,2,0,0,0,"2019-06-26 14:59:47"
|
||||
"A Aa (ylayzlmimashisafyoutub)",Arabic,23,33,0,34,1,1,0,"2021-09-27 15:34:26"
|
||||
"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"
|
||||
"Neeraj Verma (verma.neeraj.in)",Hindi,22,37,0,0,1,0,0,"2018-07-23 07:16:41"
|
||||
gnu-ewm,Polish,22,23,0,6,2,0,0,"2021-02-24 03:42:01"
|
||||
hodanli,Turkish,22,26,0,0,1,0,0,"2017-11-03 14:33:41"
|
||||
"Alcarkse (alexis.brusle)",French,21,25,0,7,11,0,0,"2017-08-06 09:32:29"
|
||||
"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"
|
||||
can13,Turkish,19,14,0,8,0,0,0,"2021-01-03 10:39:03"
|
||||
"사자솥 (toke1597)",Korean,19,19,0,0,0,0,0,"2020-02-04 13:36:11"
|
||||
KenKailer,Arabic,19,25,0,0,0,0,0,"2022-05-10 06:16:54"
|
||||
"İ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"
|
||||
sheeCesu,French,19,18,0,48,4,0,0,"2017-12-21 17:01:39"
|
||||
axikman11111,Uyghur,18,19,0,0,0,0,0,"2018-10-13 12:25:31"
|
||||
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"
|
||||
takoyakibento,Korean,17,13,0,3,0,0,0,"2020-08-01 08:44:15"
|
||||
"Ceara Lopez (cealopez)",Spanish,17,18,0,0,5,1,0,"2017-08-22 22:56:13"
|
||||
bretzel15,German,16,20,0,0,0,0,0,"2020-04-06 02:49:14"
|
||||
DebatablySane,Bulgarian,16,15,0,48,0,0,0,"2017-07-10 15:13:18"
|
||||
"Şamil Ateşoğlu (m.samilatesoglu)",Turkish,16,22,0,11,6,3,0,"2017-07-05 18:37:08"
|
||||
engineeringforgood,Russian,16,15,0,0,0,0,16,"2021-01-22 03:32:35"
|
||||
"Bhava Tharini (bhavidanush)",Tamil,15,37,0,0,0,0,0,"2019-10-09 05:43:11"
|
||||
"Maro Chr (caprisunglasses)",Greek,14,17,0,0,0,0,0,"2021-08-17 06:53:33"
|
||||
"Zeynep Esen (nezihaesen50)",Turkish,14,13,0,0,0,0,0,"2020-01-28 07:05:15"
|
||||
iamsurajbobade,Hindi,14,30,0,0,0,0,0,"2018-05-21 11:23:27"
|
||||
"Faiz Ahamed (faiznewton)",Tamil,14,31,0,0,0,0,0,"2021-05-06 23:06:46"
|
||||
"Sanji Vinsmock (mukanzhanbolat4)",Russian,14,14,0,0,0,0,0,"2020-02-18 12:38:54"
|
||||
"Zeeshan Rabbani (Zeera)",Hindi,14,25,0,0,0,0,0,"2020-09-15 11:32:01"
|
||||
"pi hobbes (uwe_silv)",Japanese,14,46,0,0,0,0,0,"2022-01-15 02:57:14"
|
||||
"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"
|
||||
"EuiHo Hwang (euiho.hwang)",Korean,14,16,0,0,0,0,0,"2020-06-23 02:40:01"
|
||||
"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"
|
||||
"Ana Kelly Vale (anakvale)","Portuguese, Brazilian",13,21,0,4,0,0,2,"2022-03-30 00:15:37"
|
||||
GiorgioHerbie,Italian,13,15,0,0,0,0,0,"2022-01-17 17:35:40"
|
||||
"Nenad Vukotic (vukotic.nenad)","Serbian (Cyrillic)",13,13,0,1,2,6,0,"2019-01-31 14:29:15"
|
||||
soura2,Arabic,12,13,0,0,0,0,0,"2020-01-13 19:23:47"
|
||||
"shreyas (techiespace)",Hindi,12,20,0,0,0,0,0,"2018-06-10 01:14:26"
|
||||
"Jo Chuang (josephch405)","Chinese Traditional",11,24,0,0,0,0,11,"2017-06-16 20:21:06"
|
||||
Vmrc,French,11,12,0,2,0,0,0,"2020-11-02 05:35:06"
|
||||
"Ammar Naif (Ammar_Naif)",Arabic,11,11,0,4,0,0,0,"2022-01-15 05:16:41"
|
||||
"Sonu Sharma (riteetude)",Hindi,11,23,0,0,0,0,0,"2021-05-30 19:38:00"
|
||||
"Edwin van Rooij (edwinvrooij)",Dutch,10,13,0,17,0,0,0,"2018-11-05 03:59:10"
|
||||
"Brian Camacho (bmcamacho)",Polish,10,11,0,0,1,1,0,"2020-08-03 02:27:28"
|
||||
"Mihael Wagner (miha.wagner)",Slovenian,10,9,0,7,0,0,0,"2017-10-18 18:26:29"
|
||||
"Hrant Hakobian (hrastgh1)",Armenian,10,9,0,0,0,0,0,"2021-08-29 15:22:10"
|
||||
"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"
|
||||
"Anonymous edgy nerd (yamentaad)",Arabic,10,13,0,1,0,0,0,"2018-05-06 09:23:57"
|
||||
"Zesar Cebrián (Txorrota)",Spanish,10,44,0,0,0,0,0,"2022-02-09 01:34:32"
|
||||
"Milan Siebenbürger (lennyd)",Czech,10,7,0,1,0,0,0,"2022-01-30 07:09:42"
|
||||
"Suhaili Hassan (kucingsyg96)",Indonesian,9,10,0,0,0,0,0,"2018-06-10 11:55:09"
|
||||
"Sourire Lucide (sourire_lucide)",Russian,9,10,0,0,1,0,0,"2018-03-22 01:37:55"
|
||||
"Martin Vostatek (martinvostatek)",Czech,9,8,0,32,2,0,0,"2019-01-21 13:52:36"
|
||||
"Seweryn Piotrowski (Draxxsx)",Polish,9,10,0,0,19,0,0,"2020-01-02 09:55:48"
|
||||
"Jakob Weickmann (jweickm)",Japanese,8,21,0,0,0,0,0,"2021-10-05 11:10:25"
|
||||
Rex123,Persian,8,8,0,0,0,0,0,"2017-07-01 00:47:42"
|
||||
"Andrey ZaXeLoN (waragaa)",Russian,7,7,0,8,1,0,0,"2017-09-18 21:37:42"
|
||||
"Konstantin (KZhidovinov)",Russian,7,7,0,0,0,0,0,"2020-01-29 13:35:12"
|
||||
ftfoi,Norwegian,7,6,0,0,0,0,0,"2020-04-11 20:42:35"
|
||||
"Vladimir Pavlychev (vovs03)",Russian,7,9,0,0,0,0,0,"2017-12-18 02:46:56"
|
||||
"Felipe Chagas (chagretes)","Portuguese, Brazilian",7,8,0,0,3,0,5,"2022-01-10 12:20:25"
|
||||
"Андрій Козицький (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"
|
||||
ChloeLiang,Japanese,6,22,0,0,1,0,3,"2017-08-08 05:02:59"
|
||||
"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"
|
||||
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"
|
||||
andriikozytskyi2018,Ukrainian,5,5,0,0,0,0,0,"2017-09-03 05:24:43"
|
||||
"Vitor Henrique (vitorhcl)","Portuguese, Brazilian",5,8,0,1,0,0,0,"2022-03-08 20:00:59"
|
||||
"Matthias Joly (joly.matt12)",French,5,8,0,27,1,0,0,"2017-08-28 09:53:59"
|
||||
"Tomáš Hrabáček (Hrabyyy)",Czech,5,3,0,0,1,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"
|
||||
"Micaela Pighin (micaelapiighin)",Spanish,5,6,0,1,0,0,0,"2019-10-09 23:32:42"
|
||||
"Manuel Tassi (Mannivu)",Italian,5,6,0,0,0,0,0,"2021-01-03 11:00:33"
|
||||
"Neko123 (emandic11)","Serbian (Cyrillic)",4,4,0,57,0,0,0,"2021-04-21 15:33:29"
|
||||
"Lopo Isaac Fernández (rocapata)",Spanish,4,3,0,0,0,0,0,"2018-09-20 11:46:22"
|
||||
"Eli Besirov (elibesirov07)",Turkish,4,4,0,0,0,0,0,"2019-03-25 07:12:34"
|
||||
marmo,German,4,4,0,0,0,0,0,"2021-01-13 01:16:35"
|
||||
bziuum,Polish,4,4,0,0,3,0,0,"2020-09-01 09:08:01"
|
||||
"Craig Foobar (craig.foobar)",German,3,3,0,25,0,0,0,"2022-02-20 16:55:47"
|
||||
Katarin,Ukrainian,3,3,0,0,0,0,0,"2022-03-17 14:44:59"
|
||||
"Sarath S (CyberShark)",Tamil,3,7,0,0,0,0,0,"2020-08-27 22:43:16"
|
||||
"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"
|
||||
"Cláudio Bernardo (claudiobernardo.ti)","Portuguese, Brazilian",3,4,0,1,0,0,0,"2019-01-08 14:41:10"
|
||||
"Unnie Here (Carb)",Hindi,3,8,0,0,0,0,0,"2020-03-18 23:34:35"
|
||||
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"
|
||||
"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"
|
||||
Magidxz,Arabic,3,3,0,0,0,0,0,"2021-01-05 05:02:54"
|
||||
"Péter Bernát (bernatp)",Hungarian,3,2,0,0,0,0,0,"2019-11-30 15:50:33"
|
||||
"joabe gabriel (joabegabrielcma1)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-08-21 09:08:59"
|
||||
"Gabriel Cavalcante (gabrielc.alves14)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2018-08-06 22:24:54"
|
||||
"Martin Zimdahl (zimdahlmartin)",Swedish,3,2,0,0,1,0,3,"2018-09-15 04:39:22"
|
||||
atomjani,Hungarian,3,3,0,0,0,0,0,"2019-01-19 00:49:25"
|
||||
"mohammadali barati (mabaraty)",Persian,3,3,0,0,0,0,0,"2021-07-10 05:54:44"
|
||||
"Hiohana Rilary (hiohanarilary)","Portuguese, Brazilian",3,4,0,0,0,0,0,"2019-07-31 20:42:20"
|
||||
"Tejaswini Boppana (Tejaswini)",Telugu,3,1,0,0,0,0,0,"2021-08-27 23:48:55"
|
||||
"Andrea Bianchi (andreawhite1597)",Italian,3,1,0,1,0,0,0,"2018-01-21 17:45:48"
|
||||
"Ño Bí Tã (pt614553)",Arabic,2,8,0,1,0,2,0,"2021-05-22 20:41:01"
|
||||
"Judith Ayala (Azul1612)",Spanish,2,1,0,0,0,1,0,"2021-05-18 17:07:19"
|
||||
"Valerij D (vala.dobler)",German,2,2,0,0,0,0,0,"2018-09-22 09:38:27"
|
||||
"Balthazar Aubard (Balatzar)",French,2,5,0,0,1,0,0,"2017-09-23 01:42:57"
|
||||
"Ahmed Bazazo (ahmedbazazo)",Arabic,2,2,0,0,0,0,0,"2022-02-19 20:11:09"
|
||||
"Ali Zaida (alizaeda92)",Arabic,2,2,0,0,0,0,0,"2019-12-01 11:47:00"
|
||||
"FAy FAy (fayfayfay52)","Chinese Traditional",2,5,0,0,0,0,0,"2017-10-06 08:53:21"
|
||||
Soroor_SI,Persian,2,2,0,0,0,0,0,"2018-06-10 06:28:27"
|
||||
chavs1997,Russian,2,2,0,9,0,0,0,"2018-05-18 16:58:19"
|
||||
"Naveen jai krishna (njsbpolymer1)",Tamil,2,5,0,0,0,0,0,"2020-01-10 14:19:41"
|
||||
omerfarukbas,Turkish,2,3,0,19,2,0,0,"2017-08-14 16:10:35"
|
||||
"Ilyas Fekhar (il47yas)",Arabic,2,2,0,0,0,0,0,"2018-04-17 22:00:41"
|
||||
"Héctor Mañas García (hectodium)",Catalan,2,3,0,0,0,0,0,"2021-10-02 20:32:09"
|
||||
"Walid Baazia (walidbaazia2005)",Arabic,2,1,0,0,0,0,0,"2021-01-27 12:47:34"
|
||||
"fatemeh s (fargolseifoori3)",Persian,2,2,0,0,0,0,0,"2019-01-31 12:06:57"
|
||||
"hesamiranii (esam.matouri)",Persian,2,2,0,0,0,0,0,"2018-09-22 16:33:36"
|
||||
REMOVED_USER,Ukrainian,2,2,0,0,0,0,0,"2017-06-15 12:24:44"
|
||||
"Alex Stein (diefaust1993)",Russian,2,2,0,4,4,0,2,"2017-07-13 06:56:17"
|
||||
amei,"Portuguese, Brazilian",2,2,0,0,0,0,0,"2018-04-19 19:42:28"
|
||||
"أم محمد تقي (souadboudia19)",Arabic,2,2,0,0,0,0,0,"2020-06-13 15:24:17"
|
||||
LNDDYL,"Chinese Traditional",2,4,0,0,0,0,2,"2018-04-22 04:00:19"
|
||||
"조화정 (yunjoo337)",Korean,2,2,0,0,0,0,0,"2019-06-16 22:25:31"
|
||||
"Sidali Aymen (sidaliaymen950)",Arabic,2,2,0,0,0,0,0,"2022-01-31 18:50:59"
|
||||
"Danial Agh (danialagh)",Persian,2,3,0,0,0,0,0,"2019-03-30 13:24:16"
|
||||
iSoron2,"Portuguese, Brazilian",1,1,0,0,0,0,0,"2017-03-18 17:56:29"
|
||||
"Anton (tT0NG)","Chinese Traditional",1,2,0,0,0,0,1,"2017-07-06 14:18:39"
|
||||
"Luca Gori (grolcu)",Italian,1,2,0,0,0,0,0,"2020-09-26 23:26:15"
|
||||
axd,Spanish,1,1,0,15,0,0,0,"2017-09-12 05:48:51"
|
||||
REMOVED_USER,Russian,1,2,0,6,1,0,1,"2019-12-26 05:37:01"
|
||||
jonesses,German,1,1,0,1,0,0,1,"2021-01-01 08:03:18"
|
||||
"Alan Jeon (skyisle)",Korean,1,2,0,8,0,0,0,"2018-01-09 10:46:00"
|
||||
"Maria Fefelova (mashafefel)",Russian,1,1,0,0,0,0,0,"2019-05-18 02:03:56"
|
||||
"Patrick Pimenta (trickap1)","Portuguese, Brazilian",1,1,0,0,0,0,0,"2018-12-01 14:31:21"
|
||||
"박찌 (perpact20)",Korean,1,1,0,0,0,0,0,"2018-02-10 10:11:44"
|
||||
"Kan Black (kanblack.va)",Vietnamese,1,2,0,0,0,1,0,"2019-01-15 03:50:10"
|
||||
"Anastasiia Bondarenko (nastasya.bondarenko.97)",Russian,1,1,0,0,0,0,0,"2019-06-07 17:43:08"
|
||||
"Wibi Cahyo (wbcahyoh)",Indonesian,1,3,0,0,0,0,0,"2017-12-14 06:35:58"
|
||||
sanyoniket,,0,0,0,0,0,0,0,"2019-07-23 12:58:40"
|
||||
"Sri Harsha Bhogi (sriharshabhogi)",,0,0,0,0,0,0,0,"2018-09-02 05:31:53"
|
||||
Irsgram,Russian,0,0,0,1,0,0,0,"2019-09-30 16:42:20"
|
||||
"Baran Özavcı (n2141n)",Turkish,0,0,0,1,0,0,0,"2022-02-26 04:32:51"
|
||||
"Masataka Yakura (myakura)",Japanese,0,0,0,1,0,0,0,"2021-09-03 22:10:36"
|
||||
ava_rfie,Persian,0,0,0,1,0,0,0,"2019-06-09 16:19:24"
|
||||
T-v-Gerwen,Dutch,0,0,0,47,0,0,0,"2018-03-02 10:26:33"
|
||||
"George Merkulov (george142.emarket)",Russian,0,0,0,11,0,0,0,"2019-06-09 19:47:02"
|
||||
philfr49,French,0,0,0,2,0,0,0,"2018-09-03 14:20:32"
|
||||
"عبد الناصر سعيد الثبيتي (asaeed)",,0,0,0,0,0,0,0,"2018-03-13 02:09:35"
|
||||
"Thomas Orlita (Thomas995)",Czech,0,0,0,1,0,0,0,"2017-12-24 04:08:27"
|
||||
"Edmunds Edmundam (edmundam)",,0,0,0,0,0,0,0,"2020-06-01 14:18:18"
|
||||
"Elmo (oberknecht)",,0,0,0,0,0,0,0,"2020-04-16 08:45:50"
|
||||
"Равиль Мифтахов (ravilmif47)",Russian,0,0,0,1,0,0,0,"2019-08-12 21:58:30"
|
||||
"Manny Farsangy (manifarsangi)",Persian,0,0,0,12,0,0,0,"2021-08-10 05:32:28"
|
||||
"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"
|
||||
REMOVED_USER,,0,0,0,0,0,0,0,"2018-08-24 00:17:43"
|
||||
REMOVED_USER,,0,0,0,0,0,0,0,"2020-02-01 03:47:48"
|
||||
"Arjun K. (arjunkdot)",,0,0,0,0,0,0,0,"2020-09-20 11:16:18"
|
||||
EwanB,,0,0,0,0,0,0,0,"2019-11-19 10:04:38"
|
||||
shuvo786,,0,0,0,0,0,0,0,"2019-11-13 00:18:12"
|
||||
"Pro AAA (pro1010)",Arabic,0,0,0,1,0,0,0,"2022-02-14 03:32:44"
|
||||
"manu (manuL96)",,0,0,0,0,0,0,0,"2022-05-06 23:34:55"
|
||||
"Rivo Zängov (Eraser)",,0,0,0,0,0,0,0,"2020-10-13 04:38:26"
|
||||
ashik8113,,0,0,0,0,0,0,0,"2022-04-13 11:58:26"
|
||||
deepbird,,0,0,0,0,0,0,0,"2022-04-11 03:21:05"
|
||||
REMOVED_USER,,0,0,0,0,0,0,0,"2018-10-27 15:34:36"
|
||||
Elham1361,,0,0,0,0,0,0,0,"2018-10-27 12:01:06"
|
||||
"Ahnaf Tajwar (atn4404)",,0,0,0,0,0,0,0,"2018-10-16 11:13:30"
|
||||
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"
|
||||
"akmal shafiq (mohdakmalshafiq)",,0,0,0,0,0,0,0,"2021-11-01 01:04:50"
|
||||
"Sylwuskak (sylwuskak)",Polish,0,0,0,1,0,0,0,"2022-01-25 04:19:53"
|
||||
"Yunsu Kim (yunsukim86)",Korean,0,0,0,2,0,0,0,"2022-01-14 06:33:43"
|
||||
"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"
|
||||
HemanthMeda,Telugu,0,0,0,4,0,0,0,"2021-12-01 14:02:14"
|
||||
"darkkingredian (rediancool)",,0,0,0,0,0,0,0,"2021-07-27 16:04:32"
|
||||
catemlitten,Japanese,0,0,0,1,0,0,0,"2021-11-17 15:06:02"
|
||||
"Said Tahsin Dane (tasomaniac)",,0,0,0,0,0,0,0,"2021-09-25 05:31:01"
|
||||
"Matus Zdansky (matuszdansky)",,0,0,0,0,0,0,0,"2019-10-20 13:52:24"
|
||||
mdrobulis,,0,0,0,0,0,0,0,"2018-05-24 01:40:42"
|
||||
valney.faria,"Portuguese, Brazilian",0,0,0,1,0,0,0,"2020-02-02 14:45:02"
|
||||
"Petros Bleyan (coolbleyan)",Russian,0,0,0,14,0,0,0,"2017-08-18 18:37:18"
|
||||
"Карлен Шаухаев (KarlenShaukhaev)",,0,0,0,0,0,0,0,"2020-04-27 08:53:49"
|
||||
"Shuvashish Sahoo (shuvashish76)",,0,0,0,0,0,0,0,"2020-09-17 09:10:09"
|
||||
REMOVED_USER,,0,0,0,0,0,0,0,"2018-01-05 16:56:12"
|
||||
"Dagna Q (dagnaq)",,0,0,0,0,0,0,0,"2017-08-06 01:42:52"
|
||||
Sandhu564.,,0,0,0,0,0,0,0,"2020-12-14 01:27:45"
|
||||
AhmedDz,Arabic,0,0,0,1,0,0,0,"2017-12-31 10:12:31"
|
||||
"Quentin Hibon (hiq)",,0,0,0,0,0,0,0,"2021-02-07 16:39:31"
|
||||
"Ahmed Nazir (ahmednazir333)",,0,0,0,0,0,0,0,"2018-05-06 12:10:27"
|
||||
"박인호 (wphestiraid)",Korean,0,0,0,2,0,0,0,"2018-01-05 00:33:14"
|
||||
Raulbertassi,,0,0,0,0,0,0,0,"2018-01-07 17:23:18"
|
||||
"Javid IRAN (twitteriran98)",Persian,0,0,0,1,0,0,0,"2017-11-25 16:47:25"
|
||||
"Wellington Ribeiro (wellington.rib)",,0,0,0,0,0,0,0,"2017-11-16 07:32:25"
|
||||
dimateos,,0,0,0,0,0,0,0,"2021-01-10 06:29:52"
|
||||
"Balaji Jayaraman (jkbalaji1103)",,0,0,0,0,0,0,0,"2017-10-30 22:12:27"
|
||||
"reza golestanzadeh (reza.golestanzadeh)",Persian,0,0,0,1,0,0,0,"2020-10-21 12:07:20"
|
||||
"Muhammet Furkan ALMACI (furkan.almaci)",Turkish,0,0,0,1,0,0,0,"2017-10-29 13:44:56"
|
||||
dongchen.yue,German,0,0,0,4,0,0,0,"2020-09-12 15:05:59"
|
||||
"Алтынбек Наурызғали (altinbeknaurizgali)",Russian,0,0,0,1,0,0,0,"2020-08-12 13:03:49"
|
||||
rooban23,,0,0,0,0,0,0,0,"2020-09-15 11:49:14"
|
||||
NairaDNV,Spanish,0,0,0,9,0,0,0,"2018-01-05 19:10:33"
|
||||
"Katherine Alexandra Flórez Ramírez (katherine.florez12)",Spanish,0,0,0,46,0,0,0,"2018-01-20 02:18:32"
|
||||
Itch,,0,0,0,0,0,0,0,"2017-10-16 09:18:42"
|
||||
"Yasin Okumus (lacivert)",Turkish,0,0,0,1,0,0,0,"2018-02-07 04:13:51"
|
||||
"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"
|
||||
Fazy1380,,0,0,0,0,0,0,0,"2021-04-10 11:02:53"
|
||||
"Arttu Ylhävuori (arttu.ylhavuori)",,0,0,0,0,0,0,0,"2019-07-24 15:03:42"
|
||||
EmanAmini,,0,0,0,0,0,0,0,"2017-03-31 13:27:43"
|
||||
AnggaRifandi,,0,0,0,0,0,0,0,"2017-03-31 19:28:35"
|
||||
"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"
|
||||
Kamalakannan,,0,0,0,0,0,0,0,"2017-05-14 11:40:23"
|
||||
farbod66,Persian,0,0,0,1,0,0,0,"2018-01-20 11:04:23"
|
||||
"vi ve (VimalV)",,0,0,0,0,0,0,0,"2021-02-08 02:35:45"
|
||||
"Éjbãss Übbeî (littlebittlebottle)",Norwegian,0,0,0,152,0,0,0,"2017-07-05 21:12:02"
|
||||
"LeMeD (LeMeS)",French,0,0,0,2,0,0,0,"2021-02-06 15:35:00"
|
||||
BongTran,Vietnamese,0,0,0,2,0,0,0,"2018-04-24 05:16:07"
|
||||
REMOVED_USER,Czech,0,0,0,18,0,0,0,"2018-03-27 06:19:52"
|
||||
mushin,,0,0,0,0,0,0,0,"2020-02-02 04:08:05"
|
||||
"Mateusz Teteruk (mttet)",Polish,0,0,0,1,0,0,0,"2021-01-23 13:09:59"
|
||||
"Sarah BCNN (fsarahboucenna)",French,0,0,0,16,0,0,0,"2018-02-11 11:07:36"
|
||||
droidahmed,Arabic,0,0,0,7,0,0,0,"2018-01-31 02:18:49"
|
||||
"Никита Карамов (nikita.karamoff)",Russian,0,0,0,10,0,0,0,"2018-10-29 03:57:21"
|
||||
|
||||
|
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
|
||||
*
|
||||
@@ -20,11 +18,10 @@
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id("com.github.triplet.play") version "3.2.0"
|
||||
id("com.android.application")
|
||||
id("com.github.triplet.play") version "3.8.6"
|
||||
id("com.android.application") version "8.1.4"
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("org.jetbrains.kotlin.kapt")
|
||||
id("org.jetbrains.kotlin.android.extensions")
|
||||
id("org.jlleitschuh.gradle.ktlint")
|
||||
}
|
||||
|
||||
@@ -32,17 +29,29 @@ tasks.compileLint {
|
||||
dependsOn("updateTranslators")
|
||||
}
|
||||
|
||||
/*
|
||||
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(11)
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
compileSdkVersion(30)
|
||||
namespace = "org.isoron.uhabits"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
versionCode(20001)
|
||||
versionName("2.0.1")
|
||||
minSdkVersion(23)
|
||||
targetSdkVersion(30)
|
||||
applicationId("org.isoron.uhabits")
|
||||
testInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner")
|
||||
versionCode = 20200
|
||||
versionName = "2.2.0"
|
||||
minSdk = 28
|
||||
targetSdk = 34
|
||||
applicationId = "org.isoron.uhabits"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -58,7 +67,7 @@ android {
|
||||
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
minifyEnabled(true)
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt")
|
||||
if (signingConfigs.findByName("release") != null) {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
@@ -70,16 +79,13 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
isCheckReleaseBuilds = false
|
||||
isAbortOnError = false
|
||||
disable("GoogleAppIndexingWarning")
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
targetCompatibility(JavaVersion.VERSION_1_8)
|
||||
sourceCompatibility(JavaVersion.VERSION_1_8)
|
||||
targetCompatibility(JavaVersion.VERSION_11)
|
||||
sourceCompatibility(JavaVersion.VERSION_11)
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
@@ -88,29 +94,29 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
val daggerVersion = "2.34.1"
|
||||
val kotlinVersion = "1.4.32"
|
||||
val kxCoroutinesVersion = "1.4.2"
|
||||
val ktorVersion = "1.5.3"
|
||||
val espressoVersion = "3.3.0"
|
||||
val daggerVersion = "2.48.1"
|
||||
val kotlinVersion = "1.9.21"
|
||||
val kxCoroutinesVersion = "1.7.3"
|
||||
val ktorVersion = "1.6.8"
|
||||
val espressoVersion = "3.5.1"
|
||||
|
||||
androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion")
|
||||
androidTestImplementation("com.google.dagger:dagger:$daggerVersion")
|
||||
androidTestImplementation("com.linkedin.dexmaker:dexmaker-mockito:2.28.1")
|
||||
androidTestImplementation("com.linkedin.dexmaker:dexmaker-mockito:2.28.3")
|
||||
androidTestImplementation("io.ktor:ktor-client-mock:$ktorVersion")
|
||||
androidTestImplementation("io.ktor:ktor-jackson:$ktorVersion")
|
||||
androidTestImplementation("androidx.annotation:annotation:1.2.0")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.2")
|
||||
androidTestImplementation("androidx.annotation:annotation:1.7.0")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
|
||||
androidTestImplementation("androidx.test:rules:1.3.0")
|
||||
androidTestImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
|
||||
androidTestImplementation("androidx.test:rules:1.5.0")
|
||||
androidTestImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
|
||||
compileOnly("javax.annotation:jsr250-api:1.0")
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
|
||||
implementation("com.github.paolorotolo:appintro:3.4.0")
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
|
||||
implementation("com.github.AppIntro:AppIntro:6.3.1")
|
||||
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("com.google.guava:guava:32.1.3-android")
|
||||
implementation("io.ktor:ktor-client-android:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-core:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-jackson:$ktorVersion")
|
||||
@@ -118,17 +124,17 @@ dependencies {
|
||||
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.2.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.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.3.0")
|
||||
implementation("com.opencsv:opencsv:5.4")
|
||||
implementation("com.google.android.material:material:1.10.0")
|
||||
implementation("com.opencsv:opencsv:5.9")
|
||||
implementation(project(":uhabits-core"))
|
||||
kapt("com.google.dagger:dagger-compiler:$daggerVersion")
|
||||
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")
|
||||
testImplementation("org.mockito.kotlin:mockito-kotlin:5.1.0")
|
||||
}
|
||||
|
||||
kapt {
|
||||
|
||||
|
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 |
|
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: 6.9 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -39,6 +39,7 @@ open class BaseUserInterfaceTest {
|
||||
private lateinit var prefs: Preferences
|
||||
private lateinit var fixtures: HabitFixtures
|
||||
private lateinit var cache: HabitCardListCache
|
||||
|
||||
@Before
|
||||
@Throws(Exception::class)
|
||||
fun setUp() {
|
||||
|
||||
@@ -153,18 +153,22 @@ open class BaseViewTest : BaseAndroidTest() {
|
||||
var filename = filename
|
||||
var dir = getSDCardDir("test-screenshots")
|
||||
if (dir == null) dir = AndroidDirFinder(targetContext).getFilesDir("test-screenshots")
|
||||
if (dir == null) throw RuntimeException(
|
||||
"Could not find suitable dir for screenshots"
|
||||
)
|
||||
if (dir == null) {
|
||||
throw RuntimeException(
|
||||
"Could not find suitable dir for screenshots"
|
||||
)
|
||||
}
|
||||
filename = filename.replace("\\.png$".toRegex(), "$suffix.png")
|
||||
val absolutePath = String.format("%s/%s", dir.absolutePath, filename)
|
||||
val parent = File(absolutePath).parentFile
|
||||
if (!parent.exists() && !parent.mkdirs()) throw RuntimeException(
|
||||
String.format(
|
||||
"Could not create dir: %s",
|
||||
parent.absolutePath
|
||||
if (!parent.exists() && !parent.mkdirs()) {
|
||||
throw RuntimeException(
|
||||
String.format(
|
||||
"Could not create dir: %s",
|
||||
parent.absolutePath
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
val out = FileOutputStream(absolutePath)
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
return absolutePath
|
||||
|
||||
@@ -23,10 +23,10 @@ import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||
import org.isoron.uhabits.core.models.Frequency
|
||||
import org.isoron.uhabits.core.models.Frequency.Companion.DAILY
|
||||
import org.isoron.uhabits.core.models.Habit
|
||||
import org.isoron.uhabits.core.models.Habit.Companion.AT_LEAST
|
||||
import org.isoron.uhabits.core.models.Habit.Companion.NUMBER_HABIT
|
||||
import org.isoron.uhabits.core.models.HabitList
|
||||
import org.isoron.uhabits.core.models.HabitType
|
||||
import org.isoron.uhabits.core.models.ModelFactory
|
||||
import org.isoron.uhabits.core.models.NumericalHabitType
|
||||
import org.isoron.uhabits.core.models.PaletteColor
|
||||
import org.isoron.uhabits.core.models.Timestamp
|
||||
import org.isoron.uhabits.core.utils.DateUtils.Companion.getToday
|
||||
@@ -102,8 +102,8 @@ class HabitFixtures(private val modelFactory: ModelFactory, private val habitLis
|
||||
val habit = modelFactory.buildHabit().apply {
|
||||
name = "Read"
|
||||
question = "How many pages did you walk today?"
|
||||
type = NUMBER_HABIT
|
||||
targetType = AT_LEAST
|
||||
type = HabitType.NUMERICAL
|
||||
targetType = NumericalHabitType.AT_LEAST
|
||||
targetValue = 200.0
|
||||
unit = "pages"
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package org.isoron.uhabits
|
||||
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
@@ -35,6 +34,7 @@ import org.isoron.uhabits.inject.ActivityScope
|
||||
import org.isoron.uhabits.inject.HabitModule
|
||||
import org.isoron.uhabits.inject.HabitsActivityModule
|
||||
import org.isoron.uhabits.inject.HabitsApplicationComponent
|
||||
import org.mockito.kotlin.mock
|
||||
|
||||
@Module
|
||||
class TestModule {
|
||||
|
||||
@@ -55,6 +55,7 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@LargeTest
|
||||
class HabitsTest : BaseUserInterfaceTest() {
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun shouldCreateHabit() {
|
||||
@@ -180,6 +181,8 @@ class HabitsTest : BaseUserInterfaceTest() {
|
||||
longPressCheckmarks("Wake up early", count = 2)
|
||||
clickText("Wake up early")
|
||||
verifyShowsScreen(SHOW_HABIT)
|
||||
// TODO: find a better way than sleeping in tests
|
||||
Thread.sleep(2001L)
|
||||
verifyDisplaysText("10%")
|
||||
}
|
||||
|
||||
@@ -194,6 +197,8 @@ class HabitsTest : BaseUserInterfaceTest() {
|
||||
verifyDoesNotDisplayText("Track time")
|
||||
verifyDisplaysText("Wake up early")
|
||||
longPressCheckmarks("Wake up early", count = 1)
|
||||
// TODO: find a better way than sleeping in tests
|
||||
Thread.sleep(2001L)
|
||||
verifyDoesNotDisplayText("Wake up early")
|
||||
clickMenu(TOGGLE_COMPLETED)
|
||||
verifyDisplaysText("Track time")
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.isoron.uhabits.acceptance.steps
|
||||
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.os.SystemClock.sleep
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import org.isoron.uhabits.BaseUserInterfaceTest.Companion.device
|
||||
@@ -39,7 +40,7 @@ fun exportFullBackup() {
|
||||
}
|
||||
|
||||
fun clearDownloadFolder() {
|
||||
device.executeShellCommand("rm -rf /sdcard/Download/")
|
||||
device.executeShellCommand("rm -rf /sdcard/Download")
|
||||
}
|
||||
|
||||
fun clearBackupFolder() {
|
||||
@@ -86,6 +87,7 @@ fun importBackupFromDownloadFolder() {
|
||||
device.findObject(UiSelector().textContains("Loop")).click()
|
||||
} else {
|
||||
device.click(50, 90) // Click menu button
|
||||
Thread.sleep(1000)
|
||||
device.findObject(UiSelector().textContains("Download")).click()
|
||||
device.findObject(UiSelector().textContains("Loop")).click()
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
*/
|
||||
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.recyclerview.widget.RecyclerView
|
||||
import androidx.test.espresso.Espresso
|
||||
@@ -31,11 +32,11 @@ import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiSelector
|
||||
import androidx.test.uiautomator.Until
|
||||
import junit.framework.Assert.assertTrue
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.activities.habits.list.ListHabitsActivity
|
||||
import org.junit.Assert.assertTrue
|
||||
|
||||
object CommonSteps : BaseUserInterfaceTest() {
|
||||
fun pressBack() {
|
||||
@@ -72,7 +73,7 @@ object CommonSteps : BaseUserInterfaceTest() {
|
||||
}
|
||||
|
||||
fun offsetHeaders() {
|
||||
device.swipe(750, 160, 600, 160, 20)
|
||||
device.swipe(500, 160, 350, 160, 20)
|
||||
}
|
||||
|
||||
fun scrollToText(text: String?) {
|
||||
@@ -133,7 +134,7 @@ object CommonSteps : BaseUserInterfaceTest() {
|
||||
@Throws(Exception::class)
|
||||
fun verifyOpensWebsite(url: String?) {
|
||||
var browserPkg = "org.chromium.webview_shell"
|
||||
if (VERSION.SDK_INT <= 23) {
|
||||
if (SDK_INT <= Build.VERSION_CODES.M) {
|
||||
browserPkg = "com.android.browser"
|
||||
}
|
||||
assertTrue(device.wait(Until.hasObject(By.pkg(browserPkg)), 5000))
|
||||
@@ -146,15 +147,19 @@ object CommonSteps : BaseUserInterfaceTest() {
|
||||
Screen.LIST_HABITS ->
|
||||
Espresso.onView(ViewMatchers.withClassName(CoreMatchers.endsWith("ListHabitsRootView")))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
Screen.SHOW_HABIT ->
|
||||
Espresso.onView(ViewMatchers.withId(R.id.subtitleCard))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
Screen.EDIT_HABIT ->
|
||||
Espresso.onView(ViewMatchers.withId(R.id.questionInput))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
Screen.SELECT_HABIT_TYPE ->
|
||||
Espresso.onView(ViewMatchers.withText(R.string.yes_or_no_example))
|
||||
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
@@ -178,6 +183,22 @@ object CommonSteps : BaseUserInterfaceTest() {
|
||||
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 {
|
||||
LIST_HABITS, SHOW_HABIT, EDIT_HABIT, SELECT_HABIT_TYPE
|
||||
}
|
||||
|
||||
@@ -36,6 +36,24 @@ object EditHabitSteps {
|
||||
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) {
|
||||
Espresso.onView(ViewMatchers.withId(R.id.colorButton)).perform(ViewActions.click())
|
||||
BaseUserInterfaceTest.device.findObject(By.descStartsWith(String.format("Color %d", color)))
|
||||
|
||||
@@ -53,6 +53,7 @@ object ListHabitsSteps {
|
||||
clickViewWithId(R.id.action_filter)
|
||||
CommonSteps.clickText(R.string.hide_completed)
|
||||
}
|
||||
else -> throw RuntimeException()
|
||||
}
|
||||
device.waitForIdle()
|
||||
}
|
||||
@@ -120,6 +121,12 @@ object ListHabitsSteps {
|
||||
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 {
|
||||
ABOUT, HELP, SETTINGS, EDIT, DELETE, ARCHIVE, TOGGLE_ARCHIVED, UNARCHIVE, TOGGLE_COMPLETED, ADD
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
*/
|
||||
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.UiSelector
|
||||
import junit.framework.Assert.assertFalse
|
||||
import junit.framework.Assert.assertTrue
|
||||
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
|
||||
object WidgetSteps {
|
||||
@Throws(Exception::class)
|
||||
@@ -50,29 +50,21 @@ object WidgetSteps {
|
||||
private fun openWidgetScreen() {
|
||||
val h = BaseUserInterfaceTest.device.displayHeight
|
||||
val w = BaseUserInterfaceTest.device.displayWidth
|
||||
if (VERSION.SDK_INT <= 21) {
|
||||
BaseUserInterfaceTest.device.pressHome()
|
||||
BaseUserInterfaceTest.device.waitForIdle()
|
||||
BaseUserInterfaceTest.device.findObject(UiSelector().description("Apps")).click()
|
||||
BaseUserInterfaceTest.device.findObject(UiSelector().description("Apps")).click()
|
||||
BaseUserInterfaceTest.device.findObject(UiSelector().description("Widgets")).click()
|
||||
} else {
|
||||
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"))
|
||||
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 (SDK_INT >= 28) {
|
||||
UiScrollable(UiSelector().resourceId(listId))
|
||||
.scrollForward()
|
||||
}
|
||||
UiScrollable(UiSelector().resourceId(listId))
|
||||
.scrollIntoView(UiSelector().text("Checkmark"))
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.isoron.uhabits.activities.common.views
|
||||
|
||||
import android.view.MotionEvent
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
@@ -52,7 +53,8 @@ class FrequencyChartTest : BaseViewTest() {
|
||||
@Test
|
||||
@Throws(Throwable::class)
|
||||
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()
|
||||
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
||||
}
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
*/
|
||||
package org.isoron.uhabits.activities.common.views
|
||||
|
||||
import android.view.MotionEvent
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.core.models.Habit
|
||||
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter.Companion.buildState
|
||||
import org.isoron.uhabits.core.ui.views.LightTheme
|
||||
import org.isoron.uhabits.utils.toFixedAndroidColor
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -39,7 +41,12 @@ class ScoreChartTest : BaseViewTest() {
|
||||
super.setUp()
|
||||
fixtures.purgeHabits(habitList)
|
||||
habit = fixtures.createLongHabit()
|
||||
val state = buildState(habit, prefs.firstWeekdayInt, 0)
|
||||
val state = buildState(
|
||||
habit = habit,
|
||||
firstWeekday = prefs.firstWeekdayInt,
|
||||
spinnerPosition = 0,
|
||||
theme = LightTheme()
|
||||
)
|
||||
view = ScoreChart(targetContext).apply {
|
||||
setScores(state.scores)
|
||||
setColor(state.color.toFixedAndroidColor())
|
||||
@@ -57,7 +64,8 @@ class ScoreChartTest : BaseViewTest() {
|
||||
@Test
|
||||
@Throws(Throwable::class)
|
||||
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()
|
||||
assertRenders(view, BASE_PATH + "renderDataOffset.png")
|
||||
}
|
||||
@@ -72,7 +80,7 @@ class ScoreChartTest : BaseViewTest() {
|
||||
@Test
|
||||
@Throws(Throwable::class)
|
||||
fun testRender_withMonthlyBucket() {
|
||||
val (scores, bucketSize) = buildState(habit, prefs.firstWeekdayInt, 2)
|
||||
val (scores, bucketSize) = buildState(habit, prefs.firstWeekdayInt, 2, LightTheme())
|
||||
view.setScores(scores)
|
||||
view.setBucketSize(bucketSize)
|
||||
view.invalidate()
|
||||
@@ -89,7 +97,7 @@ class ScoreChartTest : BaseViewTest() {
|
||||
@Test
|
||||
@Throws(Throwable::class)
|
||||
fun testRender_withYearlyBucket() {
|
||||
val state = buildState(habit, prefs.firstWeekdayInt, 4)
|
||||
val state = buildState(habit, prefs.firstWeekdayInt, 4, LightTheme())
|
||||
view.setScores(state.scores)
|
||||
view.setBucketSize(state.bucketSize)
|
||||
view.invalidate()
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.junit.runner.RunWith
|
||||
@MediumTest
|
||||
class StreakChartTest : BaseViewTest() {
|
||||
private lateinit var view: StreakChart
|
||||
|
||||
@Before
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
@@ -29,6 +29,10 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@MediumTest
|
||||
class EmptyListViewTest : BaseViewTest() {
|
||||
init {
|
||||
// TODO: fix rendering differences across APIs
|
||||
similarityCutoff = 0.00035
|
||||
}
|
||||
|
||||
private val path = "habits/list/EmptyListView"
|
||||
private val view: EmptyListView = EmptyListView(targetContext)
|
||||
|
||||
@@ -36,6 +36,7 @@ class EntryButtonViewTest : BaseViewTest() {
|
||||
lateinit var view: CheckmarkButtonView
|
||||
|
||||
var toggled = false
|
||||
var edited = false
|
||||
|
||||
@Before
|
||||
override fun setUp() {
|
||||
@@ -43,7 +44,8 @@ class EntryButtonViewTest : BaseViewTest() {
|
||||
view = component.getEntryButtonViewFactory().create().apply {
|
||||
value = Entry.NO
|
||||
color = PaletteUtils.getAndroidTestColor(5)
|
||||
onToggle = { toggled = true }
|
||||
onToggle = { _, _ -> toggled = true }
|
||||
onEdit = { edited = true }
|
||||
}
|
||||
measureView(view, dpToPixels(48), dpToPixels(48))
|
||||
}
|
||||
@@ -70,20 +72,28 @@ class EntryButtonViewTest : BaseViewTest() {
|
||||
fun testClick_withShortToggleDisabled() {
|
||||
prefs.isShortToggleEnabled = false
|
||||
view.performClick()
|
||||
assertFalse(toggled)
|
||||
assertTrue(!toggled and edited)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClick_withShortToggleEnabled() {
|
||||
prefs.isShortToggleEnabled = true
|
||||
view.performClick()
|
||||
assertTrue(toggled)
|
||||
assertTrue(toggled and !edited)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLongClick() {
|
||||
fun testLongClick_withShortToggleDisabled() {
|
||||
prefs.isShortToggleEnabled = false
|
||||
view.performLongClick()
|
||||
assertTrue(toggled)
|
||||
assertTrue(toggled and !edited)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLongClick_withShortToggleEnabled() {
|
||||
prefs.isShortToggleEnabled = true
|
||||
view.performLongClick()
|
||||
assertTrue(!toggled and edited)
|
||||
}
|
||||
|
||||
private fun assertRendersCheckedExplicitly() {
|
||||
|
||||
@@ -77,7 +77,7 @@ class EntryPanelViewTest : BaseViewTest() {
|
||||
@Test
|
||||
fun testToggle() {
|
||||
val timestamps = mutableListOf<Timestamp>()
|
||||
view.onToggle = { t, _ -> timestamps.add(t) }
|
||||
view.onToggle = { t, _, _ -> timestamps.add(t) }
|
||||
view.buttons[0].performLongClick()
|
||||
view.buttons[2].performLongClick()
|
||||
view.buttons[3].performLongClick()
|
||||
@@ -88,7 +88,7 @@ class EntryPanelViewTest : BaseViewTest() {
|
||||
fun testToggle_withOffset() {
|
||||
val timestamps = mutableListOf<Timestamp>()
|
||||
view.dataOffset = 3
|
||||
view.onToggle = { t, _ -> timestamps += t }
|
||||
view.onToggle = { t, _, _ -> timestamps += t }
|
||||
view.buttons[0].performLongClick()
|
||||
view.buttons[2].performLongClick()
|
||||
view.buttons[3].performLongClick()
|
||||
|
||||
@@ -20,15 +20,15 @@ package org.isoron.uhabits.activities.habits.list.views
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.verify
|
||||
import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@MediumTest
|
||||
|
||||
@@ -20,9 +20,6 @@ package org.isoron.uhabits.activities.habits.list.views
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import com.nhaarman.mockitokotlin2.doReturn
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.whenever
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
@@ -30,6 +27,9 @@ import org.isoron.uhabits.core.ui.screens.habits.list.HintList
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@MediumTest
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.test.filters.MediumTest
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.core.models.NumericalHabitType
|
||||
import org.isoron.uhabits.utils.PaletteUtils
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@@ -42,6 +43,7 @@ class NumberButtonViewTest : BaseViewTest() {
|
||||
super.setUp()
|
||||
view = component.getNumberButtonViewFactory().create().apply {
|
||||
units = "steps"
|
||||
targetType = NumericalHabitType.AT_LEAST
|
||||
threshold = 100.0
|
||||
color = PaletteUtils.getAndroidTestColor(8)
|
||||
onEdit = { edited = true }
|
||||
@@ -74,10 +76,10 @@ class NumberButtonViewTest : BaseViewTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRender_emptyUnits() {
|
||||
fun testRender_atMostAboveThreshold() {
|
||||
view.value = 500.0
|
||||
view.units = ""
|
||||
assertRenders(view, "$PATH/render_unitless.png")
|
||||
view.targetType = NumericalHabitType.AT_MOST
|
||||
assertRenders(view, "$PATH/render_at_most_above.png")
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,6 +88,13 @@ class NumberButtonViewTest : BaseViewTest() {
|
||||
assertRenders(view, "$PATH/render_below.png")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRender_atMostBetweenThresholds() {
|
||||
view.value = 110.0
|
||||
view.targetType = NumericalHabitType.AT_MOST
|
||||
assertRenders(view, "$PATH/render_at_most_between.png")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRender_zero() {
|
||||
view.value = 0.0
|
||||
@@ -93,15 +102,21 @@ class NumberButtonViewTest : BaseViewTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClick_shortToggleDisabled() {
|
||||
prefs.isShortToggleEnabled = false
|
||||
view.performClick()
|
||||
assertFalse(edited)
|
||||
fun testRender_atMostBelowThreshold() {
|
||||
view.value = 0.0
|
||||
view.targetType = NumericalHabitType.AT_MOST
|
||||
assertRenders(view, "$PATH/render_at_most_below.png")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClick_shortToggleEnabled() {
|
||||
prefs.isShortToggleEnabled = true
|
||||
fun testRender_emptyUnits() {
|
||||
view.value = 500.0
|
||||
view.units = ""
|
||||
assertRenders(view, "$PATH/render_unitless.png")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testClick() {
|
||||
view.performClick()
|
||||
assertTrue(edited)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.test.filters.MediumTest
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.core.models.NumericalHabitType
|
||||
import org.isoron.uhabits.core.models.Timestamp
|
||||
import org.isoron.uhabits.utils.PaletteUtils
|
||||
import org.junit.After
|
||||
@@ -55,6 +56,7 @@ class NumberPanelViewTest : BaseViewTest() {
|
||||
buttonCount = 4
|
||||
color = PaletteUtils.getAndroidTestColor(7)
|
||||
units = "steps"
|
||||
targetType = NumericalHabitType.AT_LEAST
|
||||
threshold = 5000.0
|
||||
}
|
||||
view.onAttachedToWindow()
|
||||
@@ -74,7 +76,7 @@ class NumberPanelViewTest : BaseViewTest() {
|
||||
@Test
|
||||
fun testEdit() {
|
||||
val timestamps = mutableListOf<Timestamp>()
|
||||
view.onEdit = { timestamps.plusAssign(it) }
|
||||
view.onEdit = { t -> timestamps.plusAssign(t) }
|
||||
view.buttons[0].performLongClick()
|
||||
view.buttons[2].performLongClick()
|
||||
view.buttons[3].performLongClick()
|
||||
@@ -85,7 +87,7 @@ class NumberPanelViewTest : BaseViewTest() {
|
||||
fun testEdit_withOffset() {
|
||||
val timestamps = mutableListOf<Timestamp>()
|
||||
view.dataOffset = 3
|
||||
view.onEdit = { timestamps += it }
|
||||
view.onEdit = { t -> timestamps += t }
|
||||
view.buttons[0].performLongClick()
|
||||
view.buttons[2].performLongClick()
|
||||
view.buttons[3].performLongClick()
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.ui.screens.habits.show.views.FrequencyCardPresenter
|
||||
import org.isoron.uhabits.core.ui.views.LightTheme
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -43,7 +44,13 @@ class FrequencyCardViewTest : BaseViewTest() {
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById<View>(R.id.frequencyCard) as FrequencyCardView
|
||||
view.setState(FrequencyCardPresenter.buildState(habit = habit, firstWeekday = 0))
|
||||
view.setState(
|
||||
FrequencyCardPresenter.buildState(
|
||||
habit = habit,
|
||||
firstWeekday = 0,
|
||||
theme = LightTheme()
|
||||
)
|
||||
)
|
||||
measureView(view, 800f, 600f)
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ class HistoryCardViewTest : BaseViewTest() {
|
||||
HistoryCardPresenter.buildState(
|
||||
habit = habit,
|
||||
firstWeekday = SUNDAY,
|
||||
theme = LightTheme(),
|
||||
theme = LightTheme()
|
||||
)
|
||||
)
|
||||
measureView(view, 800f, 600f)
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.models.PaletteColor
|
||||
import org.isoron.uhabits.core.ui.screens.habits.show.views.OverviewCardState
|
||||
import org.isoron.uhabits.core.ui.views.LightTheme
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -50,6 +51,7 @@ class OverviewCardViewTest : BaseViewTest() {
|
||||
scoreYearDiff = 0.74f,
|
||||
totalCount = 44,
|
||||
color = PaletteColor(7),
|
||||
theme = LightTheme()
|
||||
)
|
||||
)
|
||||
measureView(view, 800f, 300f)
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.ui.screens.habits.show.views.ScoreCardPresenter.Companion.buildState
|
||||
import org.isoron.uhabits.core.ui.views.LightTheme
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -43,7 +44,14 @@ class ScoreCardViewTest : BaseViewTest() {
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById<View>(R.id.scoreCard) as ScoreCardView
|
||||
view.setState(buildState(habit = habit, firstWeekday = 0, spinnerPosition = 0))
|
||||
view.setState(
|
||||
buildState(
|
||||
habit = habit,
|
||||
firstWeekday = 0,
|
||||
spinnerPosition = 0,
|
||||
theme = LightTheme()
|
||||
)
|
||||
)
|
||||
measureView(view, 800f, 600f)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.test.filters.MediumTest
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.ui.screens.habits.show.views.StreakCardState
|
||||
import org.isoron.uhabits.core.ui.views.LightTheme
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -47,6 +48,7 @@ class StreakCardViewTest : BaseViewTest() {
|
||||
StreakCardState(
|
||||
bestStreaks = habit.streaks.getBest(10),
|
||||
color = habit.color,
|
||||
theme = LightTheme()
|
||||
)
|
||||
)
|
||||
measureView(view, 800f, 600f)
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.isoron.uhabits.core.models.PaletteColor
|
||||
import org.isoron.uhabits.core.models.Reminder
|
||||
import org.isoron.uhabits.core.models.WeekdayList.Companion.EVERY_DAY
|
||||
import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardState
|
||||
import org.isoron.uhabits.core.ui.views.LightTheme
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -52,8 +53,7 @@ class SubtitleCardViewTest : BaseViewTest() {
|
||||
isNumerical = false,
|
||||
question = "Did you meditate this morning?",
|
||||
reminder = Reminder(8, 30, EVERY_DAY),
|
||||
unit = "",
|
||||
targetValue = 0.0,
|
||||
theme = LightTheme()
|
||||
)
|
||||
)
|
||||
measureView(view, 800f, 200f)
|
||||
|
||||
@@ -61,7 +61,7 @@ class PerformanceTest : BaseAndroidTest() {
|
||||
val habit = fixtures.createEmptyHabit()
|
||||
for (i in 0..4999) {
|
||||
val timestamp: Timestamp = Timestamp(i * DAY_LENGTH)
|
||||
CreateRepetitionCommand(habitList, habit, timestamp, 1).run()
|
||||
CreateRepetitionCommand(habitList, habit, timestamp, 1, "").run()
|
||||
}
|
||||
db.setTransactionSuccessful()
|
||||
db.endTransaction()
|
||||
|
||||
@@ -21,9 +21,12 @@ package org.isoron.uhabits.regression
|
||||
|
||||
import androidx.test.filters.LargeTest
|
||||
import org.isoron.uhabits.BaseUserInterfaceTest
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.EDIT_HABIT
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.LIST_HABITS
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.Screen.SELECT_HABIT_TYPE
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.changeFrequencyToDaily
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.changeFrequencyToMonthly
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.clickText
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.createHabit
|
||||
import org.isoron.uhabits.acceptance.steps.CommonSteps.launchApp
|
||||
@@ -37,9 +40,12 @@ import org.isoron.uhabits.acceptance.steps.EditHabitSteps.clickSave
|
||||
import org.isoron.uhabits.acceptance.steps.EditHabitSteps.typeName
|
||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.ADD
|
||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.DELETE
|
||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.changeSort
|
||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.clickMenu
|
||||
import org.isoron.uhabits.acceptance.steps.ListHabitsSteps.longPressCheckmarks
|
||||
import org.isoron.uhabits.core.models.Entry.Companion.NO
|
||||
import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN
|
||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO
|
||||
import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL
|
||||
import org.junit.Test
|
||||
|
||||
@@ -83,4 +89,37 @@ class ListHabitsRegressionTest : BaseUserInterfaceTest() {
|
||||
offsetHeaders()
|
||||
verifyDisplaysCheckmarks("Wake up early", listOf(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN))
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/iSoron/uhabits/issues/1131
|
||||
*/
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun should_refresh_sort_after_habit_edit() {
|
||||
launchApp()
|
||||
verifyShowsScreen(LIST_HABITS)
|
||||
changeSort("By score")
|
||||
changeSort("By status")
|
||||
longPressCheckmarks("Meditate", count = 1)
|
||||
changeFrequencyToMonthly("Read books")
|
||||
longPressCheckmarks("Read books", count = 2)
|
||||
longPressCheckmarks("Read books", count = 1)
|
||||
verifyDisplaysCheckmarks("Meditate", listOf(YES_AUTO, YES_MANUAL, YES_AUTO, YES_MANUAL))
|
||||
CommonSteps.verifyDisplaysTextInSequence(
|
||||
"Wake up early",
|
||||
"Read books",
|
||||
"Meditate",
|
||||
"Track time"
|
||||
)
|
||||
|
||||
changeFrequencyToDaily("Meditate")
|
||||
|
||||
verifyDisplaysCheckmarks("Meditate", listOf(NO, YES_MANUAL, UNKNOWN, YES_MANUAL))
|
||||
CommonSteps.verifyDisplaysTextInSequence(
|
||||
"Wake up early",
|
||||
"Meditate",
|
||||
"Read books",
|
||||
"Track time"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,15 @@ import android.widget.FrameLayout
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.MediumTest
|
||||
import org.hamcrest.CoreMatchers
|
||||
import org.hamcrest.CoreMatchers.`is`
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.CoreMatchers.`is`
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.isoron.uhabits.BaseViewTest
|
||||
import org.isoron.uhabits.R
|
||||
import org.isoron.uhabits.core.models.Entry
|
||||
import org.isoron.uhabits.core.models.EntryList
|
||||
import org.isoron.uhabits.core.models.Habit
|
||||
import org.isoron.uhabits.core.models.Timestamp
|
||||
import org.isoron.uhabits.core.utils.DateUtils.Companion.getTodayWithOffset
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -42,10 +43,12 @@ class CheckmarkWidgetTest : BaseViewTest() {
|
||||
private lateinit var habit: Habit
|
||||
private lateinit var entries: EntryList
|
||||
private lateinit var view: FrameLayout
|
||||
private val today = getTodayWithOffset()
|
||||
private lateinit var today: Timestamp
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
setTheme(R.style.WidgetTheme)
|
||||
today = getTodayWithOffset()
|
||||
prefs.widgetOpacity = 255
|
||||
prefs.isSkipEnabled = true
|
||||
habit = fixtures.createVeryLongHabit()
|
||||
|
||||
@@ -32,6 +32,10 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@MediumTest
|
||||
class TargetWidgetTest : BaseViewTest() {
|
||||
init {
|
||||
// TODO: fix rendering differences across APIs
|
||||
similarityCutoff = 0.00025
|
||||
}
|
||||
private lateinit var habit: Habit
|
||||
private lateinit var view: FrameLayout
|
||||
override fun setUp() {
|
||||
|
||||
@@ -33,9 +33,11 @@ import java.io.IOException
|
||||
@MediumTest
|
||||
class CheckmarkWidgetViewTest : BaseViewTest() {
|
||||
private lateinit var view: CheckmarkWidgetView
|
||||
|
||||
@Before
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
similarityCutoff = 0.00025
|
||||
setTheme(R.style.WidgetTheme)
|
||||
val habit = fixtures.createShortHabit()
|
||||
val computedEntries = habit.computedEntries
|
||||
@@ -50,7 +52,7 @@ class CheckmarkWidgetViewTest : BaseViewTest() {
|
||||
name = habit.name
|
||||
}
|
||||
view.refresh()
|
||||
measureView(view, dpToPixels(100), dpToPixels(200))
|
||||
measureView(view, dpToPixels(100), dpToPixels(125))
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
~ You should have received a copy of the GNU General Public License along
|
||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="org.isoron.uhabits">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
android:name=".HabitsApplication"
|
||||
@@ -29,6 +30,7 @@
|
||||
android:backupAgent=".HabitsBackupAgent"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/main_activity_title"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppBaseTheme">
|
||||
|
||||
@@ -48,11 +50,11 @@
|
||||
android:name=".activities.habits.list.ListHabitsActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/main_activity_title"
|
||||
android:launchMode="singleTop">
|
||||
</activity>
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<activity-alias
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/main_activity_title"
|
||||
android:launchMode="singleTop"
|
||||
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
||||
@@ -85,6 +87,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".widgets.activities.HabitPickerDialog"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
@@ -93,6 +96,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".widgets.activities.BooleanHabitPickerDialog"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
@@ -101,6 +105,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".widgets.activities.NumericalHabitPickerDialog"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
@@ -115,26 +120,16 @@
|
||||
android:value=".activities.habits.list.ListHabitsActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".widgets.activities.NumericalCheckmarkWidgetActivity"
|
||||
android:label="NumericalCheckmarkWidget"
|
||||
android:noHistory="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="org.isoron.uhabits.ACTION_SHOW_NUMERICAL_VALUE_ACTIVITY" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".notifications.SnoozeDelayPickerActivity"
|
||||
android:taskAffinity=""
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.CheckmarkWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/checkmark">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@@ -152,6 +147,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.HistoryWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/history">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@@ -164,6 +160,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.ScoreWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/score">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@@ -176,6 +173,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.StreakWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/streaks">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@@ -188,6 +186,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.FrequencyWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/frequency">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@@ -200,6 +199,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.TargetWidgetProvider"
|
||||
android:exported="true"
|
||||
android:label="@string/target">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
@@ -210,13 +210,17 @@
|
||||
android:resource="@xml/widget_target_info" />
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receivers.ReminderReceiver">
|
||||
<receiver
|
||||
android:name=".receivers.ReminderReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receivers.WidgetReceiver">
|
||||
<receiver android:name=".receivers.WidgetReceiver"
|
||||
android:exported="true"
|
||||
android:permission="false">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="org.isoron.uhabits.ACTION_SET_NUMERICAL_VALUE" />
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.animation.Keyframe;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.text.format.Time;
|
||||
import android.view.View;
|
||||
|
||||
@@ -43,17 +42,13 @@ public class Utils {
|
||||
|
||||
static final String SHARED_PREFS_NAME = "com.android.calendar_preferences";
|
||||
|
||||
public static boolean isJellybeanOrLater() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to speak the specified text, for accessibility. Only available on JB or later.
|
||||
* @param text Text to announce.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public static void tryAccessibilityAnnounce(View view, CharSequence text) {
|
||||
if (isJellybeanOrLater() && view != null && text != null) {
|
||||
if (view != null && text != null) {
|
||||
view.announceForAccessibility(text);
|
||||
}
|
||||
}
|
||||
|
||||