Compare commits

...

1156 Commits
12.7.1 ... main

Author SHA1 Message Date
renovate[bot] f8bb045d76 chore(deps): update actions/cache action to v4 2 days ago
renovate[bot] 4040a2379b fix(deps): update dependency com.google.android.gms:play-services-oss-licenses to v17.1.0 2 days ago
Alex Baker c4ee7479ca
Cache avd 2 days ago
Alex Baker be861597ef Merge branch '13.9.8' 2 days ago
Alex Baker f27332595d Set root project name for project accessors 3 days ago
Alex Baker ea7f051d85 Revert "Restore @Transaction annotations"
This reverts commit b35090cd43.
3 days ago
Alex Baker 8be7fab033 Update version and changelog 3 days ago
Alex Baker d6e0c0bdcf Fix showing completed tasks in subtask filter 3 days ago
Alex Baker 5ec02011f8 Fix backup import crashes 3 days ago
Alex Baker b35090cd43 Restore @Transaction annotations 3 days ago
renovate[bot] 92f62450ae fix(deps): update accompanist to v0.34.0 3 days ago
renovate[bot] 3ca6912492 fix(deps): update dependency androidx.appcompat:appcompat to v1.7.0 3 days ago
renovate[bot] 080b1428dd fix(deps): update room to v2.7.0-alpha03 3 days ago
Alex Baker f67c3bc56c Enable typesafe project accessors 3 days ago
renovate[bot] 5d0e88a620 fix(deps): update dependency com.google.android.gms:play-services-location to v21.3.0 3 days ago
renovate[bot] c5d5795fe2 fix(deps): update lifecycle to v2.8.1 3 days ago
renovate[bot] 3bbc0e0ab0 fix(deps): update dependency androidx.sqlite:sqlite-bundled to v2.5.0-alpha03 3 days ago
Alex Baker 009a195580 Update plugin definitions 3 days ago
renovate[bot] 772f69d8c0 fix(deps): update dependency com.google.apis:google-api-services-drive to v3-rev20240521-2.0.0 4 days ago
renovate[bot] 4229bf7067 fix(deps): update dependency com.google.apis:google-api-services-tasks to v1-rev20240526-2.0.0 4 days ago
Alex Baker 212a4b0a3d Delete transaction check
This was using platform sqlite
4 days ago
Alex Baker 4ddfe937b0 Finish converting data module to kmp 5 days ago
Alex Baker 19de0e08a5 Migrate to bundled sqlite 5 days ago
Alex Baker 60211355e0 Remove Geofence constructors 6 days ago
Alex Baker 17d218aa4e Add CommonParcelize 6 days ago
Alex Baker 505c8c29d5 Make sure dao methods are suspending 6 days ago
Alex Baker 7149308c97 Move Android platform stuff out of data 6 days ago
Alex Baker 2c5a497007 Fix backup import crash 1 week ago
Alex Baker 09f53fe1e5 Ignore multiplatform agp warnings 1 week ago
Alex Baker 5da4183aed Move ksp to gradle catalog 1 week ago
Alex Baker d35912e503 Kotlin 2.0 1 week ago
renovate[bot] 82fd99f83e fix(deps): update lifecycle to v2.8.0 1 week ago
renovate[bot] f944becea1 fix(deps): update dependency com.google.apis:google-api-services-drive to v3-rev20240509-2.0.0 1 week ago
Alex Baker acd713dc5b AGP 8.4.1 1 week ago
Alex Baker 1a93c87ad9 Update version and changelog 1 week ago
Alex Baker c4e25b8b15 Fix tests 1 week ago
Alex Baker e11c0d2528 Add default reminders when adding due/start date 1 week ago
Alex Baker 2fc6833854 Don't crash on missing vtodo value 1 week ago
Alex Baker 4a2fb13d10 Converting data module to kmp - WIP 2 weeks ago
Alex Baker a2572e2dee Remove CaldavCalendarMaker 2 weeks ago
Alex Baker 64e05c9f8f Convert Tag to data class 2 weeks ago
Alex Baker ad833b5f49 Convert TagData to data class 2 weeks ago
Alex Baker eea944cc7b Update version and changelog 2 weeks ago
Alex Baker c82dfc7d39 Fix test? 2 weeks ago
Alex Baker 8607f9556a Fix test 2 weeks ago
Alex Baker f338e84d46 Fix warnings in Migrations 2 weeks ago
Alex Baker 9ee739627e Remove AlarmEntry 2 weeks ago
Alex Baker a49c233584 Make notification immutable 2 weeks ago
Alex Baker 74fca07c1b Make alarm immutable 2 weeks ago
Alex Baker 5bd0cef42e Remove extra alarm constructor 2 weeks ago
Alex Baker 4c245edbb4 Fix snooze causing duplicate notifications 2 weeks ago
Alex Baker 97a3f074d0 Update alarms after completion transaction 2 weeks ago
Alex Baker 86ecd3cf81 Synchronize alarms before saving 2 weeks ago
Alex Baker 07a2eda5ea Cancel notifications in TaskCompleter 2 weeks ago
renovate[bot] 09ffbdd036 fix(deps): update dependency com.google.firebase:firebase-crashlytics-gradle to v3 2 weeks ago
renovate[bot] 60f22146ca fix(deps): update dependency androidx.fragment:fragment-ktx to v1.7.1 2 weeks ago
renovate[bot] c11225abaf fix(deps): update kotlin 2 weeks ago
dependabot[bot] 133ea493e3 Bump rexml from 3.2.6 to 3.2.8
Bumps [rexml](https://github.com/ruby/rexml) from 3.2.6 to 3.2.8.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/rexml/compare/v3.2.6...v3.2.8)

---
updated-dependencies:
- dependency-name: rexml
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 weeks ago
Alex Baker 0ba901be69 Remove livedata from data module 3 weeks ago
Alex Baker ebe5e5c009 Replace gson with kotlin serialization 3 weeks ago
Alex Baker d556863fda Use kotlin serialization for backups 3 weeks ago
Alex Baker 55adbc2025 Reorganized data module 3 weeks ago
Alex Baker 06c4255886 Remove androidx.core from data module 3 weeks ago
renovate[bot] 4734a99bae fix(deps): update mockito monorepo to v5.12.0 3 weeks ago
Alex Baker a6a8cac8e4 Update dependencies 3 weeks ago
Alex Baker c3fc9a57cc Replace now with currentTimeMillis 3 weeks ago
Alex Baker 6e14d07d0c Move Room to data module 3 weeks ago
Alex Baker 6118121698 Moving some code out of TimerPlugin 3 weeks ago
Alex Baker 6bf3bd4d08 Update version and changelog 3 weeks ago
Alex Baker 065be79355 Update notification work logic 3 weeks ago
Alex Baker f8f8ba3c51 Don't adjust random reminder time 3 weeks ago
Alex Baker 89465f36b3 Update version and changelog 3 weeks ago
Alex Baker 1380a34ffa Fix alarm test 3 weeks ago
Alex Baker 10af5280a3 Fix random reminders 3 weeks ago
Alex Baker 8c0f7b952d ForegroundInfo for expedited work on Android 11- 3 weeks ago
Alex Baker 65362b203f Update version and changelog 3 weeks ago
Alex Baker 3327f97a17 Revert change to not delete evicted notifications 3 weeks ago
Alex Baker c9fc02a42e Enable room kotlin codegen 4 weeks ago
renovate[bot] 93670bb9e4 fix(deps): update dependency com.google.firebase:firebase-bom to v33 4 weeks ago
Alex Baker 1fc6a50d0b Update version and changelog 4 weeks ago
Alex Baker e1ef924909 Revert "Load initial data in task edit view model"
This reverts commit b2efb42d55.
4 weeks ago
Alex Baker 686cb5d346 Add empty filter 4 weeks ago
renovate[bot] ebec25c4cb fix(deps): update dependency com.google.android.material:material to v1.12.0 4 weeks ago
renovate[bot] c140f7e673
fix(deps): update dependency com.squareup.leakcanary:leakcanary-android to v2.14 4 weeks ago
renovate[bot] efbcf11a4a fix(deps): update dependency com.google.apis:google-api-services-drive to v3-rev20240327-2.0.0 4 weeks ago
renovate[bot] 6adee85a37 fix(deps): update dependency com.google.apis:google-api-services-tasks to v1-rev20240423-2.0.0 4 weeks ago
Alex Baker 5c8643110b Update back press and intent handling 4 weeks ago
Alex Baker abd13aeb75 Exclude META-INF/INDEX.LIST 4 weeks ago
Alex Baker c210fe1893 Fix finishing recurrence 4 weeks ago
Alex Baker 26aa916c20 Fix widget crash 4 weeks ago
renovate[bot] 1eff2d1cd5 fix(deps): update dependency androidx.fragment:fragment-ktx to v1.7.0 4 weeks ago
islam2hamy c90e683ea3
Translated using Weblate (Arabic)
Currently translated at 94.1% (626 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ar/
4 weeks ago
Alex Baker 3cd0295b71 Refactor notification scheduling
* Remove foreground service
* Use expedited work to trigger notifications
* Remove miscellaneous notification channel
4 weeks ago
Alex Baker 95c351e9fd Remove midnight refresh worker 4 weeks ago
renovate[bot] 4ddb7816f1 fix(deps): update dependency androidx.compose:compose-bom to v2024.05.00 4 weeks ago
renovate[bot] 91c30f7bbf chore(deps): update dependency gradle to v8.7 1 month ago
renovate[bot] 3f4398b6e0 chore(deps): update dependency fastlane to v2.220.0 1 month ago
renovate[bot] c822e989a3 fix(deps): update dependency androidx.compose.compiler:compiler to v1.5.13 1 month ago
renovate[bot] da146723e5 chore(deps): update dependency ruby to v3.3.1 1 month ago
109247019824 931626c84a Translated using Weblate (Bulgarian)
Currently translated at 100.0% (665 of 665 strings)

Co-authored-by: 109247019824 <stoyan@gmx.com>
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
Translation: Tasks.org/Android
1 month ago
Alex Baker c534632c52 Pass uuid to TaskAdapter.onCompletedTask 1 month ago
Alex Baker c1347a7455 Update version and changelog 1 month ago
renovate[bot] 9544909a58 Update dependency androidx.activity:activity-compose to v1.9.0 1 month ago
Yurt Page 5c10dce2b9 fastlane: i18n ru
Signed-off-by: Yurt Page <yurtpage@gmail.com>
1 month ago
Alex Baker 584d4a5cbb Move after update work inside transaction 1 month ago
Alex Baker 7c68a7fa59 AGP 8.4.0 1 month ago
purushottamyadavbattula 215cc838ef Sending local broadcast refresh event for refreshing nav drawer menu to communicate about update events 1 month ago
Alex Baker d60472d1bc Remove RefreshScheduler 1 month ago
Alex Baker f84a37a60a Revert "Replace refresh work with coroutines"
Widgets 😢
1 month ago
Alex Baker 7fb85b6da1 Replace refresh work with coroutines 1 month ago
Alex Baker dc90e583e4 Fix hiding empty items in drawer 1 month ago
Don Zouras 0eac5f61eb Translated using Weblate (Esperanto)
Currently translated at 100.0% (665 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 month ago
Milo Ivir c686ce883d Translated using Weblate (Croatian)
Currently translated at 100.0% (665 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
1 month ago
大王叫我来巡山 ab25398cd0 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (665 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
1 month ago
renovate[bot] 3b1c133d22 Update kotlin 1 month ago
renovate[bot] 3bfd0ab4f8 Update dependency com.google.firebase:firebase-bom to v32.8.1 1 month ago
Liz de Sartiges ffc0113d7f Initial support for z flip 5 cover screen
see : https://developer.samsung.com/galaxy-z/flex_window.html
1 month ago
Don Zouras 9de9718ad5 Translated using Weblate (Esperanto)
Currently translated at 100.0% (665 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 month ago
Oğuz Ersen a7d2c9c406 Translated using Weblate (Turkish)
Currently translated at 100.0% (665 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
1 month ago
gallegonovato b3006b9ac2 Translated using Weblate (Spanish)
Currently translated at 100.0% (665 of 665 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
1 month ago
Don Zouras de3ef1f9c9 Translated using Weblate (Esperanto)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 month ago
Alex Baker ce9e722a3f Delete more unused tag picker code 1 month ago
Alex Baker 4b892a0eb1 Rename to TagPickerActivity
Delete some more unused code
1 month ago
Hady e6e275834a
Tag picker compose (#2849)
TagPickerActivity refactoring to Compose

1. state of the SearchBar moved to the viewModel
2. viewModel used as parameter to @Composables instead of number of separate ones
3. Import of TagPickerActivity is replaced by TagPickerActivityCompose through the project
1 month ago
Alex Baker 782f4d6d7c Fix swipe to snooze time 1 month ago
elmuffo a1da71d3e1
Swipe to snooze (#2839) 1 month ago
Alex Baker c793a300cc Add preference summary 1 month ago
Ilya Bizyaev bf84bf9e82 [Feature] Add an option to allow adding tasks without unlock
I often find myself picking up the phone just to write down a task, so
I've added a notification drawer quick setting to speed things up.
However, when I use this button from the lock screen, I have to unlock
my device first, which is annoying. I would like to be able to add (not
view) tasks without the need to unlock my phone.

This PR adds such an optional feature for devices running Android 8.1+.
Note that I am not an Android developer, so the implementation is
probably not perfect. However, from my testing on an emulator, this
code seems to do just what I want.
1 month ago
SC 363b29babb
Translated using Weblate (Portuguese)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 months ago
min7-i c1ff953f5c Translated using Weblate (German)
Currently translated at 99.3% (651 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 months ago
Alex Baker 63482e5db9 AGP 8.3.2 2 months ago
Emin Tufan Çetin 2f7dc0c7f1
Translated using Weblate (Turkish)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 months ago
Lionel HANNEQUIN d672507fae
Translated using Weblate (French)
Currently translated at 99.8% (654 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 months ago
Jonatan Nyberg ce2a3c8a3f
Translated using Weblate (Swedish)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
2 months ago
sorifukobexomajepasiricupuva33 9cd114d68b
Translated using Weblate (German)
Currently translated at 99.2% (650 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 months ago
Patrick V. Leguizamon 0e663f0e08
Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
2 months ago
Mayhm 1d1efd008d
Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
2 months ago
Alex Baker 26ab3d5866 Exclude past snooze times from Snooze Filter
This should exclude tasks that were completed before their snooze time
lapsed
2 months ago
Mayhm 9a4fcbbd39
Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
2 months ago
Alex Baker 72bfda9224 Fix subtasks row for new tasks 2 months ago
Alex Baker 1067de4183 Emit SectionedDataSource from TaskListViewModel 2 months ago
Alex Baker d686b8c7e0 Add TasksMenu composable 2 months ago
Alex Baker b2efb42d55 Load initial data in task edit view model 2 months ago
Fabio Parri 3448808c94 Translated using Weblate (Portuguese)
Currently translated at 99.3% (651 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 months ago
Alex Baker 06a9626052 Update version and changelog 2 months ago
Alex Baker e92ab7f7e1 Update to latest ModalBottomSheet 2 months ago
Alex Baker 4ff7b18c0f Fix cloning google tasks 2 months ago
Alex Baker 91887f6b17 Fix backup import dropping some tasks 2 months ago
Alex Baker cf30b56098 Update version and changelog 2 months ago
Alex Baker 9bcadaab5a Fix astrid manual ordering crash in widget 2 months ago
Alex Baker be766074b0 Fix activity crash 2 months ago
Ihor Hordiichuk 64a42a3f61 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 months ago
Mayhm 7b65ba6f06 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.6% (646 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
2 months ago
109247019824 ac2b270e9e Translated using Weblate (Bulgarian)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 months ago
Alex Baker db2ea0a039 Fix import crash on missing remoteId 2 months ago
renovate[bot] 08b78fe9f4 Update dependency androidx.compose:compose-bom to v2024.03.00 2 months ago
Alex Baker 1a1301ae3e Update version and changelog 2 months ago
Milo Ivir d00061aa7f Translated using Weblate (Croatian)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 months ago
大王叫我来巡山 45add6ab32 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 months ago
Pierfrancesco Passerini af43737c4e Translated using Weblate (Italian)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 months ago
macpac59 dd40e59b17 Translated using Weblate (German)
Currently translated at 98.9% (648 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 months ago
gallegonovato 13f3248a01 Translated using Weblate (Spanish)
Currently translated at 100.0% (655 of 655 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 months ago
renovate[bot] f6972e3e30 Update dependency com.android.tools.build:gradle to v8.3.1 2 months ago
Alex Baker 83cf48a836 Don't pass filter to remoteviews service
This was working on emulators but crashing in the wild
2 months ago
Alex Baker b7b4747a04 Update translation credits
Was in a rush to get a bug fix out!
2 months ago
Alex Baker 6bec2ceef0 Update version and changelog 2 months ago
Milo Ivir d1e60d6512 Translated using Weblate (Croatian)
Currently translated at 100.0% (654 of 654 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 months ago
bittin1ddc447d824349b2 2b85089d3a Translated using Weblate (Swedish)
Currently translated at 100.0% (654 of 654 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
2 months ago
ferranpujolcamins 2a0ef9feb6 Translated using Weblate (Catalan)
Currently translated at 34.7% (227 of 654 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
2 months ago
109247019824 33adbbd884 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (654 of 654 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 months ago
Alex Baker c25eb2e0c5 Fix crash on earlier Android versions 2 months ago
Alex Baker 14026356eb Fix widget arrow color 3 months ago
Alex Baker b328651dd4
Run tests on generic flavor (#2808) 3 months ago
Alex Baker a0e9bfabeb Update version and changelog 3 months ago
大王叫我来巡山 a1ad421b33 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
3 months ago
Mayhm 3488a08af1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.4% (648 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
3 months ago
gallegonovato b71d1af516 Translated using Weblate (Spanish)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
3 months ago
Alex Baker 041dce8617 Add dynamic widget theme 3 months ago
Alex Baker 3d92ca78dd Remove unused attrs 3 months ago
Alex Baker a32fce2d8b Remove widget_title_* layouts 3 months ago
Alex Baker 4fb3cda173 Fix loading selected filter on startup 3 months ago
Alex Baker f33cc896dd Refactor widget 3 months ago
Alex Baker 4d1d6a06a8 Fix repeat until crash 3 months ago
Alex Baker 2202516688 Update isOverdue logic 3 months ago
Alex Baker d4a5008ecb Update CI 3 months ago
Alex Baker 08189e10f1 Don't use gradle managed devices in CI 3 months ago
Anonymous d3e4c066d8 Translated using Weblate (Sinhala)
Currently translated at 92.0% (606 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/si/
3 months ago
Anonymous bbc5ae4d6d Translated using Weblate (Tamil)
Currently translated at 68.2% (449 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ta/
3 months ago
Anonymous c6cc00cf07 Translated using Weblate (Thai)
Currently translated at 89.5% (589 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/th/
3 months ago
Anonymous 22e8720021 Translated using Weblate (Hebrew)
Currently translated at 89.5% (589 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/he/
3 months ago
Anonymous a3ce98f0ea Translated using Weblate (Danish)
Currently translated at 95.8% (631 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/da/
3 months ago
macpac59 258f607d52 Translated using Weblate (German)
Currently translated at 99.6% (656 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
3 months ago
ngocanhtve 927acae7e4 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/vi/
3 months ago
Odweta 49ad9bafe3 Translated using Weblate (Czech)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/cs/
3 months ago
Alex Baker 6df616d9ce Use gradle managed devices 3 months ago
Alex Baker 157668e35a Fix tests 3 months ago
Aslam Karachiwala efdf343869 For English (en), replaced "until" with "ends on" in 'repeats_*' keys. 3 months ago
renovate[bot] 5606df17c5 Update flipper to v0.250.0 3 months ago
renovate[bot] fc3b4971f4 Update flipper to v0.249.0 3 months ago
renovate[bot] 6a1699bb33 Update dependency androidx.compose:compose-bom to v2024.02.02 3 months ago
renovate[bot] e49303d5ca Update dependency com.google.firebase:firebase-bom to v32.7.4 3 months ago
renovate[bot] 4b55569b51 Update mockito monorepo to v5.11.0 3 months ago
renovate[bot] 2d7145cde3 Update plugin com.google.devtools.ksp to v1.9.22-1.0.18 3 months ago
renovate[bot] f2ab8bed95 Update dependency com.google.firebase:firebase-bom to v32.7.3 3 months ago
renovate[bot] a5bc4cf536 Update dependency com.android.tools.build:gradle to v8.3.0 3 months ago
renovate[bot] 1b35372b3a Update dependency com.google.apis:google-api-services-tasks to v1-rev20240225-2.0.0 3 months ago
Alex Baker c0fd4bf66a Convert LocalBroadcastManager to Kotlin 3 months ago
renovate[bot] 5d366f0d61 Update dependency io.coil-kt:coil-gif to v2.6.0 3 months ago
renovate[bot] d0635ac6f3 Update hilt to v1.2.0 3 months ago
renovate[bot] 8d4cf4daa5 Update dependency androidx.compose.compiler:compiler to v1.5.10 3 months ago
renovate[bot] d1e439e70e Update dependency androidx.compose:compose-bom to v2024.02.01 3 months ago
renovate[bot] 4d4c3e5193 Update dependency org.jetbrains.kotlinx:kotlinx-coroutines-test to v1.8.0 4 months ago
Alex Baker 20f87061fd Convert WidgetPreferences to Kotlin 4 months ago
renovate[bot] c03e3747c6 Update dependency com.google.gms:google-services to v4.4.1 4 months ago
renovate[bot] 925b1b9124 Update dependency com.google.firebase:firebase-bom to v32.7.2 4 months ago
Alex Baker 43db712f64 Update version and changelog 4 months ago
Alex Baker 9d33a73ee6 Fix drawer highlighting 4 months ago
renovate[bot] 391c600ce2 Update flipper to v0.247.0 4 months ago
renovate[bot] ee4ae94817 Update dependency androidx.compose:compose-bom to v2024.02.00 4 months ago
renovate[bot] 70b4be1447
Update dependency androidx.compose.compiler:compiler to v1.5.9 4 months ago
Don Zouras bc54d92789 Translated using Weblate (Esperanto)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
Сергій 2f34724b95 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
4 months ago
Alex Baker 940fdc28dd Strip markdown from repeat snackbar 4 months ago
Alex Baker 68542fce38 Fix repeat task toast displaying old due date 4 months ago
renovate[bot] 7ba2977100 Update dependency gradle to v8.6 4 months ago
Don Zouras cb242539f0 Translated using Weblate (Esperanto)
Currently translated at 98.4% (648 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
bittin1ddc447d824349b2 304841f2c3 Translated using Weblate (Swedish)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
4 months ago
Don Zouras 819ea797e6 Translated using Weblate (Esperanto)
Currently translated at 98.4% (648 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
abc0922001 2dbea57262 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hant/
4 months ago
Don Zouras 516a916fd5 Translated using Weblate (Esperanto)
Currently translated at 96.9% (638 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
109247019824 3bd52efc80 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
4 months ago
renovate[bot] 64af955ea7 Update flipper to v0.246.0 4 months ago
Milo Ivir 4cc5ec9639 Translated using Weblate (Croatian)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
4 months ago
大王叫我来巡山 0d9292e53a Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
4 months ago
Oğuz Ersen 732ccf1913 Translated using Weblate (Turkish)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
4 months ago
gallegonovato a2852bdbbf Translated using Weblate (Spanish)
Currently translated at 100.0% (658 of 658 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
4 months ago
Don Zouras 68790ad401 Translated using Weblate (Esperanto)
Currently translated at 91.7% (603 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
Alex Baker e9afacb595 Include hidden subtasks when clearing completed 4 months ago
Alex Baker cf182aceab Display number of tasks to be cleared 4 months ago
Alex Baker db889d233a Remove AfterSaveWork 4 months ago
Alex Baker 457b89c092 Remove cleanup work 4 months ago
Don Zouras ad53af1b6a Translated using Weblate (Esperanto)
Currently translated at 87.0% (572 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
renovate[bot] 2c32b08c97 Update dependency androidx.compose:compose-bom to v2024 4 months ago
renovate[bot] a2fcf57c9e Update mockito monorepo to v5.10.0 4 months ago
renovate[bot] 59a61325f2 Update dependency org.osmdroid:osmdroid-android to v6.1.18 4 months ago
vulewuxe86 38a6064677 Reverted code
Reverted Code involving the action bar search function
4 months ago
renovate[bot] 67daccf3e8 Update lifecycle to v2.7.0 4 months ago
renovate[bot] dfe829d2a1 Update dependency com.google.android.gms:play-services-location to v21.1.0 4 months ago
renovate[bot] 23c64f4d28 Update dependency com.google.apis:google-api-services-drive to v3-rev20240123-2.0.0 4 months ago
renovate[bot] e4b8f694f3 Update dependency com.google.firebase:firebase-bom to v32.7.1 4 months ago
renovate[bot] e667c80731 Update kotlin 4 months ago
renovate[bot] 909b077e25 Update dependency com.android.tools.build:gradle to v8.2.2 4 months ago
Don Zouras e6fab9ad45 Translated using Weblate (Esperanto)
Currently translated at 82.1% (540 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
raulmagdalena 9474f5b7af Translated using Weblate (Catalan)
Currently translated at 34.5% (227 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
4 months ago
Don Zouras 1ee051d768 Translated using Weblate (Esperanto)
Currently translated at 75.1% (494 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
Don Zouras f42edaa158 Translated using Weblate (Esperanto)
Currently translated at 73.8% (485 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
4 months ago
RayBB b97eade59c fix typos 4 months ago
renovate[bot] 41aa1ca65f Update flipper to v0.245.0 4 months ago
renovate[bot] 3e9a13ea14 Update mockito monorepo to v5.9.0 5 months ago
renovate[bot] d966e8a12b Update dependency fastlane to v2.219.0 5 months ago
renovate[bot] 8ba4e64994 Update dependency com.android.tools.build:gradle to v8.2.1 5 months ago
109247019824 ee792f1ceb Translated using Weblate (Bulgarian)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
5 months ago
renovate[bot] caa09163a1 Update dependency ruby to v3.3.0 5 months ago
renovate[bot] d270abf5b3 Update dependency com.facebook.soloader:soloader to v0.11.0 5 months ago
renovate[bot] 1ef530abad Update dependency com.squareup.leakcanary:leakcanary-android to v2.13 5 months ago
renovate[bot] df26a6dbb9 Update flipper to v0.244.0 5 months ago
renovate[bot] 1882c3b7e0 Update dependency androidx.activity:activity-compose to v1.8.2 5 months ago
renovate[bot] cb53a0ca9f Update dependency com.google.android.material:material to v1.11.0 5 months ago
renovate[bot] b2fdef1ae7 Update dagger.hilt to v2.50 5 months ago
renovate[bot] defb16ce95 Update kotlin 5 months ago
renovate[bot] 823f99b28a Update flipper to v0.243.0 6 months ago
renovate[bot] 6df872b1a1 Update actions/upload-artifact action to v4 6 months ago
renovate[bot] 133b960583 Update flipper to v0.242.0 6 months ago
renovate[bot] 2e6753faec Update dependency com.google.apis:google-api-services-drive to v3-rev20231128-2.0.0 6 months ago
renovate[bot] cb07c2c267 Update dependency com.google.firebase:firebase-bom to v32.7.0 6 months ago
renovate[bot] 23757ab320 Update kotlin 6 months ago
Alex Baker 1b6ce0e48e Ignore empty rrule 6 months ago
Kakaeo 5af012068f Translated using Weblate (Persian)
Currently translated at 29.9% (197 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fa/
6 months ago
Alex Baker 6c9ffa57d7 Fix reparenting task to another list 6 months ago
Alex Baker 52c54b1eac Fix excessive querying (again) 6 months ago
Alex Baker c8d81b44b6 Fix excessive querying 6 months ago
renovate[bot] ef27a50e42 Update mockito monorepo to v5.8.0 6 months ago
Alex Baker bde1356e7f Add task to MainActivityViewModel state 6 months ago
Alex Baker 6c031925ba Replace some setter usage with constructors 6 months ago
Alex Baker 8058414137 Use release build for compose metrics 6 months ago
Alex Baker 3e37ea50f0 Update compose-compiler to v1.5.5 6 months ago
renovate[bot] 62f5a9c492 Update actions/setup-java action to v4 6 months ago
renovate[bot] a84fd65722 Update dependency androidx.room:room-ktx to v2.6.1 6 months ago
renovate[bot] 517b2d8f1b Update dependency gradle to v8.5 6 months ago
renovate[bot] 90942bf0be Update dependency com.google.dagger:hilt-android to v2.49 6 months ago
Alex Baker 83c3d1c4ba AGP 8.2.0 6 months ago
Software In Interlingua 6362ece569 Translated using Weblate (Interlingua)
Currently translated at 5.6% (37 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ia/
6 months ago
renovate[bot] 8df85041b8 Update flipper to v0.240.0 6 months ago
ngocanhtve 6d85af4c34 Translated using Weblate (Vietnamese)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/vi/
6 months ago
Olli 63f001dd72 Translated using Weblate (Finnish)
Currently translated at 99.0% (651 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fi/
6 months ago
renovate[bot] de49a50944 Update dependency fastlane to v2.217.0 6 months ago
renovate[bot] df20d2f593 Update dependency com.android.billingclient:billing-ktx to v6.1.0 6 months ago
renovate[bot] fd16772236 Update dependency androidx.activity:activity-compose to v1.8.1 6 months ago
renovate[bot] b77caac255 Update dependency com.google.firebase:firebase-bom to v32.6.0 6 months ago
renovate[bot] ad058ed09b Update kotlin 6 months ago
Alex Baker 8312113d7b Merge branch '13.6.3' 6 months ago
Alex Baker ee21cc660e Update version and changelog 6 months ago
Alex Baker 5edc481ffe Fix etag check for DecSync 6 months ago
Alex Baker d0360a4862 Revert "Update timestamp on edits"
This reverts commit b477623524.
6 months ago
Alex Baker ac35002408 Revert "Update modification timestamp logic (#2585)"
This reverts commit 775289b058.
6 months ago
Subham Jena 582ebad0f0 Translated using Weblate (Odia)
Currently translated at 20.7% (136 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/or/
6 months ago
Shaban Mamedov 684c47184a Added translation using Weblate (Azerbaijani) 6 months ago
ngocanhtve ac7a519e4e Translated using Weblate (Vietnamese)
Currently translated at 99.6% (655 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/vi/
6 months ago
renovate[bot] 5c2b41af9d Update flipper to v0.238.0 7 months ago
renovate[bot] 13986cf380 Update flipper to v0.237.0 7 months ago
CennoxX c4f0b404e9 Translated using Weblate (German)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
7 months ago
Alex Baker 145b5afbc6 AGP 8.2.0-rc03 7 months ago
elig0n 0b87a206fe Translated using Weblate (Hebrew)
Currently translated at 90.2% (593 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/he/
7 months ago
mm4c d0e70ceea8 Translated using Weblate (Dutch)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
7 months ago
J. Lavoie bf3546a878 Translated using Weblate (French)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
7 months ago
Alex Baker 8895acbf6b Prevent flashing empty inbox when switching lists 7 months ago
Alex Baker a52b1200f5 Fix menu expansion 7 months ago
renovate[bot] 23964e807a
Update flipper to v0.236.0 (#2617)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 months ago
Alex Baker 287b106dd4 Highlight selected list in drawer 7 months ago
renovate[bot] 33bab626e0
Update mockito monorepo to v5.7.0 (#2613)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 months ago
renovate[bot] a980cd75cc Update hilt to v1.1.0 7 months ago
renovate[bot] 7eac4ac223 Update dependency androidx.fragment:fragment-ktx to v1.6.2 7 months ago
renovate[bot] 82cb2f7d3f
Update dependency com.android.tools:desugar_jdk_libs to v2.0.4 7 months ago
renovate[bot] da2646597c
Update flipper to v0.235.0 (#2608)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 months ago
renovate[bot] 495855133c Update dependency com.google.firebase:firebase-bom to v32.5.0 7 months ago
renovate[bot] 242cb61662 Update coil to v2.5.0 7 months ago
renovate[bot] ab8886f3dc Update flipper to v0.234.0 7 months ago
Alex Baker e48e92d2e6 Fix dates 🤦 7 months ago
Alex Baker 5f22f5cd38 AGP 8.2.0-rc02 7 months ago
Alex Baker 8a47cc2934 Don't set local only notifications on Android 14+ 7 months ago
Alex Baker 0d94729d37 Merge branch '13.6.2' 7 months ago
Alex Baker 14599eb3c0 Update version and changelog 7 months ago
Alex Baker b477623524 Update timestamp on edits
Fix bugs introduced by 775289b05
7 months ago
Alex Baker c8bfb67b50 Allow multi-select for gallery picker 7 months ago
Alex Baker 0a36e58525 Allow multi-select in storage picker 7 months ago
Alex Baker 94a719cb66 Improve menu dismissal
Copy M3 ModalBottomSheet to add 'skipPartiallyCollapsed' support 😕
7 months ago
Alex Baker b5748aa8e6 New drawer 7 months ago
Alex Baker 7fd5647cb8 Exclude hidden and completed from snoozed filter 7 months ago
Alex Baker 2545832d67 Update version and changelog 7 months ago
Alex Baker 738bf435db Fix some back handlers 7 months ago
renovate[bot] ab02323f29
Update flipper to v0.233.0 (#2599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 months ago
Alex Baker d73a9d2795 Update version and changelog 7 months ago
Alex Baker ebe67354b6 Add tests for recurrence without intervals 7 months ago
Alex Baker 58edc6b4d8 Fix basic hourly and weekly recurrence 7 months ago
Weblate (bot) 78b2cdac06
Translations update from Hosted Weblate (#2596)
* Translated using Weblate (French)

Currently translated at 99.5% (654 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/

* Translated using Weblate (French)

Currently translated at 99.5% (654 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/

---------

Co-authored-by: Bruno Duyé <brunetton@gmail.com>
Co-authored-by: Lionel HANNEQUIN <Lionel-HANNEQUIN@users.noreply.hosted.weblate.org>
7 months ago
renovate[bot] c3d7db0087
Update flipper to v0.232.0 (#2597)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 months ago
renovate[bot] d7b1770b85
Update flipper to v0.231.0 (#2591)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 months ago
Weblate (bot) bebb3165a5
Translations update from Hosted Weblate (#2589)
Translated using Weblate (French)

Currently translated at 99.5% (654 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/

Co-authored-by: Lionel HANNEQUIN <Lionel-Fr-56@users.noreply.hosted.weblate.org>
7 months ago
Alex Baker ad1198aace Don't require network for OpenTasks sync 7 months ago
Alex Baker 7ae77a81e1 Don't need background sync for OpenTasks
Background sync handled by sync apps
7 months ago
Weblate (bot) 3e79dd5190
Translations update from Hosted Weblate (#2587)
Translated using Weblate (French)

Currently translated at 99.6% (655 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/

Co-authored-by: Lionel HANNEQUIN <Lionel-Fr-56@users.noreply.hosted.weblate.org>
7 months ago
renovate[bot] 9d57a849bf
Update flipper to v0.230.0 (#2586)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
8 months ago
Alex Baker 82103eb477 Make chips skippable 8 months ago
renovate[bot] 11fa9a2bbd Update dependency com.google.firebase:firebase-bom to v32.4.0 8 months ago
renovate[bot] b65831120f Update room to v2.6.0 8 months ago
renovate[bot] f26a90a4f9 Update hilt to v1.1.0-rc01 8 months ago
renovate[bot] dd3aa20485 Update dependency androidx.recyclerview:recyclerview to v1.3.2 8 months ago
renovate[bot] 8c84e1af50 Update dependency com.google.android.gms:play-services-maps to v18.2.0 8 months ago
renovate[bot] dc1eac23b9 Update dependency androidx.compose:compose-bom to v2023.10.01 8 months ago
renovate[bot] 5883952883
Update flipper to v0.229.0 (#2579)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
8 months ago
Alex Baker 775289b058
Update modification timestamp logic (#2585) 8 months ago
Alex Baker ee500c24b1
Convert filters to data classes (#2569) 8 months ago
Igor Sorocean 68fd36b14d Translated using Weblate (Romanian)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ro/
8 months ago
renovate[bot] b8f265fa36 Update okhttp to v4.12.0 8 months ago
Alex Baker cf4e6c1273 Update AGP to 8.2.0-rc01 8 months ago
renovate[bot] 0dcc577497 Update flipper to v0.227.0 8 months ago
kmj-99 b525e8cab3 Refactor: Change deprecated code in Fragment onAttach 8 months ago
renovate[bot] db0ad280eb Update dependency com.google.auth:google-auth-library-oauth2-http to v1.20.0 8 months ago
Alex Baker 5092f80dcc Update billing to v6.0.1 8 months ago
Kazushi Hayama 6bc42363dd Translated using Weblate (Japanese)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
8 months ago
Michal Šmahel 115461c7b0 Translated using Weblate (Czech)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/cs/
8 months ago
renovate[bot] 369c508890 Update flipper to v0.226.0 8 months ago
bittin1ddc447d824349b2 a432cc33cc Translated using Weblate (Swedish)
Currently translated at 100.0% (657 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
8 months ago
Alex Baker e5b51150cb Start sync if enqueued when app is backgrounded 8 months ago
renovate[bot] d43639556e Update dependency com.google.android.material:material to v1.10.0 8 months ago
Alex Baker ef2dd8f202 Merge branch '13.6' 8 months ago
Alex Baker abc099c309 Update version and changelog 8 months ago
Alex Baker 348367e084 Replace INSTALL_SHORTCUT with requestPinShortcut 8 months ago
renovate[bot] 6a73f6745c Update flipper to v0.225.0 8 months ago
renovate[bot] 5185c14e44 Update mockito monorepo to v5.6.0 8 months ago
Olli aa7ff0fa16 Translated using Weblate (Finnish)
Currently translated at 99.0% (651 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fi/
8 months ago
renovate[bot] 12b979d363 Update flipper to v0.224.0 8 months ago
Alex Baker 082f741983 Convert Filter to data class 8 months ago
Alex Baker 0bdd83988f Fix lint errors 8 months ago
Alex Baker 60784c10b5 Update filter fields 8 months ago
Alex Baker da8467ac56 Remove constructor 8 months ago
renovate[bot] 434d067822 Update dependency gradle to v8.4 8 months ago
renovate[bot] 04af310285 Update hilt to v1.1.0-beta01 8 months ago
renovate[bot] 5555771f45 Update dependency com.google.dagger:hilt-android-testing to v2.48.1 8 months ago
renovate[bot] 35b60df0ff Update dependency androidx.activity:activity-compose to v1.8.0 8 months ago
renovate[bot] fef19b4995 Update dependency androidx.compose:compose-bom to v2023.10.00 8 months ago
Alex Baker 4c25b81a4d Move Parcelable 8 months ago
Alex Baker 0f37f4859e Update compose reports 8 months ago
Alex Baker ee3d3fa4f5 Convert FilterListItem to interface 8 months ago
Alex Baker a32d35720a Refresh after changing sort mode 8 months ago
Alex Baker bf6fe02fe3 Convert FilterListItems to Kotlin 8 months ago
Alex Baker 6664defc16 Minor refactoring 8 months ago
renovate[bot] b318b930a5 Update flipper to v0.223.0 8 months ago
Loucura 91d18fd675 Translated using Weblate (Portuguese)
Currently translated at 99.8% (656 of 657 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
8 months ago
Alex Baker 94b6d7569b Move search to viewmodel 8 months ago
Alex Baker e70f5f3b24 Move query constants 8 months ago
renovate[bot] 68c21c4b1f Update dependency androidx.compose:compose-bom to v2023.09.02 8 months ago
renovate[bot] cbcc7f9bee Update dependency com.android.tools.build:gradle to v8.2.0-beta06 8 months ago
Milo Ivir ba394b9db4
Translated using Weblate (Croatian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
8 months ago
Eric 13298aa3be
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
8 months ago
Alex Baker 993c41b197 Remove RecurringIntervalIntentService 8 months ago
Alex Baker 2bfc46f32b Remove CalendarReminderActivity 8 months ago
Alex Baker 4c61353411 Remove TimerControlSetCallback 8 months ago
Alex Baker f8d3985e97 Add hideKeyboard extension methods 8 months ago
Alex Baker c2a9d21f01 Make review request from edit fragment 8 months ago
Alex Baker 20c81417a0 Handle sort result in task list fragment 8 months ago
Alex Baker 77c86bbfb4 Move sync state to viewmodel 8 months ago
renovate[bot] 7e9ec26f53 Update flipper to v0.222.0 8 months ago
Alex Baker 928ec9f647 Add night mode context extensions 8 months ago
Alex Baker 84ab8d0517 Remove MainActivity.onBackPressed 8 months ago
Alex Baker db66a66578 Move subscription begging to viewmodel 8 months ago
Alex Baker ea8a4b5e2d Remove InjectingAppCompatActivity 8 months ago
Alex Baker 5a4485818f Update dependency androidx.compose:compose-bom to v2023.09.01 8 months ago
renovate[bot] 1d348fcac9 Update room to v2.6.0-rc01 8 months ago
renovate[bot] 79250cb8ff Update dependency com.android.tools.build:gradle to v8.2.0-beta05 8 months ago
renovate[bot] 5d550df62e Update flipper to v0.221.0 8 months ago
Pierfrancesco Passerini 1267fbeb0d Translated using Weblate (Italian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
9 months ago
renovate[bot] 2b0e285b42 Update dependency fastlane to v2.216.0 9 months ago
Alex Baker 374f10c731 Add subtasks in order for new tasks 9 months ago
abc0922001 a38fdc065e Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hant/
9 months ago
Ihor Hordiichuk 6d4159eaac Translated using Weblate (Ukrainian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
9 months ago
Oğuz Ersen 20fe494cd9 Translated using Weblate (Turkish)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
9 months ago
Frits van Bommel e7686bd9eb Translated using Weblate (Dutch)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
9 months ago
Kaci d4d721f060 Translated using Weblate (Hungarian)
Currently translated at 99.7% (666 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hu/
9 months ago
Florian Trayon 1e9b39afd5 Translated using Weblate (French)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
9 months ago
Florian Trayon 8878df27c4 Translated using Weblate (Spanish)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
9 months ago
C. Rüdinger 07eb9db157 Translated using Weblate (German)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
9 months ago
109247019824 b4ad27152f Translated using Weblate (Bulgarian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
9 months ago
kmj-99 417a1cca46 Change deprecated code from RecyclerView.ViewHolder 9 months ago
renovate[bot] 3a6086adbd
Update flipper to v0.220.0 (#2522)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
9 months ago
Alex Baker 9f3f0a9698 Show unstarted tasks in widget by default 9 months ago
Alex Baker 8a085861de Update version and changelog 9 months ago
Alex Baker 7048f6a965 Fix crash in debug logging 9 months ago
Alex Baker a9cb7b0e89 Fix default reminders for remote icalendar tasks 9 months ago
Alex Baker 4c7e2caa73 Update OK/Cancel string
Was causing too much confusion for translators
9 months ago
Alex Baker 3a5e45283a Update change priority menu option 9 months ago
renovate[bot] a1885574da
Update dependency fastlane to v2.215.1 (#2520)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
9 months ago
vulewuxe86 113cf6f1b8
#2257 Change priority for selected items (#2452) 9 months ago
renovate[bot] 138cc21796 Update dependency com.google.firebase:firebase-bom to v32.3.1 9 months ago
Alex Baker dea3484a2f Actually update fastlane 9 months ago
Alex Baker 5948e4a958 Set googleplay as default flavor 9 months ago
renovate[bot] 10d2e8feda Update dependency com.google.gms:google-services to v4.4.0 9 months ago
renovate[bot] cef7998a52 Update dependency fastlane to v2.215.0 9 months ago
renovate[bot] 834bef7933 Update flipper to v0.219.0 9 months ago
renovate[bot] 8ed6afff2b Update flipper to v0.218.0 9 months ago
renovate[bot] 7d13e4f0ba Update dependency com.android.tools.build:gradle to v8.2.0-beta04 9 months ago
Alex Baker 5cb8419206 Fix network call on main thread 9 months ago
Alex Baker 7283491872 Update Hilt to 1.1.0-alpha01 9 months ago
Alex Baker 2de5b3c275 Use share text when subject is missing 9 months ago
Alex Baker 864550d027 Enable ksp for dagger 9 months ago
renovate[bot] b48348f30e Update dependency org.osmdroid:osmdroid-android to v6.1.17 9 months ago
renovate[bot] 81fdddc631 Update flipper to v0.216.0 9 months ago
Luna Jernberg 21cb25d902 Translated using Weblate (Swedish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
9 months ago
Anaemix b73ba43735 Translated using Weblate (Swedish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
9 months ago
renovate[bot] a3ba87e4e6 Update kotlin 9 months ago
renovate[bot] 26321633e2 Update dependency androidx.compose:compose-bom to v2023.09.00 9 months ago
renovate[bot] 1c3656a69c Update dependency com.google.firebase:firebase-bom to v32.2.3 9 months ago
renovate[bot] 88bb66a7b3 Update dependency com.google.firebase:firebase-crashlytics-gradle to v2.9.9 9 months ago
renovate[bot] 0f7c200851 Update dependency com.google.apis:google-api-services-drive to v3-rev20230822-2.0.0 9 months ago
renovate[bot] f6d5732c07 Update lifecycle to v2.6.2 9 months ago
renovate[bot] b278a04fce Update room to v2.6.0-beta01 9 months ago
renovate[bot] 71c2e2b0f6 Update dagger.hilt to v2.48 9 months ago
renovate[bot] 87639da922 Update dependency com.android.tools.build:gradle to v8.2.0-beta03 9 months ago
Anaemix d7e366712c Translated using Weblate (Swedish)
Currently translated at 98.5% (657 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
9 months ago
renovate[bot] 74ecb4a8bf Update actions/checkout action to v4 9 months ago
Emin Tufan Çetin 305bd24883 Translated using Weblate (Turkish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
9 months ago
renovate[bot] 68b7bef1ca Update flipper to v0.215.1 9 months ago
renovate[bot] f6a6b0716f Update flipper to v0.215.0 9 months ago
renovate[bot] dced669176 Update flipper to v0.214.0 9 months ago
Emin Tufan Çetin 1b431f7a61 Translated using Weblate (Turkish)
Currently translated at 98.9% (660 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
9 months ago
Joan Montané 2b3b7184e0 Translated using Weblate (Catalan)
Currently translated at 32.6% (218 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
9 months ago
renovate[bot] a7062fe937 Update flipper to v0.213.0 9 months ago
Alex Baker 573f6b897e Set audio attributes on completion sound 9 months ago
renovate[bot] e1845d71bc Update accompanist to v0.32.0 9 months ago
renovate[bot] 1027d57860 Update dependency com.google.apis:google-api-services-drive to v3-rev20230815-2.0.0 9 months ago
renovate[bot] a2c92b8fd9 Update mockito monorepo to v5.5.0 9 months ago
renovate[bot] 77643d7355 Update flipper to v0.212.0 10 months ago
Patrick V. Leguizamon 54911021a5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.6% (651 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
10 months ago
renovate[bot] 908ac19754 Update dependency gradle to v8.3 10 months ago
Alex Baker 4ebd53fdf7 Enable dagger.ignoreProvisionKeyWildcards 10 months ago
Alex Baker a0fbeba938 'More settings' opens directly to channel settings 10 months ago
Alex Baker bd6000fcd6 Add subtasks to top 10 months ago
Alex Baker aa861cb5e5 Convert room to ksp 10 months ago
Alex Baker 17818c6e29 Remove checkstyle 10 months ago
Poesty Li ca6521db23
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
10 months ago
Alex Baker dedf306106 Update kotlinx-coroutines-test to 1.7.3 10 months ago
Alex Baker 40f9b83dba Remove bundles from version catalog 10 months ago
Alex Baker c8b057867f Gradle Plugin 8.2.0-alpha16 10 months ago
Alex Baker d1ebd45492 Update to Kotlin 1.9, Compose compiler 1.5.1 10 months ago
Alex Baker ac28e26333 Update Room to 2.6.0-alpha03 10 months ago
renovate[bot] fdf9fbce08 Update flipper to v0.211.1 10 months ago
renovate[bot] 6d712642b3 Update dependency com.google.apis:google-api-services-drive to v3-rev20230714-2.0.0 10 months ago
renovate[bot] 329939e2b0 Update dependency androidx.compose:compose-bom to v2023.08.00 10 months ago
Alex Baker f62de8b7f3 Microsoft recurrence sync
Limit recurrence options for Microsoft tasks
10 months ago
deep map a2ef184c7d Translated using Weblate (German)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
10 months ago
Salif Mehmed 6ac2c88782 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
10 months ago
Naga ada31293ea Translated using Weblate (Japanese)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
10 months ago
Pierfrancesco Passerini 805d914ff4 Translated using Weblate (Italian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
10 months ago
109247019824 aa1b4ef71a Translated using Weblate (Bulgarian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
10 months ago
vulewuxe86 3d0cf46f8d
Select the new items after duplication (#2446)
#1201 Select the new items after duplication
10 months ago
abc0922001 f7e2c7824a Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hant/
10 months ago
Stefan 2e2bdbe07a Reduced minimum widget height 10 months ago
Alex Baker 427ee369b4 Fix miscellaneous inspections 10 months ago
Alex Baker 804c0f974a Force a due date for recurring tasks 10 months ago
109247019824 691dc635a9 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
10 months ago
renovate[bot] 9f2364867b Update dependency com.google.firebase:firebase-bom to v32.2.2 10 months ago
renovate[bot] cd638bba71
Update dependency com.google.firebase:firebase-crashlytics-gradle to v2.9.8 10 months ago
Naga 156669cb86 Translated using Weblate (Japanese)
Currently translated at 98.6% (658 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
10 months ago
Kazushi Hayama 6c1daf5a3c Translated using Weblate (Japanese)
Currently translated at 98.6% (658 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
10 months ago
Pierfrancesco Passerini 0a297c595f Translated using Weblate (Italian)
Currently translated at 99.2% (662 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
10 months ago
qwerty287 b698fc04db Translated using Weblate (German)
Currently translated at 98.6% (658 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
10 months ago
109247019824 ab6f3463d0 Translated using Weblate (Bulgarian)
Currently translated at 98.8% (659 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
10 months ago
Alex Baker dbcaa36812 Update version and changelog 10 months ago
Alex Baker 83a42c9d8f Fix crash on google task import 10 months ago
Alex Baker ec97722857 Track compose metrics 10 months ago
Alex Baker dd78acadcd Remove deprecated setting 10 months ago
Htet Oo Hlaing 454faa234e
Translated using Weblate (Burmese)
Currently translated at 9.7% (65 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/my/
10 months ago
bruh 55027ad625
Translated using Weblate (Vietnamese)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/vi/
10 months ago
Alex Tereschenko 13740c3d0d
Translated using Weblate (Russian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ru/
10 months ago
Alex Tereschenko 6037ee70e5
Translated using Weblate (Polish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pl/
10 months ago
Kazushi Hayama 0f2e659e6f
Translated using Weblate (Japanese)
Currently translated at 98.5% (657 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
10 months ago
Milo Ivir 7945ecb9c4
Translated using Weblate (Croatian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
10 months ago
Poesty Li 56f0be50ff
Translated using Weblate (Chinese (Simplified))
Currently translated at 99.4% (663 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
10 months ago
Ihor Hordiichuk 91d46c5f11
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
10 months ago
Htet Oo Hlaing bab3898a7f
Added translation using Weblate (Burmese) 10 months ago
Alex Baker 7b12e491ad Replace isGoogleTask with accountType 10 months ago
Alex Baker ce2bc81276 Update version and changelog 10 months ago
Frits van Bommel 39ddc8d0d6
Translated using Weblate (Dutch)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
10 months ago
Pierfrancesco Passerini 8081da3a36
Translated using Weblate (Italian)
Currently translated at 99.2% (662 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
10 months ago
Florian Trayon 766d5fa043
Translated using Weblate (French)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
10 months ago
Florian Trayon b2135f33c5
Translated using Weblate (Spanish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
10 months ago
109247019824 d1afb5891a
Translated using Weblate (Bulgarian)
Currently translated at 98.8% (659 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
10 months ago
Alex Baker dff522437d New recurrence activity 10 months ago
Alex Baker 5308404ed6 Fix some random inspections 10 months ago
renovate[bot] 320b399ab3 Update dependency androidx.recyclerview:recyclerview to v1.3.1 10 months ago
renovate[bot] 28c1ecaebc Update dependency androidx.preference:preference to v1.2.1 10 months ago
renovate[bot] 7083eb2ede Update dependency androidx.fragment:fragment-ktx to v1.6.1 10 months ago
renovate[bot] 194edd2084 Update dependency com.android.tools.build:gradle to v8.1.0 10 months ago
Michal Šmahel e21637cb3c Translated using Weblate (Czech)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/cs/
10 months ago
Alex Baker ee82f683bd Update microsoft converter
Add due dates, creation dates, and modification dates
11 months ago
Alex Baker 166635e18b Update version and changelog 11 months ago
Alex Baker 8ed5242573 Hide ascending button for 'My order' subtasks 11 months ago
Alex Baker a3d86dcb03 Exclude subtasks of hidden tasks from My Tasks 11 months ago
Alex Baker c065525cef Add subtask sort configuration 11 months ago
renovate[bot] 049f995e96 Update dependency com.google.auth:google-auth-library-oauth2-http to v1.19.0 11 months ago
renovate[bot] 8ac962d9ea Update room to v2.5.2 11 months ago
renovate[bot] 849e785189 Update dependency androidx.compose:compose-bom to v2023.06.01 11 months ago
renovate[bot] 1b1288678b Update dependency androidx.compose.material3:material3 to v1.1.1 11 months ago
renovate[bot] d2710a3c61 Update dagger.hilt to v2.47 11 months ago
renovate[bot] 0fe5b7fdb9 Update dependency fastlane to v2.214.0 11 months ago
renovate[bot] dcf645c2b8 Update dependency com.google.firebase:firebase-bom to v32.2.0 11 months ago
renovate[bot] 1fcd780b3f Update dependency com.google.firebase:firebase-crashlytics-gradle to v2.9.7 11 months ago
renovate[bot] 5fc3ac2e7f Update dependency gradle to v8.2.1 11 months ago
Luna Jernberg 3ad24f49d8
Translated using Weblate (Swedish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/sv/
11 months ago
SC 5d386bc83a
Translated using Weblate (Portuguese)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
11 months ago
Kaci c7a65c81d4
Translated using Weblate (Hungarian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hu/
11 months ago
Sunjae Choi 2034a4be74
Translated using Weblate (Korean)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ko/
11 months ago
Sameer Rustamzada ca4f120433
Added translation using Weblate (Pashto) 11 months ago
renovate[bot] 7c6aae3219 Update dependency com.squareup.leakcanary:leakcanary-android to v2.12 11 months ago
renovate[bot] 18450e8e2b Update flipper to v0.201.0 12 months ago
renovate[bot] 1181125417 Update flipper to v0.200.0 12 months ago
renovate[bot] e52c80ea3f Update dependency com.google.firebase:firebase-crashlytics-gradle to v2.9.6 12 months ago
renovate[bot] 2474dbab2a Update dependency com.google.firebase:firebase-bom to v32.1.1 12 months ago
renovate[bot] 049d46ceff Update flipper to v0.199.0 12 months ago
renovate[bot] 6f01f9a590 Update mockito monorepo to v5.4.0 12 months ago
renovate[bot] de2f39b2df Update dependency com.google.apis:google-api-services-drive to v3-rev20230610-2.0.0 12 months ago
Naga 393f7868d8 Translated using Weblate (Japanese)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
12 months ago
renovate[bot] cad6470497 Update flipper to v0.198.0 12 months ago
renovate[bot] 065385d105 Update flipper to v0.197.0 12 months ago
renovate[bot] 159fc3ad50 Update flipper to v0.195.0 12 months ago
Alex Baker f697015d7f Update sort menu design 12 months ago
Alex Baker b977f01402 Push changes after updating google task lists 12 months ago
Naga 07c7297bc8
Translated using Weblate (Japanese)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
12 months ago
Gerald Schneider 7fc81f4876
Translated using Weblate (German)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
12 months ago
Naga 3cebc6f874
Translated using Weblate (Japanese)
Currently translated at 99.1% (664 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
12 months ago
Frits van Bommel 1d997ae411
Translated using Weblate (Dutch)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
12 months ago
renovate[bot] 2e213312fe Update flipper to v0.194.0 12 months ago
renovate[bot] dc7c9aec76 Update dependency androidx.fragment:fragment-ktx to v1.6.0 12 months ago
renovate[bot] 2faff24ac9 Update dependency androidx.compose:compose-bom to v2023.06.00 12 months ago
Eudald Puy Polls 045ec4cb3f
Translated using Weblate (Catalan)
Currently translated at 34.0% (228 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
12 months ago
Milo Ivir f5a2e9282e
Translated using Weblate (Croatian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
12 months ago
Ander Romero 5ef7b6f786
Translated using Weblate (Catalan)
Currently translated at 32.3% (217 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
12 months ago
109247019824 936dfb29c9
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
12 months ago
renovate[bot] e8ac6ed556 Update dependency com.facebook.flipper:flipper to v0.193.0 1 year ago
Alex Baker a45959052b Make CaldavTask.task immutable 1 year ago
Alex Baker e1aed0f1af Make CaldavTask.id immutable 1 year ago
Alex Baker 52d664856d Convert CaldavTask to data class 1 year ago
Alex Baker 53738031d1 Change CaldavTask to val 1 year ago
Alex Baker b0bb58bb4c Convert TaskListViewModel to flow 1 year ago
Alex Baker 1811eb561f Update version and changelog 1 year ago
Alex Baker 6ef2f4a989 Change default sort ordering value 1 year ago
renovate[bot] 6b041dc47d Update dependency com.google.auth:google-auth-library-oauth2-http to v1 1 year ago
Alex Baker 2659f4fa4a Update version and changelog 1 year ago
Alex Baker 09a1e5bc4f Fix widget list chip for google task lists 1 year ago
renovate[bot] cc370557df Update flipper to v0.192.0 1 year ago
Poesty Li d7fc766b49
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
1 year ago
Ihor Hordiichuk 6734e0b281
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
1 year ago
Frits van Bommel ec75338027
Translated using Weblate (Dutch)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
1 year ago
Pierfrancesco Passerini 407adb07d2
Translated using Weblate (Italian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
1 year ago
Florian Trayon 664d8bc1f8
Translated using Weblate (French)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
1 year ago
Florian Trayon 51441e4ad0
Translated using Weblate (Spanish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
1 year ago
109247019824 4c7e88b18a
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
1 year ago
renovate[bot] e7372f3e8b Update dependency com.google.firebase:firebase-bom to v32.1.0 1 year ago
Milo Ivir c9a5d19b83 Translated using Weblate (Croatian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
1 year ago
Frits van Bommel b317a3885a Translated using Weblate (Dutch)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
1 year ago
Pierfrancesco Passerini 98dc48decd Translated using Weblate (Italian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
1 year ago
Florian Trayon 2f36ad8043 Translated using Weblate (French)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
1 year ago
Florian Trayon ed2acfbe97 Translated using Weblate (Spanish)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
1 year ago
C. Rüdinger acb95583dc Translated using Weblate (German)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
1 year ago
Alex Baker 4830aed7b4 Update version and changelog 1 year ago
Alex Baker f5ab0e6f56 Sorting updates
* Make contents scrollable
* Use fixed value for 'no date' sorting
* Completion sort defaults to descending
* Show error if 'My order' is not supported
1 year ago
Ihor Hordiichuk be55a3bc5d
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
1 year ago
Frits van Bommel 643af2e2fb
Translated using Weblate (Dutch)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
1 year ago
Kaci 24f810763f
Translated using Weblate (Hungarian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hu/
1 year ago
Florian Trayon cb792e8111
Translated using Weblate (French)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
1 year ago
Florian Trayon c451a1e272
Translated using Weblate (Spanish)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
1 year ago
109247019824 a25e93f3de
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
1 year ago
renovate[bot] 50926bc0ad Update flipper to v0.191.1 1 year ago
Alex Baker 48e73b4bb3 Sort options for completed tasks 1 year ago
renovate[bot] a4184fa63a Update dependency com.google.apis:google-api-services-drive to v3-rev20230520-2.0.0 1 year ago
Alex Baker 08ae11046a Fix tests 1 year ago
Ander Romero 74a1ee9e4f
Translated using Weblate (Catalan)
Currently translated at 32.6% (218 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
1 year ago
Alex Baker d4192803f8 Use recursive queries if filter can be sorted 1 year ago
Alex Baker 7945160536 Separate group and sort configurations 1 year ago
renovate[bot] 79e1a73c2a Update dependency com.android.tools.build:gradle to v8.0.2 1 year ago
renovate[bot] f7bc821a16 Update coil to v2.4.0 1 year ago
renovate[bot] 4ac6a5fdf6 Update dependency com.google.apis:google-api-services-drive to v3-rev20230517-2.0.0 1 year ago
renovate[bot] f623046385 Update dependency androidx.activity:activity-compose to v1.7.2 1 year ago
renovate[bot] afdabb3dc3 Update dependency fastlane to v2.213.0 1 year ago
Alex Baker 48804de63d Remove unused resources 1 year ago
qwerty287 2ad445aceb
Translated using Weblate (German)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
1 year ago
Alex Baker f1790b574f Update version and changelog 1 year ago
Alex Baker ac9e782527 Fix crash on default Google Task list migration 1 year ago
Don Zouras e0758206d8 Translated using Weblate (Esperanto)
Currently translated at 47.7% (321 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
Alex Baker 85c0ba9ccf Update bundle workflow 1 year ago
Alex Baker a0f85fcbbd Update version and changelog 1 year ago
Alex Baker 02958e46e6 Fix duplicated subtasks 1 year ago
Alex Baker fce12ae4a8 Fix sort by title 1 year ago
Alex Baker fc3dc96ade Fix widget sort by list description 1 year ago
renovate[bot] 559858d19c Update dependency com.facebook.flipper:flipper to v0.191.0 1 year ago
Ander Romero 99ffb68e7a Translated using Weblate (Catalan)
Currently translated at 32.2% (217 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ca/
1 year ago
renovate[bot] 1ce507b0bb Update dependency com.squareup.leakcanary:leakcanary-android to v2.11 1 year ago
Sunjae Choi d4feb8fd31 Translated using Weblate (Korean)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ko/
1 year ago
o20n3 16270f66c8 Translated using Weblate (Korean)
Currently translated at 99.4% (668 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ko/
1 year ago
Sunjae Choi 3f8c8feb08 Translated using Weblate (Korean)
Currently translated at 99.4% (668 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ko/
1 year ago
Oğuz Ersen 8f370fec62 Translated using Weblate (Turkish)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
1 year ago
Alex Baker f3c28fe60d
Update action badge 1 year ago
Alex Baker b06b10f930 Enable action dependency 1 year ago
Alex Baker 6efac620c4 New check and bundle actions 1 year ago
Alex Baker 41c8a803a1 Remove jtxBoard permissions 1 year ago
renovate[bot] 0ed04d7739 Update dagger-hilt to v2.46.1 1 year ago
renovate[bot] f9dbedad3b Update dependency org.jetbrains.kotlinx:kotlinx-coroutines-test to v1.7.1 1 year ago
Alex Baker 16d91aafb1 Update version and changelog 1 year ago
Alex Baker 4882570b3c Ignore invalid request when deleting google tasks 1 year ago
renovate[bot] ece1758696 Update dependency com.google.android.material:material to v1.9.0 1 year ago
renovate[bot] cfebf04b4b Update dependency androidx.compose:compose-bom to v2023.05.01 1 year ago
Alex Baker 3c87ab4fc1 Fix subtask sort order 1 year ago
Alex Baker 1562c1315c Check for remote ID before deleting Google Task 1 year ago
Alex Baker 2668e9a1df Update version and changelog 1 year ago
Alex Baker ac0fbccb54 Fix tag chips 1 year ago
Alex Baker d25f859385 Update version and changelog 1 year ago
Alex Baker 3555c11b33 Move task after saving changes 1 year ago
Alex Baker a7662d9cb6 Don't show list chips for google task lists 1 year ago
Alex Baker 2da4dcd17a Use drawer ordering for 'By list' sort mode 1 year ago
Alex Baker 1d58292a07 Separate cookie jars by username 1 year ago
renovate[bot] df2a7f8857 Update dependency com.google.firebase:firebase-bom to v32 1 year ago
renovate[bot] 56c6f2ce33 Update dependency com.android.tools.build:gradle to v8.0.1 1 year ago
renovate[bot] 019dc6ecaa Update kotlin 1 year ago
renovate[bot] e6ac0b072e Update dependency androidx.compose:compose-bom to v2023.05.00 1 year ago
Alex Baker 86d4bcbc40 Update version and changelog 1 year ago
Alex Baker e05874d36a Revert "Accompanist appcompat theme adapter"
This reverts commit db82ef7fd6.

accompanist theme adapter doesn't support translucent backgrounds like
the wallpaper theme
1 year ago
Alex Baker 7d83e8ba06 Update version and changelog 1 year ago
Alex Baker 99243e5751 Migrate Google Task default lists 1 year ago
Don Zouras c6652c851e Translated using Weblate (Esperanto)
Currently translated at 46.8% (315 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
Alex Baker 585f12d2f9 Disable persistent reminders on Android 14+ 1 year ago
Alex Baker 47c425f7e8 Update changelog 1 year ago
Alex Baker 72a337d572 Remove AD_ID permission 1 year ago
Alex Baker cbaede67cf Fix R8 errors 1 year ago
Alex Baker 7b2f526f7b Fix translation 1 year ago
renovate[bot] 2e6ec655db Update dependency com.google.apis:google-api-services-drive to v3-rev20230423-2.0.0 1 year ago
Alex Baker 57c4018e37 Update filters when restoring backup 1 year ago
Alex Baker 067317b5a0 Migrate google task filters 1 year ago
Alex Baker ad3c35bc5d Comment bar hidden by default 1 year ago
Alex Baker 8907d3f520 Set USE_EXACT_ALARM permission on Android 13+ 1 year ago
renovate[bot] 9f59d8ddf2
Update flipper to v0.190.0 (#2292)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 year ago
Alex Baker af72e35f05 Gradle 8.1.1 1 year ago
Alex Baker 251edd39ed Fix task order shifting 1 year ago
renovate[bot] 455221c625 Update okhttp to v4.11.0 1 year ago
Alex Baker f62d007ff1 Add Odia to locales_config 1 year ago
Subham Jena b466170bbf
Translated using Weblate (Odia)
Currently translated at 20.6% (139 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/or/
1 year ago
109247019824 ebeeb06420
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
1 year ago
Milo Ivir 81646bb133
Translated using Weblate (Croatian)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
1 year ago
Ihor Hordiichuk 98cc3908b6
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
1 year ago
Frits van Bommel 41f4faebe7
Translated using Weblate (Dutch)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
1 year ago
Pierfrancesco Passerini bf512537fe
Translated using Weblate (Italian)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
1 year ago
Florian Trayon 76e19e292b
Translated using Weblate (French)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
1 year ago
Florian Trayon 77db8dbe86
Translated using Weblate (Spanish)
Currently translated at 100.0% (672 of 672 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
1 year ago
Subham Jena 31f6c85f89
Added translation using Weblate (Odia) 1 year ago
renovate[bot] eeb448729c
Update dependency org.mockito:mockito-core to v5.3.1 (#2284)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 year ago
Alex Baker 84e45f0b20 Update play-services-location to 21.0.1 1 year ago
Alex Baker 114ec3f03b Convert Task to data class 1 year ago
Alex Baker f72860cef1 Remove unused constructors 1 year ago
Alex Baker 686a36ecbd Fix tests 1 year ago
renovate[bot] 4f01e4dba4 Update dependency com.google.android.gms:play-services-oss-licenses to v17.0.1 1 year ago
Alex Baker a8d62b6632 Convert TaskContainer to Kotlin 1 year ago
Alex Baker 19b2551f54 Prevent infinite recursion 1 year ago
Alex Baker c303ce32ab Change lists with drag and drop 1 year ago
Alex Baker f18a646d09 Convert list joins to inner 1 year ago
renovate[bot] 1ec48feb36 Update dependency com.google.apis:google-api-services-drive to v3-rev20230413-2.0.0 1 year ago
renovate[bot] 8c60f54f77 Update dependency androidx.fragment:fragment-ktx to v1.5.7 1 year ago
Alex Baker cfa46c7e24 Remove paging 1 year ago
Alex Baker 1d6d8e87d1 Fix some chip issues caused by sorting 1 year ago
Alex Baker 18242e5284 Add sort by list 1 year ago
Alex Baker 13b4f80c70 Update to compose 2023.04.01 1 year ago
renovate[bot] e72ceca528 Update dependency androidx.activity:activity-compose to v1.7.1 1 year ago
renovate[bot] b331f1440f Update dependency androidx.compose.compiler:compiler to v1.4.6 1 year ago
Alex Baker a739b21f0f Don't always add reminders to new incoming tasks
* Don't add reminders on initial sync
* Don't add reminders for tasks created by clients with alarm support
1 year ago
Alex Baker 47f4ae8dde Refactor recursive queries 1 year ago
Alex Baker 9e60949019 Update dependencies.txt 1 year ago
renovate[bot] d00987fcc8
Update dependency com.google.apis:google-api-services-tasks to v1-rev20230401-2.0.0 (#2273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 year ago
renovate[bot] 52d9fdce79
Update dependency fastlane to v2.212.2 (#2271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 year ago
Alex Baker 2848bd4f53 Add kotlin-parcelize 1 year ago
Alex Baker 70ab826598 Migrate some dependencies to version catalog 1 year ago
Alex Baker 5f4753da6f Gradle plugin 8.0.0 1 year ago
renovate[bot] 5ac6a3ca79 Update dependency com.google.firebase:firebase-crashlytics-gradle to v2.9.5 1 year ago
renovate[bot] 0ba7b319b2 Update dependency com.google.firebase:firebase-bom to v31.5.0 1 year ago
Alex Baker bdc01b271d Update dependencies.txt 1 year ago
Alex Baker 013f43ca34 Fix tests 1 year ago
Alex Baker e41b9561dc Convert Place to data class 1 year ago
Alex Baker 2c697fd5b9 Convert Geofence to data class 1 year ago
renovate[bot] 1a810e0298 Update kotlin 1 year ago
Alex Baker 4121163008 Non-transitive R classes 1 year ago
renovate[bot] f4e5c5c72b Update mockito monorepo to v5.3.0 1 year ago
renovate[bot] a21ee0a3c2 Update dependency gradle to v8.1 1 year ago
Alex Baker e37497b77f Fix some recomposition issues on chips 1 year ago
Alex Baker 4018277645 Use builtin build types 1 year ago
Alex Baker 97e1b75781 Check for exact alarm permission 1 year ago
109247019824 d477dfb448
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
1 year ago
renovate[bot] 360a85c57b Update flipper to v0.189.0 1 year ago
Alex Baker 88a3da822b Finish migration to gradle version catalog 1 year ago
Alex Baker df50cf9459 Add ui-tooling-preview 1 year ago
renovate[bot] 05bad27d63 Update dependency androidx.compose:compose-bom to v2023.04.00 1 year ago
renovate[bot] acbf3f2f97 Update accompanist to v0.30.1 1 year ago
renovate[bot] b6116623fa
Update flipper to v0.188.0 1 year ago
renovate[bot] 5ecc52bf78 Update dependency ruby to v3.2.2 1 year ago
renovate[bot] 26af7d74f7 Update dependency com.android.tools:desugar_jdk_libs to v2.0.3 1 year ago
renovate[bot] 72e4f853b2 Update flipper to v0.187.1 1 year ago
renovate[bot] 4c572f7504 Update coil to v2.3.0 1 year ago
Kazushi Hayama 31d7f489a7 Translated using Weblate (Japanese)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
1 year ago
renovate[bot] 14d4fa702b Update dependency org.osmdroid:osmdroid-android to v6.1.16 1 year ago
renovate[bot] 887007d898 Update dependency com.google.firebase:firebase-bom to v31.4.0 1 year ago
Alex Baker db82ef7fd6 Accompanist appcompat theme adapter 1 year ago
Alex Baker b75be2c5af Update compose and accompanist 1 year ago
renovate[bot] 8574c4f8bd Update dependency org.osmdroid:osmdroid-android to v6.1.15 1 year ago
renovate[bot] 94eb48c326 Update dependency com.google.apis:google-api-services-drive to v3-rev20230306-2.0.0 1 year ago
renovate[bot] db8744123f Update dependency androidx.work:work-runtime-ktx to v2.8.1 1 year ago
renovate[bot] 63e3311fd3 Update dependency androidx.fragment:fragment-ktx to v1.5.6 1 year ago
renovate[bot] fc58a059e4 Update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.1 1 year ago
renovate[bot] 7010d06432 Update lifecycle to v2.6.1 1 year ago
renovate[bot] c206634de1 Update room to v2.5.1 1 year ago
renovate[bot] b13a080ba4 Update dependency androidx.activity:activity-compose to v1.7.0 1 year ago
Alex Baker 26e1ffcc85 Update compose-compiler to 1.4.4 1 year ago
Simona Iacob 4be0a80d17
Translated using Weblate (Romanian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ro/
1 year ago
renovate[bot] 272b7d9dcf Update dependency com.facebook.flipper:flipper to v0.187.0 1 year ago
renovate[bot] 2f8d698dd6 Update flipper to v0.186.0 1 year ago
Alex Baker 049e4a9329 Set test timezone 1 year ago
Alex Baker 91da3191c5 Fix uploading reports for failed actions 1 year ago
Alex Baker 2bc906868d Always upload test reports 1 year ago
Alex Baker 9d142bd80b Upload test reports 1 year ago
Alex Baker db563b04ae Update actions 1 year ago
Alex Baker e2ab005e29 Fix OpenTask tests 1 year ago
Alex Baker b1b85444bd Fix backup cleanup regex 1 year ago
renovate[bot] 2c6ebf3c3e Update mockito monorepo to v5 1 year ago
renovate[bot] 58230f5e61 Update dependency gradle to v8 1 year ago
renovate[bot] 80d69ea3f5 Update flipper to v0.185.0 1 year ago
Alex Baker 4b325c0133 Attempt to filter out inactive widgets 1 year ago
Alex Baker 32eed65f04 Don't set repeat count to 0 1 year ago
renovate[bot] fe87eac962 Update kotlin 1 year ago
Alex Baker 43a943dedd Add compose compiler + kotlin group for renovate 1 year ago
Alex Baker de61bb3fe9 Update dependencies 1 year ago
renovate[bot] b6523bf30f Update dependency com.android.billingclient:billing-ktx to v4.1.0 1 year ago
renovate[bot] 6fa7b53cd7 Update dependency com.google.auth:google-auth-library-oauth2-http to v0.27.0 1 year ago
renovate[bot] ad5c1dc8d0 Update dependency com.google.android.material:compose-theme-adapter to v1.2.1 1 year ago
renovate[bot] 089337aabc Update dependency androidx.work:work-runtime-ktx to v2.8.0 1 year ago
renovate[bot] ae87325c58 Update androidx-test 1 year ago
renovate[bot] 73dfa62fcc Update dependency com.google.code.gson:gson to v2.10.1 1 year ago
renovate[bot] 0dd10e835c Update dependency org.osmdroid:osmdroid-android to v6.1.14 1 year ago
renovate[bot] 19cd5b967a Update dependency com.google.apis:google-api-services-drive to v3-rev20230212-2.0.0 1 year ago
renovate[bot] 406ae0dfdd Update dependency com.google.apis:google-api-services-tasks to v1-rev20210709-2.0.0 1 year ago
renovate[bot] 72fbf21067 Update dependency gradle to v7.6.1 1 year ago
renovate[bot] fc13be33c4 Update flipper to v0.184.0 1 year ago
renovate[bot] 204f8312ad Update lifecycle to v2.6.0 1 year ago
renovate[bot] 82b1b7bd57 Update dependency com.github.bitfireAT:dav4jvm to v2.2.1 1 year ago
renovate[bot] 973bd086dd Update dependency com.github.franmontiel:PersistentCookieJar to v1.0.1 1 year ago
renovate[bot] 3778aaaf05 Update dependency com.google.firebase:firebase-crashlytics-gradle to v2.9.4 1 year ago
Alex Baker c2cc2e0c31 Firebase BoM 1 year ago
Alex Baker 567c3ba0e7 Update dependencies.txt 1 year ago
renovate[bot] 38d273d149 Update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.0 1 year ago
renovate[bot] 1bd3cb84b2 Update dependency androidx.test.ext:junit to v1.1.5 1 year ago
renovate[bot] 273c9ebe52 Update dependency androidx.recyclerview:recyclerview to v1.3.0 1 year ago
renovate[bot] ddee3b44d1 Update dagger-hilt to v2.45 1 year ago
renovate[bot] ccfd494b49 Update dependency com.android.tools:desugar_jdk_libs to v2.0.2 1 year ago
renovate[bot] 3e3b37a66b Update coil to v2.2.2 1 year ago
renovate[bot] 3ce8f864ce Update dependency androidx.appcompat:appcompat to v1.6.1 1 year ago
Alex Baker 8d2aee359b Add renovate config 1 year ago
Alex Baker 7ced8a2fdc Replace buildSrc with gradle version catalog 1 year ago
Alex Baker 5ecc604b37 AGP 7.4.2 1 year ago
Alex Baker 379a49fa81 Merge branch 'use-iso-8601' 1 year ago
Alex Baker bd1101d73e Add old filename to matcher 1 year ago
Alex Baker e114bb4851 Remove coverage
gradle 8 breaks jacoco plugins, will have to check in on this later
1 year ago
Don Zouras 82fae728c4
Translated using Weblate (Esperanto)
Currently translated at 46.8% (315 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
Don Zouras 5f25f953fd
Translated using Weblate (Esperanto)
Currently translated at 46.2% (311 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
Chih-Hsuan Yen a1487e4c41
Translated using Weblate (Chinese (Traditional))
Currently translated at 81.4% (548 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hant/
1 year ago
Poesty Li 5c10c748dd
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
1 year ago
Naga ea994122e7
Translated using Weblate (Japanese)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
1 year ago
Kisaragi Hiu c1008a31b7
Translated using Weblate (Japanese)
Currently translated at 70.4% (474 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
1 year ago
NN 1be1f3e0ae
Translated using Weblate (Japanese)
Currently translated at 70.4% (474 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
1 year ago
Gabriel Camargo ea0a110576
Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.7% (671 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt_BR/
1 year ago
Olli 582e0a1a3d
Translated using Weblate (Finnish)
Currently translated at 99.7% (671 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fi/
1 year ago
Don Zouras 3d490f0ed6
Translated using Weblate (Esperanto)
Currently translated at 41.3% (278 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
AHOHNMYC 8764b01301
Translated using Weblate (Russian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ru/
1 year ago
Alex Baker 100928d002 Merge branch 'juliushaertl-enh/noid/quick-save-new-task' 1 year ago
Alex Baker b85dc20d24 Fix sort order string formatting 1 year ago
Alex Baker 1fdeb5fb35 Remove extra sync check 1 year ago
Alex Baker 0738ebb758 Increase memory 1 year ago
Alex Baker 417f5ac224 Merge branch 'consolidate_lists' 1 year ago
Alex Baker ad54394c08 Fix parcel crash 1 year ago
Alex Baker 3cb8cd9a45 Fix migrations 1 year ago
Alex Baker 6c10466904 Update ical4android 1 year ago
Alex Baker 3131c56651 Code review 1 year ago
Alex Baker e644971619 Update recyclerview 1 year ago
Alex Baker 120eb4dd30 Fix tests 1 year ago
Alex Baker c2222657ec Remove gt_parent from CaldavTask 1 year ago
Alex Baker f6ca98e096 Remove SubsetCaldav 1 year ago
Alex Baker ac62b4f385 Move cd_order to task table 1 year ago
Alex Baker 2006e2c84b Convert GoogleTask to CaldavTask 1 year ago
Alex Baker 513f8b017f Convert GoogleTaskList to CaldavCalendar 1 year ago
Alex Baker a04fbebd0f Convert GoogleTaskAccount to CaldavAccount 1 year ago
Alex Baker 0c2b31b84b Update version and changelog 1 year ago
Alex Baker 1eba02604d Update some libraries 1 year ago
Alex Baker 0f6013cecc Compose BOM 2023.01.00, Kotlin 1.8.0 1 year ago
Alex Baker 68d80a5d2a Sync when app comes to the foreground
If it hasn't syncd in 5+ minutes
1 year ago
Alex Baker c5587d9fea AGP 7.4.0 1 year ago
gnu-ewm e4e0ec013b
Translated using Weblate (Polish)
Currently translated at 99.8% (672 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pl/
1 year ago
Alex Baker ab8af2a3a1
Update bitcoin link 1 year ago
Alex Baker e2ad2507d3 Change to bitcoin url 1 year ago
Don Zouras 705b6e05dd
Translated using Weblate (Esperanto)
Currently translated at 41.3% (278 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
JoseFabio El que Conoces ab968dcf17
Translated using Weblate (Esperanto)
Currently translated at 40.8% (275 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
Don Zouras 50bb209cd3
Translated using Weblate (Esperanto)
Currently translated at 40.8% (275 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eo/
1 year ago
Julius Härtl 99d1dea0f1
feat: Save task when ime action done is triggered
Signed-off-by: Julius Härtl <jus@bitgrid.net>
1 year ago
bruh 9a5c4ea010
Translated using Weblate (Vietnamese)
Currently translated at 99.8% (672 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/vi/
1 year ago
Olli 6f7890ea3b
Translated using Weblate (Finnish)
Currently translated at 98.9% (666 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fi/
1 year ago
Alex Baker 63fda6f681 Add default reminders to new incoming ical tasks 1 year ago
Alex Baker 738870ac6b Update AGP 7.4.0-rc02 1 year ago
Kazushi Hayama 3b04ddb44f
Translated using Weblate (Japanese)
Currently translated at 68.3% (460 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
1 year ago
Alex Baker 4f6749dc24 Allow cleartext traffic in debug mode 1 year ago
Kazushi Hayama c18eac2b00
Translated using Weblate (Japanese)
Currently translated at 68.0% (458 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
1 year ago
C. Rüdinger 5ac9df3cb6
Translated using Weblate (German)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
1 year ago
o20n3 6405d5fe66
Translated using Weblate (Korean)
Currently translated at 93.4% (629 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ko/
1 year ago
Pierfrancesco Passerini 6df420d584
Translated using Weblate (Italian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
1 year ago
Tntdruid 9bea3ee6df
Translated using Weblate (Danish)
Currently translated at 99.7% (671 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/da/
1 year ago
haidarah esmander b85694eebd
Translated using Weblate (Arabic)
Currently translated at 96.4% (649 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ar/
1 year ago
Slávek Banko fb5ab13d99
Translated using Weblate (Czech)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/cs/
2 years ago
Alex Baker 172be4fa6a Update version and changelog 2 years ago
Alex Baker 2d3d136012 Catch exception when looking up ringtone title 2 years ago
Alex Baker 1315f59199 Fix locale on purchase sku 2 years ago
Kazushi Hayama 3a61cbf735
Translated using Weblate (Japanese)
Currently translated at 66.7% (449 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ja/
2 years ago
Pierfrancesco Passerini 4997d9e2f1
Translated using Weblate (Italian)
Currently translated at 99.7% (671 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Alex Baker dad625d402 Update version and changelog 2 years ago
Alex Baker 65ef69f46e AGP 7.4.0-rc01 2 years ago
Alex Baker 927168dcf6 Use default network security configuration 2 years ago
Alex Baker ec81bf7b85 Use default network security configuration 2 years ago
SC e034b43b39
Translated using Weblate (Portuguese)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 years ago
Alex Baker e162cc7809 Add host to msauth intent filter 2 years ago
Alex Baker 2a825ce2c7 Disable editing title for read only task 2 years ago
Alex Baker 71f22dd05d Read-only support 2 years ago
Alex Baker 644eda1eef Fix tests 2 years ago
Kaci 67ace66204
Translated using Weblate (Hungarian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hu/
2 years ago
Milo Ivir 00db98b3ca
Translated using Weblate (Croatian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Eric 188cf998fa
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Ihor Hordiichuk 8f41bf99a9
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Oğuz Ersen e1e7dde890
Translated using Weblate (Turkish)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Nikita Epifanov 9be2fbf505
Translated using Weblate (Russian)
Currently translated at 99.8% (672 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ru/
2 years ago
Frits van Bommel 45f2aa801a
Translated using Weblate (Dutch)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Gediminas Murauskas ee61aced63
Translated using Weblate (Lithuanian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/lt/
2 years ago
Pierfrancesco Passerini 7ea84b2659
Translated using Weblate (Italian)
Currently translated at 99.7% (671 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Kaci 2295e14f8a
Translated using Weblate (Hungarian)
Currently translated at 98.9% (666 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hu/
2 years ago
Florian Trayon a8698d8080
Translated using Weblate (French)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Olli d5a89649fa
Translated using Weblate (Finnish)
Currently translated at 95.0% (640 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fi/
2 years ago
Florian Trayon 222d831220
Translated using Weblate (Spanish)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
World Test e9d5afa9e7
Translated using Weblate (German)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 years ago
109247019824 137b3ce8b2
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (673 of 673 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Alex Baker 9ed8486cfc Convert CaldavCalendar to data class 2 years ago
Nikita Epifanov e529de066e
Translated using Weblate (Russian)
Currently translated at 99.7% (669 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ru/
2 years ago
Alex Baker 38e1c09b24 Convert Location to data class 2 years ago
Alex Baker 3d110347b0 Update version and changelog 2 years ago
Alex Baker ff48aa18c2 Add 'More options' experiment
The 'More options' button gets missed by a lot of users
2 years ago
Alex Baker d82e594043 Limit sort order for astrid manual sorting
Fix crash when sorting ~1000 tasks
2 years ago
Alex Baker 03f695f625 Restore original priority button order 2 years ago
Alex Baker f38b2324e9 Add MicrosoftConverter 2 years ago
Alex Baker dd48d074be Fix persistent notifications on Android 13 2 years ago
Alex Baker 670fc1591f Update desugaring, AGP, and gradle 2 years ago
Alex Baker 5c368cf970 Update dav4jvm 2 years ago
Alex Baker 80abbbcce5 Update ical4android 2 years ago
Alex Baker 35f4ebc7a2 Disable opentask notification broadcasts
Fix crash for too many pending intents
2 years ago
Alex Baker c17e2ef98b Update third party dependencies 2 years ago
Alex Baker 980ee440d5 Create link to shared test files 2 years ago
Alex Baker a07851bc5a Update to AGP 7.3.1 2 years ago
Alex Baker 8c5edf35f4 Fix RTL text in beast mode preferences 2 years ago
Alex Baker f2a728a579 Update to play billing 4.0 2 years ago
Alex Baker 55a994fcca Fix alarm calculator tests 2 years ago
Alex Baker 3691975b9d Update version and changelog 2 years ago
Alex Baker 4b3e7b026b Merge branch 'dynamic_default_reminder' of ssh://github.com/orellazri/tasks into orellazri-dynamic_default_reminder 2 years ago
Alex Baker 71b70c43b2 Fix priority button spacing 2 years ago
Alex Baker 9787a420d9 Update version and changelog 2 years ago
Alex Baker 8d78a5bfdb Merge tag '12.7.1' 2 years ago
Alex Baker eb3dd461ad Fix crash when signing back into tasks.org 2 years ago
Alex Baker 390265a9df Schedule notifications after permissions granted 2 years ago
Alex Baker e13d16d644 Jetpack Compose compiler 1.3.2 2 years ago
Alex Baker 1cd4e00919 Add xprop tests 2 years ago
Alex Baker 28e92e00c9 Update google and firebase plugins 2 years ago
Alex Baker d0dfb30860 Jetpack Compose 1.3.0-beta03 2 years ago
Milo Ivir eabde2ac57
Translated using Weblate (Croatian)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Alex Baker eb631967fd Add priority row preview 2 years ago
Gontzal Manuel Pujana Onaindia 124a9f84ee
Translated using Weblate (Basque)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eu/
2 years ago
SC ff7f55be5a
Translated using Weblate (Portuguese)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 years ago
Eric cb4c589b60
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Ihor Hordiichuk fc8e7c0226
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Oğuz Ersen 3845222f9f
Translated using Weblate (Turkish)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Frits van Bommel f3c1fd9628
Translated using Weblate (Dutch)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Pierfrancesco Passerini 4020999c40
Translated using Weblate (Italian)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Florian Trayon 14814c3d18
Translated using Weblate (French)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Florian Trayon 3b7d4315b5
Translated using Weblate (Spanish)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
qwerty287 9dd62bcfe5
Translated using Weblate (German)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 years ago
109247019824 9740891171
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (671 of 671 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Alex Baker e2d3ccacda Android Gradle Plugin 7.3.0 2 years ago
Alex Baker e5259b898a Jetpack Compose 1.3.0-beta02 2 years ago
Orel 48613bc925 Make default reminder for tasks without due times dynamic 2 years ago
Alex Baker c36e1e8173 Update version and changelog 2 years ago
Alex Baker 9219796c6b Restore trailing icon on tag row 2 years ago
Alex Baker f68ef7cbe5 Add e-mail disclosure dialog 2 years ago
Pierfrancesco Passerini 29519c24cc
Translated using Weblate (Italian)
Currently translated at 99.8% (667 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
109247019824 e62f556d27
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Ihor Hordiichuk 4a2aa97282
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Alex Baker eaa47029e7 Merge sync work 2 years ago
Alex Baker d589a89506 Create, rename, and delete microsoft lists 2 years ago
Alex Baker 1793d95d4d Add analytic event for new microsoft account 2 years ago
Alex Baker 1299bce67f Add MicrosoftService 2 years ago
Alex Baker 23bd8ba914 Fix tests 2 years ago
Alex Baker 1f07b17e75 Fix lint error 2 years ago
Alex Baker 1ff960c496 Remove unused strings 2 years ago
Alex Baker 7778c21692
Merge pull request #1999 from weblate/weblate-tasks-android
Translations update from Hosted Weblate
2 years ago
Frits van Bommel 7538f2bdbb
Translated using Weblate (Dutch)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Alex Baker 8f0d30408c Remove unused strings
Accidentally checked these in
2 years ago
Milo Ivir 6a8428cd06
Translated using Weblate (Croatian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Eric e8c0ab68ff
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Oğuz Ersen 8f0d0e9d45
Translated using Weblate (Turkish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Allan Nordhøy e49a033234
Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.9% (663 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nb_NO/
2 years ago
Florian Trayon 6e8ff8485d
Translated using Weblate (French)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Florian Trayon b947f2d765
Translated using Weblate (Spanish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
Milo Ivir 12381f9e02
Translated using Weblate (Croatian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Eric 10ba0917b7
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Ihor Hordiichuk a7232546d8
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Oğuz Ersen c707b981f1
Translated using Weblate (Turkish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Frits van Bommel 33de54aa14
Translated using Weblate (Dutch)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Pierfrancesco Passerini 38031083a3
Translated using Weblate (Italian)
Currently translated at 99.8% (666 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Florian Trayon 10ee541c7d
Translated using Weblate (French)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
J. Lavoie 64231fc742
Translated using Weblate (French)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Florian Trayon b17fde11f9
Translated using Weblate (Spanish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
109247019824 191bf5a182
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Alex Baker 7327572db4 Add Microsoft authentication 2 years ago
Alex Baker 9522c14891 Handle add account dialog clicks in settings 2 years ago
Alex Baker 3c16a0c99a Add Microsoft to account dialog 2 years ago
Alex Baker 780667b798 AppAuth 0.11.1 2 years ago
Alex Baker 26fc731e8e Fix up locales config 2 years ago
Enol P 23de9cb129
Translated using Weblate (Asturian)
Currently translated at 0.3% (2 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ast/
2 years ago
Milo Ivir feb1f18470
Translated using Weblate (Croatian)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Enol P 949bc10ca0
Added translation using Weblate (Asturian) 2 years ago
qwerty287 b65e9f673a
Translated using Weblate (German)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 years ago
Alex Baker 5452d578be Fix crash on missing location 2 years ago
Simona Iacob 55f33a3f75
Translated using Weblate (Romanian)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ro/
2 years ago
Alex Baker 9a19c0adc0 Remove MemoryCookieStore 2 years ago
Alex Baker f8c5fa47b3 Preserve cookies 2 years ago
Alex Baker 0ae473e27f Use http client factory for caldav and etesync 2 years ago
Alex Baker 37a59099cf Material components 1.8.0-alpha01 2 years ago
Alex Baker 060e674727 Move selected tags to top of list 2 years ago
Alex Baker 395ef07b4e Set user-agent 2 years ago
Alex Baker 4db88b9865 Don't pass certmanager around 2 years ago
cketti 468d42e4f6 Fix method to remove Preference
Preference instances that were not direct children of the Fragment's root PreferenceScreen were not removed.
2 years ago
Alex Baker 2783e80608 AGP 7.3.0-rc01 2 years ago
SC 0907f7c54e
Translated using Weblate (Portuguese)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 years ago
Varun Sharma a0328112fb [GitHub] Add minimum GitHub token permissions for workflows
Signed-off-by: Varun Sharma <varunsh@stepsecurity.io>
2 years ago
Alex Baker bf829727ff Check if original attachments are initialized 2 years ago
Alex Baker 8dd47881a2 Fix crash when importing older backup 2 years ago
Alex Baker 6cb0069f76 Update version and changelog 2 years ago
Alex Baker c100d21bb4 Don't set creation date on every google task sync 2 years ago
Alex Baker 6ba234ebfd Don't crash when missing widget id 2 years ago
Alex Baker e3ff3bf499 Fix crash when clicking beast mode banner 2 years ago
Alex Baker 45e48f122a Fix crash when printing repeat rule string 2 years ago
Alex Baker a51593170f Make sync account fill max width 2 years ago
Eric 837e4e5406
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Ihor Hordiichuk d83f79864b
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Oğuz Ersen 906188f5e3
Translated using Weblate (Turkish)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Frits van Bommel 2ef4adb9d8
Translated using Weblate (Dutch)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Florian Trayon 9639b16305
Translated using Weblate (French)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Florian Trayon 956dd111eb
Translated using Weblate (Spanish)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
109247019824 0259da8322
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (666 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Pierfrancesco Passerini d4b2f72ae6
Translated using Weblate (Italian)
Currently translated at 99.8% (665 of 666 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Alex Baker e16f076fb7 Convert AddAccountDialog to compose 2 years ago
Alex Baker 68b91ed2c7 Add geofence circle to place settings 2 years ago
Alex Baker 336279ee63 Fix OSM marker overlay 2 years ago
Alex Baker b8470ccc2b Fix cancel button on widget filter picker 2 years ago
Alex Baker a6da3332d3 Update version and changelog 2 years ago
Alex Baker 2c45f0da94 Fix annotation 2 years ago
Alex Baker 73adb86854 Ignore empty language tags 2 years ago
Alex Baker 587db3fa5c Thumbnails for attachments 2 years ago
Alex Baker 2eabaad0e2 Update reverse geocoder work
* Don't overwrite remote coordinates
* Ignore results >100m away
2 years ago
Alex Baker 95d5f74752 Refresh lists after deleting place 2 years ago
Alex Baker 2ac6c2413b Attachment changes
* Add attachment table to map attachment to file
* Convert TaskAttachment to immutable data class
* Copy attachments when duplicating tasks
2 years ago
Alex Baker 226687fee8 Add alarms to new subtasks 2 years ago
Alex Baker 3ce0433f9c Add alarms to new incoming google tasks 2 years ago
Alex Baker 99f13df068 Fix default reminders for Tasker tasks 2 years ago
Alex Baker ba11ec2747 Reset etebase sync flag on startup 2 years ago
Pierfrancesco Passerini 2a8ae1709d
Translated using Weblate (Italian)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Ela Bogucka 1d1a2eb6c7
Translated using Weblate (Polish)
Currently translated at 100.0% (667 of 667 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pl/
2 years ago
Alex Baker a0e26263b1 Fix list row 2 years ago
Alex Baker 4ccba6f2b1 Fix cloning subtask 2 years ago
Alex Baker 8258c73a7f Merge ssh://github.com/lkempf/tasks into HEAD 2 years ago
Alex Baker bb9e2f90b4 Replace ListPicker with FilterPicker
Simplify fragment result listeners
2 years ago
Lukas Kempf 7344f66189 Don't forget parent when copying tasks. 2 years ago
Alex Baker 5fca19e21f Address manifest warnings 2 years ago
Alex Baker 532fea0d29 Replace FilterSelectionActivity
* Add FilterPicker DialogFragment
* Add FilterPicker compose component
* Rename FilterSelectionActivity to WidgetFilterSelectionActivity
2 years ago
Alex Baker d157bbec53 Convert ListPicker to compose 2 years ago
Alex Baker 5f3b706b81 More calendar picker updates 2 years ago
Alex Baker 135f628dae Calendar picker updates
* Move some components to compose package
* Add compose previews
* Use calendar id for selected
2 years ago
Alex Baker df65415a83 Add alpha to delete icon 2 years ago
Alex Baker c1b915baf8 Update compose and kotlin 2 years ago
Alex Baker 4f267ad989 Convert calendar picker to compose 2 years ago
Alex Baker 437d69d741 Convert AlertDialogBuilder to Kotlin 2 years ago
Alex Baker 9a33f54202 Add navigation drawer view model 2 years ago
Alex Baker c2e87a86fa Update AGP 7.2.2 2 years ago
DilshanH b3ed7ea43b
Translated using Weblate (Sinhala)
Currently translated at 97.3% (650 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/si/
2 years ago
Simona Iacob 7017f14401
Translated using Weblate (Romanian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ro/
2 years ago
Alex Baker 8f5b7ccc20 Skip add dialog when replacing some reminders
* random reminders
* pick date and time reminders
2 years ago
Alex Baker 20ab106e12 Click on alarm row to replace it 2 years ago
Alex Baker 8ed2880953 Delete some compose stuff 2 years ago
Alex Baker 2ee7715c16 Align checkbox and text in subtask row 2 years ago
Sergio Varela 2841af08de
Translated using Weblate (Basque)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/eu/
2 years ago
Alex Baker e450e262a5 Fix tests 2 years ago
Alex Baker 60820ab3c9 Convert comments row to compose 2 years ago
Alex Baker 7b9b71dd67 Fill max width for task edit rows 2 years ago
Alex Baker d0fcca1a1f Embed task edit row fragments in compose 2 years ago
Alex Baker 22de530590 Ran silent code cleanup 2 years ago
Alex Baker cdd163efbf Add preferences.linkify 2 years ago
Alex Baker 3163150e8f Move add alarm to task edit view model 2 years ago
Alex Baker 738c345275 Move view state to view model 2 years ago
Alex Baker eabe2b37ee Refresh subtasks in task edit fragment 2 years ago
Alex Baker c4cd694948 Fix lint 2 years ago
Alex Baker c532abc87f Simplify task edit view model 2 years ago
Alex Baker 9c8e897f3a Kotlin 1.7.0 and Compose 1.2.0 2 years ago
Alex Baker ccaed6ddb4 Add SubtaskRow composable 2 years ago
Alex Baker 1cac090c9d Add AlarmRow composable 2 years ago
Alex Baker 00c80337de Move more composable logic 2 years ago
Alex Baker e7b6c96576 Add DescriptionRow composable 2 years ago
Alex Baker b13db7d23a Fix new subtask text color 2 years ago
Alex Baker b6efff59b4 CheckBox and SubtaskChip composables 2 years ago
Alex Baker d48d457a3d Update priority row colors 2 years ago
Alex Baker 85b8092982 Move more composable logic 2 years ago
Alex Baker 3e3de3c1d6 Moving logic into composables, adding previews 2 years ago
Alex Baker 5c3af50c9d Move more Start and due date logic into composables 2 years ago
Alex Baker e39bc8b8cc Comment bar is not an edit control set 2 years ago
Alex Baker f4d69a8a69 Convert DescriptionControlSet to compose 2 years ago
SC 1615f215c4
Translated using Weblate (Portuguese)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 years ago
Alex Baker e450f51f60 Convert repeat control set to compose 2 years ago
SC 0711176ae2
Translated using Weblate (Portuguese)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 years ago
Alex Baker 4d8a058bfb Fix migration 2 years ago
Alex Baker 57ca2f013a Update schema for recurrence
* Move repeat until into recurrence
* Move repeat from out of recurrence
2 years ago
bruh c52f90adb9
Translated using Weblate (Vietnamese)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/vi/
2 years ago
Milo Ivir 5be37001c0
Translated using Weblate (Croatian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Alex Baker 5e607f73a3 Create separate view fragment 2 years ago
Alex Baker b4c3bec3ab Convert subtask control set to compose 2 years ago
Alex Baker 8c137f6521 TaskEditRow composable with slots 2 years ago
Oğuz Ersen 2e2e74217e
Translated using Weblate (Turkish)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Alex Baker 3fa9040549 Convert FilesControlSet to compose 2 years ago
Alex Baker 9b3f5a0c65 Convert CreationDateControlSet to compose 2 years ago
Alex Baker ef308d6c14 google-services 4.3.13 2 years ago
Alex Baker 12f9352f69 Fix starting new timer 2 years ago
Alex Baker f5a53e6453 Convert TimerControlSet to compose 2 years ago
Alex Baker 908d75909d Convert CalendarControlSet to compose 2 years ago
Sameer Rustamzada 3736c4596e
Translated using Weblate (Persian)
Currently translated at 29.2% (196 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fa/
2 years ago
Alex Baker 8f4db8374d Convert LocationControlSet to compose 2 years ago
Alex Baker 08069d0a3d Convert StartDateControlSet to compose 2 years ago
Alex Baker 91cb5a158b Fix tests 2 years ago
Eric 3df26c5401
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Ihor Hordiichuk a5313d567e
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Nikita Epifanov fcec3228f7
Translated using Weblate (Russian)
Currently translated at 99.8% (669 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ru/
2 years ago
Frits van Bommel 70552aa886
Translated using Weblate (Dutch)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Pierfrancesco Passerini e97b32b5b1
Translated using Weblate (Italian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Florian Trayon 5bc0b47ab6
Translated using Weblate (French)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Florian Trayon 198252cd84
Translated using Weblate (Spanish)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
qwerty287 db49fe46bd
Translated using Weblate (German)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/de/
2 years ago
Shimon f936d60cdf
Translated using Weblate (Czech)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/cs/
2 years ago
109247019824 977ae091de
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (670 of 670 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Alex Baker d8c70a4b5c Inline DeadlineControlSet variables 2 years ago
Alex Baker 8e8b8c9f64 Convert DeadlineControlSet to compose 2 years ago
Alex Baker 6513c40c97 View model due date as state flow 2 years ago
Ihor Hordiichuk 1f3b8fd228
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Artem 90e47dc63e
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Alex Baker 6173192e72 Use info icon for creation date row 2 years ago
Alex Baker c2580e1e68 Disable configuration cache for lint action 2 years ago
Alex Baker 30961ec53a Gradle wrapper 7.4.2 2 years ago
Alex Baker de50854c99 Merge branch 'main' of ssh://github.com/ydario/tasks into main 2 years ago
Alex Baker 70e4e96ed6 Update firebase-crashlytics-gradle 2 years ago
Pierfrancesco Passerini 8957056304
Translated using Weblate (Italian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/it/
2 years ago
Allineer 99e67b2317
Translated using Weblate (Russian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/ru/
2 years ago
SC bf17a7522a
Translated using Weblate (Portuguese)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/pt/
2 years ago
mhmdanas a70b54592a Update GitHub actions 2 years ago
Milo Ivir 3bbfa11966
Translated using Weblate (Croatian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/hr/
2 years ago
Eric 839419353f
Translated using Weblate (Chinese (Simplified))
Currently translated at 99.8% (667 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/zh_Hans/
2 years ago
Ihor Hordiichuk a5a6b0f84b
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/uk/
2 years ago
Oğuz Ersen 1cc3485918
Translated using Weblate (Turkish)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/tr/
2 years ago
Frits van Bommel 55d3f463ca
Translated using Weblate (Dutch)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/nl/
2 years ago
Florian Trayon 2d6b69b95b
Translated using Weblate (French)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/fr/
2 years ago
Florian Trayon 6388a02a81
Translated using Weblate (Spanish)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/es/
2 years ago
109247019824 25c82ee906
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (668 of 668 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Alex Baker fcda6efe0c Fix task list chip group bottom padding 2 years ago
Alex Baker 1fbc2b1661 Android 13 runtime notification permissions 2 years ago
Alex Baker 99b1c2e38d Update google-services plugin 2 years ago
Alex Baker 460269351a Jetpack Compose 1.2.0-rc02 2 years ago
Alex Baker 9ea490572a Update locale injections to use language setting 2 years ago
Alex Baker 6f73765fd2 Per-app language configuration 2 years ago
Alex Baker 47d6aeddea Update target sdk to 33 2 years ago
Alex Baker 3a93af4b0a Update collect method 2 years ago
Alex Baker b455e531d3 Use new compose fragment for reminder control set 2 years ago
Alex Baker 43e787ad0c Add compose task edit fragment, chip group 2 years ago
Alex Baker 2137bf8004 Convert tag control to compose 2 years ago
Alex Baker 543e169e33 Use selected list state in subtasks control set 2 years ago
Alex Baker 25877f05e2 Convert ListFragment to compose 2 years ago
Alex Baker 9832eef2c6 Update chips
* Convert to jetpack compose
* Remove filled/outlined option
2 years ago
109247019824 b7342b770d
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (669 of 669 strings)

Translation: Tasks.org/Android
Translate-URL: https://hosted.weblate.org/projects/tasks/android/bg/
2 years ago
Alex Baker cb0ca40f4e Disable configuration cache for dependency diff 2 years ago
Alex Baker 0cecbbb376 Remove cookpad license plugin
Plugin was abandoned
2 years ago
Alex Baker 95918e3ae8 Jetpack Compose 1.2.0-rc01 2 years ago
Alex Baker ba87311759 Priority control set preview 2 years ago
Alex Baker 708e2b14e6 Convert priority control set to compose 2 years ago
Alex Baker 1ca6076005 Update crashlytics 2 years ago
Alex Baker 6b0ef5189d Enable configuration caching 2 years ago
Yuri Dario 7a17dc3719 Allow display of task's creation/modification/completion using a single row. 2 years ago
Yuri Dario bb4ce22542 Allow display of task's creation/modification/completion dates. 2 years ago
Trevor Terris bc906090aa Add ISO format to backup file matcher 3 years ago
Trevor Terris 9742d93e83 Use ISO 8601 date formatting
Update TasksJsonExporter and the default toString() method in DateTime to use the ISO 8601 standard (in particular, using four-digit years and splitting the date from the time with the character "T").
3 years ago

@ -0,0 +1,47 @@
name: Assemble bundle
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
jobs:
check:
uses: ./.github/workflows/check.yml
bundle:
runs-on: ubuntu-latest
needs: [ check ]
steps:
- name: Decode Keystore
run: |
echo ${{ secrets.KEY_STORE }} | base64 -di > "${RUNNER_TEMP}"/keystore.jks
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Bundle
env:
KEY_PATH: ${{ runner.temp }}/keystore.jks
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
MAPBOX_KEY: ${{ secrets.MAPBOX_KEY }}
GOOGLE_KEY: ${{ secrets.GOOGLE_KEY }}
run: bundle exec fastlane bundle
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: release
path: app/build/outputs/**

@ -0,0 +1,91 @@
name: Run automated checks
on:
pull_request:
workflow_call:
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Lint checks
run: bundle exec fastlane lint
- name: Archive lint reports
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: lint-reports
path: app/build/reports/*.html
test:
runs-on: ubuntu-latest
strategy:
matrix:
flavor: [Googleplay, Generic]
api-level: [29]
steps:
- name: checkout
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api-level }}
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."
- name: run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew -Pcoverage app:test${{ matrix.flavor }}DebugUnitTest app:connected${{ matrix.flavor }}DebugAndroidTest
- name: Upload test reports
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: test-reports-${{ matrix.flavor }}
path: app/build/reports/**

@ -1,36 +0,0 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Check licenses
on:
push:
paths-ignore:
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- README.md
- 'fastlane/**'
- .github/FUNDING.yml
pull_request:
paths-ignore:
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- README.md
- 'fastlane/**'
- .github/FUNDING.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: '11.0.8'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew checkLicense

@ -1,42 +0,0 @@
name: Lint
on:
push:
paths-ignore:
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- README.md
- 'fastlane/**'
- .github/FUNDING.yml
pull_request:
paths-ignore:
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- README.md
- 'fastlane/**'
- .github/FUNDING.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: '11.0.8'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Lint checks
run: bundle exec fastlane lint
- name: Archive lint reports
uses: actions/upload-artifact@v2
with:
name: lint-reports
if: always()
path: app/build/reports/*.html

@ -1,37 +0,0 @@
name: Run tests
on:
push:
paths-ignore:
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- README.md
- 'fastlane/**'
- .github/FUNDING.yml
pull_request:
paths-ignore:
- CODE_OF_CONDUCT.md
- CONTRIBUTING.md
- README.md
- 'fastlane/**'
- .github/FUNDING.yml
jobs:
test:
runs-on: macos-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: '11.0.8'
- name: run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
script: ./gradlew -Pcoverage :app:jacocoTestReportGoogleplayDebug :app:createGoogleplayDebugAndroidTestCoverageReport
- name: upload coverage
uses: codecov/codecov-action@v1
with:
directory: ./app/build

2
.gitignore vendored

@ -1,3 +1,4 @@
.kotlin
.idea
*.iml
.gradle
@ -9,3 +10,4 @@ local.properties
Thumbs.db
/captures/
/fastlane/report.xml
/compose-metrics/

@ -1 +1 @@
3.0.3
3.3.1

File diff suppressed because it is too large Load Diff

@ -1,43 +1,45 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
CFPropertyList (3.0.7)
base64
nkf
rexml
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
artifactory (3.0.15)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.598.0)
aws-sdk-core (3.131.1)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
aws-eventstream (1.3.0)
aws-partitions (1.923.0)
aws-sdk-core (3.194.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.57.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (1.80.0)
aws-sdk-core (~> 3, >= 3.193.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.114.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-s3 (1.149.0)
aws-sdk-core (~> 3, >= 3.194.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.0)
aws-sigv4 (~> 1.8)
aws-sigv4 (1.8.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.6.4)
digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
domain_name (0.6.20240107)
dotenv (2.8.1)
emoji_regex (3.2.3)
excon (0.92.3)
faraday (1.10.0)
excon (0.110.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
@ -65,15 +67,15 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.206.2)
fastimage (2.3.1)
fastlane (2.220.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
colored (~> 1.2)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
@ -85,30 +87,32 @@ GEM
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (~> 0.1.1)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.21.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-core (0.5.0)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@ -116,31 +120,29 @@ GEM
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
webrick
google-apis-iamcredentials_v1 (0.10.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-playcustomapp_v1 (0.7.0)
google-apis-core (>= 0.4, < 2.a)
google-apis-storage_v1 (0.14.0)
google-apis-core (>= 0.4, < 2.a)
google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.7.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.2.0)
google-cloud-storage (1.36.2)
google-cloud-errors (1.4.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.1.3)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
@ -148,55 +150,54 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.6.1)
json (2.6.2)
jwt (2.4.1)
memoist (0.16.2)
mini_magick (4.11.0)
mini_mime (1.1.2)
jmespath (1.6.2)
json (2.7.2)
jwt (2.8.1)
base64
mini_magick (4.12.0)
mini_mime (1.1.5)
multi_json (1.15.0)
multipart-post (2.0.0)
multipart-post (2.4.0)
nanaimo (0.3.0)
naturally (2.2.1)
optparse (0.1.1)
nkf (0.2.0)
optparse (0.5.0)
os (1.1.4)
plist (3.6.0)
public_suffix (4.0.7)
rake (13.0.6)
plist (3.7.1)
public_suffix (5.0.5)
rake (13.2.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rexml (3.2.8)
strscan (>= 3.0.9)
rouge (2.0.7)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.16.1)
security (0.1.5)
signet (0.19.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.0)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
simctl (1.6.10)
CFPropertyList
naturally
strscan (3.1.0)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.7.0)
unicode-display_width (2.5.0)
word_wrap (1.0.0)
xcodeproj (1.21.0)
xcodeproj (1.24.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)

@ -11,11 +11,11 @@ Please visit [tasks.org](https://tasks.org) for end user documentation and suppo
---
[![Donate with Bitcoin](https://img.shields.io/badge/bitcoin-donate-yellow.svg?logo=bitcoin)](https://en.cryptobadges.io/donate/136mW34jW3cmZKhxuTDn3tHXMRwbbaRU8s)
[![Donate with Bitcoin](https://img.shields.io/badge/bitcoin-donate-yellow.svg?logo=bitcoin)](https://tasks.org/docs/donate)
[![PayPal donate button](https://img.shields.io/badge/paypal-donate-yellow.svg?logo=paypal)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=alex@tasks.org)
[![Liberapay donate button](https://img.shields.io/liberapay/receives/tasks.svg?logo=liberapay)](https://liberapay.com/tasks/donate)
![tests](https://github.com/tasks/tasks/workflows/Run%20tests/badge.svg) [![weblate](https://hosted.weblate.org/widgets/tasks/-/android/svg-badge.svg)](https://hosted.weblate.org/engage/tasks/?utm_source=widget) [![codecov](https://codecov.io/gh/tasks/tasks/branch/main/graph/badge.svg)](https://codecov.io/gh/tasks/tasks) [![codebeat badge](https://codebeat.co/badges/07924fca-2f18-4eff-99a3-120ec5ac2d5f)](https://codebeat.co/projects/github-com-tasks-tasks-main)
[![build](https://github.com/tasks/tasks/actions/workflows/bundle.yml/badge.svg)](https://github.com/tasks/tasks/actions/workflows/bundle.yml) [![weblate](https://hosted.weblate.org/widgets/tasks/-/android/svg-badge.svg)](https://hosted.weblate.org/engage/tasks/?utm_source=widget) [![codebeat badge](https://codebeat.co/badges/07924fca-2f18-4eff-99a3-120ec5ac2d5f)](https://codebeat.co/projects/github-com-tasks-tasks-main)
### Contributing

@ -0,0 +1,767 @@
### 12.7 (2022-06-18)
* Android 13 themed icon - Thanks @hanthor!
* Fix self-signed SSL certificates on Android 12+
* Don't hide empty tags and places in pickers
* Update translations
* Basque - @Txopi, Sergio Varela, @osoitz
* Belarusian - @Prominence, Андрей
* Bulgarian - @StoyanDimitrov
* Czech - Shimon
* Danish - Tntdruid
* Dutch - @mm4c
* German - @3ole
* Hungarian - kaciokos
* Indonesian - Cyua Pyua
* Italian - @ppasserini
* Polish - @wiktor-k
* Portuguese (Brazilian) - @LevyMarCiS, @sunflowerskater
* Portuguese - @laralem, @alvar0liveira
* Swedish - @reportxx
* Turkish - @emintufan
* Vietnamese - @unbiaseduser
### 12.6.1 (2022-03-27)
* Move task list and edit screen options to top level settings
* Prompt users to customize edit screen
* Fix cancel button for recurring reminder dialog
* Update translations
* Bulgarian - @StoyanDimitrov
* Chinese (Simplified) - Eric, @Geeyun-JY3
* Croatian - @milotype
* Dutch - @mm4c, @fvbommel
* Finnish - J. Lavoie
* French - @FlorianLeChat
* Galician - @mglbranco, J. Lavoie
* German - @qwerty287
* Hungarian - kaciokos
* Italian - @Fs00
* Norwegian Bokmål - @comradekingu
* Polish - @wiktor-k
* Portuguese (Brazilian) - @tsunamistonefly
* Romanian - @simonaiacob
* Russian - Nikita Epifanov
* Spanish - @FlorianLeChat
* Swedish - @reportxx
* Turkish - @ersen0, @emintufan
* Ukrainian - @IhorHordiichuk
* Vietnamese - @unbiaseduser, J. Lavoie
### 12.6 (2022-03-12)
* Configure notifications to repeat at custom intervals
([#3](https://github.com/tasks/tasks/issues/3))
* Notifications can repeat by minute, hour, day, or weekly intervals
* Add 'Snoozed' filter ([#1633](https://github.com/tasks/tasks/issues/1633))
* Add 'Notifications' filter
* CalDAV/DAVx5 server selection setting
* This replaces 'Let server schedule recurring tasks'
* Synology Calendar users must set this to fix sync
([#1802](https://github.com/tasks/tasks/issues/1802))
* Mailbox.org and Open-Xchange users must set this to prevent duplicate
repeating tasks
* Set geofence radius in place settings
* Remove DAVx5/EteSync app accounts when native CalDAV/EteSync enabled
* Clear reminders when they are dismissed in Thunderbird
* Fix reminder synchronization
* Fix crash in task edit screen
* Fix prompt to discard changes
* Fix crash during 12.4 upgrade
* Update translations
* Bulgarian - @StoyanDimitrov
* Chinese (Simplified) - @Crystal-RainSlide, @Geeyun-JY3, Eric
* Croatian - @milotype
* Dutch - @mm4c, @fvbommel
* French - J. Lavoie, @FlorianLeChat
* German - @eldiep, J. Lavoie, @qwerty287
* Hungarian - kaciokos
* Italian - @ppasserini, J. Lavoie
* Portuguese (Brazilian) - @hugomg
* Romanian - @simonaiacob
* Russian - @Allineer
* Spanish - @toni-em, @FlorianLeChat, @Romerolweb
* Swedish - @reportxx
* Turkish - @ersen0
* Ukrainian - @IhorHordiichuk
* Urdue - @Crystal-RainSlide
* Vietnamese - @unbaseduser
### 12.5 (2022-02-27)
* Choose custom random reminder period
* Add multiple random reminders
* Fix sync crash for Tasks.org, CalDAV, and native EteSync
* Add Kurdish (Central) translations - @roj1512
* Update translations
* Bulgarian - @StoyanDimitrov
* Chinese (Simplified) - Eric
* Croatian - @milotype
* Dutch - @mm4c
* French - @FlorianLeChat
* Portuguese - @laralem
* Spanish - @Romerolweb, Jeffree Romero
* Turkish - @ersen0
* Ukrainian - @IhorHordiichuk
### 12.4 (2022-02-19)
* Relative reminder support
* Quickly add reminders minutes, hours, days, or weeks before due
* Sync reminders with Tasks.org, DAVx5, CalDAV, EteSync, and DecSync CC
* Synchronize relative and absolute reminders
* Tasks.org, CalDAV, and native EteSync sync improvements
* Merge remote changes before pushing local changes
* Not applicable to DAVx5, EteSync app, or DecSync CC
* View and cancel snoozed reminders in task edit screen
* Add 'Has reminder' custom filter criteria
* Fix updating calendar entries after editing task
* Fix search when using top app bar
* Fix task deletion when adding from two devices simultaneously
* Update translations
* Arabic - @mhmdanas
* Basque - Sergio Varela
* Brazilian Portuguese - @Luiz-bro
* Bulgarian - @StoyanDimitrov
* Chinese (Simplified) - Eric
* Croatian - @milotype
* Dutch - @mm4c
* French - @FlorianLeChat, J. Lavoie
* German - J. Lavoie, @qwerty287
* Hungarian - kaciokos
* Italian - @ppasserini, J. Lavoie, @andrearosso
* Portuguese - @laralem
* Romanian - @simonaiacob
* Russian - @NikGreens
* Spanish - @FlorianLeChat, Sergio Varela
* Turkish - @ersen0, @emintufan
* Ukrainian - @IhorHordiichuk
* Vietnamese - bruh, @unbaseduser
### 12.3 (2022-02-04)
* Add option to disable moving completed tasks to bottom
* Add option to disable sorting completed by completion date
* Add undo snackbar for task completion
* Fix crash when location lookup fails
* Fix voice reminders on Android 12
* Fix widget due dates in overdue sort group
* Add Karelian translations - Olexii Ondrei
* Update translations
* Basque - Sergio Varela
* Catalan - @ivangjxyz
* Chinese (Simplified) - Eric
* Croatian - @milotype
* Dutch - @mm4c
* French - @FlorianLeChat
* German - @qwerty287
* Hungarian - kaciokos
* Romanian - @simonaiacob
* Russian - @NikGreens
* Spanish - @FlorianLeChat
* Swedish - @reportxx
* Turkish - @emintufan, @ersen0
* Vietnamese - @unbaseduser
### 12.2 (2022-01-16)
* Move completed tasks to bottom
* Add option to disable collapsing app bars
* Uncheck parent tasks when subtask is unchecked
* Fix crash on completion sound
* Update translations
* Chinese (Simplified) - Eric
* Danish - @Tntdruid
* Dutch - @fvbommel, @mm4c
* French - @FlorianLeChat
* German - @qwerty287
* Russian - @NikGreens
* Spanish - @FlorianLeChat
* Turkish - @ersen0
* Ukrainian - @IhorHordiichuk
* Vietnamese - @unbaseduser
### 12.1 (2022-01-09)
* Group overdue tasks when sorting by due date
* Update translations
* Basque - Sergio Varela
* Chinese (Simplified) - Eric
* French - @FlorianLeChat
* Norwegian Bokmål - @comradekingu
* Spanish - @FlorianLeChat
* Vietnamese - @unbaseduser
### 12.0 (2022-01-08)
* New bottom app bar
* Choose top or bottom app bar in settings
* Miscellaneous design updates
* Improve privacy and security by removing RECORD_AUDIO and
WRITE_EXTERNAL_STORAGE permissions
* Attaching an audio note will launch your device's audio recorder
* Translation updates
* Catalan - @Solatec
* Dutch - @mm4c
* German - @qwerty287
* Italian - @ppasserini, @Fs00
* Portuguese - @SantosSi
* Romanian - @simonaiacob
* Russian - Nikita Epifanov
* Ukrainian - @IhorHordiichuk
### 11.13 (2021-12-31)
* Add option to play a sound when a task is completed
* Accept audio attachments shared from other apps
* Removed native EteSync v1 support
* EteSync v1 accounts can still be synchronized with the EteSync app
* Bug fixes
* Translation updates
* Bulgarian - @StoyanDimitrov
* Chinese (Simplified) - @sr093906
* Chinese (Traditional) - @dixon777
* Finnish - @CSharpest, Rami Lehtinen
* French - @FlorianLeChat
* Hungarian - kaciokos
* Italian - J. Lavoie, @Fs00
* Norwegian Bokmål - @comradekingu
* Persian - @Ahmadhosseinbor
* Spanish - @aplopez, @FlorianLeChat
* Ukrainian - @IhorHordiichuk
### 11.12.3 (2021-11-22)
* Fix reminders
* Update translations
* Indonesian - when we were sober
* Kurdish (Northern) - Pêşeroja paşerojê
* Romanian - @Steinhagen
### 11.12.2 (2021-11-13)
* Fix reminders
* Fix reminder preference backup
* Update translations
* Interlingua - @softinterlingua
* Tamil - @balogic
### 11.12.1 (2021-11-05)
* Fix reminders
* Update translations
* Bulgarian - @StoyanDimitrov
* Croatian - @milotype
* Norwegian Bokmål - @HumanNr4584093104
* Romanian - Simona Iacob
* Russian - @NikGreens
* Tamil - @balogic
* Turkish - @ersen0
### 11.12 (2021-10-26)
* Add option to notify at start date
* Widget tweaks for Android 12
* Fix crash when deleting tasks (Thanks @fschrempf!)
* Fix truncated calendar picker
* Update translations
* Basque - Sergio Varela
* Brazilian Portuguese - @laralem
* Bulgarian - @StoyanDimitrov
* Catalan - @Solatec
* Dutch - @fvbommel
* French - @FlorianLeChat
* German - @qwerty287
* Hungarian - kaciokos
* Lithuanian - @70h
* Polish - @dominik-korsa
* Simplified Chinese - @sr093906, @Geeyun-JY3
* Ukrainian - @IhorHordiichuk
* Vietnamese - bruh
### 11.11 (2021-09-21)
* Add 'Due now' filter criteria - Thanks @tkterris!
* Fix crash on Android 12 - Thanks @tkterris!
* Fix preference display issue - Thanks @Groctel!
* Target Android 12
* Ignore link clicks during multi-select
* Update translations
* Arabic - @mhmdanas, @machiav3lli
* Basque - @Thadah
* Brazilian Portuguese - @laralem
* Bulgarian - @StoyanDimitrov
* Croatian - @milotype
* Czech - @vitSkalicky
* Danish - @Tntdruid
* Dutch - @fvbommel
* French - @FlorianLeChat
* German - @machiav3lli, J. Lavoie
* Greek - @giorgio93p
* Indonesian - @erigmac
* Italian - J. Lavoie, @Fs00
* Japanese - さとうまこと
* Lithuanian - @70h
* Norwegian Bokmål - @comradekingu
* Portuguese - @laralem
* Romanian - Simona Iacob
* Russian - @tolstovka, @zhelemysh, @ToxesFoxes
* Simplified Chinese - @sr093906, @Geeyun-JY3
* Sinhala - @Dilshan-H
* Spanish - @FlorianLeChat, @Groctel, @berman00
* Swedish - @bittin
* Turkish - @ersen0
* Ukrainian - @IhorHordiichuk
* Vietnamese - bruh
### 11.10.2 (2021-07-15)
* Fix location-based reminders
* Fix preference backup
* Update translations
* Arabic - git ty, @mhmdanas
* Basque - Sergio Varela
* Croatian - @milotype
* Czech - @vitSkalicky, @p-bo
* Dutch - Beardhatcode, @fvbommel
* French - @FlorianLeChat
* German - K. Herbert, @franconian, @ecxod, @bluedeepimpact
* Indonesian - when we were sober
* Interlingua - @softinterlingua
* Italian - J. Lavoie
* Lithuanian - @70h
* Norwegian Bokmål - @Jerome2103
* Portuguese - @laralem
* Russian - @KovalevArtem, @Blueberryy
* Simplified Chinese - @sr093906, @Geeyun-JY3
* Sinhala - HelaBasa
* Spanish - @FlorianLeChat, @fitojb
* Turkish - Oğuz Ersen, @emintufan
* Ukrainian - @IhorHordiichuk
* Urdu - Maaz
* Vietnamese - bruh
### 11.10.1 (2021-05-26)
* Improve Android 12 compatibility
* Update status bar styles
* Update translations
* Arabic - @mhmdanas
* Basque - Sergio Varela
* Catalan - @toram
* Chinese (Traditional) - @kisaragi-hiu
* Croatian - @ggdorman
* Czech - @vitSkalicky
* Esperanto - @J053Fabi0, @jakubfabijan
* French - K. Herbert, J. Lavoie
* German - K. Herbert
* Greek - Eugenia Russell
* Hungarian - @gthrepwood
* Indonesian - @andhikapangestu29
* Korean - Sunjae Choi
* Portuguese (Brazil) - @laralem
* Portuguese - @SantosSi, @laralem
* Russian - Nikita Epifanov
* Sinhala - @Dilshan-H
* Spanish - @fitojb
* Ukrainian - @IhorHordiichuk
* Urdu - Maaz
* Vietnamese - bruh
### 11.10 (2021-04-19)
* Markdown support ([Documentation](https://tasks.org/docs/markdown))
* Samsung DeX support - Thanks @mhmdanas!
* Update to Google Play Billing v3
* Remove background sync for legacy EteSync v1 accounts
* Update translations
* Arabic - @mhmdanas
* Brazilian Portuguese - @daylightdev
* Dutch - @fvbommel
* French - @FlorianLeChat, J. Lavoie
* German - J. Lavoie
* Greek - Michalis, Eugenia Russell
* Indonesian - @liimee
* Italian - J. Lavoie, @Fs00
* Japanese - @kisaragi-hiu
* Kannada - @shashank-p
* Russian - @zhelemysh, Nikita Epifanov
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Turkish - Oğuz Ersen
* Ukrainian - @IhorHordiichuk
* Urdu - Maaz
### 11.9.2 (2021-03-29)
* Fix date translation issue - Thanks @mhmdanas!
* Fix misc translation strings - Thanks J. Lavoie!
* Update translations
* Dutch - @fvbommel
* French - @FlorianLeChat
* German - @franconian, Achim Schumacher, J. Lavoie
* Hungarian - kaciokos
* Indonesian - when we were sober
* Italian - @Fs00
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Turkish - @emintufan
* Ukrainian - @IhorHordiichuk
### 11.9.1 (2021-03-25)
* Open documentation links in custom tabs
* Fix crash in Mapbox reverse geocoder
* Increase 'Add subtask' touch target
* Update translations
* Arabic - @mhmdanas
* German - Achim Schumacher
* Hungarian - kaciokos
* Italian - @Fs00
* Turkish - @emintufan
### 11.9 (2021-03-20)
* New calendar and clock pickers
* New preference to default to text input for date and time
* Fix issue causing Tasks to use wrong search provider
* Fix crash when Nextcloud/ownCloud don't send list owner
* Update translations
* Basque - Sergio Varela
* Croatian - @milotype
* Dutch - @fvbommel
* French - @FlorianLeChat
* German - Achim Schumacher
* Hungarian - kaciokos
* Indonesian - when we were sober
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Ukrainian - @IhorHordiichuk
### 11.8 (2021-03-15)
* CalDAV: Send shared list invites
* Compatible with Tasks.org, Nextcloud, ownCloud, and sabre/dav
* Show shared list invite status in list settings
* Fix drawer count when list is shared with 2+ users
* Removed legacy EteSync v1 list management features
* Dropped support for Android 6.0
* Update translations
* Arabic - @mhmdanas
* Dutch - @fvbommel
* Esperanto - @jakubfabijan
* French - @FlorianLeChat
* German - @Jerome2103
* Hungarian - kaciokos
* Indonesian - when we were sober, @andhikapangestu29
* Norwegian Bokmål - @comradekingu
* Polish - @doegedomita
* Portuguese - @Jerome2103
* Spanish - @FlorianLeChat
* Turkish - Oğuz Ersen
* Ukrainian - @IhorHordiichuk
### 11.7 (2021-03-08)
* CalDAV: Display shared list members in list settings
* Compatible with Tasks.org, Nextcloud, ownCloud, OpenXchange, and sabre/dav
* CalDAV: List owners can remove shared list members from list
* Compatible with Tasks.org, Nextcloud, ownCloud, and sabre/dav
* Fix time zone issue in recurrence picker
* Update translations
* Arabic - @mhmdanas
* Basque - Sergio Varela
* Dutch - @fvbommel
* French - @FlorianLeChat
* Hungarian - kaciokos
* Indonesian - @putulopi
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Turkish - @emintufan, Oğuz Ersen
* Ukrainian - @IhorHordiichuk
### 11.6.1 (2021-03-11)
* F-Droid: Fix OpenStreetMap crash
### 11.6 (2021-03-04)
* CalDAV: Display indicator in drawer when a list is shared with other users
* Compatible with Tasks.org, Nextcloud, ownCloud, OpenXchange, and sabre/dav
* CalDAV: Don't upload changes to read-only lists
([#931](https://github.com/tasks/tasks/issues/931))
* Remove unnecessary icon-mirroring for RTL users
([#1385](https://github.com/tasks/tasks/issues/1385) and
[#1391](https://github.com/tasks/tasks/pull/1391)) - Thanks to @mhmdanas
* Update translations
* Arabic - @mhmdanas
* Basque - Sergio Varela
* Bulgarian - @StoyanDimitrov
* Czech - @vitSkalicky
* Dutch - @fvbommel
* French - @FlorianLeChat
* Hungarian - kaciokos
* Indonesian - @putulopi
* Russian - Nikita Epifanov
* Simplified Chinese - @sr093906
* Sinhala - HelaBasa
* Spanish - @FlorianLeChat
* Ukrainian - @IhorHordiichuk
### 11.5.2 (2021-02-25)
* Fix CalDAV sync error
* Report errors when generating recurrence dates
### 11.5.1 (2021-02-24)
* Fix 'repeat until' date
* Fix repeat dates for UTC+13
([#1374](https://github.com/tasks/tasks/issues/1374))
* F-Droid: Handle null name in Nominatim reverse geocoder
([#1380](https://github.com/tasks/tasks/issues/1380))
* Update translations
* Basque - Sergio Varela
* Croatian - @ggdorman
* Dutch - @fvbommel
* French - @FlorianLeChat
* Hungarian - kaciokos
* Norwegian Bokmål - @comradekingu
* Polish - @alex-ter
* Russian - Nikita Epifanov
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Turkish - Oğuz Ersen
* Ukrainian - @IhorHordiichuk
* Urdu - Maaz
### 11.5 (2021-02-17)
* Sync snooze time with Tasks.org, DAVx⁵, CalDAV, EteSync, and DecSync
* Compatible with Thunderbird
* New map theme preference
* 10 new icons
* F-Droid: Use Nominatim for reverse geocoding
* Google Play: Use OpenStreetMap tiles when Play Services not available
* Google Play: Use Android location services when Play Services not available
* Tasks.org accounts: Use Google Places for map search
* Update translations
* Dutch - @fvbommel
* French - @FlorianLeChat
* Hungarian - kaciokos
* Indonesian - when we were sober
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Ukrainian - @IhorHordiichuk
### 11.4 (2021-02-09)
* Sync collapsed subtask state with Tasks.org, DAVx⁵, CalDAV, EteSync, and
DecSync ([#1339](https://github.com/tasks/tasks/issues/1339))
* Compatible with Nextcloud and ownCloud
* F-Droid: Add location based reminders ([#770](https://github.com/tasks/tasks/issues/770))
* F-Droid: Replace Mapbox tiles with OpenStreetMap tiles ([#922](https://github.com/tasks/tasks/issues/922))
* Fix default start date ([#1350](https://github.com/tasks/tasks/issues/1350))
### 11.3.4 (2021-02-03)
* Adjust start times by one second during sync
([#1326](https://github.com/tasks/tasks/issues/1326))
* Can now sync start time = due time with DAVx⁵, EteSync app, and DecSync CC
* All day start date must come before all day due date with DAVx⁵, EteSync
app, and DecSync CC
* 'Show unstarted' toggled on by default
### 11.3.3 (2021-01-30)
* Fix all-day due date synchronization
([#1325](https://github.com/tasks/tasks/issues/1325))
### 11.3.2 (2021-01-28)
* Fix recurrence sync issue
([#1323](https://github.com/tasks/tasks/issues/1323))
### 11.3.1 (2021-01-27)
* Improve support for recurring tasks with subtasks
* Subtasks will be unchecked after completing a recurring task
* Clear completed will not delete subtasks of recurring tasks
* Improve widget sort header when space is limited
* Add option to hide widget title
* Fix timezone conversions during synchronization
* Add Esperanto translations - @jakubfabijan
### 11.3 (2021-01-20)
* 'Hide until' is now 'Start date'
* Synchronize start dates with Tasks.org, DAVx⁵, CalDAV, EteSync, and DecSync
* New start date picker
* New start date custom filter criteria
* Add sort 'By start date'
* Display start dates as chips
* Don't perform background sync when data saver enabled
* Preference changes
* Add app and widget preferences to disable start date chips
* Synchronization accounts displayed on main preference screen
* Removed background sync and metered connection options (now respecting data
saver mode)
* Removed Google Tasks 'Custom order synchronization fix' (automatically
performing full sync if 'My order' enabled)
* Remove support for legacy XML backup format ([more info](https://github.com/tasks/tasks/issues/1565))
* Bug fixes
### 11.2.2 (2021-01-07)
* Rename 'Lists' to 'Local lists' to clarify that they are not synchronized
* Tasks.org sign in improvements
* Miscellaneous improvements - Thanks @mhmdanas!
### 11.2.1 (2021-01-05)
* Fix Portuguese translation issue
* Report OpenTask sync errors
* Report Tasks.org sign in errors
* Don't crash on widget configuration error
* Purchase dialog changes
### 11.2 (2020-12-30)
* [Synchronize your Tasks.org account with third-party task and calendar apps, like Outlook,
Thunderbird, or Apple Reminders](https://tasks.org/passwords)
* Miscellaneous improvements - Thanks @mhmdanas!
### 11.1.1 (2020-12-24)
* Fix compatibility issues with third-party clients
* Completed tasks without completion dates
([222a34f](https://github.com/tasks/tasks/commit/222a34fc263816bb23f633bc9c79de78aeb3968d))
* Tasks with start date but no due date
([7a1d566](https://github.com/tasks/tasks/commit/7a1d566bfb613b95d3fe1df46d8fa67200c91021))
* Miscellaneous improvements - Thanks @mhmdanas!
### 11.1 (2020-12-21)
* Add [DecSync CC synchronization](https://tasks.org/decsync)
* Fix rescheduling remotely completed recurring task
([5eb9370](https://github.com/tasks/tasks/commit/5eb9370294ef707b3e667c4a42851030419920d8))
* Miscellaneous code improvements - Thanks @mhmdanas!
### 11.0.1 (2020-12-17)
* Fix EteSync client issue with v2 accounts
([b761309](https://github.com/tasks/tasks/commit/b76130902ae0be6e1d580d588798a9ed0d7ff385))
* Fix multi-select 'Pick time' crash
* Fix default hide until due time
([#842](https://github.com/tasks/tasks/issues/842#issuecomment-746358382))
* Add Croatian translations - Garden Hose
* Add Urdu translations - Maaz
### 11.0 (2020-12-10)
* New Tasks.org synchronization service
* Multi-select rescheduling
* New task default settings
* Default tags
* Default recurrence
* Default location
* Hide until due time
* New custom filter criteria
* Hidden tasks
* Completed tasks
* Subtasks
* Parent tasks
* Recurring tasks
* Added EteSync v2 support
* Deprecated EteSync v1 support
* v1 accounts cannot be added to Tasks.org
* v1 accounts can be added to the EteSync Android client
* Add ability to delete comments (Thanks to @romedius!)
* Add option to always display date (Thanks to @T0M0F!)
* Copy subtasks when copying tasks (Thanks to @supermzn!)
* Fix ring five times cutoff (Thanks to @przemhb!)
* Bug fixes
* Translation updates
* Arabic - @mhmdanas
* Basque - @osoitz, @ppasserini
* Dutch - @fvbommel
* French - @FlorianLeChat
* German - @franconian, J. Lavoie, @myabc
* Hebrew - @yarons
* Hungarian - kaciokos
* Indonesian - @andikatuluspangestu
* Italian - @ppasserini, @Fs00, @pjammo
* Korean - Sunjae Choi, @Hwaro-K
* Norwegian Bokmål - @comradekingu
* Polish - @alex-ter
* Russian - Nikita Epifanov
* Simplified Chinese - @sr093906
* Spanish - @FlorianLeChat
* Traditional Chinese - @realpineapplemilk
* Turkish - @emintufan, Oğuz Ersen
### 10.4.1 (2020-11-09)
* Fix Mapbox Maps crash on Android 11 (F-Droid only)
### 10.4 (2020-10-09)
* New widget configuration options
* Sort
* Show hidden
* Show completed
* Header spacing
* Bug fixes
### 10.3 (2020-10-02)
* Collapsible sort groups in widget
* Add 'System default' widget theme
* Bug fixes
### 10.2 (2020-09-25)
* Display list, tag, and place chips on widgets
* Add option to disable list, tag, and place chips on widgets
### 10.1 (2020-09-23)
* Android 11 support
* Backup improvements
* Swipe-to-refresh initiates DAVx5/EteSync sync
* Show indicator when DAVx5/EteSync are synchronizing
* Bug fixes
### 10.0.3 (2020-09-16)
* Fix crash from calendar event snackbar
* Fix crash when setting Google Maps markers
* Fix invalid calendar entry creation
### 10.0.2 (2020-09-14)
* Fix crash from corrupted custom filter
* Fix crash in 'Astrid manual sorting' mode
* Fix missing 'Calendar event created' snackbar
### 10.0.1 (2020-09-05)
* Bug fixes
* Translation updates
* Czech - @vitSkalicky
* Danish - @ChMunk
### 10.0 (2020-08-31)
* PRO: DAVx⁵ support (requires [DAVx⁵ beta](https://tasks.org/davx5))
* PRO: EteSync client support
* [ToDo Agenda](https://play.google.com/store/apps/details?id=org.andstatus.todoagenda) integration
* Changed backstack behavior to follow Android conventions
* Major internal changes! Please report any bugs!
* Remove Mapbox tiles (Google Play only)
* Added 'Astrid manual sort' information to backup file
* Bug fixes
* Performance improvements
* Security improvements
[Older releases](https://github.com/tasks/tasks/blob/main/V06_09_CHANGELOG.md)

@ -1,38 +1,35 @@
@file:Suppress("UnstableApiUsage")
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.android.application")
id("checkstyle")
alias(libs.plugins.android.application)
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
kotlin("android")
kotlin("kapt")
id("com.cookpad.android.plugin.license-tools") version "1.2.8"
id("com.github.ben-manes.versions") version "0.42.0"
id("com.vanniktech.android.junit.jacoco") version "0.16.0"
id("dagger.hilt.android.plugin")
id("com.google.android.gms.oss-licenses-plugin")
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.ksp)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.compose.compiler)
}
repositories {
mavenCentral()
google()
maven {
url = uri("https://jitpack.io")
content {
includeGroup("com.github.tasks")
includeModule("com.github.bitfireAT", "cert4android")
includeModule("com.github.tasks.opentasks", "opentasks-provider")
includeModule("com.github.QuadFlask", "colorpicker")
includeModule("com.github.twofortyfouram", "android-plugin-api-for-locale")
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
val composeReports = project.properties["composeMetrics"] ?: project.buildDir.absolutePath
freeCompilerArgs = listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${composeReports}/compose-metrics",
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${composeReports}/compose-metrics",
)
}
}
android {
val commonTest = "src/commonTest/java"
sourceSets["test"].java.srcDir(commonTest)
sourceSets["androidTest"].java.srcDirs("src/androidTest/java", commonTest)
bundle {
language {
enableSplit = false
@ -43,6 +40,7 @@ android {
viewBinding = true
dataBinding = true
compose = true
buildConfig = true
}
lint {
@ -51,23 +49,16 @@ android {
textReport = true
}
compileSdk = Versions.compileSdk
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
testApplicationId = "org.tasks.test"
applicationId = "org.tasks"
versionCode = 120701
versionName = "12.7.1"
targetSdk = Versions.targetSdk
minSdk = Versions.minSdk
versionCode = 130908
versionName = "13.9.8"
targetSdk = libs.versions.android.targetSdk.get().toInt()
minSdk = libs.versions.android.minSdk.get().toInt()
testInstrumentationRunner = "org.tasks.TestRunner"
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
}
}
}
signingConfigs {
@ -86,22 +77,15 @@ android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
composeOptions {
kotlinCompilerExtensionVersion = Versions.compose
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "1.8"
}
flavorDimensions += listOf("store")
@Suppress("LocalVariableName")
buildTypes {
getByName("debug") {
debug {
configure<CrashlyticsExtension> {
mappingFileUploadEnabled = false
}
@ -113,9 +97,9 @@ android {
resValue("string", "tasks_caldav_url", tasks_caldav_url ?: "https://caldav.tasks.org")
resValue("string", "tasks_nominatim_url", tasks_caldav_url ?: "https://nominatim.tasks.org")
resValue("string", "tasks_places_url", tasks_caldav_url ?: "https://places.tasks.org")
isTestCoverageEnabled = project.hasProperty("coverage")
enableUnitTestCoverage = project.hasProperty("coverage")
}
getByName("release") {
release {
val tasks_mapbox_key: String? by project
val tasks_google_key: String? by project
resValue("string", "mapbox_key", tasks_mapbox_key ?: "")
@ -131,21 +115,29 @@ android {
dimension = "store"
}
create("googleplay") {
isDefault = true
dimension = "store"
}
}
packagingOptions {
packaging {
resources {
excludes += setOf("META-INF/*.kotlin_module")
excludes += setOf("META-INF/*.kotlin_module", "META-INF/INDEX.LIST")
}
}
namespace = "org.tasks"
}
testOptions {
managedDevices {
localDevices {
create("pixel2api30") {
device = "Pixel 2"
apiLevel = 30
systemImageSource = "aosp-atd"
}
}
}
}
configure<CheckstyleExtension> {
configFile = project.file("google_checks.xml")
toolVersion = "8.16"
namespace = "org.tasks"
}
configurations.all {
@ -162,102 +154,129 @@ val genericImplementation by configurations
val googleplayImplementation by configurations
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
implementation("com.github.tasks:dav4jvm:deb2c9aef8")
implementation("com.github.tasks:ical4android:0e928b567c") {
exclude(group = "com.sun.mail", module = "javax.mail")
implementation(projects.data)
coreLibraryDesugaring(libs.desugar.jdk.libs)
implementation(libs.bitfire.dav4jvm) {
exclude(group = "junit")
exclude(group = "org.ogce", module = "xpp3")
}
implementation("com.github.bitfireAT:cert4android:7814052")
implementation("com.github.tasks.opentasks:opentasks-provider:a1faa1b") {
implementation(libs.bitfire.ical4android) {
exclude(group = "commons-logging")
exclude(group = "org.json", module = "json")
exclude(group = "org.codehaus.groovy", module = "groovy")
exclude(group = "org.codehaus.groovy", module = "groovy-dateutil")
}
implementation(libs.bitfire.cert4android)
implementation(libs.dmfs.opentasks.provider) {
exclude("com.github.tasks.opentasks", "opentasks-contract")
}
implementation(libs.dmfs.rfc5545.datetime)
implementation(libs.dmfs.recur)
implementation(libs.dmfs.jems)
implementation("com.google.dagger:hilt-android:${Versions.hilt}")
kapt("com.google.dagger:hilt-compiler:${Versions.hilt}")
kapt("androidx.hilt:hilt-compiler:${Versions.hilt_androidx}")
implementation("androidx.hilt:hilt-work:${Versions.hilt_androidx}")
implementation(libs.dagger.hilt)
ksp(libs.dagger.hilt.compiler)
ksp(libs.androidx.hilt.compiler)
implementation(libs.androidx.hilt.work)
implementation("androidx.fragment:fragment-ktx:1.4.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifecycle}")
implementation("androidx.room:room-ktx:${Versions.room}")
kapt("androidx.room:room-compiler:${Versions.room}")
implementation("androidx.appcompat:appcompat:1.4.0")
implementation("androidx.paging:paging-runtime:2.1.2")
implementation("io.noties.markwon:core:${Versions.markwon}")
implementation("io.noties.markwon:editor:${Versions.markwon}")
implementation("io.noties.markwon:ext-tasklist:${Versions.markwon}")
implementation("io.noties.markwon:ext-strikethrough:${Versions.markwon}")
implementation("io.noties.markwon:ext-tables:${Versions.markwon}")
implementation("io.noties.markwon:linkify:${Versions.markwon}")
implementation(libs.androidx.fragment.ktx)
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.room)
implementation(libs.androidx.sqlite)
implementation(libs.androidx.appcompat)
implementation(libs.markwon)
implementation(libs.markwon.editor)
implementation(libs.markwon.linkify)
implementation(libs.markwon.strikethrough)
implementation(libs.markwon.tables)
implementation(libs.markwon.tasklist)
debugImplementation("com.facebook.flipper:flipper:${Versions.flipper}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${Versions.flipper}")
debugImplementation("com.facebook.soloader:soloader:0.10.3")
debugImplementation("com.squareup.leakcanary:leakcanary-android:${Versions.leakcanary}")
debugImplementation("androidx.compose.ui:ui-tooling:${Versions.compose}")
debugImplementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlin}")
debugImplementation(libs.facebook.flipper)
debugImplementation(libs.facebook.flipper.network)
debugImplementation(libs.facebook.soloader)
debugImplementation(libs.leakcanary)
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation(libs.kotlin.reflect)
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${Versions.kotlin}")
implementation("com.squareup.okhttp3:okhttp:${Versions.okhttp}")
implementation("com.google.code.gson:gson:2.8.8")
implementation("com.google.android.material:material:1.6.1")
implementation("androidx.constraintlayout:constraintlayout:2.1.2")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.preference:preference:1.1.1")
implementation("com.jakewharton.timber:timber:5.0.1")
implementation("com.google.android.apps.dashclock:dashclock-api:2.0.0")
implementation("com.github.twofortyfouram:android-plugin-api-for-locale:1.0.2") {
implementation(libs.kotlin.jdk8)
implementation(libs.kotlin.immutable)
implementation(libs.kotlinx.serialization)
implementation(libs.okhttp)
implementation(libs.persistent.cookiejar)
implementation(libs.material)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.preference)
implementation(libs.timber)
implementation(libs.dashclock.api)
implementation(libs.locale) {
isTransitive = false
}
implementation("com.rubiconproject.oss:jchronic:0.2.6") {
implementation(libs.jchronic) {
isTransitive = false
}
implementation("me.leolin:ShortcutBadger:1.1.22@aar")
implementation("com.google.apis:google-api-services-tasks:v1-rev20210709-1.32.1")
implementation("com.google.apis:google-api-services-drive:v3-rev20210725-1.32.1")
implementation("com.google.auth:google-auth-library-oauth2-http:0.26.0")
implementation("androidx.work:work-runtime:${Versions.work}")
implementation("androidx.work:work-runtime-ktx:${Versions.work}")
implementation("com.etebase:client:2.3.2")
implementation("com.github.QuadFlask:colorpicker:0.0.15")
implementation("net.openid:appauth:0.8.1")
implementation("org.osmdroid:osmdroid-android:6.1.11@aar")
implementation(libs.shortcut.badger)
implementation(libs.google.api.tasks)
implementation(libs.google.api.drive)
implementation(libs.google.oauth2)
implementation(libs.androidx.work)
implementation(libs.etebase)
implementation(libs.colorpicker)
implementation(libs.appauth)
implementation(libs.osmdroid)
implementation(libs.retrofit)
implementation(libs.retrofit.moshi)
implementation(libs.androidx.recyclerview)
implementation(platform(libs.androidx.compose))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.material:material")
implementation("androidx.compose.runtime:runtime-livedata")
implementation(libs.compose.theme.adapter)
implementation(libs.androidx.activity.compose)
implementation("androidx.compose.material:material-icons-extended")
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation("androidx.compose.ui:ui-viewbinding")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation(libs.coil.compose)
implementation(libs.coil.video)
implementation(libs.coil.svg)
implementation(libs.coil.gif)
implementation("androidx.compose.ui:ui:${Versions.compose}")
implementation("androidx.compose.foundation:foundation:${Versions.compose}")
implementation("androidx.compose.material:material:${Versions.compose}")
implementation("androidx.compose.runtime:runtime-livedata:${Versions.compose}")
implementation("com.google.android.material:compose-theme-adapter:${Versions.compose_theme_adapter}")
implementation("androidx.activity:activity-compose:1.4.0")
implementation("androidx.compose.material:material-icons-extended:${Versions.compose}")
releaseCompileOnly("androidx.compose.ui:ui-tooling:${Versions.compose}")
implementation(libs.accompanist.flowlayout)
implementation(libs.accompanist.permissions)
implementation(libs.accompanist.systemuicontroller)
googleplayImplementation("com.google.firebase:firebase-crashlytics:${Versions.crashlytics}")
googleplayImplementation("com.google.firebase:firebase-analytics:${Versions.analytics}") {
googleplayImplementation(platform(libs.firebase))
googleplayImplementation("com.google.firebase:firebase-crashlytics")
googleplayImplementation("com.google.firebase:firebase-analytics") {
exclude("com.google.android.gms", "play-services-ads-identifier")
}
googleplayImplementation("com.google.firebase:firebase-config-ktx:${Versions.remote_config}")
googleplayImplementation("com.google.android.gms:play-services-location:19.0.1")
googleplayImplementation("com.google.android.gms:play-services-maps:18.0.2")
googleplayImplementation("com.android.billingclient:billing-ktx:3.0.3")
googleplayImplementation("com.google.android.play:core:1.10.3")
googleplayImplementation("com.google.android.play:core-ktx:1.8.1")
googleplayImplementation("com.google.firebase:firebase-config-ktx")
googleplayImplementation(libs.play.services.location)
googleplayImplementation(libs.play.services.maps)
googleplayImplementation(libs.play.billing.ktx)
googleplayImplementation(libs.play.core)
googleplayImplementation(libs.play.core.ktx)
googleplayImplementation(libs.play.services.oss.licenses)
androidTestImplementation("com.google.dagger:hilt-android-testing:${Versions.hilt}")
kaptAndroidTest("com.google.dagger:hilt-compiler:${Versions.hilt}")
kaptAndroidTest("androidx.hilt:hilt-compiler:${Versions.hilt_androidx}")
androidTestImplementation("org.mockito:mockito-android:${Versions.mockito}")
androidTestImplementation("com.natpryce:make-it-easy:${Versions.make_it_easy}")
androidTestImplementation("androidx.test:runner:${Versions.androidx_test}")
androidTestImplementation("androidx.test:rules:${Versions.androidx_test}")
androidTestImplementation("androidx.test.ext:junit:1.1.3")
androidTestImplementation("com.squareup.okhttp3:mockwebserver:${Versions.okhttp}")
androidTestImplementation(libs.dagger.hilt.testing)
kspAndroidTest(libs.dagger.hilt.compiler)
kspAndroidTest(libs.androidx.hilt.compiler)
androidTestImplementation(libs.mockito.android)
androidTestImplementation(libs.make.it.easy)
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.rules)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.okhttp.mockwebserver)
testImplementation("junit:junit:4.13.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.2")
testImplementation("com.natpryce:make-it-easy:${Versions.make_it_easy}")
testImplementation("androidx.test:core:${Versions.androidx_test}")
testImplementation("org.mockito:mockito-core:${Versions.mockito}")
testImplementation("org.ogce:xpp3:1.1.6")
testImplementation(libs.junit)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.make.it.easy)
testImplementation(libs.androidx.test.core)
testImplementation(libs.mockito.core)
testImplementation(libs.xpp3)
}

@ -1,263 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!-- https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-8.16/src/main/resources/google_checks.xml -->
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html.
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name = "Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="100"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation">
<property name="severity" value="ignore" />
</module>
<module name="SummaryJavadoc">
<property name="severity" value="ignore" />
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph">
<property name="severity" value="ignore" />
</module>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="JavadocMethod">
<property name="severity" value="ignore" />
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="severity" value="ignore"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>
</module>
</module>

@ -1,965 +0,0 @@
- artifact: com.github.tasks:dav4jvm:+
name: dav4jvm
copyrightHolder: bitfire web engineering (Ricki Hirner, Bernhard Stockmann)
license: Mozilla Public License, Version 2.0
licenseUrl: https://www.mozilla.org/en-US/MPL/2.0/
- artifact: com.github.tasks:ical4android:+
name: ical4android
copyrightHolder: bitfire web engineering (Ricki Hirner, Bernhard Stockmann)
license: GNU General Public License, Version 3.0
licenseUrl: https://www.gnu.org/licenses/gpl.txt
- artifact: com.github.bitfireAT:cert4android:+
name: cert4android
copyrightHolder: bitfire web engineering (Ricki Hirner, Bernhard Stockmann)
licenseUrl: https://www.gnu.org/licenses/gpl.txt
license: GNU General Public License, Version 3.0
- artifact: androidx.coordinatorlayout:coordinatorlayout:+
name: Android Support Library Coordinator Layout
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.constraintlayout:constraintlayout:+
name: Android ConstraintLayout
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://tools.android.com
- artifact: androidx.sqlite:sqlite:+
name: Android DB
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.google.apis:google-api-services-drive:+
name: Drive API v3-rev136-1.25.0
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: androidx.fragment:fragment:+
name: Android Support Library fragment
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.vectordrawable:vectordrawable-animated:+
name: Android Support AnimatedVectorDrawable
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.core:core:+
name: Android Support Library compat
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.arch.core:core-common:+
name: Android Arch-Common
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.room:room-common:+
name: Android Room-Common
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.room:room-runtime:+
name: Android Room-Runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.google.code.gson:gson:+
name: Gson
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: me.leolin:ShortcutBadger:+
name: ShortcutBadger
copyrightHolder: Leo Lin
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/leolin310148/ShortcutBadger
- artifact: androidx.lifecycle:lifecycle-runtime:+
name: Android Lifecycle Runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.versionedparcelable:versionedparcelable:+
name: VersionedParcelable and friends
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.viewpager:viewpager:+
name: Android Support Library View Pager
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.lifecycle:lifecycle-livedata:+
name: Android Lifecycle LiveData
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: commons-codec:commons-codec:+
name: Apache Commons Codec
copyrightHolder: The Apache Software Foundation
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://commons.apache.org/proper/commons-codec/
- artifact: androidx.annotation:annotation:+
name: Android Support Library Annotations
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.interpolator:interpolator:+
name: Android Support Library Interpolators
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: javax.inject:javax.inject:+
name: javax.inject
copyrightHolder: The JSR-330 Expert Group
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://code.google.com/p/atinject/
- artifact: com.github.twofortyfouram:android-plugin-api-for-locale:+
name: android-plugin-api-for-locale
copyrightHolder: two forty four a.m. LLC.
license: The Apache Software License, Version 2.0
forceGenerate: true
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: androidx.lifecycle:lifecycle-viewmodel:+
name: Android Lifecycle ViewModel
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.google.dagger:dagger:+
name: Dagger
copyrightHolder: The Dagger Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/google/dagger
- artifact: com.google.guava:guava:+
name: Guava Google Core Libraries for Java
copyrightHolder: The Guava Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.jetbrains:annotations:+
name: JetBrains Java Annotations
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/JetBrains/java-annotations
- artifact: org.apache.commons:commons-lang3:+
name: Apache Commons Lang
copyrightHolder: The Apache Software Foundation
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://commons.apache.org/proper/commons-lang/
- artifact: androidx.loader:loader:+
name: Android Support Library loader
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.cursoradapter:cursoradapter:+
name: Android Support Library Cursor Adapter
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.lifecycle:lifecycle-livedata-core:+
name: Android Lifecycle LiveData Core
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.customview:customview:+
name: Android Support Library Custom View
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.swiperefreshlayout:swiperefreshlayout:+
name: Android Support Library Custom View
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.lifecycle:lifecycle-extensions:+
name: Android Lifecycle Extensions
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.arch.core:core-runtime:+
name: Android Arch-Runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: org.apache.commons:commons-collections4:+
name: Apache Commons Collections
copyrightHolder: The Apache Software Foundation
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://commons.apache.org/proper/commons-collections/
- artifact: org.mnode.ical4j:ical4j:+
name: ical4j
copyrightHolder: Ben Fortuna
license: BSD 3-Clause
licenseUrl: https://opensource.org/licenses/BSD-3-Clause
url: http://ical4j.github.io
forceGenerate: true
- artifact: androidx.recyclerview:recyclerview:+
name: Android Support RecyclerView v7
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.collection:collection:+
name: Android Support Library collections
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.cardview:cardview:+
name: Android Support CardView v7
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: com.rubiconproject.oss:jchronic:+
name: jchronic
copyrightHolder: The jchronic authors
license: MIT License
licenseUrl: http://www.opensource.org/licenses/mit-license.php
url: http://github.com/samtingleff/jchronic
- artifact: androidx.sqlite:sqlite-framework:+
name: Android Support SQLite - Framework Implementation
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.google.android.material:material:+
name: Material Components for Android
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: com.google.android.apps.dashclock:dashclock-api:+
name: DashClock API
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://dashclock.com/api
- artifact: androidx.vectordrawable:vectordrawable:+
name: Android Support VectorDrawable
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.work:work-runtime:+
name: Android WorkManager Runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.appcompat:appcompat:+
name: Android AppCompat Library v7
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.lifecycle:lifecycle-common:+
name: Android Lifecycle-Common
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.lifecycle:lifecycle-process:+
name: Android Lifecycle Process
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.lifecycle:lifecycle-service:+
name: Android Lifecycle Service
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.transition:transition:+
name: Android Transition Support Library
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: com.jakewharton.timber:timber:+
name: Timber
copyrightHolder: Jake Wharton
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/JakeWharton/timber
- artifact: com.google.oauth-client:google-oauth-client:+
name: Google OAuth Client Library for Java
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: androidx.drawerlayout:drawerlayout:+
name: Android Support Library Drawer Layout
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: com.google.apis:google-api-services-tasks:+
name: Tasks API v1-rev55-1.25.0
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: com.google.api-client:google-api-client:+
name: Google APIs Client Library for Java
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.jetbrains.kotlin:kotlin-stdlib:+
name: org.jetbrains.kotlin:kotlin-stdlib
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://kotlinlang.org/
- artifact: com.google.http-client:google-http-client:+
name: Google HTTP Client Library for Java
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.slf4j:slf4j-jdk14:+
name: SLF4J JDK14 Binding
copyrightHolder: QOS.ch
license: MIT License
licenseUrl: http://www.opensource.org/licenses/mit-license.php
url: http://www.slf4j.org
- artifact: com.squareup.okhttp3:okhttp:+
name: OkHttp
copyrightHolder: Square, Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.slf4j:slf4j-api:+
name: SLF4J API Module
copyrightHolder: QOS.ch
license: MIT License
licenseUrl: http://www.opensource.org/licenses/mit-license.php
url: http://www.slf4j.org
- artifact: org.jetbrains.kotlin:kotlin-stdlib-common:+
name: org.jetbrains.kotlin:kotlin-stdlib-common
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://kotlinlang.org/
- artifact: com.squareup.okhttp3:logging-interceptor:+
name: OkHttp Logging Interceptor
copyrightHolder: Square, Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.jetbrains.kotlin:kotlin-stdlib-jdk7:+
name: org.jetbrains.kotlin:kotlin-stdlib-jdk7
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://kotlinlang.org/
- artifact: io.grpc:grpc-context:+
name: io.grpc:grpc-context
copyrightHolder: The gRPC Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/grpc/grpc-java
- artifact: com.google.guava:listenablefuture:+
name: Guava ListenableFuture only
copyrightHolder: The Guava Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: io.opencensus:opencensus-api:+
name: OpenCensus API
copyrightHolder: OpenCensus Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/census-instrumentation/opencensus-java
- artifact: com.google.guava:failureaccess:+
name: Guava InternalFutureFailureAccess and InternalFutures
copyrightHolder: The Guava Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: io.opencensus:opencensus-contrib-http-util:+
name: OpenCensus contrib-http-util
copyrightHolder: OpenCensus Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/census-instrumentation/opencensus-java
- artifact: androidx.core:core-ktx:+
name: Core Kotlin Extensions
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.appcompat:appcompat-resources:+
name: Android Resources Library
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.viewpager2:viewpager2:+
name: AndroidX Widget ViewPager2
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.savedstate:savedstate:+
name: Activity
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.activity:activity:+
name: Activity
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.paging:paging-runtime:+
name: Android Paging-Runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.paging:paging-common:+
name: Android Paging-Common
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: org.conscrypt:conscrypt-android:+
name: org.conscrypt:conscrypt-android
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: https://www.apache.org/licenses/LICENSE-2.0
url: https://conscrypt.org/
- artifact: org.jetbrains.kotlinx:kotlinx-coroutines-android:+
name: kotlinx-coroutines-android
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/Kotlin/kotlinx.coroutines
- artifact: androidx.databinding:databinding-adapters:+
name: databinding-adapters
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: androidx.lifecycle:lifecycle-viewmodel-ktx:+
name: Android Lifecycle ViewModel Kotlin Extensions
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.annotation:annotation-experimental:+
name: Experimental annotation
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:+
name: kotlinx-coroutines-core-jvm
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/Kotlin/kotlinx.coroutines
- artifact: androidx.databinding:databinding-common:+
name: Data Binding Base Library
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/studio
- artifact: androidx.databinding:databinding-runtime:+
name: databinding-runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: androidx.databinding:viewbinding:+
name: viewbinding
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: androidx.preference:preference:+
name: AndroidX Preference
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.lifecycle:lifecycle-viewmodel-savedstate:+
name: Android Lifecycle ViewModel with SavedState
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.github.QuadFlask:colorpicker:+
name: QuadFlask/colorpicker
copyrightHolder: QuadFlask
license: The Apache Software License, Version 2.0
url: https://github.com/QuadFlask/colorpicker
- artifact: com.google.auth:google-auth-library-credentials:+
name: Google Auth Library for Java - Credentials
copyrightHolder: Google Inc.
license: BSD 3-Clause
- artifact: com.google.auth:google-auth-library-oauth2-http:+
name: Google Auth Library for Java - OAuth2 HTTP
copyrightHolder: Google Inc.
license: BSD 3-Clause
- artifact: com.google.auto.value:auto-value-annotations:+
name: AutoValue Annotations
copyrightHolder: Google LLC
license: The Apache Software License, Version 2.0
url: https://github.com/google/auto/tree/master/value
- artifact: com.sun.mail:android-mail:+
name: android-mail
copyrightHolder: Oracle and/or its affiliates
license: Eclipse Public License, Version 2.0
- artifact: commons-io:commons-io:+
name: commons-io
copyrightHolder: The Apache Software Foundation
license: The Apache Software License, Version 2.0
url: http://commons.apache.org/proper/commons-io/
- artifact: com.sun.mail:android-activation:+
name: android-activation
copyrightHolder: Oracle and/or its affiliates
license: Eclipse Public License, Version 2.0
- artifact: androidx.hilt:hilt-work:+
name: hilt-work
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.hilt:hilt-common:+
name: hilt-common
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.google.dagger:hilt-android:+
name: hilt-android
copyrightHolder: The Dagger Authors
license: The Apache Software License, Version 2.0
licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/google/dagger
- artifact: com.google.dagger:dagger-lint-aar:+
name: dagger-lint-aar
copyrightHolder: The Dagger Authors
license: The Apache Software License, Version 2.0
licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/google/dagger
- artifact: androidx.room:room-ktx:+
name: room-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.lifecycle:lifecycle-runtime-ktx:+
name: lifecycle-runtime-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.fragment:fragment-ktx:+
name: fragment-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.activity:activity-ktx:+
name: activity-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.collection:collection-ktx:+
name: collection-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.lifecycle:lifecycle-livedata-core-ktx:+
name: lifecycle-livedata-core-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.work:work-runtime-ktx:+
name: work-runtime-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: com.github.tasks.opentasks:opentasks-provider:+
name: opentasks-provider
copyrightHolder: dmfs GmbH
license: The Apache Software License, Version 2.0
licenseUrl: https://api.github.com/licenses/apache-2.0
url: https://github.com/dmfs/opentasks
- artifact: com.github.dmfs.opentasks:opentasks-contract:+
name: opentasks-contract
copyrightHolder: dmfs GmbH
license: The Apache Software License, Version 2.0
licenseUrl: https://api.github.com/licenses/apache-2.0
url: https://github.com/dmfs/opentasks
forceGenerate: true
- artifact: org.dmfs:lib-recur:+
name: lib-recur
copyrightHolder: Marten Gajda
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/license/LICENSE-2.0.txt
url: https://github.com/dmfs/lib-recur
- artifact: org.dmfs:rfc5545-datetime:+
name: rfc5545-datetime
copyrightHolder: Marten Gajda
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/dmfs/rfc5545-datetime
- artifact: org.dmfs:jems:+
name: jems
copyrightHolder: dmfs GmbH
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/license/LICENSE-2.0.txt
url: https://github.com/dmfs/jems
- artifact: com.squareup.okio:okio:+
name: okio
copyrightHolder: Square, Inc.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/square/okio/
- artifact: com.google.dagger:hilt-core:+
name: hilt-core
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: https://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/google/dagger
- artifact: io.noties.markwon:core:+
name: core
copyrightHolder: Dimitry Ivanov
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/noties/Markwon
- artifact: com.atlassian.commonmark:commonmark:+
name: commonmark
copyrightHolder: Atlassian and others
license: BSD 2-Clause
- artifact: androidx.browser:browser:+
name: browser
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: com.etebase:client:+
name: client
copyrightHolder: Tom Hacohen
license: LGPL-3.0-only
licenseUrl: https://spdx.org/licenses/LGPL-3.0-only.html
url: https://www.etebase.com
- artifact: net.openid:appauth:+
name: appauth
copyrightHolder: The AppAuth for Android Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/openid/AppAuth-Android
- artifact: androidx.concurrent:concurrent-futures:+
name: concurrent-futures
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/topic/libraries/architecture/index.html
- artifact: androidx.lifecycle:lifecycle-livedata-ktx:+
name: lifecycle-livedata-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.dynamicanimation:dynamicanimation:+
name: dynamicanimation
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.legacy:legacy-support-core-utils:+
name: legacy-support-core-utils
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.documentfile:documentfile:+
name: documentfile
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.localbroadcastmanager:localbroadcastmanager:+
name: localbroadcastmanager
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: androidx.print:print:+
name: print
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://developer.android.com/tools/extras/support-library.html
- artifact: com.google.http-client:google-http-client-gson:+
name: google-http-client-gson
copyrightHolder: Google Inc.
license: The Apache Software License, Version 2.0
- artifact: org.osmdroid:osmdroid-android:+
name: osmdroid-android
copyrightHolder: The OsmDroid Authors
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0
url: https://github.com/osmdroid/osmdroid
- artifact: androidx.savedstate:savedstate-ktx:+
name: savedstate-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/savedstate#1.1.0
- artifact: androidx.tracing:tracing:+
name: tracing
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/tracing#1.0.0
- artifact: androidx.databinding:databinding-ktx:+
name: databinding-ktx
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
- artifact: org.jetbrains.kotlin:kotlin-stdlib-jdk8:+
name: kotlin-stdlib-jdk8
copyrightHolder: JetBrains s.r.o.
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://kotlinlang.org/
- artifact: androidx.compose.ui:ui:+
name: ui
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-beta01
- artifact: androidx.compose.animation:animation-core:+
name: animation-core
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0-beta01
- artifact: androidx.compose.ui:ui-text:+
name: ui-text
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-beta01
- artifact: androidx.compose.runtime:runtime-saveable:+
name: runtime-saveable
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.0.0-beta01
- artifact: androidx.compose.ui:ui-graphics:+
name: ui-graphics
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-beta01
- artifact: androidx.compose.ui:ui-unit:+
name: ui-unit
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-beta01
- artifact: androidx.compose.ui:ui-geometry:+
name: ui-geometry
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-beta01
- artifact: androidx.compose.ui:ui-util:+
name: ui-util
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-beta01
- artifact: androidx.compose.runtime:runtime:+
name: runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.0.0-beta01
- artifact: androidx.autofill:autofill:+
name: autofill
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx
- artifact: androidx.compose.foundation:foundation:+
name: foundation
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.0.0-beta01
- artifact: androidx.compose.animation:animation:+
name: animation
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0-beta01
- artifact: androidx.compose.foundation:foundation-layout:+
name: foundation-layout
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.0.0-beta01
- artifact: androidx.compose.material:material:+
name: material
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-material#1.0.0-beta01
- artifact: androidx.compose.material:material-ripple:+
name: material-ripple
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-material#1.0.0-beta01
- artifact: androidx.compose.material:material-icons-core:+
name: material-icons-core
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-material#1.0.0-beta01
- artifact: androidx.compose.ui:ui-tooling:+
skip: true
- artifact: androidx.compose.ui:ui-tooling-data:+
skip: true
- artifact: androidx.compose.runtime:runtime-livedata:+
name: runtime-livedata
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.0.0-beta01
- artifact: com.google.android.material:compose-theme-adapter:+
name: compose-theme-adapter
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/material-components/material-components-android-compose-theme-adapter/
- artifact: androidx.constraintlayout:constraintlayout-core:+
name: constraintlayout-core
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: http://tools.android.com
- artifact: androidx.activity:activity-compose:+
name: activity-compose
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/activity#1.3.0-alpha04
- artifact: io.noties.markwon:editor:+
name: editor
copyrightHolder: Dimitry Ivanov
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/noties/Markwon
- artifact: io.noties.markwon:ext-tasklist:+
name: ext-tasklist
copyrightHolder: Dimitry Ivanov
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/noties/Markwon
- artifact: io.noties.markwon:ext-strikethrough:+
name: ext-strikethrough
copyrightHolder: Dimitry Ivanov
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/noties/Markwon
- artifact: com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:+
name: commonmark-ext-gfm-strikethrough
copyrightHolder: Atlassian and others
license: BSD 2-Clause
- artifact: io.noties.markwon:linkify:+
name: linkify
copyrightHolder: Dimitry Ivanov
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/noties/Markwon
- artifact: io.noties.markwon:ext-tables:+
name: ext-tables
copyrightHolder: Dimitry Ivanov
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://github.com/noties/Markwon
- artifact: com.atlassian.commonmark:commonmark-ext-gfm-tables:+
name: commonmark-ext-gfm-tables
copyrightHolder: Atlassian and others
license: BSD 2-Clause
- artifact: androidx.lifecycle:lifecycle-common-java8:+
name: lifecycle-common-java8
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/lifecycle#2.3.0
- artifact: androidx.profileinstaller:profileinstaller:+
name: profileinstaller
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/profileinstaller#1.0.0-beta01
- artifact: androidx.startup:startup-runtime:+
name: startup-runtime
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/startup#1.0.0
- artifact: androidx.compose.ui:ui-tooling-preview:+
name: ui-tooling-preview
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0-rc01
- artifact: androidx.emoji2:emoji2-views-helper:+
name: emoji2-views-helper
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/emoji2#1.0.0
- artifact: androidx.emoji2:emoji2:+
name: emoji2
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/emoji2#1.0.0
- artifact: androidx.resourceinspection:resourceinspection-annotation:+
name: resourceinspection-annotation
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/resourceinspection#1.0.0
- artifact: androidx.compose.material:material-icons-extended:+
name: material-icons-extended
copyrightHolder: Android Open Source Project
license: The Apache Software License, Version 2.0
licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt
url: https://developer.android.com/jetpack/androidx/releases/compose-material#1.1.1

12
app/proguard.pro vendored

@ -16,9 +16,7 @@
-dontwarn javax.inject.**
-dontwarn com.google.j2objc.annotations.**
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn com.google.errorprone.annotations.CanIgnoreReturnValue
-dontwarn com.google.errorprone.annotations.concurrent.LazyInit
-dontwarn com.google.errorprone.annotations.ForOverride
-dontwarn com.google.errorprone.annotations.**
# https://github.com/square/okhttp/blob/0b74bba08805c28f6aede626cf06f213ef6480f2/README.md
-dontwarn okhttp3.**
@ -49,4 +47,10 @@
-dontnote java.nio.file.Files, java.nio.file.Path
-dontnote **.ILicensingService
-dontnote sun.misc.Unsafe
-dontwarn sun.misc.Unsafe
-dontwarn sun.misc.Unsafe
# errors from upgrading to AGP 8
-dontwarn java.beans.Transient
-dontwarn org.joda.convert.FromString
-dontwarn org.joda.convert.ToString
-dontwarn org.json.JSONString

@ -4,7 +4,8 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.api.CaldavFilter
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -14,9 +15,9 @@ import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.R
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery
import org.tasks.injection.InjectingTestCase
@ -40,10 +41,11 @@ class CaldavManualSortTaskAdapterTest : InjectingTestCase() {
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var preferences: Preferences
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var taskMover: TaskMover
private lateinit var adapter: CaldavManualSortTaskAdapter
private val tasks = ArrayList<TaskContainer>()
private val filter = CaldavFilter(CaldavCalendar("calendar", "1234"))
private val filter = CaldavFilter(CaldavCalendar(name = "calendar", uuid = "1234"))
private val dataSource = object : TaskAdapterDataSource {
override fun getItem(position: Int) = tasks[position]
@ -56,7 +58,7 @@ class CaldavManualSortTaskAdapterTest : InjectingTestCase() {
preferences.clear()
preferences.setBoolean(R.string.p_manual_sort, true)
tasks.clear()
adapter = CaldavManualSortTaskAdapter(googleTaskDao, caldavDao, taskDao, localBroadcastManager)
adapter = CaldavManualSortTaskAdapter(googleTaskDao, caldavDao, taskDao, localBroadcastManager, taskMover)
adapter.setDataSource(dataSource)
}
@ -216,7 +218,7 @@ class CaldavManualSortTaskAdapterTest : InjectingTestCase() {
}
private fun move(from: Int, to: Int, indent: Int = 0) = runBlocking {
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter, it) })
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter) })
val adjustedTo = if (from < to) to + 1 else to // match DragAndDropRecyclerAdapter behavior
adapter.moved(from, adjustedTo, indent)
}
@ -224,7 +226,7 @@ class CaldavManualSortTaskAdapterTest : InjectingTestCase() {
private fun checkOrder(dateTime: DateTime, index: Int) = checkOrder(dateTime.toAppleEpoch(), index)
private fun checkOrder(order: Long?, index: Int) = runBlocking {
val sortOrder = caldavDao.getTask(adapter.getTask(index).id)!!.order
val sortOrder = taskDao.fetch(adapter.getTask(index).id)!!.order
if (order == null) {
assertNull(sortOrder)
} else {

@ -3,6 +3,7 @@ package com.todoroo.astrid.adapter
import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -11,6 +12,9 @@ import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.data.*
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskContainerMaker.PARENT
@ -24,6 +28,7 @@ class CaldavTaskAdapterTest : InjectingTestCase() {
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var taskMover: TaskMover
private lateinit var adapter: TaskAdapter
private val tasks = ArrayList<TaskContainer>()
@ -33,7 +38,7 @@ class CaldavTaskAdapterTest : InjectingTestCase() {
super.setUp()
tasks.clear()
adapter = TaskAdapter(false, googleTaskDao, caldavDao, taskDao, localBroadcastManager)
adapter = TaskAdapter(false, googleTaskDao, caldavDao, taskDao, localBroadcastManager, taskMover)
adapter.setDataSource(object : TaskAdapterDataSource {
override fun getItem(position: Int) = tasks[position]
@ -194,22 +199,18 @@ class CaldavTaskAdapterTest : InjectingTestCase() {
private fun addTask(vararg properties: PropertyValue<in TaskContainer?, *>) = runBlocking {
val t = newTaskContainer(*properties)
tasks.add(t)
val task = t.task
taskDao.createNew(task)
val caldavTask = CaldavTask(t.id, "calendar")
val caldavTask = CaldavTask(task = t.id, calendar = "calendar")
if (task.parent > 0) {
caldavTask.remoteParent = caldavDao.getRemoteIdForTask(task.parent)
}
caldavTask.id = caldavDao.insert(caldavTask)
t.caldavTask = caldavTask.toSubset()
}
private fun CaldavTask.toSubset(): SubsetCaldav {
val result = SubsetCaldav()
result.cd_id = id
result.cd_calendar = calendar
result.cd_remote_parent = remoteParent
return result
}
}
tasks.add(
t.copy(
caldavTask = caldavTask.copy(
id = caldavDao.insert(caldavTask)
)
)
)
}
}

@ -4,7 +4,7 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -13,18 +13,17 @@ import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.R
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.Task
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GoogleTaskListMaker.REMOTE_ID
import org.tasks.makers.GoogleTaskListMaker.newGoogleTaskList
import org.tasks.makers.GoogleTaskMaker
import org.tasks.makers.GoogleTaskMaker.LIST
import org.tasks.makers.GoogleTaskMaker.TASK
import org.tasks.makers.GoogleTaskMaker.newGoogleTask
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.newTask
import org.tasks.preferences.Preferences
@ -38,10 +37,11 @@ class GoogleTaskManualSortAdapterTest : InjectingTestCase() {
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Inject lateinit var preferences: Preferences
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var taskMover: TaskMover
private lateinit var adapter: GoogleTaskManualSortAdapter
private val tasks = ArrayList<TaskContainer>()
private val filter = GtasksFilter(newGoogleTaskList(with(REMOTE_ID, "1234")))
private val filter = GtasksFilter(CaldavCalendar(uuid = "1234"))
private val dataSource = object : TaskAdapterDataSource {
override fun getItem(position: Int) = tasks[position]
@ -416,33 +416,33 @@ class GoogleTaskManualSortAdapterTest : InjectingTestCase() {
preferences.clear()
preferences.setBoolean(R.string.p_manual_sort, true)
tasks.clear()
adapter = GoogleTaskManualSortAdapter(googleTaskDao, caldavDao, taskDao, localBroadcastManager)
adapter = GoogleTaskManualSortAdapter(googleTaskDao, caldavDao, taskDao, localBroadcastManager, taskMover)
adapter.setDataSource(dataSource)
}
private fun move(from: Int, to: Int, indent: Int = 0) = runBlocking {
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter, it) })
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter) })
val adjustedTo = if (from < to) to + 1 else to
adapter.moved(from, adjustedTo, indent)
}
private fun checkOrder(order: Long, index: Int, parent: Long = 0) = runBlocking {
val googleTask = googleTaskDao.getByTaskId(adapter.getTask(index).id)!!
val googleTask = taskDao.fetch(adapter.getTask(index).id)!!
assertEquals(order, googleTask.order)
assertEquals(parent, googleTask.parent)
}
private fun addTask(vararg properties: PropertyValue<in Task?, *>): Long = runBlocking {
val task = newTask(*properties)
val parent = task.parent
task.parent = 0
taskDao.createNew(task)
googleTaskDao.insertAndShift(
newGoogleTask(
with(TASK, task.id),
with(LIST, "1234"),
with(GoogleTaskMaker.PARENT, parent)),
false)
task,
newCaldavTask(
with(TASK, task.id),
with(CALENDAR, "1234"),
),
false
)
task.id
}
}

@ -1,78 +0,0 @@
package com.todoroo.astrid.adapter
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.R
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.newTask
import org.tasks.preferences.Preferences
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class NonRecursiveQueryTest : InjectingTestCase() {
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
private lateinit var adapter: TaskAdapter
private val tasks = ArrayList<TaskContainer>()
private val filter = BuiltInFilterExposer.getMyTasksFilter(ApplicationProvider.getApplicationContext<Context>().resources)
private val dataSource = object : TaskAdapterDataSource {
override fun getItem(position: Int) = tasks[position]
override fun getTaskCount() = tasks.size
}
@Before
override fun setUp() {
super.setUp()
preferences.clear()
preferences.setBoolean(R.string.p_use_paged_queries, true)
tasks.clear()
adapter = TaskAdapter(false, googleTaskDao, caldavDao, taskDao, localBroadcastManager)
adapter.setDataSource(dataSource)
}
@Test
fun ignoreSubtasks() {
val parent = addTask()
val child = addTask(with(PARENT, parent))
query()
assertEquals(child, tasks[1].id)
assertEquals(parent, tasks[1].parent)
assertEquals(0, tasks[1].indent)
}
private fun addTask(vararg properties: PropertyValue<in Task?, *>): Long = runBlocking {
val task = newTask(*properties)
taskDao.createNew(task)
task.id
}
private fun query() = runBlocking {
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter, it) })
}
}

@ -6,7 +6,8 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskMover
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -14,8 +15,8 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.TaskContainer
import org.tasks.data.TaskListQuery.getQuery
import org.tasks.injection.InjectingTestCase
@ -33,6 +34,7 @@ class OfflineSubtaskTest : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var taskMover: TaskMover
private lateinit var adapter: TaskAdapter
private val tasks = ArrayList<TaskContainer>()
@ -48,7 +50,7 @@ class OfflineSubtaskTest : InjectingTestCase() {
super.setUp()
preferences.clear()
tasks.clear()
adapter = TaskAdapter(false, googleTaskDao, caldavDao, taskDao, localBroadcastManager)
adapter = TaskAdapter(false, googleTaskDao, caldavDao, taskDao, localBroadcastManager, taskMover)
adapter.setDataSource(dataSource)
}
@ -84,6 +86,6 @@ class OfflineSubtaskTest : InjectingTestCase() {
}
private fun query() = runBlocking {
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter, it) })
tasks.addAll(taskDao.fetchTasks { getQuery(preferences, filter) })
}
}

@ -4,7 +4,7 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -76,7 +76,7 @@ class RecursiveLoopTest : InjectingTestCase() {
}
private suspend fun getTasks() = taskDao.fetchTasks {
getQuery(preferences, BuiltInFilterExposer.getTodayFilter(context.resources), it)
getQuery(preferences, BuiltInFilterExposer.getTodayFilter(context.resources))
}
private suspend fun addTask(vararg properties: PropertyValue<in Task?, *>): Long {

@ -1,106 +1,255 @@
package com.todoroo.astrid.alarms
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.andlib.utility.DateUtilities
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.data.Alarm
import org.tasks.data.Alarm.Companion.TYPE_DATE_TIME
import org.tasks.data.Alarm.Companion.TYPE_RANDOM
import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.Alarm.Companion.whenDue
import org.tasks.data.Alarm.Companion.whenOverdue
import org.tasks.data.AlarmDao
import org.tasks.data.TaskDao
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.data.createDueDate
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Notification
import org.tasks.data.entity.Task
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.jobs.AlarmEntry
import org.tasks.jobs.NotificationQueue
import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.DELETION_TIME
import org.tasks.makers.TaskMaker.DUE_DATE
import org.tasks.makers.TaskMaker.DUE_TIME
import org.tasks.makers.TaskMaker.REMINDER_LAST
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class AlarmJobServiceTest : InjectingTestCase() {
@Inject lateinit var alarmDao: AlarmDao
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var jobs: NotificationQueue
@Inject lateinit var alarmService: AlarmService
@Test
fun scheduleAlarm() = runBlocking {
val task = taskDao.createNew(newTask())
val alarm = insertAlarm(Alarm(task, DateTime(2017, 9, 24, 19, 57).millis, TYPE_DATE_TIME))
verify(AlarmEntry(alarm, task, DateTime(2017, 9, 24, 19, 57).millis, TYPE_DATE_TIME))
fun testNoAlarms() = runBlocking {
testResults(emptyList(), 0)
}
@Test
fun ignoreStaleAlarm() = runBlocking {
val alarmTime = DateTime(2017, 9, 24, 19, 57)
val task = taskDao.createNew(newTask(with(REMINDER_LAST, alarmTime.endOfMinute())))
alarmDao.insert(Alarm(task, alarmTime.millis, TYPE_DATE_TIME))
fun futureAlarmWithNoPastAlarm() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 18).millis
)
)
)
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
verify()
testResults(emptyList(), DateTime(2024, 5, 18, 18, 0).millis)
}
}
@Test
fun dontScheduleReminderForCompletedTask() = runBlocking {
val task = taskDao.insert(
newTask(
with(DUE_DATE, newDateTime()),
with(COMPLETION_TIME, newDateTime())
fun pastAlarmWithNoFutureAlarm() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
testResults(
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
0
)
}
}
@Test
fun pastRecurringAlarmWithFutureRecurrence() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(
Alarm(
type = Alarm.TYPE_REL_END,
repeat = 1,
interval = TimeUnit.HOURS.toMillis(6)
)
)
)
)
alarmDao.insert(whenDue(task))
verify()
testResults(
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
DateTime(2024, 5, 18, 0, 0).millis
)
}
}
@Test
fun dontScheduleReminderForDeletedTask() = runBlocking {
val task = taskDao.insert(
newTask(
with(DUE_DATE, newDateTime()),
with(DELETION_TIME, newDateTime())
fun pastAlarmsRemoveSnoozed() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(
Alarm(type = Alarm.TYPE_REL_END),
Alarm(time = DateTimeUtils2.currentTimeMillis(), type = Alarm.TYPE_SNOOZE)
)
)
)
alarmDao.insert(whenDue(task))
verify()
testResults(
listOf(
Notification(
taskId = 1L,
timestamp = DateTimeUtils2.currentTimeMillis(),
type = Alarm.TYPE_REL_END
)
),
0
)
assertEquals(
listOf(Alarm(id = 1, task = 1, time = 0, type = Alarm.TYPE_REL_END)),
alarmService.getAlarms(1)
)
}
}
@Test
fun snoozeOverridesAll() = runBlocking {
val now = newDateTime()
val task = taskDao.insert(newTask(with(DUE_TIME, now)))
fun futureSnoozeOverrideOverdue() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
)
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(
Alarm(type = Alarm.TYPE_REL_END),
Alarm(
time = DateTimeUtils2.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5),
type = Alarm.TYPE_SNOOZE
)
)
)
alarmDao.insert(whenDue(task))
alarmDao.insert(whenOverdue(task))
alarmDao.insert(Alarm(task, DateUtilities.ONE_HOUR, TYPE_RANDOM))
val alarm = alarmDao.insert(Alarm(task, now.plusMonths(12).millis, TYPE_SNOOZE))
testResults(
emptyList(),
DateTimeUtils2.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5)
)
}
}
verify(AlarmEntry(alarm, task, now.plusMonths(12).millis, TYPE_SNOOZE))
@Test
fun ignoreStaleAlarm() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
),
reminderLast = DateTime(2024, 5, 17, 18, 0).millis,
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
)
testResults(
emptyList(),
0
)
}
}
private suspend fun insertAlarm(alarm: Alarm): Long {
alarm.id = alarmDao.insert(alarm)
return alarm.id
@Test
fun dontScheduleForCompletedTask() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
),
completionDate = DateTime(2024, 5, 17, 14, 0).millis,
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
)
testResults(
emptyList(),
0
)
}
}
private suspend fun verify(vararg alarms: AlarmEntry) {
alarmService.scheduleAllAlarms()
@Test
fun dontScheduleForDeletedTask() = runBlocking {
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
taskDao.insert(
Task(
dueDate = createDueDate(
Task.URGENCY_SPECIFIC_DAY,
DateTime(2024, 5, 17).millis
),
deletionDate = DateTime(2024, 5, 17, 14, 0).millis,
)
)
alarmService.synchronizeAlarms(
1,
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
)
testResults(
emptyList(),
0
)
}
}
assertEquals(alarms.toList(), jobs.getJobs())
private suspend fun testResults(notifications: List<Notification>, nextAlarm: Long) {
val actualNextAlarm = alarmService.triggerAlarms {
assertEquals(notifications, it)
it.forEach { taskDao.setLastNotified(it.taskId, DateTimeUtils2.currentTimeMillis()) }
}
assertEquals(nextAlarm, actualNextAlarm)
}
}

@ -5,8 +5,7 @@
*/
package com.todoroo.astrid.dao
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
@ -15,6 +14,7 @@ import org.junit.Assert.*
import org.junit.Test
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -75,23 +75,23 @@ class TaskDaoTests : InjectingTestCase() {
// create hidden task
task = Task()
task.title = "hidden"
task.hideUntil = DateUtilities.now() + 10000
task.hideUntil = currentTimeMillis() + 10000
taskDao.createNew(task)
// create task with deadlines
task = Task()
task.title = "deadlineInFuture"
task.dueDate = DateUtilities.now() + 10000
task.dueDate = currentTimeMillis() + 10000
taskDao.createNew(task)
task = Task()
task.title = "deadlineInPast"
task.dueDate = DateUtilities.now() - 10000
task.dueDate = currentTimeMillis() - 10000
taskDao.createNew(task)
// create completed task
task = Task()
task.title = "completed"
task.completionDate = DateUtilities.now() - 10000
task.completionDate = currentTimeMillis() - 10000
taskDao.createNew(task)
// check is active

@ -11,14 +11,12 @@ import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.data.GoogleTaskAccount
import org.tasks.data.GoogleTaskListDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GtaskListMaker.ID
import org.tasks.makers.GtaskListMaker.NAME
import org.tasks.makers.GtaskListMaker.REMOTE_ID
import org.tasks.makers.GtaskListMaker.newGtaskList
import org.tasks.makers.RemoteGtaskListMaker
import org.tasks.makers.RemoteGtaskListMaker.newRemoteList
import javax.inject.Inject
@ -29,6 +27,7 @@ class GtasksListServiceTest : InjectingTestCase() {
@Inject lateinit var taskDeleter: TaskDeleter
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var googleTaskListDao: GoogleTaskListDao
@Inject lateinit var caldavDao: CaldavDao
private lateinit var gtasksListService: GtasksListService
@ -44,13 +43,14 @@ class GtasksListServiceTest : InjectingTestCase() {
newRemoteList(
with(RemoteGtaskListMaker.REMOTE_ID, "1"), with(RemoteGtaskListMaker.NAME, "Default")))
assertEquals(
newGtaskList(with(ID, 1L), with(REMOTE_ID, "1"), with(NAME, "Default")),
googleTaskListDao.getById(1L))
CaldavCalendar(id = 1, account = "account", uuid = "1", name = "Default"),
googleTaskListDao.getById(1L)
)
}
@Test
fun testGetListByRemoteId() = runBlocking {
val list = newGtaskList(with(REMOTE_ID, "1"))
val list = CaldavCalendar(uuid = "1")
list.id = googleTaskListDao.insertOrReplace(list)
assertEquals(list, googleTaskListDao.getByRemoteId("1"))
}
@ -62,22 +62,24 @@ class GtasksListServiceTest : InjectingTestCase() {
@Test
fun testDeleteMissingList() = runBlocking {
googleTaskListDao.insertOrReplace(newGtaskList(with(ID, 1L), with(REMOTE_ID, "1")))
googleTaskListDao.insertOrReplace(CaldavCalendar(id = 1, account = "account", uuid = "1"))
val taskList = newRemoteList(with(RemoteGtaskListMaker.REMOTE_ID, "2"))
setLists(taskList)
assertEquals(
listOf(newGtaskList(with(ID, 2L), with(REMOTE_ID, "2"))),
googleTaskListDao.getLists("account"))
listOf(CaldavCalendar(id = 2, account = "account", uuid = "2", name = "Default")),
googleTaskListDao.getLists("account")
)
}
@Test
fun testUpdateListName() = runBlocking {
googleTaskListDao.insertOrReplace(
newGtaskList(with(ID, 1L), with(REMOTE_ID, "1"), with(NAME, "oldName")))
CaldavCalendar(id = 1, uuid = "1", name = "oldName", account = "account")
)
setLists(
newRemoteList(
with(RemoteGtaskListMaker.REMOTE_ID, "1"), with(RemoteGtaskListMaker.NAME, "newName")))
assertEquals("newName", googleTaskListDao.getById(1)!!.title)
assertEquals("newName", googleTaskListDao.getById(1)!!.name)
}
@Test
@ -87,8 +89,11 @@ class GtasksListServiceTest : InjectingTestCase() {
}
private suspend fun setLists(vararg list: TaskList) {
val account = GoogleTaskAccount("account")
googleTaskListDao.insert(account)
val account = CaldavAccount(
username = "account",
uuid = "account",
)
caldavDao.insert(account)
gtasksListService.updateLists(account, listOf(*list))
}
}

@ -1,81 +0,0 @@
/*
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.gtasks
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
import org.tasks.data.GoogleTask
import org.tasks.data.GoogleTaskDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class GtasksMetadataServiceTest : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var googleTaskDao: GoogleTaskDao
private var task: Task? = null
private var metadata: GoogleTask? = null
@Test
fun testMetadataFound() = runBlocking {
givenTask(taskWithMetadata(null))
whenSearchForMetadata()
thenExpectMetadataFound()
}
@Test
fun testMetadataDoesntExist() = runBlocking {
givenTask(taskWithoutMetadata())
whenSearchForMetadata()
thenExpectNoMetadataFound()
}
private fun thenExpectNoMetadataFound() {
assertNull(metadata)
}
private fun thenExpectMetadataFound() {
assertNotNull(metadata)
}
// --- helpers
private suspend fun whenSearchForMetadata() {
metadata = googleTaskDao.getByTaskId(task!!.id)
}
private suspend fun taskWithMetadata(id: String?): Task {
val task = Task()
task.title = "cats"
taskDao.createNew(task)
val metadata = GoogleTask(task.id, "")
if (id != null) {
metadata.remoteId = id
}
metadata.task = task.id
googleTaskDao.insert(metadata)
return task
}
private fun givenTask(taskToTest: Task) {
task = taskToTest
}
private suspend fun taskWithoutMetadata(): Task {
val task = Task()
task.title = "dogs"
taskDao.createNew(task)
return task
}
}

@ -1,7 +1,7 @@
package com.todoroo.astrid.model
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -10,7 +10,7 @@ import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeClock
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.time.DateTimeUtils
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -23,7 +23,7 @@ class TaskTest : InjectingTestCase() {
freezeClock {
val task = Task()
taskDao.createNew(task)
assertEquals(DateTimeUtils.currentTimeMillis(), task.creationDate)
assertEquals(currentTimeMillis(), task.creationDate)
}
}

@ -1,50 +1,68 @@
package com.todoroo.astrid.repeats
import com.natpryce.makeiteasy.MakeItEasy.with
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskCompleter
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.TaskDao
import org.tasks.data.dao.TaskDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.RECUR
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class RepeatWithSubtasksTests : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var repeat: RepeatTaskHelper
@Inject lateinit var taskCompleter: TaskCompleter
@Test
fun uncompleteGrandchildren() = runBlocking {
val grandparent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY")))
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
val grandparent = taskDao.createNew(
Task(
recurrence = "RRULE:FREQ=DAILY"
)
)
val parent = taskDao.createNew(
Task(
parent = grandparent
)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
repeat.handleRepeat(taskDao.fetch(grandparent)!!)
assertTrue(taskDao.fetch(child)!!.isCompleted)
taskCompleter.setComplete(grandparent)
assertFalse(taskDao.fetch(child)!!.isCompleted)
}
@Test
fun uncompleteGoogleTaskChildren() = runBlocking {
val parent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY")))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
val parent = taskDao.createNew(
Task(
recurrence = "RRULE:FREQ=DAILY"
)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
assertTrue(taskDao.fetch(child)!!.isCompleted)
repeat.handleRepeat(taskDao.fetch(parent)!!)
taskCompleter.setComplete(parent)
assertFalse(taskDao.fetch(child)!!.isCompleted)
}

@ -5,14 +5,14 @@
*/
package com.todoroo.astrid.service
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.utility.TitleParser
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.data.TagDataDao
import org.tasks.data.dao.TagDataDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import java.util.*

@ -1,10 +1,12 @@
package com.todoroo.astrid.service
import com.todoroo.astrid.api.PermaSql.*
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.DUE_DATE
import com.todoroo.astrid.data.Task.Companion.HIDE_UNTIL
import com.todoroo.astrid.data.Task.Companion.URGENCY_SPECIFIC_DAY
import com.todoroo.astrid.api.PermaSql.VALUE_EOD
import com.todoroo.astrid.api.PermaSql.VALUE_EOD_NEXT_WEEK
import com.todoroo.astrid.api.PermaSql.VALUE_EOD_TOMORROW
import org.tasks.data.entity.Task
import org.tasks.data.entity.Task.Companion.DUE_DATE
import org.tasks.data.entity.Task.Companion.HIDE_UNTIL
import org.tasks.data.entity.Task.Companion.URGENCY_SPECIFIC_DAY
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -12,6 +14,7 @@ import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.R
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.data.createDueDate
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.preferences.Preferences
@ -35,7 +38,7 @@ class TaskCreatorTest : InjectingTestCase() {
assertEquals(DateTime(2021, 2, 4).millis, task.hideUntil)
assertEquals(
Task.createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis),
createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis),
task.dueDate
)
}
@ -63,7 +66,7 @@ class TaskCreatorTest : InjectingTestCase() {
assertEquals(DateTime(2021, 2, 4).millis, task.hideUntil)
assertEquals(
Task.createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 4).millis),
createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 4).millis),
task.dueDate
)
}
@ -93,7 +96,7 @@ class TaskCreatorTest : InjectingTestCase() {
}
assertEquals(
Task.createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis),
createDueDate(URGENCY_SPECIFIC_DAY, DateTime(2021, 2, 5).millis),
task.dueDate
)
}

@ -1,25 +1,15 @@
package com.todoroo.astrid.service
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.core.BuiltInFilterExposer.Companion.getMyTasksFilter
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.GoogleTaskDao
import org.tasks.data.TaskDao
import org.tasks.data.dao.TaskDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GoogleTaskMaker
import org.tasks.makers.GoogleTaskMaker.TASK
import org.tasks.makers.GoogleTaskMaker.newGoogleTask
import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.RECUR
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -27,111 +17,26 @@ import javax.inject.Inject
class TaskDeleterTest : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var taskDeleter: TaskDeleter
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Test
fun clearCompletedTask() = runBlocking {
val task = taskDao.createNew(newTask(with(COMPLETION_TIME, DateTime())))
fun markTaskAsDeleted() = runBlocking {
val task = Task()
taskDao.createNew(task)
clearCompleted()
taskDeleter.markDeleted(task)
assertTrue(taskDao.fetch(task)!!.isDeleted)
assertTrue(taskDao.fetch(task.id)!!.isDeleted)
}
@Test
fun dontDeleteTaskWithRecurringParent() = runBlocking {
val parent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1")))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
fun dontDeleteReadOnlyTasks() = runBlocking {
val task = Task(
readOnly = true
)
taskDao.createNew(task)
clearCompleted()
taskDeleter.markDeleted(task)
assertFalse(taskDao.fetch(child)!!.isDeleted)
assertFalse(taskDao.fetch(task.id)!!.isDeleted)
}
@Test
fun dontDeleteTaskWithRecurringGrandparent() = runBlocking {
val grandparent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1")))
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
clearCompleted()
assertFalse(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearGrandchildWithNoRecurringAncestors() = runBlocking {
val grandparent = taskDao.createNew(newTask())
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearGrandchildWithCompletedRecurringAncestor() = runBlocking {
val grandparent = taskDao.createNew(newTask(
with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1"),
with(COMPLETION_TIME, DateTime())
))
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
val child = taskDao.createNew(newTask(
with(PARENT, parent),
with(COMPLETION_TIME, DateTime())
))
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun dontClearCompletedGoogleTaskWithRecurringParent() = runBlocking {
val parent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1")))
val child = taskDao.createNew(newTask(with(COMPLETION_TIME, DateTime())))
googleTaskDao.insert(newGoogleTask(with(TASK, child), with(GoogleTaskMaker.PARENT, parent)))
clearCompleted()
assertFalse(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearCompletedGoogleTaskWithNonRecurringParent() = runBlocking {
val parent = taskDao.createNew(newTask())
val child = taskDao.createNew(newTask(with(COMPLETION_TIME, DateTime())))
googleTaskDao.insert(newGoogleTask(with(TASK, child), with(GoogleTaskMaker.PARENT, parent)))
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearCompletedGoogleTaskWithCompletedRecurringParent() = runBlocking {
val parent = taskDao.createNew(newTask(
with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=1"),
with(COMPLETION_TIME, DateTime())
))
val child = taskDao.createNew(newTask(with(COMPLETION_TIME, DateTime())))
googleTaskDao.insert(newGoogleTask(with(TASK, child), with(GoogleTaskMaker.PARENT, parent)))
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
private suspend fun clearCompleted() =
taskDeleter.clearCompleted(getMyTasksFilter(context.resources))
}
}

@ -9,28 +9,24 @@ import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDao
import org.tasks.data.GoogleTaskDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_CALDAV
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_GOOGLE_TASKS
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.jobs.WorkManager
import org.tasks.makers.CaldavCalendarMaker.UUID
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT
import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.GoogleTaskMaker.LIST
import org.tasks.makers.GoogleTaskMaker.PARENT
import org.tasks.makers.GoogleTaskMaker.TASK
import org.tasks.makers.GoogleTaskMaker.newGoogleTask
import org.tasks.makers.GtaskListMaker
import org.tasks.makers.GtaskListMaker.newGtaskList
import org.tasks.makers.TaskMaker
import org.tasks.makers.TaskMaker.ID
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.newTask
import javax.inject.Inject
@ -44,18 +40,28 @@ class TaskMoverTest : InjectingTestCase() {
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var taskMover: TaskMover
@Before
fun setup() {
runBlocking {
caldavDao.insert(CaldavCalendar(uuid = "1", account = "account1"))
caldavDao.insert(CaldavCalendar(uuid = "2", account = "account2"))
}
}
@Test
fun moveBetweenGoogleTaskLists() = runBlocking {
setAccountType("account1", TYPE_GOOGLE_TASKS)
setAccountType("account2", TYPE_GOOGLE_TASKS)
createTasks(1)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
moveToGoogleTasks("2", 1)
assertEquals("2", googleTaskDao.getByTaskId(1)!!.listId)
assertEquals("2", googleTaskDao.getByTaskId(1)?.calendar)
}
@Test
fun deleteGoogleTaskAfterMove() = runBlocking {
createTasks(1)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
moveToGoogleTasks("2", 1)
val deleted = googleTaskDao.getDeletedByTaskId(1)
assertEquals(1, deleted.size.toLong())
@ -65,24 +71,25 @@ class TaskMoverTest : InjectingTestCase() {
@Test
fun moveChildrenBetweenGoogleTaskLists() = runBlocking {
createTasks(1, 2)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(PARENT, 1L)))
setAccountType("account1", TYPE_GOOGLE_TASKS)
setAccountType("account2", TYPE_GOOGLE_TASKS)
createTasks(1)
createSubtask(2, 1)
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 2), with(CALENDAR, "1")))
moveToGoogleTasks("2", 1)
val deleted = googleTaskDao.getDeletedByTaskId(2)
assertEquals(1, deleted.size.toLong())
assertEquals(2, deleted[0].task)
assertTrue(deleted[0].deleted > 0)
val task = googleTaskDao.getByTaskId(2)!!
assertEquals(1, task.parent)
assertEquals("2", task.listId)
assertEquals(1L, taskDao.fetch(2)?.parent)
assertEquals("2", googleTaskDao.getByTaskId(2)?.calendar)
}
@Test
fun moveBetweenCaldavList() = runBlocking {
createTasks(1)
caldavDao.insert(newCaldavCalendar(with(UUID, "1")))
caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1")))
caldavDao.insert(newCaldavTask(with(TASK, 1L), with(CALENDAR, "1")))
moveToCaldavList("2", 1)
assertEquals("2", caldavDao.getTask(1)!!.calendar)
}
@ -90,8 +97,7 @@ class TaskMoverTest : InjectingTestCase() {
@Test
fun deleteCaldavTaskAfterMove() = runBlocking {
createTasks(1)
caldavDao.insert(newCaldavCalendar(with(UUID, "1")))
caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1")))
caldavDao.insert(newCaldavTask(with(TASK, 1L), with(CALENDAR, "1")))
moveToCaldavList("2", 1)
val deleted = caldavDao.getMoved("1")
assertEquals(1, deleted.size.toLong())
@ -104,18 +110,17 @@ class TaskMoverTest : InjectingTestCase() {
createTasks(1)
createSubtask(2, 1)
createSubtask(3, 2)
caldavDao.insert(newCaldavCalendar(with(UUID, "1")))
caldavDao.insert(
listOf(
newCaldavTask(
with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
with(TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
newCaldavTask(
with(CaldavTaskMaker.TASK, 2L),
with(TASK, 2L),
with(CALENDAR, "1"),
with(REMOTE_ID, "b"),
with(REMOTE_PARENT, "a")),
newCaldavTask(
with(CaldavTaskMaker.TASK, 3L),
with(TASK, 3L),
with(CALENDAR, "1"),
with(REMOTE_PARENT, "b"))))
moveToCaldavList("2", 1)
@ -128,13 +133,16 @@ class TaskMoverTest : InjectingTestCase() {
@Test
fun moveGoogleTaskChildrenToCaldav() = runBlocking {
createTasks(1, 2)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(PARENT, 1L)))
setAccountType("account1", TYPE_GOOGLE_TASKS)
setAccountType("account2", TYPE_CALDAV)
createTasks(1)
createSubtask(2, 1)
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 2), with(CALENDAR, "1")))
moveToCaldavList("1", 1)
val task = caldavDao.getTask(2)
assertEquals("1", task!!.calendar)
assertEquals(1, taskDao.fetch(2)!!.parent)
assertEquals(1L, taskDao.fetch(2)?.parent)
}
@Test
@ -143,8 +151,7 @@ class TaskMoverTest : InjectingTestCase() {
createSubtask(2, 1)
createSubtask(3, 2)
moveToGoogleTasks("1", 1)
assertEquals(1, googleTaskDao.getByTaskId(3)!!.parent)
assertEquals(0, taskDao.fetch(3)!!.parent)
assertEquals(1L, taskDao.fetch(3)?.parent)
}
@Test
@ -152,7 +159,7 @@ class TaskMoverTest : InjectingTestCase() {
createTasks(1)
createSubtask(2, 1)
moveToGoogleTasks("1", 2)
assertEquals(0, taskDao.fetch(2)!!.parent)
assertEquals(0L, taskDao.fetch(2)?.parent)
}
@Test
@ -171,43 +178,43 @@ class TaskMoverTest : InjectingTestCase() {
caldavDao.insert(
listOf(
newCaldavTask(
with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
with(TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
newCaldavTask(
with(CaldavTaskMaker.TASK, 2L),
with(TASK, 2L),
with(CALENDAR, "1"),
with(REMOTE_ID, "b"),
with(REMOTE_PARENT, "a")),
newCaldavTask(
with(CaldavTaskMaker.TASK, 3L),
with(TASK, 3L),
with(CALENDAR, "1"),
with(REMOTE_PARENT, "b"))))
moveToGoogleTasks("1", 1)
val task = googleTaskDao.getByTaskId(3L)!!
assertEquals(1, task.parent)
val task = taskDao.fetch(3L)
assertEquals(1L, task?.parent)
}
@Test
fun moveGoogleTaskChildWithoutParent() = runBlocking {
createTasks(1, 2)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(PARENT, 1L)))
setAccountType("account2", TYPE_GOOGLE_TASKS)
createTasks(1)
createSubtask(2, 1)
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 2), with(CALENDAR, "1")))
moveToGoogleTasks("2", 2)
val task = googleTaskDao.getByTaskId(2)!!
assertEquals(0L, task.parent)
assertEquals("2", task.listId)
assertEquals(0L, taskDao.fetch(2)?.parent)
assertEquals("2", googleTaskDao.getByTaskId(2)?.calendar)
}
@Test
fun moveCaldavChildWithoutParent() = runBlocking {
createTasks(1)
createSubtask(2, 1)
caldavDao.insert(newCaldavCalendar(with(UUID, "1")))
caldavDao.insert(
listOf(
newCaldavTask(
with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
with(TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
newCaldavTask(
with(CaldavTaskMaker.TASK, 2L),
with(TASK, 2L),
with(CALENDAR, "1"),
with(REMOTE_PARENT, "a"))))
moveToCaldavList("2", 2)
@ -218,17 +225,19 @@ class TaskMoverTest : InjectingTestCase() {
@Test
fun moveGoogleTaskToCaldav() = runBlocking {
createTasks(1)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
moveToCaldavList("2", 1)
assertEquals("2", caldavDao.getTask(1)!!.calendar)
}
@Test
fun moveCaldavToGoogleTask() = runBlocking {
setAccountType("account1", TYPE_CALDAV)
setAccountType("account2", TYPE_GOOGLE_TASKS)
createTasks(1)
caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1")))
caldavDao.insert(newCaldavTask(with(TASK, 1L), with(CALENDAR, "1")))
moveToGoogleTasks("2", 1)
assertEquals("2", googleTaskDao.getByTaskId(1L)!!.listId)
assertEquals("2", googleTaskDao.getByTaskId(1L)?.calendar)
}
@Test
@ -237,14 +246,15 @@ class TaskMoverTest : InjectingTestCase() {
createSubtask(2, 1)
createSubtask(3, 2)
moveToCaldavList("1", 1)
assertEquals("1", caldavDao.getTask(3)!!.calendar)
assertEquals(2, taskDao.fetch(3)!!.parent)
assertEquals("1", caldavDao.getTask(3)?.calendar)
assertEquals(2L, taskDao.fetch(3)?.parent)
}
@Test
fun moveToSameGoogleTaskListIsNoop() = runBlocking {
setAccountType("account1", TYPE_GOOGLE_TASKS)
createTasks(1)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
moveToGoogleTasks("1", 1)
assertTrue(googleTaskDao.getDeletedByTaskId(1).isEmpty())
assertEquals(1, googleTaskDao.getAllByTaskId(1).size.toLong())
@ -253,7 +263,7 @@ class TaskMoverTest : InjectingTestCase() {
@Test
fun moveToSameCaldavListIsNoop() = runBlocking {
createTasks(1)
caldavDao.insert(newCaldavTask(with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1")))
caldavDao.insert(newCaldavTask(with(TASK, 1L), with(CALENDAR, "1")))
moveToCaldavList("1", 1)
assertTrue(caldavDao.getMoved("1").isEmpty())
assertEquals(1, caldavDao.getTasks(1).size.toLong())
@ -261,9 +271,10 @@ class TaskMoverTest : InjectingTestCase() {
@Test
fun dontDuplicateWhenParentAndChildGoogleTaskMoved() = runBlocking {
createTasks(1, 2)
googleTaskDao.insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
googleTaskDao.insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(PARENT, 1L)))
createTasks(1)
createSubtask(2, 1)
googleTaskDao.insert(newCaldavTask(with(TASK, 1), with(CALENDAR, "1")))
googleTaskDao.insert(newCaldavTask(with(TASK, 2), with(CALENDAR, "1")))
moveToGoogleTasks("2", 1, 2)
assertEquals(1, googleTaskDao.getAllByTaskId(2).filter { it.deleted == 0L }.size)
}
@ -272,13 +283,12 @@ class TaskMoverTest : InjectingTestCase() {
fun dontDuplicateWhenParentAndChildCaldavMoved() = runBlocking {
createTasks(1)
createSubtask(2, 1)
caldavDao.insert(newCaldavCalendar(with(UUID, "1")))
caldavDao.insert(
listOf(
newCaldavTask(
with(CaldavTaskMaker.TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
with(TASK, 1L), with(CALENDAR, "1"), with(REMOTE_ID, "a")),
newCaldavTask(
with(CaldavTaskMaker.TASK, 2L),
with(TASK, 2L),
with(CALENDAR, "1"),
with(REMOTE_PARENT, "a"))))
moveToCaldavList("2", 1, 2)
@ -292,14 +302,23 @@ class TaskMoverTest : InjectingTestCase() {
}
private suspend fun createSubtask(id: Long, parent: Long) {
taskDao.createNew(newTask(with(ID, id), with(TaskMaker.PARENT, parent)))
taskDao.createNew(newTask(with(ID, id), with(PARENT, parent)))
}
private suspend fun moveToGoogleTasks(list: String, vararg tasks: Long) {
taskMover.move(tasks.toList(), GtasksFilter(newGtaskList(with(GtaskListMaker.REMOTE_ID, list))))
taskMover.move(tasks.toList(), GtasksFilter(CaldavCalendar(uuid = list)))
}
private suspend fun moveToCaldavList(calendar: String, vararg tasks: Long) {
taskMover.move(tasks.toList(), CaldavFilter(CaldavCalendar("", calendar)))
taskMover.move(tasks.toList(), CaldavFilter(CaldavCalendar(name = "", uuid = calendar)))
}
private suspend fun setAccountType(account: String, type: Int) {
caldavDao.insert(
CaldavAccount(
uuid = account,
accountType = type,
)
)
}
}

@ -5,7 +5,7 @@
*/
package com.todoroo.astrid.service
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.utility.TitleParser
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
@ -16,7 +16,7 @@ import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.tasks.R
import org.tasks.data.TagDataDao
import org.tasks.data.dao.TagDataDao
import org.tasks.date.DateTimeUtils
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule

@ -3,7 +3,6 @@
package com.todoroo.astrid.service
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -12,12 +11,12 @@ import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.TestUtilities.assertEquals
import org.tasks.caldav.VtodoCache
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDao
import org.tasks.data.TaskDao
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.Task
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavCalendarMaker.newCaldavCalendar
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.TASK
@ -44,7 +43,7 @@ class Upgrade_11_3_Test : InjectingTestCase() {
@Before
override fun setUp() {
super.setUp()
calendar = newCaldavCalendar()
calendar = CaldavCalendar()
runBlocking {
caldavDao.insert(calendar)
}

@ -1,13 +1,13 @@
package com.todoroo.astrid.subtasks
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.tasks.data.TaskListMetadata
import org.tasks.data.entity.TaskListMetadata
import org.tasks.injection.ProductionModule
@UninstallModules(ProductionModule::class)

@ -1,12 +1,12 @@
package com.todoroo.astrid.subtasks
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.tasks.data.TaskListMetadata
import org.tasks.data.entity.TaskListMetadata
import org.tasks.injection.ProductionModule
@UninstallModules(ProductionModule::class)

@ -1,20 +1,20 @@
package com.todoroo.astrid.subtasks
import androidx.test.InstrumentationRegistry
import com.todoroo.astrid.api.Filter
import com.todoroo.astrid.api.AstridOrderingFilter
import com.todoroo.astrid.core.BuiltInFilterExposer
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.tasks.data.TaskListMetadataDao
import org.tasks.data.dao.TaskListMetadataDao
import org.tasks.injection.InjectingTestCase
import org.tasks.preferences.Preferences
import javax.inject.Inject
abstract class SubtasksTestCase : InjectingTestCase() {
lateinit var updater: SubtasksFilterUpdater
lateinit var filter: Filter
lateinit var filter: AstridOrderingFilter
@Inject lateinit var taskListMetadataDao: TaskListMetadataDao
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences

@ -1,9 +1,9 @@
package com.todoroo.astrid.sync
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.TagData
import org.tasks.data.TagDataDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.TagData
import org.tasks.data.entity.Task
import org.tasks.injection.InjectingTestCase
import javax.inject.Inject
@ -12,17 +12,17 @@ open class NewSyncTestCase : InjectingTestCase() {
@Inject lateinit var tagDataDao: TagDataDao
suspend fun createTask(): Task {
val task = Task()
task.title = SYNC_TASK_TITLE
task.priority = SYNC_TASK_IMPORTANCE
val task = Task(
title = SYNC_TASK_TITLE,
priority = SYNC_TASK_IMPORTANCE,
)
taskDao.createNew(task)
return task
}
suspend fun createTagData(): TagData {
val tag = TagData()
tag.name = "new tag"
tagDataDao.createNew(tag)
val tag = TagData(name = "new tag")
tagDataDao.insert(tag)
return tag
}

@ -1,6 +1,6 @@
package com.todoroo.astrid.sync
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking

@ -0,0 +1 @@
../../../../test/java/org/tasks/Freeze.kt

@ -0,0 +1 @@
../../../../test/java/org/tasks/SuspendFreeze.kt

@ -0,0 +1 @@
../../../../test/java/org/tasks/TestUtilities.kt

@ -1,15 +1,15 @@
package org.tasks.caldav
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.ETAG
@ -25,12 +25,13 @@ class CaldavSynchronizerTest : CaldavTest() {
@Before
override fun setUp() = runBlocking {
super.setUp()
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
username = "username"
password = encryption.encrypt("password")
url = server.url("/remote.php/dav/calendars/user1/").toString()
id = caldavDao.insert(this)
account = CaldavAccount(
uuid = UUIDHelper.newUUID(),
username = "username",
password = encryption.encrypt("password"),
url = server.url("/remote.php/dav/calendars/user1/").toString(),
).let {
it.copy(id = caldavDao.insert(it))
}
}
@ -45,11 +46,13 @@ class CaldavSynchronizerTest : CaldavTest() {
@Test
fun dontFetchCalendarIfCtagMatches() = runBlocking {
caldavDao.insert(CaldavCalendar().apply {
account = this@CaldavSynchronizerTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@CaldavSynchronizerTest.account.url}test-shared/"
})
caldavDao.insert(
CaldavCalendar(
account = this@CaldavSynchronizerTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@CaldavSynchronizerTest.account.url}test-shared/",
)
)
enqueue(OC_SHARE_PROPFIND)
sync()
@ -57,12 +60,12 @@ class CaldavSynchronizerTest : CaldavTest() {
@Test
fun dontFetchTaskIfEtagMatches() = runBlocking {
val calendar = CaldavCalendar().apply {
account = this@CaldavSynchronizerTest.account.uuid
uuid = UUIDHelper.newUUID()
url = "${this@CaldavSynchronizerTest.account.url}test-shared/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@CaldavSynchronizerTest.account.uuid,
uuid = UUIDHelper.newUUID(),
url = "${this@CaldavSynchronizerTest.account.url}test-shared/",
)
caldavDao.insert(calendar)
caldavDao.insert(newCaldavTask(
with(TASK, taskDao.insert(newTask())),
with(OBJECT, "3164728546640386952.ics"),

@ -9,8 +9,8 @@ import org.junit.Before
import org.junit.Rule
import org.junit.rules.Timeout
import org.tasks.R
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.dao.CaldavDao
import org.tasks.injection.InjectingTestCase
import org.tasks.preferences.Preferences
import org.tasks.security.KeyStoreEncryption

@ -1,19 +1,19 @@
package org.tasks.caldav
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavAccount.Companion.SERVER_OPEN_XCHANGE
import org.tasks.data.CaldavAccount.Companion.SERVER_OWNCLOUD
import org.tasks.data.CaldavAccount.Companion.SERVER_SABREDAV
import org.tasks.data.CaldavAccount.Companion.SERVER_TASKS
import org.tasks.data.CaldavAccount.Companion.SERVER_UNKNOWN
import org.tasks.data.CaldavAccount.Companion.TYPE_CALDAV
import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_OPEN_XCHANGE
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_OWNCLOUD
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_SABREDAV
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_TASKS
import org.tasks.data.entity.CaldavAccount.Companion.SERVER_UNKNOWN
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_CALDAV
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_TASKS
import org.tasks.injection.ProductionModule
@UninstallModules(ProductionModule::class)
@ -79,13 +79,14 @@ class ServerDetectionTest : CaldavTest() {
vararg headers: Pair<String, String>,
accountType: Int = TYPE_CALDAV
) {
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
username = "username"
password = encryption.encrypt("password")
url = server.url("/remote.php/dav/calendars/user1/").toString()
id = caldavDao.insert(this)
this.accountType = accountType
account = CaldavAccount(
uuid = UUIDHelper.newUUID(),
username = "username",
password = encryption.encrypt("password"),
url = server.url("/remote.php/dav/calendars/user1/").toString(),
accountType = accountType,
).let {
it.copy(id = caldavDao.insert(it))
}
this.headers.putAll(headers)
enqueue(NO_CALENDARS)

@ -1,16 +1,16 @@
package org.tasks.caldav
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.PrincipalDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.dao.PrincipalDao
import org.tasks.injection.ProductionModule
import javax.inject.Inject
@ -22,19 +22,20 @@ class SharingMailboxDotOrgTest : CaldavTest() {
@Test
fun ownerAccess() = runBlocking {
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
username = "3"
password = encryption.encrypt("password")
url = server.url("/caldav/").toString()
id = caldavDao.insert(this)
}
val calendar = CaldavCalendar().apply {
account = this@SharingMailboxDotOrgTest.account.uuid
ctag = "1614876450015"
url = "${this@SharingMailboxDotOrgTest.account.url}MzM/"
caldavDao.insert(this)
account = CaldavAccount(
uuid = UUIDHelper.newUUID(),
username = "3",
password = encryption.encrypt("password"),
url = server.url("/caldav/").toString(),
).let {
it.copy(id = caldavDao.insert(it))
}
val calendar = CaldavCalendar(
account = this@SharingMailboxDotOrgTest.account.uuid,
ctag = "1614876450015",
url = "${this@SharingMailboxDotOrgTest.account.url}MzM/",
)
caldavDao.insert(calendar)
enqueue(SHARE_OWNER)
sync()
@ -45,19 +46,20 @@ class SharingMailboxDotOrgTest : CaldavTest() {
@Test
fun principalForSharee() = runBlocking {
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
username = "3"
password = encryption.encrypt("password")
url = server.url("/caldav/").toString()
id = caldavDao.insert(this)
}
val calendar = CaldavCalendar().apply {
account = this@SharingMailboxDotOrgTest.account.uuid
ctag = "1614876450015"
url = "${this@SharingMailboxDotOrgTest.account.url}MzM/"
caldavDao.insert(this)
account = CaldavAccount(
uuid = UUIDHelper.newUUID(),
username = "3",
password = encryption.encrypt("password"),
url = server.url("/caldav/").toString(),
).let {
it.copy(id = caldavDao.insert(it))
}
val calendar = CaldavCalendar(
account = this@SharingMailboxDotOrgTest.account.uuid,
ctag = "1614876450015",
url = "${this@SharingMailboxDotOrgTest.account.url}MzM/",
)
caldavDao.insert(calendar)
enqueue(SHARE_OWNER)
sync()

@ -1,16 +1,16 @@
package org.tasks.caldav
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Test
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavCalendar.Companion.ACCESS_OWNER
import org.tasks.data.CaldavCalendar.Companion.ACCESS_READ_ONLY
import org.tasks.data.PrincipalDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_OWNER
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_ONLY
import org.tasks.data.dao.PrincipalDao
import org.tasks.injection.ProductionModule
import javax.inject.Inject
@ -21,24 +21,25 @@ class SharingOwncloudTest : CaldavTest() {
@Inject lateinit var principalDao: PrincipalDao
private suspend fun setupAccount(user: String) {
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
username = user
password = encryption.encrypt("password")
url = server.url("/remote.php/dav/calendars/$user/").toString()
id = caldavDao.insert(this)
account = CaldavAccount(
uuid = UUIDHelper.newUUID(),
username = user,
password = encryption.encrypt("password"),
url = server.url("/remote.php/dav/calendars/$user/").toString(),
).let {
it.copy(id = caldavDao.insert(it))
}
}
@Test
fun calendarOwner() = runBlocking {
setupAccount("user1")
val calendar = CaldavCalendar().apply {
account = this@SharingOwncloudTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingOwncloudTest.account.url}test-shared/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingOwncloudTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@SharingOwncloudTest.account.url}test-shared/",
)
caldavDao.insert(calendar)
enqueue(OC_OWNER)
sync()
@ -49,12 +50,12 @@ class SharingOwncloudTest : CaldavTest() {
@Test
fun readOnly() = runBlocking {
setupAccount("user2")
val calendar = CaldavCalendar().apply {
account = this@SharingOwncloudTest.account.uuid
ctag = "http://sabre.io/ns/sync/2"
url = "${this@SharingOwncloudTest.account.url}test-shared_shared_by_user1/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingOwncloudTest.account.uuid,
ctag = "http://sabre.io/ns/sync/2",
url = "${this@SharingOwncloudTest.account.url}test-shared_shared_by_user1/",
)
caldavDao.insert(calendar)
enqueue(OC_READ_ONLY)
sync()
@ -65,12 +66,12 @@ class SharingOwncloudTest : CaldavTest() {
@Test
fun principalForSharee() = runBlocking {
setupAccount("user1")
val calendar = CaldavCalendar().apply {
account = this@SharingOwncloudTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingOwncloudTest.account.url}test-shared/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingOwncloudTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@SharingOwncloudTest.account.url}test-shared/",
)
caldavDao.insert(calendar)
enqueue(OC_OWNER)
sync()
@ -89,12 +90,12 @@ class SharingOwncloudTest : CaldavTest() {
@Test
fun principalForOwner() = runBlocking {
setupAccount("user2")
val calendar = CaldavCalendar().apply {
account = this@SharingOwncloudTest.account.uuid
ctag = "http://sabre.io/ns/sync/2"
url = "${this@SharingOwncloudTest.account.url}test-shared_shared_by_user1/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingOwncloudTest.account.uuid,
ctag = "http://sabre.io/ns/sync/2",
url = "${this@SharingOwncloudTest.account.url}test-shared_shared_by_user1/",
)
caldavDao.insert(calendar)
enqueue(OC_READ_ONLY)
sync()

@ -1,18 +1,18 @@
package org.tasks.caldav
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavCalendar.Companion.ACCESS_OWNER
import org.tasks.data.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.CaldavCalendar.Companion.INVITE_ACCEPTED
import org.tasks.data.PrincipalDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_OWNER
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.entity.CaldavCalendar.Companion.INVITE_ACCEPTED
import org.tasks.data.dao.PrincipalDao
import org.tasks.injection.ProductionModule
import javax.inject.Inject
@ -23,24 +23,25 @@ class SharingSabredavTest : CaldavTest() {
@Inject lateinit var principalDao: PrincipalDao
private suspend fun setupAccount(user: String) {
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
username = user
password = encryption.encrypt("password")
url = server.url("/calendars/$user/").toString()
id = caldavDao.insert(this)
account = CaldavAccount(
uuid = UUIDHelper.newUUID(),
username = user,
password = encryption.encrypt("password"),
url = server.url("/calendars/$user/").toString(),
).let {
it.copy(id = caldavDao.insert(it))
}
}
@Test
fun calendarOwner() = runBlocking {
setupAccount("user1")
val calendar = CaldavCalendar().apply {
account = this@SharingSabredavTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingSabredavTest.account.url}940468858232147861/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingSabredavTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@SharingSabredavTest.account.url}940468858232147861/",
)
caldavDao.insert(calendar)
enqueue(SD_OWNER)
sync()
@ -54,12 +55,12 @@ class SharingSabredavTest : CaldavTest() {
@Test
fun calendarSharee() = runBlocking {
setupAccount("user2")
val calendar = CaldavCalendar().apply {
account = this@SharingSabredavTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingSabredavTest.account.url}c3853d69-cb7a-476c-a23b-30ffd70f110b/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingSabredavTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@SharingSabredavTest.account.url}c3853d69-cb7a-476c-a23b-30ffd70f110b/",
)
caldavDao.insert(calendar)
enqueue(SD_SHAREE)
sync()
@ -73,12 +74,13 @@ class SharingSabredavTest : CaldavTest() {
@Test
fun excludeCurrentUserPrincipalFromSharees() = runBlocking {
setupAccount("user1")
CaldavCalendar().apply {
account = this@SharingSabredavTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingSabredavTest.account.url}940468858232147861/"
caldavDao.insert(this)
}
caldavDao.insert(
CaldavCalendar(
account = account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${account.url}940468858232147861/",
)
)
enqueue(SD_OWNER)
sync()
@ -89,12 +91,12 @@ class SharingSabredavTest : CaldavTest() {
@Test
fun principalForSharee() = runBlocking {
setupAccount("user1")
val calendar = CaldavCalendar().apply {
account = this@SharingSabredavTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingSabredavTest.account.url}940468858232147861/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingSabredavTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@SharingSabredavTest.account.url}940468858232147861/",
)
caldavDao.insert(calendar)
enqueue(SD_OWNER)
sync()
@ -111,12 +113,12 @@ class SharingSabredavTest : CaldavTest() {
@Test
fun principalForOwner() = runBlocking {
setupAccount("user2")
val calendar = CaldavCalendar().apply {
account = this@SharingSabredavTest.account.uuid
ctag = "http://sabre.io/ns/sync/1"
url = "${this@SharingSabredavTest.account.url}c3853d69-cb7a-476c-a23b-30ffd70f110b/"
caldavDao.insert(this)
}
val calendar = CaldavCalendar(
account = this@SharingSabredavTest.account.uuid,
ctag = "http://sabre.io/ns/sync/1",
url = "${this@SharingSabredavTest.account.url}c3853d69-cb7a-476c-a23b-30ffd70f110b/",
)
caldavDao.insert(calendar)
enqueue(SD_SHAREE)
sync()

@ -2,7 +2,6 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.andlib.utility.DateUtilities.now
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -10,11 +9,15 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskContainerMaker
import org.tasks.makers.TaskContainerMaker.CREATED
import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -101,22 +104,24 @@ class CaldavDaoShiftTests : InjectingTestCase() {
fun ignoreMovedTasksWhenShiftingDown() = runBlocking {
val created = DateTime(2020, 5, 17, 9, 53, 17)
addTask(with(CREATED, created))
caldavDao.update(caldavDao.getTask(tasks[0].id).apply { this?.deleted = now() }!!)
caldavDao.update(caldavDao.getTask(tasks[0].id).apply { this?.deleted =
currentTimeMillis()
}!!)
caldavDao.shiftDown("calendar", 0, created.toAppleEpoch())
assertNull(caldavDao.getTasks(tasks[0].id)[0].order)
assertNull(taskDao.fetch(tasks[0].id)!!.order)
}
@Test
fun ignoreDeletedTasksWhenShiftingDown() = runBlocking {
val created = DateTime(2020, 5, 17, 9, 53, 17)
addTask(with(CREATED, created))
taskDao.update(taskDao.fetch(tasks[0].id).apply { this?.deletionDate = now() }!!)
taskDao.update(taskDao.fetch(tasks[0].id).apply { this?.deletionDate = currentTimeMillis() }!!)
caldavDao.shiftDown("calendar", 0, created.toAppleEpoch())
assertNull(caldavDao.getTasks(tasks[0].id)[0].order)
assertNull(taskDao.fetch(tasks[0].id)!!.order)
}
@Test
@ -134,10 +139,11 @@ class CaldavDaoShiftTests : InjectingTestCase() {
}
private suspend fun checkOrder(dateTime: DateTime?, task: TaskContainer) {
val order = taskDao.fetch(task.id)!!.order
if (dateTime == null) {
assertNull(caldavDao.getTask(task.id)!!.order)
assertNull(order)
} else {
assertEquals(dateTime.toAppleEpoch(), caldavDao.getTask(task.id)!!.order)
assertEquals(dateTime.toAppleEpoch(), order)
}
}
@ -145,22 +151,18 @@ class CaldavDaoShiftTests : InjectingTestCase() {
private suspend fun addTask(calendar: String, vararg properties: PropertyValue<in TaskContainer?, *>) {
val t = TaskContainerMaker.newTaskContainer(*properties)
tasks.add(t)
val task = t.task
taskDao.createNew(task)
val caldavTask = CaldavTask(t.id, calendar)
val caldavTask = CaldavTask(task = t.id, calendar = calendar)
if (task.parent > 0) {
caldavTask.remoteParent = caldavDao.getRemoteIdForTask(task.parent)
}
caldavTask.id = caldavDao.insert(caldavTask)
t.caldavTask = caldavTask.toSubset()
tasks.add(
t.copy(
caldavTask = caldavTask.copy(
id = caldavDao.insert(caldavTask)
)
)
)
}
private fun CaldavTask.toSubset(): SubsetCaldav {
val result = SubsetCaldav()
result.cd_id = id
result.cd_calendar = calendar
result.cd_remote_parent = remoteParent
return result
}
}
}

@ -2,12 +2,18 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.CREATION_TIME
@ -27,8 +33,7 @@ class CaldavDaoTests : InjectingTestCase() {
fun insertNewTaskAtTopOfEmptyList() = runBlocking {
val task = newTask()
taskDao.createNew(task)
val caldavTask = CaldavTask(task.id, "calendar")
caldavDao.insert(task, caldavTask, true)
caldavDao.insert(task, CaldavTask(task = task.id, calendar = "calendar"), true)
checkOrder(null, task.id)
}
@ -40,9 +45,8 @@ class CaldavDaoTests : InjectingTestCase() {
val second = newTask(with(CREATION_TIME, created.plusSeconds(1)))
taskDao.createNew(first)
taskDao.createNew(second)
caldavDao.insert(first, CaldavTask(first.id, "calendar"), true)
caldavDao.insert(second, CaldavTask(second.id, "calendar"), true)
caldavDao.insert(first, CaldavTask(task = first.id, calendar = "calendar"), true)
caldavDao.insert(second, CaldavTask(task = second.id, calendar = "calendar"), true)
checkOrder(null, first.id)
checkOrder(created.minusSeconds(1), second.id)
@ -55,9 +59,8 @@ class CaldavDaoTests : InjectingTestCase() {
val second = newTask(with(CREATION_TIME, created.plusSeconds(1)))
taskDao.createNew(first)
taskDao.createNew(second)
caldavDao.insert(first, CaldavTask(first.id, "calendar"), false)
caldavDao.insert(second, CaldavTask(second.id, "calendar"), false)
caldavDao.insert(first, CaldavTask(task = first.id, calendar = "calendar"), false)
caldavDao.insert(second, CaldavTask(task = second.id, calendar = "calendar"), false)
checkOrder(null, first.id)
checkOrder(null, second.id)
@ -70,9 +73,8 @@ class CaldavDaoTests : InjectingTestCase() {
val second = newTask(with(CREATION_TIME, created))
taskDao.createNew(first)
taskDao.createNew(second)
caldavDao.insert(first, CaldavTask(first.id, "calendar"), false)
caldavDao.insert(second, CaldavTask(second.id, "calendar"), false)
caldavDao.insert(first, CaldavTask(task = first.id, calendar = "calendar"), false)
caldavDao.insert(second, CaldavTask(task = second.id, calendar = "calendar"), false)
checkOrder(null, first.id)
checkOrder(created.plusSeconds(1), second.id)
@ -82,16 +84,14 @@ class CaldavDaoTests : InjectingTestCase() {
fun insertNewTaskAtBottomOfEmptyList() = runBlocking {
val task = newTask()
taskDao.createNew(task)
val caldavTask = CaldavTask(task.id, "calendar")
caldavDao.insert(task, caldavTask, false)
caldavDao.insert(task, CaldavTask(task = task.id, calendar = "calendar"), false)
checkOrder(null, task.id)
}
@Test
fun noResultsForEmptyAccounts() = runBlocking {
val caldavAccount = CaldavAccount()
caldavAccount.uuid = UUIDHelper.newUUID()
val caldavAccount = CaldavAccount(uuid = UUIDHelper.newUUID())
caldavDao.insert(caldavAccount)
assertTrue(caldavDao.getCaldavFilters(caldavAccount.uuid!!).isEmpty())
}
@ -99,11 +99,11 @@ class CaldavDaoTests : InjectingTestCase() {
private suspend fun checkOrder(dateTime: DateTime, task: Long) = checkOrder(dateTime.toAppleEpoch(), task)
private suspend fun checkOrder(order: Long?, task: Long) {
val sortOrder = caldavDao.getTask(task)!!.order
val sortOrder = taskDao.fetch(task)!!.order
if (order == null) {
assertNull(sortOrder)
} else {
assertEquals(order, sortOrder)
}
}
}
}

@ -2,13 +2,18 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.CaldavDao.Companion.LOCAL
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.CaldavDao.Companion.LOCAL
import org.tasks.data.dao.DeletionDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
@ -16,7 +21,7 @@ import org.tasks.makers.TaskMaker.CREATION_TIME
import org.tasks.makers.TaskMaker.DELETION_TIME
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -43,7 +48,7 @@ class DeletionDaoTests : InjectingTestCase() {
deletionDao.markDeleted(listOf(task.id))
task = taskDao.fetch(task.id)!!
assertTrue(task.modificationDate > task.creationDate)
assertTrue(task.modificationDate < DateTimeUtils.currentTimeMillis())
assertTrue(task.modificationDate < currentTimeMillis())
}
@Test
@ -53,15 +58,15 @@ class DeletionDaoTests : InjectingTestCase() {
deletionDao.markDeleted(listOf(task.id))
task = taskDao.fetch(task.id)!!
assertTrue(task.deletionDate > task.creationDate)
assertTrue(task.deletionDate < DateTimeUtils.currentTimeMillis())
assertTrue(task.deletionDate < currentTimeMillis())
}
@Test
fun purgeDeletedLocalTask() = runBlocking {
val task = newTask(with(DELETION_TIME, newDateTime()))
taskDao.createNew(task)
caldavDao.insert(CaldavCalendar("", "1234").apply { account = LOCAL })
caldavDao.insert(CaldavTask(task.id, "1234"))
caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = LOCAL))
caldavDao.insert(CaldavTask(task = task.id, calendar = "1234"))
deletionDao.purgeDeleted()
@ -72,8 +77,8 @@ class DeletionDaoTests : InjectingTestCase() {
fun dontPurgeActiveTasks() = runBlocking {
val task = newTask()
taskDao.createNew(task)
caldavDao.insert(CaldavCalendar("", "1234").apply { account = LOCAL })
caldavDao.insert(CaldavTask(task.id, "1234"))
caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = LOCAL))
caldavDao.insert(CaldavTask(task = task.id, calendar = "1234"))
deletionDao.purgeDeleted()
@ -84,11 +89,11 @@ class DeletionDaoTests : InjectingTestCase() {
fun dontPurgeDeletedCaldavTask() = runBlocking {
val task = newTask(with(DELETION_TIME, newDateTime()))
taskDao.createNew(task)
caldavDao.insert(CaldavCalendar("", "1234").apply { account = UUIDHelper.newUUID() })
caldavDao.insert(CaldavTask(task.id, "1234"))
caldavDao.insert(CaldavCalendar(name = "", uuid = "1234", account = UUIDHelper.newUUID()))
caldavDao.insert(CaldavTask(task = task.id, calendar = "1234"))
deletionDao.purgeDeleted()
assertNotNull(taskDao.fetch(task.id))
}
}
}

@ -9,15 +9,20 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_GOOGLE_TASKS
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavTask
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GoogleTaskMaker.LIST
import org.tasks.makers.GoogleTaskMaker.PARENT
import org.tasks.makers.GoogleTaskMaker.REMOTE_ID
import org.tasks.makers.GoogleTaskMaker.REMOTE_PARENT
import org.tasks.makers.GoogleTaskMaker.TASK
import org.tasks.makers.GoogleTaskMaker.newGoogleTask
import org.tasks.makers.GtaskListMaker.newGtaskList
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT
import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.TaskMaker.newTask
import javax.inject.Inject
@ -27,140 +32,135 @@ class GoogleTaskDaoTests : InjectingTestCase() {
@Inject lateinit var googleTaskListDao: GoogleTaskListDao
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var caldavDao: CaldavDao
@Before
override fun setUp() {
super.setUp()
runBlocking {
googleTaskListDao.insert(newGtaskList())
caldavDao.insert(CaldavAccount(uuid = "account", accountType = TYPE_GOOGLE_TASKS))
caldavDao.insert(CaldavCalendar(account = "account", uuid = "calendar"))
}
}
@Test
fun insertAtTopOfEmptyList() = runBlocking {
insertTop(newGoogleTask(with(REMOTE_ID, "1234")))
val tasks = googleTaskDao.getByLocalOrder("1")
insertTop(newCaldavTask(with(REMOTE_ID, "1234")))
val tasks = googleTaskDao.getByLocalOrder("calendar")
assertEquals(1, tasks.size.toLong())
val task = tasks[0]
assertEquals("1234", task.remoteId)
assertEquals(0, task.order)
assertEquals("1234", googleTaskDao.getByTaskId(task.id)?.remoteId)
assertEquals(0L, task.order)
}
@Test
fun insertAtBottomOfEmptyList() = runBlocking {
insertBottom(newGoogleTask(with(REMOTE_ID, "1234")))
val tasks = googleTaskDao.getByLocalOrder("1")
insertBottom(newCaldavTask(with(REMOTE_ID, "1234")))
val tasks = googleTaskDao.getByLocalOrder("calendar")
assertEquals(1, tasks.size.toLong())
val task = tasks[0]
assertEquals("1234", task.remoteId)
assertEquals(0, task.order)
assertEquals("1234", googleTaskDao.getByTaskId(task.id)?.remoteId)
assertEquals(0L, task.order)
}
@Test
fun getPreviousIsNullForTopTask() = runBlocking {
insert(newGoogleTask())
insert(newCaldavTask())
assertNull(googleTaskDao.getPrevious("1", 0, 0))
}
@Test
fun getPrevious() = runBlocking {
insertTop(newGoogleTask())
insertTop(newGoogleTask(with(REMOTE_ID, "1234")))
assertEquals("1234", googleTaskDao.getPrevious("1", 0, 1))
insertTop(newCaldavTask())
insertTop(newCaldavTask(with(REMOTE_ID, "1234")))
assertEquals("1234", googleTaskDao.getPrevious("calendar", 0, 1))
}
@Test
fun insertAtTopOfList() = runBlocking {
insertTop(newGoogleTask(with(REMOTE_ID, "1234")))
insertTop(newGoogleTask(with(REMOTE_ID, "5678")))
val tasks = googleTaskDao.getByLocalOrder("1")
insertTop(newCaldavTask(with(REMOTE_ID, "1234")))
insertTop(newCaldavTask(with(REMOTE_ID, "5678")))
val tasks = googleTaskDao.getByLocalOrder("calendar")
assertEquals(2, tasks.size.toLong())
val top = tasks[0]
assertEquals("5678", top.remoteId)
assertEquals(0, top.order)
assertEquals("5678", googleTaskDao.getByTaskId(top.id)?.remoteId)
assertEquals(0L, top.order)
}
@Test
fun insertAtTopOfListShiftsExisting() = runBlocking {
insertTop(newGoogleTask(with(REMOTE_ID, "1234")))
insertTop(newGoogleTask(with(REMOTE_ID, "5678")))
val tasks = googleTaskDao.getByLocalOrder("1")
insertTop(newCaldavTask(with(REMOTE_ID, "1234")))
insertTop(newCaldavTask(with(REMOTE_ID, "5678")))
val tasks = googleTaskDao.getByLocalOrder("calendar")
assertEquals(2, tasks.size.toLong())
val bottom = tasks[1]
assertEquals("1234", bottom.remoteId)
assertEquals(1, bottom.order)
assertEquals("1234", googleTaskDao.getByTaskId(bottom.id)?.remoteId)
assertEquals(1L, bottom.order)
}
@Test
fun getTaskFromRemoteId() = runBlocking {
insert(newGoogleTask(with(REMOTE_ID, "1234")))
insert(newCaldavTask(with(REMOTE_ID, "1234")))
assertEquals(1L, googleTaskDao.getTask("1234"))
}
@Test
fun getRemoteIdForTask() = runBlocking {
insert(newGoogleTask(with(REMOTE_ID, "1234")))
insert(newCaldavTask(with(REMOTE_ID, "1234")))
assertEquals("1234", googleTaskDao.getRemoteId(1L))
}
@Test
fun moveDownInList() = runBlocking {
insert(newGoogleTask(with(REMOTE_ID, "1")))
insert(newGoogleTask(with(REMOTE_ID, "2")))
insert(newGoogleTask(with(REMOTE_ID, "3")))
insert(newCaldavTask(with(REMOTE_ID, "1")))
insert(newCaldavTask(with(REMOTE_ID, "2")))
insert(newCaldavTask(with(REMOTE_ID, "3")))
val two = getByRemoteId("2")
googleTaskDao.move(two, 0, 0)
assertEquals(0, googleTaskDao.getByRemoteId("2")!!.order)
assertEquals(1, googleTaskDao.getByRemoteId("1")!!.order)
assertEquals(2, googleTaskDao.getByRemoteId("3")!!.order)
googleTaskDao.move(taskDao.fetch(two.task)!!, "calendar", 0, 0)
assertEquals(0L, getOrder("2"))
assertEquals(1L, getOrder("1"))
assertEquals(2L, getOrder("3"))
}
@Test
fun moveUpInList() = runBlocking {
insert(newGoogleTask(with(REMOTE_ID, "1")))
insert(newGoogleTask(with(REMOTE_ID, "2")))
insert(newGoogleTask(with(REMOTE_ID, "3")))
insert(newCaldavTask(with(REMOTE_ID, "1")))
insert(newCaldavTask(with(REMOTE_ID, "2")))
insert(newCaldavTask(with(REMOTE_ID, "3")))
val one = getByRemoteId("1")
googleTaskDao.move(one, 0, 1)
assertEquals(0, googleTaskDao.getByRemoteId("2")!!.order)
assertEquals(1, googleTaskDao.getByRemoteId("1")!!.order)
assertEquals(2, googleTaskDao.getByRemoteId("3")!!.order)
googleTaskDao.move(taskDao.fetch(one.task)!!, "calendar", 0, 1)
assertEquals(0L, getOrder("2"))
assertEquals(1L, getOrder("1"))
assertEquals(2L, getOrder("3"))
}
@Test
fun moveToTop() = runBlocking {
insert(newGoogleTask(with(REMOTE_ID, "1")))
insert(newGoogleTask(with(REMOTE_ID, "2")))
insert(newGoogleTask(with(REMOTE_ID, "3")))
insert(newCaldavTask(with(REMOTE_ID, "1")))
insert(newCaldavTask(with(REMOTE_ID, "2")))
insert(newCaldavTask(with(REMOTE_ID, "3")))
val three = getByRemoteId("3")
googleTaskDao.move(three, 0, 0)
assertEquals(0, googleTaskDao.getByRemoteId("3")!!.order)
assertEquals(1, googleTaskDao.getByRemoteId("1")!!.order)
assertEquals(2, googleTaskDao.getByRemoteId("2")!!.order)
googleTaskDao.move(taskDao.fetch(three.task)!!, "calendar", 0, 0)
assertEquals(0L, getOrder("3"))
assertEquals(1L, getOrder("1"))
assertEquals(2L, getOrder("2"))
}
@Test
fun moveToBottom() = runBlocking {
insert(newGoogleTask(with(REMOTE_ID, "1")))
insert(newGoogleTask(with(REMOTE_ID, "2")))
insert(newGoogleTask(with(REMOTE_ID, "3")))
insert(newCaldavTask(with(REMOTE_ID, "1")))
insert(newCaldavTask(with(REMOTE_ID, "2")))
insert(newCaldavTask(with(REMOTE_ID, "3")))
val one = getByRemoteId("1")
googleTaskDao.move(one, 0, 2)
assertEquals(0, googleTaskDao.getByRemoteId("2")!!.order)
assertEquals(1, googleTaskDao.getByRemoteId("3")!!.order)
assertEquals(2, googleTaskDao.getByRemoteId("1")!!.order)
}
@Test
fun findChildrenInList() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(PARENT, 1L)))
assertEquals(listOf(2L), googleTaskDao.getChildren(listOf(1L, 2L)))
googleTaskDao.move(taskDao.fetch(one.task)!!, "calendar", 0, 2)
assertEquals(0L, getOrder("2"))
assertEquals(1L, getOrder("3"))
assertEquals(2L, getOrder("1"))
}
@Test
fun dontAllowEmptyParent() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "1234")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "1234")))
googleTaskDao.updatePosition("1234", "", "0")
@ -169,7 +169,7 @@ class GoogleTaskDaoTests : InjectingTestCase() {
@Test
fun updatePositionWithNullParent() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "1234")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "1234")))
googleTaskDao.updatePosition("1234", null, "0")
@ -178,7 +178,7 @@ class GoogleTaskDaoTests : InjectingTestCase() {
@Test
fun updatePosition() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "1234")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "1234")))
googleTaskDao.updatePosition("1234", "abcd", "0")
@ -187,86 +187,87 @@ class GoogleTaskDaoTests : InjectingTestCase() {
@Test
fun updateParents() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "123")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(REMOTE_PARENT, "123")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "123")))
insert(newCaldavTask(with(TASK, 2), with(REMOTE_PARENT, "123")))
googleTaskDao.updateParents()
caldavDao.updateParents()
assertEquals(1, googleTaskDao.getByTaskId(2)!!.parent)
assertEquals(1, taskDao.fetch(2)!!.parent)
}
@Test
fun updateParentsByList() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "123")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(REMOTE_PARENT, "123")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "123")))
insert(newCaldavTask(with(TASK, 2), with(REMOTE_PARENT, "123")))
googleTaskDao.updateParents("1")
caldavDao.updateParents("calendar")
assertEquals(1, googleTaskDao.getByTaskId(2)!!.parent)
assertEquals(1, taskDao.fetch(2)!!.parent)
}
@Test
fun updateParentsMustMatchList() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "123")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "2"), with(REMOTE_PARENT, "123")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "123")))
insert(newCaldavTask(with(TASK, 2), with(CALENDAR, "2"), with(REMOTE_PARENT, "123")))
googleTaskDao.updateParents()
caldavDao.updateParents()
assertEquals(0, googleTaskDao.getByTaskId(2)!!.parent)
assertEquals(0, taskDao.fetch(2)!!.parent)
}
@Test
fun updateParentsByListMustMatchList() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "123")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "2"), with(REMOTE_PARENT, "123")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "123")))
insert(newCaldavTask(with(TASK, 2), with(CALENDAR, "2"), with(REMOTE_PARENT, "123")))
googleTaskDao.updateParents("2")
caldavDao.updateParents("2")
assertEquals(0, googleTaskDao.getByTaskId(2)!!.parent)
assertEquals(0, taskDao.fetch(2)!!.parent)
}
@Test
fun ignoreEmptyStringWhenUpdatingParents() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(REMOTE_ID, ""), with(REMOTE_PARENT, "")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "")))
insert(newCaldavTask(with(TASK, 2), with(REMOTE_ID, ""), with(REMOTE_PARENT, "")))
googleTaskDao.updateParents()
caldavDao.updateParents()
assertEquals(0, googleTaskDao.getByTaskId(2)!!.parent)
assertEquals(0, taskDao.fetch(2)!!.parent)
}
@Test
fun ignoreEmptyStringWhenUpdatingParentsForList() = runBlocking {
insert(newGoogleTask(with(TASK, 1), with(LIST, "1"), with(REMOTE_ID, "")))
insert(newGoogleTask(with(TASK, 2), with(LIST, "1"), with(REMOTE_ID, ""), with(REMOTE_PARENT, "")))
insert(newCaldavTask(with(TASK, 1), with(REMOTE_ID, "")))
insert(newCaldavTask(with(TASK, 2), with(REMOTE_ID, ""), with(REMOTE_PARENT, "")))
googleTaskDao.updateParents("1")
caldavDao.updateParents("1")
assertEquals(0, taskDao.fetch(2)!!.parent)
}
assertEquals(0, googleTaskDao.getByTaskId(2)!!.parent)
private suspend fun getOrder(remoteId: String): Long? {
return taskDao.fetch(googleTaskDao.getByRemoteId(remoteId)!!.task)?.order
}
private suspend fun insertTop(googleTask: GoogleTask) {
private suspend fun insertTop(googleTask: CaldavTask) {
insert(googleTask, true)
}
private suspend fun insertBottom(googleTask: GoogleTask) {
private suspend fun insertBottom(googleTask: CaldavTask) {
insert(googleTask, false)
}
private suspend fun insert(googleTask: GoogleTask, top: Boolean = false) {
private suspend fun insert(googleTask: CaldavTask, top: Boolean = false) {
val task = newTask()
taskDao.createNew(task)
googleTask.task = task.id
googleTaskDao.insertAndShift(googleTask, top)
googleTaskDao.insertAndShift(
task,
googleTask.copy(task = task.id),
top
)
}
private suspend fun getByRemoteId(remoteId: String): SubsetGoogleTask {
val googleTask = googleTaskDao.getByRemoteId(remoteId)!!
val result = SubsetGoogleTask()
result.gt_id = googleTask.id
result.gt_list_id = googleTask.listId
result.gt_order = googleTask.order
result.gt_parent = googleTask.parent
return result
private suspend fun getByRemoteId(remoteId: String): CaldavTask {
return googleTaskDao.getByRemoteId(remoteId)!!
}
}

@ -1,53 +1,31 @@
package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GoogleTaskListMaker.ACCOUNT
import org.tasks.makers.GoogleTaskListMaker.REMOTE_ID
import org.tasks.makers.GoogleTaskListMaker.newGoogleTaskList
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class GoogleTaskListDaoTest : InjectingTestCase() {
@Inject lateinit var googleTaskListDao: GoogleTaskListDao
@Inject lateinit var caldavDao: CaldavDao
@Test
fun noResultsForEmptyAccount() = runBlocking {
val account = GoogleTaskAccount()
account.account = "user@gmail.com"
googleTaskListDao.insert(account)
val account = CaldavAccount(
uuid = "user@gmail.com",
username = "user@gmail.com",
)
caldavDao.insert(account)
assertTrue(googleTaskListDao.getGoogleTaskFilters(account.account!!).isEmpty())
}
@Test
fun findListWithNullAccount() = runBlocking {
val list = newGoogleTaskList(with(REMOTE_ID, "1234"), with(ACCOUNT, null as String?))
list.id = googleTaskListDao.insert(list)
assertEquals(list, googleTaskListDao.findExistingList("1234"))
}
@Test
fun findListWithEmptyAccount() = runBlocking {
val list = newGoogleTaskList(with(REMOTE_ID, "1234"), with(ACCOUNT, ""))
list.id = googleTaskListDao.insert(list)
assertEquals(list, googleTaskListDao.findExistingList("1234"))
}
@Test
fun ignoreListWithAccount() = runBlocking {
val list = newGoogleTaskList(with(REMOTE_ID, "1234"), with(ACCOUNT, "user@gmail.com"))
googleTaskListDao.insert(list)
assertNull(googleTaskListDao.findExistingList("1234"))
assertTrue(googleTaskListDao.getGoogleTaskFilters(account.username!!).isEmpty())
}
}

@ -1,34 +1,34 @@
package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.andlib.utility.DateUtilities.now
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.caldav.GeoUtils.toLikeString
import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.dao.AlarmDao
import org.tasks.data.dao.LocationDao
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.entity.Geofence
import org.tasks.data.entity.Place
import org.tasks.data.entity.Task
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GeofenceMaker.ARRIVAL
import org.tasks.makers.GeofenceMaker.DEPARTURE
import org.tasks.makers.GeofenceMaker.PLACE
import org.tasks.makers.GeofenceMaker.TASK
import org.tasks.makers.GeofenceMaker.newGeofence
import org.tasks.makers.PlaceMaker.LATITUDE
import org.tasks.makers.PlaceMaker.LONGITUDE
import org.tasks.makers.PlaceMaker.newPlace
import org.tasks.makers.TaskMaker.COMPLETION_TIME
import org.tasks.makers.TaskMaker.DELETION_TIME
import org.tasks.makers.TaskMaker.DUE_TIME
import org.tasks.makers.TaskMaker.HIDE_TYPE
import org.tasks.makers.TaskMaker.ID
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -40,7 +40,7 @@ class LocationDaoTest : InjectingTestCase() {
@Test
fun getExistingPlace() = runBlocking {
locationDao.insert(newPlace(with(LATITUDE, 48.067222), with(LONGITUDE, 12.863611)))
locationDao.insert(Place(latitude = 48.067222, longitude = 12.863611))
val place = locationDao.findPlace(48.067222.toLikeString(), 12.863611.toLikeString())
assertEquals(48.067222, place?.latitude)
assertEquals(12.863611, place?.longitude)
@ -48,7 +48,7 @@ class LocationDaoTest : InjectingTestCase() {
@Test
fun getPlaceWithLessPrecision() = runBlocking {
locationDao.insert(newPlace(with(LATITUDE, 50.7547), with(LONGITUDE, -2.2279)))
locationDao.insert(Place(latitude = 50.7547, longitude = -2.2279))
val place = locationDao.findPlace(50.754712.toLikeString(), (-2.227945).toLikeString())
assertEquals(50.7547, place?.latitude)
assertEquals(-2.2279, place?.longitude)
@ -56,7 +56,7 @@ class LocationDaoTest : InjectingTestCase() {
@Test
fun getPlaceWithMorePrecision() = runBlocking {
locationDao.insert(newPlace(with(LATITUDE, 36.246944), with(LONGITUDE, -116.816944)))
locationDao.insert(Place(latitude = 36.246944, longitude = -116.816944))
locationDao.getPlaces().forEach { println(it) }
val place = locationDao.findPlace(36.2469.toLikeString(), (-116.8169).toLikeString())
assertEquals(36.246944, place?.latitude)
@ -65,20 +65,20 @@ class LocationDaoTest : InjectingTestCase() {
@Test
fun noActiveGeofences() = runBlocking {
val place = newPlace()
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid)))
locationDao.insert(Geofence(task = 1, place = place.uid))
assertNull(locationDao.getGeofencesByPlace(place.uid!!))
}
@Test
fun activeArrivalGeofence() = runBlocking {
val place = newPlace()
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
locationDao.insert(Geofence(task = 1, place = place.uid, isArrival = true))
val geofence = locationDao.getGeofencesByPlace(place.uid!!)
@ -88,10 +88,10 @@ class LocationDaoTest : InjectingTestCase() {
@Test
fun activeDepartureGeofence() = runBlocking {
val place = newPlace()
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(DEPARTURE, true)))
locationDao.insert(Geofence(task = 1, place = place.uid, isDeparture = true))
val geofence = locationDao.getGeofencesByPlace(place.uid!!)
@ -101,137 +101,171 @@ class LocationDaoTest : InjectingTestCase() {
@Test
fun geofenceInactiveForCompletedTask() = runBlocking {
val place = newPlace()
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1), with(COMPLETION_TIME, newDateTime())))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
locationDao.insert(Geofence(task = 1, place = place.uid, isArrival = true))
assertNull(locationDao.getGeofencesByPlace(place.uid!!))
}
@Test
fun geofenceInactiveForDeletedTask() = runBlocking {
val place = newPlace()
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(with(ID, 1), with(DELETION_TIME, newDateTime())))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
locationDao.insert(Geofence(task = 1, place = place.uid, isArrival = true))
assertNull(locationDao.getGeofencesByPlace(place.uid!!))
}
@Test
fun ignoreArrivalForSnoozedTask() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
val task = taskDao.createNew(newTask())
alarmDao.insert(Alarm(task, newDateTime().plusMinutes(15).millis, TYPE_SNOOZE))
locationDao.insert(newGeofence(with(TASK, task), with(PLACE, place.uid), with(ARRIVAL, true)))
assertTrue(locationDao.getArrivalGeofences(place.uid!!, now()).isEmpty())
alarmDao.insert(
Alarm(
task = task,
time = newDateTime().plusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
locationDao.insert(Geofence(task = task, place = place.uid, isArrival = true))
assertTrue(locationDao.getArrivalGeofences(place.uid!!, currentTimeMillis()).isEmpty())
}
}
@Test
fun ignoreDepartureForSnoozedTask() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
val task = taskDao.createNew(newTask())
alarmDao.insert(Alarm(task, newDateTime().plusMinutes(15).millis, TYPE_SNOOZE))
locationDao.insert(newGeofence(with(TASK, task), with(PLACE, place.uid), with(DEPARTURE, true)))
assertTrue(locationDao.getDepartureGeofences(place.uid!!, now()).isEmpty())
alarmDao.insert(
Alarm(
task = task,
time = newDateTime().plusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
locationDao.insert(Geofence(task = task, place = place.uid, isDeparture = true))
assertTrue(locationDao.getDepartureGeofences(place.uid!!, currentTimeMillis()).isEmpty())
}
}
@Test
fun getArrivalWithElapsedSnooze() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
val task = taskDao.createNew(newTask())
alarmDao.insert(Alarm(task, newDateTime().minusMinutes(15).millis, TYPE_SNOOZE))
val geofence = newGeofence(with(TASK, task), with(PLACE, place.uid), with(ARRIVAL, true))
geofence.id = locationDao.insert(geofence)
assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!, now()))
alarmDao.insert(
Alarm(
task = task,
time = newDateTime().minusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
val geofence = Geofence(task = task, place = place.uid, isArrival = true)
.let { it.copy(id = locationDao.insert(it)) }
assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!,
currentTimeMillis()
))
}
}
@Test
fun getDepartureWithElapsedSnooze() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
val task = taskDao.createNew(newTask())
alarmDao.insert(Alarm(task, newDateTime().minusMinutes(15).millis, TYPE_SNOOZE))
val geofence = newGeofence(with(TASK, task), with(PLACE, place.uid), with(DEPARTURE, true))
geofence.id = locationDao.insert(geofence)
assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!, now()))
alarmDao.insert(
Alarm(
task = task,
time = newDateTime().minusMinutes(15).millis,
type = TYPE_SNOOZE
)
)
val geofence = Geofence(task = task, place = place.uid, isDeparture = true)
.let { it.copy(id = locationDao.insert(it)) }
assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!,
currentTimeMillis()
))
}
}
@Test
fun ignoreArrivalForHiddenTask() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(
with(ID, 1),
with(DUE_TIME, newDateTime().plusMinutes(15)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true)))
locationDao.insert(Geofence(task = 1, place = place.uid, isArrival = true))
assertTrue(locationDao.getArrivalGeofences(place.uid!!, now()).isEmpty())
assertTrue(locationDao.getArrivalGeofences(place.uid!!, currentTimeMillis()).isEmpty())
}
}
@Test
fun ignoreDepartureForHiddenTask() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(
with(ID, 1),
with(DUE_TIME, newDateTime().plusMinutes(15)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME)))
locationDao.insert(newGeofence(with(TASK, 1), with(PLACE, place.uid), with(DEPARTURE, true)))
locationDao.insert(Geofence(task = 1, place = place.uid, isDeparture = true))
assertTrue(locationDao.getDepartureGeofences(place.uid!!, now()).isEmpty())
assertTrue(locationDao.getDepartureGeofences(place.uid!!, currentTimeMillis()).isEmpty())
}
}
@Test
fun getArrivalWithElapsedHideUntil() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(
with(ID, 1),
with(DUE_TIME, newDateTime().minusMinutes(15)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME)))
val geofence = newGeofence(with(TASK, 1), with(PLACE, place.uid), with(ARRIVAL, true))
geofence.id = locationDao.insert(geofence)
assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!, now()))
val geofence = Geofence(task = 1, place = place.uid, isArrival = true)
.let {
it.copy(id = locationDao.insert(it))
}
assertEquals(listOf(geofence), locationDao.getArrivalGeofences(place.uid!!,
currentTimeMillis()
))
}
}
@Test
fun getDepartureWithElapsedHideUntil() = runBlocking {
freezeAt(now()).thawAfter {
val place = newPlace()
freezeAt(currentTimeMillis()).thawAfter {
val place = Place()
locationDao.insert(place)
taskDao.createNew(newTask(
with(ID, 1),
with(DUE_TIME, newDateTime().minusMinutes(15)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE_TIME)))
val geofence = newGeofence(with(TASK, 1), with(PLACE, place.uid), with(DEPARTURE, true))
geofence.id = locationDao.insert(geofence)
val geofence = Geofence(task = 1, place = place.uid, isDeparture = true)
.let { it.copy(id = locationDao.insert(it)) }
assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!, now()))
assertEquals(listOf(geofence), locationDao.getDepartureGeofences(place.uid!!,
currentTimeMillis()
))
}
}
}

@ -3,43 +3,49 @@ package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.tasks.R
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.GoogleTaskDao
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.GoogleTaskListMaker.REMOTE_ID
import org.tasks.makers.GoogleTaskListMaker.newGoogleTaskList
import org.tasks.makers.GoogleTaskMaker.LIST
import org.tasks.makers.GoogleTaskMaker.ORDER
import org.tasks.makers.GoogleTaskMaker.PARENT
import org.tasks.makers.GoogleTaskMaker.TASK
import org.tasks.makers.GoogleTaskMaker.newGoogleTask
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.TaskMaker
import org.tasks.makers.TaskMaker.ID
import org.tasks.makers.TaskMaker.UUID
import org.tasks.makers.TaskMaker.ORDER
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.preferences.Preferences
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class ManualGoogleTaskQueryTest : InjectingTestCase() {
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var googleTaskDao: GoogleTaskDao
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences
private val filter: GtasksFilter = GtasksFilter(newGoogleTaskList(with(REMOTE_ID, "1234")))
private lateinit var filter: GtasksFilter
@Before
override fun setUp() {
super.setUp()
preferences.clear()
preferences.setBoolean(R.string.p_manual_sort, true)
val calendar = CaldavCalendar(uuid = "1234")
runBlocking {
caldavDao.insert(CaldavAccount())
caldavDao.insert(calendar)
}
filter = GtasksFilter(calendar)
}
@Test
@ -88,23 +94,17 @@ class ManualGoogleTaskQueryTest : InjectingTestCase() {
assertEquals(1, subtasks[2].secondarySort)
}
@Test
fun ignoreDisableSubtasksPreference() = runBlocking {
preferences.setBoolean(R.string.p_use_paged_queries, true)
newTask(1, 0, 0)
newTask(2, 0, 1)
val parent = query()[0]
assertTrue(parent.hasChildren())
}
private suspend fun newTask(id: Long, order: Long, parent: Long = 0) {
taskDao.insert(TaskMaker.newTask(with(ID, id), with(UUID, UUIDHelper.newUUID())))
googleTaskDao.insert(newGoogleTask(with(LIST, filter.list.remoteId), with(TASK, id), with(PARENT, parent), with(ORDER, order)))
taskDao.insert(TaskMaker.newTask(
with(ID, id),
with(TaskMaker.UUID, UUIDHelper.newUUID()),
with(ORDER, order),
with(PARENT, parent),
))
googleTaskDao.insert(newCaldavTask(with(CALENDAR, filter.list.uuid), with(TASK, id)))
}
private suspend fun query(): List<TaskContainer> = taskDao.fetchTasks {
TaskListQuery.getQuery(preferences, filter, it)
TaskListQuery.getQuery(preferences, filter)
}
}

@ -8,14 +8,12 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.Tag
import org.tasks.data.entity.TagData
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TagDataMaker.NAME
import org.tasks.makers.TagDataMaker.newTagData
import org.tasks.makers.TagMaker.TAGDATA
import org.tasks.makers.TagMaker.TAGUID
import org.tasks.makers.TagMaker.TASK
import org.tasks.makers.TagMaker.newTag
import org.tasks.makers.TaskMaker.ID
import org.tasks.makers.TaskMaker.newTask
import javax.inject.Inject
@ -29,13 +27,13 @@ class TagDataDaoTest : InjectingTestCase() {
@Test
fun tagDataOrderedByNameIgnoresNullNames() = runBlocking {
tagDataDao.createNew(newTagData(with(NAME, null as String?)))
tagDataDao.insert(TagData(name = null))
assertTrue(tagDataDao.tagDataOrderedByName().isEmpty())
}
@Test
fun tagDataOrderedByNameIgnoresEmptyNames() = runBlocking {
tagDataDao.createNew(newTagData(with(NAME, "")))
tagDataDao.insert(TagData(name = ""))
assertTrue(tagDataDao.tagDataOrderedByName().isEmpty())
}
@ -46,20 +44,19 @@ class TagDataDaoTest : InjectingTestCase() {
@Test
fun getTagWithCaseFixesCase() = runBlocking {
tagDataDao.createNew(newTagData(with(NAME, "Derp")))
tagDataDao.insert(TagData(name = "Derp"))
assertEquals("Derp", tagDataDao.getTagWithCase("derp"))
}
@Test
fun getTagsByName() = runBlocking {
val tagData = newTagData(with(NAME, "Derp"))
tagDataDao.createNew(tagData)
val tagData = TagData(name = "Derp").let { it.copy(id = tagDataDao.insert(it)) }
assertEquals(listOf(tagData), tagDataDao.getTags(listOf("Derp")))
}
@Test
fun getTagsByNameCaseSensitive() = runBlocking {
tagDataDao.createNew(newTagData(with(NAME, "Derp")))
tagDataDao.insert(TagData(name = "Derp"))
assertTrue(tagDataDao.getTags(listOf("derp")).isEmpty())
}
@ -69,20 +66,18 @@ class TagDataDaoTest : InjectingTestCase() {
val taskTwo = newTask()
taskDao.createNew(taskOne)
taskDao.createNew(taskTwo)
val tagOne = newTagData(with(NAME, "one"))
val tagTwo = newTagData(with(NAME, "two"))
tagDataDao.createNew(tagOne)
tagDataDao.createNew(tagTwo)
tagDao.insert(newTag(with(TAGDATA, tagOne), with(TASK, taskOne)))
tagDao.insert(newTag(with(TAGDATA, tagTwo), with(TASK, taskTwo)))
val tagOne = TagData(name = "one").let { it.copy(id = tagDataDao.insert(it)) }
val tagTwo = TagData(name = "two").let { it.copy(id = tagDataDao.insert(it)) }
tagDao.insert(Tag(task = taskOne.id, taskUid = taskOne.uuid, tagUid = tagOne.remoteId))
tagDao.insert(Tag(task = taskTwo.id, taskUid = taskTwo.uuid, tagUid = tagTwo.remoteId))
assertEquals(listOf(tagOne), tagDataDao.getTagDataForTask(taskOne.id))
}
@Test
fun getEmptyTagSelections() = runBlocking {
val selections = tagDataDao.getTagSelections(listOf(1L))
assertTrue(selections.first!!.isEmpty())
assertTrue(selections.second!!.isEmpty())
assertTrue(selections.first.isEmpty())
assertTrue(selections.second.isEmpty())
}
@Test
@ -97,7 +92,7 @@ class TagDataDaoTest : InjectingTestCase() {
fun getEmptyPartialSelections() = runBlocking {
newTag(1, "tag1")
newTag(2, "tag1")
assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).first!!.isEmpty())
assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).first.isEmpty())
}
@Test
@ -111,15 +106,15 @@ class TagDataDaoTest : InjectingTestCase() {
fun getEmptyCommonSelections() = runBlocking {
newTag(1, "tag1")
newTag(2, "tag2")
assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).second!!.isEmpty())
assertTrue(tagDataDao.getTagSelections(listOf(1L, 2L)).second.isEmpty())
}
@Test
fun getSelectionsWithNoTags() = runBlocking {
newTag(1)
val selections = tagDataDao.getTagSelections(listOf(1L))
assertTrue(selections.first!!.isEmpty())
assertTrue(selections.second!!.isEmpty())
assertTrue(selections.first.isEmpty())
assertTrue(selections.second.isEmpty())
}
@Test
@ -128,14 +123,14 @@ class TagDataDaoTest : InjectingTestCase() {
newTag(2)
val selections = tagDataDao.getTagSelections(listOf(1L, 2L))
assertEquals(setOf("tag1"), selections.first)
assertTrue(selections.second!!.isEmpty())
assertTrue(selections.second.isEmpty())
}
private suspend fun newTag(taskId: Long, vararg tags: String) {
val task = newTask(with(ID, taskId))
taskDao.createNew(task)
for (tag in tags) {
tagDao.insert(newTag(with(TASK, task), with(TAGUID, tag)))
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = tag))
}
}
}

@ -6,8 +6,7 @@
package org.tasks.data
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
@ -15,10 +14,12 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import org.tasks.data.dao.TaskDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.PARENT
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -44,23 +45,23 @@ class TaskDaoTests : InjectingTestCase() {
// create hidden task
task = Task()
task.title = "hidden"
task.hideUntil = DateUtilities.now() + 10000
task.hideUntil = currentTimeMillis() + 10000
taskDao.createNew(task)
// create task with deadlines
task = Task()
task.title = "deadlineInFuture"
task.dueDate = DateUtilities.now() + 10000
task.dueDate = currentTimeMillis() + 10000
taskDao.createNew(task)
task = Task()
task.title = "deadlineInPast"
task.dueDate = DateUtilities.now() - 10000
task.dueDate = currentTimeMillis() - 10000
taskDao.createNew(task)
// create completed task
task = Task()
task.title = "completed"
task.completionDate = DateUtilities.now() - 10000
task.completionDate = currentTimeMillis() - 10000
taskDao.createNew(task)
// check is active

@ -8,10 +8,15 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.dao.UpgraderDao
import org.tasks.data.entity.CaldavTask
import org.tasks.data.entity.Tag
import org.tasks.data.entity.TagData
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.TagDataMaker
import org.tasks.makers.TagMaker
import org.tasks.makers.TaskMaker
import javax.inject.Inject
@ -29,13 +34,13 @@ class UpgraderDaoTests : InjectingTestCase() {
fun getCaldavTasksWithTags() = runBlocking {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L))
taskDao.createNew(task)
val one = TagDataMaker.newTagData()
val two = TagDataMaker.newTagData()
tagDataDao.createNew(one)
tagDataDao.createNew(two)
tagDao.insert(TagMaker.newTag(MakeItEasy.with(TagMaker.TASK, task), MakeItEasy.with(TagMaker.TAGDATA, one)))
tagDao.insert(TagMaker.newTag(MakeItEasy.with(TagMaker.TASK, task), MakeItEasy.with(TagMaker.TAGDATA, two)))
caldavDao.insert(CaldavTask(task.id, "calendar"))
val one = TagData()
val two = TagData()
tagDataDao.insert(one)
tagDataDao.insert(two)
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = one.remoteId))
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = two.remoteId))
caldavDao.insert(CaldavTask(task = task.id, calendar = "calendar"))
assertEquals(listOf(task.id), upgraderDao.tasksWithTags())
}
@ -43,9 +48,9 @@ class UpgraderDaoTests : InjectingTestCase() {
fun ignoreNonCaldavTaskWithTags() = runBlocking {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L))
taskDao.createNew(task)
val tag = TagDataMaker.newTagData()
tagDataDao.createNew(tag)
tagDao.insert(TagMaker.newTag(MakeItEasy.with(TagMaker.TASK, task), MakeItEasy.with(TagMaker.TAGDATA, tag)))
val tag = TagData()
tagDataDao.insert(tag)
tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = tag.remoteId))
assertTrue(upgraderDao.tasksWithTags().isEmpty())
}
@ -53,8 +58,8 @@ class UpgraderDaoTests : InjectingTestCase() {
fun ignoreCaldavTaskWithoutTags() = runBlocking {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.ID, 1L))
taskDao.createNew(task)
tagDataDao.createNew(TagDataMaker.newTagData())
caldavDao.insert(CaldavTask(task.id, "calendar"))
tagDataDao.insert(TagData())
caldavDao.insert(CaldavTask(task = task.id, calendar = "calendar"))
assertTrue(upgraderDao.tasksWithTags().isEmpty())
}
}
}

@ -2,7 +2,7 @@ package org.tasks.gtasks
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test

@ -2,7 +2,7 @@ package org.tasks.injection
import android.content.Context
import androidx.room.Room
import com.todoroo.astrid.dao.Database
import org.tasks.data.db.Database
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn

@ -8,7 +8,7 @@ package org.tasks.jobs
import android.net.Uri
import androidx.test.InstrumentationRegistry
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -18,6 +18,7 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.tasks.R
import org.tasks.backup.BackupConstants.BACKUP_CLEANUP_MATCHER
import org.tasks.backup.TasksJsonExporter
import org.tasks.backup.TasksJsonExporter.ExportType
import org.tasks.injection.InjectingTestCase
@ -77,6 +78,6 @@ class BackupServiceTests : InjectingTestCase() {
// assert file created
val files = temporaryDirectory.listFiles()
assertEquals(1, files!!.size)
assertTrue(files[0].name.matches(BackupWork.BACKUP_FILE_NAME_REGEX))
assertTrue(files[0].name.matches(BACKUP_CLEANUP_MATCHER))
}
}

@ -0,0 +1 @@
../../../../test/java/org/tasks/makers

@ -1,7 +1,7 @@
package org.tasks.opentasks
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking

@ -1,11 +1,13 @@
package org.tasks.opentasks
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.TestUtilities.withTZ
@ -13,27 +15,25 @@ import org.tasks.caldav.iCalendar.Companion.collapsed
import org.tasks.caldav.iCalendar.Companion.order
import org.tasks.caldav.iCalendar.Companion.parent
import org.tasks.caldav.iCalendar.Companion.snooze
import org.tasks.data.Alarm
import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.AlarmDao
import org.tasks.data.TagDao
import org.tasks.data.TagDataDao
import org.tasks.data.dao.AlarmDao
import org.tasks.data.dao.TagDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Alarm.Companion.TYPE_SNOOZE
import org.tasks.data.entity.Tag
import org.tasks.data.entity.TagData
import org.tasks.data.entity.Task
import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavTaskMaker
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.REMOTE_ORDER
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.TagDataMaker.NAME
import org.tasks.makers.TagDataMaker.newTagData
import org.tasks.makers.TagMaker.TAGDATA
import org.tasks.makers.TagMaker.TASK
import org.tasks.makers.TagMaker.newTag
import org.tasks.makers.TaskMaker
import org.tasks.makers.TaskMaker.COLLAPSED
import org.tasks.makers.TaskMaker.ORDER
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import java.util.*
import java.util.TimeZone
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -90,8 +90,7 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
@Test
fun matchExistingTag() = runBlocking {
val (_, list) = withVtodo(ONE_TAG)
val tag = newTagData(with(NAME, "Tag1"))
tagDataDao.createNew(tag)
val tag = TagData(name = "Tag1").let { it.copy(id = tagDataDao.insert(it)) }
synchronizer.sync()
@ -129,20 +128,18 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
synchronizer.sync()
assertEquals(
633734058L,
caldavDao.getTaskByRemoteId(list.uuid!!, "3076145036806467726")?.order
)
val task = caldavDao.getTaskByRemoteId(list.uuid!!, "3076145036806467726")!!.task
assertEquals(633734058L, taskDao.fetch(task)?.order)
}
@Test
fun pushOrder() = runBlocking {
val (listId, list) = openTaskDao.insertList()
val task = newTask().apply { taskDao.createNew(this) }
val task = newTask(with(ORDER, 5678L))
taskDao.createNew(task)
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "1234"),
with(REMOTE_ORDER, 5678L),
with(CaldavTaskMaker.TASK, task.id)
))
@ -215,7 +212,14 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
?.let { taskDao.fetch(it.task) }
assertEquals(
listOf(Alarm(task!!.id, 1612972355000, TYPE_SNOOZE).apply { id = 1 }),
listOf(
Alarm(
id = 1,
task = task!!.id,
time = 1612972355000,
type = TYPE_SNOOZE
)
),
alarmDao.getAlarms(task.id)
)
}
@ -224,7 +228,13 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
fun pushSnoozeTime() = withTZ(CHICAGO) {
val (listId, list) = openTaskDao.insertList()
val taskId = taskDao.createNew(newTask())
alarmDao.insert(Alarm(taskId, DateTime(2021, 2, 4, 13, 30).millis, TYPE_SNOOZE))
alarmDao.insert(
Alarm(
task = taskId,
time = DateTime(2021, 2, 4, 13, 30).millis,
type = TYPE_SNOOZE
)
)
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
@ -243,7 +253,13 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
fun dontPushLapsedSnoozeTime() = withTZ(CHICAGO) {
val (listId, list) = openTaskDao.insertList()
val taskId = taskDao.createNew(newTask())
alarmDao.insert(Alarm(taskId, DateTime(2021, 2, 4, 13, 30).millis, TYPE_SNOOZE))
alarmDao.insert(
Alarm(
task = taskId,
time = DateTime(2021, 2, 4, 13, 30).millis,
type = TYPE_SNOOZE
)
)
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
@ -259,17 +275,18 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
}
@Test
fun removeSnoozeTime() = runBlocking {
fun removeSnoozeTime() = withTZ(CHICAGO) {
val (listId, list) = withVtodo(SNOOZED)
synchronizer.sync()
val task = caldavDao.getTaskByRemoteId(list.uuid!!, "4CBBC669-70E3-474D-A0A3-0FC42A14A5A5")
?: throw IllegalStateException("Missing task")
val snooze = alarmDao.getSnoozed(listOf(task.task))
assertEquals(1, snooze.size)
alarmDao.delete(snooze.first())
assertTrue(alarmDao.getSnoozed(listOf(task.task)).isEmpty())
assertEquals(
listOf(Alarm(1, task.id, DateTime(2021, 2, 10, 9, 52, 35).millis, TYPE_SNOOZE)),
alarmDao.getAlarms(1)
)
alarmDao.deleteSnoozed(listOf(1))
taskDao.touch(task.task)
synchronizer.sync()
@ -283,9 +300,9 @@ class OpenTasksPropertiesTests : OpenTasksTest() {
}
private suspend fun insertTag(task: Task, name: String) =
newTagData(with(NAME, name))
.apply { tagDataDao.createNew(this) }
.let { tagDao.insert(newTag(with(TASK, task), with(TAGDATA, it))) }
TagData(name = name)
.apply { tagDataDao.insert(this) }
.let { tagDao.insert(Tag(task = task.id, taskUid = task.uuid, tagUid = it.remoteId)) }
companion object {
private val CHICAGO = TimeZone.getTimeZone("America/Chicago")

@ -4,11 +4,13 @@ import com.natpryce.makeiteasy.MakeItEasy.with
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS
import org.tasks.data.CaldavCalendar
import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavAccount.Companion.TYPE_OPENTASKS
import org.tasks.data.entity.CaldavCalendar
import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
@ -38,10 +40,12 @@ class OpenTasksSynchronizerTest : OpenTasksTest() {
@Test
fun deleteRemovedAccounts() = runBlocking {
caldavDao.insert(CaldavAccount().apply {
uuid = "bitfire.at.davdroid:test_account"
accountType = TYPE_OPENTASKS
})
caldavDao.insert(
CaldavAccount(
uuid = "bitfire.at.davdroid:test_account",
accountType = TYPE_OPENTASKS,
)
)
synchronizer.sync()
@ -64,10 +68,12 @@ class OpenTasksSynchronizerTest : OpenTasksTest() {
@Test
fun removeMissingLists() = runBlocking {
val (_, list) = openTaskDao.insertList(url = "url1")
caldavDao.insert(CaldavCalendar().apply {
account = list.account
url = "url2"
})
caldavDao.insert(
CaldavCalendar(
account = list.account,
url = "url2",
)
)
synchronizer.sync()

@ -3,8 +3,8 @@ package org.tasks.opentasks
import com.todoroo.astrid.dao.TaskDao
import org.junit.Before
import org.tasks.R
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDao
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.dao.CaldavDao
import org.tasks.injection.InjectingTestCase
import org.tasks.preferences.Preferences
import javax.inject.Inject

@ -4,12 +4,13 @@ import android.content.ContentProviderResult
import android.content.Context
import at.bitfire.ical4android.BatchOperation
import at.bitfire.ical4android.Task
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.qualifiers.ApplicationContext
import org.dmfs.tasks.contract.TaskContract
import org.tasks.TestUtilities
import org.tasks.data.CaldavCalendar
import org.tasks.data.CaldavDao
import org.dmfs.tasks.contract.TaskContract.TaskListColumns.ACCESS_LEVEL_OWNER
import org.tasks.caldav.iCalendar
import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.dao.CaldavDao
import org.tasks.data.MyAndroidTask
import org.tasks.data.OpenTaskDao
import javax.inject.Inject
@ -19,10 +20,11 @@ class TestOpenTaskDao @Inject constructor(
private val caldavDao: CaldavDao
) : OpenTaskDao(context, caldavDao) {
suspend fun insertList(
name: String = DEFAULT_LIST,
type: String = DEFAULT_TYPE,
account: String = DEFAULT_ACCOUNT,
url: String = UUIDHelper.newUUID(),
name: String = DEFAULT_LIST,
type: String = DEFAULT_TYPE,
account: String = DEFAULT_ACCOUNT,
url: String = UUIDHelper.newUUID(),
accessLevel: Int = ACCESS_LEVEL_OWNER,
): Pair<Long, CaldavCalendar> {
val uri = taskLists.buildUpon()
.appendQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER, "true")
@ -34,19 +36,21 @@ class TestOpenTaskDao @Inject constructor(
.withValue(TaskContract.CommonSyncColumns._SYNC_ID, url)
.withValue(TaskContract.TaskListColumns.LIST_NAME, name)
.withValue(TaskContract.TaskLists.SYNC_ENABLED, "1")
.withValue(TaskContract.TaskLists.ACCESS_LEVEL, accessLevel)
)
val calendar = CaldavCalendar(
uuid = UUIDHelper.newUUID(),
name = name,
account = "$type:$account",
url = url,
)
return Pair(result.uri!!.lastPathSegment!!.toLong(), CaldavCalendar().apply {
uuid = UUIDHelper.newUUID()
this.name = name
this.account = "$type:$account"
this.url = url
caldavDao.insert(this)
})
caldavDao.insert(calendar)
return Pair(result.uri!!.lastPathSegment!!.toLong(), calendar)
}
fun insertTask(listId: Long, vtodo: String) {
val ops = ArrayList<BatchOperation.CpoBuilder>()
val task = MyAndroidTask(TestUtilities.fromString(vtodo))
val task = MyAndroidTask(iCalendar.fromVtodo(vtodo)!!)
ops.add(task.toBuilder(tasks).withValue(TaskContract.TaskColumns.LIST_ID, listId))
task.enqueueProperties(properties, ops, 0)
applyOperation(*ops.toTypedArray())

@ -3,9 +3,9 @@ package org.tasks.preferences
import android.annotation.SuppressLint
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.todoroo.astrid.data.Task.Companion.NOTIFY_AFTER_DEADLINE
import com.todoroo.astrid.data.Task.Companion.NOTIFY_AT_DEADLINE
import com.todoroo.astrid.data.Task.Companion.NOTIFY_AT_START
import org.tasks.data.entity.Task.Companion.NOTIFY_AFTER_DEADLINE
import org.tasks.data.entity.Task.Companion.NOTIFY_AT_DEADLINE
import org.tasks.data.entity.Task.Companion.NOTIFY_AT_START
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test

@ -9,10 +9,10 @@ import org.tasks.TestUtilities.withTZ
import org.tasks.analytics.Firebase
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.locale.Locale
import org.tasks.time.DateTime
import java.text.ParseException
import java.util.*
import java.util.Locale
import java.util.TimeZone
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@ -85,7 +85,7 @@ class RepeatRuleToStringTest : InjectingTestCase() {
Freeze.freezeAt(DateTime(2021, 1, 4)) {
withTZ(BERLIN) {
assertEquals(
"Repeats daily until February 23",
"Repeats daily, ends on February 23",
toString("RRULE:FREQ=DAILY;UNTIL=20210223;INTERVAL=1")
)
}
@ -97,7 +97,7 @@ class RepeatRuleToStringTest : InjectingTestCase() {
Freeze.freezeAt(DateTime(2021, 1, 4)) {
withTZ(LONDON) {
assertEquals(
"Repeats daily until February 23",
"Repeats daily, ends on February 23",
toString("RRULE:FREQ=DAILY;UNTIL=20210223;INTERVAL=1")
)
}
@ -109,7 +109,7 @@ class RepeatRuleToStringTest : InjectingTestCase() {
Freeze.freezeAt(DateTime(2021, 1, 4)) {
withTZ(NEW_YORK) {
assertEquals(
"Repeats daily until February 23",
"Repeats daily, ends on February 23",
toString("RRULE:FREQ=DAILY;UNTIL=20210223;INTERVAL=1")
)
}
@ -122,8 +122,11 @@ class RepeatRuleToStringTest : InjectingTestCase() {
private fun toString(language: String?, rrule: String): String? {
return try {
val locale = Locale(java.util.Locale.getDefault(), language)
RepeatRuleToString(locale.createConfigurationContext(context), locale, firebase)
val locale = language?.let { Locale.forLanguageTag(it) } ?: Locale.getDefault()
val configuration = context.resources.configuration.apply {
setLocale(locale)
}
RepeatRuleToString(context.createConfigurationContext(configuration), locale, firebase)
.toString(rrule)
} catch (e: ParseException) {
throw RuntimeException(e)

@ -1,9 +1,11 @@
package org.tasks.ui.editviewmodel
import androidx.lifecycle.SavedStateHandle
import com.todoroo.astrid.activity.TaskEditFragment
import com.todoroo.astrid.alarms.AlarmService
import com.todoroo.astrid.dao.Database
import org.tasks.data.db.Database
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import com.todoroo.astrid.gcal.GCalHelper
import com.todoroo.astrid.service.TaskCompleter
import com.todoroo.astrid.service.TaskDeleter
@ -12,11 +14,12 @@ import com.todoroo.astrid.timers.TimerPlugin
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.tasks.calendars.CalendarEventProvider
import org.tasks.data.AlarmDao
import org.tasks.data.LocationDao
import org.tasks.data.TagDataDao
import org.tasks.data.dao.AlarmDao
import org.tasks.data.dao.LocationDao
import org.tasks.data.dao.TagDataDao
import org.tasks.data.dao.UserActivityDao
import org.tasks.data.getLocation
import org.tasks.injection.InjectingTestCase
import org.tasks.location.GeofenceApi
import org.tasks.preferences.DefaultFilterProvider
@ -41,42 +44,41 @@ open class BaseTaskEditViewModelTest : InjectingTestCase() {
@Inject lateinit var locationDao: LocationDao
@Inject lateinit var tagDataDao: TagDataDao
@Inject lateinit var alarmDao: AlarmDao
@Inject lateinit var userActivityDao: UserActivityDao
protected lateinit var viewModel: TaskEditViewModel
@Before
override fun setUp() {
super.setUp()
protected fun setup(task: Task) = runBlocking {
viewModel = TaskEditViewModel(
context,
taskDao,
taskDeleter,
timerPlugin,
PermissivePermissionChecker(context),
calendarEventProvider,
gCalHelper,
taskMover,
db.locationDao,
geofenceApi,
db.tagDao,
db.tagDataDao,
preferences,
db.googleTaskDao,
db.caldavDao,
taskCompleter,
alarmService,
context,
SavedStateHandle().apply {
set(TaskEditFragment.EXTRA_TASK, task)
set(TaskEditFragment.EXTRA_LIST, defaultFilterProvider.getList(task))
set(TaskEditFragment.EXTRA_LOCATION, locationDao.getLocation(task, preferences))
set(TaskEditFragment.EXTRA_TAGS, tagDataDao.getTags(task))
set(TaskEditFragment.EXTRA_ALARMS, alarmDao.getAlarms(task))
},
taskDao,
taskDeleter,
timerPlugin,
PermissivePermissionChecker(context),
calendarEventProvider,
gCalHelper,
taskMover,
db.locationDao(),
geofenceApi,
db.tagDao(),
db.tagDataDao(),
preferences,
db.googleTaskDao(),
db.caldavDao(),
taskCompleter,
alarmService,
MutableSharedFlow(),
MutableSharedFlow(),
)
}
protected fun setup(task: Task) = runBlocking {
viewModel.setup(
task,
defaultFilterProvider.getList(task),
locationDao.getLocation(task, preferences),
tagDataDao.getTags(task),
alarmDao.getAlarms(task)
userActivityDao = userActivityDao,
taskAttachmentDao = db.taskAttachmentDao(),
alarmDao = db.alarmDao(),
)
}

@ -1,7 +1,7 @@
package org.tasks.ui.editviewmodel
import com.natpryce.makeiteasy.MakeItEasy
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import org.junit.Assert
@ -16,7 +16,7 @@ class PriorityTests : BaseTaskEditViewModelTest() {
fun changePriorityCausesChange() {
setup(TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH)))
viewModel.priority = Task.Priority.MEDIUM
viewModel.priority.value = Task.Priority.MEDIUM
Assert.assertTrue(viewModel.hasChanges())
}
@ -25,7 +25,7 @@ class PriorityTests : BaseTaskEditViewModelTest() {
fun applyPriorityChange() {
val task = TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH))
setup(task)
viewModel.priority = Task.Priority.MEDIUM
viewModel.priority.value = Task.Priority.MEDIUM
save()
@ -36,8 +36,8 @@ class PriorityTests : BaseTaskEditViewModelTest() {
fun noChangeWhenRevertingPriority() {
setup(TaskMaker.newTask(MakeItEasy.with(TaskMaker.PRIORITY, Task.Priority.HIGH)))
viewModel.priority = Task.Priority.MEDIUM
viewModel.priority = Task.Priority.HIGH
viewModel.priority.value = Task.Priority.MEDIUM
viewModel.priority.value = Task.Priority.HIGH
Assert.assertFalse(viewModel.hasChanges())
}

@ -1,65 +1,79 @@
package org.tasks.ui.editviewmodel
import com.todoroo.astrid.data.Task
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.service.TaskCreator.Companion.setDefaultReminders
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.*
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.data.Alarm
import org.tasks.data.Alarm.Companion.whenOverdue
import org.tasks.R
import org.tasks.data.createDueDate
import org.tasks.data.entity.Alarm
import org.tasks.data.entity.Alarm.Companion.whenDue
import org.tasks.data.entity.Alarm.Companion.whenOverdue
import org.tasks.data.entity.Alarm.Companion.whenStarted
import org.tasks.data.entity.Task
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker.DUE_TIME
import org.tasks.makers.TaskMaker.START_DATE
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTimeUtils.currentTimeMillis
import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2.currentTimeMillis
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class ReminderTests : BaseTaskEditViewModelTest() {
@Test
fun whenStartReminder() = runBlocking {
val task = newTask()
task.defaultReminders(Task.NOTIFY_AT_START)
setup(task)
viewModel.hideUntil = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, currentTimeMillis())
preferences.setStringSet(
R.string.p_default_reminders_key,
hashSetOf(Task.NOTIFY_AT_START.toString())
)
val task = newTask(with(START_DATE, DateTime()))
task.setDefaultReminders(preferences)
save()
setup(task)
assertEquals(
listOf(Alarm(1, 0, Alarm.TYPE_REL_START).apply { id = 1 }),
alarmDao.getAlarms(task.id)
listOf(Alarm(type = Alarm.TYPE_REL_START)),
viewModel.selectedAlarms.value
)
}
@Test
fun whenDueReminder() = runBlocking {
val task = newTask()
task.defaultReminders(Task.NOTIFY_AT_DEADLINE)
setup(task)
viewModel.dueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, currentTimeMillis())
preferences.setStringSet(
R.string.p_default_reminders_key,
hashSetOf(Task.NOTIFY_AT_DEADLINE.toString())
)
val task = newTask(with(DUE_TIME, DateTime()))
task.setDefaultReminders(preferences)
save()
setup(task)
assertEquals(
listOf(Alarm(1, 0, Alarm.TYPE_REL_END).apply { id = 1 }),
alarmDao.getAlarms(task.id)
listOf(Alarm(type = Alarm.TYPE_REL_END)),
viewModel.selectedAlarms.value
)
}
@Test
fun whenOverDueReminder() = runBlocking {
val task = newTask()
task.defaultReminders(Task.NOTIFY_AFTER_DEADLINE)
setup(task)
viewModel.dueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, currentTimeMillis())
preferences.setStringSet(
R.string.p_default_reminders_key,
hashSetOf(Task.NOTIFY_AFTER_DEADLINE.toString())
)
val task = newTask(with(DUE_TIME, DateTime()))
task.setDefaultReminders(preferences)
save()
setup(task)
assertEquals(
listOf(whenOverdue(1).apply { id = 1 }),
alarmDao.getAlarms(task.id)
listOf(whenOverdue(0)),
viewModel.selectedAlarms.value
)
}
@ -114,4 +128,67 @@ class ReminderTests : BaseTaskEditViewModelTest() {
assertFalse(taskDao.fetch(task.id)!!.isNotifyModeFive)
assertTrue(taskDao.fetch(task.id)!!.isNotifyModeNonstop)
}
}
@Test
fun noDefaultRemindersWithNoDates() = runBlocking {
val task = newTask()
task.setDefaultReminders(preferences)
setup(task)
save()
assertTrue(alarmDao.getAlarms(task.id).isEmpty())
}
@Test
fun addDefaultRemindersWhenAddingDueDate() = runBlocking {
preferences.setStringSet(
R.string.p_default_reminders_key,
hashSetOf(
Task.NOTIFY_AT_DEADLINE.toString(),
Task.NOTIFY_AFTER_DEADLINE.toString(),
)
)
val task = newTask()
setup(task)
viewModel.setDueDate(
createDueDate(
Task.URGENCY_SPECIFIC_DAY_TIME,
currentTimeMillis()
)
)
save()
assertEquals(
listOf(whenDue(1).copy(id = 1), whenOverdue(1).copy(id = 2)),
alarmDao.getAlarms(task.id)
)
}
@Test
fun addDefaultRemindersWhenAddingStartDate() = runBlocking {
preferences.setStringSet(
R.string.p_default_reminders_key,
hashSetOf(Task.NOTIFY_AT_START.toString())
)
val task = newTask()
setup(task)
viewModel.setStartDate(
createDueDate(
Task.URGENCY_SPECIFIC_DAY_TIME,
currentTimeMillis()
)
)
save()
assertEquals(
listOf(whenStarted(1).copy(id = 1)),
alarmDao.getAlarms(task.id)
)
}
}

@ -1,44 +0,0 @@
package org.tasks.ui.editviewmodel
import com.natpryce.makeiteasy.MakeItEasy.with
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.injection.ProductionModule
import org.tasks.makers.TaskMaker
import org.tasks.makers.TaskMaker.newTask
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class RepeatTests : BaseTaskEditViewModelTest() {
@Test
fun changeRepeatAfterCompletion() = runBlocking {
val task = newTask(with(TaskMaker.RECUR, "FREQ=DAILY;INTERVAL=1"))
setup(task)
viewModel.repeatAfterCompletion = true
save()
assertEquals(
"FREQ=DAILY;INTERVAL=1;FROM=COMPLETION",
taskDao.fetch(task.id)!!.recurrence)
}
@Test
fun removeRepeatAfterCompletion() = runBlocking {
val task = newTask()
task.recurrence = "RRULE:FREQ=DAILY;INTERVAL=1;FROM=COMPLETION"
setup(task)
viewModel.repeatAfterCompletion = false
save()
assertEquals(
"RRULE:FREQ=DAILY;INTERVAL=1",
taskDao.fetch(task.id)!!.recurrence)
}
}

@ -1,6 +1,6 @@
package org.tasks.ui.editviewmodel
import com.todoroo.astrid.data.Task
import org.tasks.data.entity.Task
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -33,7 +33,7 @@ class TaskEditViewModelTest : BaseTaskEditViewModelTest() {
fun dontSaveTaskTwice() = runBlocking {
setup(newTask())
viewModel.priority = Task.Priority.HIGH
viewModel.priority.value = Task.Priority.HIGH
assertTrue(save())

@ -0,0 +1,161 @@
package org.tasks.ui.editviewmodel
import com.todoroo.astrid.core.BuiltInFilterExposer
import org.tasks.data.entity.Task
import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.analytics.Firebase
import org.tasks.billing.Inventory
import org.tasks.data.dao.DeletionDao
import org.tasks.data.dao.TaskDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import org.tasks.ui.TaskListViewModel
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class TaskListViewModelTest : InjectingTestCase() {
private lateinit var viewModel: TaskListViewModel
@Inject lateinit var preferences: Preferences
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var taskDeleter: TaskDeleter
@Inject lateinit var deletionDao: DeletionDao
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
@Inject lateinit var inventory: Inventory
@Inject lateinit var firebase: Firebase
@Before
override fun setUp() {
super.setUp()
viewModel = TaskListViewModel(
context = context,
preferences = preferences,
taskDao = taskDao,
deletionDao = deletionDao,
taskDeleter = taskDeleter,
localBroadcastManager = localBroadcastManager,
inventory = inventory,
firebase = firebase,
)
viewModel.setFilter(BuiltInFilterExposer.getMyTasksFilter(context.resources))
}
@Test
fun clearCompletedTask() = runBlocking {
val task = taskDao.createNew(
Task(completionDate = currentTimeMillis())
)
clearCompleted()
assertTrue(taskDao.fetch(task)!!.isDeleted)
}
@Test
fun dontDeleteTaskWithRecurringParent() = runBlocking {
val parent = taskDao.createNew(
Task(
recurrence = "RRULE:FREQ=DAILY;INTERVAL=1"
)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
clearCompleted()
assertFalse(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun dontDeleteTaskWithRecurringGrandparent() = runBlocking {
val grandparent = taskDao.createNew(
Task(recurrence = "RRULE:FREQ=DAILY;INTERVAL=1")
)
val parent = taskDao.createNew(
Task(parent = grandparent)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
clearCompleted()
assertFalse(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearGrandchildWithNoRecurringAncestors() = runBlocking {
val grandparent = taskDao.createNew(Task())
val parent = taskDao.createNew(
Task(parent = grandparent)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearGrandchildWithCompletedRecurringAncestor() = runBlocking {
val grandparent = taskDao.createNew(
Task(
recurrence = "RRULE:FREQ=DAILY;INTERVAL=1",
completionDate = currentTimeMillis(),
)
)
val parent = taskDao.createNew(
Task(parent = grandparent)
)
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
@Test
fun clearHiddenSubtask() = runBlocking {
preferences.showCompleted = false
val parent = taskDao.createNew(Task())
val child = taskDao.createNew(
Task(
parent = parent,
completionDate = currentTimeMillis(),
)
)
clearCompleted()
assertTrue(taskDao.fetch(child)!!.isDeleted)
}
private suspend fun clearCompleted() = viewModel.markDeleted(viewModel.getTasksToClear())
}

@ -1,7 +1,7 @@
package org.tasks.ui.editviewmodel
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task.Priority.Companion.HIGH
import org.tasks.data.entity.Task.Priority.Companion.HIGH
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -29,7 +29,7 @@ class TitleTests : BaseTaskEditViewModelTest() {
val task = newTask()
setup(task)
viewModel.priority = HIGH
viewModel.priority.value = HIGH
save()

@ -7,7 +7,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.tasks.LocalBroadcastManager
import org.tasks.data.CaldavDao
import org.tasks.data.dao.CaldavDao
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.preferences.Preferences

@ -1,7 +1,7 @@
package org.tasks.caldav
import androidx.test.annotation.UiThreadTest
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
@ -9,7 +9,7 @@ import org.junit.Assert.assertEquals
import org.junit.Test
import org.tasks.R
import org.tasks.billing.Inventory
import org.tasks.data.CaldavAccount
import org.tasks.data.entity.CaldavAccount
import org.tasks.injection.ProductionModule
import javax.inject.Inject
@ -25,10 +25,8 @@ class CaldavSubscriptionTest : CaldavTest() {
inventory.clear()
inventory.add(emptyList())
account = CaldavAccount().apply {
uuid = UUIDHelper.newUUID()
id = caldavDao.insert(this)
}
account = CaldavAccount(uuid = UUIDHelper.newUUID())
.let { it.copy(id = caldavDao.insert(it)) }
synchronizer.sync(account)

@ -1,75 +0,0 @@
package org.tasks
import android.content.Context
import at.bitfire.ical4android.Task.Companion.tasksFromReader
import com.todoroo.astrid.data.Task
import kotlinx.coroutines.runBlocking
import org.tasks.caldav.applyRemote
import org.tasks.caldav.iCalendar.Companion.reminders
import org.tasks.data.Alarm
import org.tasks.data.CaldavTask
import org.tasks.preferences.Preferences
import org.tasks.time.DateTime
import java.io.StringReader
import java.nio.file.Files
import java.nio.file.Paths
import java.util.*
object TestUtilities {
fun withTZ(id: String, runnable: suspend () -> Unit) = withTZ(TimeZone.getTimeZone(id), runnable)
fun withTZ(tz: TimeZone, runnable: suspend () -> Unit) {
val def = TimeZone.getDefault()
try {
TimeZone.setDefault(tz)
runBlocking {
runnable()
}
} finally {
TimeZone.setDefault(def)
}
}
fun assertEquals(expected: Long, actual: DateTime) =
org.junit.Assert.assertEquals(expected, actual.millis)
fun assertEquals(expected: DateTime, actual: Long?) =
org.junit.Assert.assertEquals(expected.millis, actual)
fun newPreferences(context: Context): Preferences {
return Preferences(context, "test_preferences")
}
fun vtodo(path: String): Task {
val task = Task()
task.applyRemote(fromResource(path), null)
return task
}
val String.alarms: List<Alarm>
get() = fromResource(this).reminders
fun setup(path: String): Triple<Task, CaldavTask, at.bitfire.ical4android.Task> {
val task = Task()
val vtodo = readFile(path)
val remote = fromString(vtodo)
task.applyRemote(remote, null)
return Triple(task, CaldavTask(), remote)
}
private fun fromResource(path: String): at.bitfire.ical4android.Task =
fromString(readFile(path))
fun readFile(path: String): String {
val uri = javaClass.classLoader?.getResource(path)?.toURI()
?: throw IllegalArgumentException()
val paths = Paths.get(uri)
return String(Files.readAllBytes(paths), Charsets.UTF_8)
}
fun fromString(task: String): at.bitfire.ical4android.Task =
tasksFromReader(StringReader(task))
.takeIf { it.size == 1 }
?.first()
?: throw IllegalStateException()
}

@ -1,32 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import org.tasks.data.Alarm.Companion.TYPE_DATE_TIME
import org.tasks.date.DateTimeUtils.newDateTime
import org.tasks.jobs.AlarmEntry
import org.tasks.makers.Maker.make
import org.tasks.time.DateTime
object AlarmEntryMaker {
val ID: Property<AlarmEntry, Long> = newProperty()
val TASK: Property<AlarmEntry, Long> = newProperty()
val TIME: Property<AlarmEntry, DateTime> = newProperty()
val TYPE: Property<AlarmEntry, Int> = newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<AlarmEntry> ->
AlarmEntry(
lookup.valueOf(ID, 0L),
lookup.valueOf(TASK, 0L),
lookup.valueOf(TIME, newDateTime()).millis,
lookup.valueOf(TYPE, TYPE_DATE_TIME)
)
}
fun newAlarmEntry(vararg properties: PropertyValue<in AlarmEntry?, *>): AlarmEntry {
return make(instantiator, *properties)
}
}

@ -1,24 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyValue
import org.tasks.data.CaldavCalendar
import org.tasks.makers.Maker.make
object CaldavCalendarMaker {
val ACCOUNT: Property<CaldavCalendar, String> = newProperty()
val UUID: Property<CaldavCalendar, String> = newProperty()
private val instantiator = Instantiator<CaldavCalendar> { lookup ->
val calendar = CaldavCalendar()
calendar.account = lookup.valueOf(ACCOUNT, "account")
calendar.uuid = lookup.valueOf(UUID, "uuid")
calendar
}
fun newCaldavCalendar(vararg properties: PropertyValue<in CaldavCalendar?, *>): CaldavCalendar {
return make(instantiator, *properties)
}
}

@ -1,27 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import org.tasks.data.Geofence
object GeofenceMaker {
val PLACE: Property<Geofence, String> = Property.newProperty()
val TASK: Property<Geofence, Long> = Property.newProperty()
val ARRIVAL: Property<Geofence, Boolean> = Property.newProperty()
val DEPARTURE: Property<Geofence, Boolean> = Property.newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<Geofence> ->
val geofence = Geofence()
geofence.place = lookup.valueOf(PLACE, "")
geofence.task = lookup.valueOf(TASK, 1)
geofence.isArrival = lookup.valueOf(ARRIVAL, false)
geofence.isDeparture = lookup.valueOf(DEPARTURE, false)
geofence
}
fun newGeofence(vararg properties: PropertyValue<in Geofence?, *>): Geofence {
return Maker.make(instantiator, *properties)
}
}

@ -1,24 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import org.tasks.data.GoogleTaskList
object GoogleTaskListMaker {
val REMOTE_ID: Property<GoogleTaskList, String> = Property.newProperty()
val ACCOUNT: Property<GoogleTaskList, String?> = Property.newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<GoogleTaskList> ->
val list = GoogleTaskList()
list.remoteId = lookup.valueOf(REMOTE_ID, "1234")
list.account = lookup.valueOf(ACCOUNT, null as String?)
list.setColor(0)
list
}
fun newGoogleTaskList(vararg properties: PropertyValue<in GoogleTaskList?, *>): GoogleTaskList {
return Maker.make(instantiator, *properties)
}
}

@ -1,33 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.GoogleTask
import org.tasks.makers.Maker.make
object GoogleTaskMaker {
val LIST: Property<GoogleTask, String> = newProperty()
val ORDER: Property<GoogleTask, Long> = newProperty()
val REMOTE_ID: Property<GoogleTask, String> = newProperty()
val TASK: Property<GoogleTask, Long> = newProperty()
val PARENT: Property<GoogleTask, Long> = newProperty()
val REMOTE_PARENT: Property<GoogleTask, String?> = newProperty()
private val instantiator = Instantiator<GoogleTask> {
val task = GoogleTask()
task.listId = it.valueOf(LIST, "1")
task.order = it.valueOf(ORDER, 0)
task.remoteId = it.valueOf(REMOTE_ID, UUIDHelper.newUUID())
task.task = it.valueOf(TASK, 1)
task.parent = it.valueOf(PARENT, 0L)
task.remoteParent = it.valueOf(REMOTE_PARENT, null as String?)
task
}
fun newGoogleTask(vararg properties: PropertyValue<in GoogleTask?, *>): GoogleTask {
return make(instantiator, *properties)
}
}

@ -1,36 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.api.FilterListItem.NO_ORDER
import org.tasks.data.GoogleTaskList
import org.tasks.makers.Maker.make
object GtaskListMaker {
val ID: Property<GoogleTaskList, Long> = newProperty()
val ACCOUNT: Property<GoogleTaskList, String> = newProperty()
val REMOTE_ID: Property<GoogleTaskList, String> = newProperty()
val LAST_SYNC: Property<GoogleTaskList, Long> = newProperty()
val NAME: Property<GoogleTaskList, String> = newProperty()
private val ORDER: Property<GoogleTaskList, Int> = newProperty()
private val COLOR: Property<GoogleTaskList, Int> = newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<GoogleTaskList> ->
val list = GoogleTaskList()
list.id = lookup.valueOf(ID, 0L)
list.account = lookup.valueOf(ACCOUNT, "account")
list.remoteId = lookup.valueOf(REMOTE_ID, "1")
list.title = lookup.valueOf(NAME, "Default")
list.order = lookup.valueOf(ORDER, NO_ORDER)
list.lastSync = lookup.valueOf(LAST_SYNC, 0L)
list.setColor(lookup.valueOf(COLOR, 0))
list
}
fun newGtaskList(vararg properties: PropertyValue<in GoogleTaskList?, *>): GoogleTaskList {
return make(instantiator, *properties)
}
}

@ -1,26 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.Place
object PlaceMaker {
val LATITUDE: Property<Place, Double> = Property.newProperty()
val LONGITUDE: Property<Place, Double> = Property.newProperty()
val UUID: Property<Place, String> = Property.newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<Place> ->
val place = Place()
place.uid = lookup.valueOf(UUID, UUIDHelper.newUUID())
place.latitude = lookup.valueOf(LATITUDE, 0.0)
place.longitude = lookup.valueOf(LONGITUDE, 0.0)
place
}
fun newPlace(vararg properties: PropertyValue<in Place?, *>): Place {
return Maker.make(instantiator, *properties)
}
}

@ -1,25 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import org.tasks.data.TagData
import org.tasks.makers.Maker.make
object TagDataMaker {
val NAME: Property<TagData, String> = newProperty()
val UID: Property<TagData, String?> = newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<TagData> ->
val tagData = TagData()
tagData.name = lookup.valueOf(NAME, "tag")
tagData.remoteId = lookup.valueOf(UID, null as String?)
tagData
}
fun newTagData(vararg properties: PropertyValue<in TagData?, *>): TagData {
return make(instantiator, *properties)
}
}

@ -1,35 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.data.Task
import org.tasks.data.Tag
import org.tasks.data.TagData
import org.tasks.makers.Maker.make
object TagMaker {
val TAGDATA: Property<Tag, TagData?> = newProperty()
val TASK: Property<Tag, Task?> = newProperty()
val TAGUID: Property<Tag, String?> = newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<Tag> ->
val tag = Tag()
val task = lookup.valueOf(TASK, null as Task?)!!
tag.task = task.id
tag.setTaskUid(task.uuid)
tag.tagUid = lookup.valueOf(TAGUID, null as String?)
val tagData = lookup.valueOf(TAGDATA, null as TagData?)
if (tagData != null) {
tag.tagUid = tagData.remoteId
}
assert(tag.tagUid != null)
tag
}
fun newTag(vararg properties: PropertyValue<in Tag?, *>): Tag {
return make(instantiator, *properties)
}
}

@ -1,98 +0,0 @@
package org.tasks.makers
import com.natpryce.makeiteasy.Instantiator
import com.natpryce.makeiteasy.Property
import com.natpryce.makeiteasy.Property.newProperty
import com.natpryce.makeiteasy.PropertyLookup
import com.natpryce.makeiteasy.PropertyValue
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.data.Task.Companion.HIDE_UNTIL_SPECIFIC_DAY
import com.todoroo.astrid.data.Task.Companion.NO_UUID
import org.tasks.Strings
import org.tasks.date.DateTimeUtils
import org.tasks.makers.Maker.make
import org.tasks.time.DateTime
object TaskMaker {
val ID: Property<Task, Long> = newProperty()
val DUE_DATE: Property<Task, DateTime?> = newProperty()
val DUE_TIME: Property<Task, DateTime?> = newProperty()
val START_DATE: Property<Task, DateTime?> = newProperty()
val REMINDER_LAST: Property<Task, DateTime?> = newProperty()
val HIDE_TYPE: Property<Task, Int> = newProperty()
val REMINDERS: Property<Task, Int> = newProperty()
val MODIFICATION_TIME: Property<Task, DateTime> = newProperty()
val CREATION_TIME: Property<Task, DateTime> = newProperty()
val COMPLETION_TIME: Property<Task, DateTime> = newProperty()
val DELETION_TIME: Property<Task, DateTime?> = newProperty()
val RECUR: Property<Task, String?> = newProperty()
val AFTER_COMPLETE: Property<Task, Boolean> = newProperty()
val TITLE: Property<Task, String?> = newProperty()
val PRIORITY: Property<Task, Int> = newProperty()
val PARENT: Property<Task, Long> = newProperty()
val UUID: Property<Task, String> = newProperty()
val COLLAPSED: Property<Task, Boolean> = newProperty()
val DESCRIPTION: Property<Task, String?> = newProperty()
private val instantiator = Instantiator { lookup: PropertyLookup<Task> ->
val task = Task()
val title = lookup.valueOf(TITLE, null as String?)
if (!Strings.isNullOrEmpty(title)) {
task.title = title!!
}
val id = lookup.valueOf(ID, Task.NO_ID)
if (id != Task.NO_ID) {
task.id = id
}
val priority = lookup.valueOf(PRIORITY, -1)
if (priority >= 0) {
task.priority = priority
}
val dueDate = lookup.valueOf(DUE_DATE, null as DateTime?)
if (dueDate != null) {
task.dueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, dueDate.millis)
}
val dueTime = lookup.valueOf(DUE_TIME, null as DateTime?)
if (dueTime != null) {
task.dueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME, dueTime.millis)
}
val completionTime = lookup.valueOf(COMPLETION_TIME, null as DateTime?)
if (completionTime != null) {
task.completionDate = completionTime.millis
}
val deletedTime = lookup.valueOf(DELETION_TIME, null as DateTime?)
if (deletedTime != null) {
task.deletionDate = deletedTime.millis
}
lookup.valueOf(START_DATE, null as DateTime?)?.let {
task.hideUntil = task.createHideUntil(HIDE_UNTIL_SPECIFIC_DAY, it.millis)
}
val hideType = lookup.valueOf(HIDE_TYPE, -1)
if (hideType >= 0) {
task.hideUntil = task.createHideUntil(hideType, 0)
}
val reminderFlags = lookup.valueOf(REMINDERS, -1)
if (reminderFlags >= 0) {
task.ringFlags = reminderFlags
}
val reminderLast = lookup.valueOf(REMINDER_LAST, null as DateTime?)
if (reminderLast != null) {
task.reminderLast = reminderLast.millis
}
lookup.valueOf(RECUR, null as String?)?.let {
task.setRecurrence(it, lookup.valueOf(AFTER_COMPLETE, false))
}
task.notes = lookup.valueOf(DESCRIPTION, null as String?)
task.isCollapsed = lookup.valueOf(COLLAPSED, false)
task.uuid = lookup.valueOf(UUID, NO_UUID)
val creationTime = lookup.valueOf(CREATION_TIME, DateTimeUtils.newDateTime())
task.creationDate = creationTime.millis
task.modificationDate = lookup.valueOf(MODIFICATION_TIME, creationTime).millis
task.parent = lookup.valueOf(PARENT, 0L)
task
}
fun newTask(vararg properties: PropertyValue<in Task?, *>): Task {
return make(instantiator, *properties)
}
}

@ -3,7 +3,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application tools:ignore="GoogleAppIndexingWarning">
<application
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:exported="true"

@ -5,8 +5,8 @@ import com.facebook.flipper.plugins.network.NetworkReporter
import com.facebook.flipper.plugins.network.NetworkReporter.ResponseInfo
import com.google.api.client.http.*
import com.google.api.client.json.GenericJson
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.helper.UUIDHelper
import org.tasks.data.UUIDHelper
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber
import java.io.ByteArrayOutputStream
import java.io.IOException
@ -18,12 +18,12 @@ internal class FlipperHttpInterceptor<T>(private val plugin: NetworkFlipperPlugi
private set
override fun intercept(request: HttpRequest) {
plugin.reportRequest(toRequestInfo(request, DateUtilities.now()))
plugin.reportRequest(toRequestInfo(request, currentTimeMillis()))
}
@Throws(IOException::class)
override fun interceptResponse(response: HttpResponse) {
plugin.reportResponse(toResponseInfo(response, DateUtilities.now()))
plugin.reportResponse(toResponseInfo(response, currentTimeMillis()))
}
@Throws(IOException::class)

@ -5,7 +5,6 @@ import androidx.annotation.StringRes
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import at.bitfire.cert4android.CustomCertManager.Companion.resetCertificates
import com.todoroo.andlib.utility.DateUtilities.now
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.R
@ -14,6 +13,7 @@ import org.tasks.billing.Inventory
import org.tasks.extensions.Context.toast
import org.tasks.injection.InjectingPreferenceFragment
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.min
@ -62,7 +62,7 @@ class Debug : InjectingPreferenceFragment() {
findPreference(R.string.debug_clear_hints).setOnPreferenceClickListener {
preferences.installDate =
min(preferences.installDate, now() - TimeUnit.DAYS.toMillis(14))
min(preferences.installDate, currentTimeMillis() - TimeUnit.DAYS.toMillis(14))
preferences.lastSubscribeRequest = 0L
preferences.lastReviewRequest = 0L
preferences.shownBeastModeHint = false

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:tools="http://schemas.android.com/tools">
<base-config
cleartextTrafficPermitted="true"
tools:ignore="InsecureBaseConfiguration" />
</network-security-config>

@ -14,4 +14,6 @@ class Firebase @Inject constructor() {
fun addTask(source: String) {}
val subscribeCooldown = false
val moreOptionsBadge = false
val moreOptionsSolid = false
}

@ -2,8 +2,30 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>
<application tools:ignore="GoogleAppIndexingWarning">
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false"/>
<meta-data
android:name="firebase_analytics_collection_enabled"
android:value="false"/>
<meta-data
android:name="google_analytics_adid_collection_enabled"
android:value="false" />
<meta-data
android:name="google_analytics_ssaid_collection_enabled"
android:value="false" />
<meta-data
android:name="google_analytics_default_allow_ad_personalization_signals"
android:value="false" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_key" />

@ -7,11 +7,11 @@ import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import com.todoroo.andlib.utility.DateUtilities.now
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.R
import org.tasks.jobs.WorkManager
import org.tasks.preferences.Preferences
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@ -64,14 +64,20 @@ class Firebase @Inject constructor(
}
private val installCooldown: Boolean
get() = preferences.installDate + days("install_cooldown", 14L) > now()
get() = preferences.installDate + days("install_cooldown", 14L) > currentTimeMillis()
val reviewCooldown: Boolean
get() = installCooldown || preferences.lastReviewRequest + days("review_cooldown", 30L) > now()
get() = installCooldown || preferences.lastReviewRequest + days("review_cooldown", 30L) > currentTimeMillis()
val subscribeCooldown: Boolean
get() = installCooldown
|| preferences.lastSubscribeRequest + days("subscribe_cooldown", 30L) > now()
|| preferences.lastSubscribeRequest + days("subscribe_cooldown", 30L) > currentTimeMillis()
val moreOptionsBadge: Boolean
get() = remoteConfig?.getBoolean("more_options_badge") ?: false
val moreOptionsSolid: Boolean
get() = remoteConfig?.getBoolean("more_options_solid") ?: false
private fun days(key: String, default: Long): Long =
TimeUnit.DAYS.toMillis(remoteConfig?.getLong(key) ?: default)

@ -3,18 +3,22 @@ package org.tasks.billing
import android.app.Activity
import android.content.Context
import com.android.billingclient.api.AcknowledgePurchaseParams
import com.android.billingclient.api.BillingClient.*
import com.android.billingclient.api.BillingClient.BillingResponseCode
import com.android.billingclient.api.BillingClient.SkuType
import com.android.billingclient.api.BillingClient.newBuilder
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingFlowParams
import com.android.billingclient.api.BillingFlowParams.ProrationMode
import com.android.billingclient.api.BillingFlowParams.SubscriptionUpdateParams
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.ConsumeParams
import com.android.billingclient.api.Purchase.PurchaseState
import com.android.billingclient.api.Purchase.PurchasesResult
import com.android.billingclient.api.PurchasesResult
import com.android.billingclient.api.PurchasesUpdatedListener
import com.android.billingclient.api.SkuDetailsParams
import com.android.billingclient.api.querySkuDetails
import com.android.billingclient.api.consumePurchase
import com.android.billingclient.api.queryPurchasesAsync
import com.android.billingclient.api.querySkuDetails
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.NonCancellable
@ -45,8 +49,8 @@ class BillingClientImpl(
override suspend fun queryPurchases(throwError: Boolean) = try {
executeServiceRequest {
withContext(Dispatchers.IO + NonCancellable) {
val subs = billingClient.queryPurchases(SkuType.SUBS)
val iaps = billingClient.queryPurchases(SkuType.INAPP)
val subs = billingClient.queryPurchasesAsync(SkuType.SUBS)
val iaps = billingClient.queryPurchasesAsync(SkuType.INAPP)
if (subs.success || iaps.success) {
withContext(Dispatchers.Main) {
inventory.clear()
@ -77,7 +81,7 @@ class BillingClientImpl(
purchases?.forEach {
firebase.reportIabResult(
result.responseCodeString,
it.sku,
it.skus.joinToString(","),
it.purchaseState.purchaseStateString
)
}
@ -112,9 +116,12 @@ class BillingClientImpl(
?: throw IllegalStateException("Sku $sku not found")
val params = BillingFlowParams.newBuilder().setSkuDetails(skuDetails)
oldPurchase?.let {
params
.setOldSku(it.sku, it.purchaseToken)
.setReplaceSkusProrationMode(ProrationMode.IMMEDIATE_WITH_TIME_PRORATION)
params.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder()
.setOldSkuPurchaseToken(it.purchaseToken)
.setReplaceSkusProrationMode(ProrationMode.IMMEDIATE_WITH_TIME_PRORATION)
.build()
)
}
if (activity is OnPurchasesUpdated) {
onPurchasesUpdated = activity
@ -129,7 +136,7 @@ class BillingClientImpl(
.setPurchaseToken(purchase.purchaseToken)
.build()
withContext(Dispatchers.IO) {
suspendCoroutine<BillingResult> { cont ->
suspendCoroutine { cont ->
billingClient.acknowledgePurchase(params) {
Timber.d("acknowledge: ${it.responseCodeString} $purchase")
cont.resume(it)
@ -192,7 +199,7 @@ class BillingClientImpl(
const val STATE_PURCHASED = PurchaseState.PURCHASED
private val PurchasesResult.success: Boolean
get() = responseCode == BillingResponseCode.OK
get() = billingResult.responseCode == BillingResponseCode.OK
private val BillingResult.success: Boolean
get() = responseCode == BillingResponseCode.OK
@ -225,6 +232,6 @@ class BillingClientImpl(
get() = billingResult.responseCodeString
private val PurchasesResult.purchases: List<com.android.billingclient.api.Purchase>
get() = purchasesList ?: emptyList()
get() = purchasesList
}
}

@ -1,16 +1,23 @@
package org.tasks.billing
import com.android.billingclient.api.Purchase
import com.google.gson.GsonBuilder
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import org.tasks.billing.BillingClientImpl.Companion.STATE_PURCHASED
import java.util.regex.Pattern
class Purchase(private val purchase: Purchase) {
constructor(json: String?) : this(GsonBuilder().create().fromJson<Purchase>(json, Purchase::class.java))
constructor(json: String) : this(
Json.parseToJsonElement(json).jsonObject.let {
Purchase(it["zza"]!!.jsonPrimitive.content, it["zzb"]!!.jsonPrimitive.content)
}
)
fun toJson(): String {
return GsonBuilder().create().toJson(purchase)
return Json.encodeToString(mapOf("zza" to purchase.originalJson, "zzb" to purchase.signature))
}
override fun toString(): String {
@ -24,7 +31,7 @@ class Purchase(private val purchase: Purchase) {
get() = purchase.signature
val sku: String
get() = purchase.sku
get() = purchase.skus.first()
val purchaseToken: String
get() = purchase.purchaseToken

@ -28,7 +28,7 @@ package org.tasks.billing
* by implementing security measure X is greater than the money you would lose if you don't
* implement X. Talk to a UX designer if you find yourself obsessing over security.
*
* The good news is, in implementing [BillingRepository], a number of measures is taken to help
* The good news is, in implementing BillingRepository, a number of measures is taken to help
* prevent fraudulent activities in your app. We don't just focus on tech savvy hackers, but also
* on fraudulent users who may want to exploit loopholes. Just to name an obvious case:
* triangulation using Google Play, your secure server, and a local cache helps against non-techie

@ -5,11 +5,11 @@ import android.content.Context
import android.content.Intent
import com.google.android.gms.location.Geofence
import com.google.android.gms.location.GeofencingEvent
import com.todoroo.andlib.utility.DateUtilities
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.Notifier
import org.tasks.data.LocationDao
import org.tasks.data.dao.LocationDao
import org.tasks.injection.InjectingJobIntentService
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import timber.log.Timber
import javax.inject.Inject
@ -19,7 +19,7 @@ class GoogleGeofenceTransitionIntentService : InjectingJobIntentService() {
@Inject lateinit var notifier: Notifier
override suspend fun doWork(intent: Intent) {
val geofencingEvent = GeofencingEvent.fromIntent(intent)
val geofencingEvent = GeofencingEvent.fromIntent(intent) ?: return
if (geofencingEvent.hasError()) {
Timber.e("geofence error code %s", geofencingEvent.errorCode)
return
@ -28,7 +28,7 @@ class GoogleGeofenceTransitionIntentService : InjectingJobIntentService() {
val triggeringGeofences = geofencingEvent.triggeringGeofences
Timber.i("Received geofence transition: %s, %s", transitionType, triggeringGeofences)
if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER || transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
triggeringGeofences.forEach {
triggeringGeofences?.forEach {
triggerNotification(it, transitionType == Geofence.GEOFENCE_TRANSITION_ENTER)
}
} else {
@ -45,9 +45,9 @@ class GoogleGeofenceTransitionIntentService : InjectingJobIntentService() {
return
}
val geofences = if (arrival) {
locationDao.getArrivalGeofences(place.uid!!, DateUtilities.now())
locationDao.getArrivalGeofences(place.uid!!, currentTimeMillis())
} else {
locationDao.getDepartureGeofences(place.uid!!, DateUtilities.now())
locationDao.getDepartureGeofences(place.uid!!, currentTimeMillis())
}
notifier.triggerNotifications(place.id, geofences, arrival)
} catch (e: Exception) {

@ -10,9 +10,8 @@ import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.*
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.R
import org.tasks.data.Place
import org.tasks.data.entity.Place
import org.tasks.location.MapFragment.MapFragmentCallback
import java.util.*
import javax.inject.Inject
class GoogleMapFragment @Inject constructor(
@ -22,6 +21,7 @@ class GoogleMapFragment @Inject constructor(
private lateinit var callback: MapFragmentCallback
private var dark = false
private var map: GoogleMap? = null
private var circle: Circle? = null
override fun init(activity: AppCompatActivity, callback: MapFragmentCallback, dark: Boolean) {
this.callback = callback
@ -36,7 +36,7 @@ class GoogleMapFragment @Inject constructor(
}
override val mapPosition: MapPosition?
get() = map?.cameraPosition?.let { it ->
get() = map?.cameraPosition?.let {
val target = it.target
return MapPosition(target.latitude, target.longitude, it.zoom)
}
@ -75,6 +75,17 @@ class GoogleMapFragment @Inject constructor(
map?.isMyLocationEnabled = true
}
override fun showCircle(radius: Double, latitude: Double, longitude: Double) {
circle?.remove()
circle = map?.addCircle(
CircleOptions()
.radius(radius)
.center(LatLng(latitude, longitude))
.strokeColor(context.getColor(R.color.map_circle_stroke))
.fillColor(context.getColor(R.color.map_circle_fill))
)
}
override fun onMapReady(googleMap: GoogleMap) {
map = googleMap
if (dark) {

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

Loading…
Cancel
Save