Compare commits

...

56 Commits

Author SHA1 Message Date
e8a4a9740e Merge branch 'dev' into feature/sync 2021-08-22 05:13:37 -05:00
f15c660d33 Merge branch 'master' into dev 2021-08-21 07:40:28 -05:00
1866743c47 Remove absolute path to flock; change PATH in GH Actions 2021-08-21 07:22:51 -05:00
Ganessh Kumar
a781a1f947 Updating links in README
Updating http links to https links. By using http links from browser - all of them are getting redirected to https automatically except http://www.gnu.org/licenses, which displays a warning message that the connection is not secure. Switching to https makes the connection secure as well.
2021-08-16 07:21:15 -05:00
Quentin Hibon
13e57b5026 Test isFailedToday 2021-08-06 06:14:16 -05:00
Quentin Hibon
f8c7abfff4 Use 'entered' instead of 'completed' when ? or skips are enabled 2021-08-06 06:14:16 -05:00
Quentin Hibon
7fe3ce970c Hide failed habits along with completed ones 2021-08-06 06:14:16 -05:00
Quentin Hibon
b9eb244b0b Introduce HabitType and NumericalHabitType enums 2021-08-06 05:48:15 -05:00
Quentin Hibon
95a1786c4a build.sh: use full path for flock
Fixes #1044.
2021-08-02 08:30:38 +02:00
dependabot[bot]
caa1c9d72e Bump daggerVersion from 2.37 to 2.38.1
Bumps `daggerVersion` from 2.37 to 2.38.1.

Updates `dagger` from 2.37 to 2.38.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.37...dagger-2.38.1)

Updates `dagger-compiler` from 2.37 to 2.38.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.37...dagger-2.38.1)

---
updated-dependencies:
- dependency-name: com.google.dagger:dagger
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.google.dagger:dagger-compiler
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 23:49:25 +02:00
dependabot[bot]
a7afe0b309 Bump logback-classic from 1.2.3 to 1.2.5
Bumps logback-classic from 1.2.3 to 1.2.5.

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-classic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 22:53:41 +02:00
dependabot[bot]
9c03174eef Bump material from 1.3.0 to 1.4.0
Bumps [material](https://github.com/material-components/material-components-android) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/material-components/material-components-android/releases)
- [Commits](https://github.com/material-components/material-components-android/compare/1.3.0...1.4.0)

---
updated-dependencies:
- dependency-name: com.google.android.material:material
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 19:30:13 +02:00
dependabot[bot]
da02926fa6 Bump kotlin-stdlib-jdk8 from 1.5.20 to 1.5.21
Bumps [kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.5.20 to 1.5.21.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.20...v1.5.21)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 18:31:57 +02:00
Quentin Hibon
250dabfe58 Bump com.github.triplet.play from 3.2.0 to 3.5.0 2021-08-01 18:07:06 +02:00
dependabot[bot]
0bba3b76bc Bump kotlinx-coroutines-core-jvm from 1.4.2 to 1.5.1
Bumps [kotlinx-coroutines-core-jvm](https://github.com/Kotlin/kotlinx.coroutines) from 1.4.2 to 1.5.1.
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.4.2...1.5.1)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 17:05:47 +02:00
dependabot[bot]
c2479278ba Bump ktorVersion from 1.6.1 to 1.6.2
Bumps `ktorVersion` from 1.6.1 to 1.6.2.

Updates `ktor-client-mock` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-jackson` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-client-android` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-client-core` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-client-jackson` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-client-json` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-server-netty` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-server-core` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-html-builder` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

Updates `ktor-server-tests` from 1.6.1 to 1.6.2
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.1...1.6.2)

---
updated-dependencies:
- dependency-name: io.ktor:ktor-client-mock
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-jackson
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-android
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-jackson
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-json
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-server-netty
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-server-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-html-builder
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-server-tests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 14:00:24 +02:00
dependabot[bot]
499a403a06 Bump kotlin-stdlib from 1.5.20 to 1.5.21
Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.5.20 to 1.5.21.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.20...v1.5.21)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 14:00:17 +02:00
dependabot[bot]
af5d622339 Bump opencsv from 5.4 to 5.5.1
Bumps opencsv from 5.4 to 5.5.1.

---
updated-dependencies:
- dependency-name: com.opencsv:opencsv
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 10:33:09 +02:00
dependabot[bot]
5eeb54bc47 Bump kxCoroutinesVersion from 1.4.2 to 1.5.1
Bumps `kxCoroutinesVersion` from 1.4.2 to 1.5.1.

Updates `kotlinx-coroutines-android` from 1.4.2 to 1.5.1
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.4.2...1.5.1)

Updates `kotlinx-coroutines-core` from 1.4.2 to 1.5.1
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.4.2...1.5.1)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-android
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 10:32:46 +02:00
dependabot[bot]
e09e899aad Bump appcompat from 1.3.0 to 1.3.1
Bumps appcompat from 1.3.0 to 1.3.1.

---
updated-dependencies:
- dependency-name: androidx.appcompat:appcompat
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-01 10:32:19 +02:00
37f03aca37 Merge branch 'hotfix/2.0.3' into dev 2021-07-31 12:49:01 -05:00
Quentin Hibon
0ab55f6f5a Remove useless nullability 2021-07-30 21:12:33 +02:00
dependabot[bot]
43921721d4 Bump espressoVersion from 3.3.0 to 3.4.0
Bumps `espressoVersion` from 3.3.0 to 3.4.0.

Updates `espresso-contrib` from 3.3.0 to 3.4.0

Updates `espresso-core` from 3.3.0 to 3.4.0

---
updated-dependencies:
- dependency-name: androidx.test.espresso:espresso-contrib
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: androidx.test.espresso:espresso-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-03 23:37:26 +02:00
dependabot[bot]
33c88cded3 Bump rules from 1.3.0 to 1.4.0
Bumps rules from 1.3.0 to 1.4.0.

---
updated-dependencies:
- dependency-name: androidx.test:rules
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-03 18:48:12 +02:00
dependabot[bot]
aecce891ea Bump sqlite-jdbc from 3.36.0 to 3.36.0.1
Bumps [sqlite-jdbc](https://github.com/xerial/sqlite-jdbc) from 3.36.0 to 3.36.0.1.
- [Release notes](https://github.com/xerial/sqlite-jdbc/releases)
- [Changelog](https://github.com/xerial/sqlite-jdbc/blob/master/CHANGELOG)
- [Commits](https://github.com/xerial/sqlite-jdbc/compare/3.36.0...3.36.0.1)

---
updated-dependencies:
- dependency-name: org.xerial:sqlite-jdbc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-03 18:47:59 +02:00
dependabot[bot]
2ea98a7756 Bump ktorVersion from 1.6.0 to 1.6.1
Bumps `ktorVersion` from 1.6.0 to 1.6.1.

Updates `ktor-client-mock` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-jackson` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-client-android` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-client-core` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-client-jackson` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-client-json` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-server-netty` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-server-core` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-html-builder` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

Updates `ktor-server-tests` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.6.0...1.6.1)

---
updated-dependencies:
- dependency-name: io.ktor:ktor-client-mock
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-jackson
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-android
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-jackson
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-client-json
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-server-netty
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-server-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-html-builder
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: io.ktor:ktor-server-tests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-03 18:47:52 +02:00
dependabot[bot]
e667872d83 Bump junit from 1.1.2 to 1.1.3
Bumps junit from 1.1.2 to 1.1.3.

---
updated-dependencies:
- dependency-name: androidx.test.ext:junit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-03 18:47:47 +02:00
Quentin Hibon
3602a614c4 dependabot: do monthly checks rather than daily 2021-07-01 08:02:40 +02:00
dependabot[bot]
d8c5f4d93c Bump sqlite-jdbc from 3.34.0 to 3.36.0
Bumps [sqlite-jdbc](https://github.com/xerial/sqlite-jdbc) from 3.34.0 to 3.36.0.
- [Release notes](https://github.com/xerial/sqlite-jdbc/releases)
- [Changelog](https://github.com/xerial/sqlite-jdbc/blob/master/CHANGELOG)
- [Commits](https://github.com/xerial/sqlite-jdbc/compare/3.34.0...3.36.0)

---
updated-dependencies:
- dependency-name: org.xerial:sqlite-jdbc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-28 08:23:03 +02:00
dependabot[bot]
c9f4df9dae Bump kotlin-stdlib-jdk8 from 1.5.10 to 1.5.20
Bumps [kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.5.10 to 1.5.20.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.20/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.10...v1.5.20)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib-jdk8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-25 08:26:27 +02:00
dependabot[bot]
feb384bca6 Bump kotlin-stdlib from 1.5.10 to 1.5.20
Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.5.10 to 1.5.20.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/v1.5.20/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.10...v1.5.20)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlin:kotlin-stdlib
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-25 08:26:21 +02:00
dependabot[bot]
71e9160460 Bump daggerVersion from 2.36 to 2.37
Bumps `daggerVersion` from 2.36 to 2.37.

Updates `dagger` from 2.36 to 2.37
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.36...dagger-2.37)

Updates `dagger-compiler` from 2.36 to 2.37
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.36...dagger-2.37)

---
updated-dependencies:
- dependency-name: com.google.dagger:dagger
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.google.dagger:dagger-compiler
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-11 10:37:47 +02:00
Quentin Hibon
64966d3c86 Bumps org.jlleitschuh.gradle.ktlint from 10.0.0 to 10.1.0 2021-06-09 12:06:35 +02:00
dependabot[bot]
4787df4074 Bump simpleclient_hotspot from 0.10.0 to 0.11.0
Bumps [simpleclient_hotspot](https://github.com/prometheus/client_java) from 0.10.0 to 0.11.0.
- [Release notes](https://github.com/prometheus/client_java/releases)
- [Commits](https://github.com/prometheus/client_java/compare/parent-0.10.0...parent-0.11.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-09 11:57:42 +02:00
dependabot[bot]
5908692a5c Bump ktorVersion from 1.5.4 to 1.6.0 (#943)
Bumps `ktorVersion` from 1.5.4 to 1.6.0.

Updates `ktor-client-mock` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-jackson` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-client-android` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-client-core` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-client-jackson` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-client-json` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-server-netty` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-server-core` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-html-builder` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Updates `ktor-server-tests` from 1.5.4 to 1.6.0
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.4...1.6.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-05 10:08:34 -05:00
dependabot[bot]
693dce8719 Bump simpleclient_httpserver from 0.10.0 to 0.11.0 (#942)
Bumps [simpleclient_httpserver](https://github.com/prometheus/client_java) from 0.10.0 to 0.11.0.
- [Release notes](https://github.com/prometheus/client_java/releases)
- [Commits](https://github.com/prometheus/client_java/compare/parent-0.10.0...parent-0.11.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-05 10:08:09 -05:00
b232827dfd Update bug_report.md 2021-05-31 13:14:30 -05:00
dependabot[bot]
02f9f411ce Bump simpleclient from 0.10.0 to 0.11.0 (#941)
Bumps [simpleclient](https://github.com/prometheus/client_java) from 0.10.0 to 0.11.0.
- [Release notes](https://github.com/prometheus/client_java/releases)
- [Commits](https://github.com/prometheus/client_java/compare/parent-0.10.0...parent-0.11.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-31 13:12:25 -05:00
bbf9da44e1 Update bug_report.md 2021-05-29 08:07:17 -05:00
dependabot[bot]
ee896fb4f9 Bump kotlin-stdlib from 1.5.0 to 1.5.10 (#931)
Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.5.0 to 1.5.10.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.0...v1.5.10)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-26 20:40:31 -05:00
dependabot[bot]
4d7d8b6206 Bump kotlin-stdlib-jdk8 from 1.5.0 to 1.5.10 (#932)
Bumps [kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.5.0 to 1.5.10.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/compare/v1.5.0...v1.5.10)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-26 20:40:18 -05:00
dependabot[bot]
55b841a8b4 Bump daggerVersion from 2.35.1 to 2.36 (#933)
Bumps `daggerVersion` from 2.35.1 to 2.36.

Updates `dagger` from 2.35.1 to 2.36
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.35.1...dagger-2.36)

Updates `dagger-compiler` from 2.35.1 to 2.36
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.35.1...dagger-2.36)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-26 06:47:10 -05:00
7fac86b617 Update bug_report.md 2021-05-23 19:04:32 -05:00
dependabot[bot]
c31d42be2d Bump com.github.johnrengelman.shadow from 6.1.0 to 7.0.0
Bumps com.github.johnrengelman.shadow from 6.1.0 to 7.0.0.

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-23 18:45:05 -05:00
31c09b9c0b Upgrade to Gradle 7.0 and Kotlin 1.5.0 2021-05-23 18:33:57 -05:00
dependabot[bot]
db91dce57f Bump appcompat from 1.2.0 to 1.3.0 (#912)
Bumps appcompat from 1.2.0 to 1.3.0.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-23 18:01:18 -05:00
12c76245e6 Merge branch 'master' into dev 2021-05-23 17:47:14 -05:00
7f1a1add8c Revert "Temporarily remove device sync"
This reverts commit da018fc64d.
2021-05-09 18:22:15 -05:00
59a4d7552c Update translations; reorganize play/listings 2021-05-09 18:03:04 -05:00
9d7840bdd1 Merge branch 'master' into dev 2021-05-09 17:24:50 -05:00
Quentin Hibon
32db4e363b Add missing dependency to github workflow (#894) 2021-05-02 18:41:34 -05:00
dependabot[bot]
004bb8d71c Bump daggerVersion from 2.34.1 to 2.35.1
Bumps `daggerVersion` from 2.34.1 to 2.35.1.

Updates `dagger` from 2.34.1 to 2.35.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.34.1...dagger-2.35.1)

Updates `dagger-compiler` from 2.34.1 to 2.35.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.34.1...dagger-2.35.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-01 16:07:49 +02:00
dependabot[bot]
21a1e88c47 Bump ktorVersion from 1.5.3 to 1.5.4
Bumps `ktorVersion` from 1.5.3 to 1.5.4.

Updates `ktor-client-mock` from 1.5.3 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.3...1.5.4)

Updates `ktor-jackson` from 1.5.3 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.3...1.5.4)

Updates `ktor-client-android` from 1.5.3 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.3...1.5.4)

Updates `ktor-client-core` from 1.5.3 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.3...1.5.4)

Updates `ktor-client-jackson` from 1.5.3 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.3...1.5.4)

Updates `ktor-client-json` from 1.5.3 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.3...1.5.4)

Updates `ktor-server-netty` from 1.5.2 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.2...1.5.4)

Updates `ktor-server-core` from 1.5.2 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.2...1.5.4)

Updates `ktor-html-builder` from 1.5.2 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.2...1.5.4)

Updates `ktor-server-tests` from 1.5.2 to 1.5.4
- [Release notes](https://github.com/ktorio/ktor/releases)
- [Changelog](https://github.com/ktorio/ktor/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ktorio/ktor/compare/1.5.2...1.5.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-01 00:38:37 +02:00
dependabot[bot]
86fb718896 Bump appintro from 3.4.0 to 4.1.0
Bumps [appintro](https://github.com/PaoloRotolo/AppIntro) from 3.4.0 to 4.1.0.
- [Release notes](https://github.com/PaoloRotolo/AppIntro/releases)
- [Changelog](https://github.com/AppIntro/AppIntro/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PaoloRotolo/AppIntro/commits/v4.1.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-01 00:38:10 +02:00
dependabot[bot]
a4e9b2f874 Bump kotlin-stdlib-jdk8 from 1.4.32 to 1.5.0
Bumps [kotlin-stdlib-jdk8](https://github.com/JetBrains/kotlin) from 1.4.32 to 1.5.0.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-30 17:09:04 +02:00
dependabot[bot]
ac924470b8 Bump kotlin-stdlib from 1.4.32 to 1.5.0
Bumps [kotlin-stdlib](https://github.com/JetBrains/kotlin) from 1.4.32 to 1.5.0.
- [Release notes](https://github.com/JetBrains/kotlin/releases)
- [Changelog](https://github.com/JetBrains/kotlin/blob/master/ChangeLog.md)
- [Commits](https://github.com/JetBrains/kotlin/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-30 17:08:54 +02:00
147 changed files with 1693 additions and 617 deletions

View File

@@ -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.

View File

@@ -3,4 +3,4 @@ updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
interval: "monthly"

View File

@@ -55,6 +55,11 @@ jobs:
name: uhabits-android
path: uhabits-android/build/outputs/
- name: Install flock
run: |
brew install util-linux
echo "/usr/local/opt/util-linux/bin" >> $GITHUB_PATH
- name: Run Android Tests
run: ./build.sh android-tests ${{ matrix.api }}

View File

@@ -18,7 +18,7 @@ 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://f-droid.org/app/org.isoron.uhabits"><img alt="Get it on F-Droid" src="https://i.imgur.com/baSPE7X.png" height="75px"/></a>
</p>
## Screenshots
@@ -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

View File

@@ -1,11 +1,11 @@
plugins {
val kotlinVersion = "1.4.21"
id("com.android.application") version ("4.1.0") apply (false)
val kotlinVersion = "1.5.0"
id("com.android.application") version ("4.2.0") 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 "10.1.0"
}
apply {

Binary file not shown.

View File

@@ -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-7.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip

2
gradlew vendored
View File

@@ -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
View File

@@ -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

View File

@@ -20,7 +20,7 @@
*/
plugins {
id("com.github.triplet.play") version "3.2.0"
id("com.github.triplet.play") version "3.5.0"
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.kapt")
@@ -88,11 +88,11 @@ 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.38.1"
val kotlinVersion = "1.5.21"
val kxCoroutinesVersion = "1.5.1"
val ktorVersion = "1.6.2"
val espressoVersion = "3.4.0"
androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion")
androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion")
@@ -101,13 +101,13 @@ dependencies {
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.test.ext:junit:1.1.3")
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.2.0")
androidTestImplementation("androidx.test:rules:1.3.0")
androidTestImplementation("androidx.test:rules:1.4.0")
androidTestImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.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")
implementation("com.github.paolorotolo:appintro:4.1.0")
implementation("com.google.code.findbugs:jsr305:3.0.2")
implementation("com.google.dagger:dagger:$daggerVersion")
implementation("com.google.guava:guava:30.1.1-android")
@@ -118,11 +118,12 @@ 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.3.1")
implementation("androidx.legacy:legacy-preference-v14:1.0.0")
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("com.google.android.material:material:1.3.0")
implementation("com.opencsv:opencsv:5.4")
implementation("com.google.android.material:material:1.4.0")
implementation("com.google.zxing:core:3.4.1")
implementation("com.opencsv:opencsv:5.5.1")
implementation(project(":uhabits-core"))
kapt("com.google.dagger:dagger-compiler:$daggerVersion")
kaptAndroidTest("com.google.dagger:dagger-compiler:$daggerVersion")

View File

@@ -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"
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* 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/>.
*/
package org.isoron.uhabits.sync
import androidx.test.filters.MediumTest
import com.fasterxml.jackson.databind.ObjectMapper
import io.ktor.client.HttpClient
import io.ktor.client.engine.mock.MockEngine
import io.ktor.client.engine.mock.MockRequestHandleScope
import io.ktor.client.engine.mock.respond
import io.ktor.client.engine.mock.respondError
import io.ktor.client.engine.mock.respondOk
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.request.HttpRequestData
import io.ktor.client.request.HttpResponseData
import io.ktor.http.HttpStatusCode
import io.ktor.http.fullPath
import io.ktor.http.headersOf
import kotlinx.coroutines.runBlocking
import org.isoron.uhabits.BaseAndroidTest
import org.isoron.uhabits.core.sync.AbstractSyncServer
import org.isoron.uhabits.core.sync.GetDataVersionResponse
import org.isoron.uhabits.core.sync.KeyNotFoundException
import org.isoron.uhabits.core.sync.RegisterReponse
import org.isoron.uhabits.core.sync.ServiceUnavailable
import org.isoron.uhabits.core.sync.SyncData
import org.junit.Test
@MediumTest
class RemoteSyncServerTest : BaseAndroidTest() {
private val mapper = ObjectMapper()
val data = SyncData(1, "Hello world")
@Test
fun when_register_succeeds_should_return_key() = runBlocking {
val server = server("/register") {
respondWithJson(RegisterReponse("ABCDEF"))
}
assertEquals("ABCDEF", server.register())
}
@Test(expected = ServiceUnavailable::class)
fun when_register_fails_should_raise_correct_exception() = runBlocking {
val server = server("/register") {
respondError(HttpStatusCode.ServiceUnavailable)
}
server.register()
return@runBlocking
}
@Test
fun when_get_data_version_succeeds_should_return_version() = runBlocking {
server("/db/ABC/version") {
respondWithJson(GetDataVersionResponse(5))
}.apply {
assertEquals(5, getDataVersion("ABC"))
}
return@runBlocking
}
@Test(expected = ServiceUnavailable::class)
fun when_get_data_version_with_server_error_should_raise_exception() = runBlocking {
server("/db/ABC/version") {
respondError(HttpStatusCode.InternalServerError)
}.apply {
getDataVersion("ABC")
}
return@runBlocking
}
@Test(expected = KeyNotFoundException::class)
fun when_get_data_version_with_invalid_key_should_raise_exception() = runBlocking {
server("/db/ABC/version") {
respondError(HttpStatusCode.NotFound)
}.apply {
getDataVersion("ABC")
}
return@runBlocking
}
@Test
fun when_get_data_succeeds_should_return_data() = runBlocking {
server("/db/ABC") {
respondWithJson(data)
}.apply {
assertEquals(data, getData("ABC"))
}
return@runBlocking
}
@Test(expected = KeyNotFoundException::class)
fun when_get_data_with_invalid_key_should_raise_exception() = runBlocking {
server("/db/ABC") {
respondError(HttpStatusCode.NotFound)
}.apply {
getData("ABC")
}
return@runBlocking
}
@Test
fun when_put_succeeds_should_not_raise_exceptions() = runBlocking {
server("/db/ABC") {
respondOk()
}.apply {
put("ABC", data)
}
return@runBlocking
}
private fun server(
expectedPath: String,
action: MockRequestHandleScope.(HttpRequestData) -> HttpResponseData
): AbstractSyncServer {
return RemoteSyncServer(
httpClient = HttpClient(MockEngine) {
install(JsonFeature)
engine {
addHandler { request ->
when (request.url.fullPath) {
expectedPath -> action(request)
else -> error("unexpected call: ${request.url.fullPath}")
}
}
}
},
preferences = prefs
)
}
private fun MockRequestHandleScope.respondWithJson(content: Any) =
respond(
mapper.writeValueAsBytes(content),
headers = headersOf("Content-Type" to listOf("application/json"))
)
}

View File

@@ -22,6 +22,8 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".HabitsApplication"
@@ -40,6 +42,14 @@
android:value=".activities.habits.list.ListHabitsActivity" />
</activity>
<activity
android:name=".activities.sync.SyncActivity"
android:exported="true">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.settings.SettingsActivity" />
</activity>
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw" />
@@ -49,6 +59,16 @@
android:exported="true"
android:label="@string/main_activity_title"
android:launchMode="singleTop">
<tools:validation testUrl="https://loophabits.org/sync/123" />
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="loophabits.org"
android:pathPrefix="/sync" />
</intent-filter>
</activity>
<activity-alias

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* 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/>.
*/
package org.isoron.uhabits.activities.common.dialogs
import android.content.Context
import android.content.DialogInterface
import androidx.appcompat.app.AlertDialog
import org.isoron.uhabits.R
import org.isoron.uhabits.core.ui.callbacks.OnConfirmedCallback
import org.isoron.uhabits.inject.ActivityContext
class ConfirmSyncKeyDialog(
@ActivityContext context: Context,
callback: OnConfirmedCallback
) : AlertDialog(context) {
init {
setTitle(R.string.device_sync)
val res = context.resources
setMessage(res.getString(R.string.sync_confirm))
setButton(
BUTTON_POSITIVE,
res.getString(R.string.yes)
) { dialog: DialogInterface?, which: Int -> callback.onConfirmed() }
setButton(
BUTTON_NEGATIVE,
res.getString(R.string.no)
) { dialog: DialogInterface?, which: Int -> }
}
}

View File

@@ -29,10 +29,10 @@ class TaskProgressBar(
context: Context,
private val runner: TaskRunner
) : ProgressBar(
context,
null,
android.R.attr.progressBarStyleHorizontal
),
context,
null,
android.R.attr.progressBarStyleHorizontal
),
TaskRunner.Listener {
init {

View File

@@ -52,6 +52,8 @@ import org.isoron.uhabits.core.commands.CreateHabitCommand
import org.isoron.uhabits.core.commands.EditHabitCommand
import org.isoron.uhabits.core.models.Frequency
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitType
import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Reminder
import org.isoron.uhabits.core.models.WeekdayList
@@ -77,7 +79,7 @@ class EditHabitActivity : AppCompatActivity() {
private lateinit var commandRunner: CommandRunner
var habitId = -1L
var habitType = -1
lateinit var habitType: HabitType
var unit = ""
var color = PaletteColor(11)
var androidColor = 0
@@ -116,12 +118,12 @@ class EditHabitActivity : AppCompatActivity() {
binding.unitInput.setText(habit.unit)
binding.targetInput.setText(habit.targetValue.toString())
} else {
habitType = intent.getIntExtra("habitType", Habit.YES_NO_HABIT)
habitType = HabitType.fromInt(intent.getIntExtra("habitType", HabitType.YES_NO.value))
}
if (state != null) {
habitId = state.getLong("habitId")
habitType = state.getInt("habitType")
habitType = HabitType.fromInt(state.getInt("habitType"))
color = PaletteColor(state.getInt("paletteColor"))
freqNum = state.getInt("freqNum")
freqDen = state.getInt("freqDen")
@@ -132,13 +134,16 @@ class EditHabitActivity : AppCompatActivity() {
updateColors()
if (habitType == Habit.YES_NO_HABIT) {
binding.unitOuterBox.visibility = View.GONE
binding.targetOuterBox.visibility = View.GONE
} else {
binding.nameInput.hint = getString(R.string.measurable_short_example)
binding.questionInput.hint = getString(R.string.measurable_question_example)
binding.frequencyOuterBox.visibility = View.GONE
when (habitType) {
HabitType.YES_NO -> {
binding.unitOuterBox.visibility = View.GONE
binding.targetOuterBox.visibility = View.GONE
}
HabitType.NUMERICAL -> {
binding.nameInput.hint = getString(R.string.measurable_short_example)
binding.questionInput.hint = getString(R.string.measurable_question_example)
binding.frequencyOuterBox.visibility = View.GONE
}
}
setSupportActionBar(binding.toolbar)
@@ -255,9 +260,9 @@ class EditHabitActivity : AppCompatActivity() {
}
habit.frequency = Frequency(freqNum, freqDen)
if (habitType == Habit.NUMBER_HABIT) {
if (habitType == HabitType.NUMERICAL) {
habit.targetValue = targetInput.text.toString().toDouble()
habit.targetType = Habit.AT_LEAST
habit.targetType = NumericalHabitType.AT_LEAST
habit.unit = unitInput.text.trim().toString()
}
habit.type = habitType
@@ -285,7 +290,7 @@ class EditHabitActivity : AppCompatActivity() {
nameInput.error = getFormattedValidationError(R.string.validation_cannot_be_blank)
isValid = false
}
if (habitType == Habit.NUMBER_HABIT) {
if (habitType == HabitType.NUMERICAL) {
if (targetInput.text.isEmpty()) {
targetInput.error = getString(R.string.validation_cannot_be_blank)
isValid = false
@@ -338,7 +343,7 @@ class EditHabitActivity : AppCompatActivity() {
super.onSaveInstanceState(state)
with(state) {
putLong("habitId", habitId)
putInt("habitType", habitType)
putInt("habitType", habitType.value)
putInt("paletteColor", color.paletteIndex)
putInt("androidColor", androidColor)
putInt("freqNum", freqNum)

View File

@@ -25,7 +25,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatDialogFragment
import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitType
import org.isoron.uhabits.databinding.SelectHabitTypeBinding
import org.isoron.uhabits.intents.IntentFactory
@@ -40,13 +40,13 @@ class HabitTypeDialog : AppCompatDialogFragment() {
val binding = SelectHabitTypeBinding.inflate(inflater, container, false)
binding.buttonYesNo.setOnClickListener {
val intent = IntentFactory().startEditActivity(activity!!, Habit.YES_NO_HABIT)
val intent = IntentFactory().startEditActivity(activity!!, HabitType.YES_NO.value)
startActivity(intent)
dismiss()
}
binding.buttonMeasurable.setOnClickListener {
val intent = IntentFactory().startEditActivity(activity!!, Habit.NUMBER_HABIT)
val intent = IntentFactory().startEditActivity(activity!!, HabitType.NUMERICAL.value)
startActivity(intent)
dismiss()
}

View File

@@ -26,10 +26,12 @@ import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.isoron.uhabits.BaseExceptionHandler
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.sync.SyncManager
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.ui.ThemeSwitcher.Companion.THEME_DARK
import org.isoron.uhabits.core.utils.MidnightTimer
@@ -38,7 +40,7 @@ import org.isoron.uhabits.inject.ActivityContextModule
import org.isoron.uhabits.inject.DaggerHabitsActivityComponent
import org.isoron.uhabits.utils.restartWithFade
class ListHabitsActivity : AppCompatActivity() {
class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
var pureBlack: Boolean = false
lateinit var taskRunner: TaskRunner
@@ -47,10 +49,15 @@ class ListHabitsActivity : AppCompatActivity() {
lateinit var screen: ListHabitsScreen
lateinit var prefs: Preferences
lateinit var midnightTimer: MidnightTimer
lateinit var syncManager: SyncManager
private val scope = CoroutineScope(Dispatchers.Main)
private lateinit var menu: ListHabitsMenu
override fun onQuestionMarksChanged() {
invalidateOptionsMenu()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -63,6 +70,8 @@ class ListHabitsActivity : AppCompatActivity() {
component.themeSwitcher.apply()
prefs = appComponent.preferences
prefs.addListener(this)
syncManager = appComponent.syncManager
pureBlack = prefs.isPureBlackEnabled
midnightTimer = appComponent.midnightTimer
rootView = component.listHabitsRootView
@@ -79,6 +88,9 @@ class ListHabitsActivity : AppCompatActivity() {
midnightTimer.onPause()
screen.onDettached()
adapter.cancelRefresh()
scope.launch {
syncManager.onPause()
}
super.onPause()
}
@@ -87,6 +99,9 @@ class ListHabitsActivity : AppCompatActivity() {
screen.onAttached()
rootView.postInvalidate()
midnightTimer.onResume()
scope.launch {
syncManager.onResume()
}
taskRunner.run {
AutoBackup(this@ListHabitsActivity).run()
}

View File

@@ -52,6 +52,11 @@ class ListHabitsMenu @Inject constructor(
nightModeItem.isChecked = themeSwitcher.isNightMode
hideArchivedItem.isChecked = !preferences.showArchived
hideCompletedItem.isChecked = !preferences.showCompleted
if (preferences.areQuestionMarksEnabled || preferences.isSkipEnabled) {
hideCompletedItem.title = activity.resources.getString(R.string.hide_entered)
} else {
hideCompletedItem.title = activity.resources.getString(R.string.hide_completed)
}
updateArrows(menu)
}

View File

@@ -22,11 +22,13 @@ package org.isoron.uhabits.activities.habits.list
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import dagger.Lazy
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.common.dialogs.ColorPickerDialogFactory
import org.isoron.uhabits.activities.common.dialogs.ConfirmDeleteDialog
import org.isoron.uhabits.activities.common.dialogs.ConfirmSyncKeyDialog
import org.isoron.uhabits.activities.common.dialogs.NumberPickerFactory
import org.isoron.uhabits.activities.habits.edit.HabitTypeDialog
import org.isoron.uhabits.activities.habits.list.views.HabitCardListAdapter
@@ -51,6 +53,8 @@ import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.FILE_NOT_RECOGNIZED
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.IMPORT_FAILED
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.IMPORT_SUCCESSFUL
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.SYNC_ENABLED
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.SYNC_KEY_ALREADY_INSTALLED
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsMenuBehavior
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsSelectionMenuBehavior
import org.isoron.uhabits.inject.ActivityContext
@@ -99,6 +103,14 @@ class ListHabitsScreen
fun onAttached() {
commandRunner.addListener(this)
if (activity.intent.action == "android.intent.action.VIEW") {
val uri = activity.intent.data!!.toString()
val parts = uri.replace(Regex("^.*sync/"), "").split("#")
val syncKey = parts[0]
val encKey = parts[1]
Log.i("ListHabitsScreen", "sync: $syncKey enc: $encKey")
behavior.get().onSyncKeyOffer(syncKey, encKey)
}
}
fun onDettached() {
@@ -196,6 +208,8 @@ class ListHabitsScreen
DATABASE_REPAIRED -> R.string.database_repaired
COULD_NOT_GENERATE_BUG_REPORT -> R.string.bug_report_failed
FILE_NOT_RECOGNIZED -> R.string.file_not_recognized
SYNC_ENABLED -> R.string.sync_enabled
SYNC_KEY_ALREADY_INSTALLED -> R.string.sync_key_already_installed
}
)
)
@@ -230,6 +244,10 @@ class ListHabitsScreen
numberPickerFactory.create(value, unit, callback).show()
}
override fun showConfirmInstallSyncKey(callback: OnConfirmedCallback) {
ConfirmSyncKeyDialog(activity, callback).show()
}
private fun getExecuteString(command: Command): String? {
when (command) {
is ArchiveHabitsCommand -> {

View File

@@ -131,7 +131,7 @@ class CheckmarkButtonView(
paint.color = when (value) {
YES_MANUAL, YES_AUTO, SKIP -> color
NO -> {
if (preferences.areQuestionMarksEnabled()) mediumContrastColor
if (preferences.areQuestionMarksEnabled) mediumContrastColor
else lowContrastColor
}
else -> lowContrastColor
@@ -140,7 +140,7 @@ class CheckmarkButtonView(
SKIP -> R.string.fa_skipped
NO -> R.string.fa_times
UNKNOWN -> {
if (preferences.areQuestionMarksEnabled()) R.string.fa_question
if (preferences.areQuestionMarksEnabled) R.string.fa_question
else R.string.fa_times
}
else -> R.string.fa_check

View File

@@ -169,7 +169,7 @@ class NumberButtonView(
typeface = BOLD_TYPEFACE
textSize = dim(R.dimen.smallTextSize)
}
preferences.areQuestionMarksEnabled() -> {
preferences.areQuestionMarksEnabled -> {
label = resources.getString(R.string.fa_question)
typeface = getFontAwesome()
textSize = dim(R.dimen.smallerTextSize)

View File

@@ -19,6 +19,7 @@
package org.isoron.uhabits.activities.settings
import android.app.backup.BackupManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
@@ -27,6 +28,7 @@ import android.os.Build.VERSION
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import androidx.preference.CheckBoxPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
@@ -41,6 +43,7 @@ import org.isoron.uhabits.activities.habits.list.RESULT_REPAIR_DB
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.ui.NotificationTray
import org.isoron.uhabits.core.utils.DateUtils.Companion.getLongWeekdayNames
import org.isoron.uhabits.intents.IntentFactory
import org.isoron.uhabits.notifications.AndroidNotificationTray.Companion.createAndroidNotificationChannel
import org.isoron.uhabits.notifications.RingtoneManager
import org.isoron.uhabits.widgets.WidgetUpdater
@@ -97,6 +100,13 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis
intent.putExtra(Settings.EXTRA_CHANNEL_ID, NotificationTray.REMINDERS_CHANNEL_ID)
startActivity(intent)
return true
} else if (key == "pref_sync_enabled_dummy") {
if (prefs.isSyncEnabled) {
prefs.disableSync()
} else {
val context: Context? = activity
context!!.startActivity(IntentFactory().startSyncActivity(context))
}
}
return super.onPreferenceTreeClick(preference)
}
@@ -111,6 +121,7 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis
devCategory.isVisible = false
}
updateWeekdayPreference()
updateSyncPreferences()
if (VERSION.SDK_INT < Build.VERSION_CODES.O)
findPreference("reminderCustomize").isVisible = false
@@ -119,6 +130,12 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis
}
}
private fun updateSyncPreferences() {
findPreference("pref_sync_display").isVisible = prefs.isSyncEnabled
(findPreference("pref_sync_enabled_dummy") as CheckBoxPreference).isChecked =
prefs.isSyncEnabled
}
private fun updateWeekdayPreference() {
val weekdayPref = findPreference("pref_first_weekday") as ListPreference
val currentFirstWeekday = prefs.firstWeekday.daysSinceSunday + 1
@@ -140,6 +157,7 @@ class SettingsFragment : PreferenceFragmentCompat(), OnSharedPreferenceChangeLis
}
BackupManager.dataChanged("org.isoron.uhabits")
updateWeekdayPreference()
updateSyncPreferences()
}
private fun setResultOnPreferenceClick(key: String, result: Int) {

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* 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/>.
*/
package org.isoron.uhabits.activities.sync
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle
import android.text.Html
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.google.zxing.BarcodeFormat
import com.google.zxing.qrcode.QRCodeWriter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.invoke
import kotlinx.coroutines.launch
import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.R
import org.isoron.uhabits.activities.AndroidThemeSwitcher
import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.ui.screens.sync.SyncBehavior
import org.isoron.uhabits.databinding.ActivitySyncBinding
import org.isoron.uhabits.sync.RemoteSyncServer
import org.isoron.uhabits.utils.InterfaceUtils.getFontAwesome
import org.isoron.uhabits.utils.setupToolbar
import org.isoron.uhabits.utils.showMessage
class SyncActivity : AppCompatActivity(), SyncBehavior.Screen {
private lateinit var binding: ActivitySyncBinding
private lateinit var behavior: SyncBehavior
private val scope = CoroutineScope(Dispatchers.Main)
override fun onCreate(savedInstance: Bundle?) {
super.onCreate(savedInstance)
val component = (application as HabitsApplication).component
val preferences = component.preferences
val server = RemoteSyncServer(preferences = preferences)
val themeSwitcher = AndroidThemeSwitcher(this, component.preferences)
themeSwitcher.apply()
behavior = SyncBehavior(this, preferences, server, component.logging)
binding = ActivitySyncBinding.inflate(layoutInflater)
binding.errorIcon.typeface = getFontAwesome(this)
binding.root.setupToolbar(
toolbar = binding.toolbar,
color = PaletteColor(11),
title = resources.getString(R.string.device_sync),
theme = themeSwitcher.currentTheme,
)
binding.syncLink.setOnClickListener { copyToClipboard() }
binding.instructions.text = Html.fromHtml(resources.getString(R.string.sync_instructions))
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
scope.launch {
behavior.onResume()
}
}
private fun copyToClipboard() {
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("Loop Sync Link", binding.syncLink.text))
showMessage(resources.getString(R.string.copied_to_the_clipboard))
}
suspend fun generateQR(msg: String): Bitmap = Dispatchers.IO {
val writer = QRCodeWriter()
val matrix = writer.encode(msg, BarcodeFormat.QR_CODE, 1024, 1024)
val height = matrix.height
val width = matrix.width
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
val bgColor = Color.WHITE
val fgColor = Color.BLACK
for (x in 0 until width) {
for (y in 0 until height) {
val color = if (matrix.get(x, y)) fgColor else bgColor
bitmap.setPixel(x, y, color)
}
}
return@IO bitmap
}
suspend fun showQR(msg: String) {
binding.progress.visibility = View.GONE
binding.qrCode.visibility = View.VISIBLE
binding.qrCode.setImageBitmap(generateQR(msg))
}
override suspend fun showLoadingScreen() {
binding.qrCode.visibility = View.GONE
binding.progress.visibility = View.VISIBLE
binding.errorPanel.visibility = View.GONE
}
override suspend fun showErrorScreen() {
binding.qrCode.visibility = View.GONE
binding.progress.visibility = View.GONE
binding.errorPanel.visibility = View.VISIBLE
}
override suspend fun showLink(link: String) {
binding.qrCode.visibility = View.GONE
binding.progress.visibility = View.VISIBLE
binding.errorPanel.visibility = View.GONE
binding.syncLink.text = link
showQR(link)
}
}

View File

@@ -29,6 +29,7 @@ import org.isoron.uhabits.core.models.ModelFactory
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.preferences.WidgetPreferences
import org.isoron.uhabits.core.reminders.ReminderScheduler
import org.isoron.uhabits.core.sync.SyncManager
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.ui.NotificationTray
import org.isoron.uhabits.core.ui.screens.habits.list.HabitCardListCache
@@ -63,4 +64,5 @@ interface HabitsApplicationComponent {
val taskRunner: TaskRunner
val widgetPreferences: WidgetPreferences
val widgetUpdater: WidgetUpdater
val syncManager: SyncManager
}

View File

@@ -19,6 +19,7 @@
package org.isoron.uhabits.inject
import android.content.Context
import dagger.Module
import dagger.Provides
import org.isoron.uhabits.core.AppScope
@@ -33,6 +34,8 @@ import org.isoron.uhabits.core.models.sqlite.SQLiteHabitList
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.preferences.WidgetPreferences
import org.isoron.uhabits.core.reminders.ReminderScheduler
import org.isoron.uhabits.core.sync.AbstractSyncServer
import org.isoron.uhabits.core.sync.NetworkManager
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.ui.NotificationTray
import org.isoron.uhabits.database.AndroidDatabase
@@ -41,6 +44,8 @@ import org.isoron.uhabits.intents.IntentScheduler
import org.isoron.uhabits.io.AndroidLogging
import org.isoron.uhabits.notifications.AndroidNotificationTray
import org.isoron.uhabits.preferences.SharedPreferencesStorage
import org.isoron.uhabits.sync.AndroidNetworkManager
import org.isoron.uhabits.sync.RemoteSyncServer
import org.isoron.uhabits.utils.DatabaseUtils
import java.io.File
@@ -109,6 +114,18 @@ class HabitsModule(dbFile: File) {
return AndroidLogging()
}
@Provides
@AppScope
fun getNetworkManager(@AppContext context: Context): NetworkManager {
return AndroidNetworkManager(context)
}
@Provides
@AppScope
fun getSyncServer(preferences: Preferences): AbstractSyncServer {
return RemoteSyncServer(preferences)
}
@Provides
@AppScope
fun getDatabase(): Database {

View File

@@ -28,6 +28,7 @@ import org.isoron.uhabits.activities.habits.edit.EditHabitActivity
import org.isoron.uhabits.activities.habits.show.ShowHabitActivity
import org.isoron.uhabits.activities.intro.IntroActivity
import org.isoron.uhabits.activities.settings.SettingsActivity
import org.isoron.uhabits.activities.sync.SyncActivity
import org.isoron.uhabits.core.models.Habit
import javax.inject.Inject
@@ -100,4 +101,8 @@ class IntentFactory
intent.putExtra("habitType", habitType)
return intent
}
fun startSyncActivity(context: Context): Intent {
return Intent(context, SyncActivity::class.java)
}
}

View File

@@ -133,17 +133,17 @@ class PendingIntentFactory
timestamp: Long?
):
PendingIntent =
getBroadcast(
widgetContext,
2,
Intent(widgetContext, WidgetReceiver::class.java).apply {
data = Uri.parse(habit.uriString)
action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE
putExtra("numericalValue", numericalValue)
if (timestamp != null) putExtra("timestamp", timestamp)
},
FLAG_UPDATE_CURRENT
)
getBroadcast(
widgetContext,
2,
Intent(widgetContext, WidgetReceiver::class.java).apply {
data = Uri.parse(habit.uriString)
action = WidgetReceiver.ACTION_SET_NUMERICAL_VALUE
putExtra("numericalValue", numericalValue)
if (timestamp != null) putExtra("timestamp", timestamp)
},
FLAG_UPDATE_CURRENT
)
fun updateWidgets(): PendingIntent =
getBroadcast(

View File

@@ -92,6 +92,9 @@ class SharedPreferencesStorage
preferences.setNotificationsSticky(getBoolean(key, false))
"pref_led_notifications" ->
preferences.setNotificationsLed(getBoolean(key, false))
"pref_unknown_enabled" -> {
preferences.areQuestionMarksEnabled = getBoolean(key, false)
}
}
sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* 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/>.
*/
package org.isoron.uhabits.sync
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkRequest
import org.isoron.uhabits.core.sync.NetworkManager
class AndroidNetworkManager(
val context: Context,
) : NetworkManager, ConnectivityManager.NetworkCallback() {
val listeners = mutableListOf<NetworkManager.Listener>()
var connected = false
init {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
cm.registerNetworkCallback(NetworkRequest.Builder().build(), this)
}
override fun addListener(listener: NetworkManager.Listener) {
if (connected) listener.onNetworkAvailable()
else listener.onNetworkLost()
listeners.add(listener)
}
override fun remoteListener(listener: NetworkManager.Listener) {
listeners.remove(listener)
}
override fun onAvailable(network: Network) {
connected = true
for (l in listeners) l.onNetworkAvailable()
}
override fun onLost(network: Network) {
connected = false
for (l in listeners) l.onNetworkLost()
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* 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/>.
*/
package org.isoron.uhabits.sync
import android.util.Log
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
import io.ktor.client.features.ClientRequestException
import io.ktor.client.features.ServerResponseException
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.request.post
import io.ktor.client.request.put
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.invoke
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.sync.AbstractSyncServer
import org.isoron.uhabits.core.sync.EditConflictException
import org.isoron.uhabits.core.sync.GetDataVersionResponse
import org.isoron.uhabits.core.sync.KeyNotFoundException
import org.isoron.uhabits.core.sync.RegisterReponse
import org.isoron.uhabits.core.sync.ServiceUnavailable
import org.isoron.uhabits.core.sync.SyncData
class RemoteSyncServer(
private val preferences: Preferences,
private val httpClient: HttpClient = HttpClient(Android) {
install(JsonFeature)
}
) : AbstractSyncServer {
override suspend fun register(): String = Dispatchers.IO {
try {
val url = "${preferences.syncBaseURL}/register"
Log.i("RemoteSyncServer", "POST $url")
val response: RegisterReponse = httpClient.post(url)
return@IO response.key
} catch (e: ServerResponseException) {
throw ServiceUnavailable()
}
}
override suspend fun put(key: String, newData: SyncData) = Dispatchers.IO {
try {
val url = "${preferences.syncBaseURL}/db/$key"
Log.i("RemoteSyncServer", "PUT $url")
val response: String = httpClient.put(url) {
header("Content-Type", "application/json")
body = newData
}
} catch (e: ServerResponseException) {
throw ServiceUnavailable()
} catch (e: ClientRequestException) {
Log.w("RemoteSyncServer", "ClientRequestException", e)
if (e.message!!.contains("409")) throw EditConflictException()
if (e.message!!.contains("404")) throw KeyNotFoundException()
throw e
}
}
override suspend fun getData(key: String): SyncData = Dispatchers.IO {
try {
val url = "${preferences.syncBaseURL}/db/$key"
Log.i("RemoteSyncServer", "GET $url")
return@IO httpClient.get<SyncData>(url)
} catch (e: ServerResponseException) {
throw ServiceUnavailable()
} catch (e: ClientRequestException) {
Log.w("RemoteSyncServer", "ClientRequestException", e)
throw KeyNotFoundException()
}
}
override suspend fun getDataVersion(key: String): Long = Dispatchers.IO {
try {
val url = "${preferences.syncBaseURL}/db/$key/version"
Log.i("RemoteSyncServer", "GET $url")
val response: GetDataVersionResponse = httpClient.get(url)
return@IO response.version
} catch (e: ServerResponseException) {
throw ServiceUnavailable()
} catch (e: ClientRequestException) {
Log.w("RemoteSyncServer", "ClientRequestException", e)
throw KeyNotFoundException()
}
}
}

View File

@@ -103,7 +103,7 @@ class CheckmarkWidgetView : HabitWidgetView {
SKIP -> resources.getString(R.string.fa_skipped)
UNKNOWN -> {
run {
if (preferences!!.areQuestionMarksEnabled()) {
if (preferences!!.areQuestionMarksEnabled) {
return resources.getString(R.string.fa_question)
} else {
resources.getString(R.string.fa_times)

View File

@@ -0,0 +1 @@
Loop - Gewoonte Boekhouer

View File

@@ -1,22 +0,0 @@
لب يساعدك على خلق والحفاظ على العادات الجيدة، مما يسمح لك لتحقيق أهدافكة. الرسوم البيانية والإحصاءات التفصيلية تبين لكم كيف تحسن عاداتك مع مرور الوقت. هو تماما خالية من الاعلانات ومفتوحة المصدر.
<b>واجهة بسيطة، جميلة وحديثة </b>
لوب يحتوي على واجهة بسيطة وهي سهلة الاستخدام و تتابع نظام تصميم الماتريل دسيجن.
<b>نتيجة العادات</b>
بالإضافة إلى عرض التقدم الحالي، لوب ديه خوارزمية متقدمة لحساب قوة عاداتك. كل التكرار يجعل هذه العادة أقوى، وفي كل يوم غاب يجعلها أضعف. مع ذلك غيب أيام قليلة بعد تقدم طويلة ، لن تدمر تماما تقدمك .
<b>الرسوم البيانية والإحصاءات المفصلة</b>
نرى بوضوح كيف كنت قد تحسنت عاداتك بمرور الوقت مع الرسوم البيانية الجميله ومفصلة. انتقل إلى الوراء لنرى التاريخ الكامل لعاداتك.
<b>جداول مرنة</b>
تؤيد كل من العادات اليومية والعادات مع جداول أكثر تعقيدا، مثل 3 مرات كل أسبوع، مرة واحدة كل أسبوعين، أو مرة كل يومين.
<b>تذكير</b>
إنشاء تذكير لكل فرد من عاداتك، في ساعة اختيار من اليوم. تحقق بسهولة، رفض أو غفوة عادتك مباشرة من الإخطار، دون الحاجة إلى فتح التطبيق.
<b>خالية تماما من الإعلانات و المصدر المفتوح</b>
لا توجد على الاطلاق الإعلانات والشعارات المزعجة أو أذونات إضافية في هذا التطبيق، و سوف يكون هناك أبدا.
<b>الأمثل للساعات الذكية</b>
يمكن التحقق من رسائل التذكير، رفض أو غفوة عادتك مباشرة من ساعتك الاندرويد وير.

View File

@@ -1 +0,0 @@
خلق عادات جيدة وتتبع تقدمك على مر الزمن

View File

@@ -1 +0,0 @@
لوب ملاحق العادة

View File

@@ -0,0 +1 @@
Loop Следене на навици

View File

@@ -0,0 +1 @@
Loop - Hàbit Rastrejador

View File

@@ -1,22 +0,0 @@
Loop t'ajuda a crear i mantenir bons hàbits, permetent-te aconseguir els teus objectius a llarg termini. Els gràfics i estadístiques detallades et mostren com han millorat els teus hàbits al llarg del temps. És completament de codi obert i lliure de publicitat.
<b>Senzilla, bonica i moderna interfície</b>
Loop té una interfície minimalista que és fàcil d'utilitzar i segueix les guies de "material design".
<b>Puntuació d'hàbit</b>
A més de mostrar la teva ratxa actual, Loop té un algoritme avançat per a calcular la fortalesa dels teus hàbits. Cada repetició fa el teu hàbit més fort, i cada dia que fallis el farà més dèbil. Tot i això uns quants dies que fallis després d'una llarga ratxa no malmetrà completament el teu progrès.
<b>Gràfics i estadístiques detallades</b>
Permet veure de forma clara com han millorat els teus hàbits al llarg del temps amb gràfics bonics i detallats. Pots anar enrera i veure també l'històric complet dels teus hàbits.
<b>Planificació flexible</b>
Suporta tant hàbits diaris com hàbits amb planificacions més complexes, com per exemple 3 vegades per setmana; un cop setmana si setmana no; o un dia si i altre no.
<b>Recordatoris</b>
Crea un recordatori individual per a cada hàbit, a l'hora escollida del dia. Revisa fàcilment, endarrereix o anul·la el teu hàbit directament des de la notificació, sense obrir l'app.
<b>Completament de codi obert i lliure de publicitat</b>
No hi ha cap tipus de publicitat, notificacions molestes o permisos intrusius en aquesta app, i mai n'hi haurà. El codi font complet està disponible sota la llicència GPLv3.
<b>Optimitzat per a rellotges intel·ligents</b>
Els recordatoris poden ser revisats, endarrerits o anul·lats directament des del teu rellotge Android Wear.

View File

@@ -1 +0,0 @@
Crea bons hàbits i segueix el seu progrés al llarg del temps (sense publicitat)

View File

@@ -1,22 +0,0 @@
Aplikace ti pomůže vytvořit a udržovat si prospěšné návyky a dosáhnout tak tvých dlouhodobých cílů. Detailní grafy a statistiky ti ukáží, jak se tvoje zvyky postupem času zlepšují. Vše je kompletně bez reklam a open source.
<b>Jednoduché, krásné a moderní prostředí</b>
Aplikace má minimalistický design s jednoduchým použitím. Dodržuje pravidla material designu.
<b>Síla zvyku</b>
Pro zobrazení aktuální úspěšné serie aplikace využívá pokročilý algoritmus, aby vypočítala sílu tvých zvyků. Každé opakování dělá tvůj zvyk silnějším a každé nedodržení ho oslabuje. Ale pár vynechaných dní po dlouhé řadě kompletně nezničí celý tvůj postup.
<b>Detailní grafy a statistika</b>
Přehledně vidíš na krásných grafech, jak moc se tvoje zvyky zlepšují v průběhu času. Jeď zpět, abys viděl kompletní historii.
<b>Flexibilní časový plán</b>
Podpora jak denních návyků, tak návyků s komplexnějším rozvrhem. Jako jsou 3 krát týdně, jednou za dva týdny, nebo obden.
<b>Upomínky</b>
Vytvoř si individuální upomínku pro každý zvyk ve zvolený čas. Jednoduše potvrď, přeskoč nebo odlož notifikace bez nutnosti otevření aplikace.
<b>Kompletně bez reklam a open source</b>
Nejsou tu naprosto žádné reklamy, otravné notifikace nebo dotěrná povolení aplikace. A nikdy nebudou. Kompletní zdrojový kód je dostupný pod GPLv3.
<b>Optimalizované pro chytré hodinky</b>
Upomínky mohou být potvrzen, odloženy nebo smazány přímo z tvého zařízení s Android Wear.

View File

@@ -1 +0,0 @@
Vytvoř si prospěšné návyky a sleduj jejich vývoj v průběhu času (bez reklam)

View File

@@ -1 +0,0 @@
Loop - Habit Tracker

View File

@@ -0,0 +1 @@
Loop Vane Tracker

View File

@@ -1,22 +0,0 @@
Loop hilft dir gute Gewohnheiten anzunehmen und deine langfristigen Ziele zu erreichen. Detailierte Statistiken zeigen dir, wie du dich entwickelt hast. Es ist ohne Werbung und Open Source.
<b>Einfaches, schönes und modernes Oberfläche</b>
Loop hat eine minimale Oberfläche und ist deshalb einfach zu nutzen. Es folgt dem material Design.
<b>Habit Punkte</b>
Um dir deine Schwächen zu zeigen, hat Loop einen Algorithmus, um deine starken Angewohnheiten zu erkennen. Jede Wiederholung verstärkt diese und jedes Aussetzen schwächt sie. Aber ein paar Verfehlungen nach langem Durchhalten machen natürlich nicht gleich alles zu nichte.
<b>Statistiken</b>
Schau dir an, wie sich deine Angewohnheiten im Laufe der Zeit gemacht haben. Schau auf die schönen Diagramme und gehe zurück im gesamten Verlauf.
<b>Flexible Zeiten</b>
Unterstützt sowohl tägliche Vorgaben, als auch komplexere Pläne, woe etwa 3 mal pro Woche; ein mal in jeder anderen Woche; oder jeden anderen Tag.
<b>Erinnerungen</b>
Erstelle individuelle Erinnerungen und wann diese dich benachrichtigen sollen. Kontrolliere deine Vorhaben ganz einfach und lehne sie bei Bedarf direkt ab, ohne in die App zu wechseln.
<b>Komplett werbefrei und Open Source</b>
Es gibt absolut keine Werbung, nervende Einblendungen oder merkwürdige Berechtigungen in dieser App und das wird auch so bleiben. Der komplette Quellcode steht unter der GPLv3.
<b>Optimiert für Smartwatches</b>
Erinnerungen können direkt von der Android Wear watch kontrolliert, pausiert, oder verschoben werden.

View File

@@ -1 +0,0 @@
Nimm gute Gewohnheiten an und verfolge deinen Fortschritt (ohne Werbung)

View File

@@ -0,0 +1 @@
Loop - Gewohnheiten Tracking

View File

@@ -0,0 +1 @@
Loop - Καταγραφή Συνηθειών

View File

@@ -1,22 +0,0 @@
Loop te ayuda a crear y mantener buenos hábitos, permitiéndote alcanzar tus metas a largo plazo. Detallados gráficos y estadísticas muestran como tus hábitos mejoran con el tiempo. No existe ningún anuncio y es de código abierto.
<b>Una interfaz simple, bella y moderna</b>
Loop tiene una interfaz minimalista que es fácil de usar y sigue los principios del material design.
<b>Puntuación del hábito</b>
Además de mostrar tu racha actual, Loop tiene un algoritmo avanzado para calcular la fuerza de tus hábitos. Cada repetición hace tu hábito más fuerte y cada día fallido lo hace más débil. Sin embargo, unos pocos días después de una larga racha no destruirán completamente todo tu progreso.
<b>Detallados gráficos y estadísticas</b>
Observa claramente como tus hábitos han mejorado con el tiempo con bellos y detallados gráficos. Ve hacia atrás para ver el historial completo del hábito.
<b>Horarios flexibles</b>
Soporta hábitos diarios y hábitos con repeticiones más complejas, como 3 veces por semana; una vez cada varias semanas; o cada día.
<b>Recordatorios</b>
Crea recordatorios individuales para cada hábito a una hora determinada del día. Fácilmente marcables, descartables o posponibles directamente desde la notificación, sin abrir la app.
<b>Completamente sin anuncios y de código abierto</b>
No existe ningún tipo de publicidad, notificaciones molestas o permisos intrusivos, y nunca los habrá. Todo el código está disponible bajo GPLv3.
<b>Optimizado para smartwatches</b>
Los recordatorios se pueden marcar, posponer o descartar directamente desde tu reloj Android Wear.

View File

@@ -1 +0,0 @@
Crea buenos hábitos y haz un seguimiento de su progreso a lo largo del tiempo

View File

@@ -1 +0,0 @@
Loop - Analizador de Hábitos

View File

@@ -0,0 +1 @@
Loop Analizador de Hábitos

View File

@@ -1,22 +0,0 @@
Loop vous aide à créer et maintenir de bonnes habitudes, permettant de réussir vos objectifs à long terme. Des graphiques détaillés et des statistiques vous montrent comment vos habitudes saméliorent au fil du temps. C'est totalement sans pub et open source.
<b>Simple, beau avec une interface moderne</b>
Loop a une interface minimaliste, facile à utiliser et qui suit les règles de material design.
<b>Score d'habitude</b>
En plus de montrer votre série en cours, Loop a un algorithme pour calculer la force de vos habitudes. Chaque jours réussis augmente la force de l'habitude chaque jours ratés le rend plus faible. Cependant, quelques jours ratés après une longue série ne détruiront pas entièrement votre progrès.
<b>Graphiques détaillés et statistiques</b>
Observez clairement comment vos habitudes saméliorent au fil du temps avec de beaux graphiques détaillés. Défilez vers les jours passés pour voir l'historique complet de vos habitudes.
<b>Calendrier flexible</b>
Supporte les habitudes quotidiennes et celles avec un calendrier plus complexes, comme 3 fois par semaine, une fois par semaine ou un jour sur deux.
<b>Rappel</b>
Créez un rappel propre pour chaque habitude, à une heure choise de la journée. Cochez, supprimez ou réglez à plus tard votre habitude directement à partir de la notification, sans l'ouvrir l'application.
<b>Entièrement sans pub et open-source</b>
Il n'y a pas de publicités, de notifications embêtantes ou de permissions intrusives avec cette application, et il n'y en aura jamais. L'ensemble du code source est disponible sous GPLv3.
<b>Optimisée pour les montres android</b>
Les rappels peuvent être cochés, reportés ou supprimés directement à partir de votre montre Android

View File

@@ -1 +0,0 @@
Créez des bonnes habitudes et suivez leurs avancées au fil du temps (sans pub)

View File

@@ -0,0 +1 @@
Loop - आदत पर नजर

View File

@@ -0,0 +1 @@
Loop Habit Tracker

View File

@@ -1,21 +0,0 @@
Loop Vam pomaže stvoriti i održavati dobre navike kako biste ostvarili svoje dugoročne ciljeve. Detaljni grafikoni Vam pomažu kako biste bolje pratili kako napreduju Vaše navike. Loop je open source aplikacija i ne sadrži nikakav oblik reklama.
<b>Jednostavno, lijepo i moderno sučelje.</b>
Loop sadrži minimalistično sučelje jednostavno za korištenje koje prati smjernice Material Design-a.
<b>Rezultat navike</b>
Osim prikazivanja trenutnog niza, Loop ima napredni algoritam za računanje snage vaših navika. Svako ponavljanje jača vašu naviku, a svaki propušteni dan ju čini slabijom. Međutim, par propuštenih dana nakon dugačkog niza neće u potpunosti uništiti cjelokupni napredak.
<b>Detaljni grafovi i statistike</b>
Jasno vidite kako su se vaše navike poboljšale kroz vrijeme u prekrasnim i detaljnim grafovima. Kliznite natrag kako bi prikazali kompletnu povijest vaših navika.
<b>Fleksibilno planiranje</b>
Podržava i dnevne navike i navike sa složenijim planiranjem, kao npr. 3 puta svakog tjedna; jednom svaki drugi tjedan; ili svaki drugi dan.
<b>Podsjetnici</b>
Stvorite individualne podsjetnike za svaku naviku, u određenom satu u danu. Lako provjeravajte, odbacite i odgodite vašu naviku direktno iz obavijesti, bez otvaranja aplikacije.
<b>Optimizirano za pametne satove</b>
Podsjetnici se mogu provjeravati, odgoditi ili odbaciti direktno sa vašeg Android Wear sata.
<b>Potpuno bez oglasa i otvorenog izvora koda</b>

View File

@@ -1 +0,0 @@
Stvorite dobre navike i pratite njihov napredak (bez reklama)

View File

@@ -0,0 +1 @@
Loop Szokásrögzítő

View File

@@ -0,0 +1 @@
Loop Habit Tracker

View File

@@ -1,23 +0,0 @@
Loop membantu Anda untuk membuat dan mengelola Kebiasaan baik, memungkinkan Anda mencapai gol jangka panjang. Grafik detail dan statistik menampilkan perkembangan Kebiasaan Anda dari waktu ke waktu. Aplikasi ini bebas iklan dan open-source.
<b>Sederhana, minimalis dengan balutan antarmuka yang modern</b>
Loop memiliki tampilan minimalis yang mudah digunakan dan mengikuti panduan material design.
<b>Skor Kebiasaan</b>
Algoritma Loop akan menghitung kekuatan Kebiasaan Anda. Setiap kali Anda melakukan pengulangan maka skor Anda akan bertambah, sebaliknya jika Anda tidak mengerjakan Kebiasaan maka nilai akan dikurangi. Beberapa hari yang terlewat tidak akan menghapus seluruh perkembangan Kebiasaan Anda.
<b>Detail Grafik dan Statistik</b>
Lihat perkembangan Kebiasaan dari waktu ke waktu dengan tampilan yang menarik dan detail. Geser ke bawah untuk melihat seluruh catatan Kebiasaan Anda.
<b>Pengaturan jadwal fleksibel</b>
Mendukung kebiasaan harian dan kebiasaan dengan penjadwalan yang kompleks, seperti 3 kali dalam setiap minggu; 2 minggu sekali; hingga 2 hari sekali.
<b>Pengingat</b>
Anda dapat membuat pengingat untuk setiap Kebiasaan, dengan waktu yang telah Anda tentukan setiap harinya. Mudah untuk di-cek, batalkan ataupun tunda melalui panel notifikasi tanpa perlu membuka aplikasi.
<b>Bebas dari iklan dan open-source</b>
Tidak ada iklan, notifikasi menyebalkan dan juga hak akses yang tidak dibutuhkan.
Kode aplikasi tersedia dengan lisensi GPLv3
<b>Mendukung Smartwatch</b>
Anda dapat dengan mudah mengecek, menunda ataupun membatalkan pengingat melalui smartwatch Anda.

View File

@@ -1 +0,0 @@
Buat Kebiasaan baik dan catat perkembangannya setiap waktu (bebas iklan)

View File

@@ -0,0 +1 @@
Loop Habit Tracker

View File

@@ -1,18 +0,0 @@
Loop ti aiuta a creare e mantenere buone abitudini, permettendoti di raggiungere i tuoi obbiettivi a lungo termine. Grafici dettagliati e le statistiche ti mostrano come le tue abitudini sono migliorate durante il tempo. E' completamente senza pubblicità ed opensource.
<b>Interfaccia semplice e moderna</b> Loop ha un'interfaccia minimale che è semplice da usare e segue le linee guida del Material Design
<b>Forza dell'abitudine</b>
In aggiunta al traguardo attuale, Loop ha un algoritmo avanzato per calcolare la forza delle tue abitudini. Ogni ripetizione la rafforza, mentre ogni giorno mancato la indebolisce. Pochi giorni mancati dopo una lunga serie però non vanificherà completamente il tuo progresso totale.
<b>Grafici dettagliati e statistiche</b> Visualizza in modo semplice come le tue abitudini sono migliorate nel tempo con grafici dettagliati. Scorri indietro per vedere la cronologia completa delle tue abitudini.
<b>Programmi flessibili</b> Supporto per abitudini sia giornaliere che con organizzazioni più complesse, come 3 volte alla settimana; una volta ogni 2 settimane; ogni due giorni...
<b>Promemoria</b>
Crea un promemoria per ogni abitudine, ad una specificata ora del giorno. Completa, ritarda o ignora il promemoria direttamente dalla notifica, senza aprire l'app.
<b>Completamente gratuito ed opensource</b>
Non ci sono pubblicità, notifiche invasive o permessi intrusivi e mai ce ne saranno. Il codice sorgente completo è disponibile sotto licenza GPLv3.
<b>Ottimizzata per gli smartwatch</b> I promemoria possono essere completati, ritardati o ignorati direttamente dal tuo orologio Android Wear.

View File

@@ -1 +0,0 @@
Acquisisci nuove abitudini e traccia il tuo progresso (senza pubblicità)

View File

@@ -0,0 +1 @@
Loop - Tracciatore di Abitudine

View File

@@ -0,0 +1 @@
Loop Habit Tracker

View File

@@ -1,22 +0,0 @@
ループは、良い習慣を作って、維持するのに役立ちます。あなたの長期的な目標を達成することができます。詳細なグラフや統計情報が、時間をかけてあなたの習慣が改善された様子を示します。完全に広告フリーでオープンソースです。
<b>シンプルで、美しく、モダンなインターフェース</b>
ループは、使いやすく、マテリアルデザインのガイドラインに従った、最小限のインターフェースです。
<b>習慣のスコア</b>
ループは、現在の連続記録を示すことに加えて、習慣の強さを計算するための高度なアルゴリズムを持っています。繰り返しがあなたの習慣を強くし、忘れた日は弱くなります。長い連続記録の後に、少し忘れた日があっても、全体の進捗状況を完全に失うわけではありません。
<b>詳細なグラフと統計情報</b>
美しくて詳細なグラフで、あなたの習慣が時間をかけて改善された様子がはっきりわかります。スクロールで戻ると、あなたの習慣の完全な履歴を参照することができます。
<b>柔軟なスケジュール</b>
毎日の習慣と、毎週 3 回、隔週に 1 回、または一日おきなどの、より複雑なスケジュールの習慣の両方をサポートします。
<b>リマインダー</b>
1 日の選択した時間で、それぞれの習慣に個々のリマインダーを作成します。アプリを開かずに、通知から直接、簡単に習慣をチェック、解除、またはスヌーズすることができます。
<b>完全に広告フリーでオープンソース</b>
このアプリは、広告、迷惑な通知、押し付けがましいアクセス許可は全くありませんし、そうなることもありません。GPLv3 の下で全てのソースコードが利用可能です。
<b>スマートウォッチの最適化</b>
Android Wear 端末から直接、リマインダーをチェック、スヌーズ、解除することができます。

View File

@@ -1 +0,0 @@
良い習慣を作って、時間をかけてその進捗状況を追跡します (広告なし)

View File

@@ -1,20 +0,0 @@
Loop은 습관을 만들고 유지하도록 도와주어, 장기간 목표를 달성하도록 합니다. 그래프와 통계를 보고 습관이 만들어지는 과정을 보세요. 오프소스이고, 무광고입니다.
<b>아름답고 심플한 디자인</b>
Loop은 Material디자인을 따라 사용이 편합니다.
<b>습관 포인트</b>
얼마나 오랫동안 습관을 유지했는지 보여줌과 동시에, Loop은 특화된 알고리듬으로 습관의 견고함을 계산합니다. 반복할 수록 강해지고, 빠뜨린 날들이 많아질 수록 포인트는 낮아집니다. 하지만, 오랫동안 유지된 습관은 몇 일을 빠뜨렸다고 해서 포인트가 급강하하지는 않습니다.
<b>그래프와 통계</b>
습관이 어떤 과정을 거쳐서 완성되는지 그래프를 보면 알 수 있습니다.
스크롤해서 장기간의 과정을 볼 수 있습니다.
<b>여러 종류의 스케줄 조정가능</b>
매일 습관, 혹은 일주일에 3번; 2주에 한번; 같은 여러 종류의 스케줄을 만들 수 있습니다.
<b>오픈소스, 무광고</b>
광고, 귀찮은 스팸, 비정상적인 정보요구는 없습니다, 앞으로 쭉. 모든 소스코드는 GPLv3로 라이센스되었습니다.
<b>스마트시계에 최적화</B>
안드로이드 시계에서 바로 알림을 확인, 미루기 혹은 무시할 수 있습니다.

View File

@@ -1 +0,0 @@
좋은 습관을 만들고 관리하세요. (광고 없음)

View File

@@ -0,0 +1 @@
Loop Gewoonte tracker

View File

@@ -0,0 +1 @@
Loop Vaneoversikt

View File

@@ -1,22 +0,0 @@
Loop pozwala Ci na tworzenie i utrzymywanie dobrych nawyków, pozwala na Ci na osiągnięcie Twoich długoterminowych celów. Szczegółowe grafiki i statystyki pozwalają na zobaczenie jak Twoje nawyki polepszyły się. Jest całkowicie wolna od reklam i open source.
<b>Prosty, piękny i nowoczesny interfejs</b>
Loop posiada minimalistyczny interfejs, który jest prosty do użycia i przestrzega zasad material design.
<b>Punkty nawyku</b>
Oprócz pokazywania Twojej aktualnej serii, Loop posiada zaawansowany algorytm obliczania siły Twoich nawyków. Każde powtórzenie nawyku czyni go silniejszymi a każdy opuszczony dzień słabszym. Jednakże kilka opuszczonych dni po dłuższej serii nie zrujnuje Twojego całego postępu.
<b>Szczegółowe grafiki i statystyki</b>
Zobacz jak Twoje nawyki ulepszają się poprzez piękne i szczegółowe wykresy. Przewiń do tyłu aby zobaczyć pełną historię Twoich nawyków.
<b>Elastyczne plany</b>
Wspiera zarówno codzienne nawyki jak i nawyki z bardziej złożonym planem, jakie jak 3 razy co tydzień; raz w ciągu innego tygodnia; lub każdego innego dnia.
<b>Przypomnienia</b>
Utwórz indywidualne przypomnienia dla każdego nawyku, w określonej godzinie dnia. Łatwo sprawdź, usuń i uśpij powiadomienia o nawyku bezpośrednio z powiadomienia, bez otwierania aplikacji.
<b>Całkowicie bez reklam i open source</b>
Absolutnie nie ma żadnych reklam, denerwujących powiadomień czy szpiegujących uprawnień w tej aplikacji i nigdy nie będzie. Cały kod źródłowy jest dostępny pod licencją GPLv3.
<b>Zoptymalizowana pod smartwatche</b>
Przypomnienia można sprawdzić, uśpić czy usunąć bezpośrednio z twojego zegarka Android Wear.

View File

@@ -1 +0,0 @@
Twórz dobre nawyki i śledź ich postęp (bez reklam)

View File

@@ -1,19 +0,0 @@
Loop é um aplicativo que te ajuda a criar e manter bons hábitos, permitindo que você alcance os seus objetivos de longo prazo. Gráficos e estatísticas mostram em detalhe como os seus hábitos progrediram ao passar do tempo. Este aplicativo não tem nenhuma propaganda e é Open Source.
<b>Interface bonita, moderna e simples</b>
Loop tem uma interface minimalista bem simples de se usar, e segue o novo visual Material Design.
<b>Estabilidade dos hábitos</b>
Além de mostrar quantos dias seguidos você praticou cada rotina, Loop também conta com uma fórmula mais avançada para calcular a estabilidade dos seus hábitos. Cada repetição melhora a estabilidade do hábito, e cada dia de folga piora a estabilidade. Alguns dias de folga após um longo período perfeito, no entanto, não destruirá por completo o seu progresso.
<b>Gráficos e estatísticas detalhadas</b>
Veja claramente como os seus hábitos estão progredindo com o passar do tempo, através de bonitos e detalhados diagramas. O histórico completo de cada hábito fica arquivado para sempre.
<b>Rotina flexível</b>
Loop aceita tanto hábitos diários, quanto hábitos com rotinas mais complexas, como 3 vezes por semana; uma vez a cada duas semanas; ou uma vez a cada dois dias.
<b>Lembretes</b>
É possível criar lembretes individuais para cada hábito, na hora do dia em que você escolher. Marque como completado diretamente da barra de notificação, sem precisar abrir o aplicativo.
<b>Completamente sem propagandas e Open Source</b>
Não há nenhum anúncio neste aplicativo, nem notificações chatas ou permissões intrusivas; e será assim para sempre. O código fonte completo está disponível sob a licença livre GPLv3.

View File

@@ -1 +0,0 @@
Forme bons hábitos e acompanhe seu progresso ao passar do tempo (sem anúncios)

View File

@@ -0,0 +1 @@
Loop - Acompanhador de Hábitos

View File

@@ -0,0 +1 @@
Loop Habit Tracker

View File

@@ -1,22 +0,0 @@
"Трекер привычек Loop" поможет вам завести и поддерживать полезные привычки, позволяя достичь долгосрочных целей. Детализированные диаграммы и статистика покажут, как ваши привычки закрепились со временем. Приложение не содержит рекламы и является ПО с открытым исходным кодом.
<b>Простой, красивый и современный интерфейс</b>
У приложения минималистичный интерфейс, который лёгок в использовании и придерживается руководства по Material Design.
<b>Оценка привычек</b>
В дополнение к отображению текущего рекорда повторений, приложение имеет передовой алгоритм расчёта "силы" ваших привычек. Каждое повторение делает вашу привычку "сильнее", а каждый пропуск "слабее". Несколько пропущенных дней после долгих успешных повторений, однако, не загубят ваши успехи полностью.
<b>Детализированные диаграммы и статистика</b>
При помощи красивых и детализированных диаграмм вы с лёгкостью можете просмотреть, как ваши привычки закрепились со временем. Просмотрите полную историю ваших привычек, пролистав её.
<b>Гибкий график</b>
Поддерживаются как ежедневные привычки, так и привычки с более сложным графиком. Например: 3 раза в неделю; один раз каждую неделю; через день.
<b>Напоминания</b>
Создавайте отдельные для каждой привычки напоминания в выбранное время дня. С лёгкостью отмечайте, пропускайте или откладывайте выполнение привычки прямо из уведомления - без открытия приложения.
<b>Полное отсутствие рекламы и открытый исходный код</b>
В приложении совершенно нет рекламы, назойливых уведомлений или лишних разрешений. И их никогда не будет. Весь исходный код доступен под лицензией GPLv3.
<b>Оптимизировано для "умных" часов</b>
Напоминания могут быть отмечены, отложены или пропущены прямо с ваших часов Android Wear.

View File

@@ -1 +0,0 @@
Заводите полезные привычки и отслеживайте свои успехи (без рекламы)

View File

@@ -0,0 +1 @@
Loop Habit Tracker

View File

@@ -1,22 +0,0 @@
Loop vam pomaga ustvariti in vzdrževati dobre navade, kar vam omogoča, da bi dosegli svoje dolgoročne cilje. Podrobni grafi in statistike vam pokažejo kako so se vaše navade skozi čas izboljšale. Je popolnoma brez oglasov in odprtokodno.
<b>Enostaven, lep in sodoben vmesnik</b>
Loop ima minimalističen vmesnik, ki je preprost za uporabo in sledi smernicam Material design.
<b>Ocena navade</b>
Poleg tega, da vam prikazuje vaše trenutne serije, ima Loop napreden algoritem za izračun moči vaših navad. Vsaka ponovitev naredi vašo navado močnejšo in vsak zgrešen dan jo naredi šibkejšo. Nekaj zgrešenih dni po dolgi seriji, pa vendar ne bo popolnoma uničilo vašega celotnega napredka.
<b>Podrobni grafi in statistike</b>
Z lepimi in natančnimi grafi, jasno poglejte, kako so se skozi čas vaše navade izboljšale. Da boste videli celotno zgodovino svojih navad se pomaknite nazaj.
<b>Prilagodljivi urniki</b>
Podpira tako vsakdanje navade in navade z bolj zapletenimi urniki, kot so 3-krat na teden; enkrat vsak drugi teden; ali vsak drugi dan.
<b>Opomniki</b>
Ustvari individualni opomnik za vsako navado, pri izbrani uri dneva. Enostavno preverite, zavrzite ali dajte v dremež svoje navade neposredno iz obvestila, ne da bi odprli aplikacijo.
<b>Popolnoma brez oglasov in odprtokodno</b>
V tej aplikaciji ni absolutno nobene reklame, sitnih obvestil ali vsiljivih dovoljenj in jih tudi nikoli ne bo. Celotna izvorna koda je na razpolago pod GPLv3.
<b>Optimirano za pametne ure</b>
Opomnike lahko preverite, jih date v dremež ali pa zavrzite neposredno iz vaše Android Wear ure.

View File

@@ -1 +0,0 @@
Ustvarite dobre navade in spremljajte njihov napredek skozi čas (brez reklam)

View File

@@ -0,0 +1 @@
„Loop“ — praćenje navika

View File

@@ -0,0 +1 @@
„Loop“ — праћење навика

View File

@@ -1,22 +0,0 @@
Loop вам помаже да створите и одржавате здраве навике, самим тим и да достигнете дугорочне циљеве. Детаљна статистика и графикони показују вам колико су се ваше навике временом побољшале. Апликација је отвореног кода и не садржи огласе.
<b>Једноставан, леп и модеран дизајн</b>
Loop има минималистички интерфејс који је једноставан за коришћење и прати смернице за материјални дизајн.
<b>Оцена навике</b>
Поред приказа тренутног низа, Loop поседује напредни алгоритам за израчунавање снаге ваших навика. Ваша навика са сваким понављањем постаје јача, а са сваким пропуштеним даном слабија. Неколико пропуштених дана након дугог низа, пак, неће у потпуности упропастити ваш резултат.
<b>Детаљни графикони и статистика</b>
Пратите свој напредак уз лепе и детаљне графиконе. Вратите се уназад да бисте видели целу историју навика.
<b>Флексибилни распоред</b>
Подржава како дневне навике, тако и оне са сложенијим понављањем (трипут недељно, једанпут сваке друге недеље, сваки други дан и сл.).
<b>Подсетници</b>
Направите појединачни подсетник за сваку навику у жељено доба дана. С лакоћом маркирајте, одложите или откажите навику директно из обавештења, без отварања апликације.
<b>У потпуности отвореног кода и без огласа</b>
Апликација не садржи никакве огласе, досадна обавештења или наметљиве дозволе; никада и неће. Изворни кôд је у целости доступан под лиценцом GPLv3.
<b>Оптимизовано за паметне сатове</b>
Навике можете маркирати, одложити или отказати директно помоћу Android Wear сата.

Some files were not shown because too many files have changed in this diff Show More