diff --git a/.github/skills/code-review-graph-debug/SKILL.md b/.github/skills/code-review-graph-debug/SKILL.md deleted file mode 100644 index ade7baa89..000000000 --- a/.github/skills/code-review-graph-debug/SKILL.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: code-review-graph-debug -description: Systematically debug issues using the code-review-graph knowledge graph. Use instead of manual file reading when tracing call chains, locating a bug's origin, or assessing impact radius of a suspected file. ---- - -# Debug Issue with code-review-graph - -Use the knowledge graph to systematically trace and debug issues. - -## Steps - -1. Use `mcp_code-review-g_get_minimal_context_tool` first with `task=""` to orient cheaply. -2. Use `mcp_code-review-g_semantic_search_nodes_tool` to find code related to the issue. -3. Use `mcp_code-review-g_query_graph_tool` with `callers_of` and `callees_of` to trace call chains. -4. Use `mcp_code-review-g_get_flow_tool` to see full execution paths through suspected areas. -5. Run `mcp_code-review-g_detect_changes_tool` to check if recent changes caused the issue. -6. Use `mcp_code-review-g_get_impact_radius_tool` on suspected files to see what else is affected. - -## Tips - -- Check both callers and callees to understand the full context. -- Look at affected flows to find the entry point that triggers the bug. -- Recent changes are the most common source of new issues. -- Only read raw files with `#tool:read/readFile` when the graph result is insufficient — prefer the graph for navigation and reserve file reads for inspecting specific implementation details. - -## Token Efficiency Rules - -- ALWAYS start with `mcp_code-review-g_get_minimal_context_tool` before any other graph tool. -- Use `detail_level="minimal"` on all calls. Only escalate to `"standard"` when minimal is insufficient. -- Target: complete any debug task in ≤5 graph tool calls and ≤800 total output tokens. diff --git a/.github/skills/code-review-graph-explore/SKILL.md b/.github/skills/code-review-graph-explore/SKILL.md deleted file mode 100644 index ea1aef9a7..000000000 --- a/.github/skills/code-review-graph-explore/SKILL.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: code-review-graph-explore -description: Navigate and understand the codebase structure using the code-review-graph knowledge graph. Use instead of #tool:search/fileSearch or #tool:search/textSearch when the goal is architecture discovery, module mapping, or understanding relationships between components. ---- - -# Explore Codebase with code-review-graph - -Use the code-review-graph MCP tools to explore and understand the codebase. - -## Steps - -1. Start with `mcp_code-review-g_get_minimal_context_tool` with `task=""` before anything else. -2. Run `mcp_code-review-g_list_graph_stats_tool` to see overall codebase metrics. -3. Run `mcp_code-review-g_get_architecture_overview_tool` for high-level community structure. -4. Use `mcp_code-review-g_list_communities_tool` to find major modules, then `mcp_code-review-g_get_community_tool` for details. -5. Use `mcp_code-review-g_semantic_search_nodes_tool` to find specific functions or classes. -6. Use `mcp_code-review-g_query_graph_tool` with patterns like `callers_of`, `callees_of`, `imports_of` to trace relationships. -7. Use `mcp_code-review-g_list_flows_tool` and `mcp_code-review-g_get_flow_tool` to understand execution paths. - -## Tips - -- Start broad (stats, architecture) then narrow down to specific areas. -- Use `children_of` on a file to see all its functions and classes. -- Use `mcp_code-review-g_find_large_functions_tool` to identify complex code. -- Prefer graph tools over `#tool:search/textSearch` or `#tool:search/fileSearch` for relationship and structure questions; fall back to text search only when looking for an exact string not modeled in the graph. - -## Token Efficiency Rules - -- ALWAYS start with `mcp_code-review-g_get_minimal_context_tool` before any other graph tool. -- Use `detail_level="minimal"` on all calls. Only escalate to `"standard"` when minimal is insufficient. -- Target: complete any exploration task in ≤5 graph tool calls and ≤800 total output tokens. diff --git a/.github/skills/code-review-graph-refactor/SKILL.md b/.github/skills/code-review-graph-refactor/SKILL.md deleted file mode 100644 index 6e2fb266b..000000000 --- a/.github/skills/code-review-graph-refactor/SKILL.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: code-review-graph-refactor -description: Plan and execute safe refactoring using the code-review-graph dependency analysis. Use when renaming symbols, removing dead code, or decomposing large functions — instead of manually grepping callers with #tool:search/textSearch. ---- - -# Refactor Safely with code-review-graph - -Use the knowledge graph to plan and execute refactoring with confidence. - -## Steps - -1. Start with `mcp_code-review-g_get_minimal_context_tool` with `task=""` to orient. -2. Use `mcp_code-review-g_refactor_tool` with `mode="suggest"` for community-driven refactoring suggestions. -3. Use `mcp_code-review-g_refactor_tool` with `mode="dead_code"` to find unreferenced code. -4. For renames, use `mcp_code-review-g_refactor_tool` with `mode="rename"` to preview all affected locations. -5. Use `mcp_code-review-g_apply_refactor_tool` with the `refactor_id` to apply renames. -6. After changes, run `mcp_code-review-g_detect_changes_tool` to verify the refactoring impact. - -## Safety Checks - -- Always preview before applying (`rename` mode gives you an edit list — review it before calling `apply_refactor_tool`). -- Check `mcp_code-review-g_get_impact_radius_tool` before major refactors. -- Use `mcp_code-review-g_get_affected_flows_tool` to ensure no critical paths are broken. -- Use `mcp_code-review-g_find_large_functions_tool` to identify decomposition targets. -- Only open files with `#tool:read/readFile` when you need to verify specific implementation lines after the graph has confirmed the blast radius. - -## Token Efficiency Rules - -- ALWAYS start with `mcp_code-review-g_get_minimal_context_tool` before any other graph tool. -- Use `detail_level="minimal"` on all calls. Only escalate to `"standard"` when minimal is insufficient. -- Target: complete any refactor-planning task in ≤5 graph tool calls and ≤800 total output tokens. diff --git a/.github/skills/code-review-graph-review/SKILL.md b/.github/skills/code-review-graph-review/SKILL.md deleted file mode 100644 index 0e649bdea..000000000 --- a/.github/skills/code-review-graph-review/SKILL.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: code-review-graph-review -description: Perform a structured, risk-aware code review using the code-review-graph change detection and impact analysis. Use when reviewing a PR or branch diff instead of manually tracing callers with #tool:search/textSearch. ---- - -# Review Changes with code-review-graph - -Perform a thorough, risk-aware code review using the knowledge graph. - -## Steps - -1. Start with `mcp_code-review-g_get_minimal_context_tool` with `task="review changes"` to orient. -2. Run `mcp_code-review-g_detect_changes_tool` to get risk-scored change analysis. -3. Run `mcp_code-review-g_get_affected_flows_tool` to find impacted execution paths. -4. For each high-risk function, run `mcp_code-review-g_query_graph_tool` with `pattern="tests_for"` to check test coverage. -5. Run `mcp_code-review-g_get_impact_radius_tool` to understand the blast radius. -6. For any untested changes, suggest specific test cases. - -## Output Format - -Provide findings grouped by risk level (high / medium / low) with: - -- What changed and why it matters -- Test coverage status -- Suggested improvements -- Overall merge recommendation - -Use `#tool:read/readFile` only to verify specific implementation lines when the graph result requires it — do not read whole files to discover relationships. - -## Token Efficiency Rules - -- ALWAYS start with `mcp_code-review-g_get_minimal_context_tool` before any other graph tool. -- Use `detail_level="minimal"` on all calls. Only escalate to `"standard"` when minimal is insufficient. -- Target: complete any review task in ≤5 graph tool calls and ≤800 total output tokens. diff --git a/.github/skills/jenv-gradle-low-ram/SKILL.md b/.github/skills/jenv-gradle-low-ram/SKILL.md deleted file mode 100644 index f44e4b924..000000000 --- a/.github/skills/jenv-gradle-low-ram/SKILL.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -name: jenv-gradle-low-ram -description: 'Align jenv with .java-version and run Gradle reliably on low-RAM machines. Use for Java mismatch errors, Gradle OOMs, daemon memory pressure, and selecting safe build flags.' -argument-hint: 'Describe your target task and available RAM, for example: assembleDebug on 8GB RAM' ---- -# Jenv + Gradle Low-RAM Workflow - -## What This Skill Produces - -- A shell where `java` and Gradle use the Java version pinned by `.java-version`. -- A repeatable Gradle command profile tuned for constrained memory. -- Verification checks to confirm version alignment and build stability. - -## When To Use - -- Any time when `./gradlew` is about to be invoked in this repository. -- Especially important for low-RAM machines where daemon/worker pressure can destabilize builds. -- Required when verifying that Java from `.java-version` is the active runtime for Gradle. - -## Procedure - -1. Detect the required Java version. - -```bash -cat .java-version -``` - -2. Verify `jenv` is installed and initialized. - -```bash -command -v jenv -jenv versions -jenv version -``` - -Decision point: - -- If `jenv` is not found, install and initialize it in your shell startup. -- If `jenv` is found but `jenv version` does not match `.java-version`, continue to step 3. - -3. Align local Java to the repository pin. - -```bash -required_java="$(cat .java-version)" -jenv local "$required_java" -``` - -Decision point: - -- If `jenv local` fails because the version is missing, install that JDK and run `jenv add `, then retry. - -4. Confirm runtime alignment before any Gradle task. - -```bash -java -version -./gradlew -version -``` - -Quality check: - -- Gradle JVM version in `./gradlew -version` must match `.java-version` major version. - -5. Run Gradle with low-memory-safe defaults. - -Preferred one-off profile: - -```bash -./gradlew --no-daemon --max-workers=2 \ - -Dorg.gradle.jvmargs="-Xmx1536m -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8" \ - assembleDebug -``` - -For tests: - -```bash -./gradlew --no-daemon --max-workers=2 \ - -Dorg.gradle.jvmargs="-Xmx1792m -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8" \ - testDebugUnitTest -``` - -6. If memory pressure continues, downgrade concurrency. - -```bash -./gradlew --no-daemon --max-workers=1 -Dorg.gradle.parallel=false assembleDebug -``` - -7. If builds are stable and you want persistence, prefer user-local Gradle overrides (avoid committing repo-wide memory changes). - -Suggested entries for `~/.gradle/gradle.properties`: - -```properties -org.gradle.daemon=false -org.gradle.parallel=false -org.gradle.workers.max=2 -org.gradle.jvmargs=-Xmx1536m -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 -``` - -## Troubleshooting Branches - -- `jenv version` correct but `java -version` wrong: - Ensure shell init runs `eval "$(jenv init -)"` and enable export plugin with `jenv enable-plugin export`. -- `Gradle daemon disappeared unexpectedly`: - Retry with `--no-daemon --max-workers=1` and lower `-Xmx` if the OS is reclaiming memory aggressively. -- Kotlin compile OOM: - Keep workers low, disable parallel, and run module-targeted tasks (for example `:feature:media:assembleDebug`) instead of full-project builds. - -## Completion Checks - -- `.java-version` and `jenv version` resolve to the same Java release. -- `./gradlew -version` reports the expected JVM. -- Target Gradle task completes without OOM or daemon crash. -- Machine remains responsive during build (no prolonged swap thrash). - -## Fast Invocation Examples - -- "Align my shell to `.java-version` and run debug build with 8GB RAM settings" -- "I get class file major version errors; fix jenv and verify Gradle JVM" -- "Run unit tests with a low-memory Gradle profile and fallback if OOM occurs" diff --git a/.github/skills/string-resource-inline-comments/SKILL.md b/.github/skills/string-resource-inline-comments/SKILL.md deleted file mode 100644 index ed476bbf8..000000000 --- a/.github/skills/string-resource-inline-comments/SKILL.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -name: string-resource-inline-comments -description: 'Audit Android strings.xml files so every resource has an inline XML comment for POEditor translator context. Use when adding or editing string resources, documenting placeholders, reviewing localization context, or fixing uncommented strings after feature work.' ---- - -# Skill: Inline Comments for Android String Resources - -Use this skill when the task is not just naming strings correctly, but making sure translators get - enough context from the XML comments that sit directly above each resource block. - -## When to Use - -- Adding new entries to any `strings.xml` file. -- Editing existing Android string resources during feature work. -- Reviewing PRs for missing translator context. -- Cleaning up files where new strings were added without comments. -- Tightening repo guidance after a missed comment or localization regression. - -## Outcome - -- Every touched resource block in `strings.xml` has an immediate XML comment. -- Comments explain where the text appears, what it does, and what placeholders mean. -- Repo-level instructions and skills are updated when the gap came from unclear guidance. - -For Android platform behavior such as escaping, formatting, arrays, plurals, and styled text, -also consult the official Android guidance: https://developer.android.com/guide/topics/resources/string-resource - -## Procedure - -1. Open the touched `strings.xml` file and inspect the full edited block, not just the newest line. -2. Add an XML comment immediately above each touched resource block. -3. Write comments for translators, not engineers. -4. Explain placeholders such as `%1$s` or `%2$d`, plus any tone or space constraints. -5. Keep comments one resource above the matching block; do not use one comment for several unrelated entries. -6. Re-read the edited section and confirm no new resource was left uncommented. -7. If the miss happened because repo guidance was weak, update the relevant instruction and string-resource skill in the same change. - -## Comment Patterns - -```xml - -Retry - - -No episodes found - - -No summary available for %1$s at this time. -``` - -## Quality Gates - -- Every touched resource block has a comment directly above it. -- Comments mention screen, state, or interaction context. -- Placeholder variables are documented. -- Android-specific escaping or plural behavior is checked when the text uses those features. -- Comments are concise but specific enough for POEditor translators. -- XML remains cleanly formatted and easy to scan. - -## Common Failure Modes - -- Adding a batch of strings and commenting only the first one. -- Leaving a legacy string undocumented because it was already in the file. -- Forgetting that `plurals` and `string-array` blocks also need translator context. -- Writing comments like "String for button" that give no usable localization context. diff --git a/.github/skills/string-resources-convention/SKILL.md b/.github/skills/string-resources-convention/SKILL.md deleted file mode 100644 index ad48d40df..000000000 --- a/.github/skills/string-resources-convention/SKILL.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -name: string-resources-convention -description: 'Android strings.xml naming, XML translator comments, and POEditor context conventions. Use when adding, renaming, or reviewing string resources, placeholder documentation, and localization consistency.' ---- - -# Skill: String Resource Naming Conventions - -This skill defines the naming policy for Android string resources and the mandatory translator -context rules for `strings.xml`. - -For Android platform behavior around escaping, formatting, plurals, arrays, and styled text, -load [Android string resource best practices](./references/android-string-resource-best-practices.md). - -## Naming pattern - -`{prefix}_{module_or_context}_{specific_identifier}` - -## Standard prefixes - -| Prefix | Usage | -|---|---| -| `label_` | Field labels, section headers, descriptive text | -| `title_` | Screen titles, dialog titles, major headings | -| `subtitle_` | Secondary headings, descriptive subtitles | -| `placeholder_` | Input hints, empty state text | -| `action_` | Button text, menu items, actionable text | -| `message_` | User messages, notifications, feedback | -| `error_` | Error messages, validation messages | -| `hint_` | Helper text, tooltips, guidance | -| `description_` | Accessibility descriptions, detailed explanations | - -## Module context guidelines - -- Use **underscores** to separate words: `media_list_editor` not `medialisteditor`. -- Be specific but concise: `media_list` not `medialist`, `episode_progress` not `progress`. -- Include feature/module context for feature-specific strings. -- Use generic context for shared strings: `label_loading`, `action_save`, `error_network`. -- Prefer positional placeholders such as `%1$s` and `%2$d` for translatable formatted strings. -- Add `formatted="true"` for strings with parameters (e.g., `%1$s`, `%1$d`). - -## Platform best practices - -- Follow Android escaping rules for apostrophes, quotes, `@`, `?`, newline, tab, and Unicode. -- Escape literal apostrophes in normal text with `\'` unless the entire string is deliberately wrapped in double quotes. -- Treat any literal `\u` sequence as dangerous unless you are intentionally writing a Unicode code point such as `\u0027`. -- Use `` only when the grammar genuinely changes with quantity. -- Prefer quantity-neutral wording when plurals are avoidable. -- Use `getText()` when styled text must be preserved instead of flattened to plain text. -- Treat HTML markup and `` usage as platform-level behavior, not ad hoc XML tricks. - -## Good vs bad examples - -**Good:** -```xml -Watch Status -Profile Settings -Search anime and manga... -Mark as Watched -Authentication failed -``` - -**Bad:** -```xml -Watch Status -Profile Settings -Search anime and manga... -Mark as Watched -Authentication failed -``` - -## POEditor translator comments (required) - -Always add an XML comment immediately before each string resource. POEditor displays these to -community translators. - -This is mandatory for every touched resource block in `strings.xml`, including ``, -``, and ``. Do not add a single shared comment for multiple unrelated -resources, and do not leave new strings uncommented at the end of a file. - -**Format:** -```xml - -Not rated - - -Save Changes - - -Progress %1$d%% -``` - -**Effective comment guidelines:** -- **Context**: where/when the string appears in the app. -- **Purpose**: what action or information it represents. -- **Variables**: what each `%1$s` / `%1$d` parameter means. -- **Tone**: formal, casual, urgent, etc. if relevant. -- **Character limits**: note UI space constraints when applicable. - -## Audit checklist - -Use this checklist before finishing any `strings.xml` edit: - -1. Scan the touched file or edited block for uncommented resources. -2. Add an XML comment immediately above every new or modified resource block. -3. For formatted strings, explain each placeholder and any escaping requirements. -4. Keep indentation and comment style consistent with the surrounding file. -5. Re-read the edited section to confirm there are no trailing uncommented additions. - -## Migration guidelines - -- Prefer the new naming convention when updating existing string resources. -- Add a replacement comment: ``. -- Update all code references when renaming a string. -- Ensure plurals and translations follow the same naming pattern. - -## Common misses - -- Adding new strings at the bottom of a file without comments. -- Documenting only the first string in a cluster of related additions. -- Forgetting to explain `%1$s`, `%2$d`, or similar placeholders. -- Using non-positional placeholders or incorrect escaping in translatable strings. -- Leaving a literal apostrophe unescaped and only discovering it during AAPT resource flattening. -- Writing copy that accidentally contains a `\u` sequence Android tries to interpret as an invalid Unicode escape. -- Reaching for `` when a quantity-neutral phrase would be safer. -- Writing engineering notes instead of translator-facing context. diff --git a/.github/skills/string-resources-convention/references/android-string-resource-best-practices.md b/.github/skills/string-resources-convention/references/android-string-resource-best-practices.md deleted file mode 100644 index 7e93b61c7..000000000 --- a/.github/skills/string-resources-convention/references/android-string-resource-best-practices.md +++ /dev/null @@ -1,71 +0,0 @@ -# Android String Resource Best Practices - -Source: https://developer.android.com/guide/topics/resources/string-resource - -Use this reference when a string-resource task depends on Android platform behavior, not just this -repo's naming or translator-comment conventions. - -## Use This For - -- Escaping apostrophes, quotes, `@`, `?`, newlines, tabs, and Unicode characters. -- Positional formatting placeholders such as `%1$s` and `%2$d`. -- Choosing between ``, ``, and ``. -- Preserving styled text or converting HTML markup safely. -- Avoiding localization bugs caused by whitespace, plurals, or inline markup. - -## Core Platform Rules - -### 1. Escape special characters correctly - -- Apostrophes must be escaped with `\'` unless the string is wrapped in double quotes. -- Double quotes must be escaped with `\"` when they should appear literally. -- Escape `@` as `\@` and `?` as `\?` when they should not be treated as resource syntax. -- Use `\n` for new lines, `\t` for tabs, and `\uXXXX` for explicit Unicode characters. -- Never leave a stray `\u` sequence in plain copy. Android will try to parse it as a Unicode escape and fail resource flattening if the next four characters are not valid hex. -- Android collapses repeated whitespace unless the relevant region is wrapped in double quotes. - -### 2. Prefer positional formatting placeholders - -- Use `%1$s`, `%2$d`, and similar positional placeholders in translatable strings. -- Mark formatted resources with `formatted="true"` when the file convention expects it. -- Document every placeholder in the XML translator comment immediately above the resource. -- Use `getString(id, args...)` for formatted strings and `getText(id)` when you need to preserve styled text. - -### 3. Use plurals only for grammatical quantity - -- Use `` only when grammar changes with count. -- Always provide at least `one` and `other`; translators determine whether additional quantities are needed. -- If the displayed message includes the count, pass the count twice to `getQuantityString(...)`: once for selection and once for formatting. -- Prefer quantity-neutral phrasing when acceptable because it reduces localization complexity. - -### 4. Choose the right resource type - -- Use `` for single text values. -- Use `` for fixed arrays of text choices. -- Use `` for grammatically count-sensitive copy. -- Keep translator comments on every touched resource block, including arrays and plurals. - -### 5. Be careful with styled text - -- Basic HTML tags such as ``, ``, ``, `
`, `
    `, and `
  • ` are supported in string resources. -- If a string is both formatted and styled, HTML tags usually need to be escaped in XML and rehydrated with `Html.fromHtml(...)` after formatting. -- HTML-encode dynamic text before passing it into an HTML-formatted string. -- For more complex or reusable styling, prefer spans or `` tags over fragile inline HTML. -- If using ``, apply the annotation consistently across every translation. - -## Review Checklist - -1. Confirm the correct resource type: string, array, or plurals. -2. Check for Android-specific escaping needs before changing punctuation. -3. Use positional placeholders and document them in XML comments. -4. Validate whether styled text should remain plain text, HTML, or annotations. -5. For plurals, confirm the copy is truly grammatically count-sensitive. - -## Common Failure Modes - -- Unescaped apostrophes causing AAPT resource compilation failures. -- Copy that includes a literal `\u` sequence, which AAPT treats as an invalid Unicode escape during flattening. -- Non-positional placeholders in translatable text. -- Using plurals for UI state labels that are not grammatically quantity-driven. -- Mixing HTML markup with formatting arguments without escaping or `Html.fromHtml(...)`. -- Forgetting that translator context must still exist even when Android syntax is technically correct. diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index afa7d16a7..95764dfb4 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -39,6 +39,12 @@ dependencies { /** Depend on the android gradle plugin, since we want to access it in our plugin */ implementation(libs.android.gradle.plugin) + /** Depend on the android gradle plugin kotlin extension, provides com.android.legacy-kapt */ + implementation(libs.android.gradle.plugin.kotlin) + + /** Depend on the KSP Gradle plugin, since we want to apply it in our plugin */ + implementation(libs.google.devtools.ksp.gradle) + /** Depend on the kotlin plugin, since we want to access it in our plugin */ implementation(libs.jetbrains.kotlin.gradle) diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/extensions/DependencyHandlerExtensions.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/extensions/DependencyHandlerExtensions.kt index 44369aaf7..5b058e71d 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/extensions/DependencyHandlerExtensions.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/extensions/DependencyHandlerExtensions.kt @@ -29,6 +29,7 @@ private enum class DependencyType(val configurationName: String) { COMPILE("compileOnly"), DEBUG("debugOnly"), KAPT("kapt"), + KSP("ksp"), IMPLEMENTATION("implementation"), DEBUG_IMPLEMENTATION("debugImplementation"), RELEASE_IMPLEMENTATION("releaseImplementation"), @@ -129,6 +130,19 @@ internal fun DependencyHandler.kapt( dependencyConfiguration: (ExternalModuleDependency.() -> Unit)? = null ) = addDependency(dependencyNotation, DependencyType.KAPT, dependencyConfiguration) +/** + * Adds a dependency to the given configuration, and configures the dependency using the given closure. + * + * @param dependencyNotation The dependency notation, in one of the notations described above. + * @param dependencyConfiguration The closure to use to configure the dependency. + * + * @return The dependency. + */ +internal fun DependencyHandler.ksp( + dependencyNotation: Any, + dependencyConfiguration: (ExternalModuleDependency.() -> Unit)? = null +) = addDependency(dependencyNotation, DependencyType.KSP, dependencyConfiguration) + /** * Adds a dependency to the given configuration, and configures the dependency using the given closure. * diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectConfiguration.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectConfiguration.kt index 099bcc770..6a7694a55 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectConfiguration.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectConfiguration.kt @@ -17,8 +17,7 @@ package co.anitrend.buildSrc.plugins.components -import co.anitrend.buildSrc.extensions.baseAppExtension -import co.anitrend.buildSrc.extensions.baseExtension +import co.anitrend.buildSrc.extensions.applicationExtension import co.anitrend.buildSrc.extensions.hasComposeSupport import co.anitrend.buildSrc.extensions.hasCoroutineSupport import co.anitrend.buildSrc.extensions.isAppModule @@ -27,8 +26,6 @@ import co.anitrend.buildSrc.extensions.libraryExtension import co.anitrend.buildSrc.extensions.matchesAppModule import co.anitrend.buildSrc.extensions.matchesTaskModule import co.anitrend.buildSrc.extensions.props -import com.android.build.gradle.internal.api.BaseVariantOutputImpl -import com.android.build.gradle.internal.dsl.DefaultConfig import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.tasks.testing.Test @@ -39,7 +36,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile import java.io.File private fun Project.configureBuildFlavours() { - baseAppExtension().run { + applicationExtension().apply { flavorDimensions.add("default") productFlavors { create("google") { @@ -51,116 +48,129 @@ private fun Project.configureBuildFlavours() { versionNameSuffix = "-github" } } - applicationVariants.all { - outputs.map { it as BaseVariantOutputImpl }.forEach { output -> - val original = output.outputFileName - output.outputFileName = original - } - } } } -private fun DefaultConfig.applyAdditionalConfiguration(project: Project) { - if (project.isAppModule()) { - applicationId = "co.anitrend" - project.baseAppExtension().run { - buildFeatures { - viewBinding = true - compose = true +private fun Project.configureLint() = applicationExtension().lint { + abortOnError = false + ignoreWarnings = false + ignoreTestSources = true +} + +private fun Project.configureAppAndroid() { + val ext = applicationExtension() + createSigningConfiguration(ext) + configureLint() + configureBuildFlavours() + ext.apply { + compileSdk = 36 + defaultConfig { + applicationId = "co.anitrend" + minSdk = 24 + targetSdk = 36 + versionCode = props[PropertyTypes.CODE].toInt() + versionName = props[PropertyTypes.VERSION] + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + buildFeatures { + viewBinding = true + compose = true + } + buildTypes { + getByName("release") { + isMinifyEnabled = true + isShrinkResources = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + projectDir.resolve("proguard-rules.pro"), + rootDir.resolve("proguard-common.pro"), + ) + if (project.file(".config/keystore.properties").exists()) + signingConfig = signingConfigs.getByName("release") + } + getByName("debug") { + isDebuggable = true + isMinifyEnabled = false + isShrinkResources = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + projectDir.resolve("proguard-rules.pro"), + rootDir.resolve("proguard-common.pro"), + ) } } - } - else - consumerProguardFiles.add(File("consumer-rules.pro")) - - if (!project.matchesAppModule() && !project.matchesTaskModule()) { - // checking app module again since the group for app modules is - // `:app:` while the main app is just `:app` - if (!project.isAppModule() && project.hasComposeSupport()) { - project.logger.lifecycle("Applying view binding and compose build features for module -> ${project.path}") - project.libraryExtension().buildFeatures { - viewBinding = true - if (project.hasComposeSupport()) - compose = true + packaging { + resources.excludes.add("META-INF/NOTICE.*") + resources.excludes.add("META-INF/LICENSE*") + resources.excludes.add("META-INF/*kotlin_module") + resources.excludes.add("META-INF/proguard/*") + resources.excludes.add("META-INF/*.version") + resources.excludes.add("META-INF/*.properties") + resources.excludes.add("/*.properties") + resources.excludes.add("fabric/*.properties") + } + sourceSets { + map { androidSourceSet -> + androidSourceSet.java.srcDir( + "src/${androidSourceSet.name}/kotlin" + ) } } - - project.logger.lifecycle("Applying vector drawables configuration for module -> ${project.path}") - vectorDrawables.useSupportLibrary = true - } -} - -private fun Project.configureLint() = baseAppExtension().run { - lint { - abortOnError = false - ignoreWarnings = false - ignoreTestSources = true + testOptions { + unitTests { + isReturnDefaultValues = true + isIncludeAndroidResources = true + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } } } -internal fun Project.configureAndroid(): Unit = baseExtension().run { - compileSdkVersion(36) +private fun Project.configureLibraryAndroid() = libraryExtension().apply { + compileSdk = 36 defaultConfig { minSdk = 24 - targetSdk = 36 - versionCode = props[PropertyTypes.CODE].toInt() - versionName = props[PropertyTypes.VERSION] testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - applyAdditionalConfiguration(project) + vectorDrawables.useSupportLibrary = true } - - if (isAppModule()) { - configureLint() - configureBuildFlavours() - createSigningConfiguration(this) + if (!matchesAppModule() && !matchesTaskModule() && hasComposeSupport()) { + logger.lifecycle("Applying view binding and compose build features for module -> $path") + buildFeatures { + viewBinding = true + compose = true + } } - buildTypes { getByName("release") { isMinifyEnabled = true - isShrinkResources = false - isTestCoverageEnabled = false proguardFiles( - getDefaultProguardFile( - "proguard-android-optimize.txt" - ), + getDefaultProguardFile("proguard-android-optimize.txt"), projectDir.resolve("proguard-rules.pro"), rootDir.resolve("proguard-common.pro"), ) - if (project.file(".config/keystore.properties").exists()) - signingConfig = signingConfigs.getByName("release") } - getByName("debug") { - isDebuggable = true isMinifyEnabled = false - isShrinkResources = false - isTestCoverageEnabled = true proguardFiles( - getDefaultProguardFile( - "proguard-android-optimize.txt" - ), + getDefaultProguardFile("proguard-android-optimize.txt"), projectDir.resolve("proguard-rules.pro"), rootDir.resolve("proguard-common.pro"), ) } } - - packagingOptions { + packaging { resources.excludes.add("META-INF/NOTICE.*") resources.excludes.add("META-INF/LICENSE*") - // Exclude potential duplicate kotlin_module files resources.excludes.add("META-INF/*kotlin_module") - // Exclude consumer proguard files resources.excludes.add("META-INF/proguard/*") - // Exclude AndroidX version files resources.excludes.add("META-INF/*.version") - // Exclude the Firebase/Fabric/other random properties files resources.excludes.add("META-INF/*.properties") resources.excludes.add("/*.properties") resources.excludes.add("fabric/*.properties") } - sourceSets { map { androidSourceSet -> androidSourceSet.java.srcDir( @@ -168,18 +178,21 @@ internal fun Project.configureAndroid(): Unit = baseExtension().run { ) } } - testOptions { unitTests { isReturnDefaultValues = true isIncludeAndroidResources = true } } - compileOptions { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 } +} + +internal fun Project.configureAndroid() { + if (isAppModule()) configureAppAndroid() + else configureLibraryAndroid() tasks.withType(KotlinJvmCompile::class.java) { compilerOptions { @@ -233,14 +246,6 @@ internal fun Project.configureAndroid(): Unit = baseExtension().run { } } - // Disabling experimental language version, causing issues with KAPT + Room - //tasks.withType(KotlinCompilationTask::class.java) - // .configureEach { - // compilerOptions - // .languageVersion - // .set(KotlinVersion.KOTLIN_1_9) - // } - tasks.register("makeProguard") { val projectDirectory = project.layout.projectDirectory val buildDirectory = project.layout.buildDirectory diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectDependencies.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectDependencies.kt index 97336e176..00dbd9002 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectDependencies.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectDependencies.kt @@ -27,7 +27,7 @@ import co.anitrend.buildSrc.extensions.isAndroidCoreModule import co.anitrend.buildSrc.extensions.isAppModule import co.anitrend.buildSrc.extensions.isDataModule import co.anitrend.buildSrc.extensions.isDomainModule -import co.anitrend.buildSrc.extensions.kapt +import co.anitrend.buildSrc.extensions.ksp import co.anitrend.buildSrc.extensions.libs import co.anitrend.buildSrc.extensions.matchesAndroidModule import co.anitrend.buildSrc.extensions.matchesAppModule @@ -201,7 +201,7 @@ private fun Project.applyDataModuleDependencies() { dependencies.implementation(libs.androidx.paging.runtime.ktx) dependencies.implementation(libs.androidx.room.runtime) dependencies.implementation(libs.androidx.room.ktx) - dependencies.kapt(libs.androidx.room.compiler) + dependencies.ksp(libs.androidx.room.compiler) dependencies.implementation(libs.square.okhttp.logging) dependencies.implementation(libs.square.retrofit) @@ -241,7 +241,7 @@ private fun Project.applyDataModuleGroupDependencies() { dependencies.implementation(libs.androidx.room.runtime) dependencies.implementation(libs.androidx.room.ktx) - dependencies.kapt(libs.androidx.room.compiler) + dependencies.ksp(libs.androidx.room.compiler) dependencies.implementation(libs.square.okhttp.logging) dependencies.implementation(libs.square.retrofit) diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectOptions.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectOptions.kt index 385cbcf77..4ffb6167c 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectOptions.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectOptions.kt @@ -23,9 +23,9 @@ import co.anitrend.buildSrc.extensions.isDataModule import co.anitrend.buildSrc.extensions.libraryExtension import co.anitrend.buildSrc.extensions.matchesDataModule import co.anitrend.buildSrc.extensions.props +import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.LibraryBuildType import com.android.build.api.dsl.LibraryDefaultConfig -import com.android.build.gradle.BaseExtension import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import java.util.Properties @@ -88,7 +88,7 @@ private fun LibraryDefaultConfig.applyRoomCompilerOptions(project: Project) { } } -internal fun Project.createSigningConfiguration(extension: BaseExtension) { +internal fun Project.createSigningConfiguration(extension: ApplicationExtension) { var properties: Properties? = null val keyStoreFile = project.file(".config/keystore.properties") if (keyStoreFile.exists()) @@ -102,10 +102,10 @@ internal fun Project.createSigningConfiguration(extension: BaseExtension) { properties?.also { extension.signingConfigs { create("release") { - storeFile(file(it["STORE_FILE"] as String)) - storePassword(it["STORE_PASSWORD"] as String) - keyAlias(it["STORE_KEY_ALIAS"] as String) - keyPassword(it["STORE_KEY_PASSWORD"] as String) + storeFile = file(it["STORE_FILE"] as String) + storePassword = it["STORE_PASSWORD"] as String + keyAlias = it["STORE_KEY_ALIAS"] as String + keyPassword = it["STORE_KEY_PASSWORD"] as String } } } diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectPlugins.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectPlugins.kt index 60699ebfb..8f7768a6b 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectPlugins.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/components/ProjectPlugins.kt @@ -1,27 +1,10 @@ -/* - * Copyright (C) 2020 AniTrend - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package co.anitrend.buildSrc.plugins.components import co.anitrend.buildSrc.extensions.androidComponents import co.anitrend.buildSrc.extensions.hasComposeSupport -import co.anitrend.buildSrc.extensions.hasKaptSupport -import co.anitrend.buildSrc.extensions.hasKotlinAndroidExtensionSupport import co.anitrend.buildSrc.extensions.isAppModule +import co.anitrend.buildSrc.extensions.isDataGroupModule +import co.anitrend.buildSrc.extensions.isDataModule import org.gradle.api.Project import org.gradle.api.plugins.PluginContainer @@ -30,24 +13,20 @@ private fun addAndroidPlugin(project: Project, pluginContainer: PluginContainer) else pluginContainer.apply("com.android.library") } -private fun addKotlinAndroidPlugin(pluginContainer: PluginContainer) { - pluginContainer.apply("kotlin-android") - pluginContainer.apply("com.diffplug.spotless") -} - private fun addAnnotationProcessor(project: Project, pluginContainer: PluginContainer) { - if (project.hasKaptSupport()) - pluginContainer.apply("kotlin-kapt") + // KSP for all data modules + if (project.isDataGroupModule()) { + pluginContainer.apply("com.google.devtools.ksp") + } } private fun addKotlinAndroidExtensions(project: Project, pluginContainer: PluginContainer) { - if (project.hasKotlinAndroidExtensionSupport()) - pluginContainer.apply("kotlin-parcelize") + pluginContainer.apply("kotlin-parcelize") + pluginContainer.apply("com.diffplug.spotless") } internal fun Project.configurePlugins() { addAndroidPlugin(project, plugins) - addKotlinAndroidPlugin(plugins) addKotlinAndroidExtensions(project, plugins) addAnnotationProcessor(project, plugins) diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/strategy/DependencyStrategy.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/strategy/DependencyStrategy.kt index da003e5ff..537327468 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/strategy/DependencyStrategy.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/plugins/strategy/DependencyStrategy.kt @@ -38,6 +38,10 @@ internal class DependencyStrategy(private val project: Project) { test(project.libs.jetbrains.kotlin.test) test(project.libs.mockk) test(project.libs.junit) + test(project.libs.junit.platform.launcher) + test(project.libs.junit.jupiter.api) + test(project.libs.junit.jupiter.engine) + test(project.libs.junit.vintage.engine) /** Work around for crashing tests when startup. initializer is not found in *.test packages */ androidTest(project.libs.androidx.startup.runtime) diff --git a/buildSrc/src/main/java/co/anitrend/buildSrc/resolver/ConfigurationResolver.kt b/buildSrc/src/main/java/co/anitrend/buildSrc/resolver/ConfigurationResolver.kt index b82351760..442aa30ce 100644 --- a/buildSrc/src/main/java/co/anitrend/buildSrc/resolver/ConfigurationResolver.kt +++ b/buildSrc/src/main/java/co/anitrend/buildSrc/resolver/ConfigurationResolver.kt @@ -23,9 +23,15 @@ import org.gradle.api.artifacts.Configuration fun Configuration.handleConflicts(project: Project): Unit = with(project) { resolutionStrategy.eachDependency { + if (requested.name == "kotlin-android-extensions-runtime") { + useTarget("org.jetbrains.kotlin:kotlin-parcelize-runtime:${libs.versions.jetbrains.kotlin.get()}") + } when (requested.group) { "org.jetbrains.kotlin" -> { - if (requested.name.matches(Regex("kotlin-.*"))) { + if ( + requested.name.matches(Regex("kotlin-.*")) && + requested.name != "kotlin-android-extensions-runtime" + ) { useVersion(libs.versions.jetbrains.kotlin.get()) } } diff --git a/data/android/build.gradle.kts b/data/android/build.gradle.kts index 44de0622b..e049c8374 100644 --- a/data/android/build.gradle.kts +++ b/data/android/build.gradle.kts @@ -39,7 +39,7 @@ dependencies { implementation(libs.anitrend.querybuilder.annotation) implementation(libs.anitrend.querybuilder.core) - implementation(libs.anitrend.querybuilder.core.ext) + implementation(libs.anitrend.querybuilder.ext) } android { diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 77c89e3bd..3601f5378 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -39,7 +39,9 @@ dependencies { implementation(libs.androidx.startup.runtime) implementation(libs.androidx.room.paging) - implementation(libs.anitrend.sync) + implementation(libs.anitrend.sync) { + exclude(group = "org.jetbrains.kotlin", module = "kotlin-android-extensions-runtime") + } implementation(libs.cash.copper) implementation(libs.anitrend.emojify) @@ -47,8 +49,8 @@ dependencies { implementation(libs.anitrend.querybuilder.annotation) implementation(libs.anitrend.querybuilder.core) - implementation(libs.anitrend.querybuilder.core.ext) - kapt(libs.anitrend.querybuilder.processor) + implementation(libs.anitrend.querybuilder.ext) + ksp(libs.anitrend.querybuilder.processor) } android { diff --git a/data/core/build.gradle.kts b/data/core/build.gradle.kts index 8de7f2d65..b53ac75dd 100644 --- a/data/core/build.gradle.kts +++ b/data/core/build.gradle.kts @@ -27,7 +27,7 @@ dependencies { implementation(libs.androidx.collection.ktx) implementation(libs.anitrend.querybuilder.core) - implementation(libs.anitrend.querybuilder.core.ext) + implementation(libs.anitrend.querybuilder.ext) } android { diff --git a/data/core/src/test/kotlin/co/anitrend/data/core/extensions/CommonExtensionsKtTest.kt b/data/core/src/test/kotlin/co/anitrend/data/core/extensions/CommonExtensionsKtTest.kt index 85a606af4..e4d98f9d1 100644 --- a/data/core/src/test/kotlin/co/anitrend/data/core/extensions/CommonExtensionsKtTest.kt +++ b/data/core/src/test/kotlin/co/anitrend/data/core/extensions/CommonExtensionsKtTest.kt @@ -16,8 +16,8 @@ */ package co.anitrend.data.core.extensions -import org.junit.jupiter.api.Assertions.assertEquals -import kotlin.test.Test +import org.junit.Assert.assertEquals +import org.junit.Test class CommonExtensionsKtTest { @Test diff --git a/data/edge/build.gradle.kts b/data/edge/build.gradle.kts index 476bd3c71..266e67033 100644 --- a/data/edge/build.gradle.kts +++ b/data/edge/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { implementation(libs.anitrend.querybuilder.annotation) implementation(libs.anitrend.querybuilder.core) - implementation(libs.anitrend.querybuilder.core.ext) + implementation(libs.anitrend.querybuilder.ext) // Needed for database store (IAniTrendStore) & controller infrastructure // Using direct project path to avoid visibility issue with internal Modules object diff --git a/gradle.properties b/gradle.properties index a566ca85a..ccb01030d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,11 +38,7 @@ android.nonTransitiveRClass=true android.nonFinalResIds=true android.defaults.buildfeatures.resvalues=true android.sdk.defaultTargetSdkToCompileSdkIfUnset=false -android.enableAppCompileTimeRClass=false android.usesSdkInManifest.disallowed=false -android.uniquePackageNames=false android.dependency.useConstraints=true android.r8.strictFullModeForKeepRules=false android.r8.optimizedResourceShrinking=false -android.builtInKotlin=false -android.newDsl=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e1bf49e70..f49ddf820 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,7 +33,7 @@ anitrend-markdown = "0.12.1-alpha01" anitrend-material = "0.2.0" anitrend-retrofit = "0.11.13" anitrend-sync = "0.1.0-alpha01" -anitrend-querybuilder = "0.2.13" +anitrend-querybuilder = "0.3.0" airbnb-paris = "2.2.1" @@ -48,7 +48,7 @@ devrieze-xmlutil = "0.90.3" google-android-material = "1.12.0" jetbrains-dokka = "2.2.0" -jetbrains-kotlin = "2.2.10" +jetbrains-kotlin = "2.3.21" jetbrains-kotlinx-coroutines = "1.10.2" jetbrains-kotlinx-datetime = "0.7.1-0.6.x-compat" jetbrains-kotlinx-serialization = "1.11.0" @@ -78,7 +78,6 @@ google-devtools-ksp = "2.3.7" jetbrains-kotlin-plugin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "jetbrains-kotlin" } google-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "google-devtools-ksp" } jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "jetbrains-kotlin" } -kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "jetbrains-kotlin" } android-library = { id = "com.android.library", version.ref = "gradle-plugin" } @@ -87,6 +86,10 @@ annotatedtext = { module = "io.github.aghajari:AnnotatedText", version.ref = "an threeTenBp = { module = "com.jakewharton.threetenabp:threetenabp", version = "1.4.9" } timber = { module = "com.jakewharton.timber:timber", version = "5.0.1" } junit = { module = "junit:junit", version = "4.13.2" } +junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version = "1.12.2" } +junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version = "5.12.2" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version = "5.12.2" } +junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine", version = "5.12.2" } treessence = { module = "com.github.bastienpaulfr:Treessence", version = "1.1.2" } jsoup = { module = "org.jsoup:jsoup", version = "1.22.2" } @@ -96,6 +99,8 @@ retrofitSerializer = { module = "com.jakewharton.retrofit:retrofit2-kotlinx-seri deeplink = { module = "com.kingsleyadio.deeplink:deeplink", version = "0.4.0" } android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "gradle-plugin" } +android-gradle-plugin-kotlin = { module = "com.android.tools.build:gradle-kotlin", version.ref = "gradle-plugin" } +google-devtools-ksp-gradle = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "google-devtools-ksp" } androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "androidx-activity" } androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" } @@ -209,7 +214,7 @@ anitrend-sync = { module = "com.github.anitrend:support-sync-plugin", version.re anitrend-querybuilder-annotation = { module = "com.github.anitrend.support-query-builder:core", version.ref = "anitrend-querybuilder" } anitrend-querybuilder-core = { module = "com.github.anitrend.support-query-builder:annotations", version.ref = "anitrend-querybuilder" } -anitrend-querybuilder-core-ext = { module = "com.github.anitrend.support-query-builder:core-ext", version.ref = "anitrend-querybuilder" } +anitrend-querybuilder-ext = { module = "com.github.anitrend.support-query-builder:ext", version.ref = "anitrend-querybuilder" } anitrend-querybuilder-processor = { module = "com.github.anitrend.support-query-builder:processor", version.ref = "anitrend-querybuilder" } airbnb-paris = { module = "com.airbnb.android:paris", version.ref = "airbnb-paris" } @@ -246,7 +251,7 @@ google-gson = { module = "com.google.code.gson:gson", version = "2.14.0" } google-firebase-core = { module = "com.google.firebase:firebase-core", version = "21.1.1" } google-firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx", version = "22.5.0" } google-firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics", version = "20.0.5" } -google-firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlytics-gradle", version = "2.9.9" } +google-firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlytics-gradle", version = "3.0.3" } google-firebase-messaging-ktx = { module = "com.google.firebase:firebase-messaging-ktx", version = "24.1.2" } google-flexbox = { module = "com.google.android.flexbox:flexbox", version = "3.0.0" }