Compare commits

...
679 Commits
Author SHA1 Message Date
GitHub Actions 7d0c6972ef feat(release): bump version 2023-06-08 15:02:17 +00:00
Harsh Shandilya 18cb5dc07c chore: refresh feature graphic 2023-06-08 20:18:09 +05:30
Harsh Shandilya 5343e13215 fix(scripts): ensure demo mode is correctly enabled 2023-06-08 19:55:55 +05:30
renovate[bot]andGitHub 4d06a2722c fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2023.04.00-beta02 2023-06-08 12:14:43 +00:00
Harsh Shandilya b9f5bee35e fix(scripts): make setup-age architecture agnostic 2023-06-08 11:53:55 +00:00
Harsh Shandilya 72078b2768 fix(scripts): bump age to v1.1.1 2023-06-08 11:53:55 +00:00
GitHub Actions 465191609b chore(android): refresh baseline profile 2023-06-08 11:48:51 +00:00
Harsh ShandilyaandGitHub 6e1858a55e fix(benchmark): adjust for API changes 2023-06-08 07:03:28 +00:00
renovate[bot]andGitHub 3eeb947914 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v3.10.0 2023-06-08 00:02:53 +00:00
renovate[bot]andGitHub d2c99fa8b7 fix(deps): update androidx 2023-06-07 19:06:35 +00:00
renovate[bot]andGitHub dbba96426d chore(deps): update sentry 2023-06-07 15:43:33 +00:00
Harsh Shandilya a5be35a667 feat(core): manually wire in Sentry OkHttp integration 2023-06-07 21:04:24 +05:30
Harsh Shandilya 6e291a8df1 refactor(scripts): rework how Maestro flows are run 2023-06-07 18:07:18 +05:30
Harsh Shandilya 24898cf9fb chore: refresh feature graphic 2023-06-07 17:19:43 +05:30
Harsh Shandilya 66e64ac305 chore: update changelog 2023-06-07 16:24:08 +05:30
Harsh Shandilya ee6bcc864f feat: update iconography for consistency 2023-06-07 16:24:02 +05:30
Harsh Shandilya 8de49d670b fix(android): add visual indication when there are no saved posts 2023-06-07 16:11:18 +05:30
GitHub Actions 13b1c699f6 chore(android): refresh baseline profile 2023-06-07 01:34:08 +00:00
Harsh Shandilya 86a70ffb48 feat(common): remove animation for comment text 2023-06-07 02:42:15 +05:30
Harsh Shandilya 2bb71238bc fix(android): dismiss existing snackbars when showing a new one 2023-06-07 02:37:43 +05:30
Harsh Shandilya 7d491de86c fix(android): prevent comments page from stacking when spammed 2023-06-07 02:19:54 +05:30
Harsh Shandilya 02575a917b fix(android): check for previous back stack entry 2023-06-07 02:05:14 +05:30
renovate[bot]andGitHub 5206851b22 chore(deps): update dependency gradle to v8.2-rc-2 2023-06-06 19:03:10 +00:00
GitHub Actions 74c36f27ae chore(android): refresh baseline profile 2023-06-06 01:36:55 +00:00
Harsh Shandilya 2048a2bb9b chore: add test resources to .rgignore 2023-06-06 00:45:13 +05:30
renovate[bot]andGitHub ea48cdb4f3 chore(deps): update plugin modulegraphassert to v2.4.0 2023-06-05 16:10:44 +00:00
Harsh Shandilya 942b9f3fb4 fix(android): report fully drawn status 2023-06-05 16:50:29 +05:30
Harsh Shandilya 5f6d635c7a fix(android): inline useless function 2023-06-05 14:58:28 +05:30
Harsh Shandilya 47a398f518 refactor: move metadata-extractor to android 2023-06-05 13:24:22 +05:30
Harsh Shandilya 9fdd72220f feat(scripts): add a quick way to refresh the README graphic 2023-06-05 13:24:22 +05:30
Harsh Shandilya 0a1913e056 feat(build): add module-graph-assert plugin 2023-06-05 10:04:41 +05:30
Harsh Shandilya 68db3dcda6 refactor: move coroutine-utils into core 2023-06-05 09:52:12 +05:30
Harsh Shandilya c50c9c8528 chore: refresh module graph 2023-06-05 09:46:09 +05:30
Harsh Shandilya 8a418f6649 refactor: make SavedPostSerializer an object 2023-06-05 09:41:52 +05:30
Harsh Shandilya acdc924047 chore: cleanup redundant @OptIn annotations 2023-06-05 09:34:48 +05:30
GitHub Actions 2fa1d3f06f chore(android): refresh baseline profile 2023-06-05 01:37:40 +00:00
Harsh Shandilya 7ffa225487 feat(database): add test for SavedPostSerializer 2023-06-05 02:51:53 +05:30
Harsh Shandilya c1659eb2dd chore(gitignore): add claw-export.json 2023-06-05 02:18:09 +05:30
Harsh Shandilya 1e888494ee fix(build): temporarily revert to AGP 8.0.x
Android Studio's canary version is going through some trouble recognizing test sources
2023-06-05 02:16:57 +05:30
Harsh Shandilya 054ba13dc3 fix(ci): enforce concurrency for all workflows 2023-06-05 02:00:15 +05:30
Harsh Shandilya 301760c39f refactor(android): make String.toLocalDateTime private 2023-06-05 01:59:17 +05:30
Harsh Shandilya 79fd814c14 fix(android): add Snackbars to data transfer flow 2023-06-05 01:50:23 +05:30
Harsh Shandilya a82d0e7063 fix(android): only show data transfer action on home screen 2023-06-05 00:56:20 +05:30
Harsh Shandilya c6ea1182e0 refactor: remove explicit calls to rememberVectorPainter 2023-06-04 17:14:09 +00:00
Harsh Shandilya 5e7b79eb89 fix(android): hide data transfer action on data transfer screen 2023-06-04 21:19:22 +05:30
Harsh Shandilya 3738d94789 feat(android): wire up import/export settings to UI 2023-06-04 18:45:14 +05:30
Harsh Shandilya fb0e372917 feat(android): add DataTransferRepository 2023-06-04 18:45:14 +05:30
Harsh Shandilya 8945f9e33f feat(database): build a custom serializer for SavedPost 2023-06-04 18:45:14 +05:30
Harsh Shandilya 2895e7ffe7 refactor(android): split out comments functionality 2023-06-04 18:45:14 +05:30
GitHub Actions f102166fae chore(android): refresh baseline profile 2023-06-04 01:28:30 +00:00
Harsh Shandilya c51e28b8e1 fix: touch up version catalog 2023-06-04 01:33:25 +05:30
GitHub Actions a9923eb8c0 feat(release): start next development iteration 2023-06-03 18:50:53 +00:00
GitHub Actions de2f3964e0 feat(release): bump version 2023-06-03 18:46:20 +00:00
Harsh Shandilya 7c5ccbf63b fix: make nav transitions run at 2x of defaults 2023-06-04 00:03:38 +05:30
Harsh Shandilya b4b96222ed chore: reorder manifest attributes 2023-06-04 00:03:38 +05:30
Harsh Shandilya a920f899fb fix(android): automatically extract native libraries 2023-06-04 00:03:38 +05:30
GitHub Actions 31b39a49d6 chore(android): refresh baseline profile 2023-06-03 01:33:42 +00:00
renovate[bot]andGitHub bfb4e9741a chore(deps): update msfjarvis/keep-a-changelog-new-release action to v2.1.0 2023-06-02 22:59:13 +00:00
GitHub Actions bc5c5a13b4 chore(android): refresh baseline profile 2023-06-02 01:22:03 +00:00
renovate[bot]andGitHub 19c50f40cd chore(deps): update github/codeql-action action to v2.3.6 2023-06-01 19:54:14 +00:00
renovate[bot]andGitHub bb0a987d80 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v3.8.0 2023-06-01 10:22:25 +00:00
Harsh Shandilya dba380e4c4 fix(gradle): remove default-enabled feature prop 2023-06-01 12:46:32 +05:30
Harsh Shandilya 4a52524212 fix(gradle): correct property name for CC 2023-06-01 12:46:32 +05:30
Harsh Shandilya 1a94ba5a40 fix(gradle): upgrade to 8.2-rc-1 2023-06-01 12:38:05 +05:30
GitHub Actions 2022255200 chore(android): refresh baseline profile 2023-06-01 01:33:44 +00:00
renovate[bot]andGitHub ab1951f9c5 fix(deps): update dependency com.slack.eithernet:eithernet to v1.4.1 2023-05-31 19:31:40 +00:00
renovate[bot]andGitHub a9176b8508 chore(deps): update dependency io.sentry:sentry-android to v6.21.0 2023-05-31 08:54:31 +00:00
GitHub Actions 02ad998b06 chore(android): refresh baseline profile 2023-05-31 01:23:45 +00:00
GitHub Actions 31059abf23 feat(release): start next development iteration 2023-05-31 01:11:15 +00:00
GitHub Actions fc70931c2c feat(release): bump version 2023-05-31 01:07:01 +00:00
renovate[bot]andGitHub af4a6c4672 chore(deps): update agp to v8.2.0-alpha06 2023-05-31 00:40:15 +00:00
Harsh Shandilya 3347224018 feat(database): use Requery's repackaged SQLite for databases 2023-05-31 06:09:44 +05:30
Harsh Shandilya 558062a915 Revert "feat: add some navigation transitions"
This was fun but good lord it is ugly

This reverts commit 4f4b480a13.
2023-05-31 05:57:25 +05:30
Harsh Shandilya a7ab941543 chore(deps): update sqldelight to v2.0.0-rc01 2023-05-31 05:54:11 +05:30
renovate[bot]andGitHub 57b5f33720 fix(deps): update dependency com.google.truth:truth to v1.1.4 2023-05-30 17:18:20 +00:00
GitHub Actions f36d0ef5e6 chore(android): refresh baseline profile 2023-05-30 01:24:00 +00:00
GitHub Actions 0d9b0fec6b chore(android): refresh baseline profile 2023-05-29 06:19:36 +00:00
Harsh Shandilya d1b83410d0 fix(ci): adjust baseline profile path 2023-05-29 11:12:39 +05:30
Harsh Shandilya 990bb26276 fix(deps): update accompanist to 0.31.3-beta 2023-05-29 11:05:56 +05:30
Harsh Shandilya 4f4b480a13 feat: add some navigation transitions 2023-05-28 18:14:11 +05:30
Harsh Shandilya b2490cd014 fix: wrap DatabasePosts content in a Box 2023-05-28 18:13:53 +05:30
Harsh Shandilya 9d85563cf2 fix: remove deeplink for lobste.rs
It makes logging in to the website from a browser fairly annoying for minimal gain
2023-05-28 17:25:04 +05:30
Harsh Shandilya ac573d9311 chore: add changelog entry for adaptive nav 2023-05-28 17:22:52 +05:30
Harsh Shandilya 1e5ae4048c fix: make nav rail animate horizontally 2023-05-28 14:01:04 +05:30
Harsh Shandilya 3db05fb3b1 fix: remove dubious return 2023-05-28 14:01:04 +05:30
Harsh ShandilyaandGitHub 5a098e125a Apply suggestions from code review 2023-05-28 13:39:39 +05:30
Yash-Garg 78b77fd4c1 feat: add adaptive navigation for different screen sizes 2023-05-28 13:17:55 +05:30
renovate[bot]andGitHub b2470ca89b chore(deps): pin actions/cache action to 88522ab 2023-05-27 23:56:18 +00:00
Harsh Shandilya 4764698583 fix(ci): manually cache Android SDK build-tools
This is necessary to avoid the extremely slow re-download on each run
2023-05-28 03:19:10 +05:30
Harsh Shandilya c91a34aae5 chore: update changelog 2023-05-27 01:36:06 +05:30
Harsh Shandilya 8dc76f6ce5 fix(renovate): avoid R8 updates 2023-05-26 19:21:49 +05:30
Harsh Shandilya 0ebe949da6 Revert "feat(renovate): keep R8 up-to-date with ToT"
This reverts commit 25c78eed91.
2023-05-26 19:19:18 +05:30
Harsh Shandilya 6c1a40d614 fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2023.04.00-beta01.1 2023-05-26 19:18:29 +05:30
renovate[bot]andGitHub 9a81d06e2d chore(deps): update dependency io.sentry:sentry-android to v6.20.0 2023-05-26 12:40:11 +00:00
renovate[bot]andGitHub 687cd210af chore(deps): update r8 digest to c765114 2023-05-26 09:54:10 +00:00
Harsh ShandilyaandGitHub 87135c0e1b fix(renovate): stop treating R8 as a Maven dependency 2023-05-26 15:23:23 +05:30
Harsh Shandilya 48cfa6b7f1 fix(deps): update AndroidX Navigation and kotlinx.serialization 2023-05-26 01:55:49 +05:30
Harsh Shandilya 25c78eed91 feat(renovate): keep R8 up-to-date with ToT 2023-05-26 01:20:08 +05:30
renovate[bot]andGitHub 6a50387c39 chore(deps): update agp to v8.2.0-alpha05 2023-05-25 19:41:42 +00:00
renovate[bot]andHarsh Shandilya bac6f65dd0 chore(deps): update github/codeql-action action to v2.3.5 2023-05-26 01:08:19 +05:30
Harsh Shandilya 5ec34fea3b fix(ci): accept all SDK licenses 2023-05-26 01:08:19 +05:30
Harsh Shandilya 539e53c6b1 fix: add Retrofit R8 rules 2023-05-26 01:08:19 +05:30
Harsh Shandilya dfe108d13e fix(deps): use an unreleased R8 build with verifier crash fix 2023-05-26 01:08:19 +05:30
Harsh Shandilya 37e6c87046 feat: move up to AGP 8.2.x 2023-05-25 22:19:58 +05:30
renovate[bot]andGitHub e92929910d chore(deps): update github/codeql-action action to v2.3.4 2023-05-25 04:40:10 +00:00
GitHub Actions 7488afdbb3 chore(android): refresh baseline profile 2023-05-25 01:27:30 +00:00
renovate[bot]andGitHub 2dbc99a27a chore(deps): update agp to v8.0.2 2023-05-24 21:57:29 +00:00
renovate[bot]andGitHub 1dd26feebb fix(deps): update androidx 2023-05-24 18:55:21 +00:00
renovate[bot]andGitHub 203847dcd7 fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2023.04.00-beta01 2023-05-24 18:06:07 +00:00
renovate[bot]andGitHub a4a3620f71 fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.19.0 2023-05-24 04:02:03 +00:00
GitHub Actions 5fba9bfe7b chore(android): refresh baseline profile 2023-05-24 01:27:21 +00:00
renovate[bot]andGitHub c05aa75f1e fix(deps): update dependency com.google.testparameterinjector:test-parameter-injector to v1.12 2023-05-23 11:44:26 +00:00
GitHub Actions 2f378aaeec chore(android): refresh baseline profile 2023-05-22 01:27:24 +00:00
renovate[bot]andGitHub e92279634d fix(deps): update coil to v2.4.0 2023-05-21 19:07:33 +00:00
Harsh Shandilya 1bc15b7b7c fix(renovate): disable Coil updates
Coil 2.4.0 uses Kotlin 1.8.21 that we can't use yet
2023-05-21 20:41:20 +05:30
GitHub Actions 7d8083b268 chore(android): refresh baseline profile 2023-05-21 01:26:45 +00:00
GitHub Actions 7035159fa6 chore(android): refresh baseline profile 2023-05-20 01:23:53 +00:00
renovate[bot]andGitHub a2a9446e3b fix(deps): update dependency com.slack.eithernet:eithernet to v1.4.0 2023-05-19 19:34:10 +00:00
renovate[bot]andGitHub 5c40fedde2 chore(deps): update sentry to v6.19.1 2023-05-19 12:45:15 +00:00
GitHub Actions a44ca13e3a chore(android): refresh baseline profile 2023-05-19 01:22:06 +00:00
GitHub Actions 67f3595d33 chore(android): refresh baseline profile 2023-05-18 01:27:06 +00:00
Harsh Shandilya ae10d433e6 refactor: switch to Material Icons
Our previous system resulted in leaner code but was way too annoying to add
new icons to.
2023-05-18 02:03:17 +05:30
Harsh Shandilya e33768d9ca fix(android): set assist URI for profile page 2023-05-18 02:03:17 +05:30
renovate[bot]andGitHub 7624fa204d fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v3.7.0 2023-05-17 12:31:46 +00:00
renovate[bot]andGitHub 4738674f7f chore(deps): update sentry to v6.19.0 2023-05-16 13:05:10 +00:00
Harsh Shandilya 7cbc96161e feat(build): raise target bytecode to Java 17 2023-05-16 16:14:10 +05:30
Harsh Shandilya d940ba252e chore: expand changelog 2023-05-16 13:32:46 +05:30
GitHub Actions 60507cc817 chore(android): refresh baseline profile 2023-05-15 01:20:52 +00:00
GitHub Actions 3a99c28233 chore(android): refresh baseline profile 2023-05-14 01:23:15 +00:00
Harsh Shandilya 7e91628339 feat: switch over to Compose alphas 2023-05-13 19:27:28 +05:30
GitHub Actions eb053eb5bf chore(android): refresh baseline profile 2023-05-13 01:24:08 +00:00
renovate[bot]andGitHub 7462b1a2f7 fix(deps): update dagger to v2.46.1 2023-05-12 22:00:05 +00:00
Harsh Shandilya 8d557c3898 fix(deps): update coroutines to 1.7.1 2023-05-13 02:49:04 +05:30
Harsh Shandilya 6b1c53c31a chore(gradle): sort dependencies 2023-05-12 13:15:36 +05:30
GitHub Actions 5e27937358 chore(android): refresh baseline profile 2023-05-12 01:20:49 +00:00
renovate[bot]andGitHub a8aad809ba fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v3.6.0 2023-05-11 17:18:55 +00:00
Harsh ShandilyaandGitHub d94ca0e9c6 fix(deps): remove unused kotest dependencies (#375) 2023-05-11 04:19:58 +00:00
GitHub Actions aa51535e65 chore(android): refresh baseline profile 2023-05-11 01:27:50 +00:00
Harsh Shandilya 7737c82db9 fix: switch TopAppBar to non-deprecated APIs 2023-05-11 01:30:36 +05:30
renovate[bot]andGitHub 7ee64e0ead fix(deps): update androidx 2023-05-10 19:51:26 +00:00
Harsh Shandilya 987990704c fix(renovate): group all AndroidX updates 2023-05-11 01:20:53 +05:30
GitHub Actions e8975e70f5 chore(android): refresh baseline profile 2023-05-09 01:23:53 +00:00
GitHub Actions 72409a0b73 chore(android): refresh baseline profile 2023-05-08 01:25:09 +00:00
Harsh Shandilya 3dfd2d7862 chore: rework dependency declaration 2023-05-07 11:16:19 +00:00
Harsh ShandilyaandGitHub c93d2f73a9 fix(maestro): correct tap index
I initially wrote this to tap the 1st and 3rd save button but failed to account for the fact that once the first button was pressed, its text property would no longer be "Add to saved posts" which results in index=2 actually pointing to the 4th absolute position in the list.
2023-05-06 12:25:08 +05:30
Harsh Shandilya 66d638f952 fix(benchmark): raise min SDK to align with API requirements 2023-05-06 02:24:37 +05:30
Harsh Shandilya 815a8f186b chore: rejig README 2023-05-06 02:23:39 +05:30
Harsh Shandilya ae745b917e chore: refresh README feature image 2023-05-06 02:22:04 +05:30
Harsh Shandilya bd759c53cd chore(deps): update coroutines to 1.7.0 2023-05-06 02:02:34 +05:30
renovate[bot]andGitHub 8dca324f71 chore(deps): update plugin modulegraph to v0.4.0 2023-05-05 19:49:51 +00:00
Harsh Shandilya dd7a7d9977 feat: use Maestro to automatically generate Play Store screenshots 2023-05-05 21:01:31 +05:30
Harsh Shandilya a7c81a77f2 fix(android): make nav content description less shouty 2023-05-05 20:42:27 +05:30
Harsh Shandilya 15b1e68611 Revert "feat: add gradle-dependencies-sort plugin"
The lexer/parser on this is very sensitive to custom APIs being used in the
`dependencies {}` DSL.

This reverts commit 069c5a4389.
2023-05-05 20:31:29 +05:30
Harsh Shandilya a5e25e2eb5 refactor(build): simplify test dependency setup 2023-05-05 20:31:29 +05:30
renovate[bot]andGitHub c10ec27b51 chore(deps): update github/codeql-action action to v2.3.3 2023-05-04 20:26:50 +00:00
Harsh Shandilya 9c86a9124d fix: sort dependencies 2023-05-04 15:16:31 +05:30
Harsh Shandilya 069c5a4389 feat: add gradle-dependencies-sort plugin 2023-05-04 15:09:41 +05:30
Harsh Shandilya b498cf4b62 feat: fix Sentry disabling logic again 2023-05-04 14:09:05 +05:30
GitHub Actions 70ee848a41 chore(android): refresh baseline profile 2023-05-04 01:28:37 +00:00
GitHub Actions 60fd6a4af4 feat(release): start next development iteration 2023-05-03 22:38:06 +00:00
GitHub Actions 04ed687dbb feat(release): bump version 2023-05-03 22:37:02 +00:00
Harsh Shandilya d694415a4a chore: re-sync Lint baseline 2023-05-04 03:53:36 +05:30
Harsh Shandilya 3f2a9c999b chore: sync changelog 2023-05-04 03:52:18 +05:30
Harsh Shandilya ea40650214 feat(android): migrate away from kotest 2023-05-04 03:38:23 +05:30
Harsh Shandilya ae66aced83 feat(api): migrate away from kotest 2023-05-04 03:33:47 +05:30
Harsh Shandilya 5d2eebf093 fix(api): add test util for type assertion 2023-05-04 03:33:47 +05:30
Harsh Shandilya 5c8057d71f fix(model): implement contains operator fun for Tags 2023-05-04 03:33:47 +05:30
Harsh Shandilya 4d78a73602 feat(database): migrate away from kotest 2023-05-04 03:33:47 +05:30
Harsh Shandilya 7c5a9eb683 feat(build): add JUnit 5 and Truth deps 2023-05-04 03:33:47 +05:30
renovate[bot]andGitHub df423d28d6 fix(deps): update dependency androidx.profileinstaller:profileinstaller to v1.3.1 2023-05-03 20:29:20 +00:00
renovate[bot]andHarsh Shandilya a92616c5a3 fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.0-alpha14 2023-05-04 01:58:30 +05:30
renovate[bot]andHarsh Shandilya 2fc29f65ca fix(deps): update dependency androidx.compose:compose-bom to v2023.05.00 2023-05-04 01:58:30 +05:30
Harsh Shandilya aab712e680 fix(android): migrate to new paging-compose APIs 2023-05-04 01:58:30 +05:30
renovate[bot]andGitHub 4bca86d91e fix(deps): update dependency androidx.paging:paging-compose to v1.0.0-alpha19 2023-05-03 18:41:29 +00:00
GitHub Actions 63cca3eba2 chore(android): refresh baseline profile 2023-05-03 01:28:04 +00:00
Harsh Shandilya cba2ed5944 fix: strip out invalid R8 rules 2023-05-03 01:58:22 +05:30
Harsh Shandilya ee5886c9b9 chore(benchmark): use method reference 2023-05-02 19:45:28 +05:30
Harsh Shandilya e96dadae34 fix(scripts): adjust emulator bootup routines 2023-05-02 19:45:28 +05:30
Harsh Shandilya a23ad82b60 fix(scripts): migrate away from deprecated ANDROID_SDK_ROOT 2023-05-02 19:45:28 +05:30
GitHub Actions f816580886 chore(android): refresh baseline profile 2023-05-02 01:28:03 +00:00
renovate[bot]andGitHub a5f8f1a4c2 chore(deps): update agp to v8.0.1 2023-05-01 18:30:20 +00:00
GitHub Actions 0d47f06be3 chore(android): refresh baseline profile 2023-05-01 01:31:57 +00:00
GitHub Actions c4eb2d2116 chore(android): refresh baseline profile 2023-04-30 01:32:24 +00:00
renovate[bot]andGitHub 8c1dc62211 fix(deps): update dependency org.jsoup:jsoup to v1.16.1 2023-04-29 08:41:46 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>Harsh Shandilya
b1a66bb8dd chore(deps): update dependency com.facebook:ktfmt to v0.44 (#374)
* chore(deps): update dependency com.facebook:ktfmt to v0.44

* chore: reformat

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
2023-04-29 09:48:04 +05:30
GitHub Actions 61a2cefcc3 chore(android): refresh baseline profile 2023-04-29 01:27:42 +00:00
renovate[bot]andGitHub ad775bf8e1 fix(deps): update dagger to v2.46 2023-04-28 22:48:14 +00:00
renovate[bot]andGitHub a80e8bb298 fix(deps): update dependency io.sentry:sentry-bom to v6.18.1 2023-04-28 19:06:41 +00:00
renovate[bot]andGitHub 2db51746ac chore(deps): update github/codeql-action action to v2.3.2 2023-04-28 05:12:08 +00:00
GitHub Actions 3d7e6d7f4c chore(android): refresh baseline profile 2023-04-28 01:20:55 +00:00
Harsh Shandilya 6918cf5f76 fix(core): adjust OkHttp config 2023-04-27 18:52:21 +05:30
renovate[bot]andGitHub cd05ed4da9 chore(deps): update sentry to v6.18.0 2023-04-27 12:49:45 +00:00
renovate[bot]andGitHub b669900c75 chore(deps): update github/codeql-action action to v2.3.1 2023-04-27 03:05:16 +00:00
GitHub Actions 3a9bf04a4d chore(android): refresh baseline profile 2023-04-27 01:23:43 +00:00
Harsh Shandilya 0cd4257e73 Revert "feat(build): upgrade to AGP 8.1.0-beta01"
Newer AGP releases cause incorrect desugaring of the Crux dependency

This reverts commit 68a20e0d11.
2023-04-26 14:37:03 +00:00
Harsh ShandilyaandGitHub 6f55da754c fix(deps): de-commonize AndroidX Test versioning 2023-04-25 21:11:50 +05:30
Harsh ShandilyaandGitHub 31adb45152 fix(deps): rollback AndroidX Test version to 1.6.0-alpha01
alpha02 doesn't exist
2023-04-25 20:03:31 +05:30
Harsh Shandilya 68a20e0d11 feat(build): upgrade to AGP 8.1.0-beta01 2023-04-25 18:42:05 +05:30
renovate[bot]andGitHub 52657b0c08 fix(deps): update dependency androidx.test:runner to v1.6.0-alpha02 2023-04-25 05:06:38 +00:00
Harsh Shandilya a2123b7a5d chore: remove unnecessary suppress 2023-04-25 01:23:06 +05:30
Harsh Shandilya 207f98ca17 feat(common): add a preview for LobstersCard 2023-04-25 01:20:43 +05:30
Harsh Shandilya 58170b6072 feat: disable Sentry performance reporting and profiling
These features are going paid and I do not care enough to foot the bill
2023-04-24 23:36:47 +05:30
GitHub Actions 744955bf11 chore(android): refresh baseline profile 2023-04-24 01:21:34 +00:00
renovate[bot]andGitHub cd6d53d19e fix(deps): update dependency com.squareup.okhttp3:okhttp-bom to v4.11.0 2023-04-23 02:00:02 +00:00
GitHub Actions 50e03fbd50 chore(android): refresh baseline profile 2023-04-22 01:19:16 +00:00
renovate[bot]andGitHub 6dd219ee05 chore(deps): update github/codeql-action action to v2.3.0 2023-04-21 20:06:55 +00:00
renovate[bot]andGitHub 2a6cd96c8c chore(deps): update dependency gradle to v8.1.1 2023-04-21 15:30:29 +00:00
Harsh Shandilya 1323668fe6 feat(build): add a task to collect Lint SARIF reports 2023-04-20 18:00:01 +05:30
Harsh Shandilya 24b747eb38 fix(build): correct plugin application ordering 2023-04-20 18:00:01 +05:30
Harsh Shandilya ed31d1fefb chore(lint): update lint baselines 2023-04-20 18:00:01 +05:30
Harsh Shandilya 237a06f1cf feat(build): apply Android Lint plugin to JVM modules 2023-04-20 18:00:01 +05:30
renovate[bot]andGitHub 06528e7504 fix(deps): update dependency androidx.test.uiautomator:uiautomator to v2.3.0-alpha03 2023-04-20 06:00:10 +00:00
renovate[bot]andGitHub 387f9a2601 fix(deps): update dependency androidx.navigation:navigation-compose to v2.6.0-beta01 2023-04-20 05:17:28 +00:00
renovate[bot]andGitHub 4bcfd083d6 fix(deps): update dependency androidx.core:core-splashscreen to v1.0.1 2023-04-20 01:49:30 +00:00
renovate[bot]andGitHub 0e922176fe fix(deps): update dependency androidx.activity:activity-compose to v1.7.1 2023-04-19 22:03:59 +00:00
Harsh Shandilya 250e7c20e5 feat(common): use FlowRow from Compose Foundation 2023-04-20 01:44:43 +05:30
Harsh Shandilya c3de960966 feat(deps): upgrade to Compose 2023.04.01 2023-04-20 01:19:27 +05:30
renovate[bot]andGitHub 866995b2d3 fix(deps): update dependency com.slack.lint.compose:compose-lint-checks to v1.2.0 2023-04-19 16:53:22 +00:00
Harsh Shandilya 825ee23afe chore: convert launcher assets from PNG to WebP 2023-04-19 17:25:09 +05:30
Harsh Shandilya 66ce35927a refactor(build): extract out Lint config 2023-04-19 17:16:06 +05:30
Harsh Shandilya 468d363c65 feat(build): rework Lint config
- Export SARIF output
- Expand enabled ruleset
- Make HTML reports more detailed
2023-04-19 15:19:15 +05:30
Harsh Shandilya 009744cb47 fix(ci): ensure full history is cloned 2023-04-19 14:51:37 +05:30
Harsh Shandilya 2d63a1e79f chore: sync up copyright headers 2023-04-19 12:38:36 +05:30
Harsh Shandilya 5452c55e86 chore(build): enable Spotless license header sync by default 2023-04-19 12:37:44 +05:30
Harsh Shandilya 6b164f84d9 refactor(build): migrate to Kotlin compilerOptions DSL 2023-04-19 12:36:03 +05:30
Harsh Shandilya bf104a1d85 chore(build): reorder DSL declarations 2023-04-19 12:29:27 +05:30
renovate[bot]andGitHub 1d32ec810f fix(deps): update dependency com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter to v1 2023-04-19 05:18:18 +00:00
GitHub Actions 1f7b9dbbc4 chore(android): refresh baseline profile 2023-04-19 01:22:24 +00:00
renovate[bot]andGitHub 8c0bfc2143 fix(deps): update kotest to v5.6.1 2023-04-18 20:18:21 +00:00
GitHub Actions 279ddd9974 feat(release): start next development iteration 2023-04-18 08:50:27 +00:00
GitHub Actions 71b29c0b56 feat(release): bump version 2023-04-18 08:48:54 +00:00
Harsh Shandilya b331a85a2a chore: remove Qodana configurations 2023-04-18 14:06:49 +05:30
Harsh Shandilya e8037e8d60 chore(codeql): run analysis on pushes to main branch 2023-04-18 13:57:29 +05:30
Harsh Shandilya ea0dd4cb78 feat(core): implement certificate pinning for lobste.rs 2023-04-18 13:44:31 +05:30
GitHub ActionsandHarsh Shandilya 4734ab4a22 chore(android): refresh baseline profile 2023-04-18 13:44:31 +05:30
Harsh Shandilya 4df97acd73 fix(codeql): manually build project 2023-04-18 13:44:31 +05:30
GitHub ActionsandHarsh Shandilya 8ec233d761 chore(android): refresh baseline profile 2023-04-18 13:44:31 +05:30
renovate[bot]andHarsh Shandilya 135a1fc5ed fix(deps): update kotest to v5.6.0 2023-04-18 13:44:31 +05:30
GitHub ActionsandHarsh Shandilya 4cb5b09001 chore(android): refresh baseline profile 2023-04-18 13:44:31 +05:30
Harsh Shandilya 3bb8b51cb5 chore: update changelog 2023-04-18 13:44:31 +05:30
GitHub ActionsandHarsh Shandilya 1ee31873ab chore(android): refresh baseline profile 2023-04-18 13:44:31 +05:30
Harsh Shandilya 79fac06a4c fix(benchmark): adjust baseline profile iterations 2023-04-18 13:44:31 +05:30
Harsh Shandilya 553bbedc95 feat(benchmark): migrate to Gradle Managed Devices 2023-04-18 13:44:31 +05:30
Harsh Shandilya d31fe53f78 chore: change benchmark package name 2023-04-18 13:44:18 +05:30
Harsh Shandilya be74e52156 fix: adjust baseline profile emulator options 2023-04-18 13:44:18 +05:30
Harsh Shandilya a2157ae618 feat: rework Sentry disabling logic for benchmark builds 2023-04-18 13:44:18 +05:30
Harsh Shandilya 8b7bcaa92f fix(renovate): disable Kotlin updates
Renovate can't understand how to stop
2023-04-18 13:44:18 +05:30
renovate[bot]andHarsh Shandilya 157998ddf5 fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.7.1 2023-04-18 13:44:18 +05:30
renovate[bot]andHarsh Shandilya cd302bb1bb chore(deps): update gradle/gradle-build-action action to v2.4.2 2023-04-18 13:44:18 +05:30
GitHub ActionsandHarsh Shandilya 52341757e4 chore(android): refresh baseline profile 2023-04-18 13:44:18 +05:30
GitHub ActionsandHarsh Shandilya a74633df54 chore(android): refresh baseline profile 2023-04-18 13:44:18 +05:30
Harsh Shandilya b936b54132 feat: rework system bar colors 2023-04-18 13:44:18 +05:30
Harsh Shandilya cf111f7852 fix: include Anvil updates in Kotlin bundle 2023-04-18 13:44:18 +05:30
renovate[bot]andHarsh Shandilya f23f9498cd chore(deps): update github/codeql-action action to v2.2.12 2023-04-18 13:44:18 +05:30
Harsh Shandilya 7c019353df feat(deps): upgrade AGP to 8.0.0 2023-04-18 13:44:18 +05:30
renovate[bot]andGitHub 3954e63141 chore(deps): update actions/checkout action to v3.5.2 2023-04-13 15:11:26 +00:00
renovate[bot]andGitHub d04d638b27 chore(deps): update gradle/gradle-build-action action to v2.4.1 2023-04-13 08:23:27 +00:00
renovate[bot]andGitHub 3ad414dadd chore(deps): update actions/checkout action to v3.5.1 2023-04-13 02:43:26 +00:00
GitHub Actions 8bc9bd4dbb chore(android): refresh baseline profile 2023-04-13 01:30:13 +00:00
renovate[bot]andGitHub b0c3066adc chore(deps): update dependency gradle to v8.1 2023-04-12 15:06:23 +00:00
GitHub Actions c5dfd4fffe chore(android): refresh baseline profile 2023-04-12 01:30:16 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7de7b4f843 chore(deps): update dependency gradle to v8.1-rc-4 (#369)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-12 00:30:14 +05:30
GitHub Actions 7079c5a6f1 chore(android): refresh baseline profile 2023-04-09 01:24:44 +00:00
GitHub Actions 46ebda2673 chore(android): refresh baseline profile 2023-04-08 01:20:21 +00:00
GitHub Actions eee9df7d8a chore(android): refresh baseline profile 2023-04-07 01:30:51 +00:00
renovate[bot]andGitHub f8be557e6e chore(deps): update github/codeql-action action to v2.2.11 2023-04-06 17:43:27 +00:00
renovate[bot]andGitHub d6f776e12e fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.18.0 2023-04-06 05:46:57 +00:00
GitHub Actions 6fd3f32f7e chore(android): refresh baseline profile 2023-04-06 01:25:12 +00:00
renovate[bot]andHarsh Shandilya adbb400728 fix(deps): update dependency androidx.navigation:navigation-compose to v2.6.0-alpha09
(cherry picked from commit 4a0fa59c9189eb18eff966c47d2307a5591cfbc5)
2023-04-06 01:33:59 +05:30
renovate[bot]andHarsh Shandilya 8f6a46aa2e fix(deps): update dependency androidx.datastore:datastore-preferences to v1.1.0-alpha04
(cherry picked from commit 8a78f2bd470adfad7130826b7b550d0c20e4a4e7)
2023-04-06 01:33:59 +05:30
renovate[bot]andHarsh Shandilya 0ec52b84fe fix(deps): update dependency androidx.compose:compose-bom to v2023.04.00
(cherry picked from commit c67e4d2923965a671e3043a9f503c3a0ea88013e)
2023-04-06 01:33:59 +05:30
renovate[bot]andHarsh Shandilya b436f10e18 chore(deps): update github/codeql-action action to v2.2.10
(cherry picked from commit 5fed8bd9d309fb18f4b24b09458e859fd939d9f5)
2023-04-06 01:06:50 +05:30
renovate[bot]andHarsh Shandilya 75ebf57c68 fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.0-alpha13
(cherry picked from commit 8293dccef8722344993e3cc55e4e6806e16db804)
2023-04-06 01:06:50 +05:30
GitHub Actions b3cea28687 chore(android): refresh baseline profile 2023-04-05 01:30:38 +00:00
renovate[bot]andGitHub 878b51fa30 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v3.5.0 2023-04-04 19:19:14 +00:00
renovate[bot]andGitHub 81f024d197 chore(deps): update dependency gradle to v8.1-rc-3 2023-04-04 12:41:24 +00:00
renovate[bot]andHarsh Shandilya a21d665f5d chore(deps): update plugin modulegraph to v0.3.0
(cherry picked from commit d600239ba264490346e4fcaef321c50d8883119e)
2023-04-04 11:24:46 +05:30
renovate[bot]andGitHub 954bc9710b fix(deps): update accompanist to v0.30.1 2023-04-04 04:05:45 +00:00
GitHub Actions 5faeef190d chore(android): refresh baseline profile 2023-04-04 01:22:37 +00:00
GitHub Actions 43c5f93b60 chore(android): refresh baseline profile 2023-04-03 01:28:56 +00:00
Harsh Shandilya adfac94094 feat: add a module graph to the README 2023-04-02 23:44:54 +05:30
GitHub Actions bc60929fe9 chore(android): refresh baseline profile 2023-04-02 01:25:34 +00:00
GitHub Actions fdf2564f15 chore(android): refresh baseline profile 2023-04-01 01:22:47 +00:00
renovate[bot]andGitHub 8b6d422d96 chore(deps): update sentry to v6.17.0 2023-03-31 11:01:58 +00:00
GitHub Actions d2c0fea75f chore(android): refresh baseline profile 2023-03-31 01:23:47 +00:00
GitHub Actions efa5afb441 chore(android): refresh baseline profile 2023-03-30 01:28:39 +00:00
Harsh Shandilya 830144d5b1 fix(gradle): CC is now stable 2023-03-29 15:18:15 +05:30
Harsh Shandilya f6b684ceb0 chore(build): upgrade to Gradle 8.1 RC2 2023-03-29 15:18:00 +05:30
GitHub Actions cd3dfc065b chore(android): refresh baseline profile 2023-03-29 01:25:25 +00:00
Harsh Shandilya 72c1529bb9 chore: sort dependencies with gradle-dependencies-sorter 2023-03-28 12:15:18 +05:30
GitHub Actions 1b17da668d chore(android): refresh baseline profile 2023-03-28 01:32:21 +00:00
renovate[bot]andGitHub 3e7f50f4bf chore(deps): update actions/setup-java action to v3.11.0 2023-03-27 16:11:28 +00:00
renovate[bot]andGitHub 12bc6a06fb chore(deps): update github/codeql-action action to v2.2.9 2023-03-27 15:47:54 +00:00
GitHub Actions c3f146723a chore(android): refresh baseline profile 2023-03-27 01:26:13 +00:00
renovate[bot]andGitHub f64254ccef fix(deps): update coil to v2.3.0 2023-03-26 03:37:24 +00:00
GitHub Actions 0a43d9c9f6 chore(android): refresh baseline profile 2023-03-26 01:25:07 +00:00
GitHub Actions dcb9bfeb18 chore(android): refresh baseline profile 2023-03-25 01:27:05 +00:00
renovate[bot]andGitHub d6f5ea444d fix(deps): update dependency androidx.datastore:datastore-preferences to v1.1.0-alpha03 2023-03-24 19:06:44 +00:00
renovate[bot]andGitHub 3a3e02a937 fix(deps): update dependency com.google.testparameterinjector:test-parameter-injector to v1.11 2023-03-24 14:03:24 +00:00
GitHub Actions b5109fc872 feat(release): start next development iteration 2023-03-24 09:56:53 +00:00
GitHub Actions d9ed25478f feat(release): bump version 2023-03-24 09:55:40 +00:00
Harsh Shandilya f5c9da6aa0 chore: update changelog 2023-03-24 15:24:23 +05:30
Harsh Shandilya 293c04b2ad fix(build): remove DSL_SCOPE_VIOLATION suppression 2023-03-24 14:59:34 +05:30
Harsh Shandilya e91b344bea fix(build): remove no longer needed SAM conversion flag 2023-03-24 14:59:34 +05:30
Harsh Shandilya 491d8a6e71 fix(build): remove no longer needed afterEvaluate 2023-03-24 14:37:01 +05:30
Harsh Shandilya 04054914f5 chore(build): upgrade to Gradle 8.1 RC1 2023-03-24 14:35:56 +05:30
Harsh Shandilya d273c6f7b5 fix(ci): use exact versions 2023-03-24 14:27:03 +05:30
renovate[bot]andGitHub 9cf134e916 chore(deps): update actions/checkout action to v3.5.0 2023-03-24 06:43:57 +00:00
renovate[bot]andGitHub abd1e73d82 chore(deps): update actions/checkout digest to 8f4b7f8 2023-03-24 06:04:09 +00:00
GitHub Actions 5625aebb0c chore(android): refresh baseline profile 2023-03-24 01:25:53 +00:00
renovate[bot]andGitHub b84393c0d6 fix(deps): update accompanist to v0.30.0 2023-03-23 03:06:25 +00:00
GitHub Actions c0021ff5dc chore(android): refresh baseline profile 2023-03-23 01:28:23 +00:00
renovate[bot]andGitHub 9e1893612c chore(deps): update github/codeql-action digest to 67a35a0 2023-03-22 21:09:02 +00:00
Harsh Shandilya 3c2c577628 fix(deps): upgrade AndroidX dependencies 2023-03-23 01:00:07 +05:30
Harsh Shandilya 190b7b4026 fix(gradle): remove unused version declaration 2023-03-23 01:00:07 +05:30
renovate[bot]andGitHub 6fa03bad66 chore(deps): update dependency androidx.compose.compiler:compiler to v1.4.4 2023-03-22 18:49:52 +00:00
GitHub Actions 0a84659b70 chore(android): refresh baseline profile 2023-03-22 01:21:36 +00:00
GitHub Actions dec5873682 chore(android): refresh baseline profile 2023-03-21 01:30:49 +00:00
renovate[bot]andGitHub 8fc18f8324 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v3.4.3 2023-03-20 21:00:07 +00:00
GitHub Actions 590240b283 chore(android): refresh baseline profile 2023-03-20 01:24:09 +00:00
GitHub Actions 4b90ff49fd chore(android): refresh baseline profile 2023-03-19 01:27:20 +00:00
renovate[bot]andGitHub 2223cea395 chore(deps): update reactivecircus/android-emulator-runner digest to d94c3fb 2023-03-18 11:39:49 +00:00
GitHub Actions ad692b73ba chore(android): refresh baseline profile 2023-03-18 01:23:26 +00:00
renovate[bot]andGitHub de57d089eb chore(deps): update sentry to v6.16.0 2023-03-17 10:57:52 +00:00
GitHub Actions 303a706d8a chore(android): refresh baseline profile 2023-03-17 01:23:23 +00:00
GitHub Actions 108bbbda87 chore(android): refresh baseline profile 2023-03-16 01:24:39 +00:00
renovate[bot]andGitHub 65f060a8d2 chore(deps): update actions/checkout action to v3.4.0 2023-03-15 23:04:10 +00:00
renovate[bot]andGitHub f35f0af6d8 chore(deps): update actions/checkout digest to 24cb908 2023-03-15 20:05:42 +00:00
renovate[bot]andGitHub 6c30892def chore(deps): update github/codeql-action digest to 168b99b 2023-03-15 16:58:44 +00:00
GitHub Actions 1016c85e3c chore(android): refresh baseline profile 2023-03-15 01:27:15 +00:00
renovate[bot]andGitHub 887c05c2b9 fix(deps): update dependency nl.littlerobots.version-catalog-update:nl.littlerobots.version-catalog-update.gradle.plugin to v0.8.0 2023-03-14 10:50:38 +00:00
renovate[bot]andHarsh Shandilya 98cb50fab7 chore(deps): update actions/cache action to v3.3.1
(cherry picked from commit 5d965a3cf41e5ef781451c232c5965800b2d0a7b)
2023-03-14 16:19:03 +05:30
renovate[bot]andHarsh Shandilya 38d75b0e51 fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.17.0
(cherry picked from commit f693de3a5ef4c2c90b6e715d9221b2cc6e7a3e0a)
2023-03-14 16:19:03 +05:30
Harsh Shandilya 20a2389eb0 feat(android): set up DataStore 2023-03-14 16:19:03 +05:30
GitHub Actions 9cbc754574 chore(android): refresh baseline profile 2023-03-12 01:19:11 +00:00
GitHub Actions b564283419 chore(android): refresh baseline profile 2023-03-11 01:21:57 +00:00
renovate[bot]andGitHub 32dd218131 chore(deps): update github/codeql-action digest to 16964e9 2023-03-10 19:28:32 +00:00
GitHub Actions 09a36aa4c6 chore(android): refresh baseline profile 2023-03-10 01:29:02 +00:00
Harsh Shandilya c1f1d67bfa feat(android): add a repository for extracting CSRF token 2023-03-10 01:29:04 +05:30
renovate[bot]andGitHub 93d2397572 chore(deps): update actions/cache action to v3.3.0 2023-03-09 14:07:15 +00:00
renovate[bot]andGitHub 4b89dc202e fix(deps): update dependency androidx.profileinstaller:profileinstaller to v1.3.0-rc01 2023-03-09 08:02:47 +00:00
renovate[bot]andGitHub 0718e18fb0 fix(deps): update dependency androidx.navigation:navigation-compose to v2.6.0-alpha07 2023-03-09 04:31:28 +00:00
renovate[bot]andGitHub 90483889c4 fix(deps): update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.0 2023-03-09 01:50:37 +00:00
GitHub Actions b7ef4cb2d6 chore(android): refresh baseline profile 2023-03-09 01:23:10 +00:00
renovate[bot]andGitHub b73261a339 fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.0-alpha11 2023-03-08 22:06:44 +00:00
renovate[bot]andGitHub 0b4fd240cc fix(deps): update dependency androidx.activity:activity-compose to v1.7.0-rc01 2023-03-08 19:58:16 +00:00
Harsh Shandilya b1af5d2349 chore: fix OkHttp capitalisation in changelog 2023-03-09 01:09:39 +05:30
Harsh Shandilya 456205dece chore(deps): bump compose-lint-checks 2023-03-09 01:08:21 +05:30
GitHub Actions 8d092a761a chore(android): refresh baseline profile 2023-03-08 01:28:52 +00:00
Harsh Shandilya 05e9c25742 fix: update incorrect comment 2023-03-08 02:50:17 +05:30
Harsh Shandilya 998171af9e chore: update changelog 2023-03-08 02:43:11 +05:30
Harsh Shandilya 3c62dd9542 fix: address Lint warnings in icon resources 2023-03-08 02:27:51 +05:30
Harsh Shandilya 55cc397333 chore: add labels to Crossfade elements 2023-03-08 02:27:51 +05:30
Harsh Shandilya b969b5f0bf refactor: use immutable collections where flagged by Lint 2023-03-08 02:27:51 +05:30
Harsh Shandilya d7cc55ed53 chore(build): make Lint errors fatal 2023-03-08 02:27:51 +05:30
Harsh Shandilya 9ab8a3e149 fix(api): avoid unnecessary build warning 2023-03-08 02:27:51 +05:30
Harsh Shandilya 0ae48dee33 feat(build): remove Detekt and switch to Slack's Compose lints 2023-03-08 02:27:51 +05:30
Harsh ShandilyaandGitHub d612ed44d9 chore: update changelog 2023-03-07 13:00:52 +05:30
Harsh Shandilya cb798cf011 feat: upgrade to OkHttp 4.10.0 2023-03-07 12:53:51 +05:30
GitHub Actions 8392841554 chore(android): refresh baseline profile 2023-03-07 01:35:08 +00:00
Harsh Shandilya 24d4d3279a fix: remove unused version catalog key 2023-03-07 01:00:07 +05:30
Harsh Shandilya 84bdcb340b feat: add Play Store feature graphic 2023-03-06 10:51:16 +05:30
Harsh Shandilya e4a28684ef feat: refresh icon assets 2023-03-06 10:49:58 +05:30
GitHub Actions 0f5698bb58 chore(android): refresh baseline profile 2023-03-06 01:24:49 +00:00
GitHub Actions ca2da81af5 chore(android): refresh baseline profile 2023-03-05 22:05:24 +00:00
Harsh Shandilya a26fd0862f fix(build): skip Sentry setup for CI benchmarks 2023-03-06 03:17:49 +05:30
Harsh Shandilya ab905d4061 fix(build): set a default for sentryDsn 2023-03-06 02:45:26 +05:30
renovate[bot]andGitHub 7c27e26da7 chore(deps): update jetbrains/qodana-jvm-android docker tag to v2023 2023-03-04 09:56:19 +00:00
renovate[bot]andGitHub 7f49333c42 chore(deps): update dependency gradle to v8.0.2 2023-03-04 05:58:54 +00:00
GitHub Actions 50d2af7be4 feat(release): start next development iteration 2023-03-02 21:52:11 +00:00
GitHub Actions 5746bbebf8 feat(release): bump version 2023-03-02 21:47:23 +00:00
Harsh Shandilya 94551a8c71 fix(release): provide SENTRY_AUTH_TOKEN during release asset build 2023-03-03 03:13:07 +05:30
Harsh Shandilya 50ed66414c chore: add missing sentry.properties 2023-03-03 03:07:00 +05:30
Harsh Shandilya 905c27fe84 feat: set up Sentry 2023-03-03 02:42:01 +05:30
GitHub Actions 62dd421cf4 feat(release): start next development iteration 2023-03-02 08:37:46 +00:00
GitHub Actions b0851ac6f0 feat(release): bump version 2023-03-02 08:36:33 +00:00
Harsh Shandilya 3c9435dcee chore: update changelog 2023-03-02 13:23:52 +05:30
GitHub Actions 546b557796 chore(android): refresh baseline profile 2023-03-02 01:32:00 +00:00
renovate[bot]andGitHub 24d770e952 fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.7.0 2023-03-01 03:24:59 +00:00
GitHub Actions ef1e6a5d39 chore(android): refresh baseline profile 2023-03-01 01:30:24 +00:00
renovate[bot]andGitHub bd8fccb9e5 fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.16.0 2023-02-28 03:33:50 +00:00
GitHub Actions c7c5f08d23 chore(android): refresh baseline profile 2023-02-28 01:27:09 +00:00
renovate[bot]andGitHub 76cfa67682 chore(deps): update agp to v7.4.2 2023-02-27 18:33:36 +00:00
renovate[bot]andGitHub a78ae68024 chore(deps): update dependency io.nlopez.compose.rules:detekt to v0.1.2 2023-02-27 12:02:36 +00:00
GitHub Actions ee2621a487 chore(android): refresh baseline profile 2023-02-27 01:21:54 +00:00
GitHub Actions 87113455a5 chore(android): refresh baseline profile 2023-02-26 01:23:12 +00:00
renovate[bot]andGitHub 7fc98f8b4c chore(deps): update github/codeql-action digest to 32dc499 2023-02-25 01:43:36 +00:00
GitHub Actions 07a6eaac89 chore(android): refresh baseline profile 2023-02-25 01:27:58 +00:00
renovate[bot]andGitHub 357e682a1d fix(deps): update kotlin to v1.5.0 2023-02-24 18:13:00 +00:00
GitHub Actions cd712ef20d chore(android): refresh baseline profile 2023-02-24 01:30:35 +00:00
renovate[bot]andGitHub ac9c054f52 fix(deps): update dependency androidx.navigation:navigation-compose to v2.6.0-alpha06 2023-02-23 08:52:09 +00:00
renovate[bot]andGitHub 8d4cc7fb6f fix(deps): update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.0-rc01 2023-02-23 05:49:17 +00:00
renovate[bot]andGitHub 5c122f85f4 fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.0-alpha10 2023-02-23 01:49:23 +00:00
GitHub Actions d2db437e1a chore(android): refresh baseline profile 2023-02-23 01:30:37 +00:00
renovate[bot]andHarsh Shandilya 40aea664e4 chore(deps): update dependency androidx.compose.compiler:compiler to v1.4.3 2023-02-23 01:02:08 +05:30
renovate[bot]andGitHub 6fd5b120cc fix(deps): update dependency androidx.activity:activity-compose to v1.7.0-beta02 2023-02-22 19:28:06 +00:00
renovate[bot]andHarsh Shandilya 05e7daacb8 chore(deps): update actions/cache action to v3.2.6 2023-02-22 09:23:30 +05:30
Harsh Shandilya f17375e9e1 refactor: move Tags from api to model module 2023-02-22 09:23:23 +05:30
renovate[bot]andGitHub 85c11e0e80 fix(deps): update dependency com.github.ben-manes:gradle-versions-plugin to v0.46.0 2023-02-21 03:31:50 +00:00
GitHub Actions b00083ba2e chore(android): refresh baseline profile 2023-02-21 01:25:36 +00:00
GitHub Actions 6cf9b2a335 chore(android): refresh baseline profile 2023-02-20 01:23:22 +00:00
Harsh Shandilya 95fd166a98 fix: remove slimTests property and make it default 2023-02-19 11:22:47 +05:30
Pratik GoradeandHarsh Shandilya 3da0674031 feat(tags): add api to fetch posts by tags and a utility class Tags
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2023-02-19 11:22:30 +05:30
Harsh Shandilya e62e257154 chore: polish license headers 2023-02-19 09:23:00 +05:30
GitHub Actions dcb0b770c4 chore(android): refresh baseline profile 2023-02-19 01:29:26 +00:00
renovate[bot]andGitHub 8ce0991a5d chore(deps): update gradle/gradle-build-action action to v2.4.0 2023-02-18 20:40:47 +00:00
renovate[bot]andGitHub 3268f2fb90 fix(deps): update dependency org.jsoup:jsoup to v1.15.4 2023-02-18 07:32:56 +00:00
renovate[bot]andGitHub bf43a973ab chore(deps): update dependency gradle to v8.0.1 2023-02-18 03:03:17 +00:00
GitHub Actions 1486220b4a chore(android): refresh baseline profile 2023-02-18 01:25:13 +00:00
GitHub Actions f5262f964e chore(android): refresh baseline profile 2023-02-17 01:31:53 +00:00
GitHub Actions 55eef3b5ba chore(android): refresh baseline profile 2023-02-16 01:35:37 +00:00
renovate[bot]andGitHub 960943ec35 chore(deps): update jetbrains/qodana-action action to v2022.3.4 2023-02-15 16:10:50 +00:00
GitHub Actions d491c1b77c chore(android): refresh baseline profile 2023-02-15 01:25:42 +00:00
Harsh ShandilyaandGitHub d402d55718 fix(common): use system theme in Custom Tabs 2023-02-14 21:31:07 +05:30
GitHub Actions 9f7a3aca14 chore(android): refresh baseline profile 2023-02-14 01:28:28 +00:00
renovate[bot]andGitHub b8e13ae272 chore(deps): update dependency gradle to v8.0 2023-02-13 18:07:43 +00:00
GitHub Actions 01a31ad54b chore(android): refresh baseline profile 2023-02-13 01:27:21 +00:00
GitHub Actions 2e9f874691 chore(android): refresh baseline profile 2023-02-12 01:30:26 +00:00
renovate[bot]andGitHub e5de08792a fix(deps): update dependency com.chimbori.crux:crux to v3.12.0 2023-02-11 09:14:32 +00:00
renovate[bot]andGitHub 293bcf4575 chore(deps): update r0adkll/upload-google-play action to v1.1.1 2023-02-11 05:40:17 +00:00
GitHub Actions 23410dfcdc chore(android): refresh baseline profile 2023-02-11 01:28:36 +00:00
renovate[bot]andGitHub 10da5929e9 fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.15.0 2023-02-10 19:19:58 +00:00
renovate[bot]andGitHub 21a51ff907 chore(deps): update github/codeql-action digest to 17573ee 2023-02-10 19:09:11 +00:00
renovate[bot]andHarsh Shandilya 5333358b53 fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.6.5
(cherry picked from commit b9c9f50229cbae90f6e1699096e6168c60d5070c)
2023-02-11 00:38:14 +05:30
Harsh Shandilya 9638c8bab5 feat(deps): switch to Nacho's compose-rules fork
He is continuining maintenance of the work he started at Twitter.
2023-02-11 00:26:43 +05:30
renovate[bot]andGitHub 4c44df3136 chore(deps): update r0adkll/upload-google-play action to v1.1.0 2023-02-10 11:48:42 +00:00
renovate[bot]andGitHub 318214b119 chore(deps): update actions/cache action to v3.2.5 2023-02-10 06:55:46 +00:00
Harsh Shandilya 498b0b85d2 Merge remote-tracking branches 'origin/renovate/dagger', 'origin/renovate/org.gradle.android.cache-fix' and 'origin/renovate/gradle-8.x'
* origin/renovate/dagger:
  fix(deps): update dagger to v2.45

* origin/renovate/org.gradle.android.cache-fix:
  fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.6.4

* origin/renovate/gradle-8.x:
  chore(deps): update dependency gradle to v8.0-rc-5
2023-02-10 09:21:27 +05:30
renovate[bot]andGitHub 38d07285b2 fix(deps): update dagger to v2.45 2023-02-10 03:14:04 +00:00
renovate[bot]andGitHub cffdfbeafb fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.6.4 2023-02-10 03:14:00 +00:00
renovate[bot]andGitHub 54bcdab2b8 chore(deps): update dependency gradle to v8.0-rc-5 2023-02-10 03:13:56 +00:00
GitHub Actions dd4a4f9235 chore(android): refresh baseline profile 2023-02-10 01:32:10 +00:00
GitHub Actions a2e84f63be feat(release): start next development iteration 2023-02-09 13:30:31 +00:00
GitHub Actions 1c213dff03 feat(release): bump version 2023-02-09 13:29:23 +00:00
Harsh ShandilyaandGitHub 5d1b187518 fix: add changelog entry for crash fix 2023-02-09 18:57:48 +05:30
Harsh Shandilya 24a5b13029 Revert "chore(deps): upgrade to Gradle 8.1.0-alpha03"
This reverts commit 038ded5abd.
2023-02-09 12:50:52 +00:00
Harsh Shandilya bd4691c421 chore(ci): fork keep-a-changelog-new-release action
It hasn't seen any updates in years
2023-02-09 17:28:37 +05:30
Harsh Shandilya a633c1272a chore: add changelog entry for 1.20.0 2023-02-09 17:26:22 +05:30
Harsh Shandilya 332a1c7789 chore: adjust changelog formatting 2023-02-09 17:25:59 +05:30
GitHub Actions 7dc1429f1f feat(release): start next development iteration 2023-02-09 10:08:18 +00:00
GitHub Actions f4dc74c795 feat(release): bump version 2023-02-09 10:07:16 +00:00
renovate[bot]andGitHub 15d5913637 chore(deps): update github/codeql-action digest to 8775e86 2023-02-09 00:16:32 +00:00
renovate[bot]andHarsh Shandilya b0a10b37e6 fix(deps): update dependency androidx.work:work-runtime-ktx to v2.8.0 2023-02-09 01:02:01 +05:30
renovate[bot]andHarsh Shandilya f572e1255a fix(deps): update dependency androidx.profileinstaller:profileinstaller to v1.3.0-beta01 2023-02-09 01:02:00 +05:30
renovate[bot]andHarsh Shandilya 5a491447fe fix(deps): update dependency androidx.paging:paging-compose to v1.0.0-alpha18 2023-02-09 01:01:59 +05:30
renovate[bot]andHarsh Shandilya 81457f6c5b fix(deps): update dependency androidx.navigation:navigation-compose to v2.6.0-alpha05 2023-02-09 01:01:55 +05:30
renovate[bot]andHarsh Shandilya cda5c2d2d8 fix(deps): update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.0-beta01 2023-02-09 01:01:34 +05:30
renovate[bot]andGitHub f9f11e51c8 fix(deps): update dependency androidx.browser:browser to v1.5.0 2023-02-08 18:50:44 +00:00
renovate[bot]andGitHub 19638658ec fix(deps): update dependency androidx.activity:activity-compose to v1.7.0-beta01 2023-02-08 18:46:46 +00:00
Harsh Shandilya f8d220083a fix(ci): allow CI workflow to run in parallel across branches 2023-02-09 00:15:50 +05:30
Harsh Shandilya 648f4502e6 fix(renovate): set branch limit to 15 2023-02-09 00:15:35 +05:30
Harsh Shandilya 5e2c2cbdde chore(deps): use Compose Compiler from gMaven 2023-02-09 00:02:08 +05:30
renovate[bot]andGitHub 52035cde13 chore(deps): update dependency androidx.compose.compiler:compiler to v1.4.2 2023-02-08 18:25:02 +00:00
renovate[bot]andGitHub ea57889959 chore(deps): update jetbrains/qodana-action action to v2022.3.3 2023-02-08 13:20:10 +00:00
Harsh Shandilya 038ded5abd chore(deps): upgrade to Gradle 8.1.0-alpha03 2023-02-08 11:37:55 +05:30
GitHub Actions 1b5d9a87e6 chore(android): refresh baseline profile 2023-02-08 01:27:13 +00:00
renovate[bot]andGitHub 6f625a0f6f chore(deps): update actions/setup-java action to v3.10.0 2023-02-07 21:08:02 +00:00
renovate[bot]andGitHub da1948c0e6 chore(deps): update dependency com.facebook:ktfmt to v0.43 2023-02-07 16:35:32 +00:00
Harsh ShandilyaandGitHub 177d0b7162 fix(renovate): adjust regex manager 2023-02-07 22:04:39 +05:30
renovate[bot]andGitHub 5c350628ff chore(deps): update github/codeql-action digest to 39d8d7e 2023-02-07 02:33:28 +00:00
GitHub Actions cd014f2ba6 chore(android): refresh baseline profile 2023-02-07 01:27:51 +00:00
renovate[bot]andGitHub 08ec5c267c chore(deps): update dependency gradle to v8.0-rc-3 2023-02-06 13:00:38 +00:00
GitHub Actions d930450a6f chore(android): refresh baseline profile 2023-02-06 01:30:00 +00:00
renovate[bot]andHarsh Shandilya d09b5cb306 fix(deps): update kotest to v5.5.5
(cherry picked from commit 7632747f9ba345988dd0ac515c71aaab25f9a9de)
2023-02-06 03:38:22 +05:30
renovate[bot]andGitHub 89dde6e050 fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.14.1 2023-02-05 20:29:34 +00:00
GitHub Actions 4b99abbfa4 chore(android): refresh baseline profile 2023-02-05 01:30:01 +00:00
renovate[bot]andGitHub edc3a017be fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.6.3 2023-02-04 15:01:56 +00:00
renovate[bot]andGitHub ff69ccb384 fix(deps): update dependency com.github.ben-manes:gradle-versions-plugin to v0.45.0 2023-02-04 11:41:04 +00:00
Harsh ShandilyaandGitHub 09b3bd4e74 chore(deps): update Compose Compiler to 1.4.1-dev-k1.8.10-c312d77f4cb 2023-02-04 16:41:36 +05:30
Harsh ShandilyaandGitHub de8dd8a3cf fix(renovate): set maven URLs 2023-02-04 15:34:05 +05:30
renovate[bot]andGitHub 928878928a chore(deps): update kotlin to v1.8.10 2023-02-04 01:49:30 +00:00
GitHub Actions 58c5cfa5b6 chore(android): refresh baseline profile 2023-02-04 01:25:51 +00:00
GitHub Actions 3bf0849f1c chore(android): refresh baseline profile 2023-02-02 01:26:51 +00:00
renovate[bot]andGitHub 85e65fed92 chore(deps): update agp to v7.4.1 2023-02-01 19:17:39 +00:00
GitHub Actions 499fd23342 feat(release): start next development iteration 2023-02-01 13:52:30 +00:00
GitHub Actions 595dbd96e9 feat(release): bump version 2023-02-01 13:51:21 +00:00
Harsh Shandilya b62bc8dc89 chore: update changelog 2023-02-01 15:29:29 +05:30
GitHub Actions a909f1274d chore(android): refresh baseline profile 2023-02-01 07:46:45 +00:00
GitHub Actions 94a7ad788b chore(android): refresh baseline profile 2023-02-01 07:25:57 +00:00
Harsh Shandilya cfa8bc4971 fix(benchmark): enforce profile stability 2023-02-01 11:17:40 +05:30
GitHub Actions a4ad701aff chore(android): refresh baseline profile 2023-01-31 01:20:11 +00:00
renovate[bot]andGitHub 00e94eb1cb chore(deps): update actions/cache action to v3.2.4 2023-01-30 12:14:02 +00:00
Harsh Shandilya ff478b3365 fix(renovate): specify explicit registry URLs for regex Maven deps 2023-01-30 10:03:51 +05:30
GitHub Actions 7bf599ce19 chore(android): refresh baseline profile 2023-01-30 01:17:26 +00:00
GitHub Actions a4b9e227bf chore(android): refresh baseline profile 2023-01-29 01:17:30 +00:00
GitHub Actions cb9039e927 chore(android): refresh baseline profile 2023-01-28 01:17:50 +00:00
renovate[bot]andGitHub bf65027105 chore(deps): update github/codeql-action digest to 3ebbd71 2023-01-27 11:23:21 +00:00
GitHub Actions 28d655efc2 chore(android): refresh baseline profile 2023-01-27 09:47:51 +00:00
renovate[bot]andGitHub e711781eb0 fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.14.0 2023-01-27 04:47:56 +00:00
renovate[bot]andGitHub 8576bad580 chore(deps): update jetbrains/qodana-action action to v2022.3.2 2023-01-27 01:49:31 +00:00
GitHub Actions 56e089ffa9 chore(android): refresh baseline profile 2023-01-27 01:29:13 +00:00
renovate[bot]andGitHub 6625ebcfc7 chore(deps): update github/codeql-action digest to 436dbd9 2023-01-26 18:02:20 +00:00
Harsh Shandilya 540ea7ba43 feat: upgrade kotlinx.serialization to 1.5.0-RC 2023-01-26 21:49:29 +05:30
Harsh Shandilya dea2d8b468 fix(android): raise target API suppression in manifest 2023-01-26 11:49:08 +05:30
renovate[bot]andHarsh Shandilya ba292bf709 fix(deps): update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.0-alpha05
(cherry picked from commit 073a8d00dc6bfb10654b040e3d79dc296b01aab2)
2023-01-26 10:35:22 +05:30
renovate[bot]andHarsh Shandilya 2ce4d1de2e fix(deps): update dependency androidx.browser:browser to v1.5.0-rc01
(cherry picked from commit ea010bf8e1c5dfb1497c2a2478054cf0927dc3db)
2023-01-26 10:35:21 +05:30
renovate[bot]andHarsh Shandilya 9d6712d94b fix(deps): update dependency androidx.activity:activity-compose to v1.7.0-alpha04
(cherry picked from commit ef7b1062eebea83c935e57a39477bc6378619596)
2023-01-26 10:35:21 +05:30
Harsh Shandilya 4e920328e1 fix(gradle): allow resolution of androidx.resourceinspection
Newer AppCompat releases depend on this
2023-01-26 10:35:11 +05:30
GitHub Actions 1865c62db8 chore(android): refresh baseline profile 2023-01-24 01:18:43 +00:00
GitHub Actions d61206a7d2 chore(android): refresh baseline profile 2023-01-23 01:19:01 +00:00
GitHub Actions a94c48028d chore(android): refresh baseline profile 2023-01-22 01:22:12 +00:00
GitHub Actions 909c615ae6 feat(release): start next development iteration 2023-01-21 07:26:31 +00:00
GitHub Actions 5d87bb077f feat(release): bump version 2023-01-21 07:25:25 +00:00
GitHub Actions 72b5b2c795 chore(android): refresh baseline profile 2023-01-21 07:16:07 +00:00
Harsh Shandilya ce91650788 fix(deps): downgrade to Compose 2023.01.00
There seems to be a regression with `produceState` in this release

Also reverts fb4beb08ee
2023-01-21 12:32:13 +05:30
GitHub Actions 1b2534eca6 chore(android): refresh baseline profile 2023-01-21 01:23:34 +00:00
Harsh Shandilya 5e3356e1d4 fix(android): set a key for database items 2023-01-21 01:50:00 +05:30
Harsh Shandilya ddc7a7598d fix(android): throw a different error for removed stories 2023-01-21 01:46:59 +05:30
Harsh Shandilya 2cfe9d73a2 chore(deps): update app.cash.sqldelight to 2.0.0-alpha05 2023-01-21 00:07:20 +05:30
Harsh Shandilya dbed41bdbd fix(renovate): disable updates for SQLDelight 2023-01-20 23:57:54 +05:30
GitHub Actions a0296f5d5a chore(android): refresh baseline profile 2023-01-20 01:19:27 +00:00
GitHub Actions 39cca12708 chore(android): refresh baseline profile 2023-01-19 01:21:48 +00:00
renovate[bot]andGitHub 0c4e3db59c chore(deps): update github/codeql-action digest to a34ca99 2023-01-18 20:27:54 +00:00
Harsh ShandilyaandGitHub 8dea17cbf2 chore(deps): update androidx.compose.compiler to 1.4.0 2023-01-18 14:32:52 +05:30
GitHub Actions b428c73602 chore(android): refresh baseline profile 2023-01-18 01:22:44 +00:00
Harsh ShandilyaandGitHub 8c9ce29a7a chore: add Renovate config rename to blame ignore revs 2023-01-17 22:14:22 +05:30
Harsh ShandilyaandGitHub f304304bc5 fix(renovate): switch config to JSON5 2023-01-17 22:13:41 +05:30
Harsh Shandilya f14941cf27 chore(deps): upgrade to Gradle 8.0-RC-2 2023-01-17 18:54:46 +05:30
GitHub Actions c83afb3cd7 chore(android): refresh baseline profile 2023-01-17 01:18:23 +00:00
GitHub Actions dfc6d80127 chore(android): refresh baseline profile 2023-01-16 01:18:43 +00:00
GitHub Actions 3ad1b07ff8 chore(android): refresh baseline profile 2023-01-15 01:23:13 +00:00
Harsh Shandilya d3c2861939 fix(renovate): adapt to Qodana linter switch 2023-01-14 19:30:27 +05:30
renovate[bot]andGitHub 8632f8fd7a fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.13.0 2023-01-14 02:22:57 +00:00
GitHub Actions 83585b4a8a chore(android): refresh baseline profile 2023-01-14 01:24:57 +00:00
Harsh Shandilya e2e3186bb4 chore(gradle): update to 8.0-20230104085204+0000 nightly 2023-01-13 15:16:18 +05:30
Harsh Shandilya 29765f0024 fix(gradle): remove unnecessary properties 2023-01-13 11:12:55 +05:30
Harsh Shandilya 43edeaff04 fix(gradle): remove obsolete CC workaround 2023-01-13 11:11:33 +05:30
Harsh Shandilya 2b7cf7d3cb fix(renovate): remove AGP version clamp 2023-01-13 10:55:23 +05:30
Harsh Shandilya fdf13fd201 chore(deps): bump com.squareup:anvil to v2.4.4 2023-01-13 10:54:39 +05:30
renovate[bot]andGitHub 92ba77a838 chore(deps): update agp to v7.4.0 2023-01-13 02:07:17 +00:00
GitHub Actions d910810dd4 chore(android): refresh baseline profile 2023-01-13 01:22:45 +00:00
Harsh Shandilya 5f8853c69d fix(renovate): fix Compose BOM resolution 2023-01-13 00:09:08 +05:30
Harsh Shandilya 0f9b35efb1 fix(renovate): remove obsoleted Compose group 2023-01-12 22:39:47 +05:30
Harsh Shandilya 7096e62948 fix(deps): switch to Chris Banes' Compose alpha BOM 2023-01-12 22:37:10 +05:30
renovate[bot]andGitHub acb7c0e670 chore(deps): update github/codeql-action digest to 515828d 2023-01-12 14:00:44 +00:00
Harsh ShandilyaandGitHub bb91e6e083 fix(deps): update accompanist to 0.29.0-alpha 2023-01-12 19:02:26 +05:30
Harsh ShandilyaandGitHub 67a922362d chore(deps): bump accompanist to 0.29.0 2023-01-12 17:39:39 +05:30
GitHub Actions 56be44b918 feat(release): start next development iteration 2023-01-12 07:38:31 +00:00
GitHub Actions 15493aec1a feat(release): bump version 2023-01-12 07:35:33 +00:00
Harsh Shandilya 9aef7582bd chore: update README 2023-01-12 12:52:29 +05:30
Harsh Shandilya 5378ec6854 fix(ci): disable scheduled code analysis jobs
They both fail for stupid reasons 🤷
2023-01-12 12:42:00 +05:30
Harsh Shandilya 79dbb64275 chore(gradle): reformat version catalog 2023-01-12 11:27:54 +05:30
GitHub Actions b8912e747a chore(android): refresh baseline profile 2023-01-12 01:24:00 +00:00
renovate[bot]andHarsh Shandilya a9dcd0157a fix(deps): update dependency androidx.lifecycle:lifecycle-viewmodel-compose to v2.6.0-alpha04 2023-01-12 02:55:54 +05:30
renovate[bot]andHarsh Shandilya 45e8993d75 fix(deps): update dependency androidx.test.uiautomator:uiautomator to v2.3.0-alpha02 2023-01-12 02:55:54 +05:30
renovate[bot]andHarsh Shandilya 39bd1fa2eb fix(deps): update dependency androidx.profileinstaller:profileinstaller to v1.3.0-alpha03 2023-01-12 02:55:54 +05:30
renovate[bot]andHarsh Shandilya 5b33fbc20b fix(deps): update dependency androidx.browser:browser to v1.5.0-beta01 2023-01-12 02:55:53 +05:30
renovate[bot]andHarsh Shandilya 196195d867 fix(deps): update dependency androidx.benchmark:benchmark-macro-junit4 to v1.2.0-alpha09 2023-01-12 02:55:28 +05:30
renovate[bot]andHarsh Shandilya 20b8076235 fix(deps): update dependency androidx.activity:activity-compose to v1.7.0-alpha03 2023-01-12 02:54:44 +05:30
Harsh Shandilya 5f49c8149a fix(renovate): batch Compose updates together 2023-01-12 02:51:01 +05:30
Harsh Shandilya fb4beb08ee fix(common): adopt new Compose APIs 2023-01-12 02:40:37 +05:30
Harsh Shandilya 6750eff9fa chore(deps): upgrade to Compose 2023-01-12 alpha release 2023-01-12 02:31:00 +05:30
Harsh Shandilya 692cc8ce67 chore: update changelog 2023-01-12 02:20:09 +05:30
Harsh Shandilya a59b6411b1 feat: implement support for persisting read comments
Fixes #358
2023-01-12 02:20:09 +05:30
Harsh Shandilya 1345709450 feat(android): wire up PostCommentsQueries 2023-01-12 01:06:34 +05:30
Harsh Shandilya 8433f38f6e fix(model): add Comment#shortId 2023-01-12 01:06:34 +05:30
Harsh Shandilya 91c3d0f9a6 feat(common): add support for unread comments to UI 2023-01-12 01:06:34 +05:30
Harsh Shandilya 579a2ffe2e fix(database): add a migration to generate an empty PostComments table 2023-01-12 00:58:07 +05:30
Harsh Shandilya 918f28feab fix(renovate): prevent Anvil from being queried in the snapshots repo
Renovate incorrectly picks up the 2.4.4-1-8-0-SNAPSHOT version
2023-01-11 18:04:51 +05:30
Harsh Shandilya 7b13d40797 chore(deps): upgrade to Kotlin 1.8.0 2023-01-11 17:41:04 +05:30
GitHub Actions 002588a45a chore(android): refresh baseline profile 2023-01-11 01:20:37 +00:00
Harsh Shandilya 1ae0cbb95d feat(database): add a table for post comments 2023-01-11 03:05:36 +05:30
Harsh Shandilya 3e2d32e4c9 chore: refresh license headers 2023-01-11 02:40:44 +05:30
Harsh Shandilya 403f7d47b1 refactor(database): rename test class 2023-01-11 02:39:11 +05:30
GitHub Actions d1fcebdf4c chore(android): refresh baseline profile 2023-01-10 01:17:58 +00:00
renovate[bot]andGitHub a983bd729c chore(deps): update actions/cache action to v3.2.3 2023-01-09 05:49:54 +00:00
GitHub Actions 8d311a1193 chore(android): refresh baseline profile 2023-01-09 01:20:48 +00:00
GitHub Actions 6bbd2c73b5 chore(android): refresh baseline profile 2023-01-08 01:16:53 +00:00
GitHub Actions f851e2d626 chore(android): refresh baseline profile 2023-01-07 01:25:39 +00:00
renovate[bot]andGitHub 97aafc764f chore(deps): update agp to v7.4.0-rc03 2023-01-06 19:21:43 +00:00
Harsh Shandilya 183e10dba8 chore(renovate): prevent AGP from being upgraded past 7.4.x 2023-01-07 00:47:48 +05:30
Harsh Shandilya f5deaaa8ff fix(deps): downgrade AGP to 7.4.0-beta02 2023-01-07 00:44:38 +05:30
Harsh Shandilya 55537ea191 fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v2.6.1 2023-01-07 00:36:03 +05:30
Harsh Shandilya 98818023e9 chore: update changelog 2023-01-07 00:36:03 +05:30
Harsh Shandilya e67df253de Revert "feat(android): use enter always scroll behavior for TopAppBar"
This reverts commit eeef2c347d.
2023-01-07 00:36:03 +05:30
renovate[bot]andGitHub 53524c8ef8 chore(deps): update actions/upload-artifact action to v3.1.2 2023-01-06 15:46:07 +00:00
Harsh Shandilya bc90a8941a chore(github): allow running analysis actions manually 2023-01-06 20:37:42 +05:30
Harsh Shandilya 5c413d1f12 chore(qodana): switch to the Android linter 2023-01-06 20:37:42 +05:30
renovate[bot]andGitHub 8b5ab33730 chore(deps): update github/codeql-action digest to 959cbb7 2023-01-06 03:58:04 +00:00
GitHub Actions d4d1288900 chore(android): refresh baseline profile 2023-01-06 01:31:11 +00:00
renovate[bot]andGitHub f4f07d0ce3 chore(deps): update actions/checkout action to v3.3.0 2023-01-05 22:08:46 +00:00
renovate[bot]andGitHub 6282f4d6e0 chore(deps): update actions/checkout digest to ac59398 2023-01-05 18:54:06 +00:00
Harsh Shandilya 19f5f8a0ca chore: hide baseline-prof from diffs
Having this pollute regular diffs doesn't provide much value if any
at all, since it is generated by an automated process and never
touched by hand.
2023-01-05 21:08:55 +05:30
Harsh Shandilya a296d2b827 sync-backend: delete
Realistically this will be much more enjoyable to do in Rust or Go *shudder*
so let's cut out the unused code until we can tackle the backend.
2023-01-05 21:07:07 +05:30
Harsh Shandilya 45872f1653 chore: re-enable code quality workflows to run on a schedule 2023-01-05 21:00:06 +05:30
GitHub Actions 074420056b chore(android): refresh baseline profile 2023-01-05 01:23:05 +00:00
renovate[bot]andHarsh Shandilya 9f7e05d79a chore(deps): update agp to v8.0.0-alpha11 2023-01-05 00:30:58 +05:30
Harsh Shandilya 955299bd89 chore(renovate): re-enable AGP updates 2023-01-04 23:58:57 +05:30
renovate[bot]andHarsh Shandilya 6520758722 fix(deps): update dependency androidx.test.espresso:espresso-core to v3.5.1 2023-01-04 13:06:36 +05:30
renovate[bot]andGitHub 583137aa25 fix(deps): update dependency androidx.test.ext:junit to v1.1.5 2023-01-04 04:14:16 +00:00
GitHub Actions 8afce7706c chore(android): refresh baseline profile 2023-01-04 01:19:47 +00:00
renovate[bot]andGitHub 7ae0a0bae6 fix(deps): update dependency androidx.test:runner to v1.5.2 2023-01-03 21:54:08 +00:00
renovate[bot]andGitHub f34d6c5222 fix(deps): update ktor to v2.2.2 2023-01-03 18:18:52 +00:00
GitHub Actions 002f4f9309 chore(android): refresh baseline profile 2023-01-03 01:18:09 +00:00
renovate[bot]andGitHub bf77a9aaed fix(deps): update dependency com.diffplug.spotless:spotless-plugin-gradle to v6.12.1 2023-01-02 05:09:06 +00:00
GitHub Actions d17c178eaa chore(android): refresh baseline profile 2023-01-02 01:22:20 +00:00
GitHub Actions 2c0ba0fae9 chore(android): refresh baseline profile 2023-01-01 01:24:21 +00:00
renovate[bot]andGitHub 0396a488cd fix(deps): update dependency com.slack.eithernet:eithernet to v1.3.1 2022-12-31 18:53:39 +00:00
GitHub ActionsandHarsh Shandilya f5ef483cd9 chore(android): refresh baseline profile 2022-12-31 05:38:40 +00:00
Harsh Shandilya 78960f6d4e feat(deps): upgrade to Gradle 8.0-rc-1 2022-12-31 05:38:40 +00:00
GitHub Actions 2be9408560 chore(android): refresh baseline profile 2022-12-30 01:16:41 +00:00
GitHub Actions 46dc6fbe91 chore(android): refresh baseline profile 2022-12-29 01:15:22 +00:00
GitHub Actions e411cb3d7f chore(android): refresh baseline profile 2022-12-28 01:18:43 +00:00
renovate[bot]andGitHub 00535dc859 chore(deps): update actions/cache action to v3.2.2 2022-12-27 13:49:21 +00:00
GitHub Actions 465e6931ad chore(android): refresh baseline profile 2022-12-27 01:15:23 +00:00
GitHub Actions 7e64100491 chore(android): refresh baseline profile 2022-12-26 01:19:10 +00:00
GitHub Actions e199f00ca0 chore(android): refresh baseline profile 2022-12-25 01:18:18 +00:00
renovate[bot]andGitHub 8722636b13 fix(deps): update dependency ch.qos.logback:logback-classic to v1.4.5 2022-12-24 15:42:59 +00:00
Harsh Shandilya 5db4a1ee8d sync-backend: initialize barebones module
This is simply an import of the project generated by start.ktor.io cleaned of
its ungodly wildcard import fetish and better integrated into our existing build
system.
2022-12-24 14:17:59 +00:00
GitHub Actions b0bae12e6b feat(release): start next development iteration 2022-12-24 02:26:25 +00:00
GitHub Actions 585d42c6aa feat(release): bump version 2022-12-24 02:25:00 +00:00
GitHub Actions 47448616dd chore(android): refresh baseline profile 2022-12-24 01:19:28 +00:00
GitHub Actions ccd64b46e3 chore(android): refresh baseline profile 2022-12-23 20:38:40 +00:00
Harsh Shandilya bce227357f chore(gradle): run versionCatalogFormat 2022-12-24 01:43:30 +05:30
Harsh Shandilya 2ec1633c51 fix(gradle): remove unnecessary repository declarations 2022-12-24 01:38:04 +05:30
Harsh Shandilya ed8528aea4 fix(build-logic): tweak DependencyUpdates configuration 2022-12-24 01:36:29 +05:30
Harsh Shandilya 3cc74f9bcf fix(android): stupid copypasta :clown:
Fixes 2afbc73bd4
2022-12-24 01:22:38 +05:30
renovate[bot]andGitHub 015c9929b3 chore(deps): update actions/cache action to v3.2.1 2022-12-23 07:53:38 +00:00
Harsh Shandilya 76737b0eed chore(gradle): remove Compose Compiler metrics opt-in
This doesn't seem worth generating for each build

Revert "fix(gradle): address list reassignment lints"

This reverts commit 1d2da7c2f8.

Revert "chore: enable Compose Compiler metrics"

This reverts commit 0d668ac3aa.
2022-12-22 11:25:06 +05:30
Harsh Shandilya 28c454261f fix(deps): return to AGP 8.x 2022-12-22 11:19:05 +05:30
GitHub Actions 327ec9b6a5 chore(android): refresh baseline profile 2022-12-22 01:14:47 +00:00
GitHub Actions fc617a5dfa chore(android): refresh baseline profile 2022-12-21 19:16:21 +00:00
renovate[bot]andGitHub c6289908c4 chore(deps): update actions/cache action to v3.2.0 2022-12-21 15:13:13 +00:00
Harsh ShandilyaandGitHub ca0706f94b fix(ci): fix baseline profile path 2022-12-21 16:44:18 +05:30
Harsh Shandilya 350a64d479 fix(benchmark): simplify 2022-12-21 15:03:05 +05:30
Harsh Shandilya 058561e4d6 chore(ci): tweak baseline profile execution environment 2022-12-21 14:31:36 +05:30
Harsh Shandilya a4bc5476a4 feat(ci): rework benchmark workflow to improve perf 2022-12-21 14:13:23 +05:30
Harsh Shandilya 1fe559ff04 chore(benchmark): remove test filter annotations 2022-12-21 13:55:15 +05:30
Harsh Shandilya 78f050f115 Revert "fix(benchmark): remove startup benchmarks"
This reverts commit fab5cb45c4.
2022-12-21 13:36:54 +05:30
Harsh Shandilya 0d964c4a5d fix(ci): use a more granular test filter 2022-12-21 13:33:06 +05:30
Harsh Shandilya c24c433c0e chore(ci): log stacktrace on failure 2022-12-21 13:18:07 +05:30
Harsh Shandilya fd9010d468 chore(android): refresh baseline profile 2022-12-21 13:11:08 +05:30
Harsh Shandilya 90f40075e8 fix(ci): fix incorrect baseline profile destination 2022-12-21 13:10:13 +05:30
GitHub Actions f621f785f8 feat(release): start next development iteration 2022-12-20 19:17:34 +00:00
GitHub Actions 76d62906c8 feat(release): bump version 2022-12-20 19:16:18 +00:00
Harsh ShandilyaandGitHub dbeafbb569 fix(benchmark): upgrade baseline profile generator size
This takes long enough to be a large test
2022-12-21 00:05:24 +05:30
Harsh ShandilyaandGitHub fab5cb45c4 fix(benchmark): remove startup benchmarks
These just always fail and it's not worth pursuing a fix
2022-12-20 23:28:59 +05:30
Harsh Shandilya 7b593806eb fix: prevent unwanted list jumping during paging refresh
Fixes #347

Fixes SDP-34
2022-12-20 22:47:53 +05:30
Harsh ShandilyaandGitHub f6064616b0 chore: reword changelog entries 2022-12-20 16:57:24 +05:30
Harsh ShandilyaandGitHub 36d999ebb4 chore(build-logic): use kotlin DSL's apply extension 2022-12-20 16:40:20 +05:30
Harsh Shandilya 79920f6180 chore: align copyright headers with Spotless expectations 2022-12-20 16:01:44 +05:30
Harsh Shandilya 36ab72226c refactor(build-logic): simplify plugin setup 2022-12-20 16:01:18 +05:30
renovate[bot]andGitHub 7cc81047d4 chore(deps): update plugin anvil to v2.4.3 2022-12-17 00:47:20 +00:00
Harsh Shandilya 82252dbe2d chore: remove unused Nix shell config 2022-12-16 18:19:16 +05:30
renovate[bot]andGitHub da1825498a chore(deps): update actions/setup-java action to v3.9.0 2022-12-14 16:13:19 +00:00
Harsh Shandilya 947a04d82d chore: update changelog 2022-12-14 19:41:14 +05:30
Harsh Shandilya 75ab508dc3 refactor: rework ProgressBar usage 2022-12-14 18:32:28 +05:30
Harsh Shandilya 1d2da7c2f8 fix(gradle): address list reassignment lints 2022-12-14 18:27:01 +05:30
Harsh Shandilya dd019279ec fix(comments): ensure load failure screen renders correctly
Fixes SDP-21
2022-12-14 17:56:16 +05:30
Harsh Shandilya 485282a48d feat(common): change progress indicator to linear
Fixes SDP-20
2022-12-14 17:46:42 +05:30
Harsh Shandilya eeef2c347d feat(android): use enter always scroll behavior for TopAppBar 2022-12-13 17:03:04 +00:00
Harsh Shandilya b7229c6d15 chore: add changelog entry for expanded state fix 2022-12-13 11:43:46 +05:30
Harsh Shandilya da80605ae1 chore(common): updateAllExpanded -> setExpanded 2022-12-13 11:37:41 +05:30
Anunay Maheshwari 4066a86ad6 comments: Update isExpanded based on the parent node being toggled (Fixes #352) 2022-12-13 10:56:28 +05:30
renovate[bot]andGitHub 0f595f7b02 chore(deps): update actions/checkout action to v3.2.0 2022-12-12 19:52:23 +00:00
GitHub Actions 42f3068b01 feat(release): start next development iteration 2022-12-12 08:02:05 +00:00
GitHub Actions 0312c3f431 feat(release): bump version 2022-12-12 08:01:02 +00:00
Harsh Shandilya 7d324ddb8c refactor(common): tweak visibility of module members 2022-12-12 12:47:23 +05:30
Harsh Shandilya c7b7a786f3 chore: update changelog 2022-12-12 12:02:59 +05:30
Harsh Shandilya 26f69c2027 feat(common): match node collapse behaviour with the lobste.rs site 2022-12-12 12:02:59 +05:30
Harsh Shandilya 450601f26b feat(common): use a simplified search algorithm 2022-12-12 11:26:29 +05:30
Harsh Shandilya 2ab69de686 fix(common): do not compute a new node if it cannot be used 2022-12-12 10:44:00 +05:30
Harsh Shandilya 0083aa69b5 refactor(common): optimize comment entry display 2022-12-12 10:44:00 +05:30
Anunay MaheshwariandHarsh Shandilya 18d82a5eb3 refactor(comments): convert internal representation to a tree 2022-12-12 10:44:00 +05:30
Harsh Shandilya 0d668ac3aa chore: enable Compose Compiler metrics 2022-12-12 02:41:12 +05:30
Harsh Shandilya b1a32496ba refactor: improve skippability of Composables 2022-12-12 02:41:12 +05:30
Harsh Shandilya 4db59db7a1 fix(scripts): set a trap to delete temp file 2022-12-12 02:10:58 +05:30
Harsh Shandilya 0843352514 fix(ci): fix benchmark assemble tasks 2022-12-12 02:10:42 +05:30
renovate[bot]andGitHub aa50d6449d chore(deps): pin reactivecircus/android-emulator-runner action to 50986b1 2022-12-11 15:02:50 +00:00
Harsh Shandilya 6a41b966c5 feat(ci): disable lint workflows
This hasn't brought much value but eats up too much CI time
2022-12-11 19:09:44 +05:30
Harsh Shandilya 943b9bd091 chore: re-encrypt secrets with age 2022-12-11 19:09:44 +05:30
Harsh Shandilya 010f69031a feat(ci): add a job to regenerate baseline profile 2022-12-11 17:22:07 +05:30
Harsh Shandilya 168271a8f4 chore: add changelog entry for post update worker tweaks 2022-12-10 20:16:04 +05:30
Harsh Shandilya ea92d64972 fix(android): do not force re-enqueue post update job on each start 2022-12-10 20:16:04 +05:30
Harsh Shandilya 766f14cd22 refactor(android): run post updates in a batch transaction 2022-12-10 20:16:04 +05:30
Harsh Shandilya 33210319bb fix(android): manually set up WorkManager 2022-12-10 19:31:22 +05:30
Harsh Shandilya 7ef0a8fc51 fix(database): ensure schema migrations can run 2022-12-10 18:27:12 +05:30
Harsh Shandilya 1f850435b1 feat(database): add description to the saved post table 2022-12-10 18:27:12 +05:30
GitHub Actions 9d8fd77a08 feat(release): start next development iteration 2022-12-10 10:21:13 +00:00
190 changed files with 32343 additions and 19892 deletions
+3
View File
@@ -3,3 +3,6 @@
e7f4c8a7ebe4e907f65af46e6dddfd3a542415c0
ab2713154f846b3db6d44625d1022bf421b275d0
cbdfa67d075ec1f8ceec0f3559498cbca01783a0
# Renamed Renovate config file
f304304bc5b64edf189aaa473b05df912067a8bd
+1 -1
View File
@@ -1,4 +1,4 @@
* text=auto eol=lf
**/dependencies/** linguist-generated
**/clawicons/** linguist-generated
android/src/main/baseline-prof.txt linguist-generated
android/src/main/baseline-prof.txt linguist-generated -diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 198 KiB

-88
View File
@@ -1,88 +0,0 @@
{
"extends": [
"config:base",
":dependencyDashboard",
"helpers:pinGitHubActionDigests",
"github>msfjarvis/shared-workflows//renovate/automerge"
],
"packageRules": [
{
"matchPackagePatterns": [
"^com.android.tools.build",
"^com.android.test",
"^gradle"
],
"enabled": false
},
{
"matchPackagePatterns": [
"^kotlin",
"^org.jetbrains.kotlin",
"^androidx.compose.compiler"
],
"groupName": "kotlin"
},
{
"managers": [
"gradle"
],
"packagePatterns": [
"^com.squareup.okhttp3"
],
"enabled": false
},
{
"matchDatasources": [
"maven"
],
"matchPackageNames": [
"androidx.compose.compiler:compiler"
],
"registryUrls": [
"https://maven.google.com/"
]
}
],
"regexManagers": [
{
"fileMatch": [
"build-logic/kotlin-plugins/src/main/kotlin/dev/msfjarvis/aps/gradle/SpotlessPlugin.kt"
],
"matchStrings": [
"KTFMT_VERSION = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "maven",
"depNameTemplate": "com.facebook:ktfmt"
},
{
"fileMatch": [
"build-logic/kotlin-plugins/src/main/kotlin/dev/msfjarvis/aps/gradle/Detekt.kt"
],
"matchStrings": [
"TWITTER_RULES_VERSION = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "maven",
"depNameTemplate": "com.twitter.compose.rules:detekt"
},
{
"fileMatch": [
"gradle/libs.versions.toml"
],
"matchStrings": [
"composeCompiler = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "maven",
"depNameTemplate": "androidx.compose.compiler:compiler"
},
{
"fileMatch": [
"qodana.yaml"
],
"matchStrings": [
"jetbrains/qodana-jvm-community:(?<currentValue>.*)"
],
"datasourceTemplate": "docker",
"depNameTemplate": "jetbrains/qodana-jvm-community",
}
]
}
+91
View File
@@ -0,0 +1,91 @@
{
"extends": [
"config:base",
":dependencyDashboard",
"helpers:pinGitHubActionDigests",
"github>msfjarvis/shared-workflows//renovate/automerge"
],
"branchConcurrentLimit": 15,
"packageRules": [
{
matchDatasources: [
"maven"
],
registryUrls: [
"https://maven.google.com/",
"https://repo1.maven.org/maven2",
"https://plugins.gradle.org/m2/",
],
},
{
"matchPackagePatterns": [
"^androidx.*",
],
"groupName": "androidx"
},
{
"matchPackagePatterns": [
"^kotlin",
"^org.jetbrains.kotlin",
"^androidx.compose.compiler",
"^anvil",
"^coil",
],
"enabled": false
},
{
"matchPackagePatterns": [
"^io.sentry",
"^sentry",
],
"groupName": "sentry"
},
{
"managers": [
"gradle"
],
"packagePatterns": [
// Renovate refuses to stop resolving this from the snapshots repo
"^app.cash.sqldelight",
// Currently on a pre-release version for bugfixes
"com.android.tools:r8",
],
"enabled": false
},
],
"regexManagers": [
{
"fileMatch": [
"SpotlessPlugin\.kt$"
],
"matchStrings": [
"KTFMT_VERSION = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "maven",
"depNameTemplate": "com.facebook:ktfmt",
"registryUrlTemplate": "https://repo1.maven.org/maven2/",
},
{
"fileMatch": [
"gradle/libs.versions.toml"
],
"matchStrings": [
"composeCompiler = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "maven",
"depNameTemplate": "androidx.compose.compiler:compiler",
"registryUrlTemplate": "https://maven.google.com",
},
{
"fileMatch": [
"gradle/libs.versions.toml"
],
"matchStrings": [
"sentry-sdk = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "maven",
"depNameTemplate": "io.sentry:sentry-android",
"registryUrlTemplate": "https://repo1.maven.org/maven2/",
}
]
}
+105
View File
@@ -0,0 +1,105 @@
name: Baseline profile generation
on:
# every day at 00:43
schedule:
- cron: '43 0 * * *'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
baseline-profile:
runs-on: macos-latest
timeout-minutes: 45
env:
TERM: dumb
steps:
- name: Checkout repository
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
token: ${{ secrets.POST_RELEASE_GH_TOKEN }}
fetch-depth: 0
- name: Accept all SDK licenses
shell: bash
run: printf 'y\ny\ny\ny\ny\ny\n' | $ANDROID_HOME/tools/bin/sdkmanager --licenses
- name: Get build-tools directory
id: build-tools-path
shell: bash
run: echo "dir=${ANDROID_HOME}/build-tools/34.0.0-rc3" >> "${GITHUB_OUTPUT}"
- name: Cache build-tools
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.build-tools-path.outputs.dir }}
key: ${{ runner.os }}-34.0.0-rc3
- name: Set up JDK
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
- name: Set up Git author
shell: bash
run: |
git config user.name "GitHub Actions"
git config user.email noreply@github.com
- name: Setup Gradle caching
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 # v2.4.2
with:
gradle-home-cache-cleanup: true
cache-read-only: true
- name: Decrypt secrets
run: |
./scripts/setup-age.sh
./scripts/signing-setup.sh "$ENCRYPT_KEY"
env:
ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
# This allows us to build most of what we need without the emulator running
# and using resources
- name: Build app and benchmark
run: ./gradlew :benchmark:assembleBenchmark :android:assembleBenchmark
- name: Clear unused Gradle Managed Devices
run: ./gradlew cleanManagedDevices --unused-only
- name: Run benchmark on Gradle Managed Device
run: |
./gradlew api31BenchmarkAndroidTest \
-Dorg.gradle.workers.max=1 \
-Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile \
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect"
# If we're on main branch, copy over the baseline profile and
# commit it to the repository (if changed)
- name: Commit baseline profile into main
if: github.ref == 'refs/heads/main'
run: |
# Pull down any changes which may have been committed while this workflow has been running
git pull
# Sort the baseline profile, output to android/
sort -o android/src/main/baseline-prof.txt benchmark/build/outputs/managed_device_android_test_additional_output/api31/BaselineProfileGenerator_generateBaselineProfile-baseline-prof.txt
# If the baseline profile has changed, commit it
if [[ $(git diff --stat android/src/main/baseline-prof.txt) != '' ]]; then
git add android/src/main/baseline-prof.txt
git commit -m "chore(android): refresh baseline profile" && git push
fi
# Upload the entire output folder and attach it to the CI run
- name: Attach baseline profile
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: Baseline profile output
path: benchmark/build/outputs/managed_device_android_test_additional_output
- name: Clean secrets
if: always()
run: scripts/signing-cleanup.sh
+46 -17
View File
@@ -11,38 +11,48 @@ on:
- main
concurrency:
group: ${{ github.workflow }}
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
fetch-depth: 0
- name: Accept all SDK licenses
shell: bash
run: printf 'y\ny\ny\ny\ny\ny\n' | $ANDROID_HOME/tools/bin/sdkmanager --licenses
- name: Get build-tools directory
id: build-tools-path
shell: bash
run: echo "dir=${ANDROID_HOME}/build-tools/34.0.0-rc3" >> "${GITHUB_OUTPUT}"
- name: Cache build-tools
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.build-tools-path.outputs.dir }}
key: ${{ runner.os }}-34.0.0-rc3
- name: Set up JDK
uses: actions/setup-java@c3ac5dd0ed8db40fedb61c32fbe677e6b355e94c # v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
- name: Run unit tests
uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # tag=v2.3.3
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 # v2.4.2
with:
arguments: --no-configuration-cache --stacktrace check -PslimTests
gradle-home-cache-cleanup: true
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Run Detekt
uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # tag=v2.3.3
with:
arguments: --no-configuration-cache --stacktrace detektMain
arguments: --no-configuration-cache --stacktrace check
gradle-home-cache-cleanup: true
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: (Fail-only) Upload test report
if: failure()
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # tag=v3.1.1
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: Test report
path: android/build/reports
@@ -53,21 +63,40 @@ jobs:
needs: [ "check" ]
steps:
- name: Checkout repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Accept all SDK licenses
shell: bash
run: printf 'y\ny\ny\ny\ny\ny\n' | $ANDROID_HOME/tools/bin/sdkmanager --licenses
- name: Get build-tools directory
id: build-tools-path
shell: bash
run: echo "dir=${ANDROID_HOME}/build-tools/34.0.0-rc3" >> "${GITHUB_OUTPUT}"
- name: Cache build-tools
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.build-tools-path.outputs.dir }}
key: ${{ runner.os }}-34.0.0-rc3
- name: Set up JDK
uses: actions/setup-java@c3ac5dd0ed8db40fedb61c32fbe677e6b355e94c # v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
- name: Decrypt secrets
run: scripts/signing-setup.sh "$ENCRYPT_KEY"
run: |
./scripts/setup-age.sh
./scripts/signing-setup.sh "$ENCRYPT_KEY"
env:
ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
- name: Build release app
uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # tag=v2.3.3
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 # v2.4.2
env:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
with:
arguments: --no-configuration-cache --stacktrace collectReleaseApks
gradle-home-cache-cleanup: true
+44 -8
View File
@@ -1,11 +1,13 @@
name: "CodeQL"
name: CodeQL
on:
workflow_dispatch:
push:
branches:
- main
schedule:
- cron: "20 3 * * 0"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
analyze:
@@ -17,14 +19,48 @@ jobs:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
- name: Accept all SDK licenses
shell: bash
run: printf 'y\ny\ny\ny\ny\ny\n' | $ANDROID_HOME/tools/bin/sdkmanager --licenses
- name: Get build-tools directory
id: build-tools-path
shell: bash
run: echo "dir=${ANDROID_HOME}/build-tools/34.0.0-rc3" >> "${GITHUB_OUTPUT}"
- name: Cache build-tools
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.build-tools-path.outputs.dir }}
key: ${{ runner.os }}-34.0.0-rc3
- name: Set up JDK
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
- name: Setup Gradle caching
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 # v2.4.2
with:
gradle-home-cache-cleanup: true
cache-read-only: true
- name: Initialize CodeQL
uses: github/codeql-action/init@a669cc5936cc5e1b6a362ec1ff9e410dc570d190 # v2
uses: github/codeql-action/init@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6
with:
languages: java
- name: Autobuild
uses: github/codeql-action/autobuild@a669cc5936cc5e1b6a362ec1ff9e410dc570d190 # v2
tools: latest
queries: +security-extended
- name: Build project
shell: bash
run: |
./gradlew assemble
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@a669cc5936cc5e1b6a362ec1ff9e410dc570d190 # v2
uses: github/codeql-action/analyze@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6
with:
category: "/language:java"
-19
View File
@@ -1,19 +0,0 @@
name: Qodana
on:
workflow_dispatch:
pull_request:
push:
branches:
- main
jobs:
qodana:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3
with:
fetch-depth: 0
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@3fdeefa830a7634a5c04f1cd70fcfb69956137a2 # v2022.3.0
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
+30 -7
View File
@@ -2,18 +2,36 @@ name: Release to Google Play
on:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
publish-google-play-release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
token: ${{ secrets.POST_RELEASE_GH_TOKEN }}
fetch-depth: 0
- name: Accept all SDK licenses
shell: bash
run: printf 'y\ny\ny\ny\ny\ny\n' | $ANDROID_HOME/tools/bin/sdkmanager --licenses
- name: Get build-tools directory
id: build-tools-path
shell: bash
run: echo "dir=${ANDROID_HOME}/build-tools/34.0.0-rc3" >> "${GITHUB_OUTPUT}"
- name: Cache build-tools
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3
with:
path: ${{ steps.build-tools-path.outputs.dir }}
key: ${{ runner.os }}-34.0.0-rc3
- name: Set up JDK
uses: actions/setup-java@c3ac5dd0ed8db40fedb61c32fbe677e6b355e94c # v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
@@ -25,13 +43,15 @@ jobs:
git config user.email noreply@github.com
- name: Setup Gradle caching
uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # tag=v2.3.3
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629 # v2.4.2
with:
gradle-home-cache-cleanup: true
cache-read-only: true
- name: Decrypt secrets
run: scripts/signing-setup.sh "$ENCRYPT_KEY"
run: |
./scripts/setup-age.sh
./scripts/signing-setup.sh "$ENCRYPT_KEY"
env:
ENCRYPT_KEY: ${{ secrets.ENCRYPT_KEY }}
@@ -43,7 +63,7 @@ jobs:
echo VERSION="${VERSION}" >> $GITHUB_ENV
- name: Update changelog
uses: thomaseizinger/keep-a-changelog-new-release@5bc232893483441c5d6cd6c9dcb1e48abf9a2bae # 1.3.0
uses: msfjarvis/keep-a-changelog-new-release@bf43ae42f4e42f137572950af426efcf6e777207 # 2.1.0
with:
tag: v${{ env.VERSION }}
version: ${{ env.VERSION }}
@@ -55,8 +75,11 @@ jobs:
- name: Build release assets
shell: bash
env:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: |
./gradlew --no-configuration-cache collectReleaseApks collectReleaseBundle
./gradlew --no-configuration-cache collectReleaseApks collectReleaseBundle -PsentryUploadMappings
- name: Clean secrets
run: scripts/signing-cleanup.sh
@@ -78,7 +101,7 @@ jobs:
printf '%s' "${CHANGELOG}" >> distribution/whatsnew/whatsnew-en-GB
- name: Publish bundle to Google Play
uses: r0adkll/upload-google-play@78c9e796b1035c94169c101d8e46cb880194bfc3 # tag=v1.0.19
uses: r0adkll/upload-google-play@70c7397e868b00eccd390222f492ab3e30520d09 # v1.1.1
with:
mappingFile: android/bundle/mapping.txt
packageName: dev.msfjarvis.claw.android
+2
View File
@@ -245,3 +245,5 @@ hs_err_pid*
keystore.properties
distribution/
screenshots/
claw-export.json
+1
View File
@@ -1,2 +1,3 @@
*.json
baseline-prof.txt
**/test/resources/**
+196 -30
View File
@@ -7,110 +7,276 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.29.0] - 2023-06-08
### Added
* Backup and restore options for saved posts
### Fixed
* Spamming the comments button no longer causes it to be opened multiple times
* Saved posts screen now has a visual indication when you have nothing saved
* Iconography has been updated across the board to be more consistent
## [1.28.0] - 2023-06-03
### Changed
* Navigation transitions have been slightly sped up
### Fixed
* Add workaround for a native library loading crash observed on some devices
## [1.27.0] - 2023-05-31
### Changed
* Small accessibility improvements
* Slightly tweak the layout for story items to take less vertical space
* Upgrade to Compose `1.5.0-beta01` release
* Set accessibility web URI for profile screen
* Directly use Material Icons from upstream artifacts
* Upgrade dependencies
* Add adaptive navigation support (thanks @Yash-Garg)
* Use latest SQLite for backing databases
## [1.26.0] - 2023-05-03
### Changed
* Upgrade to Compose May release
* Disable Sentry performance reporting
* Migrate to Compose Foundation `FlowRow` in `LobstersCard`
## [1.25.0] - 2023-04-18
### Changed
* Make the app draw edge to edge
* Simplify Top App Bar color scheme
* Rework how baseline profiles are generated
* Upgrade to Compose April release
## [1.24.0] - 2023-03-24
### Changed
* Rebuild app icon assets to align better with Material guidelines
* Adopt Slack's Compose lints and address issues found by it
* Upgrade to OkHttp 4.x
* Upgrade to Compose March release
* Start work on support for logging in with lobste.rs
## [1.23.0] - 2023-03-02
### Added
* Introduce [Sentry](https://sentry.io) for error reporting and performance monitoring
## [1.22.0] - 2023-03-02
### Changed
* In-app browser now respects the user's choice for dark mode
* Upgrade dependencies
## [1.21.0] - 2023-02-09
### Changed
* Fix bug that caused the app to crash on launch
## [1.20.0] - 2023-02-09
### Changed
* Upgrade dependencies
## [1.19.0] - 2023-02-01
### Changed
* Upgrade dependencies
* Optimize packaged baseline profiles
## [1.18.0] - 2023-01-21
### Changed
* Special-case deleted stories in comments API
* Fix regression where save button had the incorrect visual state
## [1.17.0] - 2023-01-12
### Added
* The app will now mark new comments as unread when returning to posts
### Changed
* Upgrade to Kotlin 1.8.0
* Revert questionable app bar scrolling behaviour change
## [1.16.0] - 2022-12-24
### Changed
* Fix bug where newest posts tab actually showed hottest posts instead
## [1.15.0] - 2022-12-20
### Changed
* Fix a case where collapsing the parent of an already collapsed comment caused it to become expanded
* Tweak progress bar UI to use a linear indicator
* Allow app bar to hide when scrolling down
* Fix bug where refreshing a list of posts caused it to jump around multiple times
## [1.14.0] - 2022-12-12
### Changed
* Rework how often saved posts are updated
* Collapsing a comment now collapses all comments under it similar to how it works on the website
## [1.13.0] - 2022-12-10
### Changed
- Fix crash when viewing [jcs](https://lobste.rs/u/jcs)' comments
* Fix crash when viewing [jcs](https://lobste.rs/u/jcs)' comments
## [1.12.0] - 2022-12-09
### Changed
- Do not schedule post update job every time the app starts
- Improve favicon loading to reduce unnecessary redraws
- Fix post lists being reloaded unnecessarily
* Do not schedule post update job every time the app starts
* Improve favicon loading to reduce unnecessary redraws
* Fix post lists being reloaded unnecessarily
## [1.11.0] - 2022-12-07
### Changed
- Upgrade to Compose 2022.12.00 release
- Refresh packaged baseline profile
- Improve how saved state of posts is queried
* Upgrade to Compose 2022.12.00 release
* Refresh packaged baseline profile
* Improve how saved state of posts is queried
## [1.10.0] - 2022-11-30
### Changed
- Configure Coil image loader with better caching settings
- Refresh packaged baseline profile
* Configure Coil image loader with better caching settings
* Refresh packaged baseline profile
## [1.9.0] - 2022-11-28
### Changed
- A loading indicator is added to the bottom of the post list to identify when new posts are being fetched
* A loading indicator is added to the bottom of the post list to identify when new posts are being fetched
## [1.8.0] - 2022-11-21
### Changed
- The release pipeline now automatically generates Play Store release notes from the changelog file
* The release pipeline now automatically generates Play Store release notes from the changelog file
### Fixed
- Downgrade AGP to 8.0.0-alpha07 to fix Baseline Profiles not being packaged
* Downgrade AGP to 8.0.0-alpha07 to fix Baseline Profiles not being packaged
## [1.7.0] - 2022-11-19
### Changed
- Switch to Compose Material's swipe refresh feature
- Change metadata extractor logic to no longer prefer canonical URLs. The submitted URL will be retained as-is now.
- Remove navigation transition animations
* Switch to Compose Material's swipe refresh feature
* Change metadata extractor logic to no longer prefer canonical URLs. The submitted URL will be retained as-is now.
* Remove navigation transition animations
## [1.6.0] - 2022-11-14
### Changed
- Migrate dependency injection from Hilt to Anvil + Whetstone
* Migrate dependency injection from Hilt to Anvil + Whetstone
## [1.5.0] - 2022-11-10
### Changed
- Upgrade to Compose 2022.11.00 release
* Upgrade to Compose 2022.11.00 release
## [1.4.0] - 2022-11-02
### Changed
- Misc fixes to link metadata extractor
* Misc fixes to link metadata extractor
## [1.3.0] - 2022-10-24
### Changed
- Prevent errors during link metadata retrieval from crashing the app
- Update Jetpack libraries to 2022-10-24 release
* Prevent errors during link metadata retrieval from crashing the app
* Update Jetpack libraries to 2022-10-24 release
## [1.2.0] - 2022-10-17
### Changed
- Lazily load link metadata to improve comment page loading speed
- Upgrade to latest Compose release
- Refactor code to align with Twitter's public Compose guidelines
* Lazily load link metadata to improve comment page loading speed
* Upgrade to latest Compose release
* Refactor code to align with Twitter's public Compose guidelines
## [1.1.0] - 2022-09-30
### Added
- Add score and relative time to comments
* Add score and relative time to comments
### Changed
- Update Jetpack Compose
- Declare data backup and transfer rules
- Improve legibility of links in comments and user profiles
- Commonize and improve how network errors are displayed
* Update Jetpack Compose
* Declare data backup and transfer rules
* Improve legibility of links in comments and user profiles
* Commonize and improve how network errors are displayed
## [1.0.0] - 2022-09-20
- Initial Play Store release
* Initial Play Store release
[Unreleased]: https://github.com/msfjarvis/compose-lobsters/compare/v1.13.0...HEAD
[Unreleased]: https://github.com/msfjarvis/compose-lobsters/compare/v1.29.0...HEAD
[1.29.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.28.0...v1.29.0
[1.28.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.27.0...v1.28.0
[1.27.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.26.0...v1.27.0
[1.26.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.25.0...v1.26.0
[1.25.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.24.0...v1.25.0
[1.24.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.23.0...v1.24.0
[1.23.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.22.0...v1.23.0
[1.22.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.21.0...v1.22.0
[1.21.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.20.0...v1.21.0
[1.20.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.19.0...v1.20.0
[1.19.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.18.0...v1.19.0
[1.18.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.17.0...v1.18.0
[1.17.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.16.0...v1.17.0
[1.16.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.15.0...v1.16.0
[1.15.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.13.0...v1.14.0
[1.13.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.12.0...v1.13.0
+28 -7
View File
@@ -2,20 +2,41 @@
Unofficial Android app for read-only access to [lobste.rs](https://lobste.rs), built with [Jetpack Compose](https://developer.android.com/jetpack/compose).
<img src="https://github.com/msfjarvis/compose-lobsters/blob/main/.github/readme_feature.webp"
alt="Get it on Google Play"
height="550" />
## Download
<a href="https://play.google.com/store/apps/details?id=dev.msfjarvis.claw.android">
<img src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png"
alt="Get it on Google Play"
height="80" />
</a>
Snapshots from the development branch can be obtained [here](https://github.com/msfjarvis/compose-lobsters/releases/tag/nightly).
> Snapshots from the development branch can be obtained [here](https://github.com/msfjarvis/compose-lobsters/releases/tag/nightly).
<img src="https://github.com/msfjarvis/compose-lobsters/blob/main/.github/readme_feature.webp"
alt="Side by side screenshots of the app's main page in dark and light UI modes"
height="550" />
## Dependency Diagram
```mermaid
%%{
init: {
'theme': 'neutral'
}
}%%
graph LR
benchmark --> android
android --> api
android --> common
android --> core
android --> database
android --> model
api --> model
common --> core
common --> database
common --> model
```
## License
See [LICENSE](LICENSE)
+41 -18
View File
@@ -1,28 +1,25 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
@file:Suppress("UnstableApiUsage")
import dev.msfjarvis.claw.gradle.addTestDependencies
plugins {
id("dev.msfjarvis.claw.android-application")
id("dev.msfjarvis.claw.rename-artifacts")
id("dev.msfjarvis.claw.kotlin-android")
id("dev.msfjarvis.claw.kotlin-kapt")
id("dev.msfjarvis.claw.sentry")
id("dev.msfjarvis.claw.versioning-plugin")
alias(libs.plugins.anvil)
alias(libs.plugins.modulegraphassert)
alias(libs.plugins.whetstone)
}
whetstone {
addOns {
compose.set(true)
workManager.set(true)
}
}
android {
namespace = "dev.msfjarvis.claw.android"
defaultConfig { applicationId = "dev.msfjarvis.claw.android" }
@@ -37,26 +34,36 @@ android {
matchingFallbacks += "release"
isDebuggable = false
proguardFile("benchmark-rules.pro")
applicationIdSuffix = ".benchmark"
}
}
packaging { jniLibs { useLegacyPackaging = true } }
}
moduleGraphAssert {
assertOnAnyBuild = true
maxHeight = 4
restricted = arrayOf(":core -X> :.*")
}
whetstone {
addOns {
compose.set(true)
workManager.set(true)
}
}
dependencies {
kapt(libs.dagger.compiler)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.dagger)
implementation(projects.api)
implementation(projects.common)
implementation(projects.core)
implementation(projects.coroutineUtils)
implementation(projects.database)
implementation(projects.metadataExtractor)
implementation(projects.model)
implementation(platform(libs.okhttp.bom))
implementation(libs.accompanist.sysuicontroller)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.material)
implementation(libs.androidx.compose.material.icons.extended)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material3.window.size)
implementation(libs.androidx.core.splashscreen)
implementation(libs.androidx.datastore.preferences)
implementation(libs.androidx.lifecycle.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.paging.compose)
@@ -64,6 +71,22 @@ dependencies {
implementation(libs.androidx.work.runtime.ktx)
implementation(libs.coil)
implementation(libs.copydown)
implementation(libs.crux)
implementation(libs.dagger)
implementation(libs.jsoup)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.napier)
implementation(libs.sqldelight.extensions.coroutines)
implementation(projects.api)
implementation(projects.common)
implementation(projects.core)
implementation(projects.database)
implementation(projects.model)
kapt(libs.dagger.compiler)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.okhttp.mockwebserver)
addTestDependencies(project)
}
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 7.4.0-alpha09" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha09)" variant="all" version="7.4.0-alpha09">
<issues format="6" by="lint 8.0.1" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.1)" variant="all" version="8.0.1">
</issues>
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

+7 -10
View File
@@ -1,22 +1,19 @@
-allowaccessmodification
-dontpreverify
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
-keepattributes *Annotation*
-keepclasseswithmembernames class * {
native <methods>;
native <methods>;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * implements android.os.Parcelable {
public static final ** CREATOR;
public static final ** CREATOR;
}
-keep class androidx.annotation.Keep
@@ -24,13 +21,13 @@
-keep @androidx.annotation.Keep class * {*;}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <methods>;
@androidx.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <fields>;
@androidx.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
@androidx.annotation.Keep <init>(...);
@androidx.annotation.Keep <init>(...);
}
+20 -27
View File
@@ -1,29 +1,22 @@
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
-dontobfuscate
-keepattributes SourceFile, LineNumberTable
# From https://github.com/square/retrofit/blob/master/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
# Keep inherited services.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>
# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
# R8 full mode strips generic signatures from return types if not kept.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
+15 -15
View File
@@ -6,14 +6,14 @@
<application
android:name=".ClawApplication"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/full_backup_content"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.Claw.SplashScreen"
android:enableOnBackInvokedCallback="true"
tools:targetApi="s">
tools:targetApi="tiramisu">
<profileable
android:shell="true"
tools:targetApi="29" />
@@ -25,19 +25,6 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:ssp="//lobste.rs" />
<data android:host="lobste.rs" />
<data android:path="/" />
<data android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -149,6 +136,10 @@
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
<meta-data
android:name="com.deliveryhero.whetstone.worker.WhetstoneWorkerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
<!-- https://issuetracker.google.com/issues/258619948 -->
<receiver
@@ -159,5 +150,14 @@
<action android:name="androidx.profileinstaller.action.BENCHMARK_OPERATION" />
</intent-filter>
</receiver>
<!-- Required: set your sentry.io project identifier (DSN) -->
<meta-data android:name="io.sentry.dsn" android:value="${sentryDsn}" />
<!-- enable automatic breadcrumbs for user interactions (clicks, swipes, scrolls) -->
<meta-data android:name="io.sentry.traces.user-interaction.enable" android:value="${enableSentry}" />
<meta-data android:name="io.sentry.breadcrumbs.user-interaction" android:value="${enableSentry}" />
<!-- enable screenshot for crashes -->
<meta-data android:name="io.sentry.attach-screenshot" android:value="${enableSentry}" />
<!-- enable view hierarchy for crashes -->
<meta-data android:name="io.sentry.attach-view-hierarchy" android:value="${enableSentry}" />
</application>
</manifest>
+29149 -15668
View File
File diff suppressed because it is too large Load Diff
@@ -46,7 +46,7 @@ class ClawApplication : Application(), ApplicationComponentOwner {
WorkManager.getInstance(this)
.enqueueUniquePeriodicWork(
"updateSavedPosts",
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
ExistingPeriodicWorkPolicy.UPDATE,
postUpdateWorkRequest,
)
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -11,7 +11,10 @@ import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import com.deliveryhero.whetstone.Whetstone
import com.deliveryhero.whetstone.activity.ContributesActivityInjector
import dev.msfjarvis.claw.android.ui.LobstersApp
@@ -26,14 +29,19 @@ class MainActivity : ComponentActivity() {
@Inject lateinit var htmlConverter: HTMLConverter
private var webUri: String? = null
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
installSplashScreen()
Whetstone.inject(this)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
val windowSizeClass = calculateWindowSizeClass(this)
LobstersApp(
urlLauncher = urlLauncher,
htmlConverter = htmlConverter,
windowSizeClass = windowSizeClass,
setWebUri = { url -> webUri = url },
)
}
@@ -0,0 +1,42 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.injection
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import com.deliveryhero.whetstone.ForScope
import com.deliveryhero.whetstone.app.ApplicationScope
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
import dev.msfjarvis.claw.core.coroutines.DispatcherProvider
import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
@Module
@ContributesTo(ApplicationScope::class)
class DataStoreModule {
@Singleton
@Provides
fun provideLoginDatastore(
@ForScope(ApplicationScope::class) context: Context,
dispatcherProvider: DispatcherProvider,
): DataStore<Preferences> {
return PreferenceDataStoreFactory.create(
corruptionHandler = null,
migrations = emptyList(),
scope = CoroutineScope(dispatcherProvider.io() + SupervisorJob()),
) {
context.preferencesDataStoreFile("login")
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021 Harsh Shandilya.
* Copyright © 2021-2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -8,22 +8,13 @@ package dev.msfjarvis.claw.android.injection
import com.deliveryhero.whetstone.app.ApplicationScope
import com.squareup.anvil.annotations.ContributesTo
import dagger.Binds
import dagger.Module
import dagger.Provides
import dev.msfjarvis.claw.android.ui.util.HTMLConverterImpl
import dev.msfjarvis.claw.common.comments.HTMLConverter
import io.github.furstenheim.CopyDown
@Module
@ContributesTo(ApplicationScope::class)
object HTMLConverterModule {
@Provides
fun provideHTMLConverter() =
object : HTMLConverter {
private val copydown = CopyDown()
override fun convertHTMLToMarkdown(html: String): String {
return copydown.convert(html)
}
}
interface HTMLConverterModule {
@Binds fun HTMLConverterImpl.bind(): HTMLConverter
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021 Harsh Shandilya.
* Copyright © 2021-2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -0,0 +1,34 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.injection
import android.app.Application
import android.util.Log
import androidx.work.Configuration
import androidx.work.WorkManager
import androidx.work.WorkerFactory
import com.deliveryhero.whetstone.app.ApplicationScope
import com.squareup.anvil.annotations.ContributesMultibinding
import dev.msfjarvis.claw.core.injection.AppPlugin
import javax.inject.Inject
@ContributesMultibinding(ApplicationScope::class)
class WorkManagerPlugin
@Inject
constructor(
private val workerFactory: WorkerFactory,
) : AppPlugin {
override fun apply(application: Application) {
WorkManager.initialize(
application,
Configuration.Builder()
.setWorkerFactory(workerFactory)
.setMinimumLoggingLevel(Log.DEBUG)
.build()
)
}
}
@@ -1,15 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.injection
import javax.inject.Qualifier
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class DatabaseDispatcher
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class MainDispatcher
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class IODispatcher
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -13,7 +13,7 @@ import com.slack.eithernet.ApiResult.Success
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dev.msfjarvis.claw.android.injection.IODispatcher
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.model.LobstersPost
import java.io.IOException
import kotlinx.coroutines.CoroutineDispatcher
@@ -27,13 +27,14 @@ constructor(
) : PagingSource<Int, LobstersPost>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
val page = params.key ?: 1
val page = params.key ?: STARTING_PAGE_INDEX
return when (val result = withContext(ioDispatcher) { remoteFetcher.getItemsAtPage(page) }) {
is Success ->
LoadResult.Page(
itemsBefore = (page - 1) * PAGE_SIZE,
data = result.value,
prevKey = if (page == 1) null else page - 1,
nextKey = page.plus(1)
prevKey = if (page == STARTING_PAGE_INDEX) null else page - 1,
nextKey = page + 1,
)
is Failure.NetworkFailure -> LoadResult.Error(result.error)
is Failure.UnknownFailure -> LoadResult.Error(result.error)
@@ -42,12 +43,19 @@ constructor(
}
}
override fun getRefreshKey(state: PagingState<Int, LobstersPost>): Int {
return state.pages.size + 1
override fun getRefreshKey(state: PagingState<Int, LobstersPost>): Int? {
return state.anchorPosition?.let { anchorPosition ->
(anchorPosition / PAGE_SIZE).coerceAtLeast(STARTING_PAGE_INDEX)
}
}
@AssistedFactory
interface Factory {
fun create(remoteFetcher: RemoteFetcher<LobstersPost>): LobstersPagingSource
}
companion object {
const val PAGE_SIZE = 25
const val STARTING_PAGE_INDEX = 1
}
}
@@ -0,0 +1,23 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.settings
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import javax.inject.Inject
class LoginSettings
@Inject
constructor(
val dataStore: DataStore<Preferences>,
) {
companion object {
val CSRF_TOKEN = stringPreferencesKey("csrf_token")
val LOGIN_COOKIE = stringPreferencesKey("login_cookie")
}
}
@@ -1,28 +1,41 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.ImportExport
import androidx.compose.material.icons.filled.NewReleases
import androidx.compose.material.icons.filled.Whatshot
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.outlined.Whatshot
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
@@ -38,43 +51,44 @@ import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import androidx.paging.compose.collectAsLazyPagingItems
import com.deliveryhero.whetstone.compose.injectedViewModel
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import dev.msfjarvis.claw.android.R
import dev.msfjarvis.claw.android.ui.datatransfer.DataTransferScreen
import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationBar
import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationRail
import dev.msfjarvis.claw.android.ui.decorations.NavigationItem
import dev.msfjarvis.claw.android.ui.decorations.TransparentSystemBars
import dev.msfjarvis.claw.android.ui.lists.DatabasePosts
import dev.msfjarvis.claw.android.ui.lists.NetworkPosts
import dev.msfjarvis.claw.android.ui.navigation.ClawNavigationType
import dev.msfjarvis.claw.android.ui.navigation.Destinations
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.common.comments.CommentsPage
import dev.msfjarvis.claw.common.comments.HTMLConverter
import dev.msfjarvis.claw.common.res.ClawIcons
import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.ui.decorations.ClawAppBar
import dev.msfjarvis.claw.common.ui.surfaceColorAtNavigationBarElevation
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.common.user.UserProfile
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.coroutines.launch
@OptIn(
ExperimentalComposeUiApi::class,
ExperimentalMaterial3Api::class,
)
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun LobstersApp(
urlLauncher: UrlLauncher,
htmlConverter: HTMLConverter,
windowSizeClass: WindowSizeClass,
setWebUri: (String?) -> Unit,
modifier: Modifier = Modifier,
viewModel: ClawViewModel = injectedViewModel(),
) {
val systemUiController = rememberSystemUiController()
val hottestListState = rememberLazyListState()
val newestListState = rememberLazyListState()
val savedListState = rememberLazyListState()
val navController = rememberNavController()
val coroutineScope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
val postActions = rememberPostActions(urlLauncher, navController, viewModel)
val backStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = backStackEntry?.destination?.route
@@ -82,67 +96,57 @@ fun LobstersApp(
val hottestPosts = viewModel.hottestPosts.collectAsLazyPagingItems()
val newestPosts = viewModel.newestPosts.collectAsLazyPagingItems()
val savedPosts by viewModel.savedPosts.collectAsState(emptyMap())
val savedPosts by viewModel.savedPosts.collectAsState(persistentMapOf())
val navigationType = ClawNavigationType.fromSize(windowSizeClass.widthSizeClass)
LobstersTheme(
dynamicColor = true,
providedValues = arrayOf(LocalUriHandler provides urlLauncher),
) {
val currentUiMode = LocalConfiguration.current.uiMode
val systemBarsColor = MaterialTheme.colorScheme.surfaceColorAtNavigationBarElevation()
val backgroundColor = MaterialTheme.colorScheme.background
val navItems =
listOf(
persistentListOf(
NavigationItem(
label = "Hottest",
route = Destinations.Hottest.route,
icon = ClawIcons.Flame,
selectedIcon = ClawIcons.FlameFilled,
icon = Icons.Outlined.Whatshot,
selectedIcon = Icons.Filled.Whatshot,
) {
coroutineScope.launch { hottestListState.animateScrollToItem(index = 0) }
},
NavigationItem(
label = "Newest",
route = Destinations.Newest.route,
icon = ClawIcons.New,
selectedIcon = ClawIcons.NewFilled,
icon = Icons.Outlined.NewReleases,
selectedIcon = Icons.Filled.NewReleases,
) {
coroutineScope.launch { newestListState.animateScrollToItem(index = 0) }
},
NavigationItem(
label = "Saved",
route = Destinations.Saved.route,
icon = ClawIcons.HeartBorder,
selectedIcon = ClawIcons.Heart,
icon = Icons.Outlined.FavoriteBorder,
selectedIcon = Icons.Filled.Favorite,
) {
coroutineScope.launch { savedListState.animateScrollToItem(index = 0) }
},
)
SideEffect { systemUiController.setStatusBarColor(color = systemBarsColor) }
// Track UI mode as a key to force a navbar color update when dark theme is toggled
LaunchedEffect(currentDestination, currentUiMode) {
val color =
if (navItems.none { item -> item.route == currentDestination }) {
backgroundColor
} else {
systemBarsColor
}
systemUiController.setNavigationBarColor(color = color)
}
TransparentSystemBars()
Scaffold(
topBar = {
ClawAppBar(
backgroundColor = systemBarsColor,
navigationIcon = {
if (navItems.none { it.route == currentDestination }) {
if (
navController.previousBackStackEntry != null &&
navItems.none { it.route == currentDestination }
) {
IconButton(
onClick = { if (!navController.popBackStack()) context.getActivity()?.finish() }
) {
Icon(
painter = ClawIcons.ArrowBack,
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Go back to previous screen",
)
}
@@ -153,83 +157,112 @@ fun LobstersApp(
Text(text = stringResource(R.string.app_name), fontWeight = FontWeight.Bold)
}
},
actions = {
if (navItems.any { it.route == currentDestination }) {
IconButton(onClick = { navController.navigate(Destinations.DataTransfer.route) }) {
Icon(
imageVector = Icons.Filled.ImportExport,
contentDescription = "Data transfer options"
)
}
}
},
)
},
bottomBar = {
ClawNavigationBar(
navController = navController,
items = navItems,
isVisible = navItems.any { it.route == currentDestination },
)
AnimatedVisibility(visible = navigationType == ClawNavigationType.BOTTOM_NAVIGATION) {
ClawNavigationBar(
navController = navController,
items = navItems,
isVisible = navItems.any { it.route == currentDestination },
)
}
},
snackbarHost = { SnackbarHost(snackbarHostState) },
modifier = modifier.semantics { testTagsAsResourceId = true },
) { paddingValues ->
NavHost(
navController = navController,
startDestination = Destinations.startDestination.route,
modifier = Modifier.padding(paddingValues),
) {
val uri = LobstersApi.BASE_URL
composable(
route = Destinations.Hottest.route,
deepLinks =
listOf(navDeepLink { uriPattern = uri }, navDeepLink { uriPattern = "$uri/" }),
Row(modifier = Modifier.padding(paddingValues)) {
AnimatedVisibility(visible = navigationType == ClawNavigationType.NAVIGATION_RAIL) {
ClawNavigationRail(
navController = navController,
items = navItems,
isVisible = navItems.any { it.route == currentDestination },
)
}
NavHost(
navController = navController,
startDestination = Destinations.startDestination.route,
// Make animations 2x faster than default specs
enterTransition = { fadeIn(animationSpec = tween(350)) },
exitTransition = { fadeOut(animationSpec = tween(350)) },
) {
setWebUri("https://lobste.rs/")
NetworkPosts(
lazyPagingItems = hottestPosts,
listState = hottestListState,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
)
}
composable(
route = Destinations.Newest.route,
) {
setWebUri("https://lobste.rs/")
NetworkPosts(
lazyPagingItems = newestPosts,
listState = newestListState,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
)
}
composable(Destinations.Saved.route) {
setWebUri(null)
DatabasePosts(
items = savedPosts,
listState = savedListState,
postActions = postActions,
)
}
composable(
route = Destinations.Comments.route,
arguments = listOf(navArgument("postId") { type = NavType.StringType }),
deepLinks =
listOf(
navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}/.*" },
navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}" },
),
) { backStackEntry ->
val postId = requireNotNull(backStackEntry.arguments?.getString("postId"))
setWebUri("https://lobste.rs/s/$postId")
CommentsPage(
postId = postId,
postActions = postActions,
htmlConverter = htmlConverter,
)
}
composable(
route = Destinations.User.route,
arguments = listOf(navArgument("username") { type = NavType.StringType }),
deepLinks =
listOf(navDeepLink { uriPattern = "$uri/u/${Destinations.User.placeholder}" }),
) { backStackEntry ->
val username = requireNotNull(backStackEntry.arguments?.getString("username"))
UserProfile(
username = username,
getProfile = viewModel::getUserProfile,
)
val uri = LobstersApi.BASE_URL
composable(route = Destinations.Hottest.route) {
setWebUri("https://lobste.rs/")
NetworkPosts(
lazyPagingItems = hottestPosts,
listState = hottestListState,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
)
}
composable(route = Destinations.Newest.route) {
setWebUri("https://lobste.rs/")
NetworkPosts(
lazyPagingItems = newestPosts,
listState = newestListState,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
)
}
composable(route = Destinations.Saved.route) {
setWebUri(null)
DatabasePosts(
items = savedPosts,
listState = savedListState,
postActions = postActions,
)
}
composable(
route = Destinations.Comments.route,
arguments = listOf(navArgument("postId") { type = NavType.StringType }),
deepLinks =
listOf(
navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}/.*" },
navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}" },
),
) { backStackEntry ->
val postId = requireNotNull(backStackEntry.arguments?.getString("postId"))
setWebUri("https://lobste.rs/s/$postId")
CommentsPage(
postId = postId,
postActions = postActions,
htmlConverter = htmlConverter,
getSeenComments = viewModel::getSeenComments,
markSeenComments = viewModel::markSeenComments,
)
}
composable(
route = Destinations.User.route,
arguments = listOf(navArgument("username") { type = NavType.StringType }),
deepLinks =
listOf(navDeepLink { uriPattern = "$uri/u/${Destinations.User.placeholder}" }),
) { backStackEntry ->
val username = requireNotNull(backStackEntry.arguments?.getString("username"))
setWebUri("https://lobste.rs/u/$username")
UserProfile(
username = username,
getProfile = viewModel::getUserProfile,
)
}
composable(route = Destinations.DataTransfer.route) {
DataTransferScreen(
context = context,
dataTransferRepository = viewModel.dataTransferRepository,
snackbarHostState = snackbarHostState,
)
}
}
}
}
@@ -0,0 +1,136 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.datatransfer
import android.content.Context
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.activity.result.contract.ActivityResultContracts.GetContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Upload
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.android.viewmodel.DataTransferRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
private const val MIME_TYPE = "application/json"
@Composable
fun DataTransferScreen(
context: Context,
dataTransferRepository: DataTransferRepository,
snackbarHostState: SnackbarHostState,
modifier: Modifier = Modifier,
) {
val coroutineScope = rememberCoroutineScope()
Column(modifier = modifier) {
ImportOption(context, coroutineScope, dataTransferRepository, snackbarHostState)
ExportOption(context, coroutineScope, dataTransferRepository, snackbarHostState)
}
}
@Composable
private fun ImportOption(
context: Context,
coroutineScope: CoroutineScope,
dataTransferRepository: DataTransferRepository,
snackbarHostState: SnackbarHostState,
) {
val importAction =
rememberLauncherForActivityResult(GetContent()) { uri ->
if (uri == null) {
coroutineScope.launch { snackbarHostState.showSnackbarDismissing("No file selected") }
return@rememberLauncherForActivityResult
}
coroutineScope.launch {
context.contentResolver.openInputStream(uri)?.use { stream ->
dataTransferRepository.importPosts(stream)
snackbarHostState.showSnackbarDismissing("Successfully imported posts")
}
}
}
SettingsActionItem(
title = "Import saved posts",
description = "Import saved posts from a previously generated export",
icon = Icons.Filled.Download,
) {
importAction.launch(MIME_TYPE)
}
}
@Composable
private fun ExportOption(
context: Context,
coroutineScope: CoroutineScope,
dataTransferRepository: DataTransferRepository,
snackbarHostState: SnackbarHostState,
) {
val exportAction =
rememberLauncherForActivityResult(CreateDocument(MIME_TYPE)) { uri ->
if (uri == null) {
coroutineScope.launch { snackbarHostState.showSnackbarDismissing("No file selected") }
return@rememberLauncherForActivityResult
}
coroutineScope.launch {
context.contentResolver.openOutputStream(uri)?.use { stream ->
dataTransferRepository.exportPosts(stream)
snackbarHostState.showSnackbarDismissing("Successfully exported posts")
}
}
}
SettingsActionItem(
title = "Export posts to file",
description = "Write all saved posts into a JSON file that can be imported at a later date",
icon = Icons.Filled.Upload,
) {
exportAction.launch("claw-export.json")
}
}
@Composable
private fun SettingsActionItem(
title: String,
modifier: Modifier = Modifier,
description: String? = null,
icon: ImageVector? = null,
onClick: (() -> Unit)? = null,
) {
ListItem(
headlineContent = { Text(title) },
supportingContent = { description?.let { Text(it) } },
leadingContent = {
icon?.let {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.height(32.dp),
)
}
},
modifier = modifier.clickable { onClick?.invoke() },
)
}
/** Shows a Snackbar but dismisses any existing ones first. */
private suspend fun SnackbarHostState.showSnackbarDismissing(
text: String,
) {
currentSnackbarData?.dismiss()
showSnackbar(text)
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -19,17 +19,18 @@ import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.navigation.NavController
import dev.msfjarvis.claw.android.ui.navigation.Destinations
import kotlinx.collections.immutable.ImmutableList
private const val AnimationDuration = 100
const val AnimationDuration = 100
@Composable
fun ClawNavigationBar(
navController: NavController,
items: List<NavigationItem>,
items: ImmutableList<NavigationItem>,
isVisible: Boolean,
modifier: Modifier = Modifier,
) {
@@ -54,10 +55,10 @@ fun ClawNavigationBar(
val isCurrentDestination = navController.currentDestination?.route == navItem.route
NavigationBarItem(
icon = {
Crossfade(isCurrentDestination) {
Crossfade(isCurrentDestination, label = "nav-label") {
Icon(
painter = if (it) navItem.selectedIcon else navItem.icon,
contentDescription = navItem.label.uppercase()
imageVector = if (it) navItem.selectedIcon else navItem.icon,
contentDescription = navItem.label.replaceFirstChar(Char::uppercase),
)
}
},
@@ -66,13 +67,13 @@ fun ClawNavigationBar(
onClick = {
if (isCurrentDestination) {
navItem.listStateResetCallback()
return@NavigationBarItem
}
navController.graph.startDestinationRoute?.let { startDestination ->
navController.popBackStack(startDestination, false)
}
if (navItem.route != Destinations.startDestination.route) {
navController.navigate(navItem.route)
} else {
navController.graph.startDestinationRoute?.let { startDestination ->
navController.popBackStack(startDestination, false)
}
if (navItem.route != Destinations.startDestination.route) {
navController.navigate(navItem.route)
}
}
},
modifier = Modifier.testTag(navItem.label.uppercase()),
@@ -85,7 +86,7 @@ fun ClawNavigationBar(
class NavigationItem(
val label: String,
val route: String,
val icon: Painter,
val selectedIcon: Painter,
val icon: ImageVector,
val selectedIcon: ImageVector,
val listStateResetCallback: () -> Unit,
)
@@ -0,0 +1,84 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.decorations
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.FastOutLinearInEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.Spacer
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.navigation.NavController
import dev.msfjarvis.claw.android.ui.navigation.Destinations
import kotlinx.collections.immutable.ImmutableList
@Composable
fun ClawNavigationRail(
navController: NavController,
items: ImmutableList<NavigationItem>,
isVisible: Boolean,
modifier: Modifier = Modifier,
) {
AnimatedVisibility(
visible = isVisible,
enter =
slideInHorizontally(
// Enters by sliding in from offset -fullWidth to 0.
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(durationMillis = AnimationDuration, easing = LinearOutSlowInEasing),
),
exit =
slideOutHorizontally(
// Exits by sliding out from offset 0 to -fullWidth.
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(durationMillis = AnimationDuration, easing = FastOutLinearInEasing),
),
modifier = Modifier,
) {
NavigationRail(modifier = modifier) {
Spacer(Modifier.weight(1f))
items.forEach { navItem ->
val isCurrentDestination = navController.currentDestination?.route == navItem.route
NavigationRailItem(
icon = {
Crossfade(isCurrentDestination, label = "nav-label") {
Icon(
imageVector = if (it) navItem.selectedIcon else navItem.icon,
contentDescription = navItem.label.replaceFirstChar(Char::uppercase),
)
}
},
label = { Text(text = navItem.label) },
selected = isCurrentDestination,
onClick = {
if (isCurrentDestination) {
navItem.listStateResetCallback()
} else {
navController.graph.startDestinationRoute?.let { startDestination ->
navController.popBackStack(startDestination, false)
}
if (navItem.route != Destinations.startDestination.route) {
navController.navigate(navItem.route)
}
}
},
modifier = Modifier.testTag(navItem.label.uppercase()),
)
}
Spacer(Modifier.weight(1f))
}
}
}
@@ -0,0 +1,25 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.decorations
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.graphics.Color
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@Composable
fun TransparentSystemBars() {
val systemUiController = rememberSystemUiController()
val useDarkIcons = !isSystemInDarkTheme()
DisposableEffect(systemUiController, useDarkIcons) {
systemUiController.setSystemBarsColor(color = Color.Transparent, darkIcons = useDarkIcons)
onDispose {}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -19,8 +19,6 @@ import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LinkMetadata
import dev.msfjarvis.claw.model.LobstersPostDetails
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun Context.getActivity(): ComponentActivity? {
return when (this) {
@@ -30,14 +28,6 @@ fun Context.getActivity(): ComponentActivity? {
}
}
/**
* Parses a given [String] into a [LocalDateTime]. This method is only intended to be used for dates
* in the format returned by the Lobsters API, and is not a general purpose parsing solution.
*/
fun String.toLocalDateTime(): LocalDateTime {
return LocalDateTime.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(this))
}
@Composable
fun rememberPostActions(
urlLauncher: UrlLauncher,
@@ -51,9 +41,10 @@ fun rememberPostActions(
}
override fun viewComments(postId: String) {
navController.navigate(
val currentRoute = navController.currentDestination?.route
val newRoute =
Destinations.Comments.route.replace(Destinations.Comments.placeholder, postId)
)
if (currentRoute != Destinations.Comments.route) navController.navigate(newRoute)
}
override fun viewCommentsPage(commentsUrl: String) {
@@ -1,45 +1,72 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.lists
import androidx.activity.compose.ReportDrawn
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Inbox
import androidx.compose.material3.Divider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.ui.decorations.MonthHeader
import dev.msfjarvis.claw.database.local.SavedPost
import java.time.Month
import kotlinx.collections.immutable.ImmutableMap
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun DatabasePosts(
items: Map<Month, List<SavedPost>>,
items: ImmutableMap<Month, List<SavedPost>>,
listState: LazyListState,
postActions: PostActions,
modifier: Modifier = Modifier,
) {
LazyColumn(
state = listState,
modifier = modifier,
) {
items.forEach { (month, posts) ->
stickyHeader { MonthHeader(month = month) }
items(posts) { item ->
ListItem(
item = item,
isSaved = { true },
postActions = postActions,
ReportDrawn()
Box(modifier = modifier.fillMaxSize()) {
if (items.isEmpty()) {
Column(modifier = Modifier.align(Alignment.Center)) {
Icon(
imageVector = Icons.Filled.Inbox,
contentDescription = "Empty inbox icon",
modifier = Modifier.align(Alignment.CenterHorizontally).size(36.dp),
)
Divider()
Text(text = "No saved posts", style = MaterialTheme.typography.headlineSmall)
}
} else {
LazyColumn(state = listState) {
items.forEach { (month, posts) ->
stickyHeader(contentType = "month-header") { MonthHeader(month = month) }
items(
items = posts,
key = { it.shortId },
contentType = { "LobstersItem" },
) { item ->
ListItem(
item = item,
isSaved = { true },
postActions = postActions,
)
Divider()
}
}
}
}
}
@@ -1,11 +1,12 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.lists
import androidx.activity.compose.ReportDrawnWhen
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -26,7 +27,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.items
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.posts.toDbModel
import dev.msfjarvis.claw.common.ui.NetworkError
@@ -43,6 +45,7 @@ fun NetworkPosts(
postActions: PostActions,
modifier: Modifier = Modifier,
) {
ReportDrawnWhen { lazyPagingItems.itemCount > 0 }
val refreshLoadState = lazyPagingItems.loadState.refresh
val isRefreshing = refreshLoadState == LoadState.Loading
val pullRefreshState = rememberPullRefreshState(isRefreshing, lazyPagingItems::refresh)
@@ -57,7 +60,12 @@ fun NetworkPosts(
LazyColumn(
state = listState,
) {
items(lazyPagingItems) { item ->
items(
count = lazyPagingItems.itemCount,
key = lazyPagingItems.itemKey { it.shortId },
contentType = lazyPagingItems.itemContentType { "LobstersItem" },
) { index ->
val item = lazyPagingItems[index]
if (item != null) {
val dbModel = item.toDbModel()
ListItem(
@@ -70,12 +78,12 @@ fun NetworkPosts(
}
}
if (lazyPagingItems.loadState.append == LoadState.Loading) {
item {
item(key = "progressbar") {
ProgressBar(
modifier =
Modifier.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
.padding(top = 4.dp),
.padding(vertical = 16.dp),
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -31,6 +31,10 @@ sealed class Destinations {
override val route = "user/$placeholder"
}
object DataTransfer : Destinations() {
override val route: String = "datatransfer"
}
companion object {
val startDestination
get() = Hottest
@@ -0,0 +1,24 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.navigation
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
enum class ClawNavigationType {
BOTTOM_NAVIGATION,
NAVIGATION_RAIL;
companion object {
fun fromSize(windowSize: WindowWidthSizeClass): ClawNavigationType {
return when (windowSize) {
WindowWidthSizeClass.Medium,
WindowWidthSizeClass.Expanded -> NAVIGATION_RAIL
else -> BOTTOM_NAVIGATION
}
}
}
}
@@ -0,0 +1,21 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.ui.util
import androidx.compose.runtime.Stable
import dev.msfjarvis.claw.common.comments.HTMLConverter
import io.github.furstenheim.CopyDown
import javax.inject.Inject
@Stable
class HTMLConverterImpl @Inject constructor() : HTMLConverter {
private val copydown = CopyDown()
override fun convertHTMLToMarkdown(html: String): String {
return copydown.convert(html)
}
}
@@ -0,0 +1,36 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.viewmodel
import dev.msfjarvis.claw.api.injection.BaseUrl
import dev.msfjarvis.claw.core.injection.IODispatcher
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import org.jsoup.Jsoup
/** Helper for extracting CSRF token for authenticated requests to https://lobste.rs. */
class CSRFRepository
@Inject
constructor(
private val okHttpClient: OkHttpClient,
@IODispatcher private val dispatcher: CoroutineDispatcher,
@BaseUrl private val url: String,
) {
suspend fun extractToken(): String? {
val request = Request.Builder().url(url).get().build()
return withContext(dispatcher) {
okHttpClient.newCall(request).execute().use { response ->
val doc = Jsoup.parse(response.body?.string() ?: return@use null)
val element = doc.select("meta[name=\"csrf-token\"]").first() ?: return@use null
return@use element.attr("content")
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -13,14 +13,21 @@ import androidx.paging.PagingConfig
import com.deliveryhero.whetstone.viewmodel.ContributesViewModel
import com.slack.eithernet.ApiResult.Failure
import com.slack.eithernet.ApiResult.Success
import dev.msfjarvis.claw.android.injection.IODispatcher
import dev.msfjarvis.claw.android.paging.LobstersPagingSource
import dev.msfjarvis.claw.android.ui.toLocalDateTime
import dev.msfjarvis.claw.android.paging.LobstersPagingSource.Companion.PAGE_SIZE
import dev.msfjarvis.claw.android.paging.LobstersPagingSource.Companion.STARTING_PAGE_INDEX
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.Comment
import java.io.IOException
import java.net.HttpURLConnection
import java.time.LocalDateTime
import java.time.Month
import java.time.format.DateTimeFormatter
import javax.inject.Inject
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
@@ -33,14 +40,20 @@ class ClawViewModel
constructor(
private val api: LobstersApi,
private val savedPostsRepository: SavedPostsRepository,
private val commentsRepository: CommentsRepository,
private val linkMetadataRepository: LinkMetadataRepository,
val dataTransferRepository: DataTransferRepository,
private val pagingSourceFactory: LobstersPagingSource.Factory,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
) : ViewModel() {
private val hottestPostsPager =
Pager(PagingConfig(pageSize = 20)) { pagingSourceFactory.create(api::getHottestPosts) }
Pager(PagingConfig(pageSize = PAGE_SIZE), initialKey = STARTING_PAGE_INDEX) {
pagingSourceFactory.create(api::getHottestPosts)
}
private val newestPostsPager =
Pager(PagingConfig(pageSize = 20)) { pagingSourceFactory.create(api::getHottestPosts) }
Pager(PagingConfig(pageSize = PAGE_SIZE), initialKey = STARTING_PAGE_INDEX) {
pagingSourceFactory.create(api::getNewestPosts)
}
val hottestPosts
get() = hottestPostsPager.flow
@@ -54,9 +67,9 @@ constructor(
val savedPosts
get() = savedPostsFlow.map(::mapSavedPosts)
private fun mapSavedPosts(items: List<SavedPost>): Map<Month, List<SavedPost>> {
private fun mapSavedPosts(items: List<SavedPost>): ImmutableMap<Month, List<SavedPost>> {
val sorted = items.sortedByDescending { post -> post.createdAt.toLocalDateTime() }
return sorted.groupBy { post -> post.createdAt.toLocalDateTime().month }
return sorted.groupBy { post -> post.createdAt.toLocalDateTime().month }.toImmutableMap()
}
suspend fun isPostSaved(post: SavedPost): Boolean {
@@ -80,11 +93,23 @@ constructor(
is Success -> result.value
is Failure.NetworkFailure -> throw result.error
is Failure.UnknownFailure -> throw result.error
is Failure.HttpFailure,
is Failure.HttpFailure -> {
if (result.code == HttpURLConnection.HTTP_NOT_FOUND) {
throw IOException("Story was removed by moderator")
} else {
throw IOException("API returned an invalid response")
}
}
is Failure.ApiFailure -> throw IOException("API returned an invalid response")
}
}
suspend fun getSeenComments(postId: String) = commentsRepository.getSeenComments(postId)
fun markSeenComments(postId: String, comments: List<Comment>) {
viewModelScope.launch { commentsRepository.markSeenComments(postId, comments) }
}
suspend fun getLinkMetadata(url: String) =
withContext(ioDispatcher) { linkMetadataRepository.getLinkMetadata(url) }
@@ -98,4 +123,13 @@ constructor(
is Failure.ApiFailure -> throw IOException("API returned an invalid response")
}
}
/**
* Parses a given [String] into a [LocalDateTime]. This method is only intended to be used for
* dates in the format returned by the Lobsters API, and is not a general purpose parsing
* solution.
*/
private fun String.toLocalDateTime(): LocalDateTime {
return LocalDateTime.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(this))
}
}
@@ -0,0 +1,33 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.viewmodel
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.database.LobstersDatabase
import dev.msfjarvis.claw.database.local.PostComments
import dev.msfjarvis.claw.model.Comment
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
class CommentsRepository
@Inject
constructor(
database: LobstersDatabase,
@DatabaseDispatcher private val dbDispatcher: CoroutineDispatcher,
) {
private val postCommentsQueries = database.postCommentsQueries
suspend fun getSeenComments(postId: String) =
withContext(dbDispatcher) { postCommentsQueries.getCommentIds(postId).executeAsOneOrNull() }
suspend fun markSeenComments(postId: String, comments: List<Comment>) {
withContext(dbDispatcher) {
postCommentsQueries.rememberComments(PostComments(postId, comments.map { it.shortId }))
}
}
}
@@ -0,0 +1,54 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.viewmodel
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.database.LobstersDatabase
import dev.msfjarvis.claw.database.SavedPostSerializer
import dev.msfjarvis.claw.database.local.SavedPost
import java.io.InputStream
import java.io.OutputStream
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.encodeToStream
@OptIn(ExperimentalSerializationApi::class)
class DataTransferRepository
@Inject
constructor(
private val database: LobstersDatabase,
private val json: Json,
@DatabaseDispatcher private val dbDispatcher: CoroutineDispatcher,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
) {
private val serializer = ListSerializer(SavedPostSerializer)
private val savedPostQueries = database.savedPostQueries
suspend fun importPosts(input: InputStream) {
val posts: List<SavedPost> =
withContext(ioDispatcher) {
json.decodeFromStream(
serializer,
input,
)
}
withContext(dbDispatcher) {
database.transaction { posts.forEach(savedPostQueries::insertOrReplacePost) }
}
}
suspend fun exportPosts(output: OutputStream) {
val posts = withContext(dbDispatcher) { savedPostQueries.selectAllPosts().executeAsList() }
withContext(ioDispatcher) { json.encodeToStream(serializer, posts, output) }
}
}
@@ -1,21 +1,49 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.viewmodel
import dev.msfjarvis.claw.metadata.MetadataExtractor
import com.chimbori.crux.Crux
import com.chimbori.crux.api.Fields
import dev.msfjarvis.claw.model.LinkMetadata
import javax.inject.Inject
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import org.jsoup.Jsoup
class LinkMetadataRepository
@Inject
constructor(
private val metadataExtractor: MetadataExtractor,
private val crux: Crux,
private val okHttpClient: OkHttpClient,
) {
suspend fun getLinkMetadata(url: String): LinkMetadata {
return metadataExtractor.getExtractedMetadata(url)
return run {
val parsedUrl = url.toHttpUrlOrNull() ?: return@run null
if (!parsedUrl.isHttps) return@run null
val request = Request.Builder().url(parsedUrl).build()
val htmlContent =
okHttpClient.newCall(request).execute().use { response ->
val body = response.body ?: return@run null
body.string()
}
val extractedMetadata = crux.extractFrom(parsedUrl, Jsoup.parse(htmlContent, url))
val faviconUrl = extractedMetadata[Fields.FAVICON_URL].toString()
val readingTime = extractedMetadata[Fields.DURATION_MS].toString()
LinkMetadata(
url = url,
faviconUrl = faviconUrl,
readingTime = readingTime,
)
}
?: LinkMetadata(
url = url,
faviconUrl = null,
readingTime = null,
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -8,7 +8,7 @@ package dev.msfjarvis.claw.android.viewmodel
import app.cash.sqldelight.coroutines.asFlow
import app.cash.sqldelight.coroutines.mapToList
import dev.msfjarvis.claw.android.injection.DatabaseDispatcher
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.database.LobstersDatabase
import dev.msfjarvis.claw.database.local.SavedPost
import io.github.aakira.napier.Napier
@@ -30,6 +30,15 @@ constructor(
withContext(dbDispatcher) { savedPostQueries.insertOrReplacePost(post) }
}
suspend fun savePosts(posts: List<SavedPost>) {
Napier.d(tag = TAG) { "Saving posts: ${posts.joinToString(",") { it.shortId }}" }
withContext(dbDispatcher) {
savedPostQueries.transaction {
posts.forEach { post -> savedPostQueries.insertOrReplacePost(post) }
}
}
}
suspend fun removePost(post: SavedPost) {
Napier.d(tag = TAG) { "Removing post: ${post.shortId}" }
withContext(dbDispatcher) { savedPostQueries.deletePost(post.shortId) }
@@ -12,15 +12,13 @@ import androidx.work.WorkerParameters
import com.deliveryhero.whetstone.ForScope
import com.deliveryhero.whetstone.worker.ContributesWorker
import com.deliveryhero.whetstone.worker.WorkerScope
import com.slack.eithernet.ApiResult
import com.slack.eithernet.ApiResult.Success
import dev.msfjarvis.claw.android.viewmodel.SavedPostsRepository
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.common.posts.toDbModel
import dev.msfjarvis.claw.model.LobstersPostDetails
import javax.inject.Inject
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.supervisorScope
/**
* WorkManager-backed [CoroutineWorker] that gets all the posts from [SavedPostsRepository], fetches
@@ -38,19 +36,13 @@ constructor(
private val lobstersApi: LobstersApi,
) : CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
val posts = savedPostsRepository.savedPosts.first()
supervisorScope {
posts
.map { post ->
async {
val details = lobstersApi.getPostDetails(post.shortId)
if (details is ApiResult.Success) {
savedPostsRepository.savePost(details.value.toDbModel())
}
}
}
.awaitAll()
}
savedPostsRepository.savedPosts
.first()
.map { post -> lobstersApi.getPostDetails(post.shortId) }
.filterIsInstance<Success<LobstersPostDetails>>()
.map { result -> result.value.toDbModel() }
.toList()
.let { savedPostsRepository.savePosts(it) }
return Result.success()
}
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
<monochrome android:drawable="@mipmap/ic_launcher_foreground" />
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 B

After

Width:  |  Height:  |  Size: 44 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 B

After

Width:  |  Height:  |  Size: 44 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 B

After

Width:  |  Height:  |  Size: 46 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 B

After

Width:  |  Height:  |  Size: 52 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

@@ -0,0 +1,61 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.viewmodel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.runTest
import okhttp3.OkHttpClient
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.mockwebserver.RecordedRequest
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
class CSRFRepositoryTest {
@Test
fun `correctly extracts CSRF token`() = runTest {
val repo =
CSRFRepository(
OkHttpClient.Builder().build(),
Dispatchers.Default,
server.url("/").toString(),
)
assertThat(repo.extractToken())
.isEqualTo(
"OZWykgFemPVeOSNmB53-ccKXe458X7xCInO1-qzFU6nk_9RCSrSQqS9OPmA5_pyy8qD3IYAIZ7XfAM3gdhJpkQ"
)
}
companion object {
private val server = MockWebServer()
@JvmStatic
@BeforeAll
fun setup() {
val dispatcher =
object : Dispatcher() {
override fun dispatch(request: RecordedRequest): MockResponse {
return when (val path = request.path) {
"/" ->
MockResponse()
.setResponseCode(200)
.setBody(
javaClass.classLoader!!
.getResourceAsStream("csrf_page.html")
.readAllBytes()
.decodeToString(),
)
else -> error("Invalid path: $path")
}
}
}
server.dispatcher = dispatcher
}
}
}
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,5 +1,5 @@
#
# This file was automatically generated by 'versioning-plugin'. DO NOT EDIT MANUALLY.
#
versioning-plugin.versionCode=11300
versioning-plugin.versionName=1.13.0
versioning-plugin.versionCode=12900
versioning-plugin.versionName=1.29.0
+9 -9
View File
@@ -1,15 +1,14 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
import dev.msfjarvis.claw.gradle.addTestDependencies
plugins {
kotlin("android")
id("dev.msfjarvis.claw.kotlin-common")
id("dev.msfjarvis.claw.android-library")
id("dev.msfjarvis.claw.kotlin-android")
alias(libs.plugins.anvil)
alias(libs.plugins.whetstone)
}
@@ -19,14 +18,15 @@ android { namespace = "dev.msfjarvis.claw.api" }
anvil { generateDaggerFactories.set(true) }
dependencies {
api(projects.model)
api(libs.retrofit)
api(libs.eithernet)
api(libs.retrofit)
api(projects.model)
implementation(libs.dagger)
implementation(libs.javax.inject)
testImplementation(testFixtures(libs.eithernet))
testImplementation(libs.kotest.assertions.core)
testImplementation(libs.kotest.runner.junit5)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotlinx.serialization.json)
testImplementation(libs.retrofit.kotlinxSerializationConverter)
addTestDependencies(project)
}
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.0.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.0-alpha08)" variant="all" version="8.0.0-alpha08">
<issues format="6" by="lint 8.0.1" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.1)" variant="all" version="8.0.1">
</issues>
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -9,6 +9,7 @@ package dev.msfjarvis.claw.api
import com.slack.eithernet.ApiResult
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.Tags
import dev.msfjarvis.claw.model.User
import retrofit2.http.GET
import retrofit2.http.Path
@@ -29,6 +30,12 @@ interface LobstersApi {
@GET("u/{username}.json")
suspend fun getUser(@Path("username") username: String): ApiResult<User, Unit>
@GET("t/{tags}.json")
suspend fun getPostsByTags(
@Path("tags") tag: Tags,
@Query("page") page: Int,
): ApiResult<List<LobstersPost>, Unit>
companion object {
const val BASE_URL = "https://lobste.rs"
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -13,6 +13,7 @@ import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
import dev.msfjarvis.claw.api.LobstersApi
import javax.inject.Qualifier
import okhttp3.OkHttpClient
import retrofit2.Converter
import retrofit2.Retrofit
@@ -25,10 +26,11 @@ object ApiModule {
fun provideRetrofit(
client: OkHttpClient,
converterFactories: Set<@JvmSuppressWildcards Converter.Factory>,
@BaseUrl baseUrl: String,
): Retrofit {
return Retrofit.Builder()
.client(client)
.baseUrl(LobstersApi.BASE_URL)
.baseUrl(baseUrl)
.addConverterFactory(ApiResultConverterFactory)
.addCallAdapterFactory(ApiResultCallAdapterFactory)
.apply { converterFactories.forEach(this::addConverterFactory) }
@@ -39,4 +41,8 @@ object ApiModule {
fun provideApi(retrofit: Retrofit): LobstersApi {
return retrofit.create()
}
@Provides @BaseUrl fun provideBaseUrl(): String = LobstersApi.BASE_URL
}
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class BaseUrl
@@ -1,50 +1,74 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.api
import com.google.common.truth.Truth.assertThat
import com.slack.eithernet.ApiResult.Success
import com.slack.eithernet.test.newEitherNetController
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.Tags
import dev.msfjarvis.claw.model.User
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeTypeOf
import dev.msfjarvis.claw.util.TestUtils.assertIs
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
class ApiTest : FunSpec() {
class ApiTest {
private val wrapper = ApiWrapper(newEitherNetController())
private val api
get() = wrapper.api
init {
test("api gets correct number of items") {
val posts = api.getHottestPosts(1)
posts.shouldBeTypeOf<Success<List<LobstersPost>>>()
posts.value shouldHaveSize 25
}
@Test
fun `api gets correct number of items`() = runTest {
val posts = api.getHottestPosts(1)
assertIs<Success<List<LobstersPost>>>(posts)
assertThat(posts.value).hasSize(25)
}
test("posts with no urls") {
val posts = api.getHottestPosts(1)
posts.shouldBeTypeOf<Success<List<LobstersPost>>>()
val commentsOnlyPosts = posts.value.asSequence().filter { it.url.isEmpty() }.toSet()
commentsOnlyPosts shouldHaveSize 2
}
@Test
fun `posts with no urls`() = runTest {
val posts = api.getHottestPosts(1)
assertIs<Success<List<LobstersPost>>>(posts)
val commentsOnlyPosts = posts.value.asSequence().filter { it.url.isEmpty() }.toSet()
assertThat(commentsOnlyPosts).hasSize(2)
}
test("post details with comments") {
val postDetails = api.getPostDetails("tdfoqh")
postDetails.shouldBeTypeOf<Success<LobstersPostDetails>>()
postDetails.value.comments shouldHaveSize 7
}
@Test
fun `post details with comments`() = runTest {
val postDetails = api.getPostDetails("tdfoqh")
assertIs<Success<LobstersPostDetails>>(postDetails)
assertThat(postDetails.value.comments).hasSize(7)
}
test("get user details") {
val user = api.getUser("msfjarvis")
user.shouldBeTypeOf<Success<User>>()
user.value.username shouldBe "msfjarvis"
}
@Test
fun `get user details`() = runTest {
val user = api.getUser("msfjarvis")
assertIs<Success<User>>(user)
assertThat(user.value.username).isEqualTo("msfjarvis")
}
@Test
fun `get posts by single tag`() = runTest {
val tags = Tags()
tags.addTag("meta")
val posts = api.getPostsByTags(tags, 1)
assertIs<Success<List<LobstersPost>>>(posts)
assertThat(posts.value).hasSize(25)
assertThat(posts.value[0].tags).contains("meta")
}
@Test
fun `get posts by multiple tags`() = runTest {
val tags = Tags()
tags.addTag("programming")
tags.addTag("rust")
val posts = api.getPostsByTags(tags, 1)
assertIs<Success<List<LobstersPost>>>(posts)
assertThat(posts.value).hasSize(25)
assertThat(posts.value[0].tags).containsAnyOf("programming", "rust")
}
}
@@ -1,27 +1,47 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.api
import com.slack.eithernet.ApiResult.Companion.httpFailure
import com.slack.eithernet.ApiResult.Companion.success
import com.slack.eithernet.test.EitherNetController
import com.slack.eithernet.test.enqueue
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.Tags
import dev.msfjarvis.claw.model.User
import dev.msfjarvis.claw.util.TestUtils.getJson
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNamingStrategy
@OptIn(ExperimentalSerializationApi::class)
class ApiWrapper(controller: EitherNetController<LobstersApi>) {
private val json = Json { ignoreUnknownKeys = true }
private val json = Json {
ignoreUnknownKeys = true
namingStrategy = JsonNamingStrategy.SnakeCase
}
private val hottest: List<LobstersPost> = json.decodeFromString(getJson("hottest.json"))
private val postDetails: LobstersPostDetails =
json.decodeFromString(getJson("post_details_tdfoqh.json"))
private val user: User = json.decodeFromString(getJson("msfjarvis.json"))
private val metaPosts: List<LobstersPost> = json.decodeFromString(getJson("meta.json"))
private val programmingRustPosts: List<LobstersPost> =
json.decodeFromString(getJson("programming_rust.json"))
private val getPostsBody = { args: Array<Any> ->
val tags = args[0] as Tags
if ("meta" in tags) {
success(metaPosts)
} else if ("programming" in tags && "rust" in tags) {
success(programmingRustPosts)
} else {
httpFailure(400)
}
}
val api = controller.api
@@ -30,5 +50,7 @@ class ApiWrapper(controller: EitherNetController<LobstersApi>) {
controller.enqueue(LobstersApi::getHottestPosts) { success(hottest) }
controller.enqueue(LobstersApi::getPostDetails) { success(postDetails) }
controller.enqueue(LobstersApi::getUser) { success(user) }
controller.enqueue(LobstersApi::getPostsByTags, getPostsBody)
controller.enqueue(LobstersApi::getPostsByTags, getPostsBody)
}
}
@@ -1,18 +1,28 @@
/*
* Copyright © 2021 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.util
import com.google.common.truth.Truth.assertThat
import java.io.File
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@OptIn(ExperimentalContracts::class)
object TestUtils {
fun getJson(path: String): String {
// Load the JSON response
val uri = javaClass.classLoader.getResource(path)
val uri = javaClass.classLoader!!.getResource(path)
val file = File(uri.path)
return String(file.readBytes())
}
inline fun <reified T> assertIs(value: Any?): T {
contract { returns() implies (value is T) }
assertThat(value).isInstanceOf(T::class.java)
return value as T
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+22 -5
View File
@@ -1,10 +1,12 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
@file:Suppress("UnstableApiUsage")
import com.android.build.api.dsl.ManagedVirtualDevice
plugins {
alias(libs.plugins.android.test)
@@ -15,7 +17,10 @@ plugins {
android {
namespace = "dev.msfjarvis.claw.benchmark"
defaultConfig { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" }
defaultConfig {
minSdk = 28
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
create("benchmark") {
@@ -25,10 +30,24 @@ android {
}
}
testOptions {
managedDevices {
devices {
create<ManagedVirtualDevice>("api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
}
}
targetProjectPath = ":android"
experimentalProperties["android.experimental.self-instrumenting"] = true
}
androidComponents { beforeVariants(selector().all()) { it.enable = it.buildType == "benchmark" } }
dependencies {
implementation(libs.androidx.benchmark.macro.junit4)
implementation(libs.androidx.profileinstaller)
@@ -39,5 +58,3 @@ dependencies {
implementation(libs.androidx.test.runner)
implementation(libs.androidx.test.uiautomator)
}
androidComponents { beforeVariants(selector().all()) { it.enable = it.buildType == "benchmark" } }
@@ -11,14 +11,12 @@ import androidx.benchmark.macro.CompilationMode
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.StartupTimingMetric
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@LargeTest
class BaselineProfileBenchmark {
@get:Rule val benchmarkRule = MacrobenchmarkRule()
private lateinit var device: UiDevice
@@ -52,7 +50,7 @@ class BaselineProfileBenchmark {
startupMode = StartupMode.COLD,
compilationMode = compilationMode
) {
exploreUI(device)
startActivityAndWait()
}
}
}
@@ -1,22 +1,18 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.benchmark
import androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi
import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ExperimentalStableBaselineProfilesApi
@MediumTest
class BaselineProfileGenerator {
@get:Rule val baselineProfileRule = BaselineProfileRule()
private lateinit var device: UiDevice
@@ -28,11 +24,11 @@ class BaselineProfileGenerator {
}
@Test
fun startup() =
baselineProfileRule.collectStableBaselineProfile(
fun generateBaselineProfile() =
baselineProfileRule.collectBaselineProfile(
packageName = PACKAGE_NAME,
maxIterations = 5,
maxIterations = 8,
) {
exploreUI(device)
startActivityAndWait()
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -9,9 +9,10 @@ package dev.msfjarvis.claw.benchmark
import androidx.benchmark.macro.MacrobenchmarkScope
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
const val PACKAGE_NAME = "dev.msfjarvis.claw.android"
const val PACKAGE_NAME = "dev.msfjarvis.claw.android.benchmark"
private const val AWAIT_TIMEOUT = 10_000L
private const val SAVE_BUTTON_DESC = "Add to saved posts"
private const val NAV_ID_HOTTEST = "HOTTEST"
@@ -19,6 +20,7 @@ private const val NAV_ID_NEWEST = "NEWEST"
private const val NAV_ID_SAVED = "SAVED"
private const val COMMENT_BUTTON_DESC = "Open comments"
@Suppress("Unused")
fun MacrobenchmarkScope.exploreUI(device: UiDevice) {
startActivityAndWait()
device.run {
@@ -38,7 +40,7 @@ private fun UiDevice.waitForSubmitterName() {
private fun UiDevice.savePosts() {
waitForSubmitterName()
findObjects(By.desc(SAVE_BUTTON_DESC)).forEach { btn -> btn.click() }
findObjects(By.desc(SAVE_BUTTON_DESC)).forEach(UiObject2::click)
}
private fun UiDevice.exploreScreens() {
+18 -18
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -7,22 +7,18 @@
import org.gradle.api.JavaVersion
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { `kotlin-dsl` }
afterEvaluate {
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = JavaVersion.VERSION_11.toString()
targetCompatibility = JavaVersion.VERSION_11.toString()
}
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = JavaVersion.VERSION_17.toString()
targetCompatibility = JavaVersion.VERSION_17.toString()
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
freeCompilerArgs = freeCompilerArgs + "-Xsam-conversions=class"
}
}
tasks.withType<KotlinCompile>().configureEach {
compilerOptions { jvmTarget.set(JvmTarget.JVM_17) }
}
gradlePlugin {
@@ -47,18 +43,22 @@ gradlePlugin {
id = "dev.msfjarvis.claw.kotlin-common"
implementationClass = "dev.msfjarvis.claw.gradle.KotlinCommonPlugin"
}
register("kotlin-jvm") {
id = "dev.msfjarvis.claw.kotlin-jvm"
implementationClass = "dev.msfjarvis.claw.gradle.KotlinJvmPlugin"
}
register("kotlin-kapt") {
id = "dev.msfjarvis.claw.kotlin-kapt"
implementationClass = "dev.msfjarvis.claw.gradle.KotlinKaptPlugin"
}
register("kotlin-library") {
id = "dev.msfjarvis.claw.kotlin-library"
implementationClass = "dev.msfjarvis.claw.gradle.KotlinLibraryPlugin"
}
register("rename-artifacts") {
id = "dev.msfjarvis.claw.rename-artifacts"
implementationClass = "dev.msfjarvis.claw.gradle.RenameArtifactsPlugin"
}
register("sentry") {
id = "dev.msfjarvis.claw.sentry"
implementationClass = "dev.msfjarvis.claw.gradle.SentryPlugin"
}
register("spotless") {
id = "dev.msfjarvis.claw.spotless"
implementationClass = "dev.msfjarvis.claw.gradle.SpotlessPlugin"
@@ -77,10 +77,10 @@ gradlePlugin {
dependencies {
implementation(libs.build.agp)
implementation(libs.build.cachefix)
implementation(libs.build.detekt)
implementation(libs.build.kotlin.gradle)
implementation(libs.build.kotlin.serialization)
implementation(libs.build.r8)
implementation(libs.build.semver)
implementation(libs.build.sentry)
implementation(libs.build.spotless)
implementation(libs.build.vcu)
implementation(libs.build.versions)
+14 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -15,7 +15,6 @@ dependencyResolutionManagement {
filter {
includeGroup("androidx.databinding")
includeGroup("com.android")
includeGroup("com.android.tools")
includeGroup("com.android.tools.analytics-library")
includeGroup("com.android.tools.build")
includeGroup("com.android.tools.build.jetifier")
@@ -25,6 +24,15 @@ dependencyResolutionManagement {
includeGroup("com.android.tools.lint")
includeGroup("com.android.tools.utp")
includeGroup("com.google.testing.platform")
includeModule("com.android.tools", "annotations")
includeModule("com.android.tools", "common")
includeModule("com.android.tools", "desugar_jdk_libs")
includeModule("com.android.tools", "desugar_jdk_libs_configuration")
includeModule("com.android.tools", "dvlib")
includeModule("com.android.tools", "play-sdk-proto")
includeModule("com.android.tools", "repository")
includeModule("com.android.tools", "sdklib")
includeModule("com.android.tools", "sdk-common")
}
}
exclusiveContent {
@@ -35,6 +43,10 @@ dependencyResolutionManagement {
includeModule("gradle.plugin.org.gradle.android", "android-cache-fix-gradle-plugin")
}
}
exclusiveContent {
forRepository { maven("https://storage.googleapis.com/r8-releases/raw/main") }
filter { includeModule("com.android.tools", "r8") }
}
mavenCentral()
}
versionCatalogs { create("libs") { from(files("../gradle/libs.versions.toml")) } }
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -10,19 +10,19 @@ package dev.msfjarvis.claw.gradle
import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.LibraryExtension
import com.android.build.api.dsl.Lint
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.gradle.BaseExtension
import dev.msfjarvis.claw.gradle.LintConfig.configureLint
import org.gradle.android.AndroidCacheFixPlugin
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.findByType
private const val SLIM_TESTS_PROPERTY = "slimTests"
import org.gradle.kotlin.dsl.getByType
class AndroidCommonPlugin : Plugin<Project> {
@@ -52,8 +52,8 @@ class AndroidCommonPlugin : Plugin<Project> {
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
testOptions {
@@ -61,43 +61,28 @@ class AndroidCommonPlugin : Plugin<Project> {
unitTests.isReturnDefaultValues = true
}
}
project.extensions.findByType<ApplicationExtension>()?.run { lint.configureLint(project) }
project.extensions.findByType<LibraryExtension>()?.run { lint.configureLint(project) }
project.extensions.findByType<ApplicationExtension>()?.lint?.configureLint(project)
project.extensions.findByType<LibraryExtension>()?.lint?.configureLint(project)
val catalog = project.extensions.getByType<VersionCatalogsExtension>()
val libs = catalog.named("libs")
project.dependencies.addProvider("lintChecks", libs.findLibrary("slack-compose-lints").get())
}
}
private fun Lint.configureLint(project: Project) {
abortOnError = false
checkReleaseBuilds = false
warningsAsErrors = false
disable.add("DialogFragmentCallbacksDetector")
baseline = project.file("lint-baseline.xml")
}
/**
* When the "slimTests" project property is provided, disable the unit test tasks on `release` build
* type and `nonFree` product flavor to avoid running the same tests repeatedly in different build
* variants.
*
* Examples: `./gradlew test -PslimTests` will run unit tests for `nonFreeDebug` and `debug` build
* variants in Android App and Library projects, and all tests in JVM projects.
*/
private fun Project.configureSlimTests() {
if (providers.gradleProperty(SLIM_TESTS_PROPERTY).isPresent) {
// Disable unit test tasks on the release build type for Android Library projects
extensions.findByType<LibraryAndroidComponentsExtension>()?.run {
beforeVariants(selector().withBuildType("release")) {
it.enableUnitTest = false
it.enableAndroidTest = false
}
// Disable unit test tasks on the release build type for Android Library projects
extensions.findByType<LibraryAndroidComponentsExtension>()?.run {
beforeVariants(selector().withBuildType("release")) {
it.enableUnitTest = false
it.enableAndroidTest = false
}
}
// Disable unit test tasks on the release build type for Android Application projects.
extensions.findByType<ApplicationAndroidComponentsExtension>()?.run {
beforeVariants(selector().withBuildType("release")) {
it.enableUnitTest = false
it.enableAndroidTest = false
}
// Disable unit test tasks on the release build type for Android Application projects.
extensions.findByType<ApplicationAndroidComponentsExtension>()?.run {
beforeVariants(selector().withBuildType("release")) {
it.enableUnitTest = false
it.enableAndroidTest = false
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -23,8 +23,6 @@ class ApplicationPlugin : Plugin<Project> {
project.pluginManager.apply(AppPlugin::class)
project.pluginManager.apply(AndroidCommonPlugin::class)
project.extensions.configure<ApplicationExtension> {
installation.installOptions("--user 0")
dependenciesInfo {
includeInBundle = false
includeInApk = false
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -22,17 +22,20 @@ class DependencyUpdatesPlugin : Plugin<Project> {
project.pluginManager.apply(VersionsPlugin::class)
project.pluginManager.apply(VersionCatalogUpdatePlugin::class)
project.tasks.withType<DependencyUpdatesTask>().configureEach {
rejectVersionIf {
when (candidate.group) {
"com.squareup.okhttp3",
"org.jetbrains.kotlin" -> true
else -> false
}
}
rejectVersionIf { isNonStable(candidate.version) && !isNonStable(currentVersion) }
checkConstraints = true
checkBuildEnvironmentConstraints = true
checkForGradleUpdate = true
}
project.extensions.configure<VersionCatalogUpdateExtension> {
keep.keepUnusedLibraries.set(true)
}
}
private fun isNonStable(version: String): Boolean {
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase().contains(it) }
val regex = "^[0-9,.v-]+(-r)?$".toRegex()
val isStable = stableKeyword || regex.matches(version)
return isStable.not()
}
}
@@ -1,35 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.gradle
import io.gitlab.arturbosch.detekt.DetektPlugin
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
object Detekt {
private const val TWITTER_RULES_VERSION = "0.0.26"
fun apply(project: Project) {
project.pluginManager.apply(DetektPlugin::class.java)
project.extensions.configure<DetektExtension> {
debug = project.providers.gradleProperty("debugDetekt").isPresent
parallel = true
ignoredBuildTypes = listOf("benchmark", "release")
basePath = project.layout.projectDirectory.toString()
baseline =
project.rootProject.layout.projectDirectory
.dir("detekt-baselines")
.file("${project.name}.xml")
.asFile
}
project.dependencies.add(
"detektPlugins",
"com.twitter.compose.rules:detekt:$TWITTER_RULES_VERSION",
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -13,25 +13,32 @@ import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
@Suppress("Unused")
class KotlinCommonPlugin : Plugin<Project> {
override fun apply(project: Project) {
Detekt.apply(project)
if (project.rootProject == project) {
LintConfig.configureRootProject(project)
} else if (project.name != "benchmark") {
LintConfig.configureSubProject(project)
}
project.tasks.run {
withType<JavaCompile>().configureEach {
sourceCompatibility = JavaVersion.VERSION_11.toString()
targetCompatibility = JavaVersion.VERSION_11.toString()
sourceCompatibility = JavaVersion.VERSION_17.toString()
targetCompatibility = JavaVersion.VERSION_17.toString()
}
withType<KotlinCompile>().configureEach {
kotlinOptions {
allWarningsAsErrors =
false // project.providers.environmentVariable("GITHUB_WORKFLOW").isPresent
jvmTarget = JavaVersion.VERSION_11.toString()
freeCompilerArgs = freeCompilerArgs + ADDITIONAL_COMPILER_ARGS
languageVersion = "1.7"
withType<KotlinJvmCompile>().configureEach {
compilerOptions {
allWarningsAsErrors.set(
project.providers.environmentVariable("GITHUB_WORKFLOW").isPresent
)
jvmTarget.set(JvmTarget.JVM_17)
freeCompilerArgs.addAll(ADDITIONAL_COMPILER_ARGS)
languageVersion.set(KotlinVersion.KOTLIN_1_7)
}
}
withType<Test>().configureEach {
@@ -0,0 +1,26 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.gradle
import com.android.build.api.dsl.Lint
import com.android.build.gradle.LintPlugin
import dev.msfjarvis.claw.gradle.LintConfig.configureLint
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.findByType
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper
@Suppress("Unused")
class KotlinJvmPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply(KotlinPluginWrapper::class)
project.pluginManager.apply(LintPlugin::class)
project.extensions.findByType<Lint>()?.configureLint(project, isJVM = true)
project.pluginManager.apply(KotlinCommonPlugin::class)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -1,19 +0,0 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
@Suppress("Unused")
class KotlinLibraryPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply(KotlinCommonPlugin::class)
}
}
@@ -0,0 +1,57 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.gradle
import com.android.build.api.dsl.Lint
import org.gradle.api.Project
import org.gradle.api.tasks.Copy
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
object LintConfig {
fun Lint.configureLint(project: Project, isJVM: Boolean = false) {
quiet = project.providers.environmentVariable("CI").isPresent
abortOnError = true
checkReleaseBuilds = true
warningsAsErrors = true
ignoreWarnings = false
checkAllWarnings = true
noLines = false
showAll = true
explainIssues = true
textReport = false
xmlReport = false
htmlReport = true
sarifReport = true
if (!isJVM) {
enable += "ComposeM2Api"
error += "ComposeM2Api"
}
baseline = project.file("lint-baseline.xml")
}
fun configureRootProject(project: Project) {
project.tasks.register<Copy>("collectLintReports") {
into(project.layout.buildDirectory.dir("lint-reports"))
}
}
fun configureSubProject(project: Project) {
val collectorTask = project.rootProject.tasks.named<Copy>("collectLintReports")
val lintTask = project.tasks.named("lint")
val name = project.name
collectorTask.configure {
from(project.layout.buildDirectory.file("reports")) {
include("*.sarif")
rename { it.replace("-results", "-results-$name") }
}
dependsOn(":$name:lint")
}
lintTask.configure { finalizedBy(collectorTask) }
}
}
@@ -11,7 +11,6 @@ import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.variant.VariantOutputConfiguration
import dev.msfjarvis.claw.gradle.artifacts.CollectApksTask
import dev.msfjarvis.claw.gradle.artifacts.CollectBundleTask
import java.util.Locale
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
@@ -24,7 +23,7 @@ class RenameArtifactsPlugin : Plugin<Project> {
project.pluginManager.withPlugin("com.android.application") {
project.extensions.configure<ApplicationAndroidComponentsExtension> {
onVariants { variant ->
val taskPrefix = "collect${variant.name.capitalize(Locale.ROOT)}"
val taskPrefix = "collect${variant.name.replaceFirstChar { it.uppercase() }}"
project.tasks.register<CollectApksTask>("${taskPrefix}Apks") {
variantName.set(variant.name)
apkFolder.set(variant.artifacts.get(SingleArtifact.APK))
@@ -0,0 +1,78 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.gradle
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import io.sentry.android.gradle.extensions.InstrumentationFeature
import io.sentry.android.gradle.extensions.SentryPluginExtension
import java.util.EnumSet
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getByType
@Suppress("Unused")
class SentryPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.withPlugin("com.android.application") {
val catalog = project.extensions.getByType<VersionCatalogsExtension>()
val libs = catalog.named("libs")
project.extensions.configure<ApplicationAndroidComponentsExtension> {
onVariants(selector().all()) { variant ->
val sentryDsn = project.providers.environmentVariable(SENTRY_DSN_PROPERTY)
variant.manifestPlaceholders.put("sentryDsn", sentryDsn.getOrElse(""))
}
onVariants(selector().withBuildType("benchmark")) { variant ->
variant.manifestPlaceholders.put("enableSentry", "false")
}
onVariants(selector().withBuildType("debug")) { variant ->
variant.manifestPlaceholders.put("enableSentry", "false")
}
onVariants(selector().withBuildType("release")) { variant ->
variant.manifestPlaceholders.put("enableSentry", "true")
}
}
project.plugins.apply(io.sentry.android.gradle.SentryPlugin::class)
project.extensions.configure<SentryPluginExtension> {
val enableMappings =
project.providers.gradleProperty(SENTRY_UPLOAD_MAPPINGS_PROPERTY).isPresent
includeProguardMapping.set(enableMappings)
autoUploadProguardMapping.set(enableMappings)
uploadNativeSymbols.set(false)
autoUploadNativeSymbols.set(false)
includeNativeSources.set(false)
ignoredVariants.set(emptySet())
ignoredBuildTypes.set(setOf("benchmark", "debug"))
ignoredFlavors.set(emptySet())
tracingInstrumentation {
enabled.set(true)
debug.set(false)
forceInstrumentDependencies.set(false)
features.set(EnumSet.allOf(InstrumentationFeature::class.java))
}
experimentalGuardsquareSupport.set(false)
autoInstallation {
enabled.set(true)
sentryVersion.set(libs.findVersion("sentry-sdk").get().requiredVersion)
}
includeDependenciesReport.set(true)
}
with(project.dependencies) {
addProvider("implementation", platform(libs.findLibrary("sentry-bom").get()))
}
}
}
private companion object {
private const val SENTRY_DSN_PROPERTY = "SENTRY_DSN"
private const val SENTRY_UPLOAD_MAPPINGS_PROPERTY = "sentryUploadMappings"
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -46,6 +46,6 @@ class SpotlessPlugin : Plugin<Project> {
}
private companion object {
private const val KTFMT_VERSION = "0.41"
private const val KTFMT_VERSION = "0.44"
}
}
@@ -0,0 +1,36 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.gradle
import org.gradle.api.Project
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.DependencyHandlerScope
import org.gradle.kotlin.dsl.exclude
import org.gradle.kotlin.dsl.getByType
/** Extension function to configure JUnit5 dependencies with the Truth assertion library. */
fun DependencyHandlerScope.addTestDependencies(project: Project) {
val catalog = project.extensions.getByType<VersionCatalogsExtension>()
val libs = catalog.named("libs")
addProvider("testImplementation", libs.findLibrary("junit-jupiter-api").get())
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
"testImplementation",
libs.findLibrary("truth").get(),
) {
exclude(group = "junit", module = "junit")
}
addProvider("testRuntimeOnly", libs.findLibrary("junit-jupiter-engine").get())
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
"testRuntimeOnly",
libs.findLibrary("junit-legacy").get(),
) {
// See https://github.com/google/truth/issues/333
because("Truth needs it")
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -21,7 +21,7 @@ import org.gradle.kotlin.dsl.withType
/**
* A Gradle [Plugin] that takes a [Project] with the [AppPlugin] applied and dynamically sets the
* versionCode and versionName properties based on values read from a [VERSIONING_PROP_FILE] file in
* the [Project.getBuildDir] directory. It also adds Gradle tasks to bump the major, minor, and
* the [Project.getProjectDir] directory. It also adds Gradle tasks to bump the major, minor, and
* patch versions along with one to prepare the next snapshot.
*/
@Suppress("Unused")
+7 -3
View File
@@ -1,14 +1,18 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("DSL_SCOPE_VIOLATION")
plugins {
id("dev.msfjarvis.claw.spotless")
id("dev.msfjarvis.claw.versions")
id("dev.msfjarvis.claw.kotlin-common")
alias(libs.plugins.android.test) apply false
alias(libs.plugins.modulegraph)
}
moduleGraphConfig {
readmePath.set(project.layout.projectDirectory.file("README.md").asFile.absolutePath)
heading.set("## Dependency Diagram")
}
+33 -32
View File
@@ -1,47 +1,18 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
@file:Suppress("UnstableApiUsage")
plugins {
id("dev.msfjarvis.claw.kotlin-android")
id("dev.msfjarvis.claw.android-library")
id("dev.msfjarvis.claw.kotlin-android")
alias(libs.plugins.anvil)
alias(libs.plugins.whetstone)
}
anvil { generateDaggerFactories.set(true) }
androidComponents { beforeVariants { it.enableUnitTest = false } }
dependencies {
implementation(platform(libs.androidx.compose.bom))
api(libs.napier)
implementation(projects.core)
implementation(projects.database)
implementation(projects.model)
implementation(libs.accompanist.flowlayout)
implementation(libs.androidx.browser)
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.foundation)
implementation(libs.androidx.compose.material)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.compose.ui.text)
implementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.coil.compose)
implementation(libs.compose.richtext.markdown)
implementation(libs.compose.richtext.material3)
implementation(libs.compose.richtext.ui)
implementation(libs.kotlinx.coroutines.core)
testImplementation(kotlin("test-junit"))
testImplementation(libs.testparameterinjector)
}
android {
buildFeatures {
androidResources = true
@@ -53,3 +24,33 @@ android {
}
namespace = "dev.msfjarvis.claw.common"
}
androidComponents { beforeVariants { it.enableUnitTest = false } }
anvil { generateDaggerFactories.set(true) }
dependencies {
api(projects.core)
api(projects.database)
api(projects.model)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.browser)
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.foundation)
implementation(libs.androidx.compose.material.icons.extended)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.compose.ui.text)
implementation(libs.coil.compose)
implementation(libs.compose.richtext.markdown)
implementation(libs.compose.richtext.material3)
implementation(libs.compose.richtext.ui)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.napier)
compileOnly(libs.androidx.compose.ui.tooling.preview)
runtimeOnly(libs.androidx.compose.ui.tooling)
}
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.0.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.0-alpha08)" variant="all" version="8.0.0-alpha08">
<issues format="6" by="lint 8.0.1" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.1)" variant="all" version="8.0.1">
</issues>
@@ -1,13 +1,15 @@
/*
* Copyright © 2021-2022 Harsh Shandilya.
* Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.common
sealed class NetworkState {
internal sealed class NetworkState {
class Success<T>(val data: T) : NetworkState()
class Error(val error: Throwable, val description: String) : NetworkState()
object Loading : NetworkState()
}

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