Compare commits

...
423 Commits
Author SHA1 Message Date
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
138 changed files with 11191 additions and 13767 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 161 KiB

+36 -20
View File
@@ -5,24 +5,50 @@
"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"
"^androidx.compose.compiler",
"^anvil",
"^coil",
],
"groupName": "kotlin"
"enabled": false
},
{
"matchPackagePatterns": [
"^io.sentry",
"^sentry",
],
"groupName": "sentry"
},
{
"managers": [
"gradle"
],
"packagePatterns": [
// We want to stay in sync with Retrofit
"^com.squareup.okhttp3",
// 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
},
@@ -30,7 +56,7 @@
"regexManagers": [
{
"fileMatch": [
"build-logic/kotlin-plugins/src/main/kotlin/dev/msfjarvis/aps/gradle/SpotlessPlugin.kt"
"SpotlessPlugin\.kt$"
],
"matchStrings": [
"KTFMT_VERSION = \"(?<currentValue>.*)\""
@@ -39,17 +65,6 @@
"depNameTemplate": "com.facebook:ktfmt",
"registryUrlTemplate": "https://repo1.maven.org/maven2/",
},
{
"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",
"registryUrlTemplate": "https://repo1.maven.org/maven2/",
},
{
"fileMatch": [
"gradle/libs.versions.toml"
@@ -63,13 +78,14 @@
},
{
"fileMatch": [
"qodana.yaml"
"gradle/libs.versions.toml"
],
"matchStrings": [
"jetbrains/qodana-jvm-android:(?<currentValue>.*)"
"sentry-sdk = \"(?<currentValue>.*)\""
],
"datasourceTemplate": "docker",
"depNameTemplate": "jetbrains/qodana-jvm-android",
"datasourceTemplate": "maven",
"depNameTemplate": "io.sentry:sentry-android",
"registryUrlTemplate": "https://repo1.maven.org/maven2/",
}
]
}
+31 -53
View File
@@ -6,10 +6,6 @@ on:
- cron: '43 0 * * *'
workflow_dispatch:
env:
AVD_API_LEVEL: 31
AVD_ARCH: x86_64
jobs:
baseline-profile:
runs-on: macos-latest
@@ -19,13 +15,28 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.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@1df8dbefe2a8cbc99770194893dd902763bee34b # v3.9.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
@@ -37,19 +48,10 @@ 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
# Restore AVD from cache
- name: Cache AVD
uses: actions/cache@627f0f41f6904a5b1efbaed9f96d9eb58e92e920 # v3.2.4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: ${{ runner.os }}-avd-${{ env.AVD_API_LEVEL }}-${{ env.AVD_ARCH }}
cache-read-only: true
- name: Decrypt secrets
run: |
@@ -63,39 +65,15 @@ jobs:
- name: Build app and benchmark
run: ./gradlew :benchmark:assembleBenchmark :android:assembleBenchmark
# Now use reactivecircus/android-emulator-runner to spin up an emulator. We're gonna use it again
# to actually run the test once the emulator has booted.
- name: Create AVD snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@50986b1464923454c95e261820bc626f38490ec0 # v2
with:
api-level: ${{ env.AVD_API_LEVEL }}
arch: ${{ env.AVD_ARCH }}
channel: canary
target: aosp_atd
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
disk-size: 8G
script: echo "Generated AVD snapshot for caching."
- name: Clear unused Gradle Managed Devices
run: ./gradlew cleanManagedDevices --unused-only
# Run our baseline profile generator. We need to manually pull the baseline profiles off the
# emulator when using the GA runner
- name: Run benchmark
uses: reactivecircus/android-emulator-runner@50986b1464923454c95e261820bc626f38490ec0 # v2
with:
api-level: ${{ env.AVD_API_LEVEL }}
arch: ${{ env.AVD_ARCH }}
channel: canary
target: aosp_atd
disable-animations: true
disable-spellchecker: true
disk-size: 8G
script: |
# Run our benchmark, enabling only tests using BaselineProfile
./gradlew connectedBenchmarkAndroidTest -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile --stacktrace
# Need to manually pull the generated profiles from the emulator
adb pull /sdcard/Android/media/dev.msfjarvis.claw.benchmark benchmark/build/outputs/baseline-prof/
- 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)
@@ -104,20 +82,20 @@ jobs:
run: |
# Pull down any changes which may have been committed while this workflow has been running
git pull
# Sort the baseline profile, saving it to app/
sort -o android/src/main/baseline-prof.txt benchmark/build/outputs/baseline-prof/BaselineProfileGenerator_startup-baseline-prof.txt
# Sort the baseline profile, output to android/
sort -o android/src/main/baseline-prof.txt benchmark/build/outputs/managed_device_android_test_additional_output/benchmark/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 generated folder and attach it to the CI run
# 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/baseline-prof
path: benchmark/build/outputs/managed_device_android_test_additional_output
- name: Clean secrets
if: always()
+42 -15
View File
@@ -11,32 +11,42 @@ on:
- main
concurrency:
group: ${{ github.workflow }}
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.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@1df8dbefe2a8cbc99770194893dd902763bee34b # v3.9.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' }}
@@ -53,10 +63,25 @@ jobs:
needs: [ "check" ]
steps:
- name: Checkout repository
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.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@1df8dbefe2a8cbc99770194893dd902763bee34b # v3.9.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
@@ -69,7 +94,9 @@ jobs:
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
+43 -6
View File
@@ -1,7 +1,10 @@
name: "CodeQL"
name: CodeQL
on:
workflow_dispatch:
push:
branches:
- main
jobs:
analyze:
@@ -13,14 +16,48 @@ jobs:
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # 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@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
uses: github/codeql-action/init@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6
with:
languages: java
- name: Autobuild
uses: github/codeql-action/autobuild@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
tools: latest
queries: +security-extended
- name: Build project
shell: bash
run: |
./gradlew assemble
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2
uses: github/codeql-action/analyze@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6
with:
category: "/language:java"
-16
View File
@@ -1,16 +0,0 @@
name: Qodana
on:
workflow_dispatch:
jobs:
qodana:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
with:
fetch-depth: 0
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@c25ee7dc4d0697b27ac54877a4ff71cf5b6dde3c # v2022.3.2
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
+24 -6
View File
@@ -7,13 +7,28 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.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@1df8dbefe2a8cbc99770194893dd902763bee34b # v3.9.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
distribution: temurin
java-version: 18
@@ -25,7 +40,7 @@ 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
@@ -45,7 +60,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 }}
@@ -57,8 +72,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
@@ -80,7 +98,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
+1
View File
@@ -245,3 +245,4 @@ hs_err_pid*
keystore.properties
distribution/
screenshots/
+137 -44
View File
@@ -7,157 +7,250 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [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
* 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
* 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
* 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
* 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
* 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
* 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
* 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.19.0...HEAD
[Unreleased]: https://github.com/msfjarvis/compose-lobsters/compare/v1.28.0...HEAD
[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
+27 -1
View File
@@ -8,12 +8,38 @@ Unofficial Android app for read-only access to [lobste.rs](https://lobste.rs), b
height="80" />
</a>
> 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" />
Snapshots from the development branch can be obtained [here](https://github.com/msfjarvis/compose-lobsters/releases/tag/nightly).
## Dependency Diagram
```mermaid
%%{
init: {
'theme': 'neutral'
}
}%%
graph LR
benchmark --> android
android --> api
android --> common
android --> core
android --> coroutine-utils
android --> database
android --> metadata-extractor
android --> model
api --> model
common --> core
common --> database
common --> model
metadata-extractor --> model
database --> core
```
## License
See [LICENSE](LICENSE)
+35 -18
View File
@@ -1,28 +1,24 @@
/*
* 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.whetstone)
}
whetstone {
addOns {
compose.set(true)
workManager.set(true)
}
}
android {
namespace = "dev.msfjarvis.claw.android"
defaultConfig { applicationId = "dev.msfjarvis.claw.android" }
@@ -37,26 +33,30 @@ android {
matchingFallbacks += "release"
isDebuggable = false
proguardFile("benchmark-rules.pro")
applicationIdSuffix = ".benchmark"
}
}
packaging { jniLibs { useLegacyPackaging = true } }
}
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 +64,23 @@ dependencies {
implementation(libs.androidx.work.runtime.ktx)
implementation(libs.coil)
implementation(libs.copydown)
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.coroutineUtils)
implementation(projects.database)
implementation(projects.metadataExtractor)
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
View File
@@ -1,2 +1,22 @@
-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>
+10 -14
View File
@@ -6,13 +6,13 @@
<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="tiramisu">
<profileable
android:shell="true"
@@ -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" />
@@ -163,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>
+9341 -9987
View File
File diff suppressed because it is too large Load Diff
@@ -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.util.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")
}
}
}
@@ -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")
}
}
@@ -6,23 +6,33 @@
*/
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.Favorite
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.NavigateBefore
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.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.rememberCoroutineScope
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
@@ -38,38 +48,37 @@ 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.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()
@@ -82,67 +91,54 @@ 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 = rememberVectorPainter(Icons.Outlined.Whatshot),
selectedIcon = rememberVectorPainter(Icons.Filled.Whatshot),
) {
coroutineScope.launch { hottestListState.animateScrollToItem(index = 0) }
},
NavigationItem(
label = "Newest",
route = Destinations.Newest.route,
icon = ClawIcons.New,
selectedIcon = ClawIcons.NewFilled,
icon = rememberVectorPainter(Icons.Outlined.NewReleases),
selectedIcon = rememberVectorPainter(Icons.Filled.NewReleases),
) {
coroutineScope.launch { newestListState.animateScrollToItem(index = 0) }
},
NavigationItem(
label = "Saved",
route = Destinations.Saved.route,
icon = ClawIcons.HeartBorder,
selectedIcon = ClawIcons.Heart,
icon = rememberVectorPainter(Icons.Outlined.FavoriteBorder),
selectedIcon = rememberVectorPainter(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 }) {
IconButton(
onClick = { if (!navController.popBackStack()) context.getActivity()?.finish() }
) {
Icon(
painter = ClawIcons.ArrowBack,
painter = rememberVectorPainter(Icons.Outlined.NavigateBefore),
contentDescription = "Go back to previous screen",
)
}
@@ -156,82 +152,91 @@ fun LobstersApp(
)
},
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 },
)
}
},
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,
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"))
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,
)
}
}
}
}
@@ -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,13 +23,14 @@ import androidx.compose.ui.graphics.painter.Painter
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()
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()),
@@ -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(
painter = 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 © 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.
@@ -7,6 +7,8 @@
package dev.msfjarvis.claw.android.ui.lists
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
@@ -17,29 +19,34 @@ 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, { it.shortId }) { item ->
ListItem(
item = item,
isSaved = { true },
postActions = postActions,
)
Divider()
Box(modifier = modifier.fillMaxSize()) {
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,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.
@@ -26,7 +26,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
@@ -57,7 +58,12 @@ fun NetworkPosts(
LazyColumn(
state = listState,
) {
items(items = lazyPagingItems, key = { it.shortId }) { 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(
@@ -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,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.android.injection.IODispatcher
import dev.msfjarvis.claw.api.injection.BaseUrl
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")
}
}
}
}
@@ -25,6 +25,8 @@ import java.io.IOException
import java.net.HttpURLConnection
import java.time.Month
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
@@ -62,9 +64,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 {
@@ -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,63 @@
/*
* 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.ExperimentalCoroutinesApi
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
@OptIn(ExperimentalCoroutinesApi::class)
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=11900
versioning-plugin.versionName=1.19.0
versioning-plugin.versionCode=12800
versioning-plugin.versionName=1.28.0
+9 -8
View File
@@ -1,14 +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 {
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)
}
@@ -18,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,76 @@
/*
* 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.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
class ApiTest : FunSpec() {
@OptIn(ExperimentalCoroutinesApi::class)
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,16 +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.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.ExperimentalSerializationApi
@@ -28,6 +30,19 @@ class ApiWrapper(controller: EitherNetController<LobstersApi>) {
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
@@ -36,5 +51,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-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.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" } }
@@ -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.
@@ -26,10 +26,11 @@ class BaselineProfileGenerator {
}
@Test
fun startup() =
fun generateBaselineProfile() =
baselineProfileRule.collectStableBaselineProfile(
packageName = PACKAGE_NAME,
maxIterations = 15,
stableIterations = 2,
maxIterations = 8,
) {
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"
@@ -39,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() {
+14 -13
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 {
@@ -59,6 +55,10 @@ gradlePlugin {
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,9 +77,10 @@ gradlePlugin {
dependencies {
implementation(libs.build.agp)
implementation(libs.build.cachefix)
implementation(libs.build.detekt)
implementation(libs.build.kotlin.gradle)
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,20 @@ 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.HasUnitTestBuilder
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 +53,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 +62,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 as HasUnitTestBuilder).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 as HasUnitTestBuilder).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.
@@ -22,13 +22,7 @@ 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 -> isNonStable(candidate.version) && !isNonStable(currentVersion)
}
}
rejectVersionIf { isNonStable(candidate.version) && !isNonStable(currentVersion) }
checkConstraints = true
checkBuildEnvironmentConstraints = true
checkForGradleUpdate = true
@@ -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 {
@@ -1,20 +1,26 @@
/*
* 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.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)
}
}
@@ -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) }
}
}
@@ -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")
}
+35 -31
View File
@@ -1,46 +1,20 @@
/*
* 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 com.android.build.api.variant.HasUnitTestBuilder
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.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
@@ -52,3 +26,33 @@ android {
}
namespace = "dev.msfjarvis.claw.common"
}
androidComponents { beforeVariants { (it as HasUnitTestBuilder).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,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,6 +8,8 @@ package dev.msfjarvis.claw.common
internal sealed class NetworkState {
class Success<T>(val data: T) : NetworkState()
class Error(val error: Throwable, val description: String) : NetworkState()
object Loading : NetworkState()
}
@@ -8,7 +8,6 @@ package dev.msfjarvis.claw.common.comments
import android.text.format.DateUtils
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -21,6 +20,8 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Public
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -29,6 +30,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
@@ -41,13 +43,13 @@ import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.posts.PostTitle
import dev.msfjarvis.claw.common.posts.Submitter
import dev.msfjarvis.claw.common.posts.TagRow
import dev.msfjarvis.claw.common.res.ClawIcons
import dev.msfjarvis.claw.common.ui.NetworkImage
import dev.msfjarvis.claw.common.ui.ThemedRichText
import dev.msfjarvis.claw.model.LinkMetadata
import dev.msfjarvis.claw.model.LobstersPostDetails
import java.time.Instant
import java.time.temporal.TemporalAccessor
import kotlinx.collections.immutable.toImmutableList
@Composable
internal fun CommentsHeader(
@@ -71,7 +73,7 @@ internal fun CommentsHeader(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
PostTitle(title = postDetails.title)
TagRow(tags = postDetails.tags)
TagRow(tags = postDetails.tags.toImmutableList())
Spacer(Modifier.height(4.dp))
if (linkMetadata.url.isNotBlank()) {
@@ -114,7 +116,7 @@ private fun PostLink(
Row(modifier = Modifier.padding(16.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
NetworkImage(
url = linkMetadata.faviconUrl,
placeholder = ClawIcons.Web,
placeholder = rememberVectorPainter(Icons.Filled.Public),
contentDescription = "",
modifier = Modifier.size(24.dp),
)
@@ -131,7 +133,6 @@ private fun PostLink(
private val CommentEntryPadding = 16f.dp
@OptIn(ExperimentalAnimationApi::class)
@Composable
internal fun CommentEntry(
commentNode: CommentNode,
@@ -169,7 +170,10 @@ internal fun CommentEntry(
modifier =
Modifier.clickable { uriHandler.openUri("https://lobste.rs/u/${comment.user.username}") },
)
AnimatedContent(targetState = commentNode.isExpanded) { expandedState ->
AnimatedContent(
label = "comment_body",
targetState = commentNode.isExpanded,
) { expandedState ->
if (expandedState) {
ThemedRichText(
text = htmlConverter.convertHTMLToMarkdown(comment.comment),
@@ -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.
@@ -14,6 +14,8 @@ import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.absoluteOffset
@@ -24,6 +26,11 @@ import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.outlined.Comment
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Divider
@@ -39,14 +46,20 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.google.accompanist.flowlayout.FlowRow
import dev.msfjarvis.claw.common.res.ClawIcons
import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.ui.NetworkImage
import dev.msfjarvis.claw.common.ui.preview.ThemePreviews
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LinkMetadata
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.User
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable
@OptIn(ExperimentalFoundationApi::class)
@@ -104,7 +117,7 @@ fun LobstersCard(
fun PostDetails(post: SavedPost, modifier: Modifier = Modifier) {
Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp)) {
PostTitle(title = post.title)
TagRow(tags = post.tags)
TagRow(tags = post.tags.toImmutableList())
Spacer(Modifier.height(4.dp))
Submitter(
text = AnnotatedString("Submitted by ${post.submitterName}"),
@@ -141,7 +154,7 @@ internal fun Submitter(
) {
NetworkImage(
url = avatarUrl,
placeholder = ClawIcons.Account,
placeholder = rememberVectorPainter(Icons.Filled.AccountCircle),
contentDescription = contentDescription,
modifier = Modifier.requiredSize(24.dp).clip(CircleShape),
)
@@ -155,13 +168,16 @@ private fun SaveButton(
isSaved: Boolean,
modifier: Modifier = Modifier,
) {
Crossfade(targetState = isSaved) { saved ->
Crossfade(targetState = isSaved, label = "save-button") { saved ->
Box(modifier = modifier.padding(12.dp)) {
Icon(
painter = if (saved) ClawIcons.Heart else ClawIcons.HeartBorder,
painter =
rememberVectorPainter(
if (saved) Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder
),
tint = MaterialTheme.colorScheme.secondary,
contentDescription = if (saved) "Remove from saved posts" else "Add to saved posts",
modifier = Modifier.align(Alignment.Center)
modifier = Modifier.align(Alignment.Center),
)
}
}
@@ -191,7 +207,7 @@ private fun CommentsButton(
},
) {
Icon(
painter = ClawIcons.Comment,
painter = rememberVectorPainter(Icons.Outlined.Comment),
tint = MaterialTheme.colorScheme.secondary,
contentDescription = "Open comments",
modifier = Modifier.align(Alignment.Center),
@@ -200,16 +216,18 @@ private fun CommentsButton(
}
@Composable
@OptIn(ExperimentalLayoutApi::class)
internal fun TagRow(
tags: List<String>,
tags: ImmutableList<String>,
modifier: Modifier = Modifier,
) {
FlowRow(
modifier = modifier,
mainAxisSpacing = 8.dp,
crossAxisSpacing = 8.dp,
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
tags.forEach { tag -> TagText(tag) }
tags.forEach { tag ->
TagText(tag = tag, modifier = Modifier.padding(top = 4.dp, bottom = 4.dp))
}
}
}
@@ -228,3 +246,55 @@ private fun TagText(
style = MaterialTheme.typography.labelLarge,
)
}
@ThemePreviews
@Composable
fun LobstersCardPreview() {
LobstersTheme {
LobstersCard(
post =
SavedPost(
shortId = "ooga",
title = "Simple Anomaly Detection Using Plain SQL",
url = "https://hakibenita.com/sql-anomaly-detection",
createdAt = "2020-09-21T08:04:24.000-05:00",
commentCount = 1,
commentsUrl = "https://lobste.rs/s/q1hh1g/simple_anomaly_detection_using_plain_sql",
submitterName = "Haki",
submitterAvatarUrl = "/avatars/Haki-100.png",
tags = listOf("databases", "apis"),
description = "",
),
isSaved = true,
postActions =
object : PostActions {
override fun viewPost(postUrl: String, commentsUrl: String) {}
override fun viewComments(postId: String) {}
override fun viewCommentsPage(commentsUrl: String) {}
override fun toggleSave(post: SavedPost) {}
override suspend fun getComments(postId: String): LobstersPostDetails {
return LobstersPostDetails(
shortId = "ooga",
title = "Simple Anomaly Detection Using Plain SQL",
url = "https://hakibenita.com/sql-anomaly-detection",
createdAt = "2020-09-21T08:04:24.000-05:00",
commentCount = 1,
commentsUrl = "https://lobste.rs/s/q1hh1g/simple_anomaly_detection_using_plain_sql",
tags = listOf("databases", "apis"),
description = "",
submitter = User("Haki", "", "", "", ""),
comments = emptyList(),
)
}
override suspend fun getLinkMetadata(url: String): LinkMetadata {
return LinkMetadata("", "", "")
}
},
)
}
}
@@ -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.
@@ -14,9 +14,14 @@ import dev.msfjarvis.claw.model.LobstersPostDetails
@Stable
interface PostActions {
fun viewPost(postUrl: String, commentsUrl: String)
fun viewComments(postId: String)
fun viewCommentsPage(commentsUrl: String)
fun toggleSave(post: SavedPost)
suspend fun getComments(postId: String): LobstersPostDetails
suspend fun getLinkMetadata(url: String): LinkMetadata
}
@@ -1,41 +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.common.res
import dev.msfjarvis.claw.common.res.clawicons.account_circle_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.arrow_back_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.comment_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.favorite_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.favorite_border_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.new_releases_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.new_releases_filled_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.public_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.whatshot_black_24dp
import dev.msfjarvis.claw.common.res.clawicons.whatshot_filled_black_24dp
object ClawIcons {
val Account = account_circle_black_24dp()
val ArrowBack = arrow_back_black_24dp()
val Comment = comment_black_24dp()
val Flame = whatshot_black_24dp()
val FlameFilled = whatshot_filled_black_24dp()
val Heart = favorite_black_24dp()
val HeartBorder = favorite_border_black_24dp()
val New = new_releases_black_24dp()
val NewFilled = new_releases_filled_black_24dp()
val Web = public_black_24dp()
}
@@ -1,219 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class account_circle_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1_0
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(12.0f, 2.0f)
cubicTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
cubicTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
cubicTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
cubicTo(22.0f, 6.4799995f, 17.52f, 2.0f, 12.0f, 2.0f)
close()
moveTo(12.0f, 6.0f)
cubicTo(13.93f, 6.0f, 15.5f, 7.57f, 15.5f, 9.5f)
cubicTo(15.5f, 11.43f, 13.93f, 13.0f, 12.0f, 13.0f)
cubicTo(10.07f, 13.0f, 8.5f, 11.43f, 8.5f, 9.5f)
cubicTo(8.5f, 7.5699997f, 10.07f, 6.0f, 12.0f, 6.0f)
close()
moveTo(12.0f, 20.0f)
cubicTo(9.97f, 20.0f, 7.57f, 19.18f, 5.86f, 17.119999f)
cubicTo(7.55f, 15.8f, 9.68f, 15.0f, 12.0f, 15.0f)
cubicTo(14.32f, 15.0f, 16.45f, 15.8f, 18.14f, 17.119999f)
cubicTo(16.43f, 19.18f, 14.03f, 20.0f, 12.0f, 20.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 2.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 2.0
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 20.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 20.0
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,198 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class arrow_back_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(20.0f, 11.0f)
lineTo(7.83f, 11.0f)
lineTo(13.42f, 5.41f)
lineTo(12.0f, 4.0f)
lineTo(4.0f, 12.0f)
lineTo(12.0f, 20.0f)
lineTo(13.41f, 18.59f)
lineTo(7.83f, 13.0f)
lineTo(20.0f, 13.0f)
lineTo(20.0f, 11.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 4.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 4.0
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 16.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 16.0
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,219 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class comment_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(21.99f, 4.0f)
cubicTo(21.99f, 2.9f, 21.1f, 2.0f, 20.0f, 2.0f)
lineTo(4.0f, 2.0f)
cubicTo(2.9f, 2.0f, 2.0f, 2.9f, 2.0f, 4.0f)
lineTo(2.0f, 16.0f)
cubicTo(2.0f, 17.1f, 2.9f, 18.0f, 4.0f, 18.0f)
lineTo(18.0f, 18.0f)
lineTo(22.0f, 22.0f)
lineTo(21.99f, 4.0f)
close()
moveTo(20.0f, 4.0f)
lineTo(20.0f, 17.17f)
lineTo(18.83f, 16.0f)
lineTo(4.0f, 16.0f)
lineTo(4.0f, 4.0f)
lineTo(20.0f, 4.0f)
close()
moveTo(6.0f, 12.0f)
lineTo(18.0f, 12.0f)
lineTo(18.0f, 14.0f)
lineTo(6.0f, 14.0f)
close()
moveTo(6.0f, 9.0f)
lineTo(18.0f, 9.0f)
lineTo(18.0f, 11.0f)
lineTo(6.0f, 11.0f)
close()
moveTo(6.0f, 6.0f)
lineTo(18.0f, 6.0f)
lineTo(18.0f, 8.0f)
lineTo(6.0f, 8.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 2.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 2.0
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 20.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 20.0
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,197 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class favorite_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(12.0f, 21.35f)
lineTo(10.55f, 20.03f)
cubicTo(5.4f, 15.36f, 2.0f, 12.28f, 2.0f, 8.5f)
cubicTo(2.0f, 5.42f, 4.42f, 3.0f, 7.5f, 3.0f)
cubicTo(9.24f, 3.0f, 10.91f, 3.81f, 12.0f, 5.09f)
cubicTo(13.09f, 3.81f, 14.76f, 3.0f, 16.5f, 3.0f)
cubicTo(19.58f, 3.0f, 22.0f, 5.42f, 22.0f, 8.5f)
cubicTo(22.0f, 12.28f, 18.6f, 15.360001f, 13.45f, 20.04f)
lineTo(12.0f, 21.35f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 2.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 3.0
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 20.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 18.350000381469727
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,208 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class favorite_border_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(16.5f, 3.0f)
cubicTo(14.76f, 3.0f, 13.09f, 3.81f, 12.0f, 5.09f)
cubicTo(10.91f, 3.81f, 9.24f, 3.0f, 7.5f, 3.0f)
cubicTo(4.42f, 3.0f, 2.0f, 5.42f, 2.0f, 8.5f)
cubicTo(2.0f, 12.28f, 5.4f, 15.360001f, 10.55f, 20.04f)
lineTo(12.0f, 21.35f)
lineTo(13.45f, 20.03f)
cubicTo(18.6f, 15.36f, 22.0f, 12.28f, 22.0f, 8.5f)
cubicTo(22.0f, 5.42f, 19.58f, 3.0f, 16.5f, 3.0f)
close()
moveTo(12.1f, 18.55f)
lineTo(12.0f, 18.65f)
lineTo(11.9f, 18.55f)
cubicTo(7.14f, 14.24f, 4.0f, 11.39f, 4.0f, 8.5f)
cubicTo(4.0f, 6.5f, 5.5f, 5.0f, 7.5f, 5.0f)
cubicTo(9.04f, 5.0f, 10.54f, 5.99f, 11.07f, 7.3599997f)
lineTo(12.94f, 7.3599997f)
cubicTo(13.46f, 5.99f, 14.96f, 5.0f, 16.5f, 5.0f)
cubicTo(18.5f, 5.0f, 20.0f, 6.5f, 20.0f, 8.5f)
cubicTo(20.0f, 11.39f, 16.86f, 14.24f, 12.1f, 18.55f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 2.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 3.0
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 20.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 18.350000381469727
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,241 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class new_releases_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(23.0f, 12.0f)
lineTo(20.56f, 9.22f)
lineTo(20.9f, 5.54f)
lineTo(17.289999f, 4.72f)
lineTo(15.399999f, 1.5399997f)
lineTo(12.0f, 3.0f)
lineTo(8.6f, 1.54f)
lineTo(6.71f, 4.72f)
lineTo(3.1000001f, 5.5299997f)
lineTo(3.44f, 9.21f)
lineTo(1.0f, 12.0f)
lineTo(3.44f, 14.78f)
lineTo(3.1000001f, 18.47f)
lineTo(6.71f, 19.289999f)
lineTo(8.6f, 22.47f)
lineTo(12.0f, 21.0f)
lineTo(15.4f, 22.46f)
lineTo(17.289999f, 19.279999f)
lineTo(20.9f, 18.46f)
lineTo(20.56f, 14.779999f)
lineTo(23.0f, 12.0f)
close()
moveTo(18.49f, 14.11f)
lineTo(18.75f, 16.9f)
lineTo(16.01f, 17.52f)
lineTo(14.58f, 19.93f)
lineTo(12.0f, 18.82f)
lineTo(9.42f, 19.93f)
lineTo(7.9900002f, 17.52f)
lineTo(5.25f, 16.9f)
lineTo(5.51f, 14.099999f)
lineTo(3.66f, 12.0f)
lineTo(5.51f, 9.88f)
lineTo(5.25f, 7.1000004f)
lineTo(7.99f, 6.4900002f)
lineTo(9.42f, 4.08f)
lineTo(12.0f, 5.18f)
lineTo(14.58f, 4.0699997f)
lineTo(16.01f, 6.4799995f)
lineTo(18.75f, 7.0999994f)
lineTo(18.49f, 9.889999f)
lineTo(20.34f, 12.0f)
lineTo(18.49f, 14.11f)
close()
moveTo(11.0f, 15.0f)
lineTo(13.0f, 15.0f)
lineTo(13.0f, 17.0f)
lineTo(11.0f, 17.0f)
close()
moveTo(11.0f, 7.0f)
lineTo(13.0f, 7.0f)
lineTo(13.0f, 13.0f)
lineTo(11.0f, 13.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 1.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 1.5399997234344482
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 22.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 20.93000030517578
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,221 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class new_releases_filled_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(23.0f, 12.0f)
lineTo(20.56f, 9.22f)
lineTo(20.9f, 5.54f)
lineTo(17.289999f, 4.72f)
lineTo(15.399999f, 1.5399997f)
lineTo(12.0f, 3.0f)
lineTo(8.6f, 1.54f)
lineTo(6.71f, 4.72f)
lineTo(3.1000001f, 5.5299997f)
lineTo(3.44f, 9.21f)
lineTo(1.0f, 12.0f)
lineTo(3.44f, 14.78f)
lineTo(3.1000001f, 18.47f)
lineTo(6.71f, 19.289999f)
lineTo(8.6f, 22.47f)
lineTo(12.0f, 21.0f)
lineTo(15.4f, 22.46f)
lineTo(17.289999f, 19.279999f)
lineTo(20.9f, 18.46f)
lineTo(20.56f, 14.779999f)
lineTo(23.0f, 12.0f)
close()
moveTo(13.0f, 17.0f)
lineTo(11.0f, 17.0f)
lineTo(11.0f, 15.0f)
lineTo(13.0f, 15.0f)
lineTo(13.0f, 17.0f)
close()
moveTo(13.0f, 13.0f)
lineTo(11.0f, 13.0f)
lineTo(11.0f, 7.0f)
lineTo(13.0f, 7.0f)
lineTo(13.0f, 13.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 1.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 1.5399997234344482
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 22.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 20.93000030517578
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,217 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class public_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(12.0f, 2.0f)
cubicTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
cubicTo(2.0f, 17.52f, 6.48f, 22.0f, 12.0f, 22.0f)
cubicTo(17.52f, 22.0f, 22.0f, 17.52f, 22.0f, 12.0f)
cubicTo(22.0f, 6.4799995f, 17.52f, 2.0f, 12.0f, 2.0f)
close()
moveTo(4.0f, 12.0f)
cubicTo(4.0f, 11.39f, 4.08f, 10.79f, 4.21f, 10.22f)
lineTo(8.99f, 15.0f)
lineTo(8.99f, 16.0f)
cubicTo(8.99f, 17.1f, 9.889999f, 18.0f, 10.99f, 18.0f)
lineTo(10.99f, 19.93f)
cubicTo(7.06f, 19.43f, 4.0f, 16.07f, 4.0f, 12.0f)
close()
moveTo(17.89f, 17.4f)
cubicTo(17.63f, 16.59f, 16.89f, 16.0f, 15.99f, 16.0f)
lineTo(14.99f, 16.0f)
lineTo(14.99f, 13.0f)
cubicTo(14.99f, 12.45f, 14.54f, 12.0f, 13.99f, 12.0f)
lineTo(7.99f, 12.0f)
lineTo(7.99f, 10.0f)
lineTo(9.99f, 10.0f)
cubicTo(10.54f, 10.0f, 10.99f, 9.55f, 10.99f, 9.0f)
lineTo(10.99f, 7.0f)
lineTo(12.99f, 7.0f)
cubicTo(14.09f, 7.0f, 14.99f, 6.1f, 14.99f, 5.0f)
lineTo(14.99f, 4.59f)
cubicTo(17.92f, 5.77f, 20.0f, 8.65f, 20.0f, 12.0f)
cubicTo(20.0f, 14.08f, 19.19f, 15.98f, 17.89f, 17.4f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 2.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 2.0
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 20.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 20.0
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,212 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class whatshot_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(11.57f, 13.16f)
cubicTo(10.21f, 13.44f, 9.4f, 14.32f, 9.4f, 15.57f)
cubicTo(9.4f, 16.91f, 10.509999f, 17.99f, 11.889999f, 17.99f)
cubicTo(13.94f, 17.99f, 15.599999f, 16.33f, 15.599999f, 14.28f)
cubicTo(15.599999f, 13.21f, 15.45f, 12.16f, 15.139999f, 11.16f)
cubicTo(14.349999f, 12.23f, 12.94f, 12.88f, 11.57f, 13.16f)
close()
moveTo(13.5f, 0.67f)
cubicTo(13.5f, 0.67f, 14.24f, 3.3200002f, 14.24f, 5.4700003f)
cubicTo(14.24f, 7.53f, 12.889999f, 9.200001f, 10.83f, 9.200001f)
cubicTo(8.76f, 9.200001f, 7.2f, 7.5300007f, 7.2f, 5.4700007f)
lineTo(7.23f, 5.1100006f)
cubicTo(5.21f, 7.51f, 4.0f, 10.62f, 4.0f, 14.0f)
cubicTo(4.0f, 18.42f, 7.58f, 22.0f, 12.0f, 22.0f)
cubicTo(16.42f, 22.0f, 20.0f, 18.42f, 20.0f, 14.0f)
cubicTo(20.0f, 8.61f, 17.41f, 3.8f, 13.5f, 0.67f)
close()
moveTo(12.0f, 20.0f)
cubicTo(8.690001f, 20.0f, 6.0f, 17.31f, 6.0f, 14.0f)
cubicTo(6.0f, 12.47f, 6.3f, 10.96f, 6.86f, 9.57f)
cubicTo(7.87f, 10.58f, 9.27f, 11.2f, 10.83f, 11.2f)
cubicTo(13.49f, 11.2f, 15.58f, 9.37f, 16.11f, 6.77f)
cubicTo(17.34f, 8.97f, 18.0f, 11.44f, 18.0f, 14.0f)
cubicTo(18.0f, 17.31f, 15.309999f, 20.0f, 12.0f, 20.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 4.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 0.6700000166893005
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 16.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 21.329999923706055
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -1,204 +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.
*/
@file:Suppress(
"ClassNaming",
"FunctionNaming",
"FunctionOnlyReturningConstant",
"LongMethod",
"MagicNumber",
"WildcardImport",
)
package dev.msfjarvis.claw.common.res.clawicons
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.painter.Painter
import java.util.*
import kotlin.math.min
/**
* This class has been automatically generated using <a
* href="https://github.com/kirill-grouchnikov/aurora">Aurora SVG transcoder</a>.
*/
class whatshot_filled_black_24dp : Painter() {
@Suppress("UNUSED_VARIABLE") private var shape: Outline? = null
@Suppress("UNUSED_VARIABLE") private var generalPath: Path? = null
@Suppress("UNUSED_VARIABLE") private var brush: Brush? = null
@Suppress("UNUSED_VARIABLE") private var stroke: Stroke? = null
@Suppress("UNUSED_VARIABLE") private var clip: Shape? = null
private var alpha = 1.0f
private var blendMode = DrawScope.DefaultBlendMode
private var alphaStack = mutableListOf(1.0f)
private var blendModeStack = mutableListOf(DrawScope.DefaultBlendMode)
private fun _paint0(drawScope: DrawScope) {
@Suppress("UNUSED_VARIABLE") var shapeText: Outline?
@Suppress("UNUSED_VARIABLE") var generalPathText: Path? = null
@Suppress("UNUSED_VARIABLE") var alphaText = 0.0f
@Suppress("UNUSED_VARIABLE") var blendModeText = DrawScope.DefaultBlendMode
with(drawScope) {
//
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_0
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alphaStack.add(0, alpha)
alpha *= 1.0f
blendModeStack.add(0, BlendMode.SrcOver)
blendMode = BlendMode.SrcOver
// _0_1
if (generalPath == null) {
generalPath = Path()
} else {
generalPath!!.reset()
}
generalPath?.run {
moveTo(13.5f, 0.67f)
cubicTo(13.5f, 0.67f, 14.24f, 3.3200002f, 14.24f, 5.4700003f)
cubicTo(14.24f, 7.53f, 12.889999f, 9.200001f, 10.83f, 9.200001f)
cubicTo(8.76f, 9.200001f, 7.2f, 7.5300007f, 7.2f, 5.4700007f)
lineTo(7.23f, 5.1100006f)
cubicTo(5.21f, 7.51f, 4.0f, 10.62f, 4.0f, 14.0f)
cubicTo(4.0f, 18.42f, 7.58f, 22.0f, 12.0f, 22.0f)
cubicTo(16.42f, 22.0f, 20.0f, 18.42f, 20.0f, 14.0f)
cubicTo(20.0f, 8.61f, 17.41f, 3.8f, 13.5f, 0.67f)
close()
moveTo(11.71f, 19.0f)
cubicTo(9.93f, 19.0f, 8.49f, 17.6f, 8.49f, 15.86f)
cubicTo(8.49f, 14.24f, 9.54f, 13.099999f, 11.299999f, 12.74f)
cubicTo(13.07f, 12.38f, 14.9f, 11.53f, 15.919999f, 10.16f)
cubicTo(16.31f, 11.45f, 16.509998f, 12.809999f, 16.509998f, 14.2f)
cubicTo(16.509998f, 16.85f, 14.359999f, 19.0f, 11.709998f, 19.0f)
close()
}
shape = Outline.Generic(generalPath!!)
brush = SolidColor(Color(0, 0, 0, 255))
drawOutline(
outline = shape!!,
style = Fill,
brush = brush!!,
alpha = alpha,
blendMode = blendMode
)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
alpha = alphaStack.removeAt(0)
blendMode = blendModeStack.removeAt(0)
}
}
private fun innerPaint(drawScope: DrawScope) {
_paint0(drawScope)
shape = null
generalPath = null
brush = null
stroke = null
clip = null
alpha = 1.0f
}
companion object {
/**
* Returns the X of the bounding box of the original SVG image.
*
* @return The X of the bounding box of the original SVG image.
*/
fun getOrigX(): Double {
return 4.0
}
/**
* Returns the Y of the bounding box of the original SVG image.
*
* @return The Y of the bounding box of the original SVG image.
*/
fun getOrigY(): Double {
return 0.6700000166893005
}
/**
* Returns the width of the bounding box of the original SVG image.
*
* @return The width of the bounding box of the original SVG image.
*/
fun getOrigWidth(): Double {
return 16.0
}
/**
* Returns the height of the bounding box of the original SVG image.
*
* @return The height of the bounding box of the original SVG image.
*/
fun getOrigHeight(): Double {
return 21.329999923706055
}
}
override val intrinsicSize: Size
get() = Size.Unspecified
override fun DrawScope.onDraw() {
clipRect {
// Use the original icon bounding box and the current icon dimension to compute
// the scaling factor
val fullOrigWidth = getOrigX() + getOrigWidth()
val fullOrigHeight = getOrigY() + getOrigHeight()
val coef1 = size.width / fullOrigWidth
val coef2 = size.height / fullOrigHeight
val coef = min(coef1, coef2).toFloat()
// Use the original icon bounding box and the current icon dimension to compute
// the offset pivot for the scaling
var translateX = -getOrigX()
var translateY = -getOrigY()
if (coef1 != coef2) {
if (coef1 < coef2) {
val extraDy = ((fullOrigWidth - fullOrigHeight) / 2.0f).toFloat()
translateY += extraDy
} else {
val extraDx = ((fullOrigHeight - fullOrigWidth) / 2.0f).toFloat()
translateX += extraDx
}
}
val translateXDp = translateX.toFloat().toDp().value
val translateYDp = translateY.toFloat().toDp().value
// Create a combined scale + translate + clip transform before calling the transcoded painting
// instructions
withTransform({
scale(scaleX = coef, scaleY = coef, pivot = Offset.Zero)
translate(translateXDp, translateYDp)
clipRect(
left = 0.0f,
top = 0.0f,
right = fullOrigWidth.toFloat(),
bottom = fullOrigHeight.toFloat(),
clipOp = ClipOp.Intersect
)
}) {
innerPaint(this)
}
}
}
}
@@ -8,25 +8,21 @@ package dev.msfjarvis.claw.common.ui.decorations
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.ui.preview.DevicePreviews
import dev.msfjarvis.claw.common.ui.preview.ThemePreviews
import dev.msfjarvis.claw.common.ui.surfaceColorAtNavigationBarElevation
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun ClawAppBar(
backgroundColor: Color,
modifier: Modifier = Modifier,
navigationIcon: @Composable () -> Unit = {},
title: @Composable () -> Unit = {},
@@ -35,7 +31,7 @@ fun ClawAppBar(
TopAppBar(
title = title,
modifier = modifier.shadow(8.dp),
colors = TopAppBarDefaults.smallTopAppBarColors(containerColor = backgroundColor),
colors = TopAppBarDefaults.topAppBarColors(),
navigationIcon = navigationIcon,
actions = actions,
)
@@ -47,7 +43,6 @@ fun ClawAppBar(
fun ClawAppBarPreview() {
LobstersTheme {
ClawAppBar(
backgroundColor = MaterialTheme.colorScheme.surfaceColorAtNavigationBarElevation(),
title = { Text("Claw", fontWeight = FontWeight.Bold) },
)
}
@@ -1,11 +1,9 @@
/*
* 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("NON_SOURCE_REPEATED_ANNOTATION") // IDE false-positive
package dev.msfjarvis.claw.common.ui.preview
import android.content.res.Configuration
@@ -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.
@@ -22,7 +22,7 @@ class UrlLauncher(private val context: Context) : UriHandler {
CustomTabsIntent.Builder()
.setShareState(CustomTabsIntent.SHARE_STATE_ON)
.setShowTitle(true)
.setColorScheme(CustomTabsIntent.COLOR_SCHEME_DARK)
.setColorScheme(CustomTabsIntent.COLOR_SCHEME_SYSTEM)
.build()
try {
customTabsIntent.launchUrl(context, Uri.parse(uri))
@@ -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,6 +13,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -22,12 +24,12 @@ import androidx.compose.runtime.produceState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.NetworkState
import dev.msfjarvis.claw.common.NetworkState.Error
import dev.msfjarvis.claw.common.NetworkState.Loading
import dev.msfjarvis.claw.common.NetworkState.Success
import dev.msfjarvis.claw.common.res.ClawIcons
import dev.msfjarvis.claw.common.ui.NetworkError
import dev.msfjarvis.claw.common.ui.NetworkImage
import dev.msfjarvis.claw.common.ui.ProgressBar
@@ -90,7 +92,7 @@ private fun UserProfileInternal(
) {
NetworkImage(
url = "https://lobste.rs/${user.avatarUrl}",
placeholder = ClawIcons.Account,
placeholder = rememberVectorPainter(Icons.Filled.AccountCircle),
contentDescription = "Avatar of ${user.username}",
modifier = Modifier.requiredSize(120.dp).clip(CircleShape),
)
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,6c1.93,0,3.5,1.57,3.5,3.5S13.93,13,12,13 s-3.5-1.57-3.5-3.5S10.07,6,12,6z M12,20c-2.03,0-4.43-0.82-6.14-2.88C7.55,15.8,9.68,15,12,15s4.45,0.8,6.14,2.12 C16.43,19.18,14.03,20,12,20z"/></g></svg>

Before

Width:  |  Height:  |  Size: 461 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>

Before

Width:  |  Height:  |  Size: 217 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18zM20 4v13.17L18.83 16H4V4h16zM6 12h12v2H6zm0-3h12v2H6zm0-3h12v2H6z"/></svg>

Before

Width:  |  Height:  |  Size: 301 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>

Before

Width:  |  Height:  |  Size: 333 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"/></svg>

Before

Width:  |  Height:  |  Size: 502 B

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12zm-4.51 2.11l.26 2.79-2.74.62-1.43 2.41L12 18.82l-2.58 1.11-1.43-2.41-2.74-.62.26-2.8L3.66 12l1.85-2.12-.26-2.78 2.74-.61 1.43-2.41L12 5.18l2.58-1.11 1.43 2.41 2.74.62-.26 2.79L20.34 12l-1.85 2.11zM11 15h2v2h-2zm0-8h2v6h-2z"/></svg>

Before

Width:  |  Height:  |  Size: 558 B

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