Compare commits

...
342 Commits
Author SHA1 Message Date
GitHub Actions 6e29d61799 feat(release): bump version 2024-06-05 07:49:10 +00:00
Harsh Shandilya 1ee9d92b40 chore: update changelog 2024-06-05 13:12:57 +05:30
Harsh Shandilya 9c07169b1b fix(android): attempt to workaround duplicate item keys bug
Fixes COMPOSE-LOBSTERS-2E
2024-06-05 13:12:52 +05:30
renovate[bot]andGitHub 81f4d35f93 fix(deps): update dependency com.squareup.leakcanary:leakcanary-android-test to v3.0-alpha-8 2024-06-04 23:13:29 +00:00
renovate[bot]andGitHub 361082ded4 chore(deps): update github/codeql-action action to v3.25.8 2024-06-04 16:15:41 +00:00
renovate[bot]andGitHub 4fe43dbdc9 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.7.0 2024-06-04 08:22:24 +00:00
renovate[bot]andGitHub cef45bd3e5 chore(deps): update dependency gradle to v8.8 2024-05-31 22:51:30 +00:00
renovate[bot]andGitHub c45dd76fc4 chore(deps): update github/codeql-action action to v3.25.7 2024-05-31 10:52:15 +00:00
renovate[bot]andGitHub 9a1f42764e fix(deps): update dependency com.squareup.leakcanary:leakcanary-android-test to v3.0-alpha-7 2024-05-31 02:01:11 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
e62a0eaa84 fix(deps): update androidx (#577)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [androidx.test:runner](https://developer.android.com/testing) |
`1.6.0-beta01` -> `1.6.0-rc01` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/androidx.test:runner/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/androidx.test:runner/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/androidx.test:runner/1.6.0-beta01/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/androidx.test:runner/1.6.0-beta01/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [androidx.test:rules](https://developer.android.com/testing) |
`1.6.0-beta01` -> `1.6.0-rc01` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/androidx.test:rules/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/androidx.test:rules/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/androidx.test:rules/1.6.0-beta01/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/androidx.test:rules/1.6.0-beta01/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [androidx.test.ext:junit](https://developer.android.com/testing) |
`1.2.0-beta01` -> `1.2.0-rc01` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/androidx.test.ext:junit/1.2.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/androidx.test.ext:junit/1.2.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/androidx.test.ext:junit/1.2.0-beta01/1.2.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/androidx.test.ext:junit/1.2.0-beta01/1.2.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[androidx.test.espresso:espresso-core](https://developer.android.com/testing)
| `3.6.0-beta01` -> `3.6.0-rc01` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/androidx.test.espresso:espresso-core/3.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/androidx.test.espresso:espresso-core/3.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/androidx.test.espresso:espresso-core/3.6.0-beta01/3.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/androidx.test.espresso:espresso-core/3.6.0-beta01/3.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [androidx.test:core](https://developer.android.com/testing) |
`1.6.0-beta01` -> `1.6.0-rc01` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/androidx.test:core/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/androidx.test:core/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/androidx.test:core/1.6.0-beta01/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/androidx.test:core/1.6.0-beta01/1.6.0-rc01?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNzcuOCIsInVwZGF0ZWRJblZlciI6IjM3LjM3Ny44IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-30 21:13:05 +00:00
Harsh Shandilya 6296afe51a Revert "refactor(android): migrate to navigation safe-args"
This reverts commit cf390de486 and bb3cef2f5b.
2024-05-31 01:05:14 +05:30
Harsh Shandilya cf390de486 refactor(android): move navigation extensions to their own file 2024-05-30 18:07:23 +05:30
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
99a45ab5df chore(deps): update aboutlibraries to v11.2.1 (#574)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| com.mikepenz.aboutlibraries.plugin | `11.2.0` -> `11.2.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.mikepenz.aboutlibraries.plugin/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.mikepenz.aboutlibraries.plugin/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.mikepenz.aboutlibraries.plugin/11.2.0/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.mikepenz.aboutlibraries.plugin/11.2.0/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[com.mikepenz:aboutlibraries-compose-m3](https://togithub.com/mikepenz/AboutLibraries)
| `11.2.0` -> `11.2.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.mikepenz:aboutlibraries-compose-m3/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.mikepenz:aboutlibraries-compose-m3/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.mikepenz:aboutlibraries-compose-m3/11.2.0/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.mikepenz:aboutlibraries-compose-m3/11.2.0/11.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>mikepenz/AboutLibraries
(com.mikepenz:aboutlibraries-compose-m3)</summary>

###
[`v11.2.1`](https://togithub.com/mikepenz/AboutLibraries/releases/tag/11.2.1)

[Compare
Source](https://togithub.com/mikepenz/AboutLibraries/compare/11.2.0...11.2.1)

#### 💬 Other

-   Reduce noise of AmbiguousArtifactVariantsException logs even more
- PR:
[#&#8203;990](https://togithub.com/mikepenz/AboutLibraries/issues/990)
    -   Thanks [@&#8203;sebokopter](https://togithub.com/sebokopter)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNzcuOCIsInVwZGF0ZWRJblZlciI6IjM3LjM3Ny44IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-30 10:57:41 +00:00
Harsh Shandilya 5257d0876a fix(ci): explicitly run assemble task
Seems like the Sentry Gradle plugin doesn't run otherwise
2024-05-30 14:17:39 +05:30
Harsh Shandilya bb3cef2f5b refactor(android): migrate to navigation safe-args
(cherry picked from commit 127a69249e)

Fixes PP-77
2024-05-30 14:03:42 +05:30
Harsh Shandilya a791588423 fix(android): work around weird scroll issue with saved posts 2024-05-30 13:07:51 +05:30
Harsh Shandilya 535624bf22 fix(deps): upgrade to Compose 1.7 betas 2024-05-30 13:04:02 +05:30
Harsh Shandilya b5a7225bd8 chore: update gitignore 2024-05-30 03:19:12 +05:30
Harsh Shandilya 8c0734a19a fix(build): enable Compose strong skipping mode 2024-05-30 02:02:12 +05:30
renovate[bot]andGitHub 71afc634b9 fix(deps): update androidx 2024-05-29 17:28:26 +00:00
renovate[bot]andGitHub fbaede8215 chore(deps): update plugin poko to v0.16.0 2024-05-28 23:03:26 +00:00
Harsh Shandilya 948aea7ea8 fix(deps): upgrade coroutines to 1.9.0-RC 2024-05-29 01:16:44 +05:30
renovate[bot]andGitHub 6acab19b28 chore(deps): update mobsf/mobsfscan digest to 849b749 2024-05-27 22:55:17 +00:00
renovate[bot]andGitHub 2555140ca1 chore(deps): update dependency gradle to v8.8-rc-2 2024-05-27 09:48:31 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4a5980fd62 fix(deps): update konvert to v3.2.1 (#569)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [io.mcarle:konvert](https://togithub.com/mcarleio/konvert) | `3.2.0`
-> `3.2.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/io.mcarle:konvert/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.mcarle:konvert/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.mcarle:konvert/3.2.0/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.mcarle:konvert/3.2.0/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [io.mcarle:konvert-api](https://togithub.com/mcarleio/konvert) |
`3.2.0` -> `3.2.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/io.mcarle:konvert-api/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.mcarle:konvert-api/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.mcarle:konvert-api/3.2.0/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.mcarle:konvert-api/3.2.0/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [io.mcarle:konvert-annotations](https://togithub.com/mcarleio/konvert)
| `3.2.0` -> `3.2.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/io.mcarle:konvert-annotations/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.mcarle:konvert-annotations/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.mcarle:konvert-annotations/3.2.0/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.mcarle:konvert-annotations/3.2.0/3.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-24 09:04:05 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
215afd208e chore(deps): update plugin dependencyanalysis to v1.32.0 (#568)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[com.autonomousapps.dependency-analysis](https://togithub.com/autonomousapps/dependency-analysis-android-gradle-plugin)
| `1.31.0` -> `1.32.0` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.autonomousapps.dependency-analysis/1.32.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.autonomousapps.dependency-analysis/1.32.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.autonomousapps.dependency-analysis/1.31.0/1.32.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.autonomousapps.dependency-analysis/1.31.0/1.32.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>autonomousapps/dependency-analysis-android-gradle-plugin
(com.autonomousapps.dependency-analysis)</summary>

###
[`v1.32.0`](https://togithub.com/autonomousapps/dependency-analysis-android-gradle-plugin/blob/HEAD/CHANGELOG.md#Version-1320)

- \[New]: Output dominator tree results in JSON format including size
and total size of deps.
-   \[New]: Allow to force app behavior for pure Java projects.
-   \[New]: `generateProjectGraph` task.
-   \[New]: `reason` works for multi-capabilities.
-   \[New]: Print build file path in `projectHealth` console report.
- \[Fix]: Enhance logging (more) when `ConstantPoolParser` throws
exception.
- \[Fix]: Do not dotty for path matching and remove prefix and suffix
from binary class name.
-   \[Fix]: Fix Windows file separator incompatibility.
- \[Fix]: Don't suggest adding `testImplementation` dependency on self.
-   \[Fix]: DAGP variants have a `Category` of 'dependency-analysis'.
-   \[Fix]: Sort an input map for better reproducibility.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-24 04:41:12 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
806ef65e08 fix(deps): update dependency com.squareup.leakcanary:leakcanary-android-test to v3.0-alpha-6 (#566)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[com.squareup.leakcanary:leakcanary-android-test](https://togithub.com/square/leakcanary)
| `3.0-alpha-5` -> `3.0-alpha-6` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.squareup.leakcanary:leakcanary-android-test/3.0-alpha-6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.squareup.leakcanary:leakcanary-android-test/3.0-alpha-6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.squareup.leakcanary:leakcanary-android-test/3.0-alpha-5/3.0-alpha-6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.squareup.leakcanary:leakcanary-android-test/3.0-alpha-5/3.0-alpha-6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>square/leakcanary
(com.squareup.leakcanary:leakcanary-android-test)</summary>

###
[`v3.0-alpha-6`](https://togithub.com/square/leakcanary/releases/tag/v3.0-alpha-6)

See [Change Log](https://square.github.io/leakcanary/changelog)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4zNjguMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-22 16:43:47 +00:00
Harsh Shandilya 35e143a458 chore: update changelog 2024-05-22 14:29:21 +05:30
Harsh Shandilya 5b4d1fc48e Merge remote-tracking branches 'origin/renovate/aboutlibraries' and 'origin/renovate/com.slack.lint-slack-lint-checks-0.x'
* origin/renovate/aboutlibraries:
  chore(deps): update aboutlibraries to v11.2.0

* origin/renovate/com.slack.lint-slack-lint-checks-0.x:
  fix(deps): update dependency com.slack.lint:slack-lint-checks to v0.7.4
2024-05-22 14:14:05 +05:30
renovate[bot]andGitHub c9098bbd44 chore(deps): update aboutlibraries to v11.2.0 2024-05-21 21:11:40 +00:00
renovate[bot]andGitHub b7eecd10b4 fix(deps): update dependency com.slack.lint:slack-lint-checks to v0.7.4 2024-05-21 21:11:36 +00:00
Harsh Shandilya c471fee4ee fix(build): cut over to upstream Compose Compiler 2024-05-22 02:40:24 +05:30
Harsh Shandilya e3ed059fde fix(deps): upgrade ksp and poko 2024-05-22 02:39:02 +05:30
renovate[bot]andGitHub 44355de333 chore(deps): update kotlin and compose to v2 2024-05-21 14:31:31 +00:00
renovate[bot]andGitHub 92dc6d9e4c fix(deps): update dependency com.squareup.leakcanary:leakcanary-android-test to v3.0-alpha-5 2024-05-21 05:58:36 +00:00
renovate[bot]andGitHub 68ca569b9d chore(deps): update agp to v8.4.1 2024-05-20 23:29:23 +00:00
renovate[bot]andGitHub 105a33e335 chore(deps): update github/codeql-action action to v3.25.6 2024-05-20 15:03:52 +00:00
renovate[bot]andGitHub 7862b4b5c8 chore(deps): update plugin poko to v0.15.3 2024-05-20 00:10:30 +00:00
Harsh Shandilya b12b5c800f feat(android): add share action 2024-05-20 01:37:00 +05:30
Harsh Shandilya b56de40b12 fix(build): downgrade to stable AGP 2024-05-20 01:29:22 +05:30
renovate[bot]andGitHub 8243b8998c chore(deps): update plugin com.gradle.develocity to v3.17.4 2024-05-17 17:50:12 +00:00
renovate[bot]andGitHub 195b50f919 fix(deps): update androidx 2024-05-17 02:28:27 +00:00
Harsh Shandilya 2d7903efc1 Merge remote-tracking branches 'origin/renovate/actions-checkout-4.x', 'origin/renovate/agp' and 'origin/renovate/sentry'
* origin/renovate/actions-checkout-4.x:
  chore(deps): update actions/checkout action to v4.1.6

* origin/renovate/agp:
  chore(deps): update agp to v8.5.0-beta02

* origin/renovate/sentry:
  fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.6.0
2024-05-17 00:53:33 +05:30
renovate[bot]andGitHub e2ab469ecc fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.6.0 2024-05-16 19:18:13 +00:00
renovate[bot]andGitHub 4ccf8959d9 chore(deps): update agp to v8.5.0-beta02 2024-05-16 19:18:08 +00:00
renovate[bot]andGitHub b73a758501 chore(deps): update actions/checkout action to v4.1.6 2024-05-16 19:18:05 +00:00
Harsh Shandilya cfaa1c17a0 fix(deps): update Compose Compiler to 1.5.14 2024-05-17 00:43:56 +05:30
renovate[bot]andGitHub 47332c22ec fix(deps): update androidx 2024-05-14 17:29:24 +00:00
GitHub Actions ce64454cec feat(release): start next development iteration 2024-05-14 07:49:51 +00:00
GitHub Actions b3313efbbe feat(release): bump version 2024-05-14 07:46:16 +00:00
renovate[bot]andGitHub bc14e58513 chore(deps): update github/codeql-action action to v3.25.5 2024-05-13 14:30:30 +00:00
Harsh Shandilya 83eb3c13b2 feat(android): add a heap growth detection test 2024-05-13 02:51:25 +05:30
Harsh Shandilya 59acbe2a37 fix(build): also inject test dependencies to androidTest source set 2024-05-13 02:07:36 +05:30
renovate[bot]andGitHub 7e31de67b4 chore(deps): update agp to v8.5.0-beta01 2024-05-10 18:21:22 +00:00
renovate[bot]andGitHub 37230e03c4 fix(deps): update coroutines to v1.8.1 2024-05-10 12:47:15 +00:00
renovate[bot]andGitHub fbf937dce2 chore(deps): update plugin com.gradle.develocity to v3.17.3 2024-05-10 11:38:07 +00:00
renovate[bot]andGitHub ee9db517f7 chore(deps): update plugin anvil to v2.5.0-beta09 2024-05-10 00:50:17 +00:00
Harsh Shandilya a4dcdc6f88 chore: refresh feature graphics 2024-05-09 18:11:39 +05:30
Harsh Shandilya c9c908d1a5 fix(android): improve TopAppBar layout spacing 2024-05-09 18:11:39 +05:30
Harsh Shandilya 2ce804ed90 refactor: inline ClawAppBar 2024-05-09 18:02:02 +05:30
Harsh Shandilya 3b044a8d23 chore: reflow UserProfile code for pedantic reasons 2024-05-09 17:54:01 +05:30
Harsh Shandilya bdca0799db fix(common): restore older link styling in user profiles 2024-05-09 17:51:06 +05:30
renovate[bot]andGitHub ca37557297 chore(deps): update actions/checkout action to v4.1.5 2024-05-09 00:49:43 +00:00
Harsh Shandilya 9c0c270f5c chore: refresh feature graphic 2024-05-08 22:53:00 +05:30
Harsh Shandilya 8a9cc844b9 fix(deps): upgrade Compose Compiler to 1.5.14-dev-k1.9.24-50022def4af 2024-05-08 20:11:44 +05:30
renovate[bot]andGitHub 452ba7dbf9 chore(deps): update kotlin and compose 2024-05-08 14:03:41 +00:00
Harsh Shandilya 9edfc23ee3 Merge remote-tracking branches 'origin/renovate/sentry' and 'origin/renovate/github-codeql-action-3.x'
* origin/renovate/sentry:
  fix(deps): update sentry to v7.9.0

* origin/renovate/github-codeql-action-3.x:
  chore(deps): update github/codeql-action action to v3.25.4
2024-05-08 19:32:17 +05:30
renovate[bot]andGitHub 3057f5fede fix(deps): update sentry to v7.9.0 2024-05-08 13:59:12 +00:00
renovate[bot]andGitHub 157748bc61 chore(deps): update github/codeql-action action to v3.25.4 2024-05-08 13:59:06 +00:00
Harsh Shandilya 68a5de84f7 Revert "refactor(android): migrate to navigation safe-args"
This reverts commit 127a69249e.
2024-05-08 19:28:24 +05:30
Harsh Shandilya b69fa43d29 Revert "fix(android): correct navigation route for attribution page"
This reverts commit 60a7b815ea.
2024-05-08 19:24:05 +05:30
Harsh Shandilya 6f76a15ded fix: downgrade to Compose stable
Fixes PP-56
Fixes PP-61
Fixes COMPOSE-LOBSTERS-3Z
Fixes COMPOSE-LOBSTERS-40
2024-05-07 14:02:08 +05:30
Harsh Shandilya 9fe6e34015 chore: make LaunchedEffect keys consistent 2024-05-07 13:09:30 +05:30
Harsh Shandilya 847858d852 fix(common): set key for comment entries 2024-05-04 04:23:28 +05:30
Harsh Shandilya 8735f7f8e8 fix(common): mark CommentNode#findTopMostParent as tailrec 2024-05-04 04:23:28 +05:30
renovate[bot]andGitHub 5061843779 fix(deps): update dependency com.slack.lint:slack-lint-checks to v0.7.3 2024-05-03 21:41:12 +00:00
renovate[bot]andGitHub b8480f1994 chore(deps): update agp to v8.5.0-alpha08 2024-05-03 19:10:12 +00:00
Harsh Shandilya 60a7b815ea fix(android): correct navigation route for attribution page
Fixes PP-54
2024-05-03 23:59:21 +05:30
renovate[bot]andGitHub bff56aa52b fix(deps): update dependency com.slack.lint:slack-lint-checks to v0.7.2 2024-05-02 22:03:33 +00:00
Harsh Shandilya 3137a1bb42 chore: update changelog 2024-05-03 01:27:19 +05:30
Harsh Shandilya 127a69249e refactor(android): migrate to navigation safe-args 2024-05-03 01:27:19 +05:30
Harsh Shandilya 9361c7ef47 fix(deps): upgrade whetstone to 0.9.0-beta02 2024-05-02 12:01:29 +05:30
Harsh Shandilya e8a9594e4c Merge remote-tracking branch 'origin/renovate/com.squareup.anvil-2.x'
* origin/renovate/com.squareup.anvil-2.x:
  chore(deps): update plugin anvil to v2.5.0-beta08
2024-05-02 11:50:18 +05:30
Harsh Shandilya 0a8ca5719d fix(deps): update dev.chrisbanes.compose:compose-bom to 2024.05.00-alpha01 2024-05-02 11:49:01 +05:30
Harsh Shandilya d87e2d1b9c fix(build): adapt strong skipping plugin arg 2024-05-02 11:48:49 +05:30
renovate[bot]andGitHub 774c6cea9b chore(deps): update plugin anvil to v2.5.0-beta08 2024-05-01 18:59:03 +00:00
renovate[bot]andGitHub 5753f65737 chore(deps): update androidx 2024-05-01 18:59:01 +00:00
renovate[bot]andGitHub 17965097bc chore(deps): update aboutlibraries to v11.1.4 2024-05-01 13:15:02 +00:00
renovate[bot]andGitHub f1d06116bc fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.5.1 2024-04-30 23:12:09 +00:00
renovate[bot]andGitHub 319e30c174 chore(deps): update actions/dependency-review-action digest to 0c155c5 2024-04-30 19:37:16 +00:00
Harsh Shandilya 8e8b710603 chore: update changelog 2024-04-30 10:42:48 +05:30
renovate[bot]andGitHub a142563ad8 chore(deps): update agp to v8.5.0-alpha07 2024-04-29 20:12:22 +00:00
Harsh Shandilya 9bd0df2aa8 fix(model): restore konvert-api dependency 2024-04-30 01:41:31 +05:30
Harsh Shandilya 54ec5a4c8d Revert "fix: remove visual divider"
It's better with it

This reverts commit 687cb32f7c.
2024-04-30 01:16:17 +05:30
Harsh Shandilya c79b7114fb refactor: selectively apply DAGP advice 2024-04-30 00:53:21 +05:30
Harsh Shandilya a6fb1fd788 fix(build): add dependency-analysis plugin 2024-04-30 00:25:05 +05:30
Harsh Shandilya 5a268fa5bd Merge remote-tracking branches 'origin/renovate/androidx' and 'origin/renovate/actions-dependency-review-action-digest'
* origin/renovate/androidx:
  fix(deps): update androidx

* origin/renovate/actions-dependency-review-action-digest:
  chore(deps): update actions/dependency-review-action digest to e58c696
2024-04-30 00:19:32 +05:30
renovate[bot]andGitHub 431dabbc09 fix(deps): update androidx 2024-04-29 18:09:12 +00:00
renovate[bot]andGitHub d7f71878f6 chore(deps): update actions/dependency-review-action digest to e58c696 2024-04-29 18:09:09 +00:00
Harsh ShandilyaandGitHub 196dfd056b chore: update changelog 2024-04-29 02:19:24 +05:30
Harsh Shandilya 6d3e749ad6 fix(database): ensure DB is only opened once
Fixes COMPOSE-LOBSTERS-3S
2024-04-28 19:10:05 +05:30
Harsh Shandilya e808e77ab8 fixup! fix(build): upgrade to Gradle 8.8-RC1 2024-04-27 20:34:22 +05:30
Harsh Shandilya d8b2ff6c8d fix(android): add missing user destination to search screen
Fixes COMPOSE-LOBSTERS-3V
2024-04-27 16:56:16 +05:30
Harsh Shandilya 55635f1101 fix(build): upgrade to Gradle 8.8-RC1 2024-04-27 16:24:09 +05:30
renovate[bot]andGitHub a70801c635 chore(deps): update dependency com.facebook:ktfmt to v0.49 2024-04-26 18:45:10 +00:00
Harsh Shandilya 3a60e8f2a1 chore(ci): run on Java 22 2024-04-27 00:13:36 +05:30
renovate[bot]andGitHub 80183fd248 chore(deps): update dependency com.facebook:ktfmt to v0.48 2024-04-26 15:40:32 +00:00
Harsh Shandilya 7cbb8e6237 fix(android): eagerly init ClawApplication#applicationComponent 2024-04-26 17:45:18 +05:30
renovate[bot]andGitHub 32cba40e91 chore(deps): update github/codeql-action action to v3.25.3 2024-04-26 01:33:33 +00:00
renovate[bot]andGitHub a8cef93096 chore(deps): update gradle/actions digest to db19848 2024-04-25 23:14:46 +00:00
renovate[bot]andGitHub b3ea9c6faf chore(deps): update actions/checkout action to v4.1.4 2024-04-25 14:14:23 +00:00
GitHub Actions 215b259288 feat(release): start next development iteration 2024-04-24 18:32:18 +00:00
GitHub Actions ab1f276a08 feat(release): bump version 2024-04-24 18:28:03 +00:00
Harsh Shandilya ca03561df0 fix(common): force titles in lists to be a single line 2024-04-24 23:55:09 +05:30
Harsh Shandilya 687cb32f7c fix: remove visual divider 2024-04-24 23:44:36 +05:30
Harsh Shandilya 12e57298af chore: refresh changelog 2024-04-24 23:32:14 +05:30
Harsh Shandilya 5abb5f109b fix(android): disable back invoked callback
Testing if this fixes the bug I'm seeing

Fixes COMPOSE-LOBSTERS-2X
2024-04-24 23:31:35 +05:30
Harsh Shandilya c8eaf8d769 fix(api): remove sentry-okhttp integration
This keeps logging HTTP 500 errors despite me opting out of them

Fixes COMPOSE-LOBSTERS-2T
2024-04-24 22:58:59 +05:30
GitHub Actions 24a4d20a03 feat(release): start next development iteration 2024-04-24 06:51:09 +00:00
GitHub Actions 57f95d790d feat(release): bump version 2024-04-24 06:47:57 +00:00
renovate[bot]andGitHub 09a6e3e32b chore(deps): update msfjarvis/keep-a-changelog-new-release action to v2.2.0 2024-04-24 01:14:57 +00:00
renovate[bot]andGitHub 491be53dc3 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.5.0 2024-04-23 14:16:31 +00:00
renovate[bot]andGitHub d1e6260136 chore(deps): update github/codeql-action action to v3.25.2 2024-04-22 21:21:03 +00:00
renovate[bot]andGitHub c71b33a07f chore(deps): update actions/upload-artifact action to v4.3.3 2024-04-22 18:02:54 +00:00
renovate[bot]andGitHub 7d2094866b chore(deps): update actions/checkout action to v4.1.3 2024-04-22 14:30:42 +00:00
Harsh Shandilya a3e9957e49 fix(build): make internal build debuggable
Makes it easier to pull out the database
2024-04-22 01:21:49 +05:30
Harsh Shandilya cec2d70fda fix(common): make LobstersCard more compact
Fixes #526
2024-04-20 15:18:10 +05:30
Harsh Shandilya ec4066c472 chore(android): add a preview to NetworkPosts 2024-04-20 15:18:10 +05:30
Harsh Shandilya 433727a386 refactor(common): expose fields for LobstersCard previews 2024-04-20 15:18:10 +05:30
renovate[bot]andGitHub 1238012e0b chore(deps): update agp to v8.5.0-alpha06 2024-04-18 22:41:29 +00:00
renovate[bot]andGitHub 96e53f104d chore(deps): update gradle/actions digest to 750cdda 2024-04-18 20:34:58 +00:00
renovate[bot]andGitHub e1fed9ccc8 chore(deps): update actions/upload-artifact action to v4.3.2 2024-04-18 17:34:35 +00:00
Harsh Shandilya ced43b00be refactor(android): boost page load performance
This is kinda embarassing tbh.
2024-04-18 17:50:23 +05:30
Harsh Shandilya 0ca18d9216 fix(android): add log tags to Unfurl logger 2024-04-18 17:46:30 +05:30
Harsh ShandilyaandGitHub 1aa2dee779 fix(build): revert Develocity ToS url change
It redirects to the one I had set but the plugin still expects the older one.

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2024-04-18 15:00:05 +05:30
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7f4a382f40 fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.04.00-alpha02 (#523)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[dev.chrisbanes.compose:compose-bom](https://togithub.com/chrisbanes/compose-bom)
| `2024.04.00-alpha01` -> `2024.04.00-alpha02` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/dev.chrisbanes.compose:compose-bom/2024.04.00-alpha02?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/dev.chrisbanes.compose:compose-bom/2024.04.00-alpha02?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/dev.chrisbanes.compose:compose-bom/2024.04.00-alpha01/2024.04.00-alpha02?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/dev.chrisbanes.compose:compose-bom/2024.04.00-alpha01/2024.04.00-alpha02?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>chrisbanes/compose-bom
(dev.chrisbanes.compose:compose-bom)</summary>

###
[`v2024.04.00-alpha02`](https://togithub.com/chrisbanes/compose-bom/releases/tag/v2024.04.00-alpha02)

#### What's Changed

- chore(deps): update plugin com.android.library to v8.3.2 by
[@&#8203;renovate](https://togithub.com/renovate) in
[https://github.com/chrisbanes/compose-bom/pull/130](https://togithub.com/chrisbanes/compose-bom/pull/130)
- fix(deps): update jetpack compose by
[@&#8203;renovate](https://togithub.com/renovate) in
[https://github.com/chrisbanes/compose-bom/pull/131](https://togithub.com/chrisbanes/compose-bom/pull/131)
- Add material3-common by
[@&#8203;eygraber](https://togithub.com/eygraber) in
[https://github.com/chrisbanes/compose-bom/pull/132](https://togithub.com/chrisbanes/compose-bom/pull/132)

**Full Changelog**:
https://github.com/chrisbanes/compose-bom/compare/v2024.04.00-alpha01...v2024.04.00-alpha02

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4zMDEuNCIsInVwZGF0ZWRJblZlciI6IjM3LjMwMS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-18 01:16:41 +00:00
Harsh Shandilya ed5b6c21da Revert "fix(deps): upgrade Compose"
I guess it is not unmaintained

This reverts commit d19c1e11be.
2024-04-18 03:48:34 +05:30
Harsh Shandilya d0bf2a4fb2 fix: handle user profile navigation correctly 2024-04-18 01:54:26 +05:30
Harsh Shandilya 2b9680d3d8 refactor: remove deeplinks
Fixes #484
2024-04-18 01:08:42 +05:30
Harsh Shandilya d19c1e11be fix(deps): upgrade Compose
The BOM is likely to go unmaintained in the future

See: https://github.com/chrisbanes/compose-bom/issues/97
2024-04-18 01:02:26 +05:30
renovate[bot]andGitHub 809cec61cd chore(deps): update dependency androidx.compose.compiler:compiler to v1.5.12 2024-04-17 17:47:28 +00:00
Harsh Shandilya 13feb83063 chore(deps): upgrade AndroidX libraries 2024-04-17 23:16:47 +05:30
renovate[bot]andGitHub 40b7884520 chore(deps): update plugin com.gradle.develocity to v3.17.2 2024-04-17 14:31:29 +00:00
renovate[bot]andGitHub 75b05b83c1 chore(deps): update github/codeql-action action to v3.25.1 2024-04-17 12:26:22 +00:00
renovate[bot]andGitHub 9afe913548 chore(deps): update plugin anvil to v2.5.0-beta07 2024-04-17 00:39:33 +00:00
renovate[bot]andGitHub 44d589e729 chore(deps): update plugin anvil to v2.5.0-beta06 2024-04-16 17:24:25 +00:00
renovate[bot]andGitHub ace1a3c94c fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.4.1 2024-04-15 21:41:22 +00:00
renovate[bot]andGitHub 31c94dc8cc chore(deps): update github/codeql-action action to v3.25.0 2024-04-15 14:31:03 +00:00
Harsh Shandilya 493ab8712c chore: add changelog entry 2024-04-14 21:10:50 +05:30
Harsh Shandilya 1fff9d9aa2 fix(android): only attempt to scroll when items exist
Fixes COMPOSE-LOBSTERS-3F
2024-04-14 20:51:57 +05:30
Harsh Shandilya 9357362ef6 fix(ci): validate Gradle wrappers in CI 2024-04-13 14:18:45 +05:30
Harsh Shandilya 7b07a4676b refactor(ci): introduce a reusable workflow 2024-04-13 14:08:30 +05:30
renovate[bot]andGitHub e272427031 fix(deps): update konvert to v3.2.0 2024-04-12 21:14:45 +00:00
renovate[bot]andGitHub 7882b86b39 chore(deps): update gradle/actions digest to 6cec5d4 2024-04-12 20:11:13 +00:00
renovate[bot]andGitHub afb00c64fc chore(deps): update agp to v8.5.0-alpha05 2024-04-11 18:17:03 +00:00
renovate[bot]andGitHub 3a7727e563 chore(deps): update plugin anvil to v2.5.0-beta05 2024-04-09 19:02:52 +00:00
Harsh Shandilya d28c9c2e61 Revert "fix(deps): update glance to 1.1.0-beta01"
This reverts commit dc70293bd4.
2024-04-10 00:31:52 +05:30
renovate[bot]andHarsh Shandilya 99aff514f2 fix(deps): update sentry to v7.8.0 2024-04-10 00:31:52 +05:30
renovate[bot]andHarsh Shandilya 0e8f1a51bf chore(deps): update plugin com.gradle.develocity to v3.17.1 2024-04-10 00:31:52 +05:30
renovate[bot]andGitHub 52829fedb2 chore(deps): update dependency com.mikepenz.aboutlibraries.plugin to v11.1.3 2024-04-09 17:12:54 +00:00
renovate[bot]andGitHub 4e479cf0f1 chore(deps): update aboutlibraries to v11.1.2 2024-04-09 14:30:56 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2020f43dd6 chore(deps): update gradle/actions digest to 1168cd3 (#514)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [gradle/actions](https://togithub.com/gradle/actions) | action |
digest | `e24011a` -> `1168cd3` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjkuMiIsInVwZGF0ZWRJblZlciI6IjM3LjI2OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-09 04:17:33 +00:00
Harsh Shandilya 659eaf9789 feat: enable Compose strong skipping mode 2024-04-09 09:43:22 +05:30
renovate[bot]andGitHub a410267f99 chore(deps): update agp to v8.5.0-alpha04 2024-04-08 18:31:44 +00:00
renovate[bot]andGitHub 6f248c529e fix(deps): update sentry to v7.7.0 2024-04-08 12:56:18 +00:00
renovate[bot]andGitHub 142fafba23 fix(deps): update konvert to v3.1.0 2024-04-06 03:34:33 +00:00
renovate[bot]andGitHub 7119cda579 chore(deps): update sqldelight to v2.0.2 2024-04-06 01:21:27 +00:00
renovate[bot]andGitHub e3c1213be6 chore(deps): update github/codeql-action action to v3.24.10 2024-04-05 17:12:11 +00:00
renovate[bot]andGitHub 5487615436 chore(deps): update plugin ksp to v1.9.23-1.0.20 2024-04-05 02:24:24 +00:00
renovate[bot]andGitHub 619b771aff chore(deps): update gradle/actions digest to e24011a 2024-04-04 21:53:02 +00:00
Harsh Shandilya a12a1f92a5 fix(deps): update dev.chrisbanes.compose:compose-bom to 2024.04.00-alpha01 2024-04-04 04:28:24 +05:30
Harsh Shandilya dc70293bd4 fix(deps): update glance to 1.1.0-beta01 2024-04-04 04:22:42 +05:30
renovate[bot]andGitHub f9ecdebc63 fix(deps): update androidx 2024-04-03 19:35:21 +00:00
renovate[bot]andHarsh Shandilya 4a96af17f4 chore(deps): update plugin com.gradle.enterprise to v3.17 2024-04-03 11:22:18 +05:30
renovate[bot]andGitHub e9b69c5cad chore(deps): update agp to v8.5.0-alpha03 2024-04-02 14:08:09 +00:00
Harsh Shandilya d3f9bb4c00 fix(build): switch over to includeGroupAndSubgroups API
The bug that broke this was fixed in Gradle 8.7
2024-03-31 17:33:16 +05:30
renovate[bot]andHarsh Shandilya feae5d2630 chore(deps): update plugin licensee to v1.11.0
(cherry picked from commit a030290ec242a469d5610c85e2faa1c26ed2535f)
2024-03-30 03:00:45 +05:30
renovate[bot]andGitHub df7868de2d fix(deps): update dagger to v2.51.1 2024-03-29 20:04:32 +00:00
renovate[bot]andGitHub 8a66361a98 fix(deps): update retrofit to v2.11.0 2024-03-29 01:03:51 +00:00
renovate[bot]andGitHub 3099ffe201 chore(deps): update plugin licensee to v1.10.0 2024-03-28 21:21:17 +00:00
renovate[bot]andGitHub 0fc9c28354 fix(deps): update dependency com.slack.lint:slack-lint-checks to v0.7.1 2024-03-27 18:10:39 +00:00
renovate[bot]andGitHub 6ba7dec98d chore(deps): update actions/setup-python digest to 82c7e63 2024-03-26 16:20:57 +00:00
renovate[bot]andGitHub 332a84c6ec fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.4.0 2024-03-26 13:09:10 +00:00
renovate[bot]andGitHub a19a5e926c chore(deps): update actions/dependency-review-action digest to 5bbc3ba 2024-03-26 08:10:02 +00:00
renovate[bot]andGitHub bd952b74d8 chore(deps): update actions/dependency-review-action digest to 733dd5d 2024-03-24 14:30:41 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3e374df3aa chore(deps): update aboutlibraries to v11.1.1 (#499)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| com.mikepenz.aboutlibraries.plugin | `11.1.0` -> `11.1.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.mikepenz.aboutlibraries.plugin/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.mikepenz.aboutlibraries.plugin/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.mikepenz.aboutlibraries.plugin/11.1.0/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.mikepenz.aboutlibraries.plugin/11.1.0/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[com.mikepenz:aboutlibraries-compose-m3](https://togithub.com/mikepenz/AboutLibraries)
| `11.1.0` -> `11.1.1` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.0/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.0/11.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>mikepenz/AboutLibraries
(com.mikepenz:aboutlibraries-compose-m3)</summary>

###
[`v11.1.1`](https://togithub.com/mikepenz/AboutLibraries/releases/tag/v11.1.1)

##### 🚀 Features

-   Library Serializer
- PR:
[#&#8203;963](https://togithub.com/mikepenz/AboutLibraries/issues/963)
    -   Thanks [@&#8203;DatL4g](https://togithub.com/DatL4g)
-   Update major dependencies | Compose 1.6.4 | Compose-MP 1.6.1
- PR:
[#&#8203;968](https://togithub.com/mikepenz/AboutLibraries/issues/968)

##### 🐛 Fixes

- Set onclick listener of SimpleLibraryItem to null if no license is
known
- PR:
[#&#8203;966](https://togithub.com/mikepenz/AboutLibraries/issues/966)
    -   Thanks [@&#8203;alexbakker](https://togithub.com/alexbakker)
-   Sort a copy of the list of libraries to prevent a crash
- PR:
[#&#8203;967](https://togithub.com/mikepenz/AboutLibraries/issues/967)
    -   Thanks [@&#8203;alexbakker](https://togithub.com/alexbakker)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yNjEuMCIsInVwZGF0ZWRJblZlciI6IjM3LjI2MS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-23 16:40:19 +00:00
renovate[bot]andGitHub 6b67819007 chore(deps): update mobsf/mobsfscan digest to 35b2016 2024-03-23 00:34:18 +00:00
Harsh Shandilya 83af44b0e6 Merge remote-tracking branches 'origin/renovate/agp' and 'origin/renovate/gradle-8.x'
* origin/renovate/agp:
  chore(deps): update agp to v8.5.0-alpha02

* origin/renovate/gradle-8.x:
  chore(deps): update dependency gradle to v8.7
2024-03-23 00:42:53 +05:30
renovate[bot]andGitHub bec12d8e09 chore(deps): update dependency gradle to v8.7 2024-03-22 18:18:14 +00:00
renovate[bot]andGitHub b34fc8c721 chore(deps): update agp to v8.5.0-alpha02 2024-03-22 18:10:16 +00:00
renovate[bot]andGitHub dc51fa7802 chore(deps): update github/codeql-action action to v3.24.9 2024-03-22 11:49:49 +00:00
renovate[bot]andGitHub 42a667462f fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.03.00-alpha02 2024-03-20 22:24:53 +00:00
renovate[bot]andGitHub c76661762f chore(deps): update actions/dependency-review-action digest to 0fa40c3 2024-03-20 20:39:57 +00:00
Harsh Shandilya 9dab223da8 fix(deps): update agp to 8.5.0-alpha01 2024-03-21 01:57:58 +05:30
Harsh Shandilya 1ef6b2bf91 chore: minor formatting tweak 2024-03-21 01:29:44 +05:30
Harsh Shandilya f2f3319ac4 fix(deps): update AndroidX dependencies 2024-03-21 01:21:39 +05:30
Harsh Shandilya 7fd9cef051 chore: fix link to IzzyOnDroid badge 2024-03-20 23:21:26 +05:30
Harsh Shandilya 4d4cccbba9 chore(readme): add IzzyOnDroid badge 2024-03-19 22:41:25 +05:30
GitHub Actions aff0e366fe feat(release): start next development iteration 2024-03-19 12:57:11 +00:00
GitHub Actions f00f185f6d feat(release): bump version 2024-03-19 12:54:12 +00:00
Harsh Shandilya a08ffb903c chore: bump changelog 2024-03-19 18:20:40 +05:30
Harsh Shandilya 4eaf25e189 fix(database/core): fix upgrade path for ReadPosts table
Fixes COMPOSE-LOBSTERS-2S
2024-03-19 17:59:35 +05:30
renovate[bot]andGitHub 109176768c chore(deps): update agp to v8.3.1 2024-03-18 21:22:57 +00:00
Harsh Shandilya cf0ef021d8 fix(deps): update retrofit to 2.10.0 2024-03-19 02:48:42 +05:30
renovate[bot]andGitHub 59ba98174c chore(deps): update github/codeql-action action to v3.24.8 2024-03-18 17:32:16 +00:00
GitHub Actions afe78aa82f feat(release): start next development iteration 2024-03-17 08:24:44 +00:00
GitHub Actions 0a70924cab feat(release): bump version 2024-03-17 08:22:24 +00:00
renovate[bot]andGitHub ae362c2e03 fix(deps): update dependency com.michael-bull.kotlin-result:kotlin-result-coroutines to v2 2024-03-17 00:39:13 +00:00
renovate[bot]andGitHub 83ca0e6167 fix(deps): update dependency com.michael-bull.kotlin-result:kotlin-result-coroutines to v1.1.21 2024-03-16 21:46:14 +00:00
Harsh Shandilya 71977c5b2c refactor(android): move UIPost rewrite into PagingSource 2024-03-16 23:45:56 +05:30
Harsh Shandilya 047d6badb0 fix(core): do not capture failed network requests for Sentry
Fixes COMPOSE-LOBSTERS-2Q
2024-03-16 22:19:39 +05:30
Harsh Shandilya 5c0b5bb4f7 fix(widget): open comments screen directly for lobsters-native posts
Fixes COMPOSE-LOBSTERS-2P
2024-03-16 18:01:30 +05:30
renovate[bot]andGitHub 7762733da2 chore(deps): update msfjarvis/keep-a-changelog-new-release action to v2.1.1 2024-03-16 09:54:32 +00:00
GitHub Actions 9f705ca02a feat(release): start next development iteration 2024-03-16 06:06:39 +00:00
GitHub Actions 6c5b54587e feat(release): bump version 2024-03-16 06:04:08 +00:00
Harsh Shandilya e318ea3a35 fix(ci): drop release snapshots 2024-03-16 11:28:04 +05:30
Harsh Shandilya 5ba0c9a544 refactor(build): always enable Sentry and set environment
Thx Static-Var my beloved
2024-03-16 10:14:57 +05:30
Harsh Shandilya 85fc5cac21 fix: adjust for new API changes 2024-03-16 09:48:08 +05:30
Harsh Shandilya 86a40d2e84 fix(deps): upgrade dev.msfjarvis.whetstone to 0.9.0-beta01 2024-03-15 13:21:02 +05:30
renovate[bot]andGitHub 557407347b chore(deps): update plugin anvil to v2.5.0-beta04 2024-03-14 23:08:38 +00:00
renovate[bot]andGitHub b0467aa36c chore(deps): update actions/setup-java action to v4.2.1 2024-03-14 17:04:59 +00:00
renovate[bot]andGitHub d29b4e2ee2 chore(deps): update actions/setup-java action to v4.2.0 2024-03-13 14:30:50 +00:00
renovate[bot]andGitHub 64fb1235d5 chore(deps): update github/codeql-action action to v3.24.7 2024-03-12 19:00:05 +00:00
Harsh Shandilya d46993aaf6 fix(deps): bump Compose Compiler to 1.5.11-dev-k1.9.23-96ef9dc6af1 2024-03-12 18:59:05 +05:30
renovate[bot]andGitHub 310db93ff0 chore(deps): update kotlin and compose 2024-03-12 13:27:21 +00:00
Harsh Shandilya f07a5682a1 Revert "fix(renovate): temporarily disable Kotlin group"
This reverts commit f54d790da4.
2024-03-12 18:56:23 +05:30
Harsh Shandilya bcde4b9719 fix(ci): build internal flavor for CodeQL 2024-03-11 07:46:01 +05:30
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
e2e2f4f574 chore(deps): update mindsers/changelog-reader-action action to v2.2.3 (#482)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[mindsers/changelog-reader-action](https://togithub.com/mindsers/changelog-reader-action)
| action | patch | `v2.2.2` -> `v2.2.3` |

---

### Release Notes

<details>
<summary>mindsers/changelog-reader-action
(mindsers/changelog-reader-action)</summary>

###
[`v2.2.3`](https://togithub.com/mindsers/changelog-reader-action/releases/tag/v2.2.3)

[Compare
Source](https://togithub.com/mindsers/changelog-reader-action/compare/v2.2.2...v2.2.3)

##### Fixed

-   Upgrade dependencies to solve deprecation issues.
-   Use node v20
-   Remove useless empty line between links in the body of a version

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yMzAuMCIsInVwZGF0ZWRJblZlciI6IjM3LjIzMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-11 00:47:49 +00:00
Harsh Shandilya a42139ae1e fix(ci): upload Sentry mappings from Tramline releases 2024-03-08 22:57:41 +05:30
Harsh Shandilya 5d0e56f115 fix(build): catch up on SentryExtension changes 2024-03-08 22:57:41 +05:30
renovate[bot]andGitHub fa31e300e9 fix(deps): update sentry to v7.6.0 2024-03-08 14:31:16 +00:00
Harsh Shandilya f54d790da4 fix(renovate): temporarily disable Kotlin group 2024-03-08 17:22:02 +05:30
GitHub Actions 96c8a0450e feat(release): start next development iteration 2024-03-07 19:47:35 +00:00
GitHub Actions 886cd65a32 feat(release): bump version 2024-03-07 19:44:46 +00:00
Harsh Shandilya 8c8dd93136 chore: update changelog 2024-03-08 00:59:37 +05:30
Harsh Shandilya 9110244236 fix(deps): downgrade androidx.lifecycle back to stable
For inexplicable reasons the latest Lifecycle libraries request storage access and phone state permissions

Fixes #475
2024-03-08 00:57:34 +05:30
GitHub Actions 56f0ceddb6 feat(release): start next development iteration 2024-03-07 08:06:37 +00:00
GitHub Actions c07752df4a feat(release): bump version 2024-03-07 08:02:41 +00:00
Harsh Shandilya 3f18160dd0 fix(android): ensure import flow updates saved posts list 2024-03-07 12:49:03 +05:30
Harsh Shandilya 0c3dc00137 chore: update changelog 2024-03-07 11:53:17 +05:30
Harsh Shandilya 4fb66975fb fix(common): adopt new elevation guidelines 2024-03-07 11:41:44 +05:30
Harsh Shandilya dc584a300d fix(deps): bump dev.chrisbanes.compose:compose-bom to 2024.03.00-alpha01 2024-03-07 11:27:48 +05:30
renovate[bot]andGitHub 30121d6d88 fix(deps): update androidx 2024-03-06 19:00:23 +00:00
renovate[bot]andGitHub 2a97576e37 fix(deps): update dependency eu.bambooapps:compose-material3-pullrefresh to v1.1.1 2024-03-06 14:30:43 +00:00
Harsh Shandilya 32a59d0104 refactor(build): remove uses of internal AGP APIs 2024-03-05 22:45:46 +05:30
Harsh Shandilya a161769cbd chore: refresh Lint baselines 2024-03-05 19:12:58 +05:30
Harsh Shandilya 9a6d7d267a feat(build): add androidx.lint checks to build-logic 2024-03-05 19:12:58 +05:30
renovate[bot]andGitHub 9298fa9ea0 fix(deps): update dependency com.michael-bull.kotlin-result:kotlin-result-coroutines to v1.1.20 2024-03-04 00:35:51 +00:00
renovate[bot]andGitHub f0bd943607 fix(deps): update dependency com.michael-bull.kotlin-result:kotlin-result-coroutines to v1.1.19 2024-03-03 03:53:58 +00:00
Harsh Shandilya 30474377fc Revert "chore(build): move Tramline releases to Buildkansen"
This reverts commit 17c7313f41.
2024-03-01 19:55:41 +05:30
renovate[bot]andGitHub 6d04230dc6 fix(deps): update sentry to v7.5.0 2024-03-01 13:23:18 +00:00
renovate[bot]andGitHub 19f408b6cd fix(deps): update dependency com.google.truth:truth to v1.4.2 2024-03-01 00:30:53 +00:00
renovate[bot]andGitHub ad528792fa chore(deps): update agp to v8.3.0 2024-02-29 20:05:01 +00:00
renovate[bot]andGitHub 78e34a0042 chore(deps): update github/codeql-action action to v3.24.6 2024-02-29 14:30:53 +00:00
Harsh Shandilya 83ba17dea3 fix(ci): rework job conditions 2024-02-29 19:18:54 +05:30
Harsh Shandilya fcca85c51a fix(ci): move all workflows to macOS 14 runners
Just for keks™️
2024-02-29 18:45:25 +05:30
Harsh Shandilya 17c7313f41 chore(build): move Tramline releases to Buildkansen
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2024-02-29 18:01:35 +05:30
Harsh Shandilya 97126da808 fix(deps): upgrade richtext to 1.0.0-alpha01 2024-02-29 18:01:35 +05:30
Harsh Shandilya fdf891c8eb fix(build): disable ObsoleteLintCustomCheck lint
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2024-02-29 18:01:35 +05:30
Harsh Shandilya af7c54203f Merge remote-tracking branches 'origin/renovate/sentry' and 'origin/renovate/kotlin-and-compose'
* origin/renovate/sentry:
  fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.3.1

* origin/renovate/kotlin-and-compose:
  chore(deps): update plugin ksp to v1.9.22-1.0.18
2024-02-29 10:44:20 +05:30
renovate[bot]andGitHub 334cf11b82 chore(deps): update plugin ksp to v1.9.22-1.0.18 2024-02-29 03:53:22 +00:00
renovate[bot]andGitHub a9ba948d12 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.3.1 2024-02-28 14:30:34 +00:00
Harsh Shandilya 1e29a866a0 fix(deps): bump anvil to 2.5.0-beta03 2024-02-28 15:41:26 +05:30
renovate[bot]andGitHub 693713eb8d chore(deps): update aboutlibraries to v11.1.0 2024-02-28 09:36:36 +00:00
renovate[bot]andGitHub 1b6c6af3c4 chore(deps): update actions/setup-java action to v4.1.0 2024-02-28 06:34:02 +00:00
renovate[bot]andGitHub 61b0ac83f0 fix(deps): update dagger to v2.51 2024-02-27 19:47:02 +00:00
renovate[bot]andGitHub bce435e3d2 fix(deps): update konvert to v3.0.1 2024-02-26 11:13:45 +00:00
renovate[bot]andGitHub 833b3cd927 fix(deps): update coil to v2.6.0 2024-02-23 22:28:55 +00:00
renovate[bot]andGitHub a6a3b2a0e4 chore(deps): update github/codeql-action action to v3.24.5 2024-02-23 13:50:20 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
73e0b4927f chore(deps): update github/codeql-action action to v3.24.4 (#461)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-22 22:38:33 +05:30
Harsh Shandilya b68d58c19d fix(gradle): force use of new resolver for VCU 2024-02-22 13:47:04 +05:30
Harsh Shandilya 3bccc8748d feat(build): add internal build type
Allows testing release builds in parallel with Play Store
2024-02-22 13:47:04 +05:30
Harsh Shandilya f115fd8dda fix(build): remove obsolete workaround 2024-02-22 13:34:29 +05:30
Harsh Shandilya 954ef90d99 chore(deps): update androidx 2024-02-22 13:30:33 +05:30
Harsh Shandilya 65f7013e78 chore: refresh lint baseline 2024-02-22 11:13:57 +05:30
renovate[bot]andGitHub af799e0165 fix(deps): update dependency dev.chrisbanes.compose:compose-bom to v2024.02.00-alpha02 2024-02-22 01:22:02 +00:00
renovate[bot]andGitHub c4fb53e09d fix(deps): update sentry to v7.4.0 2024-02-21 14:30:37 +00:00
renovate[bot]andGitHub 982497a83f chore(deps): update actions/dependency-review-action digest to 9129d7d 2024-02-20 19:25:55 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
165c0eaaed chore(deps): update aboutlibraries to v11.1.0-b03 (#455)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| com.mikepenz.aboutlibraries.plugin | `11.1.0-b01` -> `11.1.0-b03` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.mikepenz.aboutlibraries.plugin/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.mikepenz.aboutlibraries.plugin/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.mikepenz.aboutlibraries.plugin/11.1.0-b01/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.mikepenz.aboutlibraries.plugin/11.1.0-b01/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[com.mikepenz:aboutlibraries-compose-m3](https://togithub.com/mikepenz/AboutLibraries)
| `11.1.0-b01` -> `11.1.0-b03` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.0-b01/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/com.mikepenz:aboutlibraries-compose-m3/11.1.0-b01/11.1.0-b03?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>mikepenz/AboutLibraries
(com.mikepenz:aboutlibraries-compose-m3)</summary>

###
[`v11.1.0-b03`](https://togithub.com/mikepenz/AboutLibraries/releases/tag/v11.1.0-b03)

#### 💬 Other

-   Fix CI for releases on macOS-14 runner
- PR:
[#&#8203;960](https://togithub.com/mikepenz/AboutLibraries/issues/960)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xOTEuMCIsInVwZGF0ZWRJblZlciI6IjM3LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-20 10:10:11 +00:00
renovate[bot]andGitHub 2c62515746 chore(deps): update actions/dependency-review-action digest to be8bc50 2024-02-19 19:24:01 +00:00
renovate[bot]andGitHub 376c2f138c chore(deps): update actions/dependency-review-action digest to fd07d42 2024-02-19 09:27:26 +00:00
renovate[bot]andGitHub d271dd3733 fix(deps): update serialization to v1.6.3 2024-02-16 21:41:06 +00:00
renovate[bot]andGitHub 0c36875502 fix(deps): update dependency com.google.truth:truth to v1.4.1 2024-02-16 18:45:08 +00:00
renovate[bot]andGitHub b31521affa fix(deps): update coroutines to v1.8.0 2024-02-15 16:46:08 +00:00
renovate[bot]andGitHub 488880ee35 chore(deps): update github/codeql-action action to v3.24.3 2024-02-15 12:56:12 +00:00
renovate[bot]andGitHub f2065d897b chore(deps): update actions/dependency-review-action digest to 80f10bf 2024-02-14 11:01:51 +00:00
renovate[bot]andGitHub e83b87be6c chore(deps): update agp to v8.3.0-rc02 2024-02-14 01:35:23 +00:00
renovate[bot]andGitHub 993b45034e chore(deps): update gradle/actions digest to 417ae3c 2024-02-13 23:02:17 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
9d6d497185 chore(deps): update github/codeql-action action to v3.24.1 (#451)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github/codeql-action](https://togithub.com/github/codeql-action) |
action | patch | `v3.24.0` -> `v3.24.1` |

---

### Release Notes

<details>
<summary>github/codeql-action (github/codeql-action)</summary>

###
[`v3.24.1`](https://togithub.com/github/codeql-action/compare/v3.24.0...v3.24.1)

[Compare
Source](https://togithub.com/github/codeql-action/compare/v3.24.0...v3.24.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xNzMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjE3My4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-13 16:38:34 +00:00
Harsh Shandilya 719d317263 fix(gradle): downgrade Glance back to v1.0.0
This is resulting in some weird miscompilation that results
in release builds having an unitialized `viewModel` field in
`WidgetReceiver` which indicates a miscompilation of the
Whetstone code surrounding it.
2024-02-13 22:01:14 +05:30
Harsh Shandilya 8d78e1910a refactor(android): centralize widget display logic 2024-02-13 22:01:14 +05:30
renovate[bot]andGitHub 62f643135b chore(deps): update plugin licensee to v1.9.1 2024-02-12 16:56:19 +00:00
renovate[bot]andGitHub 595a8f7dfe fix(deps): update dependency com.slack.eithernet:eithernet to v1.8.1 2024-02-12 04:03:03 +00:00
renovate[bot]andGitHub 1d7be62857 fix(deps): update dependency org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin to v3.0.1 2024-02-09 22:23:02 +00:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
f86cdb0e62 fix(deps): update dependency io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin to v4.3.0 (#446)
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin](https://togithub.com/getsentry/sentry-android-gradle-plugin)
| `4.2.0` -> `4.3.0` |
[![age](https://developer.mend.io/api/mc/badges/age/maven/io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin/4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin/4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin/4.2.0/4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin/4.2.0/4.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>getsentry/sentry-android-gradle-plugin
(io.sentry.android.gradle:io.sentry.android.gradle.gradle.plugin)</summary>

###
[`v4.3.0`](https://togithub.com/getsentry/sentry-android-gradle-plugin/blob/HEAD/CHANGELOG.md#430)

[Compare
Source](https://togithub.com/getsentry/sentry-android-gradle-plugin/compare/4.2.0...4.3.0)

##### Fixes

- Bundle ASM version within the plugin and bump it to `9.4`
([#&#8203;637](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/637))
- This should fix the `java.lang.AssertionError: Class with incorrect id
found` exception when using `kotlinx.serialization`
- Fall back to `findTask` if `assembleProvider` of AndroidVariant is
null when hooking source bundle and native symbols upload tasks
([#&#8203;639](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/639))
- Hook source context tasks to also run after `install{Variant}` tasks
([#&#8203;643](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/643))
- Do not run sentry-cli commands if telemetry is disabled
([#&#8203;648](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/648))
- Proguard and source context tasks don't run on every build
([#&#8203;634](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/634))
- Proguard UUID task now depends on the proguard mapping file. I.e. it
will only run if the mapping file has changed
- Source context tasks now depend on source file changes, if there are
no source changes, the tasks won't run

##### Dependencies

- Bump CLI from v2.25.0 to v2.28.0
([#&#8203;638](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/638),
[#&#8203;640](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/640),
[#&#8203;642](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/642),
[#&#8203;647](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/647),
[#&#8203;652](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/652))
-
[changelog](https://togithub.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#2280)
-
[diff](https://togithub.com/getsentry/sentry-cli/compare/2.25.0...2.28.0)
Bump Android SDK from v7.2.0 to v7.3.0
([#&#8203;646](https://togithub.com/getsentry/sentry-android-gradle-plugin/pull/646))

[changelog](https://togithub.com/getsentry/sentry-java/blob/main/CHANGELOG.md#730)

[diff](https://togithub.com/getsentry/sentry-java/compare/7.2.0...7.3.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/msfjarvis/compose-lobsters).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xNzMuMCIsInVwZGF0ZWRJblZlciI6IjM3LjE3My4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 22:13:39 +00:00
renovate[bot]andGitHub ffc525a1ad chore(deps): update r0adkll/upload-google-play action to v1.1.3 2024-02-09 12:48:52 +00:00
renovate[bot]andGitHub de6b13fbfc fix(deps): update dependency eu.bambooapps:compose-material3-pullrefresh to v1.1.0 2024-02-08 18:09:12 +00:00
Harsh Shandilya e949ee0bb6 fix(deps): bump glance and profileinstaller 2024-02-08 11:29:51 +05:30
Harsh Shandilya 9f4caa7f62 Revert "refactor: remove unused versions plugin"
This reverts commit 9fb8e17cf6.
2024-02-08 11:29:51 +05:30
Harsh Shandilya a334eebe74 fix(deps): update dev.chrisbanes.compose:compose-bom to 2024.02.00-alpha01 2024-02-08 11:13:58 +05:30
renovate[bot]andGitHub fd30320ed6 chore(deps): update androidx 2024-02-07 18:58:49 +00:00
Harsh Shandilya c293fced8a fix(android): relax constraints on post update worker 2024-02-07 00:24:35 +05:30
Harsh Shandilya fa57bc9695 refactor(android): consistently use repository layer 2024-02-07 00:16:06 +05:30
renovate[bot]andGitHub 1d1c7a36b6 chore(deps): update actions/upload-artifact action to v4.3.1 2024-02-05 22:52:07 +00:00
renovate[bot]andGitHub 682377f6c5 chore(deps): update dependency com.android.test to v8.3.0-rc01 2024-02-05 18:09:44 +00:00
Harsh Shandilya a8d637e589 chore: update changelog 2024-02-05 17:03:21 +05:30
Harsh Shandilya 9e2564f352 chore: refresh baseline profiles 2024-02-04 16:02:20 +05:30
renovate[bot]andGitHub eb17c20be8 fix(deps): update junit5 monorepo to v5.10.2 2024-02-04 09:56:24 +00:00
renovate[bot]andGitHub e878699e2a fix(deps): update dependency me.saket.swipe:swipe to v1.3.0 2024-02-04 08:14:47 +00:00
renovate[bot]andGitHub 9dc0b5cd13 fix(deps): update dependency com.google.truth:truth to v1.4.0 2024-02-02 23:18:34 +00:00
renovate[bot]andGitHub 875453cce5 chore(deps): update github/codeql-action action to v3.24.0 2024-02-02 18:40:55 +00:00
Harsh Shandilya 82a1ba9ac3 fix(build): use new Gradle API for task matching 2024-02-02 23:55:40 +05:30
Harsh Shandilya ff4a09e41b fix(deps): update Gradle to 8.6 2024-02-02 23:51:49 +05:30
renovate[bot]andGitHub 6b670ad3e5 chore(deps): pin gradle/actions action to ec92e82 2024-01-31 15:54:35 +00:00
Harsh Shandilya 2bf7ccc952 chore(deps): upgrade gradle/actions/setup-gradle to v3 2024-01-31 21:22:08 +05:30
renovate[bot]andGitHub d25476be11 fix(deps): update sentry to v7.3.0 2024-01-30 10:46:26 +00:00
Harsh Shandilya 6d7e2bc7aa fix(ci): bump setup-gradle action 2024-01-30 16:15:11 +05:30
Harsh Shandilya b1148679e3 refactor: workaround poor read/saved state management
I need a fresh set of eyes on this absolute mess
2024-01-30 01:36:00 +05:30
Harsh Shandilya 6a9cd40eaf fix(deps): update androidx.test and Licensee 2024-01-30 00:47:07 +05:30
Harsh Shandilya bd16709a81 chore: add Google Play Open Testing channel to README 2024-01-30 00:04:32 +05:30
Harsh Shandilya cbd7f2fca4 refactor: improve read posts search performance 2024-01-29 18:20:27 +05:30
Harsh Shandilya 89b821ebf1 fix(ci): rename snapshot tag back to latest
The 'nightly' name is being used by the Tramline branch now
2024-01-28 14:06:09 +05:30
Harsh Shandilya 3fc0f891d4 fix(ci): setup signing secrets in Tramline workflow 2024-01-28 14:04:03 +05:30
Harsh Shandilya 74a7835a53 refactor(android): switch over to PagingData transformations 2024-01-27 19:55:03 +05:30
Harsh Shandilya 051b7ab2bb chore(ci): migrate to new Gradle actions 2024-01-27 16:27:12 +05:30
Harsh Shandilya 38f71460f0 refactor(build): defer semver parsing to task execution 2024-01-27 15:02:15 +05:30
Harsh Shandilya 1ab1520c60 feat(build): add support for Tramline builds 2024-01-27 14:03:58 +05:30
Harsh Shandilya 0e5caf591a refactor: replace semver4j with jsemver 2024-01-27 13:18:32 +05:30
Harsh Shandilya ad2582a28e fix(build): bump About Libraries, Coroutines and WorkManager 2024-01-26 21:26:29 +05:30
renovate[bot]andGitHub c9d89f493d chore(deps): update github/codeql-action action to v3.23.2 2024-01-26 15:07:32 +00:00
renovate[bot]andGitHub 8669e3f780 chore(deps): update plugin com.gradle.enterprise to v3.16.2 2024-01-26 13:49:40 +00:00
Harsh Shandilya e7d5676cb5 refactor: address issues from compose-lint 1.3.x 2024-01-26 14:54:21 +05:30
renovate[bot]andGitHub 800bffbf24 fix(deps): update dependency com.slack.lint.compose:compose-lint-checks to v1.3.1 2024-01-26 01:18:23 +00:00
renovate[bot]andGitHub 17c02c2a25 fix(deps): update dependency com.slack.lint.compose:compose-lint-checks to v1.3.0 2024-01-25 20:33:42 +00:00
renovate[bot]andGitHub 89db5e3b3f chore(deps): update gradle/gradle-build-action action to v2.12.0 2024-01-25 01:36:13 +00:00
Harsh Shandilya 1524eb23d4 chore: refresh baseline profiles 2024-01-25 01:41:57 +05:30
Harsh Shandilya d7dd2eb611 feat(benchmark): use real devices baseline profile generation
Emulators are pretty unstable for this
2024-01-25 01:41:57 +05:30
Harsh Shandilya a3e150fdd9 fix(build): add missing inclusion for baseline profile generation 2024-01-25 01:32:12 +05:30
Harsh Shandilya fa2868edd6 fix(deps): update all AndroidX libraries to latest unstable 2024-01-25 01:19:05 +05:30
renovate[bot]andGitHub e3e62b62ad chore(deps): update androidx to v1.2.3 2024-01-24 18:26:53 +00:00
renovate[bot]andGitHub a071a65ecc chore(deps): update actions/upload-artifact action to v4.3.0 2024-01-23 19:48:31 +00:00
GitHub Actions 65e033cc80 feat(release): start next development iteration 2024-01-23 17:23:09 +00:00
118 changed files with 12159 additions and 20621 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 311 KiB

+11 -2
View File
@@ -7,6 +7,11 @@
"github>msfjarvis/shared-workflows//renovate/automerge"
],
"branchConcurrentLimit": 15,
"github-actions": {
"fileMatch": [
".github/reusable-workflows/.+\\.ya?ml$",
],
},
"packageRules": [
{
matchDatasources: [
@@ -33,8 +38,6 @@
"matchPackagePatterns": [
"^androidx.*",
],
"matchPackageNames": [
],
"groupName": "AndroidX"
},
{
@@ -50,6 +53,12 @@
],
"allowedVersions": "!/.*-1-8$/",
},
{
"matchPackagePatterns": [
"^androidx.glance",
],
"allowedVersions": "<=1.0.0",
},
],
"regexManagers": [
{
@@ -0,0 +1,42 @@
name: 'Setup Gradle'
description: 'Checks out the repository and sets up Java and Gradle'
inputs:
token:
description: 'token input for actions/checkout'
required: false
default: ${{ github.token }}
fetch-depth:
description: 'fetch-depth input for actions/checkout'
required: false
default: 1
cache-read-only:
description: 'cache-read-only input for gradle/actions/setup-gradle'
required: false
default: ${{ github.event.repository != null && github.ref_name != github.event.repository.default_branch }}
dependency-graph:
description: 'dependency-graph input for gradle/actions/setup-gradle'
required: false
default: 'disabled'
runs:
using: "composite"
steps:
- name: Checkout repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
fetch-depth: ${{ inputs.fetch-depth }}
token: ${{ inputs.token }}
- name: Set up JDK
uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
with:
distribution: temurin
java-version: 22
- name: Setup Gradle
uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3
with:
gradle-home-cache-cleanup: true
cache-read-only: ${{ inputs.cache-read-only }}
add-job-summary: always
dependency-graph: ${{ inputs.dependency-graph }}
validate-wrappers: true
+17 -72
View File
@@ -16,97 +16,42 @@ concurrency:
jobs:
check:
runs-on: ubuntu-latest
runs-on: macos-14
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup build environment
uses: msfjarvis/compose-lobsters/.github/reusable-workflows/setup-gradle@main
with:
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
with:
distribution: temurin
java-version: 18
- name: Run unit tests
uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1
with:
arguments: --no-configuration-cache --stacktrace check -PslimTests
gradle-home-cache-cleanup: true
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
dependency-graph: generate-and-submit
- name: Check changelog format
uses: mindsers/changelog-reader-action@32aa5b4c155d76c94e4ec883a223c947b2f02656 # v2.2.3
with:
path: ./CHANGELOG.md
validation_level: error
- name: Run unit tests
run: ./gradlew --no-configuration-cache --stacktrace check -PslimTests
- name: (Fail-only) Upload test report
if: failure()
uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: Test report
path: '**/build/reports/tests/**'
dependency-review:
runs-on: ubuntu-latest
runs-on: macos-14
if: "github.event_name == 'push' && github.event.ref != 'refs/heads/main'"
needs:
- check
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- name: Dependency Review
uses: actions/dependency-review-action@4cd9eb2d23752464a87e00499c30d256a59a01b4 # v4
uses: actions/dependency-review-action@0c155c5e8556a497adf53f2c18edabf945ed8e70 # v4
with:
base-ref: refs/heads/main
head-ref: ${{ github.ref }}
validate-changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Check changelog format
uses: mindsers/changelog-reader-action@b97ce03a10d9bdbb07beb491c76a5a01d78cd3ef # v2.2.2
with:
path: ./CHANGELOG.md
validation_level: error
deploy-release-snapshot:
runs-on: ubuntu-latest
if: "github.event_name == 'push' && github.event.ref == 'refs/heads/main'"
needs:
- check
- validate-changelog
- dependency-review
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up JDK
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
with:
distribution: temurin
java-version: 18
- name: Decrypt secrets
run: |
./scripts/setup-age.sh
./scripts/signing-setup.sh "$AGE_SECRET_KEY"
env:
AGE_SECRET_KEY: ${{ secrets.AGE_SECRET_KEY }}
- name: Build release app
uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1
env:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
with:
arguments: --no-configuration-cache --stacktrace collectReleaseApks
gradle-home-cache-cleanup: true
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Clean secrets
run: scripts/signing-cleanup.sh
- name: Deploy snapshot
run: scripts/deploy-snapshot.sh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+11 -32
View File
@@ -20,25 +20,16 @@ permissions:
jobs:
codeql:
name: CodeQL
runs-on: ubuntu-latest
runs-on: macos-14
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up JDK
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
- name: Setup build environment
uses: msfjarvis/compose-lobsters/.github/reusable-workflows/setup-gradle@main
with:
distribution: temurin
java-version: 18
- name: Setup Gradle caching
uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1
with:
gradle-home-cache-cleanup: true
fetch-depth: 0
cache-read-only: true
- name: Initialize CodeQL
uses: github/codeql-action/init@0b21cf2492b6b02c465a3e5d7c473717ad7721ba # v3.23.1
uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
with:
languages: java
tools: latest
@@ -47,10 +38,10 @@ jobs:
- name: Build project
shell: bash
run: |
./gradlew assembleDebug assembleRelease
./gradlew assembleDebug assembleInternal
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@0b21cf2492b6b02c465a3e5d7c473717ad7721ba # v3.23.1
uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
with:
category: "/language:java"
mobsfscan:
@@ -58,31 +49,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up JDK
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
with:
distribution: temurin
java-version: 18
- name: Setup Gradle caching
uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1
with:
gradle-home-cache-cleanup: true
cache-read-only: true
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- name: Setup python
uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5
with:
python-version: 3.8
- name: Run mobsfscan
uses: MobSF/mobsfscan@e29e85c36fa1aa950d7f1b1064345d94a70b2a28
uses: MobSF/mobsfscan@849b749e7f3244c7b4f418ff858a9fa4e1406115
with:
args: . --sarif --output results.sarif || true
- name: Upload mobsfscan report
uses: github/codeql-action/upload-sarif@0b21cf2492b6b02c465a3e5d7c473717ad7721ba # v3.23.1
uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
with:
sarif_file: results.sarif
+9 -20
View File
@@ -5,7 +5,7 @@ on:
inAppUpdatePriority:
description: 'In app update priority (0-5)'
type: number
default: "0"
default: 0
required: false
concurrency:
@@ -13,19 +13,14 @@ concurrency:
jobs:
publish-google-play-release:
runs-on: ubuntu-latest
runs-on: macos-14
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup build environment
uses: msfjarvis/compose-lobsters/.github/reusable-workflows/setup-gradle@main
with:
token: ${{ secrets.POST_RELEASE_GH_TOKEN }}
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
with:
distribution: temurin
java-version: 18
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Set up Git author
shell: bash
@@ -33,12 +28,6 @@ jobs:
git config user.name "GitHub Actions"
git config user.email noreply@github.com
- name: Setup Gradle caching
uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1
with:
gradle-home-cache-cleanup: true
cache-read-only: true
- name: Decrypt secrets
run: |
./scripts/setup-age.sh
@@ -54,7 +43,7 @@ jobs:
echo VERSION="${VERSION}" >> $GITHUB_ENV
- name: Update changelog
uses: msfjarvis/keep-a-changelog-new-release@bf43ae42f4e42f137572950af426efcf6e777207 # 2.1.0
uses: msfjarvis/keep-a-changelog-new-release@e60399f488b25149c0963a4e22fff928a9277ce7 # v2.2.0
with:
tag: v${{ env.VERSION }}
version: ${{ env.VERSION }}
@@ -70,14 +59,14 @@ jobs:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: |
./gradlew --no-configuration-cache collectReleaseApks collectReleaseBundle -PsentryUploadMappings
./gradlew --no-configuration-cache assembleRelease collectReleaseApks collectReleaseBundle -PenableSentry
- name: Clean secrets
run: scripts/signing-cleanup.sh
- name: Get changelog entry
id: changelog_reader
uses: mindsers/changelog-reader-action@b97ce03a10d9bdbb07beb491c76a5a01d78cd3ef # v2.2.2
uses: mindsers/changelog-reader-action@32aa5b4c155d76c94e4ec883a223c947b2f02656 # v2.2.3
with:
version: ${{ env.VERSION }}
path: ./CHANGELOG.md
@@ -91,7 +80,7 @@ jobs:
printf '%s' "${CHANGELOG}" >> distribution/whatsnew/whatsnew-en-GB
- name: Publish bundle to Google Play
uses: r0adkll/upload-google-play@9cf8fd30c9e616ec761db3b9abb2b0f15842ce58 # v1.1.2
uses: r0adkll/upload-google-play@935ef9c68bb393a8e6116b1575626a7f5be3a7fb # v1.1.3
with:
mappingFile: android/bundle/mapping.txt
packageName: dev.msfjarvis.claw.android
+41
View File
@@ -0,0 +1,41 @@
name: Android release build
on:
workflow_dispatch:
inputs:
versionName:
description: 'User-facing release version name'
required: true
default: ""
versionCode:
description: 'versionCode or build number'
required: true
default: ''
jobs:
signed-build:
runs-on: ubuntu-latest
steps:
- name: Setup build environment
uses: msfjarvis/compose-lobsters/.github/reusable-workflows/setup-gradle@main
with:
cache-read-only: true
- name: Build release app
run: |
./scripts/setup-age.sh
./scripts/signing-setup.sh "$AGE_SECRET_KEY"
./gradlew --no-configuration-cache --stacktrace assembleRelease collectReleaseBundle -PenableSentry
./scripts/signing-cleanup.sh
env:
AGE_SECRET_KEY: ${{ secrets.AGE_SECRET_KEY }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
ORG_GRADLE_PROJECT_VERSION_NAME: ${{ github.event.inputs.versionName }}
ORG_GRADLE_PROJECT_VERSION_CODE: ${{ github.event.inputs.versionCode }}
- name: Upload app bundle
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: release-aab
path: android/build/outputs/bundle/release/android-release.aab
+1
View File
@@ -247,3 +247,4 @@ keystore.properties
distribution/
screenshots/
claw-export.json
.kotlin/
+216 -153
View File
@@ -7,421 +7,484 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.48.0] - 2024-06-05
### Added
- Swiping a post from left to right now offers a share action
### Fixed
- Try to workaround an infrequent crash when scrolling hottest/newest posts
### Changed
- Upgrade to Kotlin 2.0.0
- Upgrade to Compose May beta releases
## [1.47.0] - 2024-05-14
### Changed
- Bring back dividers between posts (I regret my earlier choices)
- Upgrade to Compose May stable releases
### Fixed
- Navigating to user profiles now works when invoked from the search
results page
- Fix occasional crashes due to the app incorrectly trying to open
multiple database connections
## [1.46.0] - 2024-04-24
### Changed
- Remove dividers between posts
- Post titles in lists are now truncated to be a single line
### Fixed
- Disable logging of network errors to Sentry
- Add potential workaround for navigation-related crashes
## [1.45.0] - 2024-04-24
### Changed
- Upgrade to Compose April releases
- Story items are now more compact so you can see more items
on your screen.
### Fixed
- Fixed a crash when clicking an item on the bottom navigation bar
too quickly
- Removed buggy deeplinks
- Clicking a username now correctly navigates to the right page in-app
## [1.44.0] - 2024-03-19
### Fixed
- Fixed a bug in the database code that was triggering crashes for
a subset of upgrading users
## [1.43.0] - 2024-03-17
### Fixed
- Fix crash when trying to open a comments-only post from
the home screen widget
## [1.42.0] - 2024-03-16
### Fixed
- Adapt to changes in lobste.rs API
## [1.41.0] - 2024-03-07
### Fixed
- Downgrade dependency that was pulling in extraneous storage
permissions which the app does not require.
## [1.40.0] - 2024-03-07
### Changed
- Update to Compose March releases
- Improve performance of frequently invoked database queries
- Refactor UI data model to improve state handling
- Make saved posts update in the background more often
- Consolidate widget display logic
- Rework some theming logic to align with new Material guidelines
## [1.39.0] - 2024-01-23
### Changed
* Add HTML bookmarks as an export format
* Rework widget item layout for consistent touch targets
* Add attribution for libraries used in the app
* Redesign settings screen
* Update to Compose January releases
- Add HTML bookmarks as an export format
- Rework widget item layout for consistent touch targets
- Add attribution for libraries used in the app
- Redesign settings screen
- Update to Compose December releases
## [1.38.0] - 2023-11-20
### Changed
* Add brand new icon by dzuk
* Fix a bug that caused the app to fetch the same 20 posts over and over
* Significantly improve scrolling performance when there are a lot of saved posts
* Move search feature to its own screen
* Make top app and bottom system bars use the same color
* Reduce unnecessary API calls in search screen
* Upgrade to Compose November releases
* Enable logging of SQLite queries
- Add brand new icon by dzuk
- Fix a bug that caused the app to fetch the same 20 posts over and over
- Significantly improve scrolling performance when there are a lot of saved posts
- Move search feature to its own screen
- Make top app and bottom system bars use the same color
- Reduce unnecessary API calls in search screen
- Upgrade to Compose November releases
- Enable logging of SQLite queries
## [1.37.0] - 2023-10-06
### Changed
* Fixed a crash that infrequently happened in the comments page
* Fixed a crash when trying to list saved posts
* Fixed a crash in home screen widget when user had less than 50 saved posts
* Upgraded to Compose 1.6.0-alpha07
- Fixed a crash that infrequently happened in the comments page
- Fixed a crash when trying to list saved posts
- Fixed a crash in home screen widget when user had less than 50 saved posts
- Upgraded to Compose 1.6.0-alpha07
## [1.36.0] - 2023-10-04
### Added
* Introduce an initial attempt at a home screen widget
- Introduce an initial attempt at a home screen widget
### Changed
* Fixed a crash triggered when swiping items
* Adjusted pull to refresh component to match Material You theme
- Fixed a crash triggered when swiping items
- Adjusted pull to refresh component to match Material You theme
## [1.35.0] - 2023-09-19
### Changed
* Fixed missing vertical spacing between post tags
* Fixed user profile links not displaying correctly in-app
* Update to Compose October release
- Fixed missing vertical spacing between post tags
- Fixed user profile links not displaying correctly in-app
- Update to Compose October release
## [1.34.0] - 2023-08-30
### Added
* Add a swipe action on each story to open the comments page on `lobste.rs`
* Automatically mark posts as "read" and visually distinguish between them
- Add a swipe action on each story to open the comments page on `lobste.rs`
- Automatically mark posts as "read" and visually distinguish between them
### Changed
* Tweak list items to reduce vertical size and adjust colors
* Drop bogus workarounds for native library crashes
* Updated Jetpack Compose and SQLite
- Tweak list items to reduce vertical size and adjust colors
- Drop bogus workarounds for native library crashes
- Updated Jetpack Compose and SQLite
### Fixed
* Rework how comments are displayed to adapt to lobste.rs API change
- Rework how comments are displayed to adapt to lobste.rs API change
## [1.33.0] - 2023-07-31
### Changed
* Yet another attempt at fixing native library crashes
* Rework how baseline profiles are generated
- Yet another attempt at fixing native library crashes
- Rework how baseline profiles are generated
## [1.32.0] - 2023-07-27
### Changed
* Upgrade to AndroidX July 26 release
* Revert selectable text feature due to sporadic crashes
- Upgrade to AndroidX July 26 release
- Revert selectable text feature due to sporadic crashes
## [1.31.0] - 2023-07-25
### Added
* Added the ability to search for posts
* Text in the comments page is now selectable
- Added the ability to search for posts
- Text in the comments page is now selectable
### Changed
* Upgrade to Compose July release
* Upgrade to Kotlin 1.9.0
- Upgrade to Compose July release
- Upgrade to Kotlin 1.9.0
## [1.30.0] - 2023-07-02
### Changed
* Added another workaround for native library loading crash
- Added another workaround for native library loading crash
## [1.29.0] - 2023-06-08
### Added
* Backup and restore options for saved posts
- Backup and restore options for saved posts
### Fixed
* Spamming the comments button no longer causes it to be opened multiple times
* Saved posts screen now has a visual indication when you have nothing saved
* Iconography has been updated across the board to be more consistent
- Spamming the comments button no longer causes it to be opened multiple times
- Saved posts screen now has a visual indication when you have nothing saved
- Iconography has been updated across the board to be more consistent
## [1.28.0] - 2023-06-03
### Changed
* Navigation transitions have been slightly sped up
- Navigation transitions have been slightly sped up
### Fixed
* Add workaround for a native library loading crash observed on some devices
- 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
- 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`
- 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
- 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
- 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
- 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
- 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
- Fix bug that caused the app to crash on launch
## [1.20.0] - 2023-02-09
### Changed
* Upgrade dependencies
- 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
[Unreleased]: https://github.com/msfjarvis/compose-lobsters/compare/v1.39.0...HEAD
- Initial Play Store release
[Unreleased]: https://github.com/msfjarvis/compose-lobsters/compare/v1.48.0...HEAD
[1.48.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.47.0...v1.48.0
[1.47.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.46.0...v1.47.0
[1.46.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.45.0...v1.46.0
[1.45.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.44.0...v1.45.0
[1.44.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.43.0...v1.44.0
[1.43.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.42.0...v1.43.0
[1.42.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.41.0...v1.42.0
[1.41.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.40.0...v1.41.0
[1.40.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.39.0...v1.40.0
[1.39.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.38.0...v1.39.0
[1.38.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.37.0...v1.38.0
[1.37.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.36.0...v1.37.0
[1.36.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.35.0...v1.36.0
[1.35.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.34.0...v1.35.0
[1.34.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.33.0...v1.34.0
[1.33.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.32.0...v1.33.0
[1.32.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.31.0...v1.32.0
[1.31.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.30.0...v1.31.0
[1.30.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.29.0...v1.30.0
[1.29.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.28.0...v1.29.0
[1.28.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.27.0...v1.28.0
[1.27.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.26.0...v1.27.0
[1.26.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.25.0...v1.26.0
[1.25.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.24.0...v1.25.0
[1.24.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.23.0...v1.24.0
[1.23.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.22.0...v1.23.0
[1.22.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.21.0...v1.22.0
[1.21.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.20.0...v1.21.0
[1.20.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.19.0...v1.20.0
[1.19.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.18.0...v1.19.0
[1.18.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.17.0...v1.18.0
[1.17.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.16.0...v1.17.0
[1.16.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.15.0...v1.16.0
[1.15.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.13.0...v1.14.0
[1.13.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.12.0...v1.13.0
[1.12.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.11.0...v1.12.0
[1.11.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.10.0...v1.11.0
[1.10.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.9.0...v1.10.0
[1.9.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.8.0...v1.9.0
[1.8.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.7.0...1.8.0
[1.7.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/msfjarvis/compose-lobsters/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/msfjarvis/compose-lobsters/compare/29c374859b17c5fcef03585b8a01c00070de9097...v1.0.0
+8 -1
View File
@@ -8,7 +8,14 @@ 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).
<a href="https://android.izzysoft.de/repo/apk/dev.msfjarvis.claw.android">
<img src="./.github/izzy-badge.webp"
alt="Get it on IzzyOnDroid"
height="80" />
</a>
> [!NOTE]
> Daily builds are published to the Google Play 'Open Testing' channel (if there are any changes), which can be opted into via this link: [[Android]](https://play.google.com/store/apps/details?id=dev.msfjarvis.claw.android) [[Web]](https://play.google.com/apps/testing/dev.msfjarvis.claw.android)
<img src="https://github.com/msfjarvis/compose-lobsters/blob/main/.github/readme_feature_light.webp#gh-light-mode-only"
alt="A grid of screenshots from the app, in clockwise order: the main screen, the comments page, the search page and the saved posts page"
+30 -12
View File
@@ -16,24 +16,28 @@ plugins {
id("dev.msfjarvis.claw.sentry")
id("dev.msfjarvis.claw.versioning-plugin")
alias(libs.plugins.aboutlibraries)
alias(libs.plugins.android.junit5)
alias(libs.plugins.anvil)
alias(libs.plugins.modulegraphassert)
alias(libs.plugins.whetstone)
alias(libs.plugins.baselineprofile)
alias(libs.plugins.licensee)
alias(libs.plugins.tracelog)
alias(libs.plugins.kotlin.composeCompiler)
}
android {
namespace = "dev.msfjarvis.claw.android"
defaultConfig.applicationId = "dev.msfjarvis.claw.android"
defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
buildFeatures.compose = true
composeOptions {
useLiveLiterals = false
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
composeOptions { useLiveLiterals = false }
buildTypes.create("internal") {
matchingFallbacks += "release"
signingConfig = signingConfigs["debug"]
applicationIdSuffix = ".internal"
debuggable(true)
}
// kotlinx.serialization 1.6.0-RC regression
packagingOptions.resources.pickFirsts += "**/*.bin"
}
baselineProfile {
@@ -42,14 +46,15 @@ baselineProfile {
from(projects.benchmark.dependencyProject)
}
composeCompiler { enableStrongSkippingMode = true }
licensee {
allow("Apache-2.0")
allow("MIT")
ignoreDependencies("com.michael-bull.kotlin-result") { because("kotlin-result is ISC licensed") }
ignoreDependencies("org.commonmark") { because("Commonmark is BSD licensed") }
allowUrl("https://jsoup.org/license") { because("Jsoup is MIT licensed") }
allowUrl("https://opensource.org/licenses/isc-license.txt") {
because("kotlin-result is ISC licensed")
}
allowUrl("https://opensource.org/licenses/MIT") { because("That's the MIT license text") }
}
moduleGraphAssert {
@@ -70,38 +75,51 @@ dependencies {
implementation(platform(libs.okhttp.bom))
implementation(libs.aboutLibraries.m3)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.foundation)
implementation(libs.androidx.compose.glance)
implementation(libs.androidx.compose.glance.m3)
implementation(libs.androidx.compose.material.icons.extended)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.material3.window.size)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.text)
implementation(libs.androidx.compose.ui.util)
implementation(libs.androidx.core.splashscreen)
implementation(libs.androidx.lifecycle.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.paging.compose)
implementation(libs.androidx.profileinstaller)
implementation(libs.androidx.work.runtime)
implementation(libs.coil)
implementation(libs.copydown)
implementation(libs.dagger)
implementation(libs.jsoup)
implementation(libs.eithernet)
implementation(libs.javax.inject)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.material3.pulltorefresh)
implementation(libs.napier)
implementation(libs.okhttp.core)
implementation(libs.okhttp.loggingInterceptor)
implementation(libs.retrofit)
implementation(libs.sqldelight.extensions.coroutines)
implementation(libs.swipe)
implementation(libs.unfurl)
implementation(projects.api)
implementation(projects.common)
implementation(projects.core)
implementation(projects.database.core)
implementation(projects.database.impl)
implementation(projects.model)
implementation(projects.web)
kapt(libs.dagger.compiler)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.okhttp.mockwebserver)
addTestDependencies(project)
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.test.uiautomator)
androidTestImplementation(libs.leakcanary.android.test)
}
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.3.0-alpha16" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha16)" variant="all" version="8.3.0-alpha16">
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0)" variant="all" version="8.3.0">
<issue
id="VectorPath"
-20
View File
@@ -1,22 +1,2 @@
-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>
@@ -0,0 +1,13 @@
<!--
~ Copyright © 2021-2024 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.
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Performing the heap growth analysis in process requires more heap. -->
<application
android:largeHeap="true"/>
</manifest>
@@ -0,0 +1,59 @@
/*
* Copyright © 2024 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
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.google.common.truth.Truth.assertThat
import de.mannodermaus.junit5.ActivityScenarioExtension
import leakcanary.repeatingAndroidInProcessScenario
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
import shark.ObjectGrowthDetector
import shark.forAndroidHeap
class HeapGrowthCheck {
@JvmField
@RegisterExtension
val scenarioExtension = ActivityScenarioExtension.launch<MainActivity>()
private val detector = ObjectGrowthDetector.forAndroidHeap().repeatingAndroidInProcessScenario()
private lateinit var device: UiDevice
@BeforeEach
fun setUp() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
device = UiDevice.getInstance(instrumentation)
}
@Test
fun verify_heap_growth() {
val heapGrowth = detector.findRepeatedlyGrowingObjects { device.exploreScreens() }
assertThat(heapGrowth.growingObjects).isEmpty()
}
private companion object {
fun UiDevice.exploreScreens() {
listOf("HOTTEST", "NEWEST", "SAVED").forEach { tag ->
waitForObject(By.res(tag)).click()
waitForIdle()
}
}
private fun UiDevice.waitForObject(selector: BySelector, timeout: Long = 10_000L): UiObject2 {
if (wait(Until.hasObject(selector), timeout)) {
return findObject(selector)
}
error("Object with selector [$selector] not found")
}
}
}
@@ -0,0 +1,9 @@
<!--
~ Copyright © 2021-2024 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.
-->
<resources>
<string name="app_name">Claw 🤫</string>
</resources>
+9 -106
View File
@@ -11,7 +11,6 @@
<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"
@@ -32,108 +31,8 @@
<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:host="lobste.rs" />
<data android:pathPattern="/s/......" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/....../" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/....../...*" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/......" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/....../" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/....../...*" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/......" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/....../" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/s/....../...*" />
<data android:scheme="https" />
</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:host="lobste.rs" />
<data android:pathPattern="/u/......*" />
<data android:scheme="https" />
</intent-filter>
</activity>
<activity
android:name=".SearchActivity"
android:configChanges="colorMode|density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
@@ -161,6 +60,7 @@
android:value="androidx.startup"
tools:node="remove" />
</provider>
<receiver
android:name=".glance.WidgetReceiver"
android:exported="true">
@@ -171,6 +71,7 @@
android:name="android.appwidget.provider"
android:resource="@xml/saved_posts_widget_info" />
</receiver>
<!-- Required: set your sentry.io project identifier (DSN) -->
<meta-data
android:name="io.sentry.dsn"
@@ -178,17 +79,19 @@
<!-- enable automatic breadcrumbs for user interactions (clicks, swipes, scrolls) -->
<meta-data
android:name="io.sentry.traces.user-interaction.enable"
android:value="${enableSentry}" />
android:value="true" />
<meta-data
android:name="io.sentry.breadcrumbs.user-interaction"
android:value="${enableSentry}" />
android:value="true" />
<!-- enable screenshot for crashes -->
<meta-data
android:name="io.sentry.attach-screenshot"
android:value="${enableSentry}" />
android:value="true" />
<!-- enable view hierarchy for crashes -->
<meta-data
android:name="io.sentry.attach-view-hierarchy"
android:value="${enableSentry}" />
android:value="true" />
<!-- set the environment for this build -->
<meta-data android:name="io.sentry.environment" android:value="${sentryEnvironment}" />
</application>
</manifest>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -15,6 +15,7 @@ import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.platform.LocalUriHandler
import com.deliveryhero.whetstone.Whetstone
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
@@ -24,6 +25,7 @@ import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import javax.inject.Inject
/** A base class that encapsulates all activities used by Claw. */
@Stable
abstract class BaseActivity : ComponentActivity() {
@Inject lateinit var urlLauncher: UrlLauncher
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -23,8 +23,7 @@ import javax.inject.Inject
@ContributesAppInjector(generateAppComponent = true)
class ClawApplication : Application(), ApplicationComponentOwner {
override val applicationComponent by
lazy(LazyThreadSafetyMode.NONE) { GeneratedApplicationComponent.create(this) }
override val applicationComponent = GeneratedApplicationComponent.create(this)
@Inject lateinit var plugins: Set<@JvmSuppressWildcards AppPlugin>
@@ -34,19 +33,12 @@ class ClawApplication : Application(), ApplicationComponentOwner {
plugins.forEach { plugin -> plugin.apply(this) }
val postUpdateWorkRequest =
PeriodicWorkRequestBuilder<SavedPostUpdaterWorker>(POST_REFRESH_PERIOD, TimeUnit.HOURS)
.setConstraints(
Constraints.Builder()
.setRequiresCharging(false)
.setRequiresBatteryNotLow(true)
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresDeviceIdle(true)
.build()
)
.setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
.build()
WorkManager.getInstance(this)
.enqueueUniquePeriodicWork(
"updateSavedPosts",
ExistingPeriodicWorkPolicy.UPDATE,
ExistingPeriodicWorkPolicy.KEEP,
postUpdateWorkRequest,
)
}
@@ -28,44 +28,47 @@ import androidx.glance.text.Text
import androidx.glance.text.TextStyle
import dev.msfjarvis.claw.common.theme.DarkThemeColors
import dev.msfjarvis.claw.common.theme.LightThemeColors
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.UIPost
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
class SavedPostsWidget(private val posts: List<SavedPost>) : GlanceAppWidget() {
class SavedPostsWidget(private val posts: Flow<List<UIPost>>) : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
val postWindow = posts.first().take(50).toImmutableList()
provideContent {
GlanceTheme(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) GlanceTheme.colors
else ColorProviders(light = LightThemeColors, dark = DarkThemeColors)
) {
WidgetHost()
WidgetHost(postWindow)
}
}
}
@Composable
private fun WidgetHost() {
LazyColumn(
modifier =
GlanceModifier.fillMaxSize()
.background(GlanceTheme.colors.background)
.appWidgetBackground(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
item {
val style = MaterialTheme.typography.titleLarge
Text(
text = "Saved posts",
style =
TextStyle(
color = GlanceTheme.colors.onBackground,
fontSize = style.fontSize,
fontWeight = style.fontWeight.toGlance(),
fontStyle = style.fontStyle.toGlance(),
),
modifier = GlanceModifier.padding(vertical = 8.dp),
)
}
items(posts) { post -> WidgetListEntry(post = post) }
}
}
}
@Composable
fun WidgetHost(posts: ImmutableList<UIPost>, modifier: GlanceModifier = GlanceModifier) {
LazyColumn(
modifier =
modifier.fillMaxSize().background(GlanceTheme.colors.background).appWidgetBackground(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
item {
val style = MaterialTheme.typography.titleLarge
Text(
text = "Saved posts",
style =
TextStyle(
color = GlanceTheme.colors.onBackground,
fontSize = style.fontSize,
fontWeight = style.fontWeight.toGlance(),
fontStyle = style.fontStyle.toGlance(),
),
modifier = GlanceModifier.padding(vertical = 8.dp),
)
}
items(posts) { post -> WidgetListEntry(post = post) }
}
}
@@ -33,19 +33,20 @@ import androidx.glance.text.TextStyle
import dev.msfjarvis.claw.android.MainActivity
import dev.msfjarvis.claw.android.MainActivity.Companion.NAVIGATION_KEY
import dev.msfjarvis.claw.android.R
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.UIPost
private val destinationKey = Key<String>(NAVIGATION_KEY)
@Composable
@GlanceComposable
fun WidgetListEntry(post: SavedPost, modifier: GlanceModifier = GlanceModifier) {
fun WidgetListEntry(post: UIPost, modifier: GlanceModifier = GlanceModifier) {
val titleStyle = MaterialTheme.typography.titleMedium
val commentsAction =
actionStartActivity<MainActivity>(actionParametersOf(destinationKey to post.shortId))
// If the URL starts with a /, it's a relative URL and we should open the comments page directly.
val postAction =
if (post.url.isNotEmpty()) actionStartActivity(Intent(Intent.ACTION_VIEW, Uri.parse(post.url)))
else commentsAction
if (post.url.startsWith('/')) commentsAction
else actionStartActivity(Intent(Intent.ACTION_VIEW, Uri.parse(post.url)))
Box(modifier.padding(8.dp)) {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -68,7 +69,7 @@ fun WidgetListEntry(post: SavedPost, modifier: GlanceModifier = GlanceModifier)
)
Image(
provider = ImageProvider(R.drawable.ic_comment),
contentDescription = "${post.commentCount ?: 0} comments",
contentDescription = "${post.commentCount} comments",
modifier = GlanceModifier.padding(end = 4.dp).clickable(commentsAction),
)
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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,8 +14,6 @@ import com.deliveryhero.whetstone.Whetstone
import com.deliveryhero.whetstone.broadcastreceiver.ContributesBroadcastReceiverInjector
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
@ContributesBroadcastReceiverInjector
class WidgetReceiver : GlanceAppWidgetReceiver() {
@@ -23,7 +21,7 @@ class WidgetReceiver : GlanceAppWidgetReceiver() {
@Inject lateinit var viewModel: ClawViewModel
override val glanceAppWidget: GlanceAppWidget
get() = SavedPostsWidget(runBlocking { viewModel.savedPosts.first().take(50) })
get() = SavedPostsWidget(viewModel.savedPosts)
override fun onReceive(context: Context, intent: Intent) {
Whetstone.inject(this, context)
@@ -22,11 +22,11 @@ object MetadataExtractorModule {
fun provideUnfurlLogger(): UnfurlLogger {
return object : UnfurlLogger {
override fun log(message: String) {
Napier.d { message }
Napier.d(tag = "Unfurler") { message }
}
override fun log(e: Throwable, message: String) {
Napier.e(e) { message }
Napier.e(tag = "Unfurler", throwable = e) { message }
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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,10 +13,16 @@ import com.slack.eithernet.ApiResult.Success
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dev.msfjarvis.claw.android.viewmodel.ReadPostsRepository
import dev.msfjarvis.claw.android.viewmodel.SavedPostsRepository
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.UIPost
import dev.msfjarvis.claw.model.toUIPost
import java.io.IOException
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
class LobstersPagingSource
@@ -24,15 +30,33 @@ class LobstersPagingSource
constructor(
@Assisted private val remoteFetcher: RemoteFetcher<LobstersPost>,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
) : PagingSource<Int, LobstersPost>() {
private val savedPostsRepository: SavedPostsRepository,
private val readPostsRepository: ReadPostsRepository,
) : PagingSource<Int, UIPost>() {
private lateinit var savedPosts: List<String>
private lateinit var readPosts: List<String>
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, UIPost> {
if (!::savedPosts.isInitialized) {
savedPosts = savedPostsRepository.savedPosts.first().map(SavedPost::shortId)
}
if (!::readPosts.isInitialized) {
readPosts = readPostsRepository.readPosts.first()
}
val page = params.key ?: STARTING_PAGE_INDEX
return when (val result = withContext(ioDispatcher) { remoteFetcher.getItemsAtPage(page) }) {
is Success ->
LoadResult.Page(
itemsBefore = (page - 1) * PAGE_SIZE,
data = result.value,
data =
result.value.map {
it
.toUIPost()
.copy(
isSaved = savedPosts.contains(it.shortId),
isRead = readPosts.contains(it.shortId),
)
},
prevKey = if (page == STARTING_PAGE_INDEX) null else page - 1,
nextKey = page + 1,
)
@@ -43,7 +67,7 @@ constructor(
}
}
override fun getRefreshKey(state: PagingState<Int, LobstersPost>): Int? {
override fun getRefreshKey(state: PagingState<Int, UIPost>): Int? {
return state.anchorPosition?.let { anchorPosition ->
(anchorPosition / PAGE_SIZE).coerceAtLeast(STARTING_PAGE_INDEX)
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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,11 +14,16 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dev.msfjarvis.claw.android.paging.LobstersPagingSource.Companion.PAGE_SIZE
import dev.msfjarvis.claw.android.paging.LobstersPagingSource.Companion.STARTING_PAGE_INDEX
import dev.msfjarvis.claw.android.viewmodel.ReadPostsRepository
import dev.msfjarvis.claw.android.viewmodel.SavedPostsRepository
import dev.msfjarvis.claw.api.LobstersSearchApi
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.UIPost
import dev.msfjarvis.claw.model.toUIPost
import java.io.IOException
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
/**
@@ -33,14 +38,19 @@ constructor(
private val searchApi: LobstersSearchApi,
@Assisted private val queryProvider: () -> String,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
) : PagingSource<Int, LobstersPost>() {
override fun getRefreshKey(state: PagingState<Int, LobstersPost>): Int? {
return state.anchorPosition?.let { anchorPosition ->
(anchorPosition / PAGE_SIZE).coerceAtLeast(STARTING_PAGE_INDEX)
}
}
private val savedPostsRepository: SavedPostsRepository,
private val readPostsRepository: ReadPostsRepository,
) : PagingSource<Int, UIPost>() {
private lateinit var savedPosts: List<String>
private lateinit var readPosts: List<String>
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, UIPost> {
if (!::savedPosts.isInitialized) {
savedPosts = savedPostsRepository.savedPosts.first().map(SavedPost::shortId)
}
if (!::readPosts.isInitialized) {
readPosts = readPostsRepository.readPosts.first()
}
val searchQuery = queryProvider()
// If there is no query, we don't need to call the API at all.
if (searchQuery.isEmpty()) {
@@ -55,7 +65,15 @@ constructor(
val nextKey = if (result.value.isEmpty()) null else page + 1
LoadResult.Page(
itemsBefore = (page - 1) * PAGE_SIZE,
data = result.value,
data =
result.value.map {
it
.toUIPost()
.copy(
isSaved = savedPosts.contains(it.shortId),
isRead = readPosts.contains(it.shortId),
)
},
prevKey = if (page == STARTING_PAGE_INDEX) null else page - 1,
nextKey = nextKey,
)
@@ -68,6 +86,12 @@ constructor(
}
}
override fun getRefreshKey(state: PagingState<Int, UIPost>): Int? {
return state.anchorPosition?.let { anchorPosition ->
(anchorPosition / PAGE_SIZE).coerceAtLeast(STARTING_PAGE_INDEX)
}
}
@AssistedFactory
interface Factory {
fun create(queryProvider: () -> String): SearchPagingSource
@@ -1,50 +0,0 @@
/*
* Copyright © 2021-2024 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.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.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(
modifier: Modifier = Modifier,
navigationIcon: @Composable () -> Unit = {},
title: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
) {
TopAppBar(
title = title,
modifier = modifier.shadow(8.dp),
colors =
TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtNavigationBarElevation()
),
navigationIcon = navigationIcon,
actions = actions,
)
}
@DevicePreviews
@ThemePreviews
@Composable
fun ClawAppBarPreview() {
LobstersTheme { ClawAppBar(title = { Text("Claw", fontWeight = FontWeight.Bold) }) }
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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,7 @@ package dev.msfjarvis.claw.android.ui
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@@ -16,9 +17,8 @@ import dev.msfjarvis.claw.android.ui.navigation.Destinations
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LinkMetadata
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.UIPost
fun Context.getActivity(): ComponentActivity? {
return when (this) {
@@ -30,6 +30,7 @@ fun Context.getActivity(): ComponentActivity? {
@Composable
fun rememberPostActions(
context: Context,
urlLauncher: UrlLauncher,
navController: NavController,
viewModel: ClawViewModel,
@@ -49,21 +50,27 @@ fun rememberPostActions(
if (currentRoute != Destinations.Comments.route) navController.navigate(newRoute)
}
override fun viewCommentsPage(commentsUrl: String) {
// Post links from lobste.rs are of the form $baseUrl/s/$postId/$postTitle
// Interestingly, lobste.rs does not actually care for the value of $postTitle, and will
// happily accept both a missing as well as a completely arbitrary $postTitle. We
// leverage this to create a new URL format which looks like
// $baseUrl/s/$postId/$postTitle/r, and does not trigger our deeplinks,
// instead opening in the custom tab as we want it to.
urlLauncher.openUri(commentsUrl.replaceAfterLast('/', "r"))
override fun viewCommentsPage(post: UIPost) {
urlLauncher.openUri(post.commentsUrl)
}
override fun toggleSave(post: SavedPost) {
override fun toggleSave(post: UIPost) {
viewModel.toggleSave(post)
}
override suspend fun getComments(postId: String): LobstersPostDetails {
override fun share(post: UIPost) {
val sendIntent: Intent =
Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, post.url.ifEmpty { post.commentsUrl })
putExtra(Intent.EXTRA_TITLE, post.title)
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent)
}
override suspend fun getComments(postId: String): UIPost {
return viewModel.getPostComments(postId)
}
@@ -27,13 +27,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.ui.decorations.MonthHeader
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.UIPost
import kotlinx.collections.immutable.ImmutableMap
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun DatabasePosts(
items: ImmutableMap<String, List<SavedPost>>,
items: ImmutableMap<String, List<UIPost>>,
listState: LazyListState,
postActions: PostActions,
modifier: Modifier = Modifier,
@@ -54,12 +54,7 @@ fun DatabasePosts(
items.forEach { (month, posts) ->
stickyHeader(contentType = "month-header") { MonthHeader(label = month) }
items(items = posts, key = { it.shortId }, contentType = { "LobstersItem" }) { item ->
LobstersListItem(
item = item,
isSaved = { true },
isRead = { false },
postActions = postActions,
)
LobstersListItem(item = item, refresh = {}, postActions = postActions)
HorizontalDivider()
}
}
@@ -8,40 +8,37 @@ package dev.msfjarvis.claw.android.ui.lists
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Reply
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import dev.msfjarvis.claw.common.posts.LobstersCard
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.UIPost
import me.saket.swipe.SwipeAction
import me.saket.swipe.SwipeableActionsBox
@Composable
fun LobstersListItem(
item: SavedPost,
isSaved: (SavedPost) -> Boolean,
isRead: suspend (String) -> Boolean,
item: UIPost,
postActions: PostActions,
refresh: () -> Unit,
modifier: Modifier = Modifier,
) {
val read by produceState(false, item.shortId) { value = isRead(item.shortId) }
val commentsAction =
SwipeAction(
icon = rememberVectorPainter(Icons.AutoMirrored.Filled.Reply),
background = MaterialTheme.colorScheme.tertiary,
onSwipe = { postActions.viewCommentsPage(item.commentsUrl) },
onSwipe = { postActions.viewCommentsPage(item) },
)
SwipeableActionsBox(endActions = listOf(commentsAction)) {
LobstersCard(
post = item,
isSaved = isSaved(item),
isRead = read,
postActions = postActions,
modifier = modifier,
val shareAction =
SwipeAction(
icon = rememberVectorPainter(Icons.Filled.Share),
background = MaterialTheme.colorScheme.tertiary,
onSwipe = { postActions.share(item) },
)
SwipeableActionsBox(startActions = listOf(shareAction), endActions = listOf(commentsAction)) {
LobstersCard(post = item, postActions = postActions, refresh = refresh, modifier = modifier)
}
}
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.Composable
@@ -21,32 +22,35 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.paging.LoadState
import androidx.paging.PagingData
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.posts.TEST_POST
import dev.msfjarvis.claw.common.posts.TEST_POST_ACTIONS
import dev.msfjarvis.claw.common.theme.LobstersTheme
import dev.msfjarvis.claw.common.ui.NetworkError
import dev.msfjarvis.claw.common.ui.ProgressBar
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.toSavedPost
import dev.msfjarvis.claw.common.ui.preview.DevicePreviews
import dev.msfjarvis.claw.model.UIPost
import eu.bambooapps.material3.pullrefresh.PullRefreshIndicator
import eu.bambooapps.material3.pullrefresh.pullRefresh
import eu.bambooapps.material3.pullrefresh.rememberPullRefreshState
import kotlinx.coroutines.flow.MutableStateFlow
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun NetworkPosts(
lazyPagingItems: LazyPagingItems<LobstersPost>,
lazyPagingItems: LazyPagingItems<UIPost>,
listState: LazyListState,
isPostSaved: (SavedPost) -> Boolean,
isPostRead: suspend (String) -> Boolean,
postActions: PostActions,
modifier: Modifier = Modifier,
) {
ReportDrawnWhen { lazyPagingItems.itemCount > 0 }
val refreshLoadState = lazyPagingItems.loadState.refresh
val isRefreshing = refreshLoadState == LoadState.Loading
val isRefreshing = refreshLoadState == LoadState.Loading && lazyPagingItems.itemCount == 0
val pullRefreshState = rememberPullRefreshState(isRefreshing, lazyPagingItems::refresh)
Box(modifier = modifier.fillMaxSize().pullRefresh(pullRefreshState)) {
if (lazyPagingItems.itemCount == 0 && refreshLoadState is LoadState.Error) {
@@ -59,19 +63,16 @@ fun NetworkPosts(
LazyColumn(state = listState) {
items(
count = lazyPagingItems.itemCount,
key = lazyPagingItems.itemKey { it.shortId },
key = lazyPagingItems.itemKey { item -> "${item.shortId}-${item.hashCode()}" },
contentType = lazyPagingItems.itemContentType { "LobstersItem" },
) { index ->
val item = lazyPagingItems[index]
if (item != null) {
val dbModel = item.toSavedPost()
LobstersListItem(
item = dbModel,
isSaved = isPostSaved,
isRead = isPostRead,
item = item,
postActions = postActions,
refresh = { lazyPagingItems.refresh() },
)
HorizontalDivider()
}
}
@@ -95,3 +96,17 @@ fun NetworkPosts(
)
}
}
@DevicePreviews
@Composable
private fun ListPreview() {
val items = List(20) { TEST_POST.copy(shortId = "${TEST_POST.shortId}${it}") }
val flow = MutableStateFlow(PagingData.from(items))
LobstersTheme {
NetworkPosts(
lazyPagingItems = flow.collectAsLazyPagingItems(),
listState = rememberLazyListState(),
postActions = TEST_POST_ACTIONS,
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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,15 +21,13 @@ import androidx.paging.PagingData
import androidx.paging.compose.collectAsLazyPagingItems
import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.ui.SearchBar
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.UIPost
import kotlinx.coroutines.flow.Flow
@Composable
fun SearchList(
items: Flow<PagingData<LobstersPost>>,
items: Flow<PagingData<UIPost>>,
listState: LazyListState,
isPostSaved: (SavedPost) -> Boolean,
postActions: PostActions,
searchQuery: String,
setSearchQuery: (String) -> Unit,
@@ -50,8 +48,6 @@ fun SearchList(
NetworkPosts(
lazyPagingItems = lazyPagingItems,
listState = listState,
isPostSaved = isPostSaved,
isPostRead = { false },
postActions = postActions,
)
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2024 Harsh Shandilya.
* Copyright © 2024 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,6 @@ 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.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -27,13 +26,14 @@ import androidx.compose.material.icons.filled.Whatshot
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.outlined.Whatshot
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -41,10 +41,9 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -58,14 +57,12 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import androidx.paging.compose.collectAsLazyPagingItems
import com.deliveryhero.whetstone.compose.injectedViewModel
import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
import dev.msfjarvis.claw.android.MainActivity
import dev.msfjarvis.claw.android.R
import dev.msfjarvis.claw.android.SearchActivity
import dev.msfjarvis.claw.android.ui.decorations.ClawAppBar
import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationBar
import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationRail
import dev.msfjarvis.claw.android.ui.decorations.NavigationItem
@@ -76,7 +73,6 @@ import dev.msfjarvis.claw.android.ui.navigation.ClawNavigationType
import dev.msfjarvis.claw.android.ui.navigation.Destinations
import dev.msfjarvis.claw.android.ui.rememberPostActions
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.urllauncher.UrlLauncher
@@ -85,7 +81,7 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.coroutines.launch
@OptIn(ExperimentalComposeUiApi::class)
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class)
@Composable
fun LobstersPostsScreen(
urlLauncher: UrlLauncher,
@@ -95,16 +91,16 @@ fun LobstersPostsScreen(
modifier: Modifier = Modifier,
viewModel: ClawViewModel = injectedViewModel(),
) {
val context = LocalContext.current
val hottestListState = rememberLazyListState()
val newestListState = rememberLazyListState()
val savedListState = rememberLazyListState()
val navController = rememberNavController()
val coroutineScope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
val postActions = rememberPostActions(urlLauncher, navController, viewModel)
val postActions = rememberPostActions(context, urlLauncher, navController, viewModel)
val backStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = backStackEntry?.destination?.route
val context = LocalContext.current
val hottestPosts = viewModel.hottestPosts.collectAsLazyPagingItems()
val newestPosts = viewModel.newestPosts.collectAsLazyPagingItems()
@@ -113,7 +109,7 @@ fun LobstersPostsScreen(
val navigationType = ClawNavigationType.fromSize(windowSizeClass.widthSizeClass)
val postIdOverride = context.getActivity()?.intent?.extras?.getString(MainActivity.NAVIGATION_KEY)
LaunchedEffect(false) {
LaunchedEffect(Unit) {
if (postIdOverride != null) {
navController.navigate(
Destinations.Comments.route.replace(Destinations.Comments.PLACEHOLDER, postIdOverride)
@@ -129,7 +125,9 @@ fun LobstersPostsScreen(
icon = Icons.Outlined.Whatshot,
selectedIcon = Icons.Filled.Whatshot,
) {
coroutineScope.launch { hottestListState.animateScrollToItem(index = 0) }
coroutineScope.launch {
if (hottestPosts.itemCount > 0) hottestListState.animateScrollToItem(index = 0)
}
},
NavigationItem(
label = "Newest",
@@ -137,7 +135,9 @@ fun LobstersPostsScreen(
icon = Icons.Outlined.NewReleases,
selectedIcon = Icons.Filled.NewReleases,
) {
coroutineScope.launch { newestListState.animateScrollToItem(index = 0) }
coroutineScope.launch {
if (newestPosts.itemCount > 0) newestListState.animateScrollToItem(index = 0)
}
},
NavigationItem(
label = "Saved",
@@ -145,13 +145,14 @@ fun LobstersPostsScreen(
icon = Icons.Outlined.FavoriteBorder,
selectedIcon = Icons.Filled.Favorite,
) {
coroutineScope.launch { savedListState.animateScrollToItem(index = 0) }
coroutineScope.launch { if (savedPosts.isNotEmpty()) savedListState.scrollToItem(0) }
},
)
Scaffold(
topBar = {
ClawAppBar(
TopAppBar(
modifier = Modifier.shadow(8.dp),
navigationIcon = {
if (
navController.previousBackStackEntry != null &&
@@ -165,19 +166,17 @@ fun LobstersPostsScreen(
contentDescription = "Go back to previous screen",
)
}
} else {
Icon(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = "The app icon for Claw",
modifier = Modifier.size(48.dp),
)
}
},
title = {
if (navItems.any { it.route == currentDestination }) {
Row(verticalAlignment = Alignment.CenterVertically) {
Image(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null,
modifier = Modifier.size(48.dp),
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurface),
)
Text(text = stringResource(R.string.app_name), fontWeight = FontWeight.Bold)
}
Text(text = stringResource(R.string.app_name), fontWeight = FontWeight.Bold)
}
},
actions = {
@@ -222,14 +221,11 @@ fun LobstersPostsScreen(
enterTransition = { fadeIn(animationSpec = tween(350)) },
exitTransition = { fadeOut(animationSpec = tween(350)) },
) {
val uri = LobstersApi.BASE_URL
composable(route = Destinations.Hottest.route) {
setWebUri("https://lobste.rs/")
NetworkPosts(
lazyPagingItems = hottestPosts,
listState = hottestListState,
isPostSaved = viewModel::isPostSaved,
isPostRead = viewModel::isPostRead,
postActions = postActions,
)
}
@@ -238,8 +234,6 @@ fun LobstersPostsScreen(
NetworkPosts(
lazyPagingItems = newestPosts,
listState = newestListState,
isPostSaved = viewModel::isPostSaved,
isPostRead = viewModel::isPostRead,
postActions = postActions,
)
}
@@ -250,11 +244,6 @@ fun LobstersPostsScreen(
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")) {
@@ -267,19 +256,31 @@ fun LobstersPostsScreen(
htmlConverter = htmlConverter,
getSeenComments = viewModel::getSeenComments,
markSeenComments = viewModel::markSeenComments,
openUserProfile = {
navController.navigate(
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, it)
)
},
)
}
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")) {
"Navigating to ${Destinations.User.route} without necessary 'username' argument"
}
setWebUri("https://lobste.rs/u/$username")
UserProfile(username = username, getProfile = viewModel::getUserProfile)
UserProfile(
username = username,
getProfile = viewModel::getUserProfile,
openUserProfile = {
navController.navigate(
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, it)
)
},
)
}
composable(route = Destinations.Settings.route) {
SettingsScreen(
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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,6 +11,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@@ -24,6 +25,7 @@ import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
import dev.msfjarvis.claw.common.comments.CommentsPage
import dev.msfjarvis.claw.common.comments.HTMLConverter
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
import dev.msfjarvis.claw.common.user.UserProfile
@Composable
fun SearchScreen(
@@ -34,7 +36,7 @@ fun SearchScreen(
viewModel: ClawViewModel = injectedViewModel(),
) {
val navController = rememberNavController()
val postActions = rememberPostActions(urlLauncher, navController, viewModel)
val postActions = rememberPostActions(LocalContext.current, urlLauncher, navController, viewModel)
val listState = rememberLazyListState()
Scaffold(modifier = modifier) { paddingValues ->
NavHost(
@@ -47,7 +49,6 @@ fun SearchScreen(
SearchList(
items = viewModel.searchResults,
listState = listState,
isPostSaved = viewModel::isPostSaved,
postActions = postActions,
searchQuery = viewModel.searchQuery,
setSearchQuery = { query -> viewModel.searchQuery = query },
@@ -68,6 +69,30 @@ fun SearchScreen(
htmlConverter = htmlConverter,
getSeenComments = viewModel::getSeenComments,
markSeenComments = viewModel::markSeenComments,
openUserProfile = { username: String ->
navController.navigate(
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, username)
)
},
)
}
composable(
route = Destinations.User.route,
arguments = listOf(navArgument("username") { type = NavType.StringType }),
) { backStackEntry ->
val username =
requireNotNull(backStackEntry.arguments?.getString("username")) {
"Navigating to ${Destinations.User.route} without necessary 'username' argument"
}
setWebUri("https://lobste.rs/u/$username")
UserProfile(
username = username,
getProfile = viewModel::getUserProfile,
openUserProfile = {
navController.navigate(
Destinations.User.route.replace(Destinations.User.PLACEHOLDER, it)
)
},
)
}
}
@@ -18,6 +18,7 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.cachedIn
import com.deliveryhero.whetstone.app.ApplicationScope
import com.deliveryhero.whetstone.viewmodel.ContributesViewModel
import com.slack.eithernet.ApiResult.Failure
@@ -31,8 +32,10 @@ import dev.msfjarvis.claw.android.paging.SearchPagingSource
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.core.injection.MainDispatcher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.Comment
import dev.msfjarvis.claw.model.UIPost
import dev.msfjarvis.claw.model.fromSavedPost
import dev.msfjarvis.claw.model.toUIPost
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
@@ -45,11 +48,8 @@ import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
@ContributesViewModel
@@ -68,48 +68,44 @@ constructor(
@MainDispatcher private val mainDispatcher: CoroutineDispatcher,
@ForScope(ApplicationScope::class) context: Context,
) : AndroidViewModel(context as Application) {
private val hottestPostsPager =
Pager(PagingConfig(pageSize = PAGE_SIZE), initialKey = STARTING_PAGE_INDEX) {
pagingSourceFactory.create(api::getHottestPosts)
}
private val newestPostsPager =
Pager(PagingConfig(pageSize = PAGE_SIZE), initialKey = STARTING_PAGE_INDEX) {
pagingSourceFactory.create(api::getNewestPosts)
}
private val searchResultsPager =
Pager(PagingConfig(pageSize = PAGE_SIZE), initialKey = STARTING_PAGE_INDEX) {
searchPagingSourceFactory.create { searchQuery }
}
val hottestPosts
get() = hottestPostsPager.flow
val newestPosts
get() = newestPostsPager.flow
val savedPosts
get() = savedPostsRepository.savedPosts
val hottestPosts =
Pager(
config = PagingConfig(pageSize = PAGE_SIZE),
initialKey = STARTING_PAGE_INDEX,
pagingSourceFactory = { pagingSourceFactory.create(api::getHottestPosts) },
)
.flow
.cachedIn(viewModelScope)
val newestPosts =
Pager(
config = PagingConfig(pageSize = PAGE_SIZE),
initialKey = STARTING_PAGE_INDEX,
pagingSourceFactory = { pagingSourceFactory.create(api::getNewestPosts) },
)
.flow
.cachedIn(viewModelScope)
val searchResults =
Pager(
PagingConfig(pageSize = PAGE_SIZE),
initialKey = STARTING_PAGE_INDEX,
pagingSourceFactory = { searchPagingSourceFactory.create { searchQuery } },
)
.flow
val savedPosts = savedPostsRepository.savedPosts.map { it.map(UIPost.Companion::fromSavedPost) }
val savedPostsByMonth
get() = savedPosts.map(::mapSavedPosts)
val searchResults
get() = searchResultsPager.flow
get() = savedPosts.map(::groupSavedPosts)
var searchQuery by mutableStateOf("")
private val _savedPostsMutex = Mutex()
private var _readPosts = emptyList<String>()
private var _savedPosts = emptyList<String>()
init {
viewModelScope.launch {
savedPosts.collectLatest {
_savedPostsMutex.withLock { _savedPosts = it.map(SavedPost::shortId) }
}
}
viewModelScope.launch { savedPosts.collectLatest { _savedPosts = it.map(UIPost::shortId) } }
viewModelScope.launch { readPostsRepository.readPosts.collectLatest { _readPosts = it } }
}
private fun mapSavedPosts(items: List<SavedPost>): ImmutableMap<String, List<SavedPost>> {
private fun groupSavedPosts(items: List<UIPost>): ImmutableMap<String, List<UIPost>> {
val sorted =
items.sortedWith { post1, post2 ->
val post1Date = post1.createdAt.toLocalDateTime()
@@ -130,29 +126,17 @@ constructor(
.toImmutableMap()
}
fun isPostSaved(post: SavedPost): Boolean {
return _savedPosts.contains(post.shortId)
}
fun toggleSave(post: SavedPost) {
viewModelScope.launch(ioDispatcher) {
val saved = isPostSaved(post)
if (saved) {
savedPostsRepository.removePost(post)
} else {
savedPostsRepository.savePost(post)
}
val newPosts = savedPosts.first()
withContext(mainDispatcher) {
SavedPostsWidget(newPosts.take(50)).updateAll(getApplication())
}
fun toggleSave(post: UIPost) {
viewModelScope.launch {
savedPostsRepository.toggleSave(post)
withContext(mainDispatcher) { SavedPostsWidget(savedPosts).updateAll(getApplication()) }
}
}
suspend fun getPostComments(postId: String) =
withContext(ioDispatcher) {
when (val result = api.getPostDetails(postId)) {
is Success -> result.value
is Success -> result.value.toUIPost()
is Failure.NetworkFailure -> throw result.error
is Failure.UnknownFailure -> throw result.error
is Failure.HttpFailure -> {
@@ -198,8 +182,6 @@ constructor(
viewModelScope.launch { readPostsRepository.markRead(postId) }
}
suspend fun isPostRead(postId: String) = readPostsRepository.isRead(postId)
/**
* Parses a given [String] into a [LocalDateTime]. This method is only intended to be used for
* dates in the format returned by the Lobsters API, and is not a general purpose parsing
@@ -6,17 +6,16 @@
*/
package dev.msfjarvis.claw.android.viewmodel
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.core.injection.IODispatcher
import dev.msfjarvis.claw.database.SavedPostSerializer
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.database.local.SavedPostQueries
import java.io.InputStream
import java.io.OutputStream
import java.time.Instant
import java.time.format.DateTimeFormatter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.builtins.ListSerializer
@@ -29,8 +28,7 @@ class DataTransferRepository
@Inject
constructor(
private val json: Json,
private val savedPostQueries: SavedPostQueries,
@DatabaseDispatcher private val dbDispatcher: CoroutineDispatcher,
private val savedPostsRepository: SavedPostsRepository,
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
) {
private val serializer = ListSerializer(SavedPostSerializer)
@@ -38,13 +36,11 @@ constructor(
suspend fun importPosts(input: InputStream) {
val posts: List<SavedPost> =
withContext(ioDispatcher) { json.decodeFromStream(serializer, input) }
withContext(dbDispatcher) {
savedPostQueries.transaction { posts.forEach(savedPostQueries::insertOrReplacePost) }
}
savedPostsRepository.savePosts(posts)
}
suspend fun exportPostsAsJson(output: OutputStream) {
val posts = withContext(dbDispatcher) { savedPostQueries.selectAllPosts().executeAsList() }
val posts = savedPostsRepository.savedPosts.first()
withContext(ioDispatcher) { json.encodeToStream(serializer, posts, output) }
}
@@ -55,7 +51,7 @@ constructor(
return instant.toEpochMilli()
}
val posts = withContext(dbDispatcher) { savedPostQueries.selectAllPosts().executeAsList() }
val posts = savedPostsRepository.savedPosts.first()
val header =
"""
<!DOCTYPE NETSCAPE-Bookmark-file-1>
@@ -1,11 +1,13 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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 app.cash.sqldelight.coroutines.asFlow
import app.cash.sqldelight.coroutines.mapToList
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.database.local.ReadPostsQueries
import javax.inject.Inject
@@ -18,11 +20,9 @@ constructor(
private val readPostsQueries: ReadPostsQueries,
@DatabaseDispatcher private val dbDispatcher: CoroutineDispatcher,
) {
val readPosts = readPostsQueries.selectAllPosts().asFlow().mapToList(dbDispatcher)
suspend fun markRead(postId: String) {
withContext(dbDispatcher) { readPostsQueries.markRead(postId) }
}
suspend fun isRead(postId: String): Boolean =
withContext(dbDispatcher) { readPostsQueries.isRead(postId).executeAsOneOrNull() != null }
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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,6 +11,8 @@ import app.cash.sqldelight.coroutines.mapToList
import dev.msfjarvis.claw.core.injection.DatabaseDispatcher
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.database.local.SavedPostQueries
import dev.msfjarvis.claw.model.UIPost
import dev.msfjarvis.claw.model.toSavedPost
import io.github.aakira.napier.Napier
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -24,9 +26,14 @@ constructor(
) {
val savedPosts = savedPostQueries.selectAllPosts().asFlow().mapToList(dbDispatcher)
suspend fun savePost(post: SavedPost) {
Napier.d(tag = TAG) { "Saving post: ${post.shortId}" }
withContext(dbDispatcher) { savedPostQueries.insertOrReplacePost(post) }
suspend fun toggleSave(post: UIPost) {
if (post.isSaved) {
Napier.d(tag = TAG) { "Removing post: ${post.shortId}" }
withContext(dbDispatcher) { savedPostQueries.deletePost(post.shortId) }
} else {
Napier.d(tag = TAG) { "Saving post: ${post.shortId}" }
withContext(dbDispatcher) { savedPostQueries.insertOrReplacePost(post.toSavedPost()) }
}
}
suspend fun savePosts(posts: List<SavedPost>) {
@@ -38,11 +45,6 @@ constructor(
}
}
suspend fun removePost(post: SavedPost) {
Napier.d(tag = TAG) { "Removing post: ${post.shortId}" }
withContext(dbDispatcher) { savedPostQueries.deletePost(post.shortId) }
}
private companion object {
private const val TAG = "SavedPostsRepository"
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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.
@@ -18,9 +18,12 @@ import dev.msfjarvis.claw.android.glance.SavedPostsWidget
import dev.msfjarvis.claw.android.viewmodel.SavedPostsRepository
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.UIPost
import dev.msfjarvis.claw.model.fromSavedPost
import dev.msfjarvis.claw.model.toSavedPost
import javax.inject.Inject
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
/**
* WorkManager-backed [CoroutineWorker] that gets all the posts from [SavedPostsRepository], fetches
@@ -44,7 +47,10 @@ constructor(
.filterIsInstance<Success<LobstersPostDetails>>()
.map { result -> result.value.toSavedPost() }
.let { savedPostsRepository.savePosts(it) }
SavedPostsWidget(savedPostsRepository.savedPosts.first().take(50)).updateAll(applicationContext)
SavedPostsWidget(
savedPostsRepository.savedPosts.map { it.map(UIPost.Companion::fromSavedPost) }
)
.updateAll(applicationContext)
return Result.success()
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
#
# This file was automatically generated by 'versioning-plugin'. DO NOT EDIT MANUALLY.
#
versioning-plugin.versionCode=13900
versioning-plugin.versionName=1.39.0
versioning-plugin.versionCode=14800
versioning-plugin.versionName=1.48.0
+6 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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.
@@ -18,17 +18,18 @@ android { namespace = "dev.msfjarvis.claw.api" }
anvil { generateDaggerFactories.set(true) }
dependencies {
api(libs.eithernet)
api(libs.dagger)
api(libs.javax.inject)
api(libs.okhttp.core)
api(libs.retrofit)
api(projects.model)
implementation(libs.dagger)
implementation(libs.javax.inject)
implementation(libs.eithernet)
implementation(libs.jsoup)
testImplementation(testFixtures(libs.eithernet))
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotlinx.serialization.core)
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.3.0-alpha16" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha16)" variant="all" version="8.3.0-alpha16">
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0)" variant="all" version="8.3.0">
</issues>
@@ -8,7 +8,6 @@ package dev.msfjarvis.claw.api.converters
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.User
import java.lang.reflect.Type
import okhttp3.ResponseBody
import org.jsoup.Jsoup
@@ -32,8 +31,7 @@ object SearchConverter : Converter<ResponseBody, List<LobstersPost>> {
val url = titleElement.attr("href")
val tags = elem.select("span.tags > a").map(Element::text)
val (commentCount, commentsUrl) = getCommentsData(elem.select("span.comments_label"))
val submitter =
getSubmitter(elem.select("div.byline").first() ?: error("No byline element found"))
val submitter = elem.select("div.byline > a.u-author").text()
return LobstersPost(
shortId = shortId,
title = title,
@@ -55,24 +53,6 @@ object SearchConverter : Converter<ResponseBody, List<LobstersPost>> {
return (countString.toIntOrNull() ?: 0) to commentsUrl
}
/**
* Make a bare-bones [User] object given a byline [elem]. We only need this to be usable for
* displaying in a list.
*/
private fun getSubmitter(elem: Element): User {
val userElement = elem.select("a.u-author")
val avatarElement = elem.select("img.avatar")
val username = userElement.text()
val avatarUrl = avatarElement.attr("src")
return User(
username = username,
about = "",
invitedBy = null,
avatarUrl = avatarUrl,
createdAt = "",
)
}
object Factory : Converter.Factory() {
override fun responseBodyConverter(
type: Type,
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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.
@@ -33,7 +33,7 @@ class ApiTest {
val posts = api.getHottestPosts(1)
assertIs<Success<List<LobstersPost>>>(posts)
val commentsOnlyPosts = posts.value.asSequence().filter { it.url.isEmpty() }.toSet()
assertThat(commentsOnlyPosts).hasSize(2)
assertThat(commentsOnlyPosts).hasSize(1)
}
@Test
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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,7 +10,6 @@ import com.google.common.truth.Truth.assertThat
import com.slack.eithernet.ApiResult
import com.slack.eithernet.test.newEitherNetController
import dev.msfjarvis.claw.model.LobstersPost
import dev.msfjarvis.claw.model.User
import dev.msfjarvis.claw.util.TestUtils.assertIs
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
@@ -38,7 +37,7 @@ class SearchApiTest {
createdAt = "",
commentCount = 3,
commentsUrl = "https://lobste.rs/s/gjlsdg/chatgpt_visits_emacs_doctor",
submitter = User("xenodium", "", null, "/avatars/xenodium-16.png", ""),
submitter = "xenodium",
tags = listOf("ai", "emacs"),
description = "",
),
@@ -50,7 +49,7 @@ class SearchApiTest {
createdAt = "",
commentCount = 0,
commentsUrl = "https://lobste.rs/s/astcqf/implementing_question_answering_system",
submitter = User("asteroid", "", null, "/avatars/asteroid-16.png", ""),
submitter = "asteroid",
tags = listOf("ai"),
description = "",
),
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"username":"msfjarvis","created_at":"2020-04-24T11:41:56.000-05:00","is_admin":false,"about":"Android and Kotlin developer\r\n","is_moderator":false,"karma":574,"avatar_url":"/avatars/msfjarvis-100.png","invited_by_user":"Amolith","github_username":"msfjarvis","twitter_username":"msfjarvis"}
{"username":"msfjarvis","created_at":"2020-04-24T11:41:56.000-05:00","is_admin":false,"about":"Android and Kotlin developer, currently working for [Dyte](https://dyte.io/)","is_moderator":false,"karma":1343,"avatar_url":"/avatars/msfjarvis-100.png","invited_by_user":"Amolith","github_username":"msfjarvis"}
File diff suppressed because one or more lines are too long
+2 -14
View File
@@ -1,13 +1,11 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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("UnstableApiUsage")
import com.android.build.api.dsl.ManagedVirtualDevice
plugins {
id(libs.plugins.android.test.get().pluginId)
id("dev.msfjarvis.claw.kotlin-android")
@@ -30,21 +28,11 @@ android {
matchingFallbacks += "release"
}
}
testOptions.managedDevices.devices {
create<ManagedVirtualDevice>("api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
targetProjectPath = ":android"
}
baselineProfile {
managedDevices += "api31"
useConnectedDevices = false
useConnectedDevices = true
enableEmulatorDisplay = false
}
+13 -1
View File
@@ -4,7 +4,10 @@
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
plugins { `kotlin-dsl` }
plugins {
`kotlin-dsl`
alias(libs.plugins.android.lint)
}
kotlin.jvmToolchain(17)
@@ -54,9 +57,15 @@ gradlePlugin {
id = "dev.msfjarvis.claw.versioning-plugin"
implementationClass = "dev.msfjarvis.claw.gradle.versioning.VersioningPlugin"
}
register("versions") {
id = "dev.msfjarvis.claw.versions"
implementationClass = "dev.msfjarvis.claw.gradle.DependencyUpdatesPlugin"
}
}
}
lint.baseline = project.file("lint-baseline.xml")
dependencies {
implementation(libs.build.agp)
implementation(libs.build.cachefix)
@@ -64,7 +73,10 @@ dependencies {
implementation(libs.build.semver)
implementation(libs.build.sentry)
implementation(libs.build.spotless)
implementation(libs.build.vcu)
// Expose the generated version catalog API to the plugin.
implementation(files(libs::class.java.superclass.protectionDomain.codeSource.location))
lintChecks(libs.androidx.lint)
}
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0)" variant="all" version="8.3.0">
</issues>
+9
View File
@@ -23,6 +23,14 @@ pluginManagement {
includeModule("org.gradle.kotlin", "gradle-kotlin-dsl-plugins")
}
}
exclusiveContent {
forRepository { google() }
filter {
includeGroup("androidx.databinding")
includeGroup("com.google.testing.platform")
includeGroupAndSubgroups("com.android")
}
}
mavenCentral { mavenContent { releasesOnly() } }
}
}
@@ -33,6 +41,7 @@ dependencyResolutionManagement {
forRepository(::google)
filter {
includeGroup("androidx.databinding")
includeGroup("androidx.lint")
includeGroupByRegex("com.android.*")
includeGroup("com.google.testing.platform")
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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.
@@ -33,26 +33,22 @@ class ApplicationPlugin : Plugin<Project> {
buildConfig = true
}
buildTypes {
all {
setProguardFiles(
listOf(
"proguard-android-optimize.pro",
"proguard-rules.pro",
"proguard-rules-missing-classes.pro",
)
buildTypes.configureEach {
setProguardFiles(
listOf(
"proguard-android-optimize.pro",
"proguard-rules.pro",
"proguard-rules-missing-classes.pro",
)
}
named("release") {
)
if (name == "release") {
isMinifyEnabled = !project.providers.environmentVariable("DISABLE_MINIFY").isPresent
}
named("debug") {
} else if (name == "debug") {
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
isMinifyEnabled = false
}
}
project.configureBuildSigning()
}
}
@@ -0,0 +1,36 @@
/*
* Copyright © 2024 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.github.zafarkhaja.semver.Version
import kotlin.jvm.optionals.getOrNull
import nl.littlerobots.vcu.plugin.VersionCatalogUpdateExtension
import nl.littlerobots.vcu.plugin.VersionCatalogUpdatePlugin
import nl.littlerobots.vcu.plugin.versionSelector
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
@Suppress("Unused")
class DependencyUpdatesPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply(VersionCatalogUpdatePlugin::class)
project.extensions.configure<VersionCatalogUpdateExtension> {
keep.keepUnusedLibraries.set(true)
versionSelector {
val currentVersion = Version.tryParse(it.currentVersion).getOrNull()
val newVersion = Version.tryParse(it.candidate.version).getOrNull()
if (currentVersion == null || newVersion == null) {
false
} else {
newVersion.isHigherThan(currentVersion)
}
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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,15 +7,12 @@
package dev.msfjarvis.claw.gradle
import dev.msfjarvis.claw.gradle.KotlinCommonPlugin.Companion.JVM_TOOLCHAIN_ACTION
import org.gradle.accessors.dm.LibrariesForLibs
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@Suppress("Unused")
class KotlinAndroidPlugin : Plugin<Project> {
@@ -26,25 +23,5 @@ class KotlinAndroidPlugin : Plugin<Project> {
apply(KotlinCommonPlugin::class)
}
project.extensions.getByType<KotlinProjectExtension>().jvmToolchain(JVM_TOOLCHAIN_ACTION)
val libs = project.extensions.getByName("libs") as LibrariesForLibs
val composeCompilerVersion = libs.versions.composeCompiler.get()
val kotlinVersion = libs.versions.kotlin.get()
val matches = COMPOSE_COMPILER_VERSION_REGEX.find(composeCompilerVersion)
if (matches != null) {
val (compilerKotlinVersion) = matches.destructured
if (compilerKotlinVersion != kotlinVersion) {
project.tasks.withType<KotlinCompile>().configureEach {
compilerOptions.freeCompilerArgs.addAll(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=$kotlinVersion",
)
}
}
}
}
private companion object {
// Matches against 1.5.0-dev-k1.9.0-6a60475e07f
val COMPOSE_COMPILER_VERSION_REGEX = "\\d.\\d.\\d-dev-k(\\d.\\d.\\d+)-[a-z0-9]+".toRegex()
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2024 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.
@@ -41,7 +41,7 @@ class KotlinKaptPlugin : Plugin<Project> {
}
}
project.tasks
.matching { it.name.startsWith("kapt") && it.name.endsWith("UnitTestKotlin") }
.named { it.startsWith("kapt") && it.endsWith("UnitTestKotlin") }
.configureEach { enabled = false }
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -31,15 +31,13 @@ object LintConfig {
if (!isJVM) {
enable += "ComposeM2Api"
error += "ComposeM2Api"
// False-positives in the TestContainers library
disable += "DeprecatedCall"
}
baseline = project.file("lint-baseline.xml")
// This is extremely annoying
disable += "AndroidGradlePluginVersion"
disable += "GradleDependency"
disable += "NewerVersionAvailable"
// Jetpack Compose lints are incompatible with AGP 8.3.0-alpha06
// Can't do anything about this
disable += "ObsoleteLintCustomCheck"
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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.
@@ -25,25 +25,33 @@ class SentryPlugin : Plugin<Project> {
project.extensions.configure<ApplicationAndroidComponentsExtension> {
onVariants(selector().all()) { variant ->
val sentryDsn = project.providers.environmentVariable(SENTRY_DSN_PROPERTY)
val enableSentry =
project.providers.gradleProperty(SENTRY_ENABLE_GRADLE_PROPERTY).isPresent
variant.manifestPlaceholders.put("sentryDsn", sentryDsn.getOrElse(""))
variant.manifestPlaceholders.put("enableSentry", "${variant.name == "release"}")
variant.manifestPlaceholders.put(
"sentryEnvironment",
when {
variant.name.contains("release", true) && enableSentry -> "production"
variant.name.contains("release", true) && !enableSentry -> "nightly"
else -> "dev"
},
)
}
}
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)
includeProguardMapping.set(true)
autoUploadProguardMapping.set(true)
uploadNativeSymbols.set(false)
autoUploadNativeSymbols.set(false)
includeNativeSources.set(false)
ignoredVariants.set(emptySet())
ignoredBuildTypes.set(setOf("benchmark", "debug"))
ignoredBuildTypes.set(setOf("benchmark"))
ignoredFlavors.set(emptySet())
tracingInstrumentation {
enabled.set(true)
debug.set(false)
logcat.enabled.set(true)
forceInstrumentDependencies.set(false)
features.set(EnumSet.allOf(InstrumentationFeature::class.java))
}
@@ -53,14 +61,27 @@ class SentryPlugin : Plugin<Project> {
sentryVersion.set(libs.versions.sentry.sdk)
}
includeDependenciesReport.set(true)
includeSourceContext.set(true)
autoUploadSourceContext.set(true)
additionalSourceDirsForSourceContext.set(emptySet())
debug.set(false)
org.set("claw")
projectName.set("compose-lobsters")
authToken.set(project.providers.environmentVariable("SENTRY_AUTH_TOKEN"))
url.set(null)
telemetry.set(false)
telemetryDsn.set(null)
}
with(project.dependencies) {
addProvider("implementation", platform(libs.sentry.bom))
addProvider("implementation", libs.sentry.android)
}
with(project.dependencies) { addProvider("implementation", platform(libs.sentry.bom)) }
}
}
private companion object {
private const val SENTRY_DSN_PROPERTY = "SENTRY_DSN"
private const val SENTRY_UPLOAD_MAPPINGS_PROPERTY = "sentryUploadMappings"
private const val SENTRY_ENABLE_GRADLE_PROPERTY = "enableSentry"
}
}
@@ -55,6 +55,6 @@ class SpotlessPlugin : Plugin<Project> {
}
private companion object {
private const val KTFMT_VERSION = "0.47"
private const val KTFMT_VERSION = "0.49"
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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.
@@ -16,19 +16,23 @@ import org.gradle.kotlin.dsl.exclude
/** Extension function to configure JUnit5 dependencies with the Truth assertion library. */
fun DependencyHandlerScope.addTestDependencies(project: Project) {
val libs = project.extensions.getByName("libs") as LibrariesForLibs
addProvider("testImplementation", libs.junit.jupiter.api)
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
"testImplementation",
libs.truth,
) {
exclude(group = "junit", module = "junit")
}
addProvider("testRuntimeOnly", libs.junit.jupiter.engine)
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
"testRuntimeOnly",
libs.junit.legacy,
) {
// See https://github.com/google/truth/issues/333
because("Truth needs it")
}
arrayOf("test", "androidTest")
.filter { sourceSet -> project.configurations.findByName("${sourceSet}Implementation") != null }
.forEach { sourceSet ->
addProvider("${sourceSet}Implementation", libs.junit.jupiter.api)
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
"${sourceSet}Implementation",
libs.truth,
) {
exclude(group = "junit", module = "junit")
}
addProvider("${sourceSet}RuntimeOnly", libs.junit.jupiter.engine)
addProvider<MinimalExternalModuleDependency, ExternalModuleDependency>(
"${sourceSet}RuntimeOnly",
libs.junit.legacy,
) {
// See https://github.com/google/truth/issues/333
because("Truth needs it")
}
}
}
@@ -1,37 +1,34 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2024 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.signing
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import com.android.build.api.dsl.ApplicationBuildType
import com.android.build.api.dsl.CommonExtension
import java.util.Properties
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
private const val KEYSTORE_CONFIG_PATH = "keystore.properties"
/** Configure signing for all build types. */
@Suppress("UnstableApiUsage")
internal fun Project.configureBuildSigning() {
val keystoreConfigFile = rootProject.layout.projectDirectory.file(KEYSTORE_CONFIG_PATH)
if (keystoreConfigFile.asFile.exists()) {
extensions.configure<BaseAppModuleExtension> {
extensions.configure<CommonExtension<*, ApplicationBuildType, *, *, *, *>>("android") {
val contents = providers.fileContents(keystoreConfigFile).asText
val keystoreProperties = Properties()
keystoreProperties.load(contents.get().byteInputStream())
signingConfigs {
register("release") {
val releaseSigningConfig =
signingConfigs.register("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = rootProject.file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
val signingConfig = signingConfigs.getByName("release")
buildTypes.all { setSigningConfig(signingConfig) }
buildTypes.configureEach { signingConfig = releaseSigningConfig.get() }
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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,21 +8,19 @@ package dev.msfjarvis.claw.gradle.versioning
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.variant.VariantOutputConfiguration
import com.android.build.gradle.internal.plugins.AppPlugin
import com.vdurmont.semver4j.Semver
import com.github.zafarkhaja.semver.Version
import java.util.Properties
import java.util.concurrent.atomic.AtomicBoolean
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.register
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.getProjectDir] directory. It also adds Gradle tasks to bump the major, minor, and
* patch versions along with one to prepare the next snapshot.
* A Gradle [Plugin] that takes a [Project] with the `com.android.application` applied and
* dynamically sets the versionCode and versionName properties based on values read from a
* [VERSIONING_PROP_FILE] file in 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")
class VersioningPlugin : Plugin<Project> {
@@ -37,14 +35,24 @@ class VersioningPlugin : Plugin<Project> {
val contents = providers.fileContents(propFile).asText
val versionProps = Properties().also { it.load(contents.get().byteInputStream()) }
val versionName =
requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_NAME)) {
"version.properties must contain a '$VERSIONING_PROP_VERSION_NAME' property"
}
providers
.gradleProperty("VERSION_NAME")
.orElse(
requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_NAME)) {
"version.properties must contain a '$VERSIONING_PROP_VERSION_NAME' property"
}
)
val versionCode =
requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_CODE).toInt()) {
"version.properties must contain a '$VERSIONING_PROP_VERSION_CODE' property"
}
project.plugins.withType<AppPlugin> {
providers
.gradleProperty("VERSION_CODE")
.orElse(
requireNotNull(versionProps.getProperty(VERSIONING_PROP_VERSION_CODE)) {
"version.properties must contain a '$VERSIONING_PROP_VERSION_CODE' property"
}
)
.map(String::toInt)
project.pluginManager.withPlugin("com.android.application") {
androidAppPluginApplied.set(true)
extensions.configure<ApplicationAndroidComponentsExtension> {
onVariants { variant ->
@@ -57,30 +65,30 @@ class VersioningPlugin : Plugin<Project> {
}
}
}
val version = Semver(versionName)
val version = versionName.map(Version::parse)
tasks.register<VersioningTask>("clearPreRelease") {
description = "Remove the pre-release suffix from the version"
semverString.set(version.withClearedSuffix().toString())
semverString.set(version.map(Version::toStableVersion).map(Version::toString))
propertyFile.set(propFile)
}
tasks.register<VersioningTask>("bumpMajor") {
description = "Increment the major version"
semverString.set(version.withIncMajor().withClearedSuffix().toString())
semverString.set(version.map(Version::nextMajorVersion).map(Version::toString))
propertyFile.set(propFile)
}
tasks.register<VersioningTask>("bumpMinor") {
description = "Increment the minor version"
semverString.set(version.withIncMinor().withClearedSuffix().toString())
semverString.set(version.map(Version::nextMinorVersion).map(Version::toString))
propertyFile.set(propFile)
}
tasks.register<VersioningTask>("bumpPatch") {
description = "Increment the patch version"
semverString.set(version.withIncPatch().withClearedSuffix().toString())
semverString.set(version.map(Version::nextPatchVersion).map(Version::toString))
propertyFile.set(propFile)
}
tasks.register<VersioningTask>("bumpSnapshot") {
description = "Increment the minor version and add the `SNAPSHOT` suffix"
semverString.set(version.withIncMinor().withSuffix("SNAPSHOT").toString())
semverString.set(version.map { it.nextMinorVersion("SNAPSHOT") }.map(Version::toString))
propertyFile.set(propFile)
}
afterEvaluate {
@@ -1,12 +1,12 @@
/*
* Copyright © 2022 Harsh Shandilya.
* Copyright © 2022-2024 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.versioning
import com.vdurmont.semver4j.Semver
import com.github.zafarkhaja.semver.Version
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
@@ -22,11 +22,11 @@ abstract class VersioningTask : DefaultTask() {
@get:OutputFile abstract val propertyFile: RegularFileProperty
/** Generate the Android 'versionCode' property */
private fun Semver.androidCode(): Int {
return major * 1_00_00 + minor * 1_00 + patch
private fun Version.androidCode(): Long {
return majorVersion() * 1_00_00 + minorVersion() * 1_00 + patchVersion()
}
private fun Semver.toPropFileText(): String {
private fun Version.toPropFileText(): String {
val newVersionCode = androidCode()
val newVersionName = toString()
return buildString {
@@ -46,6 +46,6 @@ abstract class VersioningTask : DefaultTask() {
@TaskAction
fun execute() {
propertyFile.get().asFile.writeText(Semver(semverString.get()).toPropFileText())
propertyFile.get().asFile.writeText(Version.parse(semverString.get()).toPropFileText())
}
}
+2
View File
@@ -6,5 +6,7 @@
*/
plugins {
id("dev.msfjarvis.claw.spotless")
id("dev.msfjarvis.claw.versions")
id("dev.msfjarvis.claw.kotlin-common")
alias(libs.plugins.dependencyAnalysis)
}
+11 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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 @@ plugins {
id("dev.msfjarvis.claw.kotlin-android")
alias(libs.plugins.anvil)
alias(libs.plugins.whetstone)
alias(libs.plugins.kotlin.composeCompiler)
}
android {
@@ -20,10 +21,7 @@ android {
androidResources = true
compose = true
}
composeOptions {
useLiveLiterals = false
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
}
composeOptions { useLiveLiterals = false }
namespace = "dev.msfjarvis.claw.common"
}
@@ -31,7 +29,12 @@ androidComponents { beforeVariants { (it as HasUnitTestBuilder).enableUnitTest =
anvil { generateDaggerFactories.set(true) }
composeCompiler { enableStrongSkippingMode = true }
dependencies {
api(libs.androidx.compose.ui)
api(libs.dagger)
api(libs.javax.inject)
api(projects.core)
api(projects.database.core)
api(projects.model)
@@ -44,12 +47,15 @@ dependencies {
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.runtime)
implementation(libs.androidx.compose.ui.text)
implementation(libs.androidx.core)
implementation(libs.coil)
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.kotlinResult)
implementation(libs.kotlinResult.coroutines)
implementation(libs.napier)
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.3.0-alpha16" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha16)" variant="all" version="8.3.0-alpha16">
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0)" variant="all" version="8.3.0">
</issues>
@@ -29,7 +29,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
@@ -46,22 +45,22 @@ import dev.msfjarvis.claw.common.posts.TagRow
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 dev.msfjarvis.claw.model.UIPost
import java.time.Instant
import java.time.temporal.TemporalAccessor
import kotlinx.collections.immutable.toImmutableList
@Composable
internal fun CommentsHeader(
postDetails: LobstersPostDetails,
post: UIPost,
postActions: PostActions,
htmlConverter: HTMLConverter,
openUserProfile: (String) -> Unit,
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current
val linkMetadata by
produceState(initialValue = LinkMetadata(postDetails.url, null)) {
runSuspendCatching { postActions.getLinkMetadata(postDetails.url) }
produceState(initialValue = LinkMetadata(post.url, null)) {
runSuspendCatching { postActions.getLinkMetadata(post.url) }
.onSuccess { metadata -> value = metadata }
}
@@ -70,8 +69,8 @@ internal fun CommentsHeader(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
PostTitle(title = postDetails.title, isRead = false)
TagRow(tags = postDetails.tags.toImmutableList())
PostTitle(title = post.title, isRead = false, singleLineTitle = false)
TagRow(tags = post.tags.toImmutableList())
Spacer(Modifier.height(4.dp))
if (linkMetadata.url.isNotBlank()) {
@@ -79,24 +78,21 @@ internal fun CommentsHeader(
linkMetadata = linkMetadata,
modifier =
Modifier.clickable {
postActions.viewPost(postDetails.shortId, linkMetadata.url, postDetails.commentsUrl)
postActions.viewPost(post.shortId, linkMetadata.url, post.commentsUrl)
},
)
Spacer(Modifier.height(4.dp))
}
if (postDetails.description.isNotBlank()) {
ThemedRichText(htmlConverter.convertHTMLToMarkdown(postDetails.description))
if (post.description.isNotBlank()) {
ThemedRichText(htmlConverter.convertHTMLToMarkdown(post.description))
Spacer(Modifier.height(4.dp))
}
Submitter(
text = AnnotatedString("Submitted by ${postDetails.submitter.username}"),
avatarUrl = "https://lobste.rs/${postDetails.submitter.avatarUrl}",
contentDescription = "User avatar for ${postDetails.submitter.username}",
modifier =
Modifier.clickable {
uriHandler.openUri("https://lobste.rs/u/${postDetails.submitter.username}")
},
text = AnnotatedString("Submitted by ${post.submitter}"),
avatarUrl = "https://lobste.rs/avatars/${post.submitter}-100.png",
contentDescription = "User avatar for ${post.submitter}",
modifier = Modifier.clickable { openUserProfile(post.submitter) },
)
}
}
@@ -135,9 +131,9 @@ internal fun CommentEntry(
commentNode: CommentNode,
htmlConverter: HTMLConverter,
toggleExpanded: (CommentNode) -> Unit,
openUserProfile: (String) -> Unit,
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current
val comment = commentNode.comment
Box(
modifier =
@@ -156,16 +152,15 @@ internal fun CommentEntry(
Submitter(
text =
buildCommenterString(
commenterName = comment.user.username,
commenterName = comment.user,
score = comment.score,
isUnread = commentNode.isUnread,
createdAt = comment.createdAt,
updatedAt = comment.updatedAt,
),
avatarUrl = "https://lobste.rs/${comment.user.avatarUrl}",
contentDescription = "User avatar for ${comment.user.username}",
modifier =
Modifier.clickable { uriHandler.openUri("https://lobste.rs/u/${comment.user.username}") },
avatarUrl = "https://lobste.rs/avatars/${comment.user}-100.png",
contentDescription = "User avatar for ${comment.user}",
modifier = Modifier.clickable { openUserProfile(comment.user) },
)
if (commentNode.isExpanded) {
ThemedRichText(
@@ -71,7 +71,7 @@ internal fun setExpanded(commentNode: CommentNode, expanded: Boolean): CommentNo
return commentNode
}
internal fun findTopMostParent(node: CommentNode): CommentNode {
internal tailrec fun findTopMostParent(node: CommentNode): CommentNode {
val parent = node.parent
return if (parent != null) {
findTopMostParent(parent)
@@ -84,9 +84,15 @@ internal fun LazyListScope.nodes(
nodes: List<CommentNode>,
htmlConverter: HTMLConverter,
toggleExpanded: (CommentNode) -> Unit,
openUserProfile: (String) -> Unit,
) {
nodes.forEach { node ->
node(node = node, htmlConverter = htmlConverter, toggleExpanded = toggleExpanded)
node(
node = node,
htmlConverter = htmlConverter,
toggleExpanded = toggleExpanded,
openUserProfile = openUserProfile,
)
}
}
@@ -94,16 +100,27 @@ private fun LazyListScope.node(
node: CommentNode,
htmlConverter: HTMLConverter,
toggleExpanded: (CommentNode) -> Unit,
openUserProfile: (String) -> Unit,
) {
// Skip the node if neither the node nor its parent is expanded
if (!node.isExpanded && node.parent?.isExpanded == false) {
return
}
item {
CommentEntry(commentNode = node, htmlConverter = htmlConverter, toggleExpanded = toggleExpanded)
item(key = node.comment.shortId) {
CommentEntry(
commentNode = node,
htmlConverter = htmlConverter,
toggleExpanded = toggleExpanded,
openUserProfile = openUserProfile,
)
HorizontalDivider()
}
if (node.children.isNotEmpty()) {
nodes(node.children, htmlConverter = htmlConverter, toggleExpanded = toggleExpanded)
nodes(
node.children,
htmlConverter = htmlConverter,
toggleExpanded = toggleExpanded,
openUserProfile = openUserProfile,
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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.
@@ -36,16 +36,17 @@ import dev.msfjarvis.claw.common.ui.NetworkError
import dev.msfjarvis.claw.common.ui.ProgressBar
import dev.msfjarvis.claw.database.local.PostComments
import dev.msfjarvis.claw.model.Comment
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.UIPost
@Suppress("LongParameterList")
@Composable
private fun CommentsPageInternal(
details: LobstersPostDetails,
details: UIPost,
postActions: PostActions,
htmlConverter: HTMLConverter,
commentState: PostComments?,
markSeenComments: (String, List<Comment>) -> Unit,
openUserProfile: (String) -> Unit,
modifier: Modifier = Modifier,
) {
val commentNodes = createListNode(details.comments, commentState).toMutableStateList()
@@ -55,9 +56,10 @@ private fun CommentsPageInternal(
LazyColumn(modifier = modifier, contentPadding = PaddingValues(bottom = 24.dp)) {
item {
CommentsHeader(
postDetails = details,
post = details,
postActions = postActions,
htmlConverter = htmlConverter,
openUserProfile = openUserProfile,
)
}
@@ -83,6 +85,7 @@ private fun CommentsPageInternal(
commentNodes.add(index, parent)
}
},
openUserProfile = openUserProfile,
)
} else {
item {
@@ -108,6 +111,7 @@ fun CommentsPage(
getSeenComments: suspend (String) -> PostComments?,
markSeenComments: (String, List<Comment>) -> Unit,
modifier: Modifier = Modifier,
openUserProfile: (String) -> Unit,
) {
val postDetails by
produceState<NetworkState>(Loading) {
@@ -123,11 +127,12 @@ fun CommentsPage(
when (postDetails) {
is Success<*> -> {
CommentsPageInternal(
details = (postDetails as Success<LobstersPostDetails>).data,
details = (postDetails as Success<UIPost>).data,
postActions = postActions,
htmlConverter = htmlConverter,
commentState = commentState,
markSeenComments = markSeenComments,
openUserProfile = openUserProfile,
modifier = modifier.fillMaxSize(),
)
}
@@ -6,6 +6,7 @@
*/
package dev.msfjarvis.claw.common.posts
import androidx.annotation.VisibleForTesting
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -47,39 +48,47 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
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 dev.msfjarvis.claw.model.UIPost
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable
fun LobstersCard(
post: SavedPost,
isSaved: Boolean,
isRead: Boolean,
post: UIPost,
postActions: PostActions,
refresh: () -> Unit,
modifier: Modifier = Modifier,
) {
var localSavedState by remember(post, isSaved) { mutableStateOf(isSaved) }
var localReadState by remember(post) { mutableStateOf(post.isRead) }
var localSavedState by remember(post) { mutableStateOf(post.isSaved) }
Box(
modifier =
modifier
.fillMaxWidth()
.clickable { postActions.viewPost(post.shortId, post.url, post.commentsUrl) }
.clickable {
postActions.viewPost(post.shortId, post.url, post.commentsUrl)
localReadState = true
refresh()
}
.background(MaterialTheme.colorScheme.background)
.padding(start = 16.dp, top = 16.dp, end = 4.dp, bottom = 16.dp)
.padding(start = 8.dp)
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
PostDetails(modifier = Modifier.weight(1f), post = post, isRead = isRead)
PostDetails(
post = post,
isRead = localReadState,
singleLineTitle = true,
modifier = Modifier.weight(1f),
)
Column(
modifier = Modifier.wrapContentHeight(),
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -91,6 +100,7 @@ fun LobstersCard(
Modifier.clickable(role = Role.Button) {
localSavedState = !localSavedState
postActions.toggleSave(post)
refresh()
},
)
HorizontalDivider(modifier = Modifier.width(48.dp))
@@ -99,7 +109,11 @@ fun LobstersCard(
modifier =
Modifier.clickable(
role = Role.Button,
onClick = { postActions.viewComments(post.shortId) },
onClick = {
postActions.viewComments(post.shortId)
localReadState = true
refresh()
},
),
)
}
@@ -108,27 +122,39 @@ fun LobstersCard(
}
@Composable
fun PostDetails(post: SavedPost, isRead: Boolean, modifier: Modifier = Modifier) {
fun PostDetails(
post: UIPost,
isRead: Boolean,
singleLineTitle: Boolean,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp)) {
PostTitle(title = post.title, isRead = isRead)
PostTitle(title = post.title, isRead = isRead, singleLineTitle = singleLineTitle)
TagRow(tags = post.tags.toImmutableList())
Spacer(Modifier.height(4.dp))
Submitter(
text = AnnotatedString("Submitted by ${post.submitterName}"),
avatarUrl = "https://lobste.rs/${post.submitterAvatarUrl}",
contentDescription = "User avatar for ${post.submitterName}",
text = AnnotatedString("Submitted by ${post.submitter}"),
avatarUrl = "https://lobste.rs/avatars/${post.submitter}-100.png",
contentDescription = "User avatar for ${post.submitter}",
)
}
}
@Composable
internal fun PostTitle(title: String, isRead: Boolean, modifier: Modifier = Modifier) {
internal fun PostTitle(
title: String,
isRead: Boolean,
singleLineTitle: Boolean,
modifier: Modifier = Modifier,
) {
Text(
text = title,
modifier = modifier,
style = MaterialTheme.typography.titleMedium,
fontWeight = if (isRead) FontWeight.Normal else FontWeight.Bold,
color = MaterialTheme.colorScheme.onBackground,
maxLines = if (singleLineTitle) 1 else Int.MAX_VALUE,
overflow = TextOverflow.Ellipsis,
)
}
@@ -163,7 +189,7 @@ internal fun Submitter(
@Composable
private fun SaveButton(isSaved: Boolean, modifier: Modifier = Modifier) {
Crossfade(targetState = isSaved, label = "save-button") { saved ->
Box(modifier = modifier.padding(12.dp)) {
Box(modifier = modifier.padding(vertical = 12.dp)) {
Icon(
imageVector = if (saved) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder,
tint = MaterialTheme.colorScheme.secondary,
@@ -177,7 +203,7 @@ private fun SaveButton(isSaved: Boolean, modifier: Modifier = Modifier) {
@Composable
private fun CommentsButton(commentCount: Int?, modifier: Modifier = Modifier) {
BadgedBox(
modifier = modifier.padding(12.dp),
modifier = modifier.padding(vertical = 12.dp),
badge = {
if (commentCount != null) {
Badge(
@@ -228,55 +254,57 @@ private fun TagText(tag: String, modifier: Modifier = Modifier) {
)
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
val TEST_POST_ACTIONS =
object : PostActions {
override fun viewPost(postId: String, postUrl: String, commentsUrl: String) {}
override fun viewComments(postId: String) {}
override fun viewCommentsPage(post: UIPost) {}
override fun toggleSave(post: UIPost) {}
override fun share(post: UIPost) {}
override suspend fun getComments(postId: String): UIPost {
return UIPost(
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 = "Haki",
comments = emptyList(),
)
}
override suspend fun getLinkMetadata(url: String): LinkMetadata {
return LinkMetadata("", "")
}
}
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
val TEST_POST =
UIPost(
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",
submitter = "Haki",
tags = listOf("databases", "apis"),
description = "",
isSaved = true,
isRead = true,
)
@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 = "",
),
isRead = true,
isSaved = true,
postActions =
object : PostActions {
override fun viewPost(postId: String, 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("", "")
}
},
)
}
private fun LobstersCardPreview() {
LobstersTheme { LobstersCard(post = TEST_POST, postActions = TEST_POST_ACTIONS, refresh = {}) }
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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,9 +7,8 @@
package dev.msfjarvis.claw.common.posts
import androidx.compose.runtime.Stable
import dev.msfjarvis.claw.database.local.SavedPost
import dev.msfjarvis.claw.model.LinkMetadata
import dev.msfjarvis.claw.model.LobstersPostDetails
import dev.msfjarvis.claw.model.UIPost
@Stable
interface PostActions {
@@ -17,11 +16,13 @@ interface PostActions {
fun viewComments(postId: String)
fun viewCommentsPage(commentsUrl: String)
fun viewCommentsPage(post: UIPost)
fun toggleSave(post: SavedPost)
fun toggleSave(post: UIPost)
suspend fun getComments(postId: String): LobstersPostDetails
fun share(post: UIPost)
suspend fun getComments(postId: String): UIPost
suspend fun getLinkMetadata(url: String): LinkMetadata
}
@@ -1,20 +0,0 @@
/*
* 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.common.ui
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.LocalAbsoluteTonalElevation
import androidx.compose.material3.NavigationBarDefaults
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
@Composable
fun ColorScheme.surfaceColorAtNavigationBarElevation(): Color {
val elevation = LocalAbsoluteTonalElevation.current + NavigationBarDefaults.Elevation
return surfaceColorAtElevation(elevation)
}
@@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import com.halilibo.richtext.markdown.Markdown
import com.halilibo.richtext.commonmark.Markdown
import com.halilibo.richtext.ui.RichTextStyle
import com.halilibo.richtext.ui.material3.RichText
import com.halilibo.richtext.ui.string.RichTextStringStyle
@@ -30,7 +30,7 @@ import io.github.aakira.napier.Napier
@Composable
fun NetworkError(label: String, error: Throwable, modifier: Modifier = Modifier) {
LaunchedEffect(true) { Napier.e(error, "NetworkError") { "Failed to load posts" } }
LaunchedEffect(Unit) { Napier.e(error, "NetworkError") { "Failed to load posts" } }
var showDialog by remember { mutableStateOf(false) }
Column(verticalArrangement = Arrangement.spacedBy(4.dp), modifier = modifier) {
Text(
@@ -70,7 +70,7 @@ fun SearchBar(
@DevicePreviews
@ThemePreviews
@Composable
fun SearchBarPreview() {
private fun SearchBarPreview() {
LobstersTheme {
Box(Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.background).padding(8.dp)) {
var value by remember { mutableStateOf("") }
@@ -19,7 +19,6 @@ 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
fun MonthHeader(label: String, modifier: Modifier = Modifier) {
@@ -27,7 +26,7 @@ fun MonthHeader(label: String, modifier: Modifier = Modifier) {
modifier
.fillMaxWidth()
.wrapContentHeight()
.background(MaterialTheme.colorScheme.surfaceColorAtNavigationBarElevation())
.background(MaterialTheme.colorScheme.surfaceContainerHighest)
) {
Text(
text = label,
@@ -40,6 +39,6 @@ fun MonthHeader(label: String, modifier: Modifier = Modifier) {
@DevicePreviews
@ThemePreviews
@Composable
fun MonthHeaderPreview() {
private fun MonthHeaderPreview() {
LobstersTheme { MonthHeader("April 2023") }
}
@@ -24,6 +24,8 @@ 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.text.LinkAnnotation
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.unit.dp
import com.github.michaelbull.result.coroutines.runSuspendCatching
import com.github.michaelbull.result.fold
@@ -42,6 +44,7 @@ import dev.msfjarvis.claw.model.User
fun UserProfile(
username: String,
getProfile: suspend (username: String) -> User,
openUserProfile: (String) -> Unit,
modifier: Modifier = Modifier,
) {
val user by
@@ -56,7 +59,11 @@ fun UserProfile(
}
when (user) {
is Success<*> -> {
UserProfileInternal(user = (user as Success<User>).data, modifier = modifier)
UserProfileInternal(
user = (user as Success<User>).data,
openUserProfile = openUserProfile,
modifier = modifier,
)
}
is Error -> {
val error = user as Error
@@ -77,7 +84,11 @@ fun UserProfile(
}
@Composable
private fun UserProfileInternal(user: User, modifier: Modifier = Modifier) {
private fun UserProfileInternal(
user: User,
openUserProfile: (String) -> Unit,
modifier: Modifier = Modifier,
) {
Surface(modifier = modifier) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
@@ -93,7 +104,19 @@ private fun UserProfileInternal(user: User, modifier: Modifier = Modifier) {
Text(text = user.username, style = MaterialTheme.typography.displaySmall)
ThemedRichText(text = user.about)
user.invitedBy?.let { invitedBy ->
ThemedRichText(text = "Invited by [${invitedBy}](https://lobste.rs/u/${user.invitedBy})")
Text(
text =
buildAnnotatedString {
append("Invited by ")
pushLink(
LinkAnnotation.Clickable(
tag = "username",
linkInteractionListener = { openUserProfile(invitedBy) },
)
)
append(invitedBy)
}
)
}
}
}
+6 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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.
@@ -16,16 +16,17 @@ android { namespace = "dev.msfjarvis.claw.core" }
anvil { generateDaggerFactories.set(true) }
dependencies {
api(libs.dagger)
api(libs.javax.inject)
api(libs.kotlinx.coroutines.core)
api(libs.kotlinx.serialization.json)
api(libs.okhttp.loggingInterceptor)
api(libs.napier)
api(libs.okhttp.core)
api(libs.retrofit)
implementation(platform(libs.okhttp.bom))
implementation(platform(libs.sentry.bom))
implementation(libs.dagger)
implementation(libs.napier)
implementation(libs.okhttp.core)
implementation(libs.kotlinx.serialization.core)
implementation(libs.retrofit.kotlinxSerializationConverter)
implementation(libs.sentry.okhttp)
}
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.3.0-alpha16" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha16)" variant="all" version="8.3.0-alpha16">
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0)" variant="all" version="8.3.0">
</issues>
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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,7 +7,6 @@
package dev.msfjarvis.claw.core.injection
import com.deliveryhero.whetstone.app.ApplicationScope
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
@@ -18,6 +17,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNamingStrategy
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Converter
import retrofit2.converter.kotlinx.serialization.asConverterFactory
@Module
@ContributesTo(ApplicationScope::class)
@@ -1,5 +1,5 @@
/*
* Copyright © 2022-2023 Harsh Shandilya.
* Copyright © 2022-2024 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.
@@ -18,7 +18,6 @@ import dagger.multibindings.IntoSet
import dev.msfjarvis.claw.core.network.DelegatingSocketFactory
import dev.msfjarvis.claw.core.network.NapierLogger
import dev.msfjarvis.claw.core.network.UserAgentInterceptor
import io.sentry.okhttp.SentryOkHttpInterceptor
import java.net.Socket
import javax.net.SocketFactory
import okhttp3.Cache
@@ -88,11 +87,5 @@ interface OkHttpModule {
fun provideHttpLoggingInterceptor(logger: HttpLoggingInterceptor.Logger): Interceptor {
return HttpLoggingInterceptor(logger).setLevel(HttpLoggingInterceptor.Level.BASIC)
}
@Provides
@IntoSet
fun provideSentryInterceptor(): Interceptor {
return SentryOkHttpInterceptor()
}
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.3.0-alpha16" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha16)" variant="all" version="8.3.0-alpha16">
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0)" variant="all" version="8.3.0">
</issues>
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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.
@@ -32,7 +32,6 @@ object SavedPostSerializer : KSerializer<SavedPost> {
element<Int?>("commentCount", isOptional = true)
element<String>("commentsUrl")
element<String>("submitterName")
element<String>("submitterAvatarUrl")
element<List<String>>("tags")
element<String>("description")
}
@@ -46,7 +45,6 @@ object SavedPostSerializer : KSerializer<SavedPost> {
var commentCount: Int? = null
var commentsUrl = ""
var submitterName = ""
var submitterAvatarUrl = ""
var tags = emptyList<String>()
var description = ""
while (true) {
@@ -58,9 +56,8 @@ object SavedPostSerializer : KSerializer<SavedPost> {
4 -> commentCount = decodeNullableSerializableElement(descriptor, 4, Int.serializer())
5 -> commentsUrl = decodeStringElement(descriptor, 5)
6 -> submitterName = decodeStringElement(descriptor, 6)
7 -> submitterAvatarUrl = decodeStringElement(descriptor, 7)
8 -> tags = decodeSerializableElement(descriptor, 8, delegateSerializer)
9 -> description = decodeStringElement(descriptor, 9)
7 -> tags = decodeSerializableElement(descriptor, 7, delegateSerializer)
8 -> description = decodeStringElement(descriptor, 8)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
@@ -73,7 +70,6 @@ object SavedPostSerializer : KSerializer<SavedPost> {
commentCount = commentCount,
commentsUrl = commentsUrl,
submitterName = submitterName,
submitterAvatarUrl = submitterAvatarUrl,
tags = tags,
description = description,
)
@@ -89,9 +85,8 @@ object SavedPostSerializer : KSerializer<SavedPost> {
encodeNullableSerializableElement(descriptor, 4, Int.serializer(), value.commentCount)
encodeStringElement(descriptor, 5, value.commentsUrl)
encodeStringElement(descriptor, 6, value.submitterName)
encodeStringElement(descriptor, 7, value.submitterAvatarUrl)
encodeSerializableElement(descriptor, 8, delegateSerializer, value.tags)
encodeStringElement(descriptor, 9, value.description)
encodeSerializableElement(descriptor, 7, delegateSerializer, value.tags)
encodeStringElement(descriptor, 8, value.description)
}
}
}
@@ -1,17 +1,16 @@
CREATE TABLE ReadPosts(
CREATE TABLE IF NOT EXISTS ReadPosts(
id TEXT NOT NULL PRIMARY KEY
);
selectAllPosts:
SELECT *
FROM ReadPosts;
markRead:
INSERT OR REPLACE
INSERT OR IGNORE
INTO ReadPosts(id)
VALUES (?);
markUnread:
DELETE FROM ReadPosts
WHERE id = ?;
isRead:
SELECT *
FROM ReadPosts
WHERE id = ?;
@@ -10,7 +10,6 @@ CREATE TABLE IF NOT EXISTS SavedPost(
commentCount INTEGER AS Int,
commentsUrl TEXT NOT NULL,
submitterName TEXT NOT NULL,
submitterAvatarUrl TEXT NOT NULL,
tags TEXT AS List<String> NOT NULL,
description TEXT NOT NULL DEFAULT ""
);
@@ -36,8 +35,3 @@ deletePost:
DELETE
FROM SavedPost
WHERE shortId = ?;
selectPost:
SELECT *
FROM SavedPost
WHERE shortId = ?;
@@ -1,3 +1,3 @@
CREATE TABLE ReadPosts(
CREATE TABLE IF NOT EXISTS ReadPosts(
id TEXT NOT NULL PRIMARY KEY
);
@@ -0,0 +1,23 @@
import kotlin.Int;
import kotlin.String;
import kotlin.collections.List;
ALTER TABLE SavedPost RENAME TO SavedPost_Old;
CREATE TABLE IF NOT EXISTS SavedPost(
shortId TEXT NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
url TEXT NOT NULL,
createdAt TEXT NOT NULL,
commentCount INTEGER AS Int,
commentsUrl TEXT NOT NULL,
submitterName TEXT NOT NULL,
tags TEXT AS List<String> NOT NULL,
description TEXT NOT NULL DEFAULT ""
);
INSERT INTO SavedPost(shortId, title, url, createdAt, commentCount, commentsUrl, submitterName, tags, description)
SELECT shortId, title, url, createdAt, commentCount, commentsUrl, submitterName, tags, description
FROM SavedPost_Old;
DROP TABLE SavedPost_Old;
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 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.
@@ -52,7 +52,6 @@ class SavedPostSerializerTest {
commentCount = 13,
commentsUrl = "https://lobste.rs/s/nbigsf/fun_format_friday_you_now_have_super",
submitterName = "LenFalken",
submitterAvatarUrl = "/avatars/LenFalken-100.png",
tags = listOf("ask", "programming"),
description =
"<p>You suddenly have in your possession a super computer. What comes next? What projects are suddenly possible for you? What performance tests can you now explore?</p>\n",
@@ -1 +1 @@
{"short_id":"nbigsf","title":"Fun Format Friday: You now have a super computer. What next?","url":"","created_at":"2023-05-04T23:43:50.000-05:00","comment_count":13,"comments_url":"https://lobste.rs/s/nbigsf/fun_format_friday_you_now_have_super","submitter_name":"LenFalken","submitter_avatar_url":"/avatars/LenFalken-100.png","tags":["ask","programming"],"description":"<p>You suddenly have in your possession a super computer. What comes next? What projects are suddenly possible for you? What performance tests can you now explore?</p>\n"}
{"short_id":"nbigsf","title":"Fun Format Friday: You now have a super computer. What next?","url":"","created_at":"2023-05-04T23:43:50.000-05:00","comment_count":13,"comments_url":"https://lobste.rs/s/nbigsf/fun_format_friday_you_now_have_super","submitter_name":"LenFalken","tags":["ask","programming"],"description":"<p>You suddenly have in your possession a super computer. What comes next? What projects are suddenly possible for you? What performance tests can you now explore?</p>\n"}
+3 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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.
@@ -18,6 +18,8 @@ android { namespace = "dev.msfjarvis.claw.database" }
anvil { generateDaggerFactories.set(true) }
dependencies {
api(libs.dagger)
api(libs.javax.inject)
api(projects.database.core)
implementation(libs.napier)
implementation(libs.dagger)
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 8.3.0-alpha16" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0-alpha16)" variant="all" version="8.3.0-alpha16">
<issues format="6" by="lint 8.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (8.3.0)" variant="all" version="8.3.0">
</issues>
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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 app.cash.sqldelight.logs.LogSqliteDriver
import com.deliveryhero.whetstone.app.ApplicationScope
import com.squareup.anvil.annotations.ContributesTo
import com.squareup.anvil.annotations.optional.ForScope
import com.squareup.anvil.annotations.optional.SingleIn
import dagger.Module
import dagger.Provides
import dev.msfjarvis.claw.database.LobstersDatabase
@@ -28,7 +29,9 @@ object DatabaseModule {
private const val LOBSTERS_DATABASE_NAME = "SavedPosts.db"
@[Provides InternalDatabaseApi]
@Provides
@InternalDatabaseApi
@SingleIn(ApplicationScope::class)
fun provideDatabase(@ForScope(ApplicationScope::class) context: Context): LobstersDatabase {
val driver =
LogSqliteDriver(
@@ -1,5 +1,5 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Copyright © 2023-2024 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
@@ -23,8 +23,8 @@ class ReadPostsQueriesTest {
fun `mark post as read`() {
val id = UUID.randomUUID().toString()
postQueries.markRead(id)
assertThat(postQueries.isRead(id).executeAsOne()).isNotNull()
assertThat(postQueries.selectAllPosts().executeAsList()).contains(id)
postQueries.markUnread(id)
assertThat(postQueries.isRead(id).executeAsOneOrNull()).isNull()
assertThat(postQueries.selectAllPosts().executeAsList()).doesNotContain(id)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright © 2021-2023 Harsh Shandilya.
* Copyright © 2021-2024 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.
@@ -32,7 +32,7 @@ class SavedPostQueriesTest {
@Test
fun `update post in database`() {
// Get 1 post
val post = createTestData(1)[0]
val post = createTestData(1).first()
// Insert post into DB
postQueries.insertOrReplacePost(post)
@@ -46,15 +46,14 @@ class SavedPostQueriesTest {
assertThat(postsCount).isEqualTo(1)
// Check if post is updated
val postFromDb = postQueries.selectPost(post.shortId).executeAsOne()
val postFromDb = postQueries.selectAllPosts().executeAsOne()
assertThat(postFromDb.submitterName).isEqualTo("Fake name")
}
@Test
fun `get post from db`() {
// Get 1 post
val post = createTestData(1)[0]
val post = createTestData(1).first()
// Insert post into DB
postQueries.insertOrReplacePost(post)
@@ -123,7 +122,6 @@ class SavedPostQueriesTest {
commentCount = 0,
commentsUrl = "test_comments_url",
submitterName = "test_user_$i",
submitterAvatarUrl = "test_avatar_url",
tags = listOf(),
description = "",
)

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