Compare commits

...

1286 Commits

Author SHA1 Message Date
0cce6b30b1 Merge branch 'hotfix/1.8.8' 2020-06-21 11:39:25 -05:00
bf650a7565 Fix crash when saving habit (some languages only) 2020-06-21 11:31:53 -05:00
b78cd1dd0d Update tests 2020-06-21 11:00:00 -05:00
6d9ad8c56c Tweak snapIntervalsTogether so that "1 time every x days" habits work better 2020-06-21 10:59:31 -05:00
e7a3f0cffa Fix build script; remove some obsolete tests 2020-06-21 10:45:46 -05:00
6aa72caf6c Bump version to 1.8.8 2020-06-21 10:39:27 -05:00
a3344358b9 Shorten release notes 2020-01-06 18:43:27 -06:00
22fcecb48c Merge branch 'dev' 2020-01-06 18:27:24 -06:00
58d8c799ce Bump version to 1.8.7 2020-01-06 18:25:37 -06:00
f9437d61b0 Fix issue causing multiple notifications to be dismissed at once (#540) 2020-01-06 18:24:53 -06:00
997ebfc28a ListHabitsRegressionTest: update imports 2020-01-05 19:01:28 -06:00
6a91300d82 Migrate to AndroidX (#544) 2020-01-05 18:47:01 -06:00
889ce9faef Merge branch 'dev' 2020-01-05 08:30:21 -06:00
b3a40efe46 Bump version to 1.8.6 2020-01-05 08:29:56 -06:00
547c7ffdf7 Fix ID assignment on SQLiteHabitList 2020-01-05 08:29:49 -06:00
olegivo
82486c7514 migrate InstrumentationRegistry 2020-01-05 12:24:36 +03:00
olegivo
fe732ea385 manual migration 2020-01-05 12:24:36 +03:00
olegivo
85ec0faa99 update butterknife (10.2.1) for support jetifier 2020-01-05 12:24:27 +03:00
olegivo
9ac1ae9915 automatic migration 2020-01-05 11:22:58 +03:00
895d66b663 Merge branch 'dev' 2020-01-04 09:01:36 -06:00
0f2a93cd27 Bump version to 1.8.5 (48) 2020-01-04 08:58:09 -06:00
323c98edb8 Fix ReminderSchedulerTest 2020-01-04 08:44:42 -06:00
aadfac68cd Bring back snooze button 2020-01-03 19:56:19 -06:00
7076cffec5 Disable more flaky tests 2020-01-03 18:13:01 -06:00
0ef5a8dead Merge branch 'dev' 2020-01-03 17:55:47 -06:00
526c8fe750 Bump version to 1.8.4 (47) 2020-01-03 17:55:20 -06:00
464eaf613d Fix some empty CSV files 2020-01-03 17:46:46 -06:00
b21d77514a Increase logging for ReminderReceiver and WidgetReceiver 2020-01-03 17:46:46 -06:00
58ed759224 Disable notification bundling; add default question 2020-01-03 17:46:42 -06:00
7c742e1016 Make HabitCardListCache more thread-safe; add null checks 2020-01-03 17:09:39 -06:00
2e9330b5c5 Merge branch 'dev' 2020-01-03 13:27:02 -06:00
d1b83d069d Loop 1.8.3 2020-01-03 13:20:09 -06:00
7d35a85a37 Disable some flaky tests 2020-01-03 13:19:34 -06:00
616d9ab46c Put SavedState tests together 2020-01-03 12:59:59 -06:00
b9c9d6852a Merge branch 'edi_habit_crash' into dev 2020-01-03 09:00:35 -06:00
29e4a8d4ec Minor style changes 2020-01-03 09:00:17 -06:00
Rechee
ceed784acd remove unused tag 2020-01-03 08:56:50 -06:00
Rechee
897887f802 optimize imports 2020-01-03 08:56:50 -06:00
Rechee
dcd0c61b8d fixed issue where weekly picker dialog isn't being restored on rotation
squash! fixed issue where weekly picker dialog isn't being restored on rotation
2020-01-03 08:56:50 -06:00
1285b653ed Fix imports 2020-01-03 08:56:40 -06:00
dfd5c65595 Create failing regression test for issue #534 2020-01-03 08:15:52 -06:00
315bddea96 Automatically fix invalid timestamps, instead of crashing 2020-01-03 06:40:30 -06:00
938739d535 Update app description 2020-01-02 17:47:06 -06:00
27f625873d Reorganize .secret 2020-01-02 15:59:59 -06:00
f37d25e86b Loop 1.8.2 2020-01-02 12:58:26 -06:00
b2df70c059 Add Google Play Publisher plugin and Play Store assets 2020-01-02 12:55:44 -06:00
3afd46c59c Remove unused HabitLogger class 2020-01-02 05:41:03 -06:00
e36c649333 Fix unit tests 2020-01-02 05:31:51 -06:00
b2e7c9fe6e Remove HabitNotFound exception from WidgetPreferences 2020-01-02 05:27:17 -06:00
2171d582dc Fix some issues with reminders and print more logs 2020-01-02 05:12:44 -06:00
b7be459537 Create main GitHub Actions workflow 2020-01-01 20:54:51 -06:00
TacoTheDank
cbee09c38f Update gradle scripts and dependencies (#538)
* Update gradle wrapper
* Clean up some unnecessary/unused things in android gradles
* Update some dependencies
2020-01-01 18:03:53 -06:00
6f24e42d1f Disable write-ahead log on SQLite
Android 9 (Pie) silently introduced a new behavior where new SQLite
databases have Write-Ahead Logs (WALs) enabled by default. The data,
even after committed, is not written to the main database file until
later. This caused a silent bug leading to data loss, where exported
backups would either be empty or miss some recent data.
2020-01-01 09:40:35 -06:00
93bb105dac Remove gradle git plugin 2020-01-01 08:45:05 -06:00
f67b74d57d Update CHANGELOG 2020-01-01 08:31:16 -06:00
abbf1e4d66 Update translations 2020-01-01 08:29:44 -06:00
e3f6353062 Preserve widgets from Loop 1.7.11 and lower versions 2020-01-01 08:11:37 -06:00
38d5b2bf16 build.sh: Rename env variables; copy final APK to build/ 2020-01-01 07:46:29 -06:00
7801c933f0 Allow user to change first day of the week
Closes #421
2019-12-31 14:12:17 -06:00
5cdb9eb9d5 Settings: Remove extra margin 2019-12-31 11:23:02 -06:00
dee4670f65 Update CHANGELOG 2019-12-31 11:11:06 -06:00
50a6d7190b Revert change to launcher name 2019-12-30 17:29:24 -06:00
d3371badf8 Make the short name of the app untranslatable 2019-12-30 17:07:59 -06:00
ed1f3e5cdb Update translations 2019-12-30 17:05:46 -06:00
5947926cd5 Rename launcher icon to "Loop" 2019-12-30 16:39:47 -06:00
61cd77e5df Update screenshots 2019-12-30 16:17:17 -06:00
d6ec33d6d3 Fix failing unit test 2019-12-30 16:03:56 -06:00
3f002efb53 Allow user to change transparency of widgets
Closes #376
2019-12-30 16:03:56 -06:00
5191290188 Fix EditHabitDialog theme 2019-12-30 16:03:56 -06:00
cc05543692 Improve performance of detail page by cancelling useless async tasks 2019-12-30 16:03:56 -06:00
Brian Norman
e94e0c057e Capitalize sentences on dialogFormInputMultiline (#535) 2019-12-30 02:46:30 -06:00
350f002ed3 Update translations and credits 2019-12-29 16:15:37 -06:00
04cf4e7785 Update CHANGELOG 2019-12-29 14:31:54 -06:00
bf644f4e09 Rename night mode to dark theme; abide by system-wide settings (API 29)
Closes issue #513
2019-12-29 12:22:19 -06:00
3658aef2e2 Use dark navigation bar in dark theme 2019-12-29 11:42:10 -06:00
190a1171c4 Bump minSdkVersion to 21 (Lollipop) 2019-12-29 11:29:24 -06:00
2b20b6bb9d Add link to privacy policy 2019-12-29 11:12:29 -06:00
caed1aef79 Hide widget stacks feature for non-developers 2019-12-29 08:24:07 -06:00
8341956a90 Hide numerical habits feature for non-developers 2019-12-29 08:24:07 -06:00
de44b48dba Make all tests pass on Android 9.0 (Pie) 2019-12-29 08:24:07 -06:00
7eafd92b2d Make all tests pass on Android 7.1.1 (Nougat) 2019-12-29 08:24:07 -06:00
47dc26fea0 Fix typo in TEST.md 2019-11-17 19:32:04 -06:00
a6dd0939b2 Add TEST.md 2019-11-17 19:12:14 -06:00
898a33a754 Make all tests pass on Android 6.0 (Marshmallow) 2019-11-17 18:23:07 -06:00
1997d9491b Make all tests run successfully on Lollipop 2019-11-17 17:46:36 -06:00
6d57ea0368 Merge branch 'master' into dev 2019-11-16 23:00:26 -06:00
83c1197dc1 Increase target SDK to 29; update support library 2019-11-16 22:31:19 -06:00
48d145626f Update to Build Tools 3.5.2 2019-11-16 22:18:14 -06:00
a57f310c76 Remove DexCount plugin 2019-11-16 22:14:07 -06:00
1e6cb2e841 Remove PlayPublisher plugin 2019-11-16 22:06:19 -06:00
c676a02ca8 Remove Jacoco 2019-11-16 22:04:11 -06:00
ded57cd04a Merge branch 'dev' into agp-update 2019-11-16 22:00:13 -06:00
b8f9e2f309 Update to Dagger 2.25.2 2019-11-16 21:56:49 -06:00
olegivo
2fb9168686 Convert IntroActivity to Kotlin (#520) 2019-11-16 21:16:20 -06:00
9199a64d73 Pick specific Jacoco version (0.8.4) 2019-11-16 21:15:00 -06:00
Mick Dekkers
a69fb369df Preserve selections when reopening EditSettingActivity (#524) 2019-11-10 08:41:10 -06:00
0790961bb5 BUILD.md: add Android Studio instructions 2019-11-10 08:03:57 -06:00
c88fa4a003 First version of BUILD.md 2019-11-09 20:44:56 -06:00
f403dfd7d1 Disable failing tests 2019-11-09 18:37:21 -06:00
105baf629a Flip bar chart 2019-11-08 21:40:49 -06:00
oleg.industry
af37036ac5 jacoco concrete version fixed 2019-10-28 11:45:08 +03:00
oleg.industry
8717ad6ad0 kotlin update (1.3.50) 2019-10-28 11:45:08 +03:00
olegivo
95af0217ff google repository simplification 2019-10-08 14:25:18 +03:00
olegivo
fe091fa740 update AGP (3.5.1)
using default build tools version (from AGP)
2019-10-08 14:25:13 +03:00
olegivo
00abb4486d update libraries
auto-factory (1.0-beta6)
butterknife (9.0.0)
guava (24.1-android)
2019-10-08 14:24:21 +03:00
olegivo
dadfcb7c16 extracted AUTO_FACTORY_VERSION 2019-10-08 14:24:21 +03:00
Veyndan Stuart
77a9701805 Convert PaletteUtils to Kotlin (#510)
* Convert PaletteUtils to Kotlin
2019-10-05 07:31:32 -04:00
bfea4b024a core: Implement bar chart 2019-08-18 07:47:46 -05:00
Tthecreator
3e2cf48223 Changed habit type selection to dropdown instead of popup message (#498) 2019-08-12 12:39:44 -05:00
ec2fa16fab Web: update npm modules 2019-08-12 06:27:20 -05:00
8d97a8d140 Re-enable view tests 2019-08-12 06:10:56 -05:00
563aa8b7b4 Finish Kotlin implementation of IosCanvas 2019-08-12 06:01:32 -05:00
74475bd191 Partial implementation of IosCanvas in Kotlin 2019-08-11 17:11:29 -05:00
957a5b7c17 Fix CSV export in some locales; bump version to 1.7.11 (38) 2019-08-10 11:42:25 -05:00
64cc9f78a8 Increase targetSdk to 28 2019-06-15 09:46:06 -05:00
e50c411d1e Fix crash preventing some Xiaomi devices from showing notifications 2019-06-15 08:57:11 -05:00
046a7eab7f Move IosDatabase to Kotlin 2019-06-09 13:16:29 -05:00
d96732b588 Update 2019-06-07 07:11:47 -05:00
a3bfc05068 Move view tests to common 2019-04-14 10:33:36 -05:00
defa2f9431 Reorganize source tree 2019-04-13 22:54:26 -05:00
fe4139e268 Move tests to commonTest; convert some classes from Swift to Kotlin 2019-04-13 22:28:05 -05:00
d463bb55d7 Unify async tests 2019-04-13 19:27:51 -05:00
5ea19c9475 Restore Backend class; replace TaskRunner by Kotlin Coroutines 2019-04-13 09:20:37 -05:00
b0cedde0a9 Partial kotlin implementation of IosCanvas 2019-04-12 05:17:31 -05:00
e0894c9313 Move IosFiles implementation to Kotlin; setup tests for ios target 2019-04-12 05:16:31 -05:00
8378d88186 Update gradle 2019-04-11 08:13:19 -05:00
ddd363917c Implement JsFileStorage using IndexedDB 2019-04-10 20:07:15 -05:00
f310eaf7d9 Make I/O asynchronous with coroutines; make all JS tests pass 2019-04-10 08:20:13 -05:00
8972f2d03d Move most tests to commonTest 2019-04-10 05:35:56 -05:00
e88c58916a Implement JsFiles 2019-04-10 04:52:17 -05:00
7d169d8053 Update copyright date 2019-04-09 08:46:25 -05:00
c018d89ca6 Implement JsDatabase using sql.js 2019-04-09 08:43:23 -05:00
5c402b5400 Implement HtmlCanvas; move some tests to commonTest 2019-04-09 06:39:38 -05:00
7ba7edb7d4 Set up javascript tests 2019-04-07 16:51:28 -05:00
fe219b5296 Update kotlin gradle plugin; add js target 2019-04-07 13:07:50 -05:00
1abc041d87 Fix ios tests; remove empty test 2019-04-07 09:56:34 -05:00
c16a0ecd65 Migrate Scores to pure Kotlin; display correct score on main screen 2019-04-06 18:53:22 -05:00
6d527a31d7 Add app icon 2019-04-03 06:56:42 -05:00
4d0d631d8a Set minimum number of buttons 2019-04-03 06:56:28 -05:00
5b2b554a7a Dynamically select number of columns to display 2019-04-03 05:50:42 -05:00
33bae657a3 Show numerical habits 2019-04-02 20:16:00 -05:00
082c575f82 Allow user to show/hide archived and completed habits 2019-04-02 07:46:41 -05:00
90f553b4f6 Add Preferences table and repository 2019-04-02 05:57:11 -05:00
6af576c09c Change language automatically 2019-04-01 20:53:00 -05:00
c380abad5a Remove outdated tests 2019-04-01 07:35:18 -05:00
905099ccdb Fix invalid translation files 2019-04-01 07:32:34 -05:00
76b848752c Convert i18n strings from Android XML to Kotlin 2019-04-01 07:22:48 -05:00
48c3ff584a Rename to DetailScreenController; pass habit as argument 2019-03-31 19:43:20 -05:00
979affef22 Replace action sheet icon 2019-03-31 19:08:07 -05:00
274d3d6858 Main screen: add action sheet 2019-03-31 18:08:42 -05:00
f491acdda9 Simplify data trasfer in MainScreenDataSource 2019-03-31 17:31:40 -05:00
6ac7ef7807 Add stubs for Score and Streak 2019-03-31 17:15:39 -05:00
5d1f5168ad Create Observable class 2019-03-31 16:54:43 -05:00
262b9460bd Move README and related files to root 2019-03-31 06:48:30 -05:00
f4e4da6dc5 iOS: use actual data for checkmarks on main screen 2019-03-31 06:48:29 -05:00
024c99e60d Remove Xcode files 2019-03-31 06:48:29 -05:00
aa6b13f3a6 Remove DateCalculator 2019-03-31 06:48:29 -05:00
70a79856f2 Reorganize packages; implement checkmarks 2019-03-31 06:48:29 -05:00
6a30bb98c6 Rename legacy to android 2019-03-31 06:48:29 -05:00
07cf74d400 Remove obsolete react-native version of Android app 2019-03-31 06:48:26 -05:00
94b35545b7 Remove obsolete information from README.md 2019-03-31 06:48:26 -05:00
8544c5dc8a Remove react-native; rewrite main screen in (native) swift 2019-03-31 06:48:26 -05:00
a546f6de73 Update 2019-03-31 06:48:26 -05:00
7cab0a39e5 Implement database access (with migrations) 2019-03-31 06:48:26 -05:00
e19339d808 Add symlink to node_modules 2019-03-31 06:48:26 -05:00
134975b8ba Fix instructions in core/build.gradle 2019-03-31 06:48:26 -05:00
2d0a57efbd Update README 2019-03-31 06:48:26 -05:00
50e94c4d09 Update README; add screenshot 2019-03-31 06:48:26 -05:00
15974bdca8 Add README 2019-03-31 06:48:26 -05:00
0734e74154 Add gradle wrappers 2019-03-31 06:48:26 -05:00
f108bc8dc1 Initial prototype of multi-platform version 2019-03-31 06:48:26 -05:00
4ccda9d6f7 Move existing source code to subfolder 2019-03-31 06:48:26 -05:00
db1ba822fe Merge pull request #472 from chennemann/feat/create-habit-with-long-description
fix: habits with long description could not be saved
2019-01-27 22:30:14 -06:00
bd18a4320a Merge pull request #471 from chennemann/feat/always-hide-archive-action
Always hide archive/unarchive icon
2019-01-27 22:19:43 -06:00
Christoph Hennemann
b180f11834 fix: habits with long description could not be saved
- That was due to a bug where the dialog was not resized
    or scrollable and therefore the save button was not
    accessible

References: #462
2019-01-23 21:16:26 +01:00
Christoph Hennemann
d4b5c7b9d5 feat: Always hide archive/unarchive icon
- Improves usability since the icons do not
    jump around when more than one habit is
    selected

References: #465
2019-01-23 20:55:38 +01:00
a719f6ad98 Merge pull request #459 from chennemann/feat/scroll-bar-in-main-menu
Add scrollbars to habit overview list
2019-01-22 16:49:37 -06:00
Christoph Hennemann
d8894753e0 feat: Add scrollbars to habit overview list
References: #365
2019-01-20 00:40:35 +01:00
178061475e Improve performance when importing database 2018-12-08 12:24:44 -06:00
3581173193 NumberPicker: automatically show keyboard 2018-12-08 08:30:23 -06:00
a839631aae Fix previews in Layout Editor 2018-12-07 05:59:54 -06:00
a3e0d7ffb1 BarCard: fix target 2018-12-06 20:16:45 -06:00
6d4dbcdee7 Disable more flaky tests 2018-12-05 22:08:02 -06:00
33ae289ff1 Temporarily disable flaky tests 2018-12-05 21:52:44 -06:00
fca695ee6b Remove nightly APK badge 2018-12-05 21:27:29 -06:00
8fd175685d Update badge.py to Python 3 2018-12-05 21:02:23 -06:00
6a3e430a5e Merge pull request #438 from vyu1/dev
Add name (Victor Yu) to developer list
2018-09-18 19:04:27 -05:00
Victor Yu
07efa8b321 Add name (Victor Yu) to developer list 2018-09-17 23:31:50 -04:00
9183cb9f37 Update test images 2018-08-14 07:32:02 -05:00
a1bd4836dd gradle: do not abort on lint errors 2018-08-14 07:31:18 -05:00
dc74c0e54b Simplify StackWidgetService; reduce flicker 2018-06-16 19:35:28 -05:00
436d19dfea Merge branch 'dev' into feature/stackview
# Conflicts:
#	uhabits-android/src/main/java/org/isoron/uhabits/widgets/HabitPickerDialog.kt
2018-06-16 18:06:23 -05:00
6ca4877f1f BarChart: allow user to pick interval 2018-06-15 21:11:47 -05:00
6ad302b697 Show bar chart with monthly totals 2018-06-14 22:59:31 -05:00
b0820095f1 Add action for randomizing habit history (dev mode) 2018-06-13 21:39:06 -05:00
b5fda334d4 build.gradle: Give higher priority to Google Maven repository 2018-06-07 22:57:16 -05:00
88beb7b883 build.gradle: Give higher priority to Google Maven repository 2018-06-07 22:54:07 -05:00
49689317b7 Fix adaptive icons; remove obsolete folder 2018-06-07 22:35:20 -05:00
052d26c708 Upgrade to Kotlin 1.2.41 2018-06-07 22:23:40 -05:00
76c88848b2 Upgrade to Gradle 4.4 2018-06-07 22:03:13 -05:00
87f069f986 Merge branch 'master' into dev 2018-06-04 19:57:02 -05:00
ce27773138 Merge branch 'hotfix/1.7.9' 2018-04-21 10:31:54 -05:00
0864f83307 Update CHANGELOG 2018-04-21 10:17:38 -05:00
624cc67d9b Update translations 2018-04-21 10:17:31 -05:00
462bac8167 Add support for adaptive icons
Closes #395
2018-04-21 09:39:30 -05:00
5865eb41f7 Update notification for Android Oreo
- Add link to notification channel settings
- Remove snooze button

Closes #400
2018-04-21 08:50:53 -05:00
2bfd4a942d Remove unused PebbleReceiverTest 2018-04-21 08:00:00 -05:00
b4a33cba39 Add ActiveAndroid source code to our tree and remove content providers
ActiveAndroid is not actively maintained anymore and contains code
related to that Content Providers that makes the application crash on
Android Oreo.
2018-04-14 10:22:31 -05:00
f02c86e61b Bump targetSdkVersion to 27 2018-04-14 10:19:34 -05:00
5021f50e18 Bump version to 1.7.9 (36) 2018-04-14 08:11:22 -05:00
2654521647 Update only widgets containing the habit that was modified 2018-02-04 10:14:24 -06:00
778a7eb6bc Make widgets dark grey instead of black 2018-02-04 10:13:47 -06:00
71d559d6d9 Merge branch 'dev' into feature/stackview 2018-02-04 09:52:16 -06:00
b94d2f2fa6 StackWidget: allow user to select habits 2018-01-27 20:34:11 -06:00
2904f3e2f8 Move some methods to StringUtils 2018-01-27 20:25:55 -06:00
1ad06bcc15 Preferences: allow storing Long arrays 2018-01-27 19:07:05 -06:00
bf8c14fc03 Fix reminder tests 2017-12-06 22:23:28 -06:00
b46b7aae25 Merge branch 'feature/custom-snooze' into dev 2017-12-06 21:42:04 -06:00
357f51fd5e SnoozeDelayPickerActivity: Fix timepicker layout 2017-12-06 21:41:42 -06:00
7f257e045b MemoryHabitList: iterate over a copy of the list 2017-12-04 23:13:31 -06:00
0dc46d02a4 Minor style changes 2017-11-15 21:54:30 -06:00
ecf3086aef Merge branch 'add-delete-button-to-stats' of git://github.com/derebaba/uhabits into pull/delete-button 2017-11-15 21:42:30 -06:00
derebaba
10be875b48 Fixed test 2017-11-15 10:57:00 +03:00
0077d35ff9 Automatically dismiss summary notification 2017-11-14 23:03:46 -06:00
2a4a7c975f Add action to show reminder right now (for developers) 2017-11-14 22:35:37 -06:00
e91f1c3fa4 Merge branch 'dev' into feature/custom-snooze 2017-11-14 22:20:32 -06:00
9d48b4bcdb Simplify code; change notification actions to Yes/No/Later 2017-11-14 22:07:52 -06:00
7f1a35ebe5 Merge branch 'dev' of git://github.com/rsri/uhabits into pull/cancel_notification 2017-11-14 21:54:16 -06:00
5ccd546958 Merge branch 'dev' of git://github.com/TruffelNL/uhabits into dev
# Conflicts:
#	uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt
2017-11-14 21:45:56 -06:00
Victor Yu
def71d8141 Merge branch 'dev' into stack_checkmark_widget 2017-11-08 21:04:45 -05:00
Victor Yu
8feb07ff1b Code review changes; Made 'stack view' design available for all widgets 2017-11-08 21:03:06 -05:00
derebaba
1edd76ae8c Added delete button to statistics screen 2017-11-02 14:21:27 +03:00
7613e6e1cb Update to Android Studio 3.0 stable 2017-10-29 14:43:17 -05:00
5629a28823 Merge pull request #348 from llunak/fix_synchronized
synchronize HabitList properly
2017-10-26 19:54:51 -05:00
Luboš Luňák
b1c2ab90d3 synchronize HabitList properly
When the app is not running and ReminderReceiver receives ACTION_SHOW_REMINDER,
the (SQLite)HabitList will start loading its data in the background for some
reason, and if the loading takes a moment, ReminderReceiver will call
the unsynchronized HabitList.getById() before the loading finishes,
failing to find the habit for which to show the notification.
2017-10-18 15:17:31 +02:00
Victor Yu
268cb0bc18 Can make either the normal checkmark widget or stackview checkmark widget 2017-10-15 20:44:21 -04:00
Victor Yu
5a78de5a25 Implemented ability to choose multiple habits for stackview 2017-10-15 13:36:54 -04:00
Victor Yu
82972d6e47 Implemented stackwidget style for checkmark widgets 2017-10-15 13:36:54 -04:00
a201273781 Refactoring 2017-10-10 21:31:31 -05:00
819a8d341f Merge branch 'llunak/custom_snooze' into dev 2017-10-09 19:16:57 -05:00
b8f7d4fad2 Add missing test screenshots 2017-10-04 21:43:34 -05:00
dea4e069c5 Add test screenshots for Oreo 2017-10-04 21:27:43 -05:00
07c7234bfc Merge branch 'master' into dev 2017-09-30 13:40:09 -05:00
bf3964a231 Merge branch 'hotfix/1.7.7' 2017-09-30 13:27:45 -05:00
657cde75d8 Disable signing config 2017-09-30 13:18:26 -05:00
c56b86d32c Bump version again
The previous number was already in use by an alpha version
2017-09-30 13:14:42 -05:00
16f20d50a0 Fix bug that caused reminders to keep repeating every few seconds
Fixes #351
2017-09-30 13:11:40 -05:00
7bb88dcb97 Bump version and update CHANGELOG 2017-09-30 12:59:02 -05:00
223b8bc5ec Merge branch 'dev' into llunak/custom_snooze 2017-09-28 07:00:51 -05:00
Luboš Luňák
e052a144bd fix testTruncate_dayOfWeek failing with some locales 2017-09-28 06:55:13 -05:00
Luboš Luňák
318caa886c fix csv export with locales that do not use dot as decimal separator 2017-09-28 06:55:13 -05:00
Luboš Luňák
46c61f9ea9 force US locale for tests 2017-09-28 06:55:13 -05:00
ba78e563cd Merge branch 'keep_position' of git://github.com/llunak/uhabits into dev 2017-09-28 06:44:36 -05:00
acb94db6d6 Introduce failing test for bug #339 2017-09-28 06:40:06 -05:00
Luboš Luňák
d2cc283bd5 don't reset habit position when editing it 2017-09-28 13:03:34 +02:00
6c66078a65 Merge pull request #337 from llunak/export_name
fix name of exported files (correct the time)
2017-09-27 20:32:26 -05:00
Luboš Luňák
be9c2ff64d fix name of exported files (correct the time)
This reverts part of a75a27ad, where this got changed presumably by mistake.
2017-09-27 20:13:29 +02:00
bb22972eb2 Minor code style changes 2017-09-24 07:19:35 -05:00
e911fb35b6 Better explain LED lights feature 2017-09-24 07:16:59 -05:00
d1490ee771 Update Gradle and Android plugin 2017-09-24 06:05:29 -05:00
6d44b4124d Merge pull request #333 from llunak/fix_sql
avoid sql error when updating sql database
2017-09-21 07:01:59 -05:00
Luboš Luňák
f8e0d07236 avoid sql error when updating sql database
The index doesn't exist in version 1.7.6 and so trying to drop it
would lead to an error, resulting in not being able to import
1.7.6 database.
https://github.com/iSoron/uhabits/issues/327
2017-09-16 19:35:50 +02:00
Luboš Luňák
e970473876 make notification snooze popup follow night mode setting 2017-09-15 13:06:42 +02:00
Luboš Luňák
cec05ccbca when asking for snooze delay, first show a list of common options 2017-09-15 13:06:37 +02:00
Luboš Luňák
aac59367dc properly handle the activity window of the snooze time dialog 2017-09-15 12:01:44 +02:00
Luboš Luňák
0421ca0549 make snooze time dialog follow night mode setting 2017-09-15 12:00:51 +02:00
Luboš Luňák
43e802fb8e implement custom snooze for notifications 2017-09-15 12:00:42 +02:00
52c4282601 Merge pull request #329 from llunak/fix_snooze
fix snooze button in notifications
2017-09-13 07:03:46 -05:00
665204bf7a Merge pull request #326 from llunak/notifications-led
Make notifications also blink the LED
2017-09-13 07:00:57 -05:00
Luboš Luňák
f52da56221 fix snooze button in notifications
The "pref_snooze_interval" preference is manipulated by the ListPreference
class, which according to its docs stores the preference as a string.
Without reverting this part of 864636705d,
this results in "java.lang.ClassCastException: java.lang.String cannot be
cast to java.lang.Long" when trying to snooze a notification.
2017-09-12 15:54:43 +02:00
Luboš Luňák
4d59783809 make LED blinking for notifications configurable 2017-09-11 15:18:42 +02:00
Luboš Luňák
a680d57cac make notifications also blink the LED 2017-09-11 13:46:49 +02:00
TruffelNL
f6620be2d9 Removed an if statement
Removed the check if a summary was already shown.
2017-08-15 23:44:41 +02:00
TruffelNL
1c2abb543b Added private variables 2017-08-15 23:09:19 +02:00
TruffelNL
87cf2871a7 Added bundled notifications
Added bundled/grouped/stacked notifications as per https://github.com/iSoron/uhabits/issues/243
2017-08-15 23:02:58 +02:00
srikanth r
e041d9041b Implemented cancel to reminders of habits. 2017-08-04 23:01:41 +05:30
dccf5eae47 Only use signing configuration if env variables are defined 2017-08-02 11:19:25 -04:00
b2a8c9c45f Remove PebbleReceiver 2017-07-26 11:39:02 -04:00
125a574ff9 Merge branch 'master' into dev 2017-07-26 10:37:08 -04:00
7bb62c197f Include Play Store plugin 2017-07-26 10:07:25 -04:00
a75a27ad42 Make the day start at 3am instead of midnight
Closes #50
2017-07-25 20:18:01 -04:00
4126f01ef1 Reactivate proguard 2017-07-25 18:09:48 -04:00
9816fc9127 Update Android plugin 2017-07-25 12:35:22 -04:00
b135aa09a3 Use more simple toString style 2017-07-24 12:14:48 -04:00
f3a64fd67a Add tests for equals, hashCode and toString 2017-07-24 11:41:12 -04:00
864636705d Implement tests for Preferences 2017-07-24 09:54:51 -04:00
281861cac5 build.sh: read keystore from environment variables 2017-07-24 00:14:46 -04:00
c05f50998f Add branch and commit hash to version name 2017-07-24 00:14:46 -04:00
b2734b179c README: Add link to latest stable release 2017-07-23 23:30:24 -04:00
00a4abf266 README: Switch to shields.io 2017-07-23 22:17:35 -04:00
47e279b3b3 Update SharedPreferencesStorage 2017-07-23 20:14:12 -04:00
87f1d635d8 Implement PropertiesStorage 2017-07-23 20:07:44 -04:00
fdcb9daadc LoopDBImporter: update table names 2017-07-23 17:26:08 -04:00
5fde0501b5 README: Add link to dev apk 2017-07-23 17:04:20 -04:00
f72799f48c README: Update badge link 2017-07-23 14:26:34 -04:00
60c62b8609 Temporarily disable proguard 2017-07-23 13:50:33 -04:00
e5bc06c138 Increase time limit 2017-07-23 13:37:49 -04:00
fa5ba0c1ef Update build.sh 2017-07-23 13:00:57 -04:00
43be70b27c build.sh: Do not abort when uninstall fails 2017-07-23 10:59:18 -04:00
89400e281e Move version numbers from build.gradle to gradle.properties 2017-07-23 10:03:09 -04:00
57dc19550d Fix errors 2017-07-22 20:05:01 -04:00
a8aa6f192c Replace Long by Timestamp 2017-07-22 16:29:08 -04:00
882ddba324 Fix acceptance tests 2017-07-22 09:28:30 -04:00
2f7509b94e Update test images (KitKat) 2017-07-21 19:31:37 -04:00
10e68aa008 Update build.sh 2017-07-21 19:30:55 -04:00
a5720e8d7f BaseViewTest: increase tolerance 2017-07-21 19:30:46 -04:00
c7aaa98935 Convert widget providers to Kotlin 2017-07-21 18:32:13 -04:00
efcb5710c0 Convert more classes to Kotlin 2017-07-21 18:32:03 -04:00
3783fd8506 Convert RingtoneManager to Kotlin 2017-07-21 18:31:49 -04:00
6f80a9c030 Convert intents and notifications to Kotlin 2017-07-21 18:17:42 -04:00
a02376497a Convert automation and database packages to Kotlin 2017-07-21 18:17:28 -04:00
180c18f6bf Merge branch 'feature/kotlin' into dev 2017-07-21 18:12:45 -04:00
2db4c06fe8 Merge branch 'master' into dev
# Conflicts:
#	app/src/androidTest/java/org/isoron/uhabits/espresso/MainTest.java
#	app/src/androidTest/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkListTest.java
#	app/src/main/java/org/isoron/uhabits/activities/habits/list/views/HabitCardView.java
#	app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkList.java
#	app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteScoreList.java
#	app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteStreakList.java
#	app/src/main/java/org/isoron/uhabits/models/sqlite/records/CheckmarkRecord.java
#	uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/HistoryChart.java
#	uhabits-android/src/main/res/values-id/strings.xml
#	uhabits-android/src/test/java/org/isoron/uhabits/receivers/ReminderControllerTest.java
2017-07-18 22:54:52 -04:00
540a618ba8 Merge branch 'hotfix/1.7.6' 2017-07-18 22:45:50 -04:00
bf24cc608c Update changelog 2017-07-18 22:45:36 -04:00
a73459784e Fix NPE in HabitCardView.triggerRipple 2017-07-18 22:16:11 -04:00
de3b97dfdf Fix IndexOutOfBoundsException in HabitCardListAdapter 2017-07-18 22:13:10 -04:00
91996924d9 Never store reference to SQLiteDatabase
SQLiteDatabase closes automatically at random times. Storing a reference
to an open SQLiteDatabase eventually leads to a crash.
See: https://stackoverflow.com/questions/1483629/
2017-07-18 22:07:21 -04:00
9fe446b424 Fix crash when tapping HistoryChart 2017-07-18 21:55:15 -04:00
3857eaf5e9 Update changelog 2017-07-18 21:47:25 -04:00
e29fb58922 Fix failing tests 2017-07-18 21:47:19 -04:00
404fc869b0 Repair inconsistent data instead of throwing exception 2017-07-18 21:28:48 -04:00
001dd5a7c1 Update translations 2017-07-18 18:39:20 -04:00
7930cc8f31 Bump version to 1.7.6 2017-07-18 17:52:21 -04:00
122b300c50 Update view test images (KitKat) 2017-07-18 16:10:41 -04:00
0984f7ff5d Update Android gradle plugin 2017-07-18 06:57:22 -04:00
2d9a5ae7e2 Update links to build server 2017-07-17 22:01:37 -04:00
Jude Ibe (Toochukwu)
02f9660fda Socket.io depreciated function
Kept socket.io to previous version in gradle.
2017-07-14 10:20:51 -05:00
Jude Ibe (Toochukwu)
d3d733ab42 Build Tools Upgrade
3.0.0-alpha4 to 3.0.0-alpha6
Gradle 4
2017-07-14 10:19:56 -05:00
bb282da92d Fix tests 2017-06-23 16:25:25 -04:00
38d3b0d047 Update habit.position after reordering list 2017-06-23 12:12:23 -04:00
8ccada67d6 Import Loop DB without app restart 2017-06-23 10:24:54 -04:00
33f7acc9ca Add reordering tests for SQLiteHabitList 2017-06-23 09:29:19 -04:00
5d9563b9d8 Fix handling of null values in AndroidDatabase 2017-06-23 09:14:36 -04:00
f55dc0d811 Fix animation when card moves and updates simultaneously 2017-06-22 23:31:46 -04:00
7872983064 Fix order by position 2017-06-22 23:21:44 -04:00
ea640a8a17 Rebuild order after removing habit 2017-06-22 22:50:27 -04:00
6801d1d1ae Add more constraints on table Repetitions 2017-06-21 13:18:29 -04:00
3584affbe0 Move BaseUnitTest 2017-06-21 10:20:59 -04:00
1069fcfc62 Move importers to uhabits-core 2017-06-21 00:30:32 -04:00
59745fb90f Refactor Android database classes 2017-06-20 22:37:35 -04:00
1976160ae8 Move tests to uhabits-core 2017-06-20 22:20:46 -04:00
6dd7e49112 Move database migrations to uhabits-core 2017-06-20 21:46:30 -04:00
ecb5352134 Implement JDBC database 2017-06-20 14:13:37 -04:00
b96385c4a7 Move models.sqlite to uhabits-core 2017-06-20 12:50:57 -04:00
96c1a046d4 Merge branch 'feature/raw-sqlite' into dev 2017-06-20 10:43:04 -04:00
00660d3e36 Make filtered MemoryHabitLists update automatically 2017-06-20 10:34:21 -04:00
PrototypeNM1
b14ca5c625 Don't list archived Habits when creating Widgets. (#309)
Fixes #283
2017-06-20 06:07:15 -04:00
71fe6137be Remove old database migrations; add missing ones 2017-06-19 12:08:06 -04:00
0a5d565030 Remove dependency: ActiveAndroid 2017-06-19 11:12:31 -04:00
6d06e06840 Simplify SQLite lists 2017-06-19 09:23:40 -04:00
edeba897fb Implement SQLiteRepository 2017-06-19 09:22:48 -04:00
e4b9c50ee2 Update Gradle plugin 2017-06-19 09:22:30 -04:00
af7c4e227d Fix merge 2017-06-10 19:34:44 -04:00
96ab887545 Merge tag 'v1.7.5' into dev
1.7.5
2017-06-10 18:59:28 -04:00
526830ba61 Merge branch 'hotfix/1.7.5' 2017-06-10 18:56:22 -04:00
fe1513bb64 Fix race conditions on SQLiteScoreList 2017-06-10 16:48:53 -04:00
e06ace9ea8 Fix ArrayIndexOutOfBoundsException on FrequencyChart 2017-06-10 15:38:21 -04:00
d727dabb2b Fix snooze button on notifications 2017-06-10 15:30:51 -04:00
d17e8fcbfb Bump version to 1.7.5 2017-06-10 15:28:12 -04:00
f8a9da59dd Simplify ListHabitsActivity 2017-06-05 22:56:08 -04:00
50a6c6d9dd Remove unused code 2017-06-05 18:11:30 -04:00
8d181a6683 Simplify ShowHabitActivity 2017-06-05 18:01:13 -04:00
217516ad59 Create android-pickers module 2017-06-05 16:38:58 -04:00
fc4b610d59 Create android-base module 2017-06-05 15:58:42 -04:00
382b52e5b2 Merge tag 'v1.7.4' into dev
1.7.4

# Conflicts:
#	app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteCheckmarkList.java
#	app/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteScoreList.java
#	uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java
2017-06-05 09:20:47 -04:00
be3d7145ab Merge branch 'hotfix/1.7.4' 2017-06-04 17:36:17 -04:00
cf66587644 ScoreList: make getValue synchronized 2017-06-04 17:29:41 -04:00
0dc9ec2e5f Expire caches on SQLite lists 2017-06-04 17:24:18 -04:00
0a375ded96 Silently ignore missing habits 2017-06-04 17:07:07 -04:00
fa5d6f8fee Bump version 2017-06-04 17:01:40 -04:00
277738f94d Fix default color and failing tests 2017-06-04 13:14:45 -04:00
cf25229fbc Merge branch 'dev' into pull/austil 2017-06-04 12:59:15 -04:00
7652d71c94 Uninstall test APK before running tests 2017-06-04 12:46:30 -04:00
74e0dcf706 Disable PebbleReceiver tests on KitKat 2017-06-04 12:46:16 -04:00
4e1cc6dc80 Fix tests for KitKat 2017-06-04 12:21:29 -04:00
c34f9f9e9f Merge branch 'dev' of https://github.com/austil/uhabits into pull/austil 2017-06-04 11:30:10 -04:00
ed9066f393 Implement alternative checkmark algorithm
Fix failing tests
2017-06-04 10:58:00 -04:00
96e1771c25 Remove inferred tables from SQLite database 2017-06-03 10:51:17 -04:00
austil
d0d3c7eef5 More Colors - requested changes 2017-06-03 15:16:09 +02:00
6875fc0428 Move notifications and reminders to uhabits-core 2017-06-02 19:30:39 -04:00
b88b3a683d Move preferences to uhabits-core 2017-06-02 18:24:12 -04:00
d97f94075d Implement widget test 2017-06-02 15:25:24 -04:00
28f095e56a Implement additional UI tests 2017-06-02 14:45:06 -04:00
ead87519b1 UI tests: reset state programmatically 2017-06-02 13:16:15 -04:00
7cfe3355e4 Downgrade Mockito to 1.0 on AndroidTest 2017-06-01 21:55:13 -04:00
a51ecaaf24 Annotate all Android tests 2017-06-01 21:55:13 -04:00
322645da9b Update badge link 2017-05-31 21:35:07 -04:00
5eb63df633 Merge branch 'modules' into dev 2017-05-31 21:17:28 -04:00
e4b5a3ea45 Implement acceptance tests for some basic features 2017-05-31 18:24:22 -04:00
88c1e73720 Merge tag 'v1.7.3' into dev
1.7.3
2017-05-30 11:11:42 -04:00
0393e58d3b Merge tag 'v1.7.3' into dev
1.7.3
2017-05-30 10:38:07 -04:00
534e6c2d9d Merge branch 'hotfix/1.7.3' 2017-05-30 09:34:12 -04:00
b6501c9a29 Fix NullPointerException 2017-05-30 09:22:15 -04:00
238a1c724d Bump version and update changelog 2017-05-30 09:06:50 -04:00
34ca9d17a2 Make usage of BundleSavedState more robust 2017-05-30 09:05:05 -04:00
6ccfb53329 Add missing tests for RepetitionList and Habit 2017-05-30 08:19:28 -04:00
8a29fbf07d Merge branch 'hotfix/1.7.3' into modules
# Conflicts:
#	uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java
#	uhabits-android/src/main/java/org/isoron/uhabits/models/sqlite/SQLiteScoreList.java
#	uhabits-core/src/main/java/org/isoron/uhabits/core/models/CheckmarkList.java
2017-05-29 22:55:08 -04:00
e844390614 Improve performance of repeated getTodayValue calls 2017-05-29 22:22:31 -04:00
223aee3be2 Add Test Butler APK 2017-05-29 09:14:02 -04:00
745d07024c Remove unused permissions 2017-05-29 08:37:49 -04:00
94025c5262 Add test for BundleSavedState 2017-05-28 22:26:36 -04:00
ab09eb8a03 Update CI build script 2017-05-28 17:04:04 -04:00
e826c80ff2 Fix Android tests 2017-05-28 15:26:28 -04:00
6255fe2d12 Make generated classes work on Android Studio 2017-05-28 11:39:07 -04:00
1746920699 Rename uhabits-core package 2017-05-28 11:38:20 -04:00
c9b62669de Merge branch 'dev' into modules 2017-05-28 09:44:55 -04:00
d2f367678f Merge tag 'v1.7.2' into dev
v1.7.2
2017-05-28 00:47:08 -04:00
5e00d07b73 Merge branch 'hotfix/1.7.2' 2017-05-28 00:41:37 -04:00
28b6ae7014 Apply dark theme on dialogs
Fixes #291
2017-05-28 00:31:48 -04:00
2a1bf5fc2e Update CHANGELOG 2017-05-27 23:38:58 -04:00
ef7483f9dc Make SQLiteHabitList.toList synchronized 2017-05-27 23:37:24 -04:00
bbb9ed8f99 Update translations 2017-05-27 23:30:45 -04:00
c49d576871 Fix crash at startup 2017-05-27 23:29:35 -04:00
bc66ae4f7a Bump version to 1.7.2 2017-05-27 23:28:16 -04:00
56c5fb6c9d Write missing tests 2017-05-27 22:46:33 -04:00
d8d4c4f55e Write tests for ListHabits behaviors 2017-05-27 20:33:30 -04:00
70423ddb0a Move ListHabits controllers to uhabits-core 2017-05-27 18:52:06 -04:00
94c70485b7 Remove unit tests for uhabits-android 2017-05-27 10:31:05 -04:00
3e558be4d4 Move ListHabitsBehavior to uhabits-core 2017-05-26 22:04:59 -04:00
95385fa8f4 Activate coverage report for uhabits-core 2017-05-26 18:38:08 -04:00
fa4944700c Move UI behavior to uhabits-core 2017-05-26 16:33:21 -04:00
df0cf57984 Move tests to androidTest 2017-05-25 18:41:59 -04:00
29d1de46e7 Reorganize tests 2017-05-25 15:59:03 -04:00
cb4ab3b436 Move ExportCSVTask to uhabits-core 2017-05-25 12:50:38 -04:00
370e7343d7 Move commands to uhabits-core 2017-05-25 10:00:56 -04:00
acd653db70 Create org.isoron.androidbase package 2017-05-25 09:31:54 -04:00
51ca4aa98e Move remaining model classes 2017-05-25 08:54:21 -04:00
d23b59ced2 Move some models 2017-05-25 08:24:22 -04:00
f18ac9db48 Create module uhabits-core 2017-05-25 08:16:55 -04:00
c20ca3921f Rename android module to uhabits-android 2017-05-25 08:00:00 -04:00
96f620455f Update toolchain 2017-05-25 00:02:02 -04:00
2dd14dbf04 Small changes to coverage badge 2017-05-24 17:57:28 -04:00
8346f28497 Generate code coverage badges 2017-05-24 17:33:25 -04:00
97967b2b2e Improve build script 2017-05-24 00:23:01 -04:00
cf6a257143 Activate ProGuard; test signed release APK instead of debug 2017-05-23 19:13:30 -04:00
275125d230 Update dependencies 2017-05-23 16:25:11 -04:00
cb7b569d4e Use 'adb emu kill' to stop emulator 2017-05-23 12:21:53 -04:00
89b6f4c5cc Fix compilation error when ROBO_SDK is defined 2017-05-23 11:58:29 -04:00
8d555eb837 Read Robolectric version from environment 2017-05-23 11:39:17 -04:00
9288528f94 Fix assets path 2017-05-23 11:07:12 -04:00
e92ffb3894 Drop support for Android ICS and Jelly Bean; remove obsolete code 2017-05-23 10:50:11 -04:00
96bdb42365 Remove unused files 2017-05-23 00:18:22 -04:00
ecb207d322 Generate XML reports for instrumented tests 2017-05-22 22:37:08 -04:00
64001604cf Update link to build server 2017-05-22 14:24:22 -04:00
b9d3d22894 Use absolute paths on run_tests 2017-05-22 13:22:16 -04:00
25705297cb Update run scripts 2017-05-21 21:12:08 -04:00
532637ef7e Update link to CI server 2017-05-21 13:14:26 -04:00
0a1907ee2c Merge tag 'v1.7.1' into dev
v1.7.1
2017-05-21 10:20:58 -04:00
fa416adbb9 Merge branch 'hotfix/1.7.1' 2017-05-21 10:20:48 -04:00
8b835b9918 Update CHANGELOG 2017-05-21 10:10:30 -04:00
471c5d341f Update translations 2017-05-21 10:03:13 -04:00
d0e76d3d55 Implement tests for BaseScreen 2017-05-20 23:36:07 -04:00
1832ea639b Implement tests for BaseActivity 2017-05-20 22:10:37 -04:00
cd3944b90f Add Robolectric dependency; implement a basic test 2017-05-20 20:05:12 -04:00
9f2f8f7117 View tests: create wrapper for getDimension; other fixes 2017-05-17 22:41:06 -04:00
1b97b9040d View tests: use fixed screen density 2017-05-17 19:20:44 -04:00
austil
8a80a66a80 More Colors for habits 2017-05-06 16:38:14 +02:00
austil
894423e49f Revert "New color but Sort By Color broken"
This reverts commit 4ce9013e6a.
2017-05-06 13:27:28 +02:00
austil
4ce9013e6a New color but Sort By Color broken 2017-05-06 13:25:17 +02:00
96b95edef8 Separate expected view snapshots according to version 2017-04-22 23:12:44 -04:00
704854fdf1 View tests: adjust similarity cutoff 2017-04-22 22:01:06 -04:00
6e0393f611 Improve view tests 2017-04-22 00:10:42 -04:00
e6ceed9ec9 Update README.md 2017-04-21 20:13:42 -04:00
cf3d289145 Enable XML reports 2017-04-21 19:19:42 -04:00
6bd59aad97 Update code coverage gradle command 2017-04-21 18:53:17 -04:00
a5567d491f Enable test coverage 2017-04-21 18:26:29 -04:00
9604c26973 Remove inactive espresso tests; fix other tests 2017-04-21 12:03:55 -04:00
81ad1ba8c8 Merge branch 'feature/parallel' into dev 2017-04-21 10:08:06 -04:00
1d68122a6f Replace layout inflation by code 2017-04-20 18:14:06 -04:00
7d9d45ffed Small performance changes 2017-04-20 16:39:41 -04:00
50e21b2cc1 Merge branch 'hotfix/1.7.1' into dev 2017-04-19 19:47:49 -04:00
57296745b3 Improve performance of CheckmarkButtonView 2017-04-19 14:33:59 -04:00
fb1b1221d3 Merge remote-tracking branch 'origin/dev' into dev 2017-04-15 18:10:08 -04:00
788c790f9e Detect network changes 2017-04-15 17:13:41 -04:00
293d838d80 Move Sync to foreground service 2017-04-15 16:34:15 -04:00
3da996b8a4 Update SyncManager 2017-04-14 23:08:00 -04:00
08e3c9cc40 Replace toJSON methods by Gson 2017-04-14 20:32:00 -04:00
13b4128777 Update code coverage 2017-04-14 10:56:38 -04:00
b4e79c3f4b Merge branch 'feature/sync' into dev 2017-04-13 23:34:57 -04:00
2d07f5e924 Create switch for numerical habits feature 2017-04-13 21:44:23 -04:00
Mihail Stefanov
cb29fef17e Use of Cyrillic letters to display Bulgarian (#276)
I switched the phonetic notation with Cyrillic letters to denote the Bulgarian language.
2017-04-13 19:08:33 -04:00
1d76760dc8 Create hidden settings for experimental features 2017-04-12 23:19:22 -04:00
b6994034d2 Fix failing test 2017-04-12 13:09:28 -04:00
8fc0c072e5 Merge branch 'artem-p-reminderDaysFix' into dev 2017-04-12 11:25:33 -04:00
e6deb1f281 Merge branch 'hotfix/1.7.1' into dev 2017-04-12 11:25:28 -04:00
artem-p
bb0d43018e Fix resetting reminder days 2017-04-12 11:17:27 -04:00
140ab34a76 Verify database version before importing 2017-04-11 22:03:16 -04:00
0d6ad26505 Ignore exception when habit is not found 2017-04-11 21:19:03 -04:00
65cc99dbf7 Switch from View.BaseSavedState to Support Library's AbsSavedState
See https://code.google.com/p/android/issues/detail?id=196430
2017-04-11 17:49:55 -04:00
6855ef9d5e Update translations 2017-04-11 17:26:06 -04:00
4c58b084c6 Fix missing dialog title 2017-04-11 17:19:18 -04:00
5c8e522646 Fix header labels for RTL languages such as Arabic 2017-04-11 17:14:25 -04:00
55da0759d4 Bump version 2017-04-11 16:58:35 -04:00
Dmitriy Bogdanov
814b734ad3 Import java.text.DecimalFormat instead of one from ICU (#273) 2017-04-10 08:05:08 -04:00
6f5941472b Merge remote-tracking branch 'origin/dev' into dev 2017-04-09 18:15:55 -04:00
7699423aa7 Merge tag 'v1.7.0' into dev
1.7.0
2017-04-09 18:14:53 -04:00
692fe3218f Merge branch 'release/1.7.0' 2017-04-09 18:13:52 -04:00
387930c08d Fix icon size, remove unused icons 2017-04-09 17:37:14 -04:00
6bd31f9607 Add Basque, Catalan, Persian and Romanian languages 2017-04-09 17:16:08 -04:00
9aafe7160c Update translation links 2017-04-09 16:56:04 -04:00
5cc4aac67a Update translations 2017-04-09 16:41:32 -04:00
831421bc98 Ignore CrowdIn configuration files 2017-04-09 16:03:00 -04:00
e48dab9ed3 Update translation link 2017-04-04 17:47:14 -04:00
161d8f2517 Update changelog 2017-03-31 09:12:53 -04:00
bfe4b822b3 Bump version 2017-03-31 08:15:04 -04:00
53a599c6b8 Merge branch 'feature/numerical-habits' into dev 2017-03-30 23:00:12 -04:00
103c0b57f8 Unify habit creation dialogs 2017-03-28 16:59:08 -04:00
7de69c1c10 Simplify BooleanHabitDialog subclasses and factories 2017-03-28 13:36:49 -04:00
fe7e8ef039 Refactor habit creation dialogs 2017-03-28 12:06:09 -04:00
19f4a19dba Minor changes to BarChart 2017-03-27 19:25:53 -04:00
b66da24e39 Fix the form fields containing examples 2017-03-27 18:41:52 -04:00
3dd33274e4 Small changes to formatValue 2017-03-27 17:50:57 -04:00
c61834e604 Color days on HistoryChart according to target 2017-03-26 16:36:28 -04:00
e082705b0c First version of BarChart 2017-03-26 16:16:13 -04:00
83ce92d8ac Allow fractional values to be entered 2017-03-26 13:19:01 -04:00
177525817c Small changes to the layout of NumberButtonView 2017-03-26 10:57:04 -04:00
1dfa0c6b0d Hide completed according to the target value 2017-03-26 10:32:27 -04:00
b3f039d658 Make score take target value into account 2017-03-26 10:14:23 -04:00
7d2e8573f8 Persist unit and target value of a habit 2017-03-25 19:57:38 -04:00
5653651c0d Update score calculation
The value of a score is now a double. For boolean habits, this number goes from zero
to one and corresponds to the percentage. For numerical habits, it now corresponds
to a weighted average of the checkmark values. Also, for non-daily boolean habits, the
score now increases with implicit checkmarks.
2017-03-25 12:31:19 -04:00
d3b540199c Switch score values from int to double 2017-03-25 10:46:35 -04:00
f0430ffeb3 Use alternative design with units on NumberButtonView 2017-03-25 09:43:52 -04:00
d03edf2895 Update habit creation dialogs 2017-03-24 16:47:40 -04:00
5c1ccfe6fe Fix small issues with the number picker 2017-03-24 10:13:19 -04:00
5b9e90fe7a Persist repetition values 2017-03-24 09:41:52 -04:00
ac32460859 Create number picker dialog 2017-03-24 08:20:59 -04:00
e2a8de3acf Update controllers and HabitCardView 2017-03-23 19:09:44 -04:00
7bf9f88ee3 Implement NumberButtonView and related classes 2017-03-23 18:26:58 -04:00
19e79a8559 Fix failing test 2017-03-20 22:32:53 -04:00
876d4f0ac7 Merge branch 'feature/scroll-header' into dev
Fixes #155
2017-03-20 20:05:26 -04:00
f4f7faf3a4 Fix a few issues with header scrolling 2017-03-20 20:00:10 -04:00
56f2ae57fe Persist scrolling after configuration change 2017-03-20 18:53:48 -04:00
3fe09efe9b Scroll checkmarks 2017-03-19 20:36:16 -04:00
f0de29fbfe Make HeaderView scrollable 2017-03-19 18:31:43 -04:00
324facfffd Re-enable haptic feedback on CheckmarkButtonView 2017-03-19 16:35:57 -04:00
03e58f9ef2 Preserve position of ScrollableChart on configuration changes
Fixes #240
2017-03-18 23:57:54 -04:00
e6c9f7f0c9 Preserve ScrollView position after configuration change
Fixes #239
2017-03-18 22:41:32 -04:00
42bdedb86a Update dependencies 2017-03-18 22:40:38 -04:00
ab0c510fda Rename export action and move to overflow menu 2017-03-18 22:22:07 -04:00
e46fd58664 Fix ImportTest on Nougat 2017-03-17 22:49:52 -04:00
8532bd402e Update APK filename 2017-03-17 22:11:48 -04:00
2c599b18ef Fix ambiguous reference to R 2017-03-17 21:52:51 -04:00
0d78ba4ba9 Update gradle 2017-03-17 21:52:13 -04:00
Janet Do
611dfa00a5 Export data from the statistics screen
Closes #27
2017-02-02 21:31:37 -05:00
Anirudha Agashe
54a195243d Fixed failing build
Replaced static method to obtain context with appropriate dependency
2017-01-18 12:58:56 -06:00
Anirudha Agashe
4fc30fae53 Remove use of static context from HabitsApplication class (#224)
Remove static context from application class. Replace static method to obtain context with appropriate dependency. Remove context from controller. Add auto factory to export db task.
2017-01-09 23:09:05 -05:00
b3fe9c65d2 Refresh data at midnight
Fixes #221
2016-12-31 18:24:26 -05:00
09f1ae8765 Update circle.yml 2016-12-31 12:30:10 -05:00
0a8b763ece Make TimePicker slightly smaller
Fixes #219
2016-12-30 12:58:37 -05:00
edd5f25529 Update circle.yml 2016-12-25 23:56:34 -05:00
d81fdb41dc Remove temp file after importing 2016-12-25 23:50:38 -05:00
02c8810e46 Bump targetSdkVersion to 25 2016-12-25 23:05:47 -05:00
6adf8061d3 Use FileProvider instead of File URIs 2016-12-25 23:05:17 -05:00
d19d57e5df Use Storage Access Framework when importing files 2016-12-25 11:54:08 -05:00
c20d5c8729 Make model classes thread-safe 2016-11-24 20:06:28 -05:00
fd82e6c24b Remember last used order 2016-11-24 06:00:02 -05:00
56263efa39 Sort by score 2016-11-24 05:45:08 -05:00
d5eacba303 Disable drag-and-drop when automatically sorting 2016-11-24 05:27:26 -05:00
222261c674 Add order menu 2016-11-23 06:35:07 -05:00
b1a06df7f8 Implement automatic sorting for SQLHabitList 2016-11-23 05:58:46 -05:00
a1fc7dd0d1 Implement automatic sorting for MemoryHabitList 2016-11-04 05:59:34 -04:00
Justin Inácio
10131d5124 Allow intervals larger than 99 days (#202) 2016-11-02 06:13:31 -04:00
aa94959ad2 Merge tag 'v1.6.2' into dev
v1.6.2
2016-10-13 07:09:19 -04:00
967dc2586b Merge branch 'hotfix/1.6.2' 2016-10-13 07:09:11 -04:00
908fd1d6ae Fix NoSuchMethodError on Android 4.1 2016-10-11 06:34:22 -04:00
45fd8a29e1 Merge tag 'v1.6.1' into dev
v1.6.1
2016-10-10 12:10:23 -04:00
4624acd477 Merge branch 'hotfix/1.6.1' 2016-10-10 12:10:14 -04:00
c8cd4fa389 Delete old database cache 2016-10-10 11:39:18 -04:00
8c4fab28aa Merge tag 'v1.6.0' into dev
v1.6.0
2016-10-10 09:54:29 -04:00
d6b91cef01 Merge branch 'release/1.6.0' 2016-10-10 09:54:20 -04:00
e273fe7375 Automatically repair inconsistent databases before crashing 2016-10-10 08:49:16 -04:00
ab3b946c65 Update translations 2016-10-09 18:23:24 -04:00
38cd47c199 Remove empty title bar on TimePickerDialog 2016-10-09 13:18:36 -04:00
fa64bd389d Update list of developers 2016-10-09 12:47:33 -04:00
d03578fd9e Update changelog 2016-10-09 12:40:02 -04:00
79ae181df2 Bump version to 1.6.0 2016-10-09 12:14:03 -04:00
320dca9070 Automatically change order of days on pre-lollipop 2016-10-09 12:05:57 -04:00
f3b9fc825a HabitMatcher: only compute today's value if needed 2016-10-09 11:58:03 -04:00
50da14022f Fix bug that prevented ringtone from being saved 2016-10-09 11:47:30 -04:00
84a02fe541 Remove duplicate shadows and some duplicate code 2016-10-09 11:32:50 -04:00
b3aa3d14c0 Remove unused resources 2016-10-04 07:52:36 -04:00
e9cdfd23c4 Fix widgets on API 15 2016-10-04 07:43:40 -04:00
659ad2d817 Fix card background color (pre-lollipop) 2016-10-04 07:37:40 -04:00
d537ba0dfa Fix layout issues on pre-lollipop 2016-10-04 07:29:51 -04:00
7c14725d88 Always show menu icons 2016-10-04 06:57:01 -04:00
638b3f763c Fix some crashes on old devices 2016-09-30 08:10:25 -04:00
f876fc50bb Only recalculate all list positions when repairing database 2016-09-30 07:24:29 -04:00
919504ccfb Render widgets in a separate thread 2016-09-30 07:03:23 -04:00
1a8d9e72a1 Add Tasker screenshots 2016-09-25 11:55:16 -04:00
8e82f369c7 Implement Tasker/Locale plugin 2016-09-25 11:01:17 -04:00
0a5677211e Remove reference to MainActivity 2016-09-24 17:02:30 -04:00
65071797c9 SettingsActivity: Fix toolbar color in night mode 2016-09-24 16:49:45 -04:00
df1751b21a Refactor AboutActivity 2016-09-24 16:41:14 -04:00
4e952dd87a Remove MainActivity and use activity-alias 2016-09-24 16:03:41 -04:00
Nikhil
132dce8919 Improve error message on widget
Fixes #168
2016-09-19 21:24:32 -04:00
5c8450191a Make notifications actionable on the Pebble
Closes #126
2016-09-19 18:32:03 -04:00
b1d00598eb Add option to repair database 2016-09-18 08:09:18 -04:00
518ade3165 Add some database checks 2016-09-18 08:08:56 -04:00
dc5d7930a6 Merge pull request #173 from JotraN/dev
Add exporting scores and checkmarks files with multiple habits (#68).
2016-09-17 12:38:27 -04:00
jotran
ec34043041 Add exporting scores and checkmarks files with multiple habits (#68).
Add writeMultipleHabits to write a scores file and a checkmarks file
that contains scores and checkmarks of multiple habits.
Add getTimeframe because it was necessary to get the timeframe between
all habits so that row data could be populated correctly for habits that
started before/after other habits.
Move writeCheckmarks to below writeScores since it wasn't called until
after writeScores in writeHabits.

Add getByInterval to ScoreList, MemoryScoreList, and SQLiteScoreList to
get scores between a given interval - simiarly to CheckmarkList.

Add getValues (ScoreList) to get all values between a given timeframe.

Add getNewest to get the newest repetition in a list and to correspond
with getOldest.

Add getDaysBetween to DateUtils to quickly get the number of days
between two timestamps.

Add tests for the new functions.
2016-09-17 09:04:49 -07:00
4d5407a5cc Fix bug on compute methods that prevented them from recomputing old values 2016-09-16 13:17:52 -04:00
904489d812 Remove debug log 2016-09-16 11:41:20 -04:00
d2436a3165 Merge pull request #174 from Donaira/dev
Increase width of name column according to screen size
2016-09-14 15:35:21 -04:00
Donaira Tamulynaitė
bc19858bca Habit label takes up to 1/3 screen width. 2016-09-14 13:03:38 +03:00
a998a62cdb Remove notification when habit is deleted 2016-09-11 11:35:32 -04:00
1a89bb02be Add option to make notifications sticky 2016-09-11 10:40:43 -04:00
6e8ea471aa Do not cancel notifications automatically 2016-09-11 09:55:47 -04:00
ec42fb54f4 Do not store position of ViewHolder 2016-09-11 09:35:53 -04:00
c46fa84135 Fix bug that made it impossible to disable a reminder 2016-09-11 09:18:06 -04:00
16dcc0cbc2 Fix tests 2016-09-11 09:04:39 -04:00
6f10039aba Merge pull request #171 from regularcoder/dev
Add repetition count to overview card
2016-09-11 08:10:34 -04:00
RegularCoder
5cbc0a3292 Add repetition count to overview card, for #115 2016-09-05 21:14:12 -04:00
7f67a9eb63 Revert concurrent AsyncTasks 2016-09-03 09:37:16 -04:00
d3f7ebd60c SQLiteHabitList: fix corrupted order automatically 2016-09-03 09:33:09 -04:00
461fe1f0b6 Improve performance 2016-09-03 09:25:23 -04:00
8eb9f398d5 Allow multiple AsyncTasks to run concurrently
Fixes #134
2016-09-03 09:00:20 -04:00
f178bcbdd2 CheckmarkButtonView: avoid layout inflation 2016-09-03 08:00:36 -04:00
66c3136fad Allow views to be rendered by the layout editor 2016-09-03 07:46:41 -04:00
4b04966617 Update AMOLED mode upon exiting settings
Fixes #118
2016-09-02 22:24:21 -04:00
3ea21fe823 Update order of checkmark buttons automatically upon exiting settings 2016-09-02 21:13:56 -04:00
e0df69beb6 Prevent progress bar from flickering 2016-09-02 21:03:09 -04:00
b5cd4584b2 Disallow empty WeekdayLists 2016-09-02 21:02:38 -04:00
af7c8b1f2e Merge pull request #170 from regularcoder/dev
Fix issue#65 by setting launchMode to singleTop
2016-09-02 06:30:48 -04:00
RegularCoder
283cb2a3f0 Fix issue#65 by setting launchMode to singleTop 2016-09-01 21:43:28 -04:00
79ddbca307 Fix ripple when days are reversed 2016-08-29 20:57:43 -04:00
46a0777195 Restore progress bars 2016-08-29 20:53:48 -04:00
b35305e16c Preferences: update link to AboutActivity 2016-08-29 20:03:25 -04:00
8c4a745ecb Merge pull request #165 from klanmiko/enhancement/archive
Fix #161 reminder disable on archive
2016-08-22 22:38:03 -04:00
klanmiko
e5162c48ab Scheduler should ignore archived habits
Also consider changing "archive" to "inactive"
2016-08-22 19:00:36 -07:00
b54c4de5f7 ShowHabitRootView: update title automatically
Fixes #162
2016-08-22 17:02:20 -04:00
2bdc0b4f5e Update unit tests for ListHabitsMenu 2016-08-22 16:48:58 -04:00
22db61db01 Fix crash on startup and after dismissing notification 2016-08-22 16:40:23 -04:00
c7cfbd1643 Allow cards to be rendered by the layout editor 2016-08-07 08:43:18 -04:00
8655437f3e Change 'show completed' to 'hide completed' 2016-08-05 19:37:47 -04:00
3ad3cf54ec Add tests for HabitCardView 2016-08-05 07:54:06 -04:00
9a470cc61d Initialize db earlier; fixes crash 2016-08-05 06:30:32 -04:00
fc2087fe68 Write tests for ListHabits controller, menu and screen 2016-08-04 21:56:38 -04:00
7b8ab6a625 Dismiss notification automatically 2016-08-04 07:46:10 -04:00
2d40fb0b82 Write tests for receivers 2016-08-04 07:34:38 -04:00
c961045b63 Call refresh from UI thread 2016-08-04 06:15:43 -04:00
d0db3359fe Allow StyledResources to receive a fixed theme for testing 2016-08-03 22:27:49 -04:00
11378e07bf Properly initialize appComponent 2016-08-03 22:13:30 -04:00
8132188e46 Replace Singleton by AppScope 2016-08-03 07:48:58 -04:00
7eb454788f Refactor receivers 2016-08-03 07:37:00 -04:00
c262adbe85 Move Preferences to their own package 2016-07-31 08:47:20 -04:00
05aa5b1172 Replace InterfaceUtils theme methods by ThemeSwitcher 2016-07-31 08:42:40 -04:00
dd3d78b82c Filter Dagger classes from coverage report 2016-07-31 08:39:47 -04:00
3d4ae2126b Remove DialogFactory 2016-07-31 08:03:07 -04:00
5aa9114aff Fix name of Ukrainian language 2016-07-30 21:58:06 -04:00
77e0ad007f Update list of developers 2016-07-30 21:56:27 -04:00
2e53b75705 Merge pull request #151 from sciamano/freq2
relative size of the marks in the frequency view
2016-07-30 21:24:30 -04:00
Denis
0ec03035f5 maximal frequency of the data 2016-07-30 21:26:09 +02:00
Denis
67ae48b527 radius and color of the mark in the frequency view 2016-07-30 21:26:06 +02:00
Denis
82d2931559 fix code duplication 2016-07-30 21:26:01 +02:00
a527140802 Use the same HabitCardListCache for all activities
Fixes #147
2016-07-29 07:40:56 -04:00
9ec3d9048a Make Preferences listen for external changes 2016-07-29 07:28:44 -04:00
3ed4f3b280 Make scrolling very smooth again 2016-07-29 07:21:47 -04:00
f101975320 Take timezone into account when scheduling alarms 2016-07-29 07:07:02 -04:00
3a7f27755c Use hashmap on AndroidTaskRunner 2016-07-29 07:06:49 -04:00
3a3be664f7 Fix some bugs on fragments and model listeners 2016-07-28 21:45:54 -04:00
33ae8d1edf Show empty message at startup 2016-07-28 21:45:54 -04:00
cb3b8f2cde Reorganize sections and add GPLv3 logo 2016-07-28 18:30:11 -04:00
307e025b1a Fix CheckmarkListTest 2016-07-28 08:00:01 -04:00
03dd24d17b Clean up BaseUnitTest 2016-07-28 07:42:03 -04:00
5f4ac21a41 Small changes 2016-07-27 20:29:13 -04:00
b33616d363 Remove old .gitmodules 2016-07-27 19:30:37 -04:00
b7d1c6d254 Update copyright notice 2016-07-27 19:01:05 -04:00
bd30ceee1b Fix small layout issue. 2016-07-27 18:58:51 -04:00
fe96313162 Update NOTICE.md 2016-07-27 18:56:24 -04:00
938fe3325e Remove disabled test 2016-07-27 18:13:02 -04:00
237de035bb Remove remaining static references to app component 2016-07-27 18:09:36 -04:00
ddc85ced0b Remove waitForTasks 2016-07-27 17:10:07 -04:00
eceb1bfb7d Remove most static references to app component; fix tests 2016-07-27 17:05:51 -04:00
3b737996e9 Reorganize packages 2016-07-27 00:03:59 -04:00
7f75f9b6da Construct ListHabits using dagger 2016-07-26 23:52:39 -04:00
74f78f0fdf Improve usage of dagger 2016-07-26 19:26:42 -04:00
ef63dd19e7 Fix reference to MainActivity 2016-07-25 17:03:09 -04:00
c7878d979f Switch from toasts to snackbars 2016-07-25 08:58:28 -04:00
ebd294be63 Split InterfaceUtils 2016-07-25 08:31:26 -04:00
748cec06a8 Dagger: replace injects by getters 2016-07-23 21:18:20 -04:00
15a4a2c002 Refactor reminders; replace int by WeekdayList 2016-07-23 19:19:22 -04:00
37a9e793e7 Add tests for HabitCardListCache; refactor TaskRunners 2016-07-23 18:06:03 -04:00
d54de9df89 Refactor tasks; break progress bars 2016-07-23 11:45:59 -04:00
94a5db2208 Add view tests 2016-07-22 08:01:44 -04:00
a984467516 Some refactoring; add tests for ListHabitsScreen 2016-07-21 22:48:37 -04:00
d6dacfd24b Refactor reminder scheduling, add tests 2016-07-20 17:01:24 -04:00
3938ae6fa8 Fix test sizes 2016-07-18 20:57:21 -04:00
7dbbc51a9a Add task for combined coverage report 2016-07-18 10:53:23 -04:00
c9d1bb821c Refactor pending intents 2016-07-18 09:07:21 -04:00
77f406dcee Refactor broadcast receivers and add a public receiver
Fixes #6
2016-07-17 17:28:14 -04:00
61b0b1fdea Use separate broadcast actions for widgets and notifications 2016-07-17 09:32:42 -04:00
8cde0d6aca HistoryChart: make toggling faster 2016-07-17 09:32:21 -04:00
fa9f90a09e Refactor HeaderView; update list on resume 2016-07-17 08:59:34 -04:00
28eb615b0e Notification: add checkmark instead of toggling 2016-07-17 08:43:14 -04:00
c1e10e09a5 Refresh list after importing DB 2016-07-17 08:30:07 -04:00
35e93fddc6 Use dynamic number of streaks on widget 2016-07-17 08:28:19 -04:00
33596a2797 Restore dynamic number of checkmarks 2016-07-17 08:02:31 -04:00
207f026ceb Fix habit creation 2016-07-16 10:35:55 -04:00
0f12d02990 Use same cache for every SQLHabitList 2016-07-16 10:12:06 -04:00
bc4bbaefac Remove some drag-and-drop glitches 2016-07-15 09:33:57 -04:00
a802053ef7 Update .gitignore 2016-07-15 09:33:07 -04:00
cf98d1a5c3 AndroidTest: Increase timeout 2016-07-14 11:54:15 -04:00
cc1e56894b Fix test scripts 2016-07-14 11:30:21 -04:00
06b5f89b7a Make habit deletions instantaneous
Fixes #133
2016-07-14 10:57:45 -04:00
17423b3ecd Fix most issues with the RecyclerView; improve loading 2016-07-14 10:15:56 -04:00
1526f617c5 Remove most animation glitches on RecyclerView; disable reordering 2016-07-11 22:06:30 -04:00
365eb400d0 Add proguard file 2016-07-11 09:04:36 -04:00
785d57c778 Merge branch 'dev' of github.com:iSoron/uhabits into dev 2016-07-11 09:03:24 -04:00
8e9f1aa166 Add basic API for the Pebble app 2016-07-11 08:47:00 -04:00
b2f97cb0a5 Merge pull request #145 from ajbarnes/dev
Add 24hr snooze. Fixes #103
2016-07-06 04:39:00 -04:00
Adam Barnes
4c1ff4f0a8 Add 24hr snooze. Fixes #103 2016-07-05 23:44:16 -04:00
94a48133ec Merge branch 'feature/recyclerview' into dev 2016-07-01 10:22:06 -04:00
71dd6cde89 Restore drag & drop and click; remove DragSortListView library 2016-07-01 09:23:07 -04:00
b33420cabb Replace ListView with RecyclerView 2016-07-01 08:03:30 -04:00
dbe268b8e9 Add simple filter to menu 2016-06-30 07:23:28 -04:00
3d53812d7f Restore CircleCI badge 2016-06-29 21:31:34 -04:00
5b4b436f0f CircleCI: use JDK8 2016-06-29 21:10:22 -04:00
6ef2983906 Implement filter by colors 2016-06-29 20:12:09 -04:00
b749f7f391 Fix CircleCI scripts 2016-06-29 20:11:39 -04:00
922b234307 Initial implementation of filters 2016-06-29 19:49:19 -04:00
31fdae1c8b Merge branch 'feature/refactoring-mvc' into dev 2016-06-29 12:23:04 -04:00
5d61fdd3d0 Write tests for HintView 2016-06-29 10:03:56 -04:00
588b45d47b Merge branch 'dev' into feature/refactoring-mvc 2016-06-28 22:48:45 -04:00
9a059275ce Merge branch 'dev' into feature/refactoring-mvc 2016-06-28 22:46:17 -04:00
4ae813e6f9 Restore all widgets 2016-06-28 22:39:24 -04:00
52701666bc Start refactoring widgets 2016-06-28 12:11:34 -04:00
a90e26691f Fix HistoryEditorDialog 2016-06-26 17:10:17 -04:00
f0c62a5908 Update run_tests script to run JVM tests 2016-06-26 17:07:38 -04:00
e899a70eb0 Fix most tests 2016-06-25 05:53:19 -04:00
aa41717c66 Remove CircleCI temporarily 2016-06-25 05:43:49 -04:00
6ba6d7c8c1 Refactor ShowHabit screen; remove fragment 2016-06-24 14:52:41 -04:00
efd0d1e051 Refactor ShowHabit fragment; break widgets 2016-06-24 08:39:48 -04:00
a11ad6e909 ShowHabit: Refactor score chart 2016-06-22 19:47:16 -04:00
a060cbe578 ShowHabit: Refactor subtitle and overview 2016-06-22 08:48:08 -04:00
a445ca962b Merge tag 'v1.5.6' into dev
v1.5.6
2016-06-19 17:10:17 -04:00
2b6fc06b86 Merge branch 'hotfix/1.5.6' 2016-06-19 17:10:12 -04:00
98ad3aab9d Make checkmark widgets work again 2016-06-19 17:06:03 -04:00
c7e63a40da Bump version to 1.5.6 2016-06-19 17:04:25 -04:00
b6ed33b1e6 Merge branch 'dev' into feature/refactoring-mvc 2016-06-19 16:16:04 -04:00
91e39372a1 Merge tag 'v1.5.5' into dev
v1.5.5
2016-06-19 10:08:26 -04:00
c2dd26eeb3 Merge branch 'hotfix/1.5.5' 2016-06-19 10:08:19 -04:00
5831340343 Update French translation; add Slovenian and Croatian translations 2016-06-19 09:57:45 -04:00
d7f6f52a49 Always refresh data after resuming
Fixes #120
2016-06-19 09:32:42 -04:00
93b442332d Bugfix: add check on correct date when checking from notification 2016-06-19 09:08:34 -04:00
e248824bcd Bump version to 1.5.5 2016-06-19 08:08:00 -04:00
ec4a381d70 Refactor Habit class 2016-06-17 07:29:48 -04:00
b13f2b4228 Create a class for Reminders 2016-06-16 15:19:02 -04:00
efc7b2cebb Replace ActiveAndroid queries with raw SQLite queries 2016-06-16 13:51:36 -04:00
add08d6054 Fix reordering 2016-06-15 10:12:33 -04:00
5d8a348aaf Hide empty message at startup 2016-06-15 09:54:39 -04:00
ec0e8ac24c Cancel selection with back button correctly 2016-06-15 09:48:01 -04:00
fee3137a6f Move ripple to correct place 2016-06-15 05:39:13 -04:00
abe6b10964 Restore dynamic checkmark button count 2016-06-15 05:32:20 -04:00
6484b96e5a Reformat and reorganize some code 2016-06-15 05:04:12 -04:00
3d3d5b9b96 Fix top navigation on Settings and About screens 2016-06-15 05:02:13 -04:00
14364901ff Reorganize instrumented tests 2016-06-14 05:46:31 -04:00
440706882b Move command tests to JVM 2016-06-14 05:30:30 -04:00
ca9d56e59e Fix toolbars 2016-06-12 18:22:04 -04:00
9a6dafaa79 Improve documentation 2016-06-12 09:23:55 -04:00
9a44774284 Add instrumented unit tests for SQLite lists 2016-06-12 07:55:47 -04:00
2b23b36e36 Move remaining model tests to JVM; simplify SQLite implementation 2016-06-10 18:55:32 -04:00
78d4f86cab Separate ActiveAndroid from models 2016-06-10 13:30:33 -04:00
18e8390aed Merge branch 'dev' into feature/refactoring-mvc 2016-06-05 04:37:46 -04:00
cabcd5b1bf CSV export: allow spaces on filename and fix tests 2016-06-04 22:06:01 -04:00
7e8a2a0c1c Major refactoring of ListHabitsActivity 2016-06-04 18:10:33 -04:00
650971bf36 Merge tag 'v1.5.4' into dev
Version 1.5.4
2016-05-29 12:06:46 -04:00
00774368d4 Merge branch 'hotfix/1.5.4' 2016-05-29 12:06:36 -04:00
cbf1bd3e19 Update changelog 2016-05-29 11:57:33 -04:00
4061921b93 Add Serbian translation 2016-05-29 11:56:57 -04:00
59d42fe62f Show empty ringtone name in case of RuntimeException
Fixes #116
2016-05-29 11:47:36 -04:00
3ffa079e24 Remove code duplication 2016-05-28 13:03:37 -04:00
bb950d61fc Move sendFile and sendEmail to Screen 2016-05-28 12:21:38 -04:00
0ad0e5cf36 Fix time out on tests 2016-05-28 12:20:02 -04:00
3b56d6d596 Add missing file 2016-05-28 10:16:21 -04:00
8d57273987 Refactor EditHabitDialog 2016-05-28 10:15:55 -04:00
b98853ab26 Introduce ButterKnife 2016-05-27 23:02:04 -04:00
071cad73d4 Make models observable, refactor ShowHabitFragment 2016-05-27 22:26:33 -04:00
16dc9c25d2 Fix bug that caused checkmarks not to update sometimes 2016-05-27 14:06:55 -04:00
6b23858136 Create HabitListView and move most code from Fragment to it 2016-05-27 12:19:29 -04:00
e0198e9926 Reorganize files 2016-05-27 10:20:16 -04:00
6445bf62bc Refactor MainActivity and Preferences 2016-05-26 16:35:47 -04:00
83ef8564e1 Reorganize file tree according to feature 2016-05-26 10:38:59 -04:00
88e8aad0d8 CSV export: sanitize habit name before creating folder
Fix #113
2016-05-25 10:09:39 -04:00
a4b6728721 Bump version to 1.5.4 2016-05-25 10:09:11 -04:00
e6e80b9841 Update sync protocol 2016-05-22 18:28:06 -04:00
442c3ed78d Merge branch 'dev' into feature/sync 2016-05-22 17:50:14 -04:00
ca9745f550 Merge tag 'v1.5.3' into dev
Version 1.5.3
2016-05-22 12:56:36 -04:00
33bc8f78e7 Merge branch 'hotfix/1.5.3' 2016-05-22 12:56:28 -04:00
0f223f8504 Update changelog 2016-05-22 12:56:15 -04:00
007996c69e Update translations 2016-05-22 12:50:42 -04:00
ff9d50b32a Remove debug code 2016-05-22 12:29:37 -04:00
38024d71ce Allow checkmark widget to be resized to very small sizes 2016-05-22 12:24:28 -04:00
9ec1afc208 Remove associated preference after deleting widget 2016-05-22 10:28:58 -04:00
e0888a9b4d Remove fields from BaseWidgetProvider
This caused a bug when multiple widgets had different sizes. The size of the
last widget would be used in all of them.
2016-05-22 10:27:27 -04:00
8aade2f145 Fix crash when habits with reminders have short names
Fixes #109
2016-05-22 09:33:30 -04:00
1ba1d775f7 Bump version to 1.5.3 2016-05-22 09:24:20 -04:00
605593d739 Update UI tests 2016-05-19 12:51:36 -04:00
bfbfcbd8cf Merge tag 'v1.5.2' into dev
Version 1.5.2
2016-05-19 12:01:37 -04:00
bd6cba8303 Merge branch 'hotfix/1.5.2' 2016-05-19 12:01:29 -04:00
befc3a0ad8 Update changelog 2016-05-19 12:01:24 -04:00
f4c963e2c1 Update Japanese translation 2016-05-19 11:58:20 -04:00
e9a4a047c1 Trim habit names on log files 2016-05-19 11:50:38 -04:00
7ce1988d2e Fix NullPointerException on RingView 2016-05-19 11:46:02 -04:00
53911fa410 Send bug report on the body of email, instead of attachment 2016-05-19 11:39:17 -04:00
f5f43d9a16 Bump version to 1.5.2 2016-05-19 10:40:45 -04:00
2399dccddc Emit JSON object instead of string 2016-05-19 10:35:44 -04:00
dd5f37290c Merge branch 'dev' into feature/sync 2016-05-17 10:58:53 -04:00
dbf569ff87 Merge tag 'v1.5.1' into dev
v1.5.1
2016-05-17 09:36:00 -04:00
d0e475ad78 Merge branch 'hotfix/1.5.1' 2016-05-17 09:35:51 -04:00
b3199cf092 Update version and changelog 2016-05-17 09:35:10 -04:00
73e6f2a2d4 Remove ActiveAndroid.jar 2016-05-17 09:29:53 -04:00
5b402478e9 Use encrypted connection to server (TLS) 2016-05-16 22:29:10 -04:00
e3b7e9f60f Persist pending events to database 2016-05-16 08:20:08 -04:00
b0040bd83c Fetch commands since last sync 2016-05-15 09:06:25 -04:00
56e1268f85 Sync remaining commands 2016-05-15 09:06:25 -04:00
41d9e2f0f5 Sync archive/unarchive commands 2016-05-15 09:06:25 -04:00
1fcfb9b22e First version of sync feature 2016-05-15 09:06:25 -04:00
2c80544aaa Merge tag 'v1.5.0' into dev
Version 1.5.0
2016-05-15 08:43:39 -04:00
097a5be864 Merge branch 'release/1.5.0' 2016-05-15 08:43:26 -04:00
0287473e61 Update changelog 2016-05-15 08:40:58 -04:00
f403dc6f77 Update view tests 2016-05-15 08:40:27 -04:00
23466523df Remove minTextSize
This was causing problems, since some launchers completely
ignore minimum widget sizes. When widgets were too small,
the text started to overflow.
2016-05-15 08:21:46 -04:00
83ca136346 Update changelog 2016-05-13 07:09:09 -04:00
7830b599db Bump version to 1.5.0 2016-05-13 06:52:32 -04:00
49376d4f41 Minor changes to widget colors 2016-05-13 06:50:35 -04:00
8ee9c9c0b1 Update screenshots 2016-05-13 06:50:22 -04:00
ee9da29422 Update introduction 2016-05-13 06:42:22 -04:00
ae7b0408b2 Update list of complete translations 2016-05-13 06:29:19 -04:00
d926d9dbd6 Keep name of the app consistent across translations 2016-05-13 06:14:40 -04:00
5694da2413 Add new translations and update list of contributors 2016-05-13 06:08:09 -04:00
7e0ae144b8 Update translations 2016-05-13 04:56:02 -04:00
1426d887e7 CircleCI: Ignore some branches 2016-05-13 04:41:15 -04:00
acb8e820fd Use AlertDialog from Support Library 2016-05-11 07:38:43 -04:00
eae0d66f51 Dismiss notification automatically when user adds a checkmark 2016-05-11 07:30:45 -04:00
e933cbbc43 Fix up navigation when opening the app from widget
Fixes #94
2016-05-11 06:44:11 -04:00
0b95b6a78c Install build-tools before compiling 2016-05-08 08:51:08 -04:00
5e873a3659 Make frequency text more natural 2016-05-08 08:46:45 -04:00
d292ecd988 Increase default amount of memory for gradle 2016-05-08 08:24:14 -04:00
19b484c368 Fix crash on settings screen 2016-05-08 08:23:50 -04:00
834ae92d87 Reschedule alarms on boot
Fixes #93
2016-05-08 08:04:24 -04:00
26ce92d381 Update versions 2016-05-08 07:38:57 -04:00
0eb12812d4 Allow user to reverse the order of days 2016-05-04 06:30:06 -04:00
a1a636c718 Make ScoreView use custom interval also on widgets 2016-05-01 10:06:02 -04:00
b2811b9797 Allow user to select reminder sound
Closes #63
2016-05-01 09:43:28 -04:00
4db7a6e89c Show larger ripple when toggling check marks
Closes #78
2016-05-01 08:21:36 -04:00
677a643e5b Allow theme to be fixed during tests 2016-04-30 19:13:36 -04:00
dbca3238f6 Small changes to ScoreView 2016-04-30 17:14:44 -04:00
ae5dd700f3 Fix widget colors and size 2016-04-30 16:42:27 -04:00
7e4c508d7d Merge branch 'feature/ring-view' into dev 2016-04-30 12:44:25 -04:00
d0c056eeaa Update screenshots 2016-04-30 12:43:18 -04:00
f172c69eed Update tests 2016-04-30 12:30:20 -04:00
0cd4a41438 Bump gradle version 2016-04-29 11:48:46 -04:00
d77c78249c Tweak layout to work with older phones with smaller screen 2016-04-29 11:48:06 -04:00
d9d48ff984 Minor UI changes 2016-04-29 07:55:45 -04:00
7be71ba4f8 Fix icon colors and remove some warnings 2016-04-29 07:44:06 -04:00
f0534fefbc Show more information on score overview 2016-04-29 07:35:38 -04:00
30ef75bb45 Alternative design for header bar 2016-04-29 06:40:02 -04:00
44ed74a693 Correct colors 2016-04-29 06:38:19 -04:00
4aea527e07 Fix some crashes on widgets 2016-04-27 06:01:10 -04:00
638539259a Bump gradle version 2016-04-26 20:09:06 -04:00
75dec88411 Update widget previews 2016-04-26 20:08:59 -04:00
2dc4fcbc46 Fix transparency on widgets 2016-04-25 22:22:37 -04:00
7977d5247c Tweak transparency and colors 2016-04-25 21:03:23 -04:00
8b18e32a16 Create color palette for widgets 2016-04-24 06:42:14 -04:00
dbcad9a5f4 Use dark theme for widget colors 2016-04-24 06:42:14 -04:00
3bba75ff50 Add ripple effect to check mark widget 2016-04-24 06:42:14 -04:00
9bbeee66e2 Impose max number of lines on habit list 2016-04-24 06:42:14 -04:00
c6e76f4cfd Show multiple lines on check mark widget 2016-04-24 06:42:14 -04:00
980db1d171 Add ring to check mark widget 2016-04-24 06:42:14 -04:00
aee5d975db Replace star by ring 2016-04-24 06:42:14 -04:00
e2bb4371d3 Fix UI test for settings screen 2016-04-24 06:37:15 -04:00
fcee8552f0 Switch to compat ActionMode; fix tests 2016-04-24 05:55:42 -04:00
a4864e4612 Extract some strings; move definitions to correct file
Fixes #81
2016-04-21 06:05:38 -04:00
8ddf4574e3 Fix failed view tests 2016-04-20 09:27:44 -04:00
f1ca8c5449 Merge branch 'feature/material-compat' into dev 2016-04-20 07:52:06 -04:00
81a188f125 Customize action mode colors 2016-04-20 07:50:12 -04:00
44402bf3a4 Fix progress bar position 2016-04-20 07:31:02 -04:00
7f159149ef Minor layout changes on the spinners 2016-04-19 22:50:41 -04:00
0c1e8d5131 Switch to AppCompatDialogFragment and compat Fragment 2016-04-19 22:10:25 -04:00
a4e3f7e037 Fix spinners on EditHabitDialog 2016-04-19 21:53:14 -04:00
b354a0765b Use grey toolbar on pre-Lollipop 2016-04-19 21:02:05 -04:00
bbd959dfda Fix borders on HistoryEditorDialog 2016-04-19 09:01:36 -04:00
d05d404c55 Show toolbar shadow on pre-Lollipop 2016-04-19 08:27:45 -04:00
8938b0c9a6 Improve settings screen 2016-04-19 07:50:05 -04:00
bd6fcd066c Fix dialog borders 2016-04-19 05:36:34 -04:00
6a5f2abb76 Switch to AppCompatActivity 2016-04-18 07:59:41 -04:00
33b5215b00 Use SwitchPreference instead of checkmarks 2016-04-18 06:21:04 -04:00
5d808dd2e8 Update padding on widgets 2016-04-16 09:20:33 -04:00
767ec1b6de Minor layout improvements for HabitScoreView 2016-04-16 09:16:39 -04:00
9e5f3d8f58 Fix blinking when updating widgets 2016-04-16 09:03:45 -04:00
775d028629 Add missing icon 2016-04-16 08:51:56 -04:00
4bfb839370 Draw separate widgets for landscape and portrait modes
Fixes #76
2016-04-16 08:51:20 -04:00
8f64b696d8 Remove debug messages 2016-04-16 08:10:12 -04:00
c4bf31e778 Adjust text size and position on HistoryView and StreakView 2016-04-16 08:06:01 -04:00
c757ce6548 Enforce min text size on HabitScoreView 2016-04-16 07:36:39 -04:00
78994bb3c4 Add screenshots for night mode 2016-04-15 19:12:45 -04:00
2373ba5407 Update screenshots 2016-04-15 19:10:38 -04:00
b601a643dd Merge branch 'feature/dark-theme' into dev 2016-04-15 18:29:39 -04:00
90e513e778 Remove warning when palette cannot be found 2016-04-15 18:26:01 -04:00
728c9557f0 Migrate DB to new color format 2016-04-15 18:25:30 -04:00
5bd0c842f5 Minor typo 2016-04-15 18:10:34 -04:00
97711087f9 Fix invisible text on widgets 2016-04-15 17:49:10 -04:00
2fe2d8834a Fix spinner theme on pre-lollipop 2016-04-15 17:41:16 -04:00
93a893d660 Replace icons with Material icons
Fixes #9
2016-04-15 16:34:22 -04:00
feff9a18e6 Fix action icons 2016-04-15 16:13:52 -04:00
b42565b770 Backport dark theme to pre-lollipop devices 2016-04-13 11:54:24 -04:00
3de702ced2 Fix colors in About screen 2016-04-13 10:44:11 -04:00
42f7f4042d Add option for AMOLED night mode 2016-04-13 10:38:20 -04:00
2115a590f2 Add fade transition when switching themes 2016-04-13 09:53:37 -04:00
f5f3ec9f88 Update tests for custom views 2016-04-12 23:42:02 -04:00
6d5a8f5753 Merge branch 'sciamano-day-of-week' into dev 2016-04-12 23:29:10 -04:00
06fc04092b Code cleanup 2016-04-12 23:21:00 -04:00
Denis
24c02605d1 Select first day of week according to the current locale 2016-04-12 23:11:32 -04:00
11fcb67624 Improve custom views' colors 2016-04-11 18:11:18 -04:00
abc92e390a Update list of translators 2016-04-10 12:59:42 -04:00
52c07660b1 Implement menu item to switch between themes 2016-04-10 10:41:52 -04:00
35f778c376 Do not use habit color as primary color on dark themes 2016-04-10 08:32:01 -04:00
436ae7e574 Update selected_box colors for dark theme 2016-04-10 08:17:36 -04:00
5c683a77c2 Fix ripple on ListHabitsFragment 2016-04-10 08:13:05 -04:00
dd1f6c9efc Change habit.color palette according to current theme 2016-04-09 20:01:35 -04:00
cba089407b Merge tag 'v1.4.1' into dev
Loop 1.4.1
2016-04-09 05:36:12 -04:00
a7b0395a2a Merge branch 'hotfix/1.4.1' 2016-04-09 05:36:05 -04:00
7d2946360f Update changelog 2016-04-09 05:31:07 -04:00
04e8432522 Widgets: show error message instead of crashing 2016-04-09 05:27:39 -04:00
13d34945b4 Merge branch 'poeditor' into hotfix/1.4.1 2016-04-09 05:10:41 -04:00
756578508e Bump version to 1.4.1 2016-04-09 05:10:20 -04:00
38fc7650b9 Update translations 2016-04-09 05:08:02 -04:00
cf06ec0a4b Fix chart colors 2016-04-09 04:58:26 -04:00
f0701f7b35 First version of dark theme 2016-04-08 17:15:14 -04:00
de8018af7d Delete unused resources 2016-04-08 15:53:47 -04:00
ac885e1503 Refactor ListHabitsFragment layouts and styles 2016-04-08 15:50:51 -04:00
f85e09288c Add link to open beta on Google Play 2016-04-07 18:03:46 -04:00
6f11596bb7 Merge tag 'v1.4.0' into dev
Loop 1.4.0
2016-04-07 17:48:50 -04:00
64c4367706 Merge branch 'release/1.4.0' 2016-04-07 17:48:33 -04:00
c08702341a Update Spanish translations 2016-04-07 17:23:01 -04:00
abb8c09bc9 Update widgets after executing command 2016-04-07 17:15:33 -04:00
87255ceb25 RingView: invalidate after updating percentage and color
Fixes #79
2016-04-07 17:02:02 -04:00
aedbfded0f Show POEditor link if language is not fully translated 2016-04-06 06:33:52 -04:00
779c0040bd Add some options back to settings screen 2016-04-05 13:32:46 -04:00
7bba6a887f Increase width of chart labels as needed 2016-04-05 08:11:37 -04:00
52a1d19793 Allow labels to expand 2016-04-05 06:50:42 -04:00
35e346e7ea Remove empty strings from translations 2016-04-05 06:42:32 -04:00
3102158bdb Merge branch 'poeditor' into release/1.4.0 2016-04-05 06:34:00 -04:00
7afa65a53c Add Czech translation 2016-04-05 06:33:48 -04:00
2e5533d480 Update translations (POEditor) 2016-04-05 06:28:35 -04:00
b29c7e695a Save failed views to SD card root if writable 2016-04-05 05:47:09 -04:00
7df745eb82 Update CHANGELOG 2016-04-04 20:49:57 -04:00
c0d518ca4d Bump version to 1.4.0 2016-04-04 19:48:49 -04:00
eeff14a2ca Bump version to 1.4.0 2016-04-04 19:31:35 -04:00
af3b18f518 Fix incorrect date format for some languages 2016-04-04 19:05:24 -04:00
3811f4b339 Rename tests for compatibility with AWS Device Farm 2016-04-04 11:15:17 -04:00
50a8aece6f Move expensive call to background thread 2016-04-04 08:18:59 -04:00
2f66cfc417 Minor string change 2016-04-04 08:07:10 -04:00
132ce36a57 More detailed logs in case getFilesDir fails 2016-04-04 07:58:07 -04:00
147f010d1b Update website URL 2016-04-04 07:57:28 -04:00
afc91ed89a Merge branch 'feature/performance' into dev 2016-04-04 07:04:22 -04:00
684c37d167 Update list of translators 2016-04-04 07:02:41 -04:00
8b296ce2ae Make setup method public 2016-04-04 06:56:02 -04:00
e2e9e2e27a Remove debug code 2016-04-04 06:54:12 -04:00
8b2f31c44a Update widget preview 2016-04-04 06:53:55 -04:00
83db9fe2f2 Hide progress bar on startup 2016-04-04 06:46:16 -04:00
9891139b5a Fix tests on ICS 2016-04-04 06:43:42 -04:00
cbc8cbfea3 Fix scores with null habit 2016-04-04 06:02:56 -04:00
96c46b655d Minor refactoring 2016-04-04 05:43:07 -04:00
0de52d4fa3 BaseTask: move register/unregister to onPre/PostExecute 2016-04-04 05:42:27 -04:00
16d85dc4c7 Update README.md 2016-04-03 12:41:57 -04:00
c51b1fd399 Remove progress bar; switch to BaseTask 2016-04-03 07:51:54 -04:00
eb8dd1d450 Simplify and optimize loading time of ShowHabitFragment 2016-04-03 07:46:08 -04:00
357646152f Use postInvalidate instead of invalidate 2016-04-03 07:27:37 -04:00
ae5be202b2 Add convenience methods for tracing 2016-04-03 07:27:16 -04:00
cc3e2153d0 Allow BaseTask to publish integer progress 2016-04-03 07:26:40 -04:00
7433a2413d Refactor BaseTask interface 2016-04-03 06:45:10 -04:00
1cd8eb6849 NumberView: do not request layout on setNumber 2016-04-03 05:11:45 -04:00
7f009e2365 Create indexes in database 2016-04-03 05:10:13 -04:00
4cec7d7367 Implement methods to generate huge test database 2016-04-03 05:08:57 -04:00
f59c0bd7ff Replace badges 2016-04-02 13:58:38 -04:00
2d2bb8b4ed Render widgets in background 2016-04-02 13:32:04 -04:00
e476096ae1 Fix view tests 2016-04-02 11:47:28 -04:00
e2c814a982 Fix ShowHabitFragment and HistoryEditorDialog 2016-04-02 10:48:33 -04:00
4fcaa68baf Throw exception when slow methods are executed on the main thread 2016-04-02 10:27:45 -04:00
02e45dbe27 Rename DialogHelper to UIHelper 2016-04-02 10:14:21 -04:00
bf6562f854 Update views on background thread 2016-04-01 17:50:14 -04:00
3c927e009a Improve performance of Score computation 2016-04-01 17:49:17 -04:00
a9bcae0f2f Clean up CheckmarkView 2016-04-01 17:24:12 -04:00
bc54f3f916 Improve performance of toggleCheckmark 2016-04-01 16:21:22 -04:00
5763d76167 Make setup method public 2016-04-01 16:08:51 -04:00
86b66b1388 Add tests for DeleteHabitsCommand 2016-03-31 08:02:44 -04:00
5e0422848b Add tests for EditHabitCommand 2016-03-31 07:54:00 -04:00
a67a3297b1 Add tests for ToggleRepetitionCommand 2016-03-31 07:34:20 -04:00
b2f2d4ad28 Add tests for UnarchiveHabitsCommand 2016-03-31 07:24:43 -04:00
4dc8201dcb Add tests for CreateHabitCommand 2016-03-31 07:20:20 -04:00
f24e300b40 Implement tests for Archive and ChangeColor commands 2016-03-31 07:11:24 -04:00
21157eaa19 Increase similarity threshold 2016-03-31 07:09:47 -04:00
0ea2c8e5c8 HistoryView: test tap at invalid locations 2016-03-31 06:31:13 -04:00
826491bc90 Test custom views with transparent background 2016-03-31 06:21:01 -04:00
72f5ca5531 Add tests for NumberView 2016-03-31 06:03:16 -04:00
f9da90a93a Add tests for HabitStreakView 2016-03-30 21:02:05 -04:00
96c6a97ad0 Add tests for HabitScoreView 2016-03-30 19:46:37 -04:00
20469789ea Add tests for HabitFrequencyView 2016-03-30 18:41:00 -04:00
abafffcff1 Increase similarity threshold 2016-03-30 12:25:45 -04:00
d45a4445cc Minor changes to HabitHistoryView rendering; enable haptic feedback 2016-03-30 12:25:24 -04:00
94f56a8869 Make all unit tests inherit from BaseTest 2016-03-30 08:49:42 -04:00
bc331d0a4d Write tests for HabitHistoryView 2016-03-30 08:28:21 -04:00
2ba7246e5f Refactor Tasks for better testability 2016-03-30 08:28:06 -04:00
67b88c5012 Show log when build fails 2016-03-30 08:24:42 -04:00
e0b637e84d Merge branch 'feature/unit-test-views' into dev 2016-03-28 21:14:42 -04:00
e14d73cf32 Add translator 2016-03-28 21:00:07 -04:00
16b9584868 Minor changes to strings.xml 2016-03-28 20:20:18 -04:00
c091116105 Compute padding/margins more precisely on CheckmarkView 2016-03-28 20:06:32 -04:00
37e1a6233c Copy failed generated images to CircleCI artifacts folder 2016-03-27 18:47:26 -04:00
6838a0f2d3 Restore missing asset 2016-03-27 06:40:56 -04:00
53e737c169 Allow API version-specific view tests; use relative image distance 2016-03-27 06:39:40 -04:00
285f79ed95 Add tests for CheckmarkView 2016-03-26 20:11:17 -04:00
4f65c8bef1 Add script to pull failed generated images from device 2016-03-26 19:47:53 -04:00
51b7cfc8fa Remove useless asset 2016-03-26 19:47:04 -04:00
55ed2585ea Additional tests for RingView 2016-03-26 19:46:33 -04:00
2c62e1578a Create base test class for custom views 2016-03-26 19:25:50 -04:00
e3d96c0431 Upload code coverage to codecov.io 2016-03-26 17:03:21 -04:00
b4c2d2237a Draw month name on the following column.
This reverts commit f9377e17. See #55 for reason.
2016-03-26 08:57:18 -04:00
d14fbbd130 Make streak colors consistent 2016-03-26 08:49:02 -04:00
e2c99d745e Improve visualization of streaks
Closes #20
2016-03-26 08:27:23 -04:00
dfe41176bc Reintroduce vibrate permission 2016-03-25 17:01:41 -04:00
1ef4f8d456 Use system haptic feedback instead of custom vibration; enable on short press
Closes #66
2016-03-25 14:39:57 -04:00
6c810ee7a3 Allow user to send bug report from settings screen 2016-03-25 14:39:57 -04:00
5115379fdd Merge branch 'feature/import-data' into dev 2016-03-25 09:21:47 -04:00
d176ea91fb Use custom matcher for settings activity 2016-03-25 09:04:07 -04:00
62df660079 Implement UI tests for import/export and help 2016-03-25 08:10:10 -04:00
790beb185a Do not save backup when importing Loop DB 2016-03-25 08:09:33 -04:00
59c0af17d7 Use application context to initialize ActiveAndroid 2016-03-25 07:09:41 -04:00
28dad560a6 Write tests for CSV exporter 2016-03-25 07:09:06 -04:00
9e410f8395 Refactor and write tests for IO tasks 2016-03-25 06:18:07 -04:00
3656c51e95 Disable pre-dexing 2016-03-24 22:14:54 -04:00
d3ebb4ff25 Create SD card 2016-03-24 21:52:59 -04:00
3c595bc79d Add null check on DatabaseHelper 2016-03-24 21:51:02 -04:00
1120f56dd4 Write tests for CSV export 2016-03-24 21:36:41 -04:00
2dfbcfcdb0 Revert to alpha version of gradle
Build fails otherwise
2016-03-24 20:14:26 -04:00
90a3964f0f Close database 2016-03-24 18:39:49 -04:00
6c05366f0f Remove illegal characters from filename 2016-03-24 18:39:32 -04:00
dcc771abe7 Chose external dir better 2016-03-24 18:39:14 -04:00
743431ef67 Refactor DatabaseHelper; write tests for data import 2016-03-24 06:59:41 -04:00
d5fc1a6886 Allow user to import full database
Closes #67
2016-03-23 19:21:06 -04:00
eeb0b109ae Remove export CSV from context menu 2016-03-23 19:20:12 -04:00
ad391fa791 Remove extra permissions; better organize files dir 2016-03-23 18:50:02 -04:00
e8bbae8ef9 Allow user to export a full copy of the database 2016-03-23 18:01:25 -04:00
c9793df7c7 Reorganize files 2016-03-23 17:20:26 -04:00
3c6114fc87 Update README.md 2016-03-23 14:19:30 -04:00
4ea4201b6a Merge pull request #69 from XuToTo/patch-1
Update strings.xml
2016-03-23 14:10:42 -04:00
XuToTo
30b5b90091 Update strings.xml
Make some zh-translation words more friendly :)
2016-03-24 00:53:37 +08:00
e6b7b8b590 Export all habits as CSV from the settings menu
Closes #28
2016-03-22 22:54:02 -04:00
2d675ed9b0 Use DB transaction to perform import 2016-03-22 22:54:02 -04:00
1db2f69f05 Import data from HabitBull
Closes #44
2016-03-22 22:54:02 -04:00
49a80faca3 Trap all exceptions 2016-03-22 22:54:02 -04:00
aa5df56437 Use stable version of gradle 2016-03-22 22:54:01 -04:00
581197be03 Import data from Tickmate and Rewire
Closes #36, closes #41
2016-03-22 22:53:16 -04:00
dfe5c4954e Refactor CSVExporter 2016-03-21 06:25:48 -04:00
a0582b65d5 Merge tag 'v1.3.3' into dev
Version 1.3.3
2016-03-20 17:55:16 -04:00
9edc3e12c9 Merge branch 'hotfix/1.3.3' 2016-03-20 17:55:07 -04:00
7bb3db213f Update changelog 2016-03-20 17:46:10 -04:00
e05a69b527 Merge branch 'poeditor' into hotfix/1.3.3 2016-03-20 17:31:08 -04:00
d5df6ddcdb Add Spanish and Korean translations
Closes #40
2016-03-20 17:30:55 -04:00
3016263750 Update translations 2016-03-20 17:25:06 -04:00
f9377e1768 Draw month name on the correct column
Fixes #55
2016-03-20 17:10:57 -04:00
ae0dad9120 Use DateHelper instead of instantiating GregorianCalendar directly
Fixes #58
2016-03-20 17:06:22 -04:00
be114bde7f Bump version to 1.3.3 2016-03-20 17:01:58 -04:00
e7148abc2e Open statistics page when user taps on widget
Closes #19
2016-03-20 08:36:16 -04:00
2d87076a48 Change the way score are grouped 2016-03-20 08:19:57 -04:00
7da4ddf91b Allow user to change score view interval
Closes #10
2016-03-20 08:06:12 -04:00
e4e8d77acc Add link to FAQ
Closes #24
2016-03-19 13:30:04 -04:00
7945a5faf9 Set default habit frequency to daily 2016-03-19 11:58:25 -04:00
3f7d25461d Wake up device in Doze mode 2016-03-19 10:19:28 -04:00
519737a1c3 Minor changes to English strings 2016-03-19 10:02:49 -04:00
c3ff1fbe03 Add quick selection for commonly used habit frequencies
Closes #25
2016-03-19 09:46:42 -04:00
d39e1978a2 Add Spanish and Korean translations
Closes #40
2016-03-19 05:03:23 -04:00
536c095f23 Merge tag 'v1.3.2' into dev
Version 1.3.2
2016-03-18 11:36:48 -04:00
8aaa5aca28 Merge branch 'hotfix/1.3.2' 2016-03-18 11:35:24 -04:00
5540a66e08 Minor spelling change 2016-03-18 11:34:05 -04:00
01ffc6c144 Update changelog 2016-03-18 11:25:57 -04:00
21aa658acc Fix crash when input is empty 2016-03-18 11:25:34 -04:00
e17667d85d Fix small layout issue on RingView 2016-03-18 11:25:19 -04:00
f2948dac6f Bump version to 1.3.2 (12) 2016-03-18 11:12:33 -04:00
31a7d92f77 Update translations 2016-03-18 11:11:04 -04:00
82d7970f86 Update list of translators 2016-03-18 11:11:04 -04:00
af1a21a959 Add Swedish translation 2016-03-18 11:11:04 -04:00
e7c1575083 Add Russian translation 2016-03-18 11:11:04 -04:00
d5a14ca55b Add Polish translation 2016-03-18 11:11:04 -04:00
c4d6b80944 Add Italian translation 2016-03-18 11:11:04 -04:00
c4b6cad6bb Update German translation 2016-03-18 11:11:03 -04:00
7070530d0e Update French translation 2016-03-18 11:11:03 -04:00
1332a70eb4 Declare RTL support in the manifest 2016-03-18 11:11:03 -04:00
11c9a3dab0 Add Arabic translation 2016-03-18 11:11:03 -04:00
74f7b0fd28 Update translators' names 2016-03-18 11:11:03 -04:00
e693504183 Update translations 2016-03-18 11:01:25 -04:00
7d9a94ae9e Add line to disable large tests 2016-03-18 10:58:18 -04:00
326cb8f73f Minor changes to javadoc and method visibility 2016-03-18 10:42:47 -04:00
6826bd1ddc Update test 2016-03-18 10:36:56 -04:00
b5bc347624 Use default instead of null for reminderDays 2016-03-18 07:43:11 -04:00
55c058ff42 Minor spelling mistakes 2016-03-18 07:24:26 -04:00
e829bb8109 Enable parallel and daemon (gradle) 2016-03-18 07:18:50 -04:00
0921f9346e Refactor and write docs for Score and ScoreList 2016-03-18 07:16:31 -04:00
eb017bf99b Write missing tests and docs for RepetitionList 2016-03-17 06:49:11 -04:00
79b6ef8200 Improve null check for Checkmark and CheckmarkList 2016-03-17 06:39:29 -04:00
7ba62d6784 Minor formatting 2016-03-17 06:39:12 -04:00
f5e4a88415 Implement missing tests for Habit; remove some dead code 2016-03-17 06:20:52 -04:00
075b7812eb Refactor and write documentation for Habit 2016-03-16 07:49:40 -04:00
3d42505fb9 Merge tag 'v1.3.1' into dev 2016-03-15 20:38:51 -04:00
824f98dd96 Merge branch 'hotfix/1.3.1' 2016-03-15 20:31:06 -04:00
fcb82bcb72 Update changelog for v1.3.1 2016-03-15 20:30:01 -04:00
851cae3662 Show error message on widget when habit not found
Fixes #35
2016-03-15 20:25:47 -04:00
7778c5fb21 Check for null on notifications 2016-03-15 20:17:15 -04:00
ef847dac17 Use StaticLayout to draw RingView label
Fixes #29
2016-03-15 19:56:14 -04:00
8102c18c67 Use long for millisecondsInOneDay
Fixes #34
2016-03-15 19:55:50 -04:00
59ed9ec9bd Bump version to 1.3.1 2016-03-15 19:51:50 -04:00
ffdc923268 Make labels more clear and customizable 2016-03-15 06:10:39 -04:00
9232378d04 Refactor RingView; make text size consistent 2016-03-15 05:30:27 -04:00
b20fd44cbc Scroll to view before clicking 2016-03-14 20:48:39 -04:00
ded8800017 Extract common style 2016-03-14 19:36:05 -04:00
606f66b8d9 Merge branch 'feature/repetition-count' into dev 2016-03-14 19:30:58 -04:00
1bb6cd405b Externalize strings 2016-03-14 19:13:33 -04:00
babf7d64f0 Display repetition count for last week, month, etc
Closes #21
2016-03-14 19:07:32 -04:00
dfbcf78dd7 Update list of translators 2016-03-14 15:46:52 -04:00
e01c668e4d Add Swedish translation 2016-03-14 15:46:40 -04:00
2eef696027 Add Russian translation 2016-03-14 15:46:30 -04:00
ddd10cacd1 Add Polish translation 2016-03-14 15:38:42 -04:00
0cdde4901e Add Italian translation 2016-03-14 15:38:29 -04:00
f13e9b7362 Update German translation 2016-03-14 15:38:12 -04:00
558f72d7c5 Update French translation 2016-03-14 15:33:06 -04:00
6e493f55bc Declare RTL support in the manifest 2016-03-14 15:18:58 -04:00
5186ab840a Add Arabic translation 2016-03-14 15:11:41 -04:00
65fd82d888 Fix indentation 2016-03-14 15:04:15 -04:00
866b62987c Wake up device before running UI tests 2016-03-14 14:55:47 -04:00
18abb2038f Check if habit is null on BaseWidgetProvider 2016-03-14 14:54:43 -04:00
f7f4b5eeb0 Simplify code for drawing header 2016-03-14 14:35:57 -04:00
45a7433773 Use StaticLayout to draw RingView label
Fixes #29
2016-03-14 13:34:21 -04:00
40420c3a77 Save logcat to reports 2016-03-14 08:37:02 -04:00
988b39f2e5 Add missing debug messages to SystemHelper 2016-03-14 08:33:46 -04:00
a0803966f9 Merge branch 'feature/unit-tests' into dev 2016-03-14 08:14:56 -04:00
e4af662836 Merge pull request #33 from vanniktech/patch-1 2016-03-14 08:10:10 -04:00
e95adab422 Include CircleCI badge 2016-03-14 07:39:43 -04:00
012fed01eb Fix CircleCI; remove Travis-CI 2016-03-14 07:39:43 -04:00
4cf2b8072b Unlock screen before running UI tests 2016-03-14 07:39:43 -04:00
196a79a88c Add CircleCI config file 2016-03-14 07:39:43 -04:00
4b7e2e79a7 Update tools versions 2016-03-14 07:39:43 -04:00
9156bba267 Disable animations when testing 2016-03-14 07:39:43 -04:00
1a18bb939d Refactor and write unit tests for RepetitionList 2016-03-14 07:39:43 -04:00
144524e53b Refactor and write tests for checkmarks 2016-03-14 07:39:43 -04:00
3d1c53396c Allow date to be fixed at a certain timestamp 2016-03-14 07:39:43 -04:00
1930db3cd1 Wait after toggling checkmarks 2016-03-14 07:39:43 -04:00
a2c2a5531a Use temporary database for tests 2016-03-14 07:39:43 -04:00
eee2605f74 Add first unit tests for habit 2016-03-14 07:39:43 -04:00
Niklas Baudy
9df0c9ae9e Update EditText of Edit Habit Description to capitalize sentences 2016-03-14 10:19:47 +01:00
e0533505c1 Merge pull request #30 from vanniktech/patch-1
Update EditText of Edit Habit to capitalize sentences
2016-03-14 04:41:09 -04:00
Niklas Baudy
433894336c Update EditText of Edit Habit to capitalize sentences
Basically when entering a word the first letter will be capitalized. Something minor that bugs me always a bit.
2016-03-13 23:46:29 +01:00
9061182301 Update translators' names 2016-03-12 19:39:03 -05:00
8c45f52d56 Merge tag 'v1.3.0' into dev
Release v1.3.0
2016-03-12 06:03:02 -05:00
53c9dca3e2 Merge branch 'release/1.3.0' 2016-03-12 06:02:22 -05:00
8b37daa9fb Update CHANGELOG 2016-03-12 06:02:11 -05:00
f9c2e83c79 Update screenshots 2016-03-12 05:37:00 -05:00
71bdc70c1a Bump version to 1.3.0 2016-03-12 05:25:10 -05:00
5e4a40579a Put about under link category on settings screen 2016-03-12 05:23:34 -05:00
d326be1224 Reintroduce longClick hack 2016-03-12 05:17:55 -05:00
fb8a09c95c Add German translation 2016-03-12 05:13:11 -05:00
1635b9905d Split test 2016-03-12 05:03:04 -05:00
2d88fc0b20 Update Japanese translation 2016-03-11 16:27:40 -05:00
1d74359c06 Update widgets in background 2016-03-11 15:07:56 -05:00
f75f77cec7 Merge branch 'feature/ui-test' into dev
Closes #22
2016-03-11 13:21:10 -05:00
8b10138cd6 Fix tests on pre-Lollipop devices 2016-03-11 13:20:43 -05:00
2b40633110 Add more tests for settings and about 2016-03-11 12:39:59 -05:00
1102d05a61 Test unarchiving habits 2016-03-11 12:39:59 -05:00
51e8c2f111 Implement basic user interface tests 2016-03-11 12:39:59 -05:00
547e4e5f63 Use white background on pre-Lollipop, instead of ripple 2016-03-11 12:39:41 -05:00
84d5c2aac6 Remove longClick hack 2016-03-11 12:26:56 -05:00
2b3b423fa3 Show color button even for a single habit 2016-03-11 12:26:34 -05:00
3b28c37c5e Rebuild order after commit 2016-03-11 12:26:13 -05:00
e749e787ad Add Japanese translation 2016-03-10 06:20:42 -05:00
9c5d582f24 Update copyright notices for translations 2016-03-10 06:10:25 -05:00
75a4edb61c Merge branch 'feature/frequency-view' into dev 2016-03-10 05:52:45 -05:00
34c0758308 Remove debug code 2016-03-10 05:49:34 -05:00
85963ae061 Add frequency widget 2016-03-10 05:43:56 -05:00
e3390d5397 Rename header to frequency; update translations 2016-03-10 05:25:42 -05:00
59a2f31a73 Fix timezone issues; rename class to HabitFrequencyView 2016-03-10 05:25:22 -05:00
c01f8450d3 Update README.md 2016-03-09 14:00:48 -05:00
cea5241135 Implement weekday frequency view 2016-03-09 08:23:55 -05:00
7784fc5c75 Add broadcast receiver to ShowHabitActivity 2016-03-08 22:13:47 -05:00
6dd017f33e Refresh also main activity when history editor closes 2016-03-08 21:57:42 -05:00
c8cd9f85f6 Remove hardcoded string 2016-03-08 21:50:42 -05:00
d038bdb741 Update widgets after history editor closes 2016-03-08 21:50:10 -05:00
f55e8d2c85 Merge branch 'feature/history-editor' into dev
Closes #14
2016-03-08 21:33:27 -05:00
f8dc1d9eae Force rebuild of scores 2016-03-08 21:30:09 -05:00
85393b0d40 Handle configuration changes 2016-03-08 21:22:59 -05:00
75599ad20c Fix timezone issues 2016-03-08 20:58:29 -05:00
c6b948cbf5 Save changes on configuration change
Fixes #16
2016-03-08 18:16:34 -05:00
4d42133a4b Add links to F-Droid 2016-03-08 08:38:16 -05:00
5b151805ff Make HistoryView not editable by default 2016-03-08 07:56:40 -05:00
aa86826bdb Refresh data after closing history editor 2016-03-08 07:53:24 -05:00
821373a340 Make history editor functional 2016-03-08 07:35:55 -05:00
8f37e293b1 Implement dummy history editor; add edit history button 2016-03-08 06:58:34 -05:00
0fb8ed0b53 Add French translation 2016-03-07 20:53:37 -05:00
0c696b2eb2 Include Material Design Icons 2016-03-07 16:41:38 -05:00
cd127bc3f8 Add copyright notices 2016-03-07 16:35:34 -05:00
2cfc809490 Update copyright notices in all files 2016-03-07 15:54:56 -05:00
ba31dee16a Merge branch 'feature/refactoring' into dev 2016-03-07 08:39:11 -05:00
146c743fb8 Simplify list adapter 2016-03-07 08:03:30 -05:00
0c00e9ec2d Simplify constructor 2016-03-07 07:51:48 -05:00
49af55a2de Move more methods to helper 2016-03-07 07:31:06 -05:00
0114b48197 Fix formatting; include license section 2016-03-07 05:44:02 -05:00
09f615a5e6 Update translations 2016-03-07 05:39:15 -05:00
9014acc548 Remove settings menu from ShowHabitActivity 2016-03-07 05:39:15 -05:00
4fb386be86 Include building and installing instructions
Closes #11
2016-03-07 05:29:05 -05:00
ea8606be97 More details to the code contribution subsection 2016-03-06 21:58:02 -05:00
e0527dc8ff Implement about screen 2016-03-06 08:34:18 -05:00
aaf2789a21 Include contributing section 2016-03-06 06:00:12 -05:00
f8dc64cc6b Move time and color pickers resources into separate file 2016-03-05 16:13:48 -05:00
ced5b751be Move methods to helper 2016-03-05 08:43:09 -05:00
8a60dda74e Further simplify ListHabitsFragment 2016-03-05 08:33:17 -05:00
c8c4df6ef7 Split ListHabitsFragment into smaller classes 2016-03-05 07:30:04 -05:00
0c0ac9dee5 Minor formatting 2016-03-05 06:48:25 -05:00
fdf6c91929 Use equals instead of operator 2016-03-05 06:48:01 -05:00
08d6e39a17 Throw exception when trying to undo deletion of habit 2016-03-05 06:46:52 -05:00
b9bc7bd1b5 Merge branch 'master' into dev 2016-03-04 13:28:39 -05:00
7b73238448 Add explicit READ_EXTERNAL_STORAGE permission with maxSdkVersion 2016-03-04 13:19:03 -05:00
83ccfb82ac Merge branch 'release/1.2.0' into master 2016-03-04 12:53:24 -05:00
199d35d9c7 Merge branch 'release/1.2.0' into dev 2016-03-04 12:53:04 -05:00
382a2fe600 Update CHANGELOG.md 2016-03-04 12:46:49 -05:00
e02f9c1d60 Bump version to 1.2.0 2016-03-04 12:46:36 -05:00
5e7636d7ff Fix position for new habits 2016-03-04 12:43:55 -05:00
616322cd35 Fix card background (pre-Lollipop) 2016-03-04 12:43:55 -05:00
299c6a0c1d Show action icons on pre-Lollipop 2016-03-04 12:43:55 -05:00
b4911b6cb4 Save last app version on preferences 2016-03-04 11:13:20 -05:00
f41f877107 Fix data export on older devices 2016-03-04 11:13:20 -05:00
58aa7f6687 Add padding to HabitScoreView 2016-03-04 07:03:05 -05:00
d196e01da0 Update widgets and reminders on background; faster startup 2016-03-04 06:52:31 -05:00
1fbd12a947 Fix incorrect streaks 2016-03-04 06:39:30 -05:00
7493291ade Use average of scores in the interval 2016-03-03 07:38:50 -05:00
2a750704d9 Minor string change 2016-03-03 07:38:11 -05:00
eb79113e4c Update screenshots to include widgets 2016-03-03 06:49:46 -05:00
cb2f3823cd Update widget previews 2016-03-03 06:36:06 -05:00
39e29dabb8 Add code to save widget preview to file 2016-03-03 06:35:37 -05:00
51d1b93d03 Split Habit class into several smaller classes 2016-03-03 05:22:19 -05:00
8acbc63914 Move commands to their own files 2016-03-03 04:42:40 -05:00
ac8e78ff24 Minor style changes 2016-03-02 10:39:13 -05:00
162ded66d8 Improve widget measuring 2016-03-02 09:52:32 -05:00
5428209543 Improve widget colors 2016-03-01 08:37:57 -05:00
141fd30d70 Merge branch 'widgets' into dev 2016-02-29 07:45:41 -05:00
48d446a243 Minor color changes 2016-02-29 07:44:59 -05:00
ae7869d3a2 Implement multiple widget providers 2016-02-29 07:19:43 -05:00
b8cacaffa9 Refactor custom views; fix rendering issues 2016-02-29 05:50:27 -05:00
4def8f0409 Perform additional checks to avoid negative lengths 2016-02-28 15:23:20 -05:00
f0d12e9925 Widgets for HistoryView, ScoreView, etc 2016-02-28 13:55:39 -05:00
a2331260e4 Alternative design for widgets 2016-02-28 11:37:50 -05:00
c1a846d42b Minor style changes 2016-02-27 19:42:05 -05:00
031d684b3e Update main activity on notification/widget click 2016-02-27 18:26:25 -05:00
3a770e71e3 Add configuration activity for widgets 2016-02-27 18:06:57 -05:00
b29dd8ea79 Remove debug code 2016-02-27 16:31:48 -05:00
7f1553a4a1 Toggle checkmarks from widget 2016-02-27 14:09:02 -05:00
d748f5d6de Assign habits to widgets; refresh on database change 2016-02-27 13:54:24 -05:00
7234e072e6 Implement widget with fixed data 2016-02-27 13:24:01 -05:00
7f71f46367 Remove useless widget preview 2016-02-27 13:12:12 -05:00
c1dae021bf Implement dummy widget 2016-02-27 11:52:46 -05:00
88455acc76 Fix check button for previous day reminders 2016-02-27 05:44:14 -05:00
6a1cb09ca2 Remove unused imports and variables 2016-02-26 08:25:56 -05:00
33d7ab52ca Remove unused resources 2016-02-26 08:11:43 -05:00
d2682358c2 Allow custom views to be rendered on the layout editor 2016-02-26 07:44:34 -05:00
f511ca2028 Explicitly allow backups 2016-02-26 05:31:26 -05:00
d5774e8511 Close cursors 2016-02-26 05:31:17 -05:00
b6e7e72f5a Remove object allocations during draw 2016-02-26 05:29:02 -05:00
27220c9ab2 Specify locale explicitly 2016-02-26 05:17:33 -05:00
f1424e5820 Add content description for images 2016-02-26 05:16:58 -05:00
a18e0fbda0 Remove hardcoded string 2016-02-26 05:09:56 -05:00
4c3a72df81 Delete duplicate resource 2016-02-26 05:08:35 -05:00
e9ce50f686 Use correct XML namespace 2016-02-26 05:07:04 -05:00
acb26964f3 Mark as untranslatable 2016-02-26 05:06:39 -05:00
917d1218ae Update pt translation 2016-02-26 05:06:18 -05:00
f5ccd7d8c3 Move ripple backgrounds to drawable-v21 2016-02-26 04:53:19 -05:00
456a9e49a9 Remove extra translations 2016-02-26 04:52:55 -05:00
6b05004647 Implement fling and more natural scrolling on ScrollableDataView 2016-02-25 21:33:19 -05:00
f9a9339042 Use GestureDetector for scrolling 2016-02-25 21:31:28 -05:00
5e21d877c5 Fetch all the data with one call 2016-02-25 20:17:44 -05:00
af0ef90e4d Export to CSV 2016-02-25 15:46:39 -05:00
02b3ea58cf Update drag-sort-listview 2016-02-25 15:46:39 -05:00
0dcedb3c59 Update README.md 2016-02-25 10:20:25 -05:00
637d75fd2e Update README.md 2016-02-25 10:17:01 -05:00
0cd8dd973b Bump version to 1.1.1 2016-02-24 18:30:29 -05:00
2898a21157 Disallow empty list of days 2016-02-24 15:58:58 -05:00
0fa25c6701 Internationalize string 2016-02-24 15:58:45 -05:00
843f3b06a1 Update translations 2016-02-24 15:58:12 -05:00
1328 changed files with 71473 additions and 6942 deletions

31
.github/workflows/main.yml vendored Normal file
View File

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

40
.github/workflows/publish.yml vendored Normal file
View File

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

51
.gitignore vendored
View File

@@ -1,35 +1,18 @@
#built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
# Local configuration file (sdk path, etc)
local.properties
# Windows thumbnail db
Thumbs.db
# OSX files
.DS_Store
# Eclipse project files
.classpath
.project
# Android Studio
.idea
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
.gradle
build/
*.iml
art/
*.pbxuser
*.perspective
*.perspectivev3
*.swp
*~.nib
.DS_Store
._.DS_Store
.externalNativeBuild
.gradle
.idea
.secret
build
build/
captures
local.properties
node_modules
*xcuserdata*

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "libs/drag-sort-listview"]
path = libs/drag-sort-listview
url = https://github.com/iSoron/drag-sort-listview.git

16
.secret/decrypt.sh Executable file
View File

@@ -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
gpg \
--quiet \
--batch \
--yes \
--decrypt \
--passphrase="$GPG_PASSWORD" \
--output secret.tar.gz \
secret
tar -xzf secret.tar.gz
rm secret.tar.gz

BIN
.secret/secret Normal file

Binary file not shown.

205
CHANGELOG.md Normal file
View File

@@ -0,0 +1,205 @@
# Changelog
### 1.8.8 (June 21, 2020)
* Make small changes to the habit scheduling algorithm, so that "1 time every x days" habits work more predictably.
* Fix crash when saving habit
### 1.8.0 (Jan 1, 2020)
* New bar chart showing number of repetitions performed in each week, month, quarter or year.
* Improved calculation of streaks for non-daily habits: performing habits on irregular weekdays will no longer break your streak.
* Many more colors to choose from (now 20 in total).
* Ability to customize how transparent the widgets are on your home screen.
* Ability to customize the first day of the week.
* Yes/No buttons on notifications, instead of just "Check".
* Automatic dark theme according to phone settings (Android 10).
* Smaller APK and backup files.
* Many other internal code changes improving performance and stability.
### 1.7.11 (Aug 10, 2019)
* Fix bug that produced corrupted CSV files in some countries
### 1.7.10 (June 15, 2019)
* Fix bug that prevented some devices from showing notifications.
* Update targetSdk to Android Pie (API level 28)
### 1.7.8 (April 21, 2018)
* Add support for adaptive icons (Oreo)
* Add support for notification channels (Oreo)
* Update translations
### 1.7.7 (September 30, 2017)
* Fix bug that caused reminders to show repeatedly on DST changes
### 1.7.6 (July 18, 2017)
* Fix bug that caused widgets not to render sometimes
* Fix other minor bugs
* Update translations
### 1.7.3 (May 30, 2017)
* Improve performance of 'sort by score'
* Other minor bug fixes
### 1.7.2 (May 27, 2017)
* Fix crash at startup
### 1.7.1 (May 21, 2017)
* Fix crash (BadParcelableException)
* Fix layout for RTL languages such as Arabic
* Automatically detect and reject invalid database files
* Add Hebrew translation
### 1.7.0 (Mar 31, 2017)
* Sort habits automatically
* Allow swiping the header to see previous days
* Import backups directly from Google Drive or Dropbox
* Refresh data automatically at midnight
* Other minor bug fixes and enhancements
### 1.6.2 (Oct 13, 2016)
* Fix crash on Android 4.1
### 1.6.1 (Oct 10, 2016)
* Fix a crash at startup when database is corrupted
### 1.6.0 (Oct 10, 2016)
* Add option to make notifications sticky
* Add option to hide completed habits
* Display total number of repetitions for each habit
* Pebble integration: check/snooze habits from the watch
* Tasker/Locale integration: allow third-party apps to add checkmarks
* Export an unified CSV file, with checkmarks for all the habits
* Increase width of name column according to screen size
* Stop showing reminders for archived habits
* Add Danish, Dutch, Greek, Hindi and Portuguese (PT) translations
* Other minor fixes and enhancements
### 1.5.6 (Jun 19, 2016)
* Fix bug that prevented checkmark widget from working
### 1.5.5 (Jun 19, 2016)
* Fix bug that prevented check button on notification to work sometimes
* Fix bug that caused back button to apparently erase some checkmarks
* Complete French translation
* Add Croatian and Slovenian translations
### 1.5.4 (May 29, 2016)
* Fix crash upon opening settings screen in some phones
* Fix missing folders in CSV archive
* Add Serbian translation
### 1.5.3 (May 22, 2016)
* Complete Arabic and Czech translations
* Fix crash at startup
* Fix checkmark widget on custom launchers
### 1.5.2 (May 19, 2016)
* Fix missing attachment on bug reports
* Fix bug that prevents some widgets from rendering
* Complete Japanese translation
### 1.5.1 (May 17, 2016)
* Fix build on F-Droid
### 1.5.0 (May 15, 2016)
* Add night mode, with AMOLED support
* Backport material design to older devices
* Display more information on statistics screen
* Display score on main screen and checkmark widget
* Make widgets react immediately to touch
* Reschedule reminders after reboot
* Pick first day of the week according to country
* Add option to reverse order of days on main screen
* Add option to change notification sounds
* Add Catalan, Indonesian, Turkish, Ukrainian translations
* Switch between Simplified/Traditional Chinese according to country
### 1.4.1 (April 9, 2016)
* Show error message on widgets, instead of crashing
* Complete French translation
* Minor fixes to other translations
### 1.4.0 (April 7, 2016)
* Ability to import data from third-party apps
* Ability to save and restore full database backup
* Show more information on streak chart
* Simplify interface for creating habits
* Add link to Frequently Asked Questions (FAQ)
* Reduce app loading time and lag on widgets
* Generate bug reports on crash and from settings screen
* Disable vibration according to phone settings
* Add Czech translation
* Fix wrong month names for some languages
### 1.3.3 (March 20, 2016)
* Add Spanish and Korean translations
* Make small corrections to other translations
* Fix incorrect date in history calendar
### 1.3.2 (March 18, 2016)
* Add Arabic, Italian, Polish, Russian and Swedish translations
* Minor fixes to German and French translations
* Minor bug fixes
### 1.3.1 (March 15, 2016)
* Fixes crash on devices with large screen, such as the Nexus 10
* Fixes crash when clicking widgets and reminders of deleted habits
* Other minor bug fixes
### 1.3.0 (March 12, 2016)
* New frequency plot: view total repetitions per day of week
* New history editor: put checkmarks in the past
* Add German, French and Japanese translations
* Add about screen, with credits to all contributors
* Fix small bug that prevented habit from being reordered
* Fix small bug caused by rotating the device
### 1.2.0 (March 4, 2016)
* Ability to export habit data as CSV
* Widgets (checkmark, history, score and streaks)
* More natural scrolling on data views (fling)
* Minor UI improvements on pre-Lollipop devices
* Fix crash on Samsung Galaxy TabS 8.4
* Other minor bug fixes
### 1.1.1 (February 24, 2016)
* Show reminder only on chosen days of the week
* Rearrange habits by long-pressing then dragging
* Select and modify multiple habits simultaneously
* 12/24 hour format according to phone preferences
* Permanently delete habits
* Usage hints during startup
* Translation to Brazilian Portuguese and Chinese
* Other minor fixes
### 1.0.0 (February 19, 2016)
* Initial release

207
NOTICE.md Normal file
View File

@@ -0,0 +1,207 @@
# Copyright Notices
### ActiveAndroid
<https://github.com/pardom/ActiveAndroid>
Copyright (C) 2010 Michael Pardo
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
http://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.
### Android Open Source Project
<https://source.android.com/>
Copyright (C) 2013 The Android Open Source Project
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
http://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.
### FontAwesome
<http://fontawesome.io>
Font Awesome is a full suite of 605 pictographic icons for easy scalable
vector graphics on websites, created and maintained by Dave Gandy. Licensed
under the SIL OFL 1.1.
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
### Material Design Icons
<https://github.com/google/material-design-icons>
Material design icons are the official icon set from Google that are designed
under the material design guidelines. Available under the Creative Common
Attribution 4.0 International License (CC-BY 4.0).
### Android Flow Layout
<https://github.com/ApmeM/android-flowlayout>
Extended linear layout that wrap its content when there is no place in the current line.
Copyright 2011, Artem Votincev (apmem.org)
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
http://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.
### Dagger 2
<https://github.com/google/dagger>
A fast dependency injector for Android and Java.
Copyright 2012 Square, Inc.
Copyright 2012 Google, Inc.
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
http://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.
### AutoFactory
<https://github.com/google/auto/tree/master/factory>
A source code generator for JSR-330-compatible factories.
Copyright 2013 Google, Inc.
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
http://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.
### Retrolambda
<https://github.com/orfjackal/retrolambda>
Backport of Java 8's lambda expressions to Java 7, 6 and 5
Copyright (c) 2013-2016 Esko Luontola and other Retrolambda contributors
This software is released under the Apache License 2.0.
The license text is at http://www.apache.org/licenses/LICENSE-2.0
### PebbleKit SDK
<https://github.com/pebble/pebble-android-sdk/>
Android PebbleKit SDK to talk to the Pebble via Bluetooth
The MIT License (MIT)
Copyright (c) 2014 - 2015 Pebble Technology
### AppIntro
<https://github.com/PaoloRotolo/AppIntro>
Make a cool intro for your Android app.
Copyright 2015 Paolo Rotolo
Copyright 2016 Maximilian Narr
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
http://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.
### ButterKnife
<https://github.com/JakeWharton/butterknife>
Bind Android views and callbacks to fields and methods
Copyright 2013 Jake Wharton
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
http://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.
### opencsv
<http://opencsv.sourceforge.net/>
Opencsv is a very simple csv (comma-separated values) parser library for Java.
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
http://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.

126
README.md
View File

@@ -1,16 +1,14 @@
# Loop Habit Tracker
Loop is a simple Android app that helps you create and maintain good habits. Detailed graphs and statistics show you how your habits improved over time. It is completely ad-free and open source, with no intrusive permissions. Join the open beta at [Google Play Store](https://play.google.com/apps/testing/org.isoron.uhabits).
Loop is a mobile app that helps you create and maintain good habits,
allowing you to achieve your long-term goals. Detailed graphs and statistics
show you how your habits improved over time. It is completely ad-free and open
source.
## Features
* Simple and beautiful interface, following the Material Design guidelines.
* Advanced algorithms 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.
* Detailed graphs and statistics, showing how did you habits improve over time. Scroll back to see the complete history of your habit.
* Support for both daily habits and habits with more complex schedules, such as 3 times every week; one time every other week; or every other day.
* Habit reminders at a chosen hour of the day.
* Support for Android Wear. Reminders can be checked or dismissed from the watch.
* 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 the GPLv3.
<p align="center">
<a href="https://play.google.com/store/apps/details?id=org.isoron.uhabits&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-AC-global-none-all-co-pr-py-PartBadges-Oct1515-1"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/apps/en-play-badge-border.png" height="75px"/></a>
<a href="http://f-droid.org/app/org.isoron.uhabits"><img alt="Get it on F-Droid" src="http://i.imgur.com/baSPE7X.png" height="75px"/></a>
</p>
## Screenshots
@@ -18,12 +16,104 @@ Loop is a simple Android app that helps you create and maintain good habits. Det
[![Edit habit][screen2th]][screen2]
[![Habit strength][screen3th]][screen3]
[![Habit history and streaks][screen4th]][screen4]
[![Widgets][screen5th]][screen5]
[![Night mode][screen6th]][screen6]
[screen1]: screenshots/original/uhabits1.png
[screen2]: screenshots/original/uhabits2.png
[screen3]: screenshots/original/uhabits3.png
[screen4]: screenshots/original/uhabits4.png
[screen1th]: screenshots/thumbs/uhabits1.png
[screen2th]: screenshots/thumbs/uhabits2.png
[screen3th]: screenshots/thumbs/uhabits3.png
[screen4th]: screenshots/thumbs/uhabits4.png
## Features
* <b>Beautiful, minimalistic and lightweight interface.</b>
Loop has an elegant and minimalistic interface that is very easy to use, even for first-time users. Highly optimized for speed, the app works well even on older phones.
* <b>Habit score.</b>
Loop has an advanced formula for calculating the strength of your habits. Every repetition makes your habit stronger and every missed day makes it weaker. A few missed days after a long streak, however, will not completely destroy your progress, unlike many other don't-break-the-chain apps.
* <b>Flexible schedules.</b>
In addition to daily habits, Loop supports habits with more complex schedules, such as 3 times per week or every other day.
* <b>Reminders.</b>
Schedule notifications to remind you of your habits. Each habit can have its own reminder, at a chosen time of the day. Easily check or dismiss your habit directly from the notification.
* <b>Widgets.</b>
Be reminded of your habits whenever you unlock your phone. Colorful widgets allow you to track your habits directly from your home screen, without even opening the app.
* <b>Take control of your data.</b>
If you want to further analyze your data, or move it to another service, Loop allows you to export it to spreadsheets (CSV) or to a database file (SQLite). For power users, checkmarks can be added through other apps, such as Tasker.
* <b>No limitations.</b>
Track as many habits as you wish. Loop imposes no artificial limits on how many habits you can have. All features are available to all users. There are no in-app purchases.
* <b>Completely ad-free and open source.</b>
There are no advertisements, annoying notifications or intrusive permissions in this app, and there will never be. The app is completely open-source (GPLv3).
* <b>Works offline and respects your privacy.</b>
Loop doesn't require an Internet connection or online account registration. Your confidential data is never sent to anyone. Neither the developers nor any third-parties have access to it.
## Installing
The easiest way to install Loop is through the [Google Play Store][playstore] or [F-Droid][fdroid].
You may also download and install the APK from the [releases page][releases];
note, however, that the app will not be updated automatically. To build this
app from the source code, see [build instructions][build].
## Contributing
Loop is an open source project developed entirely by volunteers. If you would
like to contribute to the project, you are very welcome. There are many ways to
contribute, even if you are not a software developer.
* **Report bugs, suggest features.** The easiest way to contribute is to simply
use the app and let us know if you find any problems or have any suggestions
to improve it. You can either use the link inside the app, or open an issue
at GitHub. If you would like to receive the newest versions of the app
earlier than everyone else, [join our open beta on Google Play][beta].
* **Spread the word.** If you like the app, share it with your family, friends
and colleagues. You can also rate and review the app on Google Play Store, to help
other users find it more easily.
* **Translate the app into your own language.** If you are not a native English
speaker, and would like to see the app translated into your own language,
please join our [open translation project][poedit]. If the translation
is already completed, you are also very welcome to join and proofread it.
* **Write some code.** If you are an Android developer, you are very welcome to
contribute with code. Please, see the [developer guidelines][dev-guide] for more details.
## License
<img align="right" src="https://www.gnu.org/graphics/gplv3-88x31.png">
Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
Loop Habit Tracker is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
Loop Habit Tracker is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
[screen1]: screenshots/uhabits1.png
[screen2]: screenshots/uhabits2.png
[screen3]: screenshots/uhabits3.png
[screen4]: screenshots/uhabits4.png
[screen5]: screenshots/uhabits5.png
[screen6]: screenshots/uhabits6.png
[screen1th]: screenshots/uhabits1_th.png
[screen2th]: screenshots/uhabits2_th.png
[screen3th]: screenshots/uhabits3_th.png
[screen4th]: screenshots/uhabits4_th.png
[screen5th]: screenshots/uhabits5_th.png
[screen6th]: screenshots/uhabits6_th.png
[poedit]: http://translate.loophabits.org
[playstore]: https://play.google.com/store/apps/details?id=org.isoron.uhabits
[releases]: https://github.com/iSoron/uhabits/releases
[fdroid]: http://f-droid.org/app/org.isoron.uhabits
[dev-guide]: https://github.com/iSoron/uhabits/wiki/Developer-guidelines
[build]: https://github.com/iSoron/uhabits/wiki/Developer-guidelines#building
[beta]: https://play.google.com/apps/testing/org.isoron.uhabits

28
android/.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
*.ap_
*.apk
*.class
*.dex
*.iml
*.local
*.local.*
*.swp
*.trace
*~
.DS_Store
.classpath
.gradle
.idea
.project
.secret
Thumbs.db
art/
bin/
build/
captures/
docs/
gen/
local.properties
crowdin.yaml
local
tmp/
secret/

1
android/android-base/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,31 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion COMPILE_SDK_VERSION as Integer
defaultConfig {
minSdkVersion MIN_SDK_VERSION as Integer
targetSdkVersion TARGET_SDK_VERSION as Integer
versionCode VERSION_CODE as Integer
versionName "$VERSION_NAME"
}
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation "com.google.dagger:dagger:$DAGGER_VERSION"
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation "org.apache.commons:commons-lang3:3.5"
annotationProcessor "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
}

25
android/android-base/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /gemini-b/opt/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,2 @@
<manifest package="org.isoron.androidbase"
xmlns:android="http://schemas.android.com/apk/res/android"/>

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase;
import android.content.*;
import android.os.*;
import android.view.*;
import androidx.annotation.NonNull;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.inject.*;
public class AndroidBugReporter
{
private final Context context;
@Inject
public AndroidBugReporter(@NonNull @AppContext Context context)
{
this.context = context;
}
/**
* Captures and returns a bug report. The bug report contains some device
* information and the logcat.
*
* @return a String containing the bug report.
* @throws IOException when any I/O error occur.
*/
@NonNull
public String getBugReport() throws IOException
{
String logcat = getLogcat();
String deviceInfo = getDeviceInfo();
String log = "---------- BUG REPORT BEGINS ----------\n";
log += deviceInfo + "\n" + logcat;
log += "---------- BUG REPORT ENDS ------------\n";
return log;
}
public String getDeviceInfo()
{
if (context == null) return "null context\n";
WindowManager wm =
(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
return
String.format("App Version Name: %s\n", BuildConfig.VERSION_NAME) +
String.format("App Version Code: %s\n", BuildConfig.VERSION_CODE) +
String.format("OS Version: %s (%s)\n",
System.getProperty("os.version"), Build.VERSION.INCREMENTAL) +
String.format("OS API Level: %s\n", Build.VERSION.SDK) +
String.format("Device: %s\n", Build.DEVICE) +
String.format("Model (Product): %s (%s)\n", Build.MODEL,
Build.PRODUCT) +
String.format("Manufacturer: %s\n", Build.MANUFACTURER) +
String.format("Other tags: %s\n", Build.TAGS) +
String.format("Screen Width: %s\n",
wm.getDefaultDisplay().getWidth()) +
String.format("Screen Height: %s\n",
wm.getDefaultDisplay().getHeight()) +
String.format("External storage state: %s\n\n",
Environment.getExternalStorageState());
}
public String getLogcat() throws IOException
{
int maxLineCount = 250;
StringBuilder builder = new StringBuilder();
String[] command = new String[]{ "logcat", "-d" };
java.lang.Process process = Runtime.getRuntime().exec(command);
InputStreamReader in = new InputStreamReader(process.getInputStream());
BufferedReader bufferedReader = new BufferedReader(in);
LinkedList<String> log = new LinkedList<>();
String line;
while ((line = bufferedReader.readLine()) != null)
{
log.addLast(line);
if (log.size() > maxLineCount) log.removeFirst();
}
for (String l : log)
{
builder.append(l);
builder.append('\n');
}
return builder.toString();
}
/**
* Captures a bug report and saves it to a file in the SD card.
* <p>
* The contents of the file are generated by the method {@link
* #getBugReport()}. The file is saved in the apps's external private
* storage.
*
* @return the generated file.
* @throws IOException when I/O errors occur.
*/
@NonNull
public void dumpBugReportToFile()
{
try
{
String date =
new SimpleDateFormat("yyyy-MM-dd HHmmss", Locale.US).format(
new Date());
if (context == null) throw new IllegalStateException();
File dir = new AndroidDirFinder(context).getFilesDir("Logs");
if (dir == null)
throw new IOException("log dir should not be null");
File logFile =
new File(String.format("%s/Log %s.txt", dir.getPath(), date));
FileWriter output = new FileWriter(logFile);
output.write(getBugReport());
output.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase;
import android.content.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.*;
import android.util.*;
import org.isoron.androidbase.utils.*;
import java.io.*;
import javax.inject.*;
public class AndroidDirFinder
{
@NonNull
private Context context;
@Inject
public AndroidDirFinder(@NonNull @AppContext Context context)
{
this.context = context;
}
@Nullable
public File getFilesDir(@Nullable String relativePath)
{
File externalFilesDirs[] =
ContextCompat.getExternalFilesDirs(context, null);
if (externalFilesDirs == null)
{
Log.e("BaseSystem",
"getFilesDir: getExternalFilesDirs returned null");
return null;
}
return FileUtils.getDir(externalFilesDirs, relativePath);
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase;
import java.lang.annotation.*;
import javax.inject.*;
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface AppContext
{
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase;
import android.content.*;
import dagger.*;
@Module
public class AppContextModule
{
private final Context context;
public AppContextModule(@AppContext Context context)
{
this.context = context;
}
@Provides
@AppContext
Context getContext()
{
return context;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.isoron.androidbase.activities.*;
public class BaseExceptionHandler implements Thread.UncaughtExceptionHandler
{
@Nullable
private Thread.UncaughtExceptionHandler originalHandler;
@NonNull
private BaseActivity activity;
public BaseExceptionHandler(@NonNull BaseActivity activity)
{
this.activity = activity;
originalHandler = Thread.getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(@Nullable Thread thread,
@Nullable Throwable ex)
{
if (ex == null) return;
try
{
ex.printStackTrace();
new AndroidBugReporter(activity).dumpBugReportToFile();
}
catch (Exception e)
{
e.printStackTrace();
}
// if (ex.getCause() instanceof InconsistentDatabaseException)
// {
// HabitsApplication app = (HabitsApplication) activity.getApplication();
// HabitList habits = app.getComponent().getHabitList();
// habits.repair();
// System.exit(0);
// }
if (originalHandler != null)
originalHandler.uncaughtException(thread, ex);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase;
import android.content.*;
import androidx.annotation.NonNull;
import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.*;
import javax.inject.*;
import javax.net.ssl.*;
public class SSLContextProvider
{
private Context context;
@Inject
public SSLContextProvider(@NonNull @AppContext Context context)
{
this.context = context;
}
public SSLContext getCACertSSLContext()
{
try
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getAssets().open("cacert.pem");
Certificate ca = cf.generateCertificate(caInput);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("ca", ca);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
return ctx;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import java.lang.annotation.*;
import javax.inject.*;
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityContext
{
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import android.content.*;
import dagger.*;
@Module
public class ActivityContextModule
{
private Context context;
public ActivityContextModule(Context context)
{
this.context = context;
}
@Provides
@ActivityContext
public Context getContext()
{
return context;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import javax.inject.*;
/**
* Scope used by objects that live as long as the activity is alive.
*/
@Scope
public @interface ActivityScope { }

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import android.content.*;
import android.os.*;
import androidx.annotation.Nullable;
import androidx.appcompat.app.*;
import android.view.*;
import org.isoron.androidbase.*;
import static android.R.anim.fade_in;
import static android.R.anim.fade_out;
/**
* Base class for all activities in the application.
* <p>
* This class delegates the responsibilities of an Android activity to other
* classes. For example, callbacks related to menus are forwarded to a {@link
* BaseMenu}, while callbacks related to activity results are forwarded to a
* {@link BaseScreen}.
* <p>
* A BaseActivity also installs an {@link java.lang.Thread.UncaughtExceptionHandler}
* to the main thread. By default, this handler is an instance of
* BaseExceptionHandler, which logs the exception to the disk before the application
* crashes. To the default handler, you should override the method
* getExceptionHandler.
*/
abstract public class BaseActivity extends AppCompatActivity
{
@Nullable
private BaseMenu baseMenu;
@Nullable
private BaseScreen screen;
@Override
public boolean onCreateOptionsMenu(@Nullable Menu menu)
{
if (menu == null) return true;
if (baseMenu == null) return true;
baseMenu.onCreate(getMenuInflater(), menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@Nullable MenuItem item)
{
if (item == null) return false;
if (baseMenu == null) return false;
return baseMenu.onItemSelected(item);
}
public void restartWithFade(Class<?> cls)
{
new Handler().postDelayed(() ->
{
finish();
overridePendingTransition(fade_in, fade_out);
startActivity(new Intent(this, cls));
}, 500); // HACK: Let the menu disappear first
}
public void setBaseMenu(@Nullable BaseMenu baseMenu)
{
this.baseMenu = baseMenu;
}
public void setScreen(@Nullable BaseScreen screen)
{
this.screen = screen;
}
public void showDialog(AppCompatDialogFragment dialog, String tag)
{
dialog.show(getSupportFragmentManager(), tag);
}
public void showDialog(AppCompatDialog dialog)
{
dialog.show();
}
@Override
protected void onActivityResult(int request, int result, Intent data)
{
if (screen == null) super.onActivityResult(request, result, data);
else screen.onResult(request, result, data);
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(getExceptionHandler());
}
protected Thread.UncaughtExceptionHandler getExceptionHandler()
{
return new BaseExceptionHandler(this);
}
@Override
protected void onResume()
{
super.onResume();
if(screen != null) screen.reattachDialogs();
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import dagger.*;
@Module
public class BaseActivityModule
{
private BaseActivity activity;
public BaseActivityModule(BaseActivity activity)
{
this.activity = activity;
}
@Provides
public BaseActivity getBaseActivity()
{
return activity;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import android.view.*;
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
/**
* Base class for all the menus in the application.
* <p>
* This class receives from BaseActivity all callbacks related to menus, such as
* menu creation and click events. It also handles some implementation details
* of creating menus in Android, such as inflating the resources.
*/
public abstract class BaseMenu
{
@NonNull
private final BaseActivity activity;
public BaseMenu(@NonNull BaseActivity activity)
{
this.activity = activity;
}
@NonNull
public BaseActivity getActivity()
{
return activity;
}
/**
* Declare that the menu has changed, and should be recreated.
*/
public void invalidate()
{
activity.invalidateOptionsMenu();
}
/**
* Called when the menu is first displayed.
* <p>
* The given menu is already inflated and ready to receive items. The
* application should override this method and add items to the menu here.
*
* @param menu the menu that is being created.
*/
public void onCreate(@NonNull Menu menu)
{
}
/**
* Called when the menu is first displayed.
* <p>
* This method should not be overridden. The application should override
* the methods onCreate(Menu) and getMenuResourceId instead.
*
* @param inflater a menu inflater, for creating the menu
* @param menu the menu that is being created.
*/
public void onCreate(@NonNull MenuInflater inflater, @NonNull Menu menu)
{
menu.clear();
inflater.inflate(getMenuResourceId(), menu);
onCreate(menu);
}
/**
* Called whenever an item on the menu is selected.
*
* @param item the item that was selected.
* @return true if the event was consumed, or false otherwise
*/
public boolean onItemSelected(@NonNull MenuItem item)
{
return false;
}
/**
* Returns the id of the resource that should be used to inflate this menu.
*
* @return id of the menu resource.
*/
@MenuRes
protected abstract int getMenuResourceId();
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import android.content.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import android.view.*;
import android.widget.*;
import org.isoron.androidbase.*;
import org.isoron.androidbase.utils.*;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
/**
* Base class for all root views in the application.
* <p>
* A root view is an Android view that is directly attached to an activity. This
* view usually includes a toolbar and a progress bar. This abstract class hides
* some of the complexity of setting these things up, for every version of
* Android.
*/
public abstract class BaseRootView extends FrameLayout
{
@NonNull
private final Context context;
protected boolean shouldDisplayHomeAsUp = false;
@Nullable
private BaseScreen screen;
public BaseRootView(@NonNull Context context)
{
super(context);
this.context = context;
}
public boolean getDisplayHomeAsUp()
{
return shouldDisplayHomeAsUp;
}
public void setDisplayHomeAsUp(boolean b)
{
shouldDisplayHomeAsUp = b;
}
@NonNull
public Toolbar getToolbar()
{
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar == null) throw new RuntimeException(
"Your BaseRootView should have a " +
"toolbar with id R.id.toolbar");
return toolbar;
}
public int getToolbarColor()
{
StyledResources res = new StyledResources(context);
return res.getColor(R.attr.colorPrimary);
}
protected void initToolbar()
{
if (SDK_INT >= LOLLIPOP)
{
getToolbar().setElevation(InterfaceUtils.dpToPixels(context, 2));
View view = findViewById(R.id.toolbarShadow);
if (view != null) view.setVisibility(GONE);
view = findViewById(R.id.headerShadow);
if (view != null) view.setVisibility(GONE);
}
}
public void onAttachedToScreen(BaseScreen screen)
{
this.screen = screen;
}
@Nullable
public BaseScreen getScreen()
{
return screen;
}
}

View File

@@ -0,0 +1,318 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import android.content.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.net.*;
import android.os.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.content.res.*;
import androidx.appcompat.app.*;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
import android.view.*;
import android.widget.*;
import com.google.android.material.snackbar.Snackbar;
import org.isoron.androidbase.*;
import org.isoron.androidbase.utils.*;
import java.io.*;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static androidx.core.content.FileProvider.getUriForFile;
/**
* Base class for all screens in the application.
* <p>
* Screens are responsible for deciding what root views and what menus should be
* attached to the main window. They are also responsible for showing other
* screens and for receiving their results.
*/
public class BaseScreen
{
protected BaseActivity activity;
@Nullable
private BaseRootView rootView;
@Nullable
private BaseSelectionMenu selectionMenu;
protected Snackbar snackbar;
public BaseScreen(@NonNull BaseActivity activity)
{
this.activity = activity;
}
@Deprecated
public static int getDefaultActionBarColor(Context context)
{
if (SDK_INT < LOLLIPOP)
{
return ResourcesCompat.getColor(context.getResources(),
R.color.grey_900, context.getTheme());
}
else
{
StyledResources res = new StyledResources(context);
return res.getColor(R.attr.colorPrimary);
}
}
@Deprecated
public static void setupActionBarColor(@NonNull AppCompatActivity activity,
int color)
{
Toolbar toolbar = (Toolbar) activity.findViewById(R.id.toolbar);
if (toolbar == null) return;
activity.setSupportActionBar(toolbar);
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar == null) return;
actionBar.setDisplayHomeAsUpEnabled(true);
ColorDrawable drawable = new ColorDrawable(color);
actionBar.setBackgroundDrawable(drawable);
if (SDK_INT >= LOLLIPOP)
{
int darkerColor = ColorUtils.mixColors(color, Color.BLACK, 0.75f);
activity.getWindow().setStatusBarColor(darkerColor);
toolbar.setElevation(InterfaceUtils.dpToPixels(activity, 2));
View view = activity.findViewById(R.id.toolbarShadow);
if (view != null) view.setVisibility(View.GONE);
view = activity.findViewById(R.id.headerShadow);
if (view != null) view.setVisibility(View.GONE);
}
}
/**
* Notifies the screen that its contents should be updated.
*/
public void invalidate()
{
if (rootView == null) return;
rootView.invalidate();
}
public void invalidateToolbar()
{
if (rootView == null) return;
activity.runOnUiThread(() ->
{
Toolbar toolbar = rootView.getToolbar();
activity.setSupportActionBar(toolbar);
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar == null) return;
actionBar.setDisplayHomeAsUpEnabled(rootView.getDisplayHomeAsUp());
int color = rootView.getToolbarColor();
setActionBarColor(actionBar, color);
setStatusBarColor(color);
});
}
/**
* Called when another Activity has finished, and has returned some result.
*
* @param requestCode the request code originally supplied to {@link
* android.app.Activity#startActivityForResult(Intent,
* int, Bundle)}.
* @param resultCode the result code sent by the other activity.
* @param data an Intent containing extra data sent by the other
* activity.
* @see {@link android.app.Activity#onActivityResult(int, int, Intent)}
*/
public void onResult(int requestCode, int resultCode, Intent data)
{
}
/**
* Called after activity has been recreated, and the dialogs should be
* reattached to their controllers.
*/
public void reattachDialogs()
{
}
/**
* Sets the menu to be shown by this screen.
* <p>
* This menu will be visible if when there is no active selection operation.
* If the provided menu is null, then no menu will be shown.
*
* @param menu the menu to be shown.
*/
public void setMenu(@Nullable BaseMenu menu)
{
activity.setBaseMenu(menu);
}
/**
* Sets the root view for this screen.
*
* @param rootView the root view for this screen.
*/
public void setRootView(@Nullable BaseRootView rootView)
{
this.rootView = rootView;
activity.setContentView(rootView);
if (rootView == null) return;
rootView.onAttachedToScreen(this);
invalidateToolbar();
}
/**
* Sets the menu to be shown when a selection is active on the screen.
*
* @param menu the menu to be shown during a selection
*/
public void setSelectionMenu(@Nullable BaseSelectionMenu menu)
{
this.selectionMenu = menu;
}
/**
* Shows a message on the screen.
*
* @param stringId the string resource id for this message.
*/
public void showMessage(@StringRes Integer stringId)
{
if (stringId == null || rootView == null) return;
if (snackbar == null)
{
snackbar = Snackbar.make(rootView, stringId, Snackbar.LENGTH_SHORT);
int tvId = R.id.snackbar_text;
TextView tv = (TextView) snackbar.getView().findViewById(tvId);
tv.setTextColor(Color.WHITE);
}
else snackbar.setText(stringId);
snackbar.show();
}
public void showSendEmailScreen(@StringRes int toId,
@StringRes int subjectId,
String content)
{
String to = activity.getString(toId);
String subject = activity.getString(subjectId);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("message/rfc822");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ to });
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, content);
activity.startActivity(intent);
}
public void showSendFileScreen(@NonNull String archiveFilename)
{
File file = new File(archiveFilename);
Uri fileUri = getUriForFile(activity, "org.isoron.uhabits", file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("application/zip");
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
activity.startActivity(intent);
}
/**
* Instructs the screen to start a selection.
* <p>
* If a selection menu was provided, this menu will be shown instead of the
* regular one.
*/
public void startSelection()
{
activity.startSupportActionMode(new ActionModeWrapper());
}
private void setActionBarColor(@NonNull ActionBar actionBar, int color)
{
ColorDrawable drawable = new ColorDrawable(color);
actionBar.setBackgroundDrawable(drawable);
}
private void setStatusBarColor(int baseColor)
{
if (SDK_INT < LOLLIPOP) return;
int darkerColor = ColorUtils.mixColors(baseColor, Color.BLACK, 0.75f);
activity.getWindow().setStatusBarColor(darkerColor);
}
private class ActionModeWrapper implements ActionMode.Callback
{
@Override
public boolean onActionItemClicked(@Nullable ActionMode mode,
@Nullable MenuItem item)
{
if (item == null || selectionMenu == null) return false;
return selectionMenu.onItemClicked(item);
}
@Override
public boolean onCreateActionMode(@Nullable ActionMode mode,
@Nullable Menu menu)
{
if (selectionMenu == null) return false;
if (mode == null || menu == null) return false;
selectionMenu.onCreate(activity.getMenuInflater(), mode, menu);
return true;
}
@Override
public void onDestroyActionMode(@Nullable ActionMode mode)
{
if (selectionMenu == null) return;
selectionMenu.onFinish();
}
@Override
public boolean onPrepareActionMode(@Nullable ActionMode mode,
@Nullable Menu menu)
{
if (selectionMenu == null || menu == null) return false;
return selectionMenu.onPrepare(menu);
}
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.activities;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ActionMode;
import android.view.*;
/**
* Base class for all the selection menus in the application.
* <p>
* A selection menu is a menu that appears when the screen starts a selection
* operation. It contains actions that modify the selected items, such as delete
* or archive. Since it replaces the toolbar, it also has a title.
* <p>
* This class hides many implementation details of creating such menus in
* Android. The interface is supposed to look very similar to {@link BaseMenu},
* with a few additional methods, such as finishing the selection operation.
* Internally, it uses an {@link ActionMode}.
*/
public abstract class BaseSelectionMenu
{
@Nullable
private ActionMode actionMode;
/**
* Finishes the selection operation.
*/
public void finish()
{
if (actionMode != null) actionMode.finish();
}
/**
* Declare that the menu has changed, and should be recreated.
*/
public void invalidate()
{
if (actionMode != null) actionMode.invalidate();
}
/**
* Called when the menu is first displayed.
* <p>
* This method should not be overridden. The application should override
* the methods onCreate(Menu) and getMenuResourceId instead.
*
* @param inflater a menu inflater, for creating the menu
* @param mode the action mode associated with this menu.
* @param menu the menu that is being created.
*/
public void onCreate(@NonNull MenuInflater inflater,
@NonNull ActionMode mode,
@NonNull Menu menu)
{
this.actionMode = mode;
inflater.inflate(getResourceId(), menu);
onCreate(menu);
}
/**
* Called when the selection operation is about to finish.
*/
public void onFinish()
{
}
/**
* Called whenever an item on the menu is selected.
*
* @param item the item that was selected.
* @return true if the event was consumed, or false otherwise
*/
public boolean onItemClicked(@NonNull MenuItem item)
{
return false;
}
/**
* Called whenever the menu is invalidated.
*
* @param menu the menu to be refreshed
* @return true if the menu has changes, false otherwise
*/
public boolean onPrepare(@NonNull Menu menu)
{
return false;
}
/**
* Sets the title of the selection menu.
*
* @param title the new title.
*/
public void setTitle(String title)
{
if (actionMode != null) actionMode.setTitle(title);
}
protected abstract int getResourceId();
/**
* Called when the menu is first created.
*
* @param menu the menu being created
*/
protected void onCreate(@NonNull Menu menu)
{
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.utils;
import android.graphics.*;
public abstract class ColorUtils
{
public static int mixColors(int color1, int color2, float amount)
{
final byte ALPHA_CHANNEL = 24;
final byte RED_CHANNEL = 16;
final byte GREEN_CHANNEL = 8;
final byte BLUE_CHANNEL = 0;
final float inverseAmount = 1.0f - amount;
int a = ((int) (((float) (color1 >> ALPHA_CHANNEL & 0xff) * amount) +
((float) (color2 >> ALPHA_CHANNEL & 0xff) *
inverseAmount))) & 0xff;
int r = ((int) (((float) (color1 >> RED_CHANNEL & 0xff) * amount) +
((float) (color2 >> RED_CHANNEL & 0xff) *
inverseAmount))) & 0xff;
int g = ((int) (((float) (color1 >> GREEN_CHANNEL & 0xff) * amount) +
((float) (color2 >> GREEN_CHANNEL & 0xff) *
inverseAmount))) & 0xff;
int b = ((int) (((float) (color1 & 0xff) * amount) +
((float) (color2 & 0xff) * inverseAmount))) & 0xff;
return a << ALPHA_CHANNEL | r << RED_CHANNEL | g << GREEN_CHANNEL |
b << BLUE_CHANNEL;
}
public static int setAlpha(int color, float newAlpha)
{
int intAlpha = (int) (newAlpha * 255);
return Color.argb(intAlpha, Color.red(color), Color.green(color),
Color.blue(color));
}
public static int setMinValue(int color, float newValue)
{
float hsv[] = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] = Math.max(hsv[2], newValue);
return Color.HSVToColor(hsv);
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.utils;
import android.os.*;
import android.util.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.*;
public abstract class FileUtils
{
public static void copy(File src, File dst) throws IOException
{
FileInputStream inStream = new FileInputStream(src);
FileOutputStream outStream = new FileOutputStream(dst);
copy(inStream, outStream);
}
public static void copy(InputStream inStream, File dst) throws IOException
{
FileOutputStream outStream = new FileOutputStream(dst);
copy(inStream, outStream);
}
public static void copy(InputStream in, OutputStream out) throws IOException
{
int numBytes;
byte[] buffer = new byte[1024];
while ((numBytes = in.read(buffer)) != -1)
out.write(buffer, 0, numBytes);
}
@Nullable
public static File getDir(@NonNull File potentialParentDirs[],
@Nullable String relativePath)
{
if (relativePath == null) relativePath = "";
File chosenDir = null;
for (File dir : potentialParentDirs)
{
if (dir == null || !dir.canWrite()) continue;
chosenDir = dir;
break;
}
if (chosenDir == null)
{
Log.e("FileUtils",
"getDir: all potential parents are null or non-writable");
return null;
}
File dir = new File(
String.format("%s/%s/", chosenDir.getAbsolutePath(), relativePath));
if (!dir.exists() && !dir.mkdirs())
{
Log.e("FileUtils",
"getDir: chosen dir does not exist and cannot be created");
return null;
}
return dir;
}
@Nullable
public static File getSDCardDir(@Nullable String relativePath)
{
File parents[] =
new File[]{ Environment.getExternalStorageDirectory() };
return getDir(parents, relativePath);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.utils;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.*;
import android.util.*;
import android.view.*;
import android.widget.*;
public abstract class InterfaceUtils
{
private static Typeface fontAwesome;
@Nullable
private static Float fixedResolution = null;
public static void setFixedResolution(@NonNull Float f)
{
fixedResolution = f;
}
public static Typeface getFontAwesome(Context context)
{
if(fontAwesome == null) fontAwesome =
Typeface.createFromAsset(context.getAssets(),
"fontawesome-webfont.ttf");
return fontAwesome;
}
public static float dpToPixels(Context context, float dp)
{
if(fixedResolution != null) return dp * fixedResolution;
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
}
public static float spToPixels(Context context, float sp)
{
if(fixedResolution != null) return sp * fixedResolution;
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics);
}
public static float getDimension(Context context, int id)
{
float dim = context.getResources().getDimension(id);
if (fixedResolution == null) return dim;
else
{
DisplayMetrics dm = context.getResources().getDisplayMetrics();
float actualDensity = dm.density;
return dim / actualDensity * fixedResolution;
}
}
public static void setupEditorAction(@NonNull ViewGroup parent,
@NonNull TextView.OnEditorActionListener listener)
{
for (int i = 0; i < parent.getChildCount(); i++)
{
View child = parent.getChildAt(i);
if (child instanceof ViewGroup)
setupEditorAction((ViewGroup) child, listener);
if (child instanceof TextView)
((TextView) child).setOnEditorActionListener(listener);
}
}
public static boolean isLayoutRtl(View view)
{
return ViewCompat.getLayoutDirection(view) ==
ViewCompat.LAYOUT_DIRECTION_RTL;
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.androidbase.utils;
import android.content.*;
import android.content.res.*;
import android.graphics.drawable.*;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import org.isoron.androidbase.*;
public class StyledResources
{
private static Integer fixedTheme;
private final Context context;
public StyledResources(@NonNull Context context)
{
this.context = context;
}
public static void setFixedTheme(Integer theme)
{
fixedTheme = theme;
}
public boolean getBoolean(@AttrRes int attrId)
{
TypedArray ta = getTypedArray(attrId);
boolean bool = ta.getBoolean(0, false);
ta.recycle();
return bool;
}
public int getDimension(@AttrRes int attrId)
{
TypedArray ta = getTypedArray(attrId);
int dim = ta.getDimensionPixelSize(0, 0);
ta.recycle();
return dim;
}
public int getColor(@AttrRes int attrId)
{
TypedArray ta = getTypedArray(attrId);
int color = ta.getColor(0, 0);
ta.recycle();
return color;
}
public Drawable getDrawable(@AttrRes int attrId)
{
TypedArray ta = getTypedArray(attrId);
Drawable drawable = ta.getDrawable(0);
ta.recycle();
return drawable;
}
public float getFloat(@AttrRes int attrId)
{
TypedArray ta = getTypedArray(attrId);
float f = ta.getFloat(0, 0);
ta.recycle();
return f;
}
public int[] getPalette()
{
int resourceId = getResource(R.attr.palette);
if (resourceId < 0) throw new RuntimeException("resource not found");
return context.getResources().getIntArray(resourceId);
}
public int getResource(@AttrRes int attrId)
{
TypedArray ta = getTypedArray(attrId);
int resourceId = ta.getResourceId(0, -1);
ta.recycle();
return resourceId;
}
private TypedArray getTypedArray(@AttrRes int attrId)
{
int[] attrs = new int[]{ attrId };
if (fixedTheme != null)
return context.getTheme().obtainStyledAttributes(fixedTheme, attrs);
return context.obtainStyledAttributes(attrs);
}
}

View File

@@ -0,0 +1,6 @@
<resources>
<item name="toolbar" type="id" />
<item name="toolbarShadow" type="id" />
<item name="headerShadow" type="id" />
<attr name="palette" format="reference"/>
</resources>

View File

@@ -1,60 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The Android Open Source Project
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
http://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.
-->
<resources>
<color name="primary">#37474f</color>
<color name="primary_darker">#263238</color>
<color name="accent">#9a4000</color>
<color name="windowBackground">#e6e6e6</color>
<color name="white">#ffffff</color>
<color name="grey">#cccccc</color>
<!-- Time and Date picker -->
<color name="circle_background">#f2f2f2</color>
<color name="line_background">#cccccc</color>
<color name="ampm_text_color">#8c8c8c</color>
<color name="done_text_color_normal">#000000</color>
<color name="done_text_color_disabled">#cccccc</color>
<color name="numbers_text_color">#8c8c8c</color>
<color name="transparent">#00000000</color>
<color name="transparent_black">#7f000000</color>
<color name="blue">#33b5e5</color>
<color name="blue_focused">#c1e8f7</color>
<color name="neutral_pressed">#33999999</color>
<color name="darker_blue">#0099cc</color>
<color name="date_picker_text_normal">#ff999999</color>
<color name="calendar_header">#999999</color>
<color name="date_picker_view_animator">#f2f2f2</color>
<color name="calendar_selected_date_text">#ffd1d2d4</color>
<color name="done_text_color">#888888</color>
<color name="done_text_color_dark">#888888</color>
<!-- Colors for red theme -->
<color name="red">#ff3333</color>
<color name="red_focused">#853333</color>
<color name="light_gray">#404040</color>
<color name="dark_gray">#363636</color>
<color name="line_dark">#808080</color>
<color name="done_text_color_dark_normal">#ffffff</color>
<color name="done_text_color_dark_disabled">#888888</color>
<color name="done_disabled_dark">#bfbfbf</color>
<!-- Material design color palette -->
<color name="red_50">#FFEBEE</color>
<color name="red_100">#FFCDD2</color>
<color name="red_200">#EF9A9A</color>
@@ -325,6 +270,31 @@
<color name="grey_500">#9E9E9E</color>
<color name="grey_600">#757575</color>
<color name="grey_700">#616161</color>
<color name="grey_750">#525252</color>
<color name="grey_800">#424242</color>
<color name="grey_850">#303030</color>
<color name="grey_875">#282828</color>
<color name="grey_900">#212121</color>
<color name="grey_950">#101010</color>
<color name="white">#ffffff</color>
<color name="black">#000000</color>
<color name="black_ae">#ef000000</color>
<color name="black_ac">#cf000000</color>
<color name="black_aa">#af000000</color>
<color name="black_a8">#8f000000</color>
<color name="black_a6">#6f000000</color>
<color name="black_a4">#4f000000</color>
<color name="black_a2">#2f000000</color>
<color name="black_a0">#0f000000</color>
<color name="white_ae">#efffffff</color>
<color name="white_ac">#cfffffff</color>
<color name="white_aa">#afffffff</color>
<color name="white_a8">#8fffffff</color>
<color name="white_a6">#6fffffff</color>
<color name="white_a4">#4fffffff</color>
<color name="white_a2">#2fffffff</color>
<color name="white_a0">#0fffffff</color>
</resources>

1
android/android-pickers/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,24 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion COMPILE_SDK_VERSION as Integer
defaultConfig {
minSdkVersion MIN_SDK_VERSION as Integer
targetSdkVersion TARGET_SDK_VERSION as Integer
}
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0'
}

View File

@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /gemini-b/opt/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,2 @@
<manifest package="com.android"
xmlns:android="http://schemas.android.com/apk/res/android"/>

View File

@@ -16,24 +16,21 @@
package com.android.colorpicker;
import org.isoron.uhabits.R;
import android.app.*;
import android.os.*;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.*;
import android.view.*;
import android.widget.*;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import com.android.colorpicker.ColorPickerSwatch.OnColorSelectedListener;
import com.android.*;
import com.android.colorpicker.ColorPickerSwatch.*;
/**
* A dialog which takes in as input an array of palette and creates a palette allowing the user to
* select a specific color swatch, which invokes a listener.
*/
public class ColorPickerDialog extends DialogFragment implements OnColorSelectedListener {
public class ColorPickerDialog extends AppCompatDialogFragment implements OnColorSelectedListener {
public static final int SIZE_LARGE = 1;
public static final int SIZE_SMALL = 2;

View File

@@ -16,18 +16,14 @@
package com.android.colorpicker;
import org.isoron.uhabits.R;
import android.content.*;
import android.content.res.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TableRow;
import com.android.colorpicker.ColorPickerSwatch.OnColorSelectedListener;
import com.android.*;
import com.android.colorpicker.ColorPickerSwatch.*;
/**
* A color picker custom view which creates an grid of color squares. The number of squares per

View File

@@ -16,14 +16,12 @@
package com.android.colorpicker;
import org.isoron.uhabits.R;
import android.content.*;
import android.graphics.drawable.*;
import android.view.*;
import android.widget.*;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.android.*;
/**
* Creates a circular swatch of a specified color. Adds a checkmark if marked as checked.

View File

@@ -16,36 +16,23 @@
package com.android.datetimepicker.date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import android.animation.*;
import android.app.*;
import android.content.res.*;
import android.os.*;
import android.text.format.*;
import android.util.*;
import android.view.*;
import android.view.View.*;
import android.view.animation.*;
import android.widget.*;
import org.isoron.uhabits.R;
import com.android.*;
import com.android.datetimepicker.*;
import com.android.datetimepicker.date.MonthAdapter.*;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.DialogFragment;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.datetimepicker.HapticFeedbackController;
import com.android.datetimepicker.Utils;
import com.android.datetimepicker.date.MonthAdapter.CalendarDay;
import java.text.*;
import java.util.*;
/**
* Dialog allowing users to select a date.

View File

@@ -16,37 +16,27 @@
package com.android.datetimepicker.date;
import java.security.InvalidParameterException;
import java.util.Calendar;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.Paint.*;
import android.os.*;
import androidx.core.view.*;
import androidx.core.view.accessibility.*;
import androidx.core.widget.*;
import android.text.format.*;
import android.view.*;
import android.view.accessibility.*;
import androidx.customview.widget.ExploreByTouchHelper;
import com.android.*;
import com.android.datetimepicker.*;
import com.android.datetimepicker.date.MonthAdapter.*;
import java.security.*;
import java.util.*;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import org.isoron.uhabits.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.widget.ExploreByTouchHelper;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.datetimepicker.Utils;
import com.android.datetimepicker.date.MonthAdapter.CalendarDay;
/**
* A calendar-like view displaying a specified month and the appropriate selectable day numbers

View File

@@ -16,16 +16,14 @@
package com.android.datetimepicker.date;
import org.isoron.uhabits.R;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.Paint.*;
import android.util.*;
import android.widget.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.widget.TextView;
import com.android.*;
/**
* A text view which, when pressed or activated, displays a blue circle around the text.

View File

@@ -16,24 +16,18 @@
package com.android.datetimepicker.date;
import java.util.ArrayList;
import java.util.List;
import android.content.*;
import android.content.res.*;
import android.graphics.drawable.*;
import android.view.*;
import android.view.accessibility.*;
import android.widget.*;
import android.widget.AdapterView.*;
import org.isoron.uhabits.R;
import com.android.*;
import com.android.datetimepicker.date.DatePickerDialog.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.StateListDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.android.datetimepicker.date.DatePickerDialog.OnDateChangedListener;
import java.util.*;
/**
* Displays a selectable list of years.

View File

@@ -16,20 +16,17 @@
package com.android.datetimepicker.time;
import java.text.DateFormatSymbols;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.Paint.*;
import android.util.*;
import android.view.*;
import org.isoron.uhabits.R;
import com.android.*;
import com.android.datetimepicker.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Typeface;
import android.util.Log;
import android.view.View;
import com.android.datetimepicker.Utils;
import java.text.*;
/**
* Draw the two smaller AM and PM circles next to where the larger circle will be.

View File

@@ -16,14 +16,14 @@
package com.android.datetimepicker.time;
import org.isoron.uhabits.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.util.*;
import android.view.*;
import com.android.*;
/**
* Draws a simple white circle on which the numbers will be drawn.

View File

@@ -16,30 +16,20 @@
package com.android.datetimepicker.time;
import org.isoron.uhabits.R;
import android.animation.*;
import android.annotation.*;
import android.content.*;
import android.content.res.*;
import android.os.*;
import android.text.format.*;
import android.util.*;
import android.view.*;
import android.view.View.*;
import android.view.accessibility.*;
import android.widget.*;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.datetimepicker.HapticFeedbackController;
import com.android.*;
import com.android.datetimepicker.*;
/**
* The primary layout to hold the circular picker, and the am/pm buttons. This view well measure

View File

@@ -16,21 +16,16 @@
package com.android.datetimepicker.time;
import org.isoron.uhabits.R;
import android.animation.*;
import android.animation.ValueAnimator.*;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.util.*;
import android.view.*;
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
import com.android.datetimepicker.Utils;
import com.android.*;
import com.android.datetimepicker.*;
/**
* View to show what number is selected. This will draw a blue circle over the number, with a blue

View File

@@ -16,21 +16,16 @@
package com.android.datetimepicker.time;
import org.isoron.uhabits.R;
import android.animation.*;
import android.animation.ValueAnimator.*;
import android.content.*;
import android.content.res.*;
import android.graphics.*;
import android.graphics.Paint.*;
import android.util.*;
import android.view.*;
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Typeface;
import android.util.Log;
import android.view.View;
import com.android.*;
/**
* A view to show a series of numbers in a circular pattern.

View File

@@ -16,39 +16,30 @@
package com.android.datetimepicker.time;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Locale;
import android.animation.*;
import android.annotation.*;
import android.app.ActionBar.*;
import android.app.*;
import android.content.*;
import android.content.res.*;
import android.os.*;
import androidx.appcompat.app.*;
import android.util.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import org.isoron.uhabits.R;
import com.android.*;
import com.android.datetimepicker.*;
import com.android.datetimepicker.time.RadialPickerLayout.*;
import android.animation.ObjectAnimator;
import android.app.ActionBar.LayoutParams;
import android.app.DialogFragment;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.datetimepicker.HapticFeedbackController;
import com.android.datetimepicker.Utils;
import com.android.datetimepicker.time.RadialPickerLayout.OnValueSelectedListener;
import java.text.*;
import java.util.*;
/**
* Dialog to set a time.
*/
public class TimePickerDialog extends DialogFragment implements OnValueSelectedListener{
public class TimePickerDialog extends AppCompatDialogFragment implements OnValueSelectedListener{
private static final String TAG = "TimePickerDialog";
private static final String KEY_HOUR_OF_DAY = "hour_of_day";
@@ -72,6 +63,7 @@ public class TimePickerDialog extends DialogFragment implements OnValueSelectedL
private static final int PULSE_ANIMATOR_DELAY = 300;
private OnTimeSetListener mCallback;
private DialogInterface.OnDismissListener dismissListener;
private HapticFeedbackController mHapticFeedbackController;
@@ -125,13 +117,14 @@ public class TimePickerDialog extends DialogFragment implements OnValueSelectedL
*/
void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute);
void onTimeCleared(RadialPickerLayout view);
default void onTimeCleared(RadialPickerLayout view) {}
}
public TimePickerDialog() {
// Empty constructor required for dialog fragment.
}
@SuppressLint("Java")
public TimePickerDialog(Context context, int theme, OnTimeSetListener callback,
int hourOfDay, int minute, boolean is24HourMode) {
// Empty constructor required for dialog fragment.
@@ -190,10 +183,16 @@ public class TimePickerDialog extends DialogFragment implements OnValueSelectedL
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
return new AppCompatDialog(getActivity(), R.style.TimePickerDialog);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View view = inflater.inflate(R.layout.time_picker_dialog, null);
KeyboardListener keyboardListener = new KeyboardListener();
@@ -1000,4 +999,15 @@ public class TimePickerDialog extends DialogFragment implements OnValueSelectedL
return false;
}
}
public void setDismissListener( DialogInterface.OnDismissListener listener ) {
dismissListener = listener;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if( dismissListener != null )
dismissListener.onDismiss(dialog);
}
}

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
~
~ This file is part of Loop Habit Tracker.
~
~ Loop Habit Tracker is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by the
~ Free Software Foundation, either version 3 of the License, or (at your
~ option) any later version.
~
~ Loop Habit Tracker is distributed in the hope that it will be useful, but
~ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
~ more details.
~
~ You should have received a copy of the GNU General Public License along
~ with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<dimen name="color_swatch_large">64dip</dimen>
<dimen name="color_swatch_small">48dip</dimen>
<dimen name="color_swatch_margins_large">8dip</dimen>
<dimen name="color_swatch_margins_small">4dip</dimen>
<item name="circle_radius_multiplier" format="float" translatable="false" type="string">
0.82
</item>
<item name="circle_radius_multiplier_24HourMode" format="float" translatable="false" type="string">
0.85
</item>
<item name="selection_radius_multiplier" format="float" translatable="false" type="string">
0.16
</item>
<item name="ampm_circle_radius_multiplier" format="float" translatable="false" type="string">
0.19
</item>
<item name="numbers_radius_multiplier_normal" format="float" translatable="false" type="string">
0.81
</item>
<item name="numbers_radius_multiplier_inner" format="float" translatable="false" type="string">
0.60
</item>
<item name="numbers_radius_multiplier_outer" format="float" translatable="false" type="string">
0.83
</item>
<item name="text_size_multiplier_normal" format="float" translatable="false" type="string">
0.17
</item>
<item name="text_size_multiplier_inner" format="float" translatable="false" type="string">
0.14
</item>
<item name="text_size_multiplier_outer" format="float" translatable="false" type="string">
0.11
</item>
<dimen name="time_label_size">60sp</dimen>
<dimen name="extra_time_label_margin">-30dp</dimen>
<dimen name="ampm_label_size">16sp</dimen>
<dimen name="done_label_size">14sp</dimen>
<dimen name="ampm_left_padding">6dip</dimen>
<dimen name="separator_padding">4dip</dimen>
<dimen name="header_height">80dip</dimen>
<dimen name="footer_height">48dip</dimen>
<dimen name="minimum_margin_sides">48dip</dimen>
<dimen name="minimum_margin_top_bottom">24dip</dimen>
<dimen name="picker_dimen">250dip</dimen>
<dimen name="date_picker_component_width">250dp</dimen>
<dimen name="date_picker_header_height">30dp</dimen>
<dimen name="selected_calendar_layout_height">155dp</dimen>
<dimen name="date_picker_view_animator_height">270dp</dimen>
<dimen name="done_button_height">42dp</dimen>
<dimen name="month_list_item_header_height">50dp</dimen>
<dimen name="month_day_label_text_size">10sp</dimen>
<dimen name="day_number_select_circle_radius">16dp</dimen>
<dimen name="month_select_circle_radius">45dp</dimen>
<dimen name="selected_date_year_size">30dp</dimen>
<dimen name="selected_date_day_size">75dp</dimen>
<dimen name="selected_date_month_size">30dp</dimen>
<dimen name="date_picker_header_text_size">14dp</dimen>
<dimen name="month_label_size">16sp</dimen>
<dimen name="day_number_size">16sp</dimen>
<dimen name="year_label_height">64dp</dimen>
<dimen name="year_label_text_size">22dp</dimen>
<string name="color_swatch_description" translatable="false">Color <xliff:g example="14" id="color_index">%1$d</xliff:g></string>
<string name="color_swatch_description_selected" translatable="false">Color <xliff:g example="14" id="color_index">%1$d</xliff:g> selected</string>
<!-- Date and time picker -->
<string name="hour_picker_description" translatable="false">Hours circular slider</string>
<string name="minute_picker_description" translatable="false">Minutes circular slider</string>
<string name="day_picker_description" translatable="false">Month grid of days</string>
<string name="year_picker_description" translatable="false">Year list</string>
<string name="select_day" translatable="false">Select month and day</string>
<string name="select_year" translatable="false">Select year</string>
<string name="item_is_selected" translatable="false"><xliff:g example="2013" id="item">%1$s</xliff:g> selected</string>
<string name="deleted_key" translatable="false"><xliff:g example="4" id="key">%1$s</xliff:g> deleted</string>
<string name="time_placeholder" translatable="false">--</string>
<string name="time_separator" translatable="false">:</string>
<string name="radial_numbers_typeface" translatable="false">sans-serif</string>
<string name="sans_serif" translatable="false">sans-serif</string>
<string name="day_of_week_label_typeface" translatable="false">sans-serif</string>
<!-- Time and Date picker -->
<color name="circle_background">#f2f2f2</color>
<color name="line_background">#cccccc</color>
<color name="ampm_text_color">#8c8c8c</color>
<color name="done_text_color_normal">#000000</color>
<color name="done_text_color_disabled">#cccccc</color>
<color name="numbers_text_color">#8c8c8c</color>
<color name="transparent">#00000000</color>
<color name="transparent_black">#7f000000</color>
<color name="blue">#33b5e5</color>
<color name="blue_focused">#c1e8f7</color>
<color name="neutral_pressed">#33999999</color>
<color name="darker_blue">#0099cc</color>
<color name="date_picker_text_normal">#ff999999</color>
<color name="calendar_header">#999999</color>
<color name="date_picker_view_animator">#f2f2f2</color>
<color name="calendar_selected_date_text">#ffd1d2d4</color>
<color name="done_text_color">#888888</color>
<color name="done_text_color_dark">#888888</color>
<color name="white">#ffffff</color>
<color name="black">#000000</color>
<!-- Colors for red theme -->
<color name="red">#ff3333</color>
<color name="red_focused">#853333</color>
<color name="light_gray">#404040</color>
<color name="dark_gray">#363636</color>
<color name="line_dark">#808080</color>
<style name="time_label">
<item name="android:textSize">@dimen/time_label_size</item>
<item name="android:textColor">@color/numbers_text_color</item>
</style>
<style name="ampm_label">
<item name="android:textSize">@dimen/ampm_label_size</item>
<item name="android:textAllCaps">true</item>
<item name="android:textColor">@color/ampm_text_color</item>
<item name="android:textStyle">bold</item>
</style>
<style name="TimePickerDialog" parent="@style/Theme.AppCompat.Light.Dialog">
<item name="windowNoTitle">true</item>
</style>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="select_hours"/>
<string name="select_minutes"/>
<string name="color_picker_default_title"/>
<string name="clear"/>
<string name="clear_label"/>
<string name="done_label"/>
</resources>

21
android/build.gradle Normal file
View File

@@ -0,0 +1,21 @@
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:$BUILD_TOOLS_VERSION"
classpath "com.neenbedankt.gradle.plugins:android-apt:1.8"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION"
classpath "org.ajoberstar:grgit:1.5.0"
}
}
allprojects {
repositories {
google()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
jcenter()
}
}

279
android/build.sh Executable file
View File

@@ -0,0 +1,279 @@
#!/bin/bash
# Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
# This file is part of Loop Habit Tracker.
#
# Loop Habit Tracker is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# Loop Habit Tracker is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
cd "$(dirname "$0")"
ADB="${ANDROID_HOME}/platform-tools/adb"
EMULATOR="${ANDROID_HOME}/tools/emulator"
GRADLE="./gradlew --stacktrace"
PACKAGE_NAME=org.isoron.uhabits
OUTPUTS_DIR=uhabits-android/build/outputs
VERSION=$(cat gradle.properties | grep VERSION_NAME | sed -e 's/.*=//g;s/ //g')
if [ ! -f "${ANDROID_HOME}/platform-tools/adb" ]; then
echo "Error: ANDROID_HOME is not set correctly"
exit 1
fi
log_error() {
if [ ! -z "$TEAMCITY_VERSION" ]; then
echo "###teamcity[progressMessage '$1']"
else
local COLOR='\033[1;31m'
local NC='\033[0m'
echo -e "$COLOR>>> $1 $NC"
fi
}
log_info() {
if [ ! -z "$TEAMCITY_VERSION" ]; then
echo "###teamcity[progressMessage '$1']"
else
local COLOR='\033[1;32m'
local NC='\033[0m'
echo -e "$COLOR>>> $1 $NC"
fi
}
fail() {
log_error "BUILD FAILED"
exit 1
}
if [ ! -z $RELEASE ]; then
log_info "Reading secret env variables from ../.secret/env"
source ../.secret/env || fail
fi
run_adb_as_root() {
log_info "Running adb as root"
$ADB root
}
build_apk() {
log_info "Removing old APKs..."
rm -vf build/*.apk
if [ ! -z $RELEASE ]; then
log_info "Building release APK"
./gradlew assembleRelease
cp -v uhabits-android/build/outputs/apk/release/uhabits-android-release.apk build/loop-$VERSION-release.apk
fi
log_info "Building debug APK"
./gradlew assembleDebug || fail
cp -v uhabits-android/build/outputs/apk/debug/uhabits-android-debug.apk build/loop-$VERSION-debug.apk
}
build_instrumentation_apk() {
log_info "Building instrumentation APK"
if [ ! -z $RELEASE ]; then
$GRADLE assembleAndroidTest \
-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
else
$GRADLE assembleAndroidTest || fail
fi
}
uninstall_apk() {
log_info "Uninstalling existing APK"
$ADB uninstall ${PACKAGE_NAME}
}
install_test_butler() {
log_info "Installing Test Butler"
$ADB uninstall com.linkedin.android.testbutler
$ADB install tools/test-butler-app-2.0.2.apk
}
install_apk() {
log_info "Installing APK"
if [ ! -z $RELEASE ]; then
$ADB install -r ${OUTPUTS_DIR}/apk/release/uhabits-android-release.apk || fail
else
$ADB install -t -r ${OUTPUTS_DIR}/apk/debug/uhabits-android-debug.apk || fail
fi
}
install_test_apk() {
log_info "Uninstalling existing test APK"
$ADB uninstall ${PACKAGE_NAME}.test
log_info "Installing test APK"
$ADB install -r ${OUTPUTS_DIR}/apk/androidTest/debug/uhabits-android-debug-androidTest.apk || fail
}
run_instrumented_tests() {
SIZE=$1
log_info "Running instrumented tests"
$ADB shell am instrument \
-r -e coverage true -e size $SIZE \
-w ${PACKAGE_NAME}.test/androidx.test.runner.AndroidJUnitRunner \
| tee ${OUTPUTS_DIR}/instrument.txt
if grep "\(INSTRUMENTATION_STATUS_CODE.*-1\|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() {
log_info "Parsing instrumented test results"
java -jar tools/automator-log-converter-1.5.0.jar ${OUTPUTS_DIR}/instrument.txt || fail
}
generate_coverage_badge() {
log_info "Generating code coverage badge"
CORE_REPORT=uhabits-core/build/reports/jacoco/test/jacocoTestReport.xml
rm -f ${OUTPUTS_DIR}/coverage-badge.svg
python3 tools/coverage-badge/badge.py -i $CORE_REPORT -o ${OUTPUTS_DIR}/coverage-badge
}
fetch_logcat() {
log_info "Fetching logcat"
$ADB logcat -d > ${OUTPUTS_DIR}/logcat.txt
}
run_jvm_tests() {
log_info "Running JVM tests"
if [ ! -z $RELEASE ]; then
$GRADLE testReleaseUnitTest :uhabits-core:check || fail
else
$GRADLE testDebugUnitTest :uhabits-core:check || fail
fi
}
uninstall_test_apk() {
log_info "Uninstalling test APK"
$ADB uninstall ${PACKAGE_NAME}.test
}
fetch_images() {
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/
}
accept_images() {
find $OUTPUTS_DIR/test-screenshots -name '*.expected*' -delete
rsync -av $OUTPUTS_DIR/test-screenshots/ uhabits-android/src/androidTest/assets/
}
run_tests() {
SIZE=$1
run_adb_as_root
install_test_butler
uninstall_apk
install_apk
install_test_apk
run_instrumented_tests $SIZE
parse_instrumentation_results
fetch_logcat
uninstall_test_apk
}
parse_opts() {
OPTS=`getopt -o r --long release -n 'build.sh' -- "$@"`
if [ $? != 0 ] ; then exit 1; fi
eval set -- "$OPTS"
while true; do
case "$1" in
-r | --release ) RELEASE=1; shift ;;
* ) break ;;
esac
done
}
remove_build_dir() {
rm -rfv build
rm -rfv android-base/build
rm -rfv android-pickers/build
rm -rfv uhabits-android/build
rm -rfv uhabits-core/build
}
case "$1" in
build)
shift; parse_opts $*
build_apk
build_instrumentation_apk
run_jvm_tests
#generate_coverage_badge
;;
medium-tests)
shift; parse_opts $*
run_tests medium
;;
large-tests)
shift; parse_opts $*
run_tests large
;;
fetch-images)
fetch_images
;;
accept-images)
accept_images
;;
install)
shift; parse_opts $*
build_apk
install_apk
;;
clean)
remove_build_dir
;;
*)
cat <<END
Usage: $0 <command> [options]
Builds, installs and tests Loop Habit Tracker
Commands:
accept-images Copies fetched images to corresponding assets folder
build Build APK and run JVM tests
clean Remove build directory
fetch-images Fetches failed view test images from device
install Install app on connected device
large-tests Run large-sized tests on connected device
medium-tests Run medium-sized tests on connected device
Options:
-r --release Build and test release APK, instead of debug
END
exit 1
;;
esac

18
android/gradle.properties Normal file
View File

@@ -0,0 +1,18 @@
VERSION_CODE = 51
VERSION_NAME = 1.8.8
MIN_SDK_VERSION = 21
TARGET_SDK_VERSION = 29
COMPILE_SDK_VERSION = 29
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.3
org.gradle.parallel=false
org.gradle.daemon=true
org.gradle.jvmargs=-Xms2048m -Xmx2048m -XX:MaxPermSize=2048m
android.useAndroidX=true
android.enableJetifier=true

Binary file not shown.

View File

@@ -1,6 +1,5 @@
#Wed Apr 10 15:27:10 PDT 2013
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-2.2.1-all.zip

183
android/gradlew vendored Executable file
View File

@@ -0,0 +1,183 @@
#!/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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# 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 () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
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
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# 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`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
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" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
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" "$@"

100
android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,100 @@
@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
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
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
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
android/play Symbolic link
View File

@@ -0,0 +1 @@
uhabits-android/src/main/play/

1
android/settings.gradle Normal file
View File

@@ -0,0 +1 @@
include ':uhabits-android', ':uhabits-core', ':android-base', ':android-pickers'

Binary file not shown.

View File

@@ -0,0 +1,157 @@
"""
Generate coverage badges for Coverage.py.
Forked from https://github.com/dbrgn/coverage-badge
"""
# -*- coding: utf-8 -*-
from __future__ import print_function, division, absolute_import, unicode_literals
import os
import sys
import argparse
import pkg_resources
from bs4 import BeautifulSoup
__version__ = '0.2.0-uhabits'
DEFAULT_COLOR = '#a4a61d'
COLORS = {
'brightgreen': '#4c1',
'green': '#97CA00',
'yellowgreen': '#a4a61d',
'yellow': '#dfb317',
'orange': '#fe7d37',
'red': '#e05d44',
'lightgrey': '#9f9f9f',
}
COLOR_RANGES = [
(95, 'brightgreen'),
(90, 'green'),
(75, 'yellowgreen'),
(60, 'yellow'),
(40, 'orange'),
(0, 'red'),
]
class Devnull(object):
"""
A file like object that does nothing.
"""
def write(self, *args, **kwargs):
pass
def get_total(report):
missed = 0
covered = 0
for r in report.split(":"):
doc = BeautifulSoup(open(r), 'xml')
tag = doc.select("report > counter[type^INST]")[0]
missed = missed + float(tag['missed'])
covered = covered + float(tag['covered'])
return str(int(round(100 * covered / (missed + covered))))
def get_color(total):
"""
Return color for current coverage precent
"""
try:
xtotal = int(total)
except ValueError:
return COLORS['lightgrey']
for range_, color in COLOR_RANGES:
if xtotal >= range_:
return COLORS[color]
def get_badge(total, color=DEFAULT_COLOR):
"""
Read the SVG template from the package, update total, return SVG as a
string.
"""
template_path = os.path.join('templates', 'flat.svg')
template = pkg_resources.resource_string(__name__, template_path).decode('utf8')
return template.replace('{{ total }}', total).replace('{{ color }}', color)
def parse_args(argv=None):
"""
Parse the command line arguments.
"""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-o', dest='filepath',
help='Save the file to the specified path.')
parser.add_argument('-p', dest='plain_color', action='store_true',
help='Plain color mode. Standard green badge.')
parser.add_argument('-f', dest='force', action='store_true',
help='Force overwrite image, use with -o key.')
parser.add_argument('-q', dest='quiet', action='store_true',
help='Don\'t output any non-error messages.')
parser.add_argument('-v', dest='print_version', action='store_true',
help='Show version.')
parser.add_argument('-i', dest='reportFilename',
help='Jacoco report')
# If arguments have been passed in, use them.
if argv:
return parser.parse_args(argv)
# Otherwise, just use sys.argv directly.
else:
return parser.parse_args()
def save_badge(badge, filepath, force=False):
"""
Save badge to the specified path.
"""
# Validate path (part 1)
if filepath.endswith('/'):
print('Error: Filepath may not be a directory.')
sys.exit(1)
# Get absolute filepath
path = os.path.abspath(filepath)
if not path.lower().endswith('.svg'):
path += '.svg'
# Validate path (part 2)
if not force and os.path.exists(path):
print('Error: "{}" already exists.'.format(path))
sys.exit(1)
# Write file
with open(path, 'w') as f:
f.write(badge)
return path
def main(argv=None):
"""
Console scripts entry point.
"""
args = parse_args(argv)
# Print version
if args.print_version:
print('coverage-badge v{}'.format(__version__))
sys.exit(0)
total = get_total(args.reportFilename)
color = DEFAULT_COLOR if args.plain_color else get_color(total)
badge = get_badge(total, color)
# Show or save output
if args.filepath:
path = save_badge(badge, args.filepath, args.force)
if not args.quiet:
print('Saved badge to {}'.format(path))
else:
print(badge, end='')
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="a">
<rect width="99" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#a)">
<path fill="#555" d="M0 0h63v20H0z"/>
<path fill="{{ color }}" d="M63 0h36v20H63z"/>
<path fill="url(#b)" d="M0 0h99v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
<text x="31.5" y="14">coverage</text>
<text x="80" y="15" fill="#010101" fill-opacity=".3">{{ total }}%</text>
<text x="80" y="14">{{ total }}%</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

View File

@@ -0,0 +1,137 @@
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
def secretPropsFile = file("../../.secret/gradle.properties")
if (secretPropsFile.exists()) {
def secrets = new Properties()
secretPropsFile.withInputStream { secrets.load(it) }
signingConfigs {
release {
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
}
defaultConfig {
versionCode VERSION_CODE as Integer
versionName "$VERSION_NAME"
minSdkVersion MIN_SDK_VERSION as Integer
targetSdkVersion TARGET_SDK_VERSION as Integer
applicationId "org.isoron.uhabits"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
debug {
testCoverageEnabled true
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
disable 'GoogleAppIndexingWarning'
}
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
testOptions {
unitTests.all {
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen { false }
showStandardStreams = true
}
}
}
sourceSets {
main.assets.srcDirs += '../uhabits-core/src/main/resources/'
}
}
dependencies {
implementation project(":uhabits-core")
implementation project(":android-base")
implementation project(":android-pickers")
implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "com.github.paolorotolo:appintro:3.4.0"
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.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"
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
kapt "com.jakewharton:butterknife-compiler:10.2.1"
annotationProcessor "com.google.auto.factory:auto-factory:$AUTO_FACTORY_VERSION"
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
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"
androidTestImplementation 'androidx.annotation:annotation:1.0.0'
androidTestImplementation 'androidx.test:rules:1.1.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation "com.google.guava:guava:24.1-android"
androidTestImplementation project(":uhabits-core")
kaptAndroidTest "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
// 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.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.12"
implementation('com.opencsv:opencsv:3.10') {
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation('io.socket:socket.io-client:0.8.3') {
exclude group: 'org.json', module: 'json'
}
}
kapt {
correctErrorTypes = true
}
play {
serviceAccountCredentials = file("../../.secret/gcp-key.json")
track = "alpha"
}

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