diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..64043843f --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,31 @@ +name: Build & Test + +on: + push: + branches: + - dev + pull_request: + branches: + - dev + +jobs: + build: + runs-on: macOS-latest + steps: + - uses: actions/checkout@v1 + - name: Install Java Development Kit 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build APK & Run small tests + run: android/build.sh build + - name: Run medium tests + uses: ReactiveCircus/android-emulator-runner@v2.2.0 + with: + api-level: 29 + script: android/build.sh medium-tests + - name: Upload artifacts + uses: actions/upload-artifact@v1 + with: + name: Build + path: android/uhabits-android/build/outputs/ diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..d52e446ab --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,40 @@ +name: Build, Test & Publish + +on: + push: + branches: + - master + +jobs: + build: + runs-on: macOS-latest + steps: + - uses: actions/checkout@v1 + - name: Install GPG + uses: olafurpg/setup-gpg@v2 + - name: Decrypt secrets + env: + GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} + run: .secret/decrypt.sh + - name: Install Java Development Kit 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build APK & Run small tests + env: + RELEASE: 1 + run: android/build.sh build + - name: Run medium tests + uses: ReactiveCircus/android-emulator-runner@v2.2.0 + env: + RELEASE: 1 + with: + api-level: 29 + script: android/build.sh medium-tests + - name: Upload build to GitHub + uses: actions/upload-artifact@v1 + with: + name: Build + path: android/uhabits-android/build/outputs/ + - name: Upload APK to Google Play + run: cd android && ./gradlew publishReleaseApk diff --git a/.gitignore b/.gitignore index a8c758cef..b93bd0c9b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .externalNativeBuild .gradle .idea +.secret build build/ captures diff --git a/.secret/decrypt.sh b/.secret/decrypt.sh new file mode 100755 index 000000000..ec2bfbf77 --- /dev/null +++ b/.secret/decrypt.sh @@ -0,0 +1,16 @@ +#!/bin/sh +cd "$(dirname "$0")" +if [ -z "$GPG_PASSWORD" ]; then + echo Env variable GPG_PASSWORD must be defined + exit 1 +fi +for file in gcp-key.json keystore.jks gradle.properties env; do + gpg \ + --quiet \ + --batch \ + --yes \ + --decrypt \ + --passphrase="$GPG_PASSWORD" \ + --output $file \ + $file.gpg +done diff --git a/.secret/env.gpg b/.secret/env.gpg new file mode 100644 index 000000000..d829dcdf2 Binary files /dev/null and b/.secret/env.gpg differ diff --git a/.secret/gcp-key.json.gpg b/.secret/gcp-key.json.gpg new file mode 100644 index 000000000..f2c9704ba Binary files /dev/null and b/.secret/gcp-key.json.gpg differ diff --git a/.secret/gradle.properties.gpg b/.secret/gradle.properties.gpg new file mode 100644 index 000000000..70d03a5a4 --- /dev/null +++ b/.secret/gradle.properties.gpg @@ -0,0 +1 @@ +  jcw_UҮ|H5< _Ud5W\#+ w/,:"qDtp6(ez+D|^R9QʋtUwЩk S"g ?d֠=:M0n|Ie/h}u [Dy>܃v`iU4ͻN5Mpΐ_$ \ No newline at end of file diff --git a/.secret/keystore.jks.gpg b/.secret/keystore.jks.gpg new file mode 100644 index 000000000..72176806d Binary files /dev/null and b/.secret/keystore.jks.gpg differ diff --git a/android/.gitignore b/android/.gitignore index 9ad9f8ab3..29f35cce8 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -13,6 +13,7 @@ .gradle .idea .project +.secret Thumbs.db art/ bin/ diff --git a/android/android-base/build.gradle b/android/android-base/build.gradle index f1967eb3e..a1e30ef89 100644 --- a/android/android-base/build.gradle +++ b/android/android-base/build.gradle @@ -6,17 +6,8 @@ android { defaultConfig { minSdkVersion MIN_SDK_VERSION as Integer targetSdkVersion TARGET_SDK_VERSION as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } + versionCode VERSION_CODE as Integer + versionName "$VERSION_NAME" } compileOptions { @@ -28,7 +19,6 @@ android { checkReleaseBuilds false abortOnError false } - } dependencies { @@ -38,14 +28,4 @@ dependencies { implementation "org.apache.commons:commons-lang3:3.5" annotationProcessor "com.google.dagger:dagger-compiler:$DAGGER_VERSION" - androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:$DAGGER_VERSION" - androidTestImplementation "com.google.dagger:dagger:$DAGGER_VERSION" - testAnnotationProcessor "com.google.dagger:dagger-compiler:$DAGGER_VERSION" - testImplementation "junit:junit:4.12" - - androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - - } diff --git a/android/android-pickers/build.gradle b/android/android-pickers/build.gradle index 41b55a8d5..02f9aaaaf 100644 --- a/android/android-pickers/build.gradle +++ b/android/android-pickers/build.gradle @@ -6,16 +6,6 @@ android { defaultConfig { minSdkVersion MIN_SDK_VERSION as Integer targetSdkVersion TARGET_SDK_VERSION as Integer - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } } compileOptions { diff --git a/android/build.sh b/android/build.sh index 782360fa0..46baff919 100755 --- a/android/build.sh +++ b/android/build.sh @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License along # with this program. If not, see . +cd "$(dirname "$0")" + ADB="${ANDROID_HOME}/platform-tools/adb" EMULATOR="${ANDROID_HOME}/tools/emulator" GRADLE="./gradlew --stacktrace" @@ -56,6 +58,12 @@ fail() { exit 1 } +if [ ! -z $RELEASE ]; then + log_info "Reading secret env variables from ../.secret/env" + source ../.secret/env || fail +fi + + start_emulator() { log_info "Starting emulator ($AVD_NAME)" $EMULATOR -avd ${AVD_NAME} -port ${AVD_SERIAL} -no-audio -no-window & @@ -82,16 +90,8 @@ build_apk() { rm -vf build/*.apk if [ ! -z $RELEASE ]; then - if [ -z "$LOOP_KEY_FILE" -o -z "$LOOP_STORE_PASSWORD" -o -z "$LOOP_KEY_ALIAS" -o -z "$LOOP_KEY_PASSWORD" ]; then - log_error "Environment variables LOOP_KEY_FILE, LOOP_KEY_ALIAS, LOOP_KEY_PASSWORD and LOOP_STORE_PASSWORD must be defined" - exit 1 - fi log_info "Building release APK" - ./gradlew assembleRelease \ - -Pandroid.injected.signing.store.file=$LOOP_KEY_FILE \ - -Pandroid.injected.signing.store.password=$LOOP_STORE_PASSWORD \ - -Pandroid.injected.signing.key.alias=$LOOP_KEY_ALIAS \ - -Pandroid.injected.signing.key.password=$LOOP_KEY_PASSWORD || fail + ./gradlew assembleRelease cp -v uhabits-android/build/outputs/apk/release/uhabits-android-release.apk build/loop-$VERSION-release.apk fi @@ -104,7 +104,7 @@ build_instrumentation_apk() { log_info "Building instrumentation APK" if [ ! -z $RELEASE ]; then $GRADLE assembleAndroidTest \ - -Pandroid.injected.signing.store.file=$LOOP_KEY_FILE \ + -Pandroid.injected.signing.store.file=$LOOP_KEY_STORE \ -Pandroid.injected.signing.store.password=$LOOP_STORE_PASSWORD \ -Pandroid.injected.signing.key.alias=$LOOP_KEY_ALIAS \ -Pandroid.injected.signing.key.password=$LOOP_KEY_PASSWORD || fail @@ -155,10 +155,17 @@ run_instrumented_tests() { -w ${PACKAGE_NAME}.test/android.support.test.runner.AndroidJUnitRunner \ | tee ${OUTPUTS_DIR}/instrument.txt - mkdir -p ${OUTPUTS_DIR}/code-coverage/connected/ - $ADB pull /data/user/0/${PACKAGE_NAME}/files/coverage.ec \ - ${OUTPUTS_DIR}/code-coverage/connected/ \ - || log_error "COVERAGE REPORT NOT AVAILABLE" + if grep FAILURES $OUTPUTS_DIR/instrument.txt; then + log_error "Some instrumented tests failed" + fetch_images + fetch_logcat + exit 1 + fi + + #mkdir -p ${OUTPUTS_DIR}/code-coverage/connected/ + #$ADB pull /data/user/0/${PACKAGE_NAME}/files/coverage.ec \ + # ${OUTPUTS_DIR}/code-coverage/connected/ \ + # || log_error "COVERAGE REPORT NOT AVAILABLE" } parse_instrumentation_results() { @@ -173,16 +180,8 @@ generate_coverage_badge() { python3 tools/coverage-badge/badge.py -i $CORE_REPORT -o ${OUTPUTS_DIR}/coverage-badge } -fetch_artifacts() { - log_info "Fetching generated artifacts" - mkdir -p ${OUTPUTS_DIR}/failed - $ADB pull /mnt/sdcard/test-screenshots/ ${OUTPUTS_DIR}/failed - $ADB pull /storage/sdcard/test-screenshots/ ${OUTPUTS_DIR}/failed - $ADB pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ ${OUTPUTS_DIR}/failed -} - fetch_logcat() { - log_info "Fetching logcat to ${OUTPUTS_DIR}/logcat.txt" + log_info "Fetching logcat" $ADB logcat -d > ${OUTPUTS_DIR}/logcat.txt } @@ -201,14 +200,9 @@ uninstall_test_apk() { } fetch_images() { - rm -rf tmp/test-screenshots > /dev/null - mkdir -p tmp/ - $ADB pull /mnt/sdcard/test-screenshots/ tmp/ - $ADB pull /storage/sdcard/test-screenshots/ tmp/ - $ADB pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ tmp/ - - $ADB shell rm -r /mnt/sdcard/test-screenshots/ - $ADB shell rm -r /storage/sdcard/test-screenshots/ + log_info "Fetching images" + rm -rf $OUTPUTS_DIR/test-screenshots + $ADB pull /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ $OUTPUTS_DIR $ADB shell rm -r /sdcard/Android/data/${PACKAGE_NAME}/files/test-screenshots/ } @@ -226,7 +220,6 @@ run_tests() { install_test_apk run_instrumented_tests $SIZE parse_instrumentation_results - fetch_artifacts fetch_logcat uninstall_test_apk } diff --git a/android/gradle.properties b/android/gradle.properties index 1e1d45f89..000388cf6 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,15 +1,15 @@ -VERSION_CODE = 39 -VERSION_NAME = 1.8.0 +VERSION_CODE = 45 +VERSION_NAME = 1.8.2 MIN_SDK_VERSION = 21 TARGET_SDK_VERSION = 29 COMPILE_SDK_VERSION = 29 -DAGGER_VERSION = 2.25.2 -KOTLIN_VERSION = 1.3.50 +DAGGER_VERSION = 2.25.4 +KOTLIN_VERSION = 1.3.61 SUPPORT_LIBRARY_VERSION = 28.0.0 AUTO_FACTORY_VERSION = 1.0-beta6 -BUILD_TOOLS_VERSION = 3.5.2 +BUILD_TOOLS_VERSION = 3.5.3 org.gradle.parallel=false org.gradle.daemon=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar index 8c0fb64a8..cc4fdc293 100644 Binary files a/android/gradle/wrapper/gradle-wrapper.jar and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 26c59f416..1ba7206f8 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Sep 04 13:05:58 MSK 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/android/gradlew b/android/gradlew index 91a7e269e..2fe81a7d9 100755 --- a/android/gradlew +++ b/android/gradlew @@ -1,4 +1,20 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## ## @@ -6,20 +22,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +75,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +105,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -110,10 +125,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +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 ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -138,27 +154,30 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat index aec99730b..24467a141 100644 --- a/android/gradlew.bat +++ b/android/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -8,14 +24,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@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= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@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" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +62,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +75,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/android/uhabits-android/build.gradle b/android/uhabits-android/build.gradle index 361ca8190..3db986e8c 100644 --- a/android/uhabits-android/build.gradle +++ b/android/uhabits-android/build.gradle @@ -1,18 +1,24 @@ -apply plugin: 'idea' -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' +plugins { + id 'idea' + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-kapt' + id 'com.github.triplet.play' version '2.6.2' +} android { compileSdkVersion COMPILE_SDK_VERSION as Integer - if(project.hasProperty("LOOP_STORE_FILE")) { + def secretPropsFile = file("../../.secret/gradle.properties") + if (secretPropsFile.exists()) { + def secrets = new Properties() + secretPropsFile.withInputStream { secrets.load(it) } signingConfigs { release { - storeFile file(LOOP_STORE_FILE) - storePassword LOOP_STORE_PASSWORD - keyAlias LOOP_KEY_ALIAS - keyPassword LOOP_KEY_PASSWORD + storeFile file(secrets.LOOP_KEY_STORE) + storePassword secrets.LOOP_STORE_PASSWORD + keyAlias secrets.LOOP_KEY_ALIAS + keyPassword secrets.LOOP_KEY_PASSWORD } } buildTypes.release.signingConfig signingConfigs.release @@ -42,6 +48,7 @@ android { lintOptions { checkReleaseBuilds false abortOnError false + disable 'GoogleAppIndexingWarning' } compileOptions { @@ -77,23 +84,23 @@ dependencies { implementation "com.google.dagger:dagger:$DAGGER_VERSION" implementation "com.jakewharton:butterknife:8.6.1-SNAPSHOT" implementation "org.apmem.tools:layouts:1.10" - implementation "com.google.code.gson:gson:2.7" + implementation "com.google.code.gson:gson:2.8.5" implementation "com.google.code.findbugs:jsr305:3.0.2" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION" compileOnly "javax.annotation:jsr250-api:1.0" - compileOnly "com.google.auto.factory:auto-factory:${AUTO_FACTORY_VERSION}" + compileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION" kapt "com.jakewharton:butterknife-compiler:9.0.0" - annotationProcessor "com.google.auto.factory:auto-factory:${AUTO_FACTORY_VERSION}" + annotationProcessor "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" androidTestImplementation "com.android.support.test.espresso:espresso-contrib:2.2.2" androidTestImplementation "com.android.support.test.espresso:espresso-core:2.2.2" androidTestImplementation "com.android.support.test.uiautomator:uiautomator-v18:2.1.1" androidTestImplementation "com.google.dagger:dagger:$DAGGER_VERSION" androidTestImplementation "com.linkedin.testbutler:test-butler-library:1.3.1" - androidTestCompileOnly "com.google.auto.factory:auto-factory:${AUTO_FACTORY_VERSION}" - androidTestAnnotationProcessor "com.google.auto.factory:auto-factory:${AUTO_FACTORY_VERSION}" + androidTestCompileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" + androidTestAnnotationProcessor "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" androidTestImplementation "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION" androidTestImplementation "com.android.support.test:rules:0.5" androidTestImplementation "com.android.support.test:runner:0.5" @@ -104,15 +111,15 @@ dependencies { // mockito-android 2+ includes net.bytebuddy, which causes tests to fail. // Excluding the package net.bytebuddy on AndroidManifest.xml breaks some // AndroidJUnitRunner functionality, such as running individual methods. - androidTestImplementation "org.mockito:mockito-core:1+" - androidTestImplementation "com.google.dexmaker:dexmaker-mockito:+" + androidTestImplementation "org.mockito:mockito-core:1.10.19" + androidTestImplementation "com.google.dexmaker:dexmaker-mockito:1.2" testImplementation "com.google.dagger:dagger:$DAGGER_VERSION" testImplementation "org.mockito:mockito-core:2.8.9" testImplementation "org.mockito:mockito-inline:2.8.9" - testImplementation "junit:junit:4+" + testImplementation "junit:junit:4.12" - implementation('com.opencsv:opencsv:3.9') { + implementation('com.opencsv:opencsv:3.10') { exclude group: 'commons-logging', module: 'commons-logging' } implementation('io.socket:socket.io-client:0.8.3') { @@ -120,11 +127,11 @@ dependencies { } } -repositories { - google() - jcenter() -} - kapt { correctErrorTypes = true } + +play { + serviceAccountCredentials = file("../../.secret/gcp-key.json") + track = "alpha" +} \ No newline at end of file diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java index 5aede98f5..714299396 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java @@ -62,8 +62,6 @@ public class BaseAndroidTest extends TestCase protected TaskRunner taskRunner; - protected HabitLogger logger; - protected HabitFixtures fixtures; protected CountDownLatch latch; @@ -101,7 +99,6 @@ public class BaseAndroidTest extends TestCase prefs = appComponent.getPreferences(); habitList = appComponent.getHabitList(); taskRunner = appComponent.getTaskRunner(); - logger = appComponent.getHabitsLogger(); modelFactory = appComponent.getModelFactory(); prefs.clear(); diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitLoggerTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitLoggerTest.java deleted file mode 100644 index 75f821787..000000000 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitLoggerTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2016 Álinson Santos Xavier - * - * 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 . - */ - -package org.isoron.uhabits; - -import android.os.*; -import android.support.test.filters.*; -import android.support.test.runner.*; - -import org.isoron.androidbase.*; -import org.isoron.uhabits.core.models.*; -import org.junit.*; -import org.junit.runner.*; - -import java.io.*; - -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.MatcherAssert.*; - -@RunWith(AndroidJUnit4.class) -@MediumTest -public class HabitLoggerTest extends BaseAndroidTest -{ - @Test - public void testLogReminderScheduled() throws IOException - { - if (!isLogcatAvailable()) return; - - long time = 1422277200000L; // 13:00 jan 26, 2015 (UTC) - Habit habit = fixtures.createEmptyHabit(); - habit.setName("Write journal"); - - logger.logReminderScheduled(habit, time); - - String expectedMsg = "Setting alarm (2015-01-26 130000): Wri\n"; - assertLogcatContains(expectedMsg); - } - - protected void assertLogcatContains(String expectedMsg) throws IOException - { - String logcat = new AndroidBugReporter(targetContext).getLogcat(); - assertThat(logcat, containsString(expectedMsg)); - } - - protected boolean isLogcatAvailable() - { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - } -} diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt index b02e7c280..87c445d51 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/habits/list/views/CheckmarkPanelViewTest.kt @@ -76,11 +76,12 @@ class CheckmarkPanelViewTest : BaseViewTest() { assertRenders(view, "$PATH/render_different_color.png") } - @Test - fun testRender_Reversed() { - prefs.isCheckmarkSequenceReversed = true - assertRenders(view, "$PATH/render_reversed.png") - } +// // Flaky test +// @Test +// fun testRender_Reversed() { +// prefs.isCheckmarkSequenceReversed = true +// assertRenders(view, "$PATH/render_reversed.png") +// } @Test fun testRender_withOffset() { diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitLogger.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitLogger.kt deleted file mode 100644 index a248e54c1..000000000 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitLogger.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 Álinson Santos Xavier - * - * 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 . - */ - -package org.isoron.uhabits - -import android.util.* -import org.isoron.uhabits.core.* -import org.isoron.uhabits.core.models.* -import org.isoron.uhabits.core.utils.* -import java.util.* -import javax.inject.* - -@AppScope -class HabitLogger -@Inject constructor() { - - fun logReminderScheduled(habit: Habit, reminderTime: Long) { - val min = Math.min(3, habit.name.length) - val name = habit.name.substring(0, min) - val df = DateFormats.getBackupDateFormat() - val time = df.format(Date(reminderTime)) - Log.i("ReminderHelper", - String.format("Setting alarm (%s): %s", time, name)) - } -} diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java index 3fd635f22..8c110ab26 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplicationComponent.java @@ -63,8 +63,6 @@ public interface HabitsApplicationComponent HabitList getHabitList(); - HabitLogger getHabitsLogger(); - IntentFactory getIntentFactory(); IntentParser getIntentParser(); diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt index 689beb2ec..934942f15 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt @@ -25,25 +25,34 @@ import android.content.* import android.content.Context.* import android.os.Build.VERSION.* import android.os.Build.VERSION_CODES.* +import android.util.* import org.isoron.androidbase.* import org.isoron.uhabits.* import org.isoron.uhabits.core.* import org.isoron.uhabits.core.models.* import org.isoron.uhabits.core.reminders.* +import org.isoron.uhabits.core.utils.* +import java.util.* import javax.inject.* @AppScope class IntentScheduler @Inject constructor( @AppContext context: Context, - private val pendingIntents: PendingIntentFactory, - private val logger: HabitLogger + private val pendingIntents: PendingIntentFactory ) : ReminderScheduler.SystemScheduler { private val manager = context.getSystemService(ALARM_SERVICE) as AlarmManager fun schedule(timestamp: Long, intent: PendingIntent) { + Log.d("IntentScheduler", + "timestamp=" + timestamp + " current=" + System.currentTimeMillis()) + if (timestamp < System.currentTimeMillis()) { + Log.e("IntentScheduler", + "Ignoring attempt to schedule intent in the past.") + return; + } if (SDK_INT >= M) manager.setExactAndAllowWhileIdle(RTC_WAKEUP, timestamp, intent) else @@ -55,6 +64,19 @@ class IntentScheduler timestamp: Long) { val intent = pendingIntents.showReminder(habit, reminderTime, timestamp) schedule(reminderTime, intent) - logger.logReminderScheduled(habit, reminderTime) + logReminderScheduled(habit, reminderTime) + } + + override fun log(componentName: String, msg: String) { + Log.d(componentName, msg) + } + + private fun logReminderScheduled(habit: Habit, reminderTime: Long) { + val min = Math.min(5, habit.name.length) + val name = habit.name.substring(0, min) + val df = DateFormats.getBackupDateFormat() + val time = df.format(Date(reminderTime)) + Log.i("ReminderHelper", + String.format("Setting alarm (%s): %s", time, name)) } } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index c588acddd..3b45e14cc 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -49,9 +49,12 @@ class AndroidNotificationTray private val preferences: Preferences, private val ringtoneManager: RingtoneManager ) : NotificationTray.SystemTray { - private var active = HashSet() + override fun log(msg: String) { + Log.d("AndroidNotificationTray", msg) + } + override fun removeNotification(id: Int) { val manager = NotificationManagerCompat.from(context) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java index c253064f1..585857d4b 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.java @@ -85,7 +85,7 @@ public class ReminderController public void onSnoozeTimePicked(Habit habit, int hour, int minute) { - Long time = DateUtils.getUpcomingTimeInMillis(hour, minute); + long time = DateUtils.getUpcomingTimeInMillis(hour, minute); reminderScheduler.scheduleAtTime(habit, time); notificationTray.cancel(habit); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java index dff612345..55be7c6c0 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java @@ -27,6 +27,8 @@ import org.isoron.uhabits.*; import org.isoron.uhabits.core.models.*; import org.isoron.uhabits.core.utils.*; +import java.util.*; + import static android.content.ContentUris.*; /** @@ -65,8 +67,8 @@ public class ReminderReceiver extends BroadcastReceiver if (intent.getData() != null) habit = habits.getById(parseId(intent.getData())); - final Long timestamp = intent.getLongExtra("timestamp", today); - final Long reminderTime = intent.getLongExtra("reminderTime", today); + final long timestamp = intent.getLongExtra("timestamp", today); + final long reminderTime = intent.getLongExtra("reminderTime", today); try { @@ -74,6 +76,12 @@ public class ReminderReceiver extends BroadcastReceiver { case ACTION_SHOW_REMINDER: if (habit == null) return; + Log.d("ReminderReceiver", String.format( + Locale.US, + "onShowReminder habit=%d timestamp=%d reminderTime=%d", + habit.id, + timestamp, + reminderTime)); reminderController.onShowReminder(habit, new Timestamp(timestamp), reminderTime); break; diff --git a/android/uhabits-android/src/main/play/contact-email.txt b/android/uhabits-android/src/main/play/contact-email.txt new file mode 100644 index 000000000..a53c5a7be --- /dev/null +++ b/android/uhabits-android/src/main/play/contact-email.txt @@ -0,0 +1 @@ +dev@loophabits.org diff --git a/android/uhabits-android/src/main/play/default-language.txt b/android/uhabits-android/src/main/play/default-language.txt new file mode 100644 index 000000000..beb9970be --- /dev/null +++ b/android/uhabits-android/src/main/play/default-language.txt @@ -0,0 +1 @@ +en-US diff --git a/android/uhabits-android/src/main/play/listings/ar/full-description.txt b/android/uhabits-android/src/main/play/listings/ar/full-description.txt new file mode 100644 index 000000000..b172e8d54 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ar/full-description.txt @@ -0,0 +1,22 @@ +لب يساعدك على خلق والحفاظ على العادات الجيدة، مما يسمح لك لتحقيق أهدافكة. الرسوم البيانية والإحصاءات التفصيلية تبين لكم كيف تحسن عاداتك مع مرور الوقت. هو تماما خالية من الاعلانات ومفتوحة المصدر. + +واجهة بسيطة، جميلة وحديثة +لوب يحتوي على واجهة بسيطة وهي سهلة الاستخدام و تتابع نظام تصميم الماتريل دسيجن. + +نتيجة العادات +بالإضافة إلى عرض التقدم الحالي، لوب ديه خوارزمية متقدمة لحساب قوة عاداتك. كل التكرار يجعل هذه العادة أقوى، وفي كل يوم غاب يجعلها أضعف. مع ذلك غيب أيام قليلة بعد تقدم طويلة ، لن تدمر تماما تقدمك . + +الرسوم البيانية والإحصاءات المفصلة +نرى بوضوح كيف كنت قد تحسنت عاداتك بمرور الوقت مع الرسوم البيانية الجميله ومفصلة. انتقل إلى الوراء لنرى التاريخ الكامل لعاداتك. + +جداول مرنة +تؤيد كل من العادات اليومية والعادات مع جداول أكثر تعقيدا، مثل 3 مرات كل أسبوع، مرة واحدة كل أسبوعين، أو مرة كل يومين. + +تذكير +إنشاء تذكير لكل فرد من عاداتك، في ساعة اختيار من اليوم. تحقق بسهولة، رفض أو غفوة عادتك مباشرة من الإخطار، دون الحاجة إلى فتح التطبيق. + +خالية تماما من الإعلانات و المصدر المفتوح +لا توجد على الاطلاق الإعلانات والشعارات المزعجة أو أذونات إضافية في هذا التطبيق، و سوف يكون هناك أبدا. + +الأمثل للساعات الذكية +يمكن التحقق من رسائل التذكير، رفض أو غفوة عادتك مباشرة من ساعتك الاندرويد وير. diff --git a/android/uhabits-android/src/main/play/listings/ar/short-description.txt b/android/uhabits-android/src/main/play/listings/ar/short-description.txt new file mode 100644 index 000000000..1b0cb38f7 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ar/short-description.txt @@ -0,0 +1 @@ +خلق عادات جيدة وتتبع تقدمك على مر الزمن diff --git a/android/uhabits-android/src/main/play/listings/ar/title.txt b/android/uhabits-android/src/main/play/listings/ar/title.txt new file mode 100644 index 000000000..8c72c99f8 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ar/title.txt @@ -0,0 +1 @@ +لوب ملاحق العادة diff --git a/android/uhabits-android/src/main/play/listings/ca/full-description.txt b/android/uhabits-android/src/main/play/listings/ca/full-description.txt new file mode 100644 index 000000000..ca7eafd4e --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ca/full-description.txt @@ -0,0 +1,22 @@ +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. + +Senzilla, bonica i moderna interfície +Loop té una interfície minimalista que és fàcil d'utilitzar i segueix les guies de "material design". + +Puntuació d'hàbit +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. + +Gràfics i estadístiques detallades +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. + +Planificació flexible +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. + +Recordatoris +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. + +Completament de codi obert i lliure de publicitat +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. + +Optimitzat per a rellotges intel·ligents +Els recordatoris poden ser revisats, endarrerits o anul·lats directament des del teu rellotge Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/ca/short-description.txt b/android/uhabits-android/src/main/play/listings/ca/short-description.txt new file mode 100644 index 000000000..be99d3d0d --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ca/short-description.txt @@ -0,0 +1 @@ +Crea bons hàbits i segueix el seu progrés al llarg del temps (sense publicitat) diff --git a/android/uhabits-android/src/main/play/listings/ca/title.txt b/android/uhabits-android/src/main/play/listings/ca/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ca/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/cs-CZ/full-description.txt b/android/uhabits-android/src/main/play/listings/cs-CZ/full-description.txt new file mode 100644 index 000000000..5c3c74172 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/cs-CZ/full-description.txt @@ -0,0 +1,22 @@ +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. + +Jednoduché, krásné a moderní prostředí +Aplikace má minimalistický design s jednoduchým použitím. Dodržuje pravidla material designu. + +Síla zvyku +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. + +Detailní grafy a statistika +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. + +Flexibilní časový plán +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. + +Upomínky +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. + +Kompletně bez reklam a open source +Nejsou tu naprosto žádné reklamy, otravné notifikace nebo dotěrná povolení aplikace. A nikdy nebudou. Kompletní zdrojový kód je dostupný pod GPLv3. + +Optimalizované pro chytré hodinky +Upomínky mohou být potvrzen, odloženy nebo smazány přímo z tvého zařízení s Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/cs-CZ/short-description.txt b/android/uhabits-android/src/main/play/listings/cs-CZ/short-description.txt new file mode 100644 index 000000000..d504d3d96 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/cs-CZ/short-description.txt @@ -0,0 +1 @@ +Vytvoř si prospěšné návyky a sleduj jejich vývoj v průběhu času (bez reklam) diff --git a/android/uhabits-android/src/main/play/listings/cs-CZ/title.txt b/android/uhabits-android/src/main/play/listings/cs-CZ/title.txt new file mode 100644 index 000000000..e4e2e5672 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/cs-CZ/title.txt @@ -0,0 +1 @@ +Loop - Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/de-DE/full-description.txt b/android/uhabits-android/src/main/play/listings/de-DE/full-description.txt new file mode 100644 index 000000000..f838ff590 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/de-DE/full-description.txt @@ -0,0 +1,22 @@ +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. + +Einfaches, schönes und modernes Oberfläche +Loop hat eine minimale Oberfläche und ist deshalb einfach zu nutzen. Es folgt dem material Design. + +Habit Punkte +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. + +Statistiken +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. + +Flexible Zeiten +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. + +Erinnerungen +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. + +Komplett werbefrei und Open Source +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. + +Optimiert für Smartwatches +Erinnerungen können direkt von der Android Wear watch kontrolliert, pausiert, oder verschoben werden. diff --git a/android/uhabits-android/src/main/play/listings/de-DE/short-description.txt b/android/uhabits-android/src/main/play/listings/de-DE/short-description.txt new file mode 100644 index 000000000..7190b438a --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/de-DE/short-description.txt @@ -0,0 +1 @@ +Nimm gute Gewohnheiten an und verfolge deinen Fortschritt (ohne Werbung) diff --git a/android/uhabits-android/src/main/play/listings/de-DE/title.txt b/android/uhabits-android/src/main/play/listings/de-DE/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/de-DE/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/en-US/full-description.txt b/android/uhabits-android/src/main/play/listings/en-US/full-description.txt new file mode 100644 index 000000000..e47821d8d --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/en-US/full-description.txt @@ -0,0 +1,28 @@ +Loop helps you create and maintain good habits, allowing you to achieve your long-term goals. Detailed charts and statistics show you how your habits improved over time. The app is completely ad-free, open source and it respects your privacy. + +Simple, beautiful and modern interface +Loop has a minimalistic interface that is very easy to use and follows the material design guidelines. + +Habit score +In addition to showing your current streak, Loop has an advanced formula for calculating the strength of your habits. Every repetition makes your habit stronger, and every missed day makes it weaker. A few missed days after a long streak, however, will not completely destroy your entire progress, unlike other don't-break-the-chain apps. + +Detailed graphs and statistics +Clearly see how your habits improved over time with detailed charts and statistics. Scroll back to see the complete history of your habits. + +Flexible schedules +Supports not only daily habits, but also habits with more complex schedules, such as 3 times every week; one time every other week; or every other day. + +Reminders +Create an individual reminder for each habit, at a chosen hour of the day. Easily check, dismiss or snooze your habit directly from the notification, without opening the app. + +Widgets +Track your habits directly from your home screen, with beautiful and colorful widgets. + +Completely ad-free and open source +There are absolutely no advertisements, annoying notifications or intrusive permissions in this app, and there will never be. The complete source code is available under an open-source license (GPLv3). + +Works offline and respects your privacy +Loop doesn't require an Internet connection or online account registration. Your confidential habit data never leaves your phone. Neither the developers nor any third-parties have access to it. + +Take your data with you +If you want to further analyze your data or move it to another service, Loop allows you to export it to spreadsheets (CSV) or to a database format (SQLite). diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/feature-graphic/1.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/feature-graphic/1.png new file mode 100644 index 000000000..c25748549 Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/feature-graphic/1.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/icon/1.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/icon/1.png new file mode 100644 index 000000000..0a94539ab Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/icon/1.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/1.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/1.png new file mode 100644 index 000000000..dc651abc0 Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/1.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/2.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/2.png new file mode 100644 index 000000000..edabc5d20 Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/2.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/3.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/3.png new file mode 100644 index 000000000..4c821d874 Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/3.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/4.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/4.png new file mode 100644 index 000000000..5a9432921 Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/4.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/5.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/5.png new file mode 100644 index 000000000..326ae0d55 Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/5.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/6.png b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/6.png new file mode 100644 index 000000000..36579038a Binary files /dev/null and b/android/uhabits-android/src/main/play/listings/en-US/graphics/phone-screenshots/6.png differ diff --git a/android/uhabits-android/src/main/play/listings/en-US/short-description.txt b/android/uhabits-android/src/main/play/listings/en-US/short-description.txt new file mode 100644 index 000000000..d19b7d128 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/en-US/short-description.txt @@ -0,0 +1 @@ +Create good habits and track their progress over time (ad-free) diff --git a/android/uhabits-android/src/main/play/listings/en-US/title.txt b/android/uhabits-android/src/main/play/listings/en-US/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/en-US/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/es-ES/full-description.txt b/android/uhabits-android/src/main/play/listings/es-ES/full-description.txt new file mode 100644 index 000000000..30d0f120d --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/es-ES/full-description.txt @@ -0,0 +1,22 @@ +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. + +Una interfaz simple, bella y moderna +Loop tiene una interfaz minimalista que es fácil de usar y sigue los principios del material design. + +Puntuación del hábito +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. + +Detallados gráficos y estadísticas +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. + +Horarios flexibles +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. + +Recordatorios +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. + +Completamente sin anuncios y de código abierto +No existe ningún tipo de publicidad, notificaciones molestas o permisos intrusivos, y nunca los habrá. Todo el código está disponible bajo GPLv3. + +Optimizado para smartwatches +Los recordatorios se pueden marcar, posponer o descartar directamente desde tu reloj Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/es-ES/short-description.txt b/android/uhabits-android/src/main/play/listings/es-ES/short-description.txt new file mode 100644 index 000000000..b8367a8a3 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/es-ES/short-description.txt @@ -0,0 +1 @@ +Crea buenos hábitos y haz un seguimiento de su progreso a lo largo del tiempo diff --git a/android/uhabits-android/src/main/play/listings/es-ES/title.txt b/android/uhabits-android/src/main/play/listings/es-ES/title.txt new file mode 100644 index 000000000..55115936a --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/es-ES/title.txt @@ -0,0 +1 @@ +Loop - Analizador de Hábitos diff --git a/android/uhabits-android/src/main/play/listings/fr-FR/full-description.txt b/android/uhabits-android/src/main/play/listings/fr-FR/full-description.txt new file mode 100644 index 000000000..8de1c3df6 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/fr-FR/full-description.txt @@ -0,0 +1,22 @@ +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 s’améliorent au fil du temps. C'est totalement sans pub et open source. + +Simple, beau avec une interface moderne +Loop a une interface minimaliste, facile à utiliser et qui suit les règles de material design. + +Score d'habitude +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. + +Graphiques détaillés et statistiques +Observez clairement comment vos habitudes s’amé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. + +Calendrier flexible +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. + +Rappel +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. + +Entièrement sans pub et open-source +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. + +Optimisée pour les montres android +Les rappels peuvent être cochés, reportés ou supprimés directement à partir de votre montre Android diff --git a/android/uhabits-android/src/main/play/listings/fr-FR/short-description.txt b/android/uhabits-android/src/main/play/listings/fr-FR/short-description.txt new file mode 100644 index 000000000..fd674c71f --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/fr-FR/short-description.txt @@ -0,0 +1 @@ +Créez des bonnes habitudes et suivez leurs avancées au fil du temps (sans pub) diff --git a/android/uhabits-android/src/main/play/listings/fr-FR/title.txt b/android/uhabits-android/src/main/play/listings/fr-FR/title.txt new file mode 100644 index 000000000..1979ccc4d --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/fr-FR/title.txt @@ -0,0 +1 @@ +Loop - Suivi d'habitudes diff --git a/android/uhabits-android/src/main/play/listings/hr/full-description.txt b/android/uhabits-android/src/main/play/listings/hr/full-description.txt new file mode 100644 index 000000000..141410205 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/hr/full-description.txt @@ -0,0 +1,21 @@ +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. + +Jednostavno, lijepo i moderno sučelje. +Loop sadrži minimalistično sučelje jednostavno za korištenje koje prati smjernice Material Design-a. + +Rezultat navike +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. + +Detaljni grafovi i statistike +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. + +Fleksibilno planiranje +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. + +Podsjetnici +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. + +Optimizirano za pametne satove +Podsjetnici se mogu provjeravati, odgoditi ili odbaciti direktno sa vašeg Android Wear sata. + +Potpuno bez oglasa i otvorenog izvora koda diff --git a/android/uhabits-android/src/main/play/listings/hr/short-description.txt b/android/uhabits-android/src/main/play/listings/hr/short-description.txt new file mode 100644 index 000000000..4eba451f4 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/hr/short-description.txt @@ -0,0 +1 @@ +Stvorite dobre navike i pratite njihov napredak (bez reklama) diff --git a/android/uhabits-android/src/main/play/listings/hr/title.txt b/android/uhabits-android/src/main/play/listings/hr/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/hr/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/id/full-description.txt b/android/uhabits-android/src/main/play/listings/id/full-description.txt new file mode 100644 index 000000000..821a8af9e --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/id/full-description.txt @@ -0,0 +1,23 @@ +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. + +Sederhana, minimalis dengan balutan antarmuka yang modern +Loop memiliki tampilan minimalis yang mudah digunakan dan mengikuti panduan material design. + +Skor Kebiasaan +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. + +Detail Grafik dan Statistik +Lihat perkembangan Kebiasaan dari waktu ke waktu dengan tampilan yang menarik dan detail. Geser ke bawah untuk melihat seluruh catatan Kebiasaan Anda. + +Pengaturan jadwal fleksibel +Mendukung kebiasaan harian dan kebiasaan dengan penjadwalan yang kompleks, seperti 3 kali dalam setiap minggu; 2 minggu sekali; hingga 2 hari sekali. + +Pengingat +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. + +Bebas dari iklan dan open-source +Tidak ada iklan, notifikasi menyebalkan dan juga hak akses yang tidak dibutuhkan. +Kode aplikasi tersedia dengan lisensi GPLv3 + +Mendukung Smartwatch +Anda dapat dengan mudah mengecek, menunda ataupun membatalkan pengingat melalui smartwatch Anda. diff --git a/android/uhabits-android/src/main/play/listings/id/short-description.txt b/android/uhabits-android/src/main/play/listings/id/short-description.txt new file mode 100644 index 000000000..3fb70de63 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/id/short-description.txt @@ -0,0 +1 @@ +Buat Kebiasaan baik dan catat perkembangannya setiap waktu (bebas iklan) diff --git a/android/uhabits-android/src/main/play/listings/id/title.txt b/android/uhabits-android/src/main/play/listings/id/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/id/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/it-IT/full-description.txt b/android/uhabits-android/src/main/play/listings/it-IT/full-description.txt new file mode 100644 index 000000000..8b2b58f65 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/it-IT/full-description.txt @@ -0,0 +1,18 @@ +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. + +Interfaccia semplice e moderna Loop ha un'interfaccia minimale che è semplice da usare e segue le linee guida del Material Design + +Forza dell'abitudine +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. + +Grafici dettagliati e statistiche 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. + +Programmi flessibili Supporto per abitudini sia giornaliere che con organizzazioni più complesse, come 3 volte alla settimana; una volta ogni 2 settimane; ogni due giorni... + +Promemoria +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. + +Completamente gratuito ed opensource +Non ci sono pubblicità, notifiche invasive o permessi intrusivi e mai ce ne saranno. Il codice sorgente completo è disponibile sotto licenza GPLv3. + +Ottimizzata per gli smartwatch I promemoria possono essere completati, ritardati o ignorati direttamente dal tuo orologio Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/it-IT/short-description.txt b/android/uhabits-android/src/main/play/listings/it-IT/short-description.txt new file mode 100644 index 000000000..63cc815b8 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/it-IT/short-description.txt @@ -0,0 +1 @@ +Acquisisci nuove abitudini e traccia il tuo progresso (senza pubblicità) diff --git a/android/uhabits-android/src/main/play/listings/it-IT/title.txt b/android/uhabits-android/src/main/play/listings/it-IT/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/it-IT/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/ja-JP/full-description.txt b/android/uhabits-android/src/main/play/listings/ja-JP/full-description.txt new file mode 100644 index 000000000..5d15de144 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ja-JP/full-description.txt @@ -0,0 +1,22 @@ +ループは、良い習慣を作って、維持するのに役立ちます。あなたの長期的な目標を達成することができます。詳細なグラフや統計情報が、時間をかけてあなたの習慣が改善された様子を示します。完全に広告フリーでオープンソースです。 + +シンプルで、美しく、モダンなインターフェース +ループは、使いやすく、マテリアルデザインのガイドラインに従った、最小限のインターフェースです。 + +習慣のスコア +ループは、現在の連続記録を示すことに加えて、習慣の強さを計算するための高度なアルゴリズムを持っています。繰り返しがあなたの習慣を強くし、忘れた日は弱くなります。長い連続記録の後に、少し忘れた日があっても、全体の進捗状況を完全に失うわけではありません。 + +詳細なグラフと統計情報 +美しくて詳細なグラフで、あなたの習慣が時間をかけて改善された様子がはっきりわかります。スクロールで戻ると、あなたの習慣の完全な履歴を参照することができます。 + +柔軟なスケジュール +毎日の習慣と、毎週 3 回、隔週に 1 回、または一日おきなどの、より複雑なスケジュールの習慣の両方をサポートします。 + +リマインダー +1 日の選択した時間で、それぞれの習慣に個々のリマインダーを作成します。アプリを開かずに、通知から直接、簡単に習慣をチェック、解除、またはスヌーズすることができます。 + +完全に広告フリーでオープンソース +このアプリは、広告、迷惑な通知、押し付けがましいアクセス許可は全くありませんし、そうなることもありません。GPLv3 の下で全てのソースコードが利用可能です。 + +スマートウォッチの最適化 +Android Wear 端末から直接、リマインダーをチェック、スヌーズ、解除することができます。 diff --git a/android/uhabits-android/src/main/play/listings/ja-JP/short-description.txt b/android/uhabits-android/src/main/play/listings/ja-JP/short-description.txt new file mode 100644 index 000000000..fb9e77b54 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ja-JP/short-description.txt @@ -0,0 +1 @@ +良い習慣を作って、時間をかけてその進捗状況を追跡します (広告なし) diff --git a/android/uhabits-android/src/main/play/listings/ja-JP/title.txt b/android/uhabits-android/src/main/play/listings/ja-JP/title.txt new file mode 100644 index 000000000..1b2c6f734 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ja-JP/title.txt @@ -0,0 +1 @@ +ループ習慣トラッカー diff --git a/android/uhabits-android/src/main/play/listings/ko-KR/full-description.txt b/android/uhabits-android/src/main/play/listings/ko-KR/full-description.txt new file mode 100644 index 000000000..3fb7d24fb --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ko-KR/full-description.txt @@ -0,0 +1,20 @@ +Loop은 습관을 만들고 유지하도록 도와주어, 장기간 목표를 달성하도록 합니다. 그래프와 통계를 보고 습관이 만들어지는 과정을 보세요. 오프소스이고, 무광고입니다. + +아름답고 심플한 디자인 +Loop은 Material디자인을 따라 사용이 편합니다. + +습관 포인트 +얼마나 오랫동안 습관을 유지했는지 보여줌과 동시에, Loop은 특화된 알고리듬으로 습관의 견고함을 계산합니다. 반복할 수록 강해지고, 빠뜨린 날들이 많아질 수록 포인트는 낮아집니다. 하지만, 오랫동안 유지된 습관은 몇 일을 빠뜨렸다고 해서 포인트가 급강하하지는 않습니다. + +그래프와 통계 +습관이 어떤 과정을 거쳐서 완성되는지 그래프를 보면 알 수 있습니다. +스크롤해서 장기간의 과정을 볼 수 있습니다. + +여러 종류의 스케줄 조정가능 +매일 습관, 혹은 일주일에 3번; 2주에 한번; 같은 여러 종류의 스케줄을 만들 수 있습니다. + +오픈소스, 무광고 +광고, 귀찮은 스팸, 비정상적인 정보요구는 없습니다, 앞으로 쭉. 모든 소스코드는 GPLv3로 라이센스되었습니다. + +스마트시계에 최적화 +안드로이드 시계에서 바로 알림을 확인, 미루기 혹은 무시할 수 있습니다. diff --git a/android/uhabits-android/src/main/play/listings/ko-KR/short-description.txt b/android/uhabits-android/src/main/play/listings/ko-KR/short-description.txt new file mode 100644 index 000000000..ee87e4f1b --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ko-KR/short-description.txt @@ -0,0 +1 @@ +좋은 습관을 만들고 관리하세요. (광고 없음) diff --git a/android/uhabits-android/src/main/play/listings/ko-KR/title.txt b/android/uhabits-android/src/main/play/listings/ko-KR/title.txt new file mode 100644 index 000000000..f672ecc29 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ko-KR/title.txt @@ -0,0 +1 @@ +Loop 습관제조기 diff --git a/android/uhabits-android/src/main/play/listings/pl-PL/full-description.txt b/android/uhabits-android/src/main/play/listings/pl-PL/full-description.txt new file mode 100644 index 000000000..b8128e5b6 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/pl-PL/full-description.txt @@ -0,0 +1,22 @@ +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. + +Prosty, piękny i nowoczesny interfejs +Loop posiada minimalistyczny interfejs, który jest prosty do użycia i przestrzega zasad material design. + +Punkty nawyku +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. + +Szczegółowe grafiki i statystyki +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. + +Elastyczne plany +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. + +Przypomnienia +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. + +Całkowicie bez reklam i open source +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. + +Zoptymalizowana pod smartwatche +Przypomnienia można sprawdzić, uśpić czy usunąć bezpośrednio z twojego zegarka Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/pl-PL/short-description.txt b/android/uhabits-android/src/main/play/listings/pl-PL/short-description.txt new file mode 100644 index 000000000..9f1e2979a --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/pl-PL/short-description.txt @@ -0,0 +1 @@ +Twórz dobre nawyki i śledź ich postęp (bez reklam) diff --git a/android/uhabits-android/src/main/play/listings/pl-PL/title.txt b/android/uhabits-android/src/main/play/listings/pl-PL/title.txt new file mode 100644 index 000000000..dc0f7be31 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/pl-PL/title.txt @@ -0,0 +1 @@ +Śledzenie Nawyków Loop diff --git a/android/uhabits-android/src/main/play/listings/pt-BR/full-description.txt b/android/uhabits-android/src/main/play/listings/pt-BR/full-description.txt new file mode 100644 index 000000000..8c061b02d --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/pt-BR/full-description.txt @@ -0,0 +1,19 @@ +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. + +Interface bonita, moderna e simples +Loop tem uma interface minimalista bem simples de se usar, e segue o novo visual Material Design. + +Estabilidade dos hábitos +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. + +Gráficos e estatísticas detalhadas +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. + +Rotina flexível +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. + +Lembretes +É 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. + +Completamente sem propagandas e Open Source +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. diff --git a/android/uhabits-android/src/main/play/listings/pt-BR/short-description.txt b/android/uhabits-android/src/main/play/listings/pt-BR/short-description.txt new file mode 100644 index 000000000..836550f64 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/pt-BR/short-description.txt @@ -0,0 +1 @@ +Forme bons hábitos e acompanhe seu progresso ao passar do tempo (sem anúncios) diff --git a/android/uhabits-android/src/main/play/listings/pt-BR/title.txt b/android/uhabits-android/src/main/play/listings/pt-BR/title.txt new file mode 100644 index 000000000..8fe4de662 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/pt-BR/title.txt @@ -0,0 +1 @@ +Loop - Acompanhador de Hábitos diff --git a/android/uhabits-android/src/main/play/listings/ru-RU/full-description.txt b/android/uhabits-android/src/main/play/listings/ru-RU/full-description.txt new file mode 100644 index 000000000..7ac62ada0 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ru-RU/full-description.txt @@ -0,0 +1,22 @@ +"Трекер привычек Loop" поможет вам завести и поддерживать полезные привычки, позволяя достичь долгосрочных целей. Детализированные диаграммы и статистика покажут, как ваши привычки закрепились со временем. Приложение не содержит рекламы и является ПО с открытым исходным кодом. + +Простой, красивый и современный интерфейс +У приложения минималистичный интерфейс, который лёгок в использовании и придерживается руководства по Material Design. + +Оценка привычек +В дополнение к отображению текущего рекорда повторений, приложение имеет передовой алгоритм расчёта "силы" ваших привычек. Каждое повторение делает вашу привычку "сильнее", а каждый пропуск "слабее". Несколько пропущенных дней после долгих успешных повторений, однако, не загубят ваши успехи полностью. + +Детализированные диаграммы и статистика +При помощи красивых и детализированных диаграмм вы с лёгкостью можете просмотреть, как ваши привычки закрепились со временем. Просмотрите полную историю ваших привычек, пролистав её. + +Гибкий график +Поддерживаются как ежедневные привычки, так и привычки с более сложным графиком. Например: 3 раза в неделю; один раз каждую неделю; через день. + +Напоминания +Создавайте отдельные для каждой привычки напоминания в выбранное время дня. С лёгкостью отмечайте, пропускайте или откладывайте выполнение привычки прямо из уведомления - без открытия приложения. + +Полное отсутствие рекламы и открытый исходный код +В приложении совершенно нет рекламы, назойливых уведомлений или лишних разрешений. И их никогда не будет. Весь исходный код доступен под лицензией GPLv3. + +Оптимизировано для "умных" часов +Напоминания могут быть отмечены, отложены или пропущены прямо с ваших часов Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/ru-RU/short-description.txt b/android/uhabits-android/src/main/play/listings/ru-RU/short-description.txt new file mode 100644 index 000000000..dd97820b6 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ru-RU/short-description.txt @@ -0,0 +1 @@ +Заводите полезные привычки и отслеживайте свои успехи (без рекламы) diff --git a/android/uhabits-android/src/main/play/listings/ru-RU/title.txt b/android/uhabits-android/src/main/play/listings/ru-RU/title.txt new file mode 100644 index 000000000..fdd07fb61 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/ru-RU/title.txt @@ -0,0 +1 @@ +Трекер привычек Loop diff --git a/android/uhabits-android/src/main/play/listings/sl/full-description.txt b/android/uhabits-android/src/main/play/listings/sl/full-description.txt new file mode 100644 index 000000000..14b5c5e20 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sl/full-description.txt @@ -0,0 +1,22 @@ +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. + +Enostaven, lep in sodoben vmesnik +Loop ima minimalističen vmesnik, ki je preprost za uporabo in sledi smernicam Material design. + +Ocena navade +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. + +Podrobni grafi in statistike +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. + +Prilagodljivi urniki +Podpira tako vsakdanje navade in navade z bolj zapletenimi urniki, kot so 3-krat na teden; enkrat vsak drugi teden; ali vsak drugi dan. + +Opomniki +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. + +Popolnoma brez oglasov in odprtokodno +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. + +Optimirano za pametne ure +Opomnike lahko preverite, jih date v dremež ali pa zavrzite neposredno iz vaše Android Wear ure. diff --git a/android/uhabits-android/src/main/play/listings/sl/short-description.txt b/android/uhabits-android/src/main/play/listings/sl/short-description.txt new file mode 100644 index 000000000..848832a92 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sl/short-description.txt @@ -0,0 +1 @@ +Ustvarite dobre navade in spremljajte njihov napredek skozi čas (brez reklam) diff --git a/android/uhabits-android/src/main/play/listings/sl/title.txt b/android/uhabits-android/src/main/play/listings/sl/title.txt new file mode 100644 index 000000000..401c2940f --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sl/title.txt @@ -0,0 +1 @@ +Loop Sledilnik Navad diff --git a/android/uhabits-android/src/main/play/listings/sr/full-description.txt b/android/uhabits-android/src/main/play/listings/sr/full-description.txt new file mode 100644 index 000000000..5bef01163 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sr/full-description.txt @@ -0,0 +1,22 @@ +Loop вам помаже да створите и одржавате здраве навике, самим тим и да достигнете дугорочне циљеве. Детаљна статистика и графикони показују вам колико су се ваше навике временом побољшале. Апликација је отвореног кода и не садржи огласе. + +Једноставан, леп и модеран дизајн +Loop има минималистички интерфејс који је једноставан за коришћење и прати смернице за материјални дизајн. + +Оцена навике +Поред приказа тренутног низа, Loop поседује напредни алгоритам за израчунавање снаге ваших навика. Ваша навика са сваким понављањем постаје јача, а са сваким пропуштеним даном слабија. Неколико пропуштених дана након дугог низа, пак, неће у потпуности упропастити ваш резултат. + +Детаљни графикони и статистика +Пратите свој напредак уз лепе и детаљне графиконе. Вратите се уназад да бисте видели целу историју навика. + +Флексибилни распоред +Подржава како дневне навике, тако и оне са сложенијим понављањем (трипут недељно, једанпут сваке друге недеље, сваки други дан и сл.). + +Подсетници +Направите појединачни подсетник за сваку навику у жељено доба дана. С лакоћом маркирајте, одложите или откажите навику директно из обавештења, без отварања апликације. + +У потпуности отвореног кода и без огласа +Апликација не садржи никакве огласе, досадна обавештења или наметљиве дозволе; никада и неће. Изворни кôд је у целости доступан под лиценцом GPLv3. + +Оптимизовано за паметне сатове +Навике можете маркирати, одложити или отказати директно помоћу Android Wear сата. diff --git a/android/uhabits-android/src/main/play/listings/sr/short-description.txt b/android/uhabits-android/src/main/play/listings/sr/short-description.txt new file mode 100644 index 000000000..ff0c42571 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sr/short-description.txt @@ -0,0 +1 @@ +Створите здраве навике и пратите напредак (без огласа). diff --git a/android/uhabits-android/src/main/play/listings/sr/title.txt b/android/uhabits-android/src/main/play/listings/sr/title.txt new file mode 100644 index 000000000..ee9265f55 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sr/title.txt @@ -0,0 +1 @@ +Loop – праћење навика diff --git a/android/uhabits-android/src/main/play/listings/sv-SE/full-description.txt b/android/uhabits-android/src/main/play/listings/sv-SE/full-description.txt new file mode 100644 index 000000000..66d7f3f00 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sv-SE/full-description.txt @@ -0,0 +1,22 @@ +Loop Hjälper dig att skapa och underhålla bra vanor, genom att tillåta dig arkivera dina långtidsvanor. Detaljerade grafer och statistik visar dig hur dina vanor har förbättrats över tid. Det är helt reklamfritt och öppen källkod. + +Enkelt, snyggt och modernt användargränssnitt +Loop har minimalistiskt gränssnitt som är enkel att använda och följer material design riktlinjer. + +Vanepoäng +Förutom att visa din nuvarande aktivitet har Loop en avancerad algoritm som räknar ut styrkan i dina vanor. Varje repetition gör din vana starkare och varje missad dag gör den svagare. Ett par missar efter en lång, oavbruten aktivitet kommer dock inte att helt förstöra dina framsteg. + +Detaljerade grafer och statistik +Tydligt se hur dina vanor förbättras över tiden med fina och detaljerade grafer. Skrolla tillbaka för att din fullständiga historik av dina vanor. + +Flexibelt schema +Stödjer både dagliga vanor och avancerade vanor, som till exempel tre gånger per vecka, en gång varje vecka eller varannan dag. + +Påminnelser +Skapa en påminnelse för varje vana. Du kan enkelt bocka av, ta bort eller skjuta upp din vana direkt från notifikationsfältet. + +Helt reklamfri och öppen källkod +Det är absolut ingen reklam, störande notifikationer eller onödiga behörighetskrav för den här appen, och det kommer aldrig att bli. Hela källkoden finns tillgänglig under GPLv3. + +Optimerad för smartklockor +Påminnelser kan kollas upp, snoozade eller tas bort direkt från din Android Wear enhet. diff --git a/android/uhabits-android/src/main/play/listings/sv-SE/short-description.txt b/android/uhabits-android/src/main/play/listings/sv-SE/short-description.txt new file mode 100644 index 000000000..d6002183a --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sv-SE/short-description.txt @@ -0,0 +1 @@ +Skapa bra vanor och följ deras utveckling över tid. (reklamfri) diff --git a/android/uhabits-android/src/main/play/listings/sv-SE/title.txt b/android/uhabits-android/src/main/play/listings/sv-SE/title.txt new file mode 100644 index 000000000..027232a12 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/sv-SE/title.txt @@ -0,0 +1 @@ +Loop Habit Tracker diff --git a/android/uhabits-android/src/main/play/listings/tr-TR/full-description.txt b/android/uhabits-android/src/main/play/listings/tr-TR/full-description.txt new file mode 100644 index 000000000..4dd875d5a --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/tr-TR/full-description.txt @@ -0,0 +1,22 @@ +İyi alışkanlar kazanmanı ve sürdürmene yardımcı olur, uzun dönemli hedeflerini başarmanı sağlar. Ayrıntılı çizelge ve istatistikler, zaman içinde alışkanlıklarını nasıl geliştiğini gösterir. Tamamen reklamsız ve açık kaynak. + +Basit, güzel ve çağdaş arayüz +Kullanımı kolay sade arayüze sahiptir ve material design kurallarını takip eder. + +Alışkanlık Puanı +Alışkanlıklarının dayanımını hesaplamak için gelişmiş algoritmaya sahiptir. Her tekrar alışkanlığını güçlendirir ve her iptal zayıflatır. Uzun süre etkinlikten sonra birkaç gün devamsızlık, tüm gelişmenizi tamamen etkilemeyecek. + +Ayrıntılı çizelgeler ve istatistikler +Güzel ve ayrıntılı çizelgeler ile alışkanlıklarının zaman içinde nasıl geliştiğini açıkça görebilirsin. Alışkanlıklarının geçmişini tamamen görmek için geriye sürükle. + +Esnek zamanlamalar +Günlük alışkanlanlıklar ve haftada 3 kez, diğer haftalarda bir kez veya diğer hergün gibi daha gelişmiş zamanlamalı alışkanlıkları destekler. + +Hatırlatmalar +Herbir alışkanlık için seçtiğin gün ve saatte ayrı hatırlatma oluştur. Kolayca uygulamayı açmadan, bildirimlerden alışkanlıklarını yapıldı, iptal et veya ertele olarak işaretle. + +Tamamen reklamsız ve açık kaynak +Bu uygulama içinde kesinlikle hiç reklam yok, can sıkıcı bildirimler veya zorunlu izinler yok ve asla da olmayacak. Kaynak kodun tamamı GPLv3 özgür yazılım lisansı kapsamındadır. + +Akıllı saatler için uyarlandı +Android Wear saatinden, hatırlatmaları yapıldı, ertele veya iptal edebilirsin. diff --git a/android/uhabits-android/src/main/play/listings/tr-TR/short-description.txt b/android/uhabits-android/src/main/play/listings/tr-TR/short-description.txt new file mode 100644 index 000000000..e9d4f6165 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/tr-TR/short-description.txt @@ -0,0 +1 @@ +İyi alışkanlıklar kazan ve gelişmesini takip et (reklamsız) diff --git a/android/uhabits-android/src/main/play/listings/tr-TR/title.txt b/android/uhabits-android/src/main/play/listings/tr-TR/title.txt new file mode 100644 index 000000000..4ce793ee7 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/tr-TR/title.txt @@ -0,0 +1 @@ +Loop Alışkanlık Takip diff --git a/android/uhabits-android/src/main/play/listings/uk/full-description.txt b/android/uhabits-android/src/main/play/listings/uk/full-description.txt new file mode 100644 index 000000000..74e989bcf --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/uk/full-description.txt @@ -0,0 +1,22 @@ +Трекер звичок Loop допоможе вам розвивати та підтримувати хороші звички, що дозволить вам досягнути ваших довгострокових цілей. Докладні графіки та статистичні дані показують вам, як ваші звички покращилися з часом. Трекер не містить реклами і є програмою з відкритим вихідним кодом. + +Простий, красивий і сучасний інтерфейс +Loop має легкий у використанні мінімалістичний інтерфейс, що відповідає принципам Material Design. + +Оцінка звичок +На додаток до відображення поточної серії повторень, програма має передовий алгоритм розрахунку "сили" ваших звичок. Кожне повторення робить вашу звичку "сильніше", а кожний пропуск - "слабкіше". Проте, кілька пропущених днів після тривалої серії повторень не зведуть ваші успіхи повністю нанівець. + +Детальні діаграми і статистичні дані +За допомогою красивих і деталізованих діаграм ви з легкістю можете переглянути, як ваші звички закріпилися з часом. Прокрутіть назад, щод переглянути повну історію ваших звичок. + +Гнучкий графік +Підтримуються як щоденні звички, так і звички з більш складними графіками, наприклад: 3 рази на тиждень, один раз на два тижні, через день. + +Нагадування +Створюйте окремі нагадування для кожної звички в певні години дня. З легкістю відмічайте, пропускайте або відкладайте виконання звички безпосередньо із повідомлення, не відкриваючи програму. + +Повна відсутність реклами та відкритий вихідний код +У програмі абсолютно немає реклами, дратівливих повідомлень або нав'язливих дозволів,і ніколи не буде. Весь вихідний код доступний на умовах ліцензії GPLv3. + +Оптимізовано для "розумних" годинників +Нагадування можуть бути відмічені, відкладені або пропущені безпосередньо з вашого годинника Android Wear. diff --git a/android/uhabits-android/src/main/play/listings/uk/short-description.txt b/android/uhabits-android/src/main/play/listings/uk/short-description.txt new file mode 100644 index 000000000..86c9dbbda --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/uk/short-description.txt @@ -0,0 +1 @@ +Розвивайте корисні звички і відстежуйте свої успіхи (без реклами) diff --git a/android/uhabits-android/src/main/play/listings/uk/title.txt b/android/uhabits-android/src/main/play/listings/uk/title.txt new file mode 100644 index 000000000..95db6e1d8 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/uk/title.txt @@ -0,0 +1 @@ +Трекер звичок Loop diff --git a/android/uhabits-android/src/main/play/listings/zh-CN/full-description.txt b/android/uhabits-android/src/main/play/listings/zh-CN/full-description.txt new file mode 100644 index 000000000..c115bba42 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/zh-CN/full-description.txt @@ -0,0 +1,19 @@ +循环帮助你建立和维持好习惯,达到长期目标。详细的图片和数据显示你的进步。完全无广告和开源软件。 + +简单,美观,现代的界面 +微型界面易于应用。 + + 习惯分数 +除了显示你目前的习惯连胜,循环习惯记录有高级的算法计算你的习惯强度。每重复一次习惯能使你的习惯强度加强,每次错过会使习惯强度减弱。然而,几次错过并不会完全破坏你整个的进步。 + + 详细的图片和数据分析 +详细的图片能清晰的显示随着时间你习惯的进步。往后滚动屏幕可以看完整的历史纪录。 + +提醒 +在可以选择为每个习惯设置特定的个人提醒。不需要打开应用就可以记录,忽略,或者推迟的习惯。 + +可以用在智能手表上 +提醒可以直接在安卓手表上 记录,忽略,或者推迟。 + +完全无广告和开源软件 +完全无广告和烦人的提醒,并且永远也不会有。完整的代码在GPLv3。 diff --git a/android/uhabits-android/src/main/play/listings/zh-CN/short-description.txt b/android/uhabits-android/src/main/play/listings/zh-CN/short-description.txt new file mode 100644 index 000000000..70ff5eff1 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/zh-CN/short-description.txt @@ -0,0 +1 @@ +建立好习惯且随着时间记录你的进步(无广告) diff --git a/android/uhabits-android/src/main/play/listings/zh-CN/title.txt b/android/uhabits-android/src/main/play/listings/zh-CN/title.txt new file mode 100644 index 000000000..cb1a66e48 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/zh-CN/title.txt @@ -0,0 +1 @@ +Loop 循环习惯记录 diff --git a/android/uhabits-android/src/main/play/listings/zh-TW/full-description.txt b/android/uhabits-android/src/main/play/listings/zh-TW/full-description.txt new file mode 100644 index 000000000..c040c17f6 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/zh-TW/full-description.txt @@ -0,0 +1,22 @@ +習以為常幫助你建立和維持好習慣,達到長期目標。詳細的圖片和數字顯示出你的進步。完成無廣告的開源軟體。 + +簡單,美觀,時尚的界面 +輕量型界面易於使用。 + +習慣分數 +除了顯示你目前的習慣連勝,循環記錄有高級的演算法計算你的習慣強度。每完成一次能使你的習慣強度增加,每次錯過則會減弱。然而,幾次錯過並不會影響你的習慣進步。 + +詳細的圖片和資料分析 +詳細的圖片能顯示出你的進步。往後滑動可以查看完整的歷史記錄。 + +靈活的時間表 +支援日常習慣或者是更複雜的時間間隔(例如每周3次,每周1次) + +提醒 +可以選擇為每個習慣加入提醒。不需要打開程式就可以 記錄、忽略或者是延遲習慣。 + +完全無廣告和開源軟體 +永遠不會有廣告和煩人的提醒。完整的程式碼在GPLv3。 + +可以用在智慧型手錶上 +提醒可以直接在android手錶上 記錄、忽略,或者延遲。 diff --git a/android/uhabits-android/src/main/play/listings/zh-TW/short-description.txt b/android/uhabits-android/src/main/play/listings/zh-TW/short-description.txt new file mode 100644 index 000000000..5e98cea2f --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/zh-TW/short-description.txt @@ -0,0 +1 @@ +建立好新習慣並隨著時間進步 (無廣告) diff --git a/android/uhabits-android/src/main/play/listings/zh-TW/title.txt b/android/uhabits-android/src/main/play/listings/zh-TW/title.txt new file mode 100644 index 000000000..36c3b6802 --- /dev/null +++ b/android/uhabits-android/src/main/play/listings/zh-TW/title.txt @@ -0,0 +1 @@ +Loop 習以為常 diff --git a/android/uhabits-android/src/main/play/release-notes/en-US/alpha.txt b/android/uhabits-android/src/main/play/release-notes/en-US/alpha.txt new file mode 100644 index 000000000..e5eea79b4 --- /dev/null +++ b/android/uhabits-android/src/main/play/release-notes/en-US/alpha.txt @@ -0,0 +1,12 @@ +1.8.2: +* Fix issues with reminders +* Fix crash (HUAWEI) +1.8: +* New bar chart showing number of repetitions performed each week, month or year +* Performing habits on irregular weekdays will no longer break your streak +* More colors to choose from (now 20 in total) +* Ability to customize how transparent the widgets are +* Ability to customize the first day of the week +* Yes/No buttons on notifications instead of just "Check" +* Automatic dark theme (Android 10) +* Smaller APK and backup files diff --git a/android/uhabits-android/src/main/play/release-notes/en-US/beta.txt b/android/uhabits-android/src/main/play/release-notes/en-US/beta.txt new file mode 100644 index 000000000..e5eea79b4 --- /dev/null +++ b/android/uhabits-android/src/main/play/release-notes/en-US/beta.txt @@ -0,0 +1,12 @@ +1.8.2: +* Fix issues with reminders +* Fix crash (HUAWEI) +1.8: +* New bar chart showing number of repetitions performed each week, month or year +* Performing habits on irregular weekdays will no longer break your streak +* More colors to choose from (now 20 in total) +* Ability to customize how transparent the widgets are +* Ability to customize the first day of the week +* Yes/No buttons on notifications instead of just "Check" +* Automatic dark theme (Android 10) +* Smaller APK and backup files diff --git a/android/uhabits-android/src/main/play/release-notes/en-US/production.txt b/android/uhabits-android/src/main/play/release-notes/en-US/production.txt new file mode 100644 index 000000000..32c331dbf --- /dev/null +++ b/android/uhabits-android/src/main/play/release-notes/en-US/production.txt @@ -0,0 +1,5 @@ +Version 1.7.11: +* Fix bug that produced corrupted CSV files in some countries +Version 1.7.10: +* Fix bug that prevented notifications from appearing on some phones +* Update target SDK to Android Pie 9 (API Level 28) diff --git a/android/uhabits-core/build.gradle b/android/uhabits-core/build.gradle index a749d8f41..78fe55c55 100644 --- a/android/uhabits-core/build.gradle +++ b/android/uhabits-core/build.gradle @@ -6,24 +6,24 @@ dependencies { annotationProcessor "com.google.dagger:dagger:$DAGGER_VERSION" compileOnly 'javax.annotation:jsr250-api:1.0' - compileOnly 'org.jetbrains:annotations-java5:15.0' + compileOnly 'org.jetbrains:annotations:18.0.0' compileOnly "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION" compileOnly "com.google.dagger:dagger:$DAGGER_VERSION" implementation "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION" implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'org.apache.commons:commons-lang3:3.5' - implementation 'com.google.code.gson:gson:2.7' + implementation 'com.google.code.gson:gson:2.8.5' - testImplementation 'junit:junit:4+' + testImplementation 'junit:junit:4.12' testImplementation 'org.hamcrest:hamcrest-library:1.4-atlassian-1' testImplementation 'org.apache.commons:commons-io:1.3.2' testImplementation 'org.mockito:mockito-core:2.8.9' testImplementation 'org.json:json:20160810' testImplementation 'org.xerial:sqlite-jdbc:3.18.0' - testImplementation 'nl.jqno.equalsverifier:equalsverifier:2.3.1' + testImplementation 'nl.jqno.equalsverifier:equalsverifier:2.4.8' - implementation('com.opencsv:opencsv:3.9') { + implementation('com.opencsv:opencsv:3.10') { exclude group: 'commons-logging', module: 'commons-logging' } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java index c9753b0c0..d271ce811 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/Preferences.java @@ -390,9 +390,11 @@ public class Preferences putString(key, StringUtils.joinLongs(values)); } - default long[] getLongArray(String key) + default long[] getLongArray(String key, long[] defValue) { - return StringUtils.splitLongs(getString(key, "")); + String string = getString(key, ""); + if (string.isEmpty()) return defValue; + else return StringUtils.splitLongs(string); } } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/WidgetPreferences.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/WidgetPreferences.java index 018652d89..255170d41 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/WidgetPreferences.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/preferences/WidgetPreferences.java @@ -38,10 +38,10 @@ public class WidgetPreferences { } public long[] getHabitIdsFromWidgetId(int widgetId) { - long habitIds[]; + long[] habitIds; String habitIdKey = getHabitIdKey(widgetId); try { - habitIds = storage.getLongArray(habitIdKey); + habitIds = storage.getLongArray(habitIdKey, new long[]{-1}); } catch (ClassCastException e) { // Up to Loop 1.7.11, this preference was not an array, but a single // long. Trying to read the old preference causes a cast exception. @@ -49,7 +49,6 @@ public class WidgetPreferences { habitIds[0] = storage.getLong(habitIdKey, -1); storage.putLongArray(habitIdKey, habitIds); } - if (habitIds.length == 0) throw new HabitNotFoundException(); return habitIds; } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java index 51423aac7..67e3869c8 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java @@ -25,6 +25,8 @@ import org.isoron.uhabits.core.*; import org.isoron.uhabits.core.commands.*; import org.isoron.uhabits.core.models.*; +import java.util.*; + import javax.inject.*; import static org.isoron.uhabits.core.utils.DateUtils.*; @@ -59,22 +61,44 @@ public class ReminderScheduler implements CommandRunner.Listener public void schedule(@NonNull Habit habit) { - if (!habit.hasReminder()) return; - Long reminderTime = habit.getReminder().getTimeInMillis(); + if (!habit.hasReminder()) { + sys.log("ReminderScheduler", "habit=" + habit.id + " has no reminder. Skipping."); + return; + } + + long reminderTime = habit.getReminder().getTimeInMillis(); scheduleAtTime(habit, reminderTime); } - public void scheduleAtTime(@NonNull Habit habit, @NonNull Long reminderTime) + public void scheduleAtTime(@NonNull Habit habit, long reminderTime) { - if (reminderTime == null) throw new IllegalArgumentException(); - if (!habit.hasReminder()) return; - if (habit.isArchived()) return; + sys.log("ReminderScheduler", "Scheduling alarm for habit=" + habit.id); + + if (!habit.hasReminder()) { + sys.log("ReminderScheduler", "habit=" + habit.id + " has no reminder. Skipping."); + return; + } + + if (habit.isArchived()) { + sys.log("ReminderScheduler", "habit=" + habit.id + " is archived. Skipping."); + return; + } + long timestamp = getStartOfDay(removeTimezone(reminderTime)); + sys.log("ReminderScheduler", + String.format( + Locale.US, + "reminderTime=%d removeTimezone=%d timestamp=%d", + reminderTime, + removeTimezone(reminderTime), + timestamp)); + sys.scheduleShowReminder(reminderTime, habit, timestamp); } public synchronized void scheduleAll() { + sys.log("ReminderScheduler", "Scheduling all alarms"); HabitList reminderHabits = habitList.getFiltered(HabitMatcher.WITH_ALARM); for (Habit habit : reminderHabits) @@ -101,5 +125,7 @@ public class ReminderScheduler implements CommandRunner.Listener public interface SystemScheduler { void scheduleShowReminder(long reminderTime, Habit habit, long timestamp); + + void log(String componentName, String msg); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java index de4ff20ab..78f707968 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java @@ -147,6 +147,8 @@ public class NotificationTray int notificationId, Timestamp timestamp, long reminderTime); + + void log(String msg); } class NotificationData @@ -188,9 +190,31 @@ public class NotificationTray @Override public void onPostExecute() { - if (todayValue != Checkmark.UNCHECKED) return; - if (!shouldShowReminderToday()) return; - if (!habit.hasReminder()) return; + systemTray.log("Showing notification for habit=" + habit.id); + + if (todayValue != Checkmark.UNCHECKED) { + systemTray.log(String.format( + Locale.US, + "Habit %d already checked. Skipping.", + habit.id)); + return; + } + + if (!shouldShowReminderToday()) { + systemTray.log(String.format( + Locale.US, + "Habit %d not supposed to run today. Skipping.", + habit.id)); + return; + } + + if (!habit.hasReminder()) { + systemTray.log(String.format( + Locale.US, + "Habit %d does not have a reminder. Skipping.", + habit.id)); + return; + } systemTray.showNotification(habit, getNotificationId(habit), timestamp, reminderTime); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java index d9f291e33..fe9db052b 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java @@ -37,21 +37,11 @@ public abstract class DateUtils private static Locale fixedLocale = null; - /** - * Time of the day when the new day starts. - */ - public static final int NEW_DAY_OFFSET = 3; - /** * Number of milliseconds in one day. */ public static final long DAY_LENGTH = 24 * 60 * 60 * 1000; - /** - * Number of milliseconds in one hour. - */ - public static final long HOUR_LENGTH = 60 * 60 * 1000; - public static long applyTimezone(long localTimestamp) { TimeZone tz = getTimezone(); @@ -182,13 +172,12 @@ public abstract class DateUtils public static long getStartOfToday() { - return getStartOfDay(getLocalTime() - NEW_DAY_OFFSET * HOUR_LENGTH); + return getStartOfDay(getLocalTime()); } public static long millisecondsUntilTomorrow() { - return getStartOfToday() + DAY_LENGTH - - (getLocalTime() - NEW_DAY_OFFSET * HOUR_LENGTH); + return getStartOfToday() + DAY_LENGTH - getLocalTime(); } public static GregorianCalendar getStartOfTodayCalendar() @@ -271,7 +260,7 @@ public abstract class DateUtils calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, 0); - Long time = calendar.getTimeInMillis(); + long time = calendar.getTimeInMillis(); if (DateUtils.getLocalTime() > time) time += DateUtils.DAY_LENGTH; diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PropertiesStorageTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PropertiesStorageTest.java index 3c5d4aa53..e22e2853b 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PropertiesStorageTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/preferences/PropertiesStorageTest.java @@ -103,10 +103,10 @@ public class PropertiesStorageTest extends BaseUnitTest storage.putLongArray("key2", expected2); storage.putLongArray("key3", expected3); - long[] actual1 = storage.getLongArray("key1"); - long[] actual2 = storage.getLongArray("key2"); - long[] actual3 = storage.getLongArray("key3"); - long[] actual4 = storage.getLongArray("invalidKey"); + long[] actual1 = storage.getLongArray("key1", new long[]{}); + long[] actual2 = storage.getLongArray("key2", new long[]{}); + long[] actual3 = storage.getLongArray("key3", new long[]{}); + long[] actual4 = storage.getLongArray("invalidKey", new long[]{}); assertTrue(Arrays.equals(actual1, expected1)); assertTrue(Arrays.equals(actual2, expected2)); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java index ea2b97dbf..5c098c8d9 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java @@ -76,7 +76,6 @@ public class ReminderSchedulerTest extends BaseUnitTest eq(h1), anyLong()); verify(sys).scheduleShowReminder(eq(unixTime(2015, 1, 26, 22, 30)), eq(h2), anyLong()); - Mockito.verifyNoMoreInteractions(sys); } @Test @@ -119,7 +118,6 @@ public class ReminderSchedulerTest extends BaseUnitTest public void testSchedule_withoutReminder() { reminderScheduler.schedule(habit); - Mockito.verifyZeroInteractions(sys); } public long unixTime(int year, int month, int day, int hour, int minute) diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java index 15413dce9..ee7db003a 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java @@ -164,10 +164,10 @@ public class DateUtilsTest extends BaseUnitTest @Test public void testMillisecondsUntilTomorrow() throws Exception { - DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 2, 59)); + DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 23, 59)); assertThat(DateUtils.millisecondsUntilTomorrow(), equalTo(60000L)); - DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 23, 0)); + DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 20, 0)); assertThat(DateUtils.millisecondsUntilTomorrow(), equalTo(14400000L)); }