diff --git a/.github/workflows/Build.yaml b/.github/workflows/Build.yaml index 0ca4d7536..8679fef93 100644 --- a/.github/workflows/Build.yaml +++ b/.github/workflows/Build.yaml @@ -1,6 +1,7 @@ name: Build on: + workflow_dispatch: push: branches: - main @@ -29,16 +30,19 @@ jobs: - name: Copy CI gradle.properties run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: 21 - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: "https://gradle.com/terms-of-service" + build-scan-terms-of-use-agree: "yes" - name: Check build-logic run: ./gradlew :build-logic:convention:check @@ -73,6 +77,28 @@ jobs: disable_globbing: true commit_message: "🤖 Updates baselines for Dependency Guard" + - name: Update Graphs + run: ./gradlew graphUpdate + + - name: Check Graphs + id: graphs_verify + run: git add -- '**/README.md' && git diff --cached --quiet --exit-code -- '**/README.md' + + - name: Prevent updating graphs if this is a fork + id: checkfork_graphs + continue-on-error: false + if: steps.graphs_verify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository + run: | + echo "::error::Check Graphs failed, please update graphs with: ./gradlew graphUpdate" && exit 1 + + - name: Push new graphs if available + if: steps.graphs_verify.outcome == 'failure' && github.event_name == 'pull_request' + uses: stefanzweifel/git-auto-commit-action@v5 + with: + file_pattern: '**/README.md' + disable_globbing: true + commit_message: "🤖 Updates graphs" + - name: Run all local screenshot tests (Roborazzi) id: screenshotsverify continue-on-error: true @@ -107,7 +133,7 @@ jobs: run: ./gradlew testDemoDebug :lint:test - name: Build all build type and flavor permutations - run: ./gradlew :app:assemble + run: ./gradlew :app:assemble -PminifyWithR8=false - name: Upload build outputs (APKs) uses: actions/upload-artifact@v4 @@ -139,11 +165,26 @@ jobs: name: lint-reports path: '**/build/reports/lint-results-*.html' - - name: Upload lint reports (SARIF) - if: ${{ !cancelled() && hashFiles('**/*.sarif') != '' }} + - name: Upload lint reports (SARIF) for app module + if: ${{ !cancelled() && hashFiles('app/**/*.sarif') != '' }} + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: './app/' + category: app + + - name: Upload lint reports (SARIF) for app-nia-catalog module + if: ${{ !cancelled() && hashFiles('app-nia-catalog/**/*.sarif') != '' }} + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: './app-nia-catalog/' + category: app-nia-catalog + + - name: Upload lint reports (SARIF) for lint module + if: ${{ !cancelled() && hashFiles('lint/**/*.sarif') != '' }} uses: github/codeql-action/upload-sarif@v3 with: - sarif_file: './' + sarif_file: './lint/' + category: lint - name: Check badging run: ./gradlew :app:checkProdReleaseBadging @@ -180,16 +221,19 @@ jobs: - name: Copy CI gradle.properties run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: 17 + java-version: 21 - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: "https://gradle.com/terms-of-service" + build-scan-terms-of-use-agree: "yes" - name: AVD cache uses: actions/cache@v4 diff --git a/.github/workflows/NightlyBaselineProfiles.yaml b/.github/workflows/NightlyBaselineProfiles.yaml index 6e7354476..43d4b73fa 100644 --- a/.github/workflows/NightlyBaselineProfiles.yaml +++ b/.github/workflows/NightlyBaselineProfiles.yaml @@ -1,6 +1,7 @@ name: NightlyBaselineProfiles on: + workflow_dispatch: schedule: - cron: '42 4 * * *' @@ -39,6 +40,9 @@ jobs: uses: gradle/actions/setup-gradle@v4 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: "https://gradle.com/terms-of-service" + build-scan-terms-of-use-agree: "yes" - name: Setup Android SDK uses: android-actions/setup-android@v3 diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index b952ccb50..4c764a51d 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -1,6 +1,7 @@ name: GitHub Release with APKs on: + workflow_dispatch: push: tags: - 'v*' @@ -36,6 +37,9 @@ jobs: uses: gradle/actions/setup-gradle@v4 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: "https://gradle.com/terms-of-service" + build-scan-terms-of-use-agree: "yes" - name: Setup Android SDK uses: android-actions/setup-android@v3 @@ -75,4 +79,4 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: app/build/outputs/apk/demo/release/app-demo-release.apk asset_name: app-demo-release.apk - asset_content_type: application/vnd.android.package-archive + asset_content_type: application/vnd.android.package-archive diff --git a/AGENT.md b/AGENT.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/AGENT.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..efb39ef19 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,58 @@ +# Now in Android Project + +Now in Android is a native Android mobile application written in Kotlin. It provides regular news +about Android development. Users can choose to follow topics, be notified when new content is +available, and bookmark items. + +## Architecture + +This project is a modern Android application that follows the official architecture guidance from Google. It is a reactive, single-activity app that uses the following: + +- **UI:** Built entirely with Jetpack Compose, including Material 3 components and adaptive layouts for different screen sizes. +- **State Management:** Unidirectional Data Flow (UDF) is implemented using Kotlin Coroutines and `Flow`s. `ViewModel`s act as state holders, exposing UI state as streams of data. +- **Dependency Injection:** Hilt is used for dependency injection throughout the app, simplifying the management of dependencies and improving testability. +- **Navigation:** Navigation is handled by Jetpack Navigation 2 for Compose, allowing for a declarative and type-safe way to navigate between screens. +- **Data:** The data layer is implemented using the repository pattern. + - **Local Data:** Room and DataStore are used for local data persistence. + - **Remote Data:** Retrofit and OkHttp are used for fetching data from the network. +- **Background Processing:** WorkManager is used for deferrable background tasks. + +## Modules + +The main Android app lives in the `app/` folder. Feature modules live in `feature/` and core and shared modules in `core/`. + +## Commands to Build & Test + +The app and Android libraries have two product flavors: `demo` and `prod`, and two build types: `debug` and `release`. + +- Build: `./gradlew assemble{Variant}`. Typically `assembleDemoDebug`. +- Fix linting/formatting: `./gradlew --init-script gradle/init.gradle.kts spotlessApply` +- Run local tests: `./gradlew {variant}Test` +- Run single test: `./gradlew {variant}Test --tests "com.example.myapp.MyTestClass"` +- Run local screenshot tests: `./gradlew verifyRoborazziDemoDebug` + +### Instrumented tests + +- Gradle-managed devices to run on device tests: `./gradlew pixel6api31aospDebugAndroidTest`. Also `pixel4api30aospatdDebugAndroidTest` and `pixelcapi30aospatdDebugAndroidTest`. + +### Creating tests + +#### Instrumented tests + +- Tests for UI features should only use `ComposeTestRule` with a `ComponentActivity`. +- Bigger tests live in the `:app` module and they can start activities like `MainActivity`. + +#### Local tests + +- [kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines) for most assertions +- [cashapp/turbine](https://github.com/cashapp/turbine) for complex coroutine tests +- [google/truth](https://github.com/google/truth) for assertions + +## Continuous integration + +- The workflows are defined in `.github/workflows/*.yaml` and they contain various checks. +- Screenshot tests are generated by CI, so they shouldn't be checked into the repo from a workstation. + +## Version control and code location + +- The project uses git and is hosted in https://github.com/android/nowinandroid. diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..db0882010 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @dturner diff --git a/app-nia-catalog/README.md b/app-nia-catalog/README.md index cf6d05f4f..8fd8dcb8d 100644 --- a/app-nia-catalog/README.md +++ b/app-nia-catalog/README.md @@ -1,3 +1,58 @@ -# :app-nia-catalog module -## Dependency graph -![Dependency graph](../docs/images/graphs/dep_graph_app_nia_catalog.svg) +# `:app-nia-catalog` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm-library + :core:ui[ui]:::android-library + end + :app-nia-catalog[app-nia-catalog]:::android-application + + :app-nia-catalog -.-> :core:designsystem + :app-nia-catalog -.-> :core:ui + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt b/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt index 04a864e86..5606bcd1d 100644 --- a/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt +++ b/app-nia-catalog/dependencies/releaseRuntimeClasspath.txt @@ -1,7 +1,7 @@ androidx.activity:activity-compose:1.9.3 androidx.activity:activity-ktx:1.9.3 androidx.activity:activity:1.9.3 -androidx.annotation:annotation-experimental:1.4.1 +androidx.annotation:annotation-experimental:1.5.1 androidx.annotation:annotation-jvm:1.9.1 androidx.annotation:annotation:1.9.1 androidx.appcompat:appcompat-resources:1.6.1 @@ -9,97 +9,111 @@ androidx.arch.core:core-common:2.2.0 androidx.arch.core:core-runtime:2.2.0 androidx.autofill:autofill:1.0.0 androidx.browser:browser:1.8.0 -androidx.collection:collection-jvm:1.5.0-beta01 -androidx.collection:collection-ktx:1.5.0-beta01 -androidx.collection:collection:1.5.0-beta01 -androidx.compose.animation:animation-android:1.8.0-alpha07 -androidx.compose.animation:animation-core-android:1.8.0-alpha07 -androidx.compose.animation:animation-core:1.8.0-alpha07 -androidx.compose.animation:animation:1.8.0-alpha07 -androidx.compose.foundation:foundation-android:1.8.0-alpha07 -androidx.compose.foundation:foundation-layout-android:1.8.0-alpha07 -androidx.compose.foundation:foundation-layout:1.8.0-alpha07 -androidx.compose.foundation:foundation:1.8.0-alpha07 -androidx.compose.material3.adaptive:adaptive-android:1.0.0 -androidx.compose.material3.adaptive:adaptive:1.0.0 -androidx.compose.material3:material3-adaptive-navigation-suite-android:1.3.1 -androidx.compose.material3:material3-adaptive-navigation-suite:1.3.1 -androidx.compose.material3:material3-android:1.3.1 -androidx.compose.material3:material3:1.3.1 -androidx.compose.material:material-icons-core-android:1.7.6 -androidx.compose.material:material-icons-core:1.7.6 -androidx.compose.material:material-icons-extended-android:1.7.6 -androidx.compose.material:material-icons-extended:1.7.6 -androidx.compose.material:material-ripple-android:1.7.6 -androidx.compose.material:material-ripple:1.7.6 -androidx.compose.runtime:runtime-android:1.8.0-alpha07 -androidx.compose.runtime:runtime-saveable-android:1.8.0-alpha07 -androidx.compose.runtime:runtime-saveable:1.8.0-alpha07 -androidx.compose.runtime:runtime:1.8.0-alpha07 -androidx.compose.ui:ui-android:1.8.0-alpha07 -androidx.compose.ui:ui-geometry-android:1.8.0-alpha07 -androidx.compose.ui:ui-geometry:1.8.0-alpha07 -androidx.compose.ui:ui-graphics-android:1.8.0-alpha07 -androidx.compose.ui:ui-graphics:1.8.0-alpha07 -androidx.compose.ui:ui-text-android:1.8.0-alpha07 -androidx.compose.ui:ui-text:1.8.0-alpha07 -androidx.compose.ui:ui-tooling-preview-android:1.8.0-alpha07 -androidx.compose.ui:ui-tooling-preview:1.8.0-alpha07 -androidx.compose.ui:ui-unit-android:1.8.0-alpha07 -androidx.compose.ui:ui-unit:1.8.0-alpha07 -androidx.compose.ui:ui-util-android:1.8.0-alpha07 -androidx.compose.ui:ui-util:1.8.0-alpha07 -androidx.compose.ui:ui:1.8.0-alpha07 -androidx.compose:compose-bom:2024.12.01 +androidx.collection:collection-jvm:1.5.0 +androidx.collection:collection-ktx:1.5.0 +androidx.collection:collection:1.5.0 +androidx.compose.animation:animation-android:1.10.0-alpha02 +androidx.compose.animation:animation-core-android:1.10.0-alpha02 +androidx.compose.animation:animation-core:1.10.0-alpha02 +androidx.compose.animation:animation:1.10.0-alpha02 +androidx.compose.foundation:foundation-android:1.10.0-alpha02 +androidx.compose.foundation:foundation-layout-android:1.10.0-alpha02 +androidx.compose.foundation:foundation-layout:1.10.0-alpha02 +androidx.compose.foundation:foundation:1.10.0-alpha02 +androidx.compose.material3.adaptive:adaptive-android:1.2.0-beta01 +androidx.compose.material3.adaptive:adaptive:1.2.0-beta01 +androidx.compose.material3:material3-adaptive-navigation-suite-android:1.5.0-alpha03 +androidx.compose.material3:material3-adaptive-navigation-suite:1.5.0-alpha03 +androidx.compose.material3:material3-android:1.5.0-alpha03 +androidx.compose.material3:material3:1.5.0-alpha03 +androidx.compose.material:material-icons-core-android:1.7.8 +androidx.compose.material:material-icons-core:1.7.8 +androidx.compose.material:material-icons-extended-android:1.7.8 +androidx.compose.material:material-icons-extended:1.7.8 +androidx.compose.material:material-ripple-android:1.10.0-alpha02 +androidx.compose.material:material-ripple:1.10.0-alpha02 +androidx.compose.runtime:runtime-android:1.10.0-alpha02 +androidx.compose.runtime:runtime-annotation-android:1.10.0-alpha02 +androidx.compose.runtime:runtime-annotation:1.10.0-alpha02 +androidx.compose.runtime:runtime-saveable-android:1.10.0-alpha02 +androidx.compose.runtime:runtime-saveable:1.10.0-alpha02 +androidx.compose.runtime:runtime:1.10.0-alpha02 +androidx.compose.ui:ui-android:1.10.0-alpha02 +androidx.compose.ui:ui-geometry-android:1.10.0-alpha02 +androidx.compose.ui:ui-geometry:1.10.0-alpha02 +androidx.compose.ui:ui-graphics-android:1.10.0-alpha02 +androidx.compose.ui:ui-graphics:1.10.0-alpha02 +androidx.compose.ui:ui-text-android:1.10.0-alpha02 +androidx.compose.ui:ui-text:1.10.0-alpha02 +androidx.compose.ui:ui-tooling-preview-android:1.10.0-alpha02 +androidx.compose.ui:ui-tooling-preview:1.10.0-alpha02 +androidx.compose.ui:ui-unit-android:1.10.0-alpha02 +androidx.compose.ui:ui-unit:1.10.0-alpha02 +androidx.compose.ui:ui-util-android:1.10.0-alpha02 +androidx.compose.ui:ui-util:1.10.0-alpha02 +androidx.compose.ui:ui:1.10.0-alpha02 +androidx.compose:compose-bom-alpha:2025.08.01 androidx.concurrent:concurrent-futures:1.1.0 -androidx.core:core-ktx:1.13.1 -androidx.core:core:1.13.1 +androidx.core:core-ktx:1.16.0 +androidx.core:core-viewtree:1.0.0 +androidx.core:core:1.16.0 androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview:1.0.0 +androidx.documentfile:documentfile:1.0.0 +androidx.dynamicanimation:dynamicanimation:1.0.0 androidx.emoji2:emoji2:1.4.0 androidx.exifinterface:exifinterface:1.3.7 androidx.fragment:fragment:1.5.1 androidx.graphics:graphics-path:1.0.1 +androidx.graphics:graphics-shapes-android:1.0.1 +androidx.graphics:graphics-shapes:1.0.1 androidx.interpolator:interpolator:1.0.0 -androidx.lifecycle:lifecycle-common-java8:2.8.7 -androidx.lifecycle:lifecycle-common-jvm:2.8.7 -androidx.lifecycle:lifecycle-common:2.8.7 -androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7 -androidx.lifecycle:lifecycle-livedata-core:2.8.7 -androidx.lifecycle:lifecycle-livedata:2.8.7 -androidx.lifecycle:lifecycle-process:2.8.7 -androidx.lifecycle:lifecycle-runtime-android:2.8.7 -androidx.lifecycle:lifecycle-runtime-compose-android:2.8.7 -androidx.lifecycle:lifecycle-runtime-compose:2.8.7 -androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7 -androidx.lifecycle:lifecycle-runtime-ktx:2.8.7 -androidx.lifecycle:lifecycle-runtime:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-android:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 -androidx.lifecycle:lifecycle-viewmodel:2.8.7 +androidx.legacy:legacy-support-core-utils:1.0.0 +androidx.lifecycle:lifecycle-common-java8:2.10.0-alpha03 +androidx.lifecycle:lifecycle-common-jvm:2.10.0-alpha03 +androidx.lifecycle:lifecycle-common:2.10.0-alpha03 +androidx.lifecycle:lifecycle-livedata-core-ktx:2.10.0-alpha03 +androidx.lifecycle:lifecycle-livedata-core:2.10.0-alpha03 +androidx.lifecycle:lifecycle-livedata:2.10.0-alpha03 +androidx.lifecycle:lifecycle-process:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-compose-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-compose:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-ktx-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-ktx:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-savedstate:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel:2.10.0-alpha03 androidx.loader:loader:1.0.0 +androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 +androidx.print:print:1.0.0 androidx.profileinstaller:profileinstaller:1.4.0 -androidx.savedstate:savedstate-ktx:1.2.1 -androidx.savedstate:savedstate:1.2.1 +androidx.savedstate:savedstate-android:1.4.0-alpha03 +androidx.savedstate:savedstate-compose-android:1.4.0-alpha03 +androidx.savedstate:savedstate-compose:1.4.0-alpha03 +androidx.savedstate:savedstate-ktx:1.4.0-alpha03 +androidx.savedstate:savedstate:1.4.0-alpha03 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.3.0-alpha02 androidx.tracing:tracing:1.3.0-alpha02 +androidx.transition:transition:1.6.0 androidx.vectordrawable:vectordrawable-animated:1.1.0 androidx.vectordrawable:vectordrawable:1.1.0 androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.viewpager:viewpager:1.0.0 -androidx.window.extensions.core:core:1.0.0 -androidx.window:window-core-android:1.3.0 -androidx.window:window-core:1.3.0 -androidx.window:window:1.3.0 +androidx.window:window-core-android:1.4.0 +androidx.window:window-core:1.4.0 +androidx.window:window:1.4.0 com.google.accompanist:accompanist-drawablepainter:0.32.0 com.google.code.findbugs:jsr305:3.0.2 -com.google.dagger:dagger-lint-aar:2.54 -com.google.dagger:dagger:2.54 -com.google.dagger:hilt-android:2.54 -com.google.dagger:hilt-core:2.54 +com.google.dagger:dagger-lint-aar:2.57.2 +com.google.dagger:dagger:2.57.2 +com.google.dagger:hilt-android:2.57.2 +com.google.dagger:hilt-core:2.57.2 com.google.guava:listenablefuture:1.0 com.squareup.okhttp3:okhttp:4.12.0 com.squareup.okio:okio-jvm:3.9.0 @@ -110,15 +124,18 @@ io.coil-kt:coil-compose:2.7.0 io.coil-kt:coil:2.7.0 jakarta.inject:jakarta.inject-api:2.0.1 javax.inject:javax.inject:1 -org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0 +org.jetbrains.kotlin:kotlin-stdlib-common:2.2.21 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -org.jetbrains.kotlin:kotlin-stdlib:2.1.0 +org.jetbrains.kotlin:kotlin-stdlib:2.2.21 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.6.1 org.jetbrains.kotlinx:kotlinx-datetime:0.6.1 +org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3 +org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3 +org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3 org.jetbrains:annotations:23.0.0 org.jspecify:jspecify:1.0.0 diff --git a/app/README.md b/app/README.md index a3fb4572a..3fb136547 100644 --- a/app/README.md +++ b/app/README.md @@ -1,3 +1,134 @@ -# :app module -## Dependency graph -![Dependency graph](../docs/images/graphs/dep_graph_app.svg) +# `:app` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:bookmarks[bookmarks]:::android-feature + :feature:foryou[foryou]:::android-feature + :feature:interests[interests]:::android-feature + :feature:search[search]:::android-feature + :feature:settings[settings]:::android-feature + :feature:topic[topic]:::android-feature + end + subgraph :sync + direction TB + :sync:work[work]:::android-library + end + :benchmarks[benchmarks]:::android-test + :app[app]:::android-application + + :app -.->|baselineProfile| :benchmarks + :app -.-> :core:analytics + :app -.-> :core:common + :app -.-> :core:data + :app -.-> :core:designsystem + :app -.-> :core:model + :app -.-> :core:ui + :app -.-> :feature:bookmarks + :app -.-> :feature:foryou + :app -.-> :feature:interests + :app -.-> :feature:search + :app -.-> :feature:settings + :app -.-> :feature:topic + :app -.-> :sync:work + :benchmarks -.->|testedApks| :app + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:domain --> :core:data + :core:domain --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:bookmarks -.-> :core:data + :feature:bookmarks -.-> :core:designsystem + :feature:bookmarks -.-> :core:ui + :feature:foryou -.-> :core:data + :feature:foryou -.-> :core:designsystem + :feature:foryou -.-> :core:domain + :feature:foryou -.-> :core:notifications + :feature:foryou -.-> :core:ui + :feature:interests -.-> :core:data + :feature:interests -.-> :core:designsystem + :feature:interests -.-> :core:domain + :feature:interests -.-> :core:ui + :feature:search -.-> :core:data + :feature:search -.-> :core:designsystem + :feature:search -.-> :core:domain + :feature:search -.-> :core:ui + :feature:settings -.-> :core:data + :feature:settings -.-> :core:designsystem + :feature:settings -.-> :core:ui + :feature:topic -.-> :core:data + :feature:topic -.-> :core:designsystem + :feature:topic -.-> :core:ui + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 05212a28f..09005606b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,7 +22,7 @@ plugins { alias(libs.plugins.nowinandroid.android.application.jacoco) alias(libs.plugins.nowinandroid.android.application.firebase) alias(libs.plugins.nowinandroid.hilt) - id("com.google.android.gms.oss-licenses-plugin") + alias(libs.plugins.google.osslicenses) alias(libs.plugins.baselineprofile) alias(libs.plugins.roborazzi) alias(libs.plugins.kotlin.serialization) @@ -43,9 +43,11 @@ android { applicationIdSuffix = NiaBuildType.DEBUG.applicationIdSuffix } release { - isMinifyEnabled = true + isMinifyEnabled = providers.gradleProperty("minifyWithR8") + .map(String::toBooleanStrict).getOrElse(true) applicationIdSuffix = NiaBuildType.RELEASE.applicationIdSuffix - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro") // To publish on the Play store a private signing key is required, but to allow anyone // who clones the code to sign and run the release variant, use the debug signing key. @@ -61,11 +63,7 @@ android { excludes.add("/META-INF/{AL2.0,LGPL2.1}") } } - testOptions { - unitTests { - isIncludeAndroidResources = true - } - } + testOptions.unitTests.isIncludeAndroidResources = true namespace = "com.google.samples.apps.nowinandroid" } @@ -86,6 +84,7 @@ dependencies { implementation(projects.sync.work) implementation(libs.androidx.activity.compose) + implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3.adaptive) implementation(libs.androidx.compose.material3.adaptive.layout) implementation(libs.androidx.compose.material3.adaptive.navigation) diff --git a/app/dependencies/prodReleaseRuntimeClasspath.txt b/app/dependencies/prodReleaseRuntimeClasspath.txt index 6fca688a1..f4f1e35c8 100644 --- a/app/dependencies/prodReleaseRuntimeClasspath.txt +++ b/app/dependencies/prodReleaseRuntimeClasspath.txt @@ -1,7 +1,7 @@ -androidx.activity:activity-compose:1.9.3 -androidx.activity:activity-ktx:1.9.3 -androidx.activity:activity:1.9.3 -androidx.annotation:annotation-experimental:1.4.1 +androidx.activity:activity-compose:1.10.1 +androidx.activity:activity-ktx:1.10.1 +androidx.activity:activity:1.10.1 +androidx.annotation:annotation-experimental:1.5.1 androidx.annotation:annotation-jvm:1.9.1 androidx.annotation:annotation:1.9.1 androidx.appcompat:appcompat-resources:1.7.0 @@ -10,60 +10,63 @@ androidx.arch.core:core-common:2.2.0 androidx.arch.core:core-runtime:2.2.0 androidx.autofill:autofill:1.0.0 androidx.browser:browser:1.8.0 -androidx.collection:collection-jvm:1.5.0-beta01 -androidx.collection:collection-ktx:1.5.0-beta01 -androidx.collection:collection:1.5.0-beta01 -androidx.compose.animation:animation-android:1.8.0-alpha07 -androidx.compose.animation:animation-core-android:1.8.0-alpha07 -androidx.compose.animation:animation-core:1.8.0-alpha07 -androidx.compose.animation:animation:1.8.0-alpha07 -androidx.compose.foundation:foundation-android:1.8.0-alpha07 -androidx.compose.foundation:foundation-layout-android:1.8.0-alpha07 -androidx.compose.foundation:foundation-layout:1.8.0-alpha07 -androidx.compose.foundation:foundation:1.8.0-alpha07 -androidx.compose.material3.adaptive:adaptive-android:1.0.0 -androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0 -androidx.compose.material3.adaptive:adaptive-layout:1.0.0 -androidx.compose.material3.adaptive:adaptive-navigation-android:1.0.0 -androidx.compose.material3.adaptive:adaptive-navigation:1.0.0 -androidx.compose.material3.adaptive:adaptive:1.0.0 -androidx.compose.material3:material3-adaptive-navigation-suite-android:1.3.1 -androidx.compose.material3:material3-adaptive-navigation-suite:1.3.1 -androidx.compose.material3:material3-android:1.3.1 -androidx.compose.material3:material3-window-size-class-android:1.3.1 -androidx.compose.material3:material3-window-size-class:1.3.1 -androidx.compose.material3:material3:1.3.1 -androidx.compose.material:material-icons-core-android:1.7.6 -androidx.compose.material:material-icons-core:1.7.6 -androidx.compose.material:material-icons-extended-android:1.7.6 -androidx.compose.material:material-icons-extended:1.7.6 -androidx.compose.material:material-ripple-android:1.7.6 -androidx.compose.material:material-ripple:1.7.6 -androidx.compose.runtime:runtime-android:1.8.0-alpha07 -androidx.compose.runtime:runtime-saveable-android:1.8.0-alpha07 -androidx.compose.runtime:runtime-saveable:1.8.0-alpha07 -androidx.compose.runtime:runtime-tracing:1.8.0-alpha07 -androidx.compose.runtime:runtime:1.8.0-alpha07 -androidx.compose.ui:ui-android:1.8.0-alpha07 -androidx.compose.ui:ui-geometry-android:1.8.0-alpha07 -androidx.compose.ui:ui-geometry:1.8.0-alpha07 -androidx.compose.ui:ui-graphics-android:1.8.0-alpha07 -androidx.compose.ui:ui-graphics:1.8.0-alpha07 -androidx.compose.ui:ui-text-android:1.8.0-alpha07 -androidx.compose.ui:ui-text:1.8.0-alpha07 -androidx.compose.ui:ui-tooling-preview-android:1.8.0-alpha07 -androidx.compose.ui:ui-tooling-preview:1.8.0-alpha07 -androidx.compose.ui:ui-unit-android:1.8.0-alpha07 -androidx.compose.ui:ui-unit:1.8.0-alpha07 -androidx.compose.ui:ui-util-android:1.8.0-alpha07 -androidx.compose.ui:ui-util:1.8.0-alpha07 -androidx.compose.ui:ui:1.8.0-alpha07 -androidx.compose:compose-bom:2024.12.01 +androidx.collection:collection-jvm:1.5.0 +androidx.collection:collection-ktx:1.5.0 +androidx.collection:collection:1.5.0 +androidx.compose.animation:animation-android:1.10.0-alpha02 +androidx.compose.animation:animation-core-android:1.10.0-alpha02 +androidx.compose.animation:animation-core:1.10.0-alpha02 +androidx.compose.animation:animation:1.10.0-alpha02 +androidx.compose.foundation:foundation-android:1.10.0-alpha02 +androidx.compose.foundation:foundation-layout-android:1.10.0-alpha02 +androidx.compose.foundation:foundation-layout:1.10.0-alpha02 +androidx.compose.foundation:foundation:1.10.0-alpha02 +androidx.compose.material3.adaptive:adaptive-android:1.2.0-beta01 +androidx.compose.material3.adaptive:adaptive-layout-android:1.2.0-beta01 +androidx.compose.material3.adaptive:adaptive-layout:1.2.0-beta01 +androidx.compose.material3.adaptive:adaptive-navigation-android:1.2.0-beta01 +androidx.compose.material3.adaptive:adaptive-navigation:1.2.0-beta01 +androidx.compose.material3.adaptive:adaptive:1.2.0-beta01 +androidx.compose.material3:material3-adaptive-navigation-suite-android:1.5.0-alpha03 +androidx.compose.material3:material3-adaptive-navigation-suite:1.5.0-alpha03 +androidx.compose.material3:material3-android:1.5.0-alpha03 +androidx.compose.material3:material3-window-size-class-android:1.5.0-alpha03 +androidx.compose.material3:material3-window-size-class:1.5.0-alpha03 +androidx.compose.material3:material3:1.5.0-alpha03 +androidx.compose.material:material-icons-core-android:1.7.8 +androidx.compose.material:material-icons-core:1.7.8 +androidx.compose.material:material-icons-extended-android:1.7.8 +androidx.compose.material:material-icons-extended:1.7.8 +androidx.compose.material:material-ripple-android:1.10.0-alpha02 +androidx.compose.material:material-ripple:1.10.0-alpha02 +androidx.compose.runtime:runtime-android:1.10.0-alpha02 +androidx.compose.runtime:runtime-annotation-android:1.10.0-alpha02 +androidx.compose.runtime:runtime-annotation:1.10.0-alpha02 +androidx.compose.runtime:runtime-saveable-android:1.10.0-alpha02 +androidx.compose.runtime:runtime-saveable:1.10.0-alpha02 +androidx.compose.runtime:runtime-tracing:1.10.0-alpha02 +androidx.compose.runtime:runtime:1.10.0-alpha02 +androidx.compose.ui:ui-android:1.10.0-alpha02 +androidx.compose.ui:ui-geometry-android:1.10.0-alpha02 +androidx.compose.ui:ui-geometry:1.10.0-alpha02 +androidx.compose.ui:ui-graphics-android:1.10.0-alpha02 +androidx.compose.ui:ui-graphics:1.10.0-alpha02 +androidx.compose.ui:ui-text-android:1.10.0-alpha02 +androidx.compose.ui:ui-text:1.10.0-alpha02 +androidx.compose.ui:ui-tooling-preview-android:1.10.0-alpha02 +androidx.compose.ui:ui-tooling-preview:1.10.0-alpha02 +androidx.compose.ui:ui-unit-android:1.10.0-alpha02 +androidx.compose.ui:ui-unit:1.10.0-alpha02 +androidx.compose.ui:ui-util-android:1.10.0-alpha02 +androidx.compose.ui:ui-util:1.10.0-alpha02 +androidx.compose.ui:ui:1.10.0-alpha02 +androidx.compose:compose-bom-alpha:2025.08.01 androidx.concurrent:concurrent-futures-ktx:1.1.0 androidx.concurrent:concurrent-futures:1.1.0 -androidx.core:core-ktx:1.15.0 +androidx.core:core-ktx:1.16.0 androidx.core:core-splashscreen:1.0.1 -androidx.core:core:1.15.0 +androidx.core:core-viewtree:1.0.0 +androidx.core:core:1.16.0 androidx.cursoradapter:cursoradapter:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview:1.0.0 @@ -79,37 +82,41 @@ androidx.datastore:datastore-preferences:1.1.1 androidx.datastore:datastore:1.1.1 androidx.documentfile:documentfile:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0 +androidx.dynamicanimation:dynamicanimation:1.0.0 androidx.emoji2:emoji2-views-helper:1.4.0 androidx.emoji2:emoji2:1.4.0 androidx.exifinterface:exifinterface:1.3.7 androidx.fragment:fragment:1.5.4 androidx.graphics:graphics-path:1.0.1 +androidx.graphics:graphics-shapes-android:1.0.1 +androidx.graphics:graphics-shapes:1.0.1 androidx.hilt:hilt-common:1.2.0 androidx.hilt:hilt-navigation-compose:1.2.0 androidx.hilt:hilt-navigation:1.2.0 androidx.hilt:hilt-work:1.2.0 androidx.interpolator:interpolator:1.0.0 androidx.legacy:legacy-support-core-utils:1.0.0 -androidx.lifecycle:lifecycle-common-java8:2.8.7 -androidx.lifecycle:lifecycle-common-jvm:2.8.7 -androidx.lifecycle:lifecycle-common:2.8.7 -androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.7 -androidx.lifecycle:lifecycle-livedata-core:2.8.7 -androidx.lifecycle:lifecycle-livedata:2.8.7 -androidx.lifecycle:lifecycle-process:2.8.7 -androidx.lifecycle:lifecycle-runtime-android:2.8.7 -androidx.lifecycle:lifecycle-runtime-compose-android:2.8.7 -androidx.lifecycle:lifecycle-runtime-compose:2.8.7 -androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.7 -androidx.lifecycle:lifecycle-runtime-ktx:2.8.7 -androidx.lifecycle:lifecycle-runtime:2.8.7 -androidx.lifecycle:lifecycle-service:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-android:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7 -androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.7 -androidx.lifecycle:lifecycle-viewmodel:2.8.7 +androidx.lifecycle:lifecycle-common-java8:2.10.0-alpha03 +androidx.lifecycle:lifecycle-common-jvm:2.10.0-alpha03 +androidx.lifecycle:lifecycle-common:2.10.0-alpha03 +androidx.lifecycle:lifecycle-livedata-core-ktx:2.10.0-alpha03 +androidx.lifecycle:lifecycle-livedata-core:2.10.0-alpha03 +androidx.lifecycle:lifecycle-livedata:2.10.0-alpha03 +androidx.lifecycle:lifecycle-process:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-compose-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-compose:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-ktx-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime-ktx:2.10.0-alpha03 +androidx.lifecycle:lifecycle-runtime:2.10.0-alpha03 +androidx.lifecycle:lifecycle-service:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-compose-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-savedstate-android:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel-savedstate:2.10.0-alpha03 +androidx.lifecycle:lifecycle-viewmodel:2.10.0-alpha03 androidx.loader:loader:1.0.0 androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 @@ -123,25 +130,32 @@ androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common:2.6.1 -androidx.room:room-ktx:2.6.1 -androidx.room:room-runtime:2.6.1 -androidx.savedstate:savedstate-ktx:1.2.1 -androidx.savedstate:savedstate:1.2.1 -androidx.sqlite:sqlite-framework:2.4.0 -androidx.sqlite:sqlite:2.4.0 +androidx.room:room-common-jvm:2.8.3 +androidx.room:room-common:2.8.3 +androidx.room:room-ktx:2.8.3 +androidx.room:room-runtime-android:2.8.3 +androidx.room:room-runtime:2.8.3 +androidx.savedstate:savedstate-android:1.4.0-alpha03 +androidx.savedstate:savedstate-compose-android:1.4.0-alpha03 +androidx.savedstate:savedstate-compose:1.4.0-alpha03 +androidx.savedstate:savedstate-ktx:1.4.0-alpha03 +androidx.savedstate:savedstate:1.4.0-alpha03 +androidx.sqlite:sqlite-android:2.6.1 +androidx.sqlite:sqlite-framework-android:2.6.1 +androidx.sqlite:sqlite-framework:2.6.1 +androidx.sqlite:sqlite:2.6.1 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.3.0-alpha02 androidx.tracing:tracing-perfetto:1.0.0 androidx.tracing:tracing:1.3.0-alpha02 +androidx.transition:transition:1.6.0 androidx.vectordrawable:vectordrawable-animated:1.1.0 androidx.vectordrawable:vectordrawable:1.1.0 androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.viewpager:viewpager:1.0.0 -androidx.window.extensions.core:core:1.0.0 -androidx.window:window-core-android:1.3.0 -androidx.window:window-core:1.3.0 -androidx.window:window:1.3.0 +androidx.window:window-core-android:1.4.0 +androidx.window:window-core:1.4.0 +androidx.window:window:1.4.0 androidx.work:work-runtime-ktx:2.10.0 androidx.work:work-runtime:2.10.0 com.caverock:androidsvg-aar:1.4 @@ -164,10 +178,10 @@ com.google.android.gms:play-services-oss-licenses:17.1.0 com.google.android.gms:play-services-stats:17.0.2 com.google.android.gms:play-services-tasks:18.2.0 com.google.code.findbugs:jsr305:3.0.2 -com.google.dagger:dagger-lint-aar:2.54 -com.google.dagger:dagger:2.54 -com.google.dagger:hilt-android:2.54 -com.google.dagger:hilt-core:2.54 +com.google.dagger:dagger-lint-aar:2.57.2 +com.google.dagger:dagger:2.57.2 +com.google.dagger:hilt-android:2.57.2 +com.google.dagger:hilt-core:2.57.2 com.google.errorprone:error_prone_annotations:2.26.0 com.google.firebase:firebase-abt:21.1.1 com.google.firebase:firebase-analytics:22.1.2 @@ -212,10 +226,10 @@ javax.inject:javax.inject:1 org.checkerframework:checker-qual:3.12.0 org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.9.22 org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22 -org.jetbrains.kotlin:kotlin-stdlib-common:2.1.0 +org.jetbrains.kotlin:kotlin-stdlib-common:2.2.21 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -org.jetbrains.kotlin:kotlin-stdlib:2.1.0 +org.jetbrains.kotlin:kotlin-stdlib:2.2.21 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.1 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.10.1 diff --git a/app/prodRelease-badging.txt b/app/prodRelease-badging.txt index 0d770604e..640949857 100644 --- a/app/prodRelease-badging.txt +++ b/app/prodRelease-badging.txt @@ -1,5 +1,5 @@ package: name='com.google.samples.apps.nowinandroid' versionCode='8' versionName='0.1.2' platformBuildVersionName='15' platformBuildVersionCode='35' compileSdkVersion='35' compileSdkVersionCodename='15' -sdkVersion:'21' +minSdkVersion:'23' targetSdkVersion:'35' uses-permission: name='android.permission.INTERNET' uses-permission: name='android.permission.ACCESS_NETWORK_STATE' @@ -105,9 +105,9 @@ application-icon-640:'res/mipmap-anydpi-v26/ic_launcher.xml' application-icon-65534:'res/mipmap-anydpi-v26/ic_launcher.xml' application: label='Now in Android' icon='res/mipmap-anydpi-v26/ic_launcher.xml' launchable-activity: name='com.google.samples.apps.nowinandroid.MainActivity' label='' icon='' -uses-library-not-required:'android.ext.adservices' uses-library-not-required:'androidx.window.extensions' uses-library-not-required:'androidx.window.sidecar' +uses-library-not-required:'android.ext.adservices' feature-group: label='' uses-feature: name='android.hardware.faketouch' uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps' diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 000000000..24a0b4a16 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,2 @@ +# Repackage classes into the default package to reduce the size of descriptors. +-repackageclasses diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/NiaApplication.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/NiaApplication.kt index 77f72e5fc..4975e5d65 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/NiaApplication.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/NiaApplication.kt @@ -66,7 +66,7 @@ class NiaApplication : Application(), ImageLoaderFactory { private fun setStrictModePolicy() { if (isDebuggable()) { StrictMode.setThreadPolicy( - Builder().detectAll().penaltyLog().penaltyDeath().build(), + Builder().detectAll().penaltyLog().build(), ) } } diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt index f27b90cbe..b237684ef 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/NiaApp.kt @@ -21,7 +21,9 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.exclude import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawing @@ -166,8 +168,7 @@ internal fun NiaApp( ) }, label = { Text(stringResource(destination.iconTextId)) }, - modifier = - Modifier + modifier = Modifier .testTag("NiaNavItem") .then(if (hasUnread) Modifier.notificationDot() else Modifier), ) @@ -182,7 +183,16 @@ internal fun NiaApp( containerColor = Color.Transparent, contentColor = MaterialTheme.colorScheme.onBackground, contentWindowInsets = WindowInsets(0, 0, 0, 0), - snackbarHost = { SnackbarHost(snackbarHostState) }, + snackbarHost = { + SnackbarHost( + snackbarHostState, + modifier = Modifier.windowInsetsPadding( + WindowInsets.safeDrawing.exclude( + WindowInsets.ime, + ), + ), + ) + }, ) { padding -> Column( Modifier @@ -211,7 +221,7 @@ internal fun NiaApp( actionIconContentDescription = stringResource( id = settingsR.string.feature_settings_top_app_bar_action_icon_description, ), - colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, ), onActionClick = { onTopAppBarActionClick() }, diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt index 669c6300a..c0f425c65 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt @@ -17,47 +17,53 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane import androidx.activity.compose.BackHandler -import androidx.annotation.Keep +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.material3.LocalMinimumInteractiveComponentSize +import androidx.compose.material3.VerticalDragHandle import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi import androidx.compose.material3.adaptive.WindowAdaptiveInfo import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.material3.adaptive.layout.AnimatedPane -import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.layout.PaneAdaptedValue +import androidx.compose.material3.adaptive.layout.PaneExpansionAnchor import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective +import androidx.compose.material3.adaptive.layout.defaultDragHandleSemantics +import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState +import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior +import androidx.compose.material3.adaptive.navigation.NavigableListDetailPaneScaffold import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator +import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.Saver -import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds +import androidx.compose.ui.layout.layout +import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavGraphBuilder -import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder +import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen +import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute -import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic -import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen +import kotlinx.coroutines.launch import kotlinx.serialization.Serializable -import java.util.UUID +import kotlin.math.max @Serializable internal object TopicPlaceholderRoute -// TODO: Remove @Keep when https://issuetracker.google.com/353898971 is fixed -@Keep -@Serializable internal object DetailPaneNavHostRoute - fun NavGraphBuilder.interestsListDetailScreen() { composable { InterestsListDetailScreen() @@ -93,70 +99,139 @@ internal fun InterestsListDetailScreen( }, ), ) - BackHandler(listDetailNavigator.canNavigateBack()) { - listDetailNavigator.navigateBack() + val coroutineScope = rememberCoroutineScope() + + val paneExpansionState = rememberPaneExpansionState( + anchors = listOf( + PaneExpansionAnchor.Proportion(0f), + PaneExpansionAnchor.Proportion(0.5f), + PaneExpansionAnchor.Proportion(1f), + ), + ) + + ThreePaneScaffoldPredictiveBackHandler( + listDetailNavigator, + BackNavigationBehavior.PopUntilScaffoldValueChange, + ) + BackHandler( + paneExpansionState.currentAnchor == PaneExpansionAnchor.Proportion(0f) && + listDetailNavigator.isListPaneVisible() && + listDetailNavigator.isDetailPaneVisible(), + ) { + coroutineScope.launch { + paneExpansionState.animateTo(PaneExpansionAnchor.Proportion(1f)) + } } - var nestedNavHostStartRoute by remember { + var topicRoute by remember { val route = selectedTopicId?.let { TopicRoute(id = it) } ?: TopicPlaceholderRoute mutableStateOf(route) } - var nestedNavKey by rememberSaveable( - stateSaver = Saver({ it.toString() }, UUID::fromString), - ) { - mutableStateOf(UUID.randomUUID()) - } - val nestedNavController = key(nestedNavKey) { - rememberNavController() - } fun onTopicClickShowDetailPane(topicId: String) { onTopicClick(topicId) - if (listDetailNavigator.isDetailPaneVisible()) { - // If the detail pane was visible, then use the nestedNavController navigate call - // directly - nestedNavController.navigateToTopic(topicId) { - popUpTo() + topicRoute = TopicRoute(id = topicId) + coroutineScope.launch { + listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail) + } + if (paneExpansionState.currentAnchor == PaneExpansionAnchor.Proportion(1f)) { + coroutineScope.launch { + paneExpansionState.animateTo(PaneExpansionAnchor.Proportion(0f)) } - } else { - // Otherwise, recreate the NavHost entirely, and start at the new destination - nestedNavHostStartRoute = TopicRoute(id = topicId) - nestedNavKey = UUID.randomUUID() } - listDetailNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail) } - ListDetailPaneScaffold( - value = listDetailNavigator.scaffoldValue, - directive = listDetailNavigator.scaffoldDirective, + val mutableInteractionSource = remember { MutableInteractionSource() } + val minPaneWidth = 300.dp + + NavigableListDetailPaneScaffold( + navigator = listDetailNavigator, listPane = { AnimatedPane { - InterestsRoute( - onTopicClick = ::onTopicClickShowDetailPane, - highlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(), - ) + Box( + modifier = Modifier.clipToBounds() + .layout { measurable, constraints -> + val width = max(minPaneWidth.roundToPx(), constraints.maxWidth) + val placeable = measurable.measure( + constraints.copy( + minWidth = minPaneWidth.roundToPx(), + maxWidth = width, + ), + ) + layout(constraints.maxWidth, placeable.height) { + placeable.placeRelative( + x = 0, + y = 0, + ) + } + }, + ) { + InterestsRoute( + onTopicClick = ::onTopicClickShowDetailPane, + shouldHighlightSelectedTopic = listDetailNavigator.isDetailPaneVisible(), + ) + } } }, detailPane = { AnimatedPane { - key(nestedNavKey) { - NavHost( - navController = nestedNavController, - startDestination = nestedNavHostStartRoute, - route = DetailPaneNavHostRoute::class, - ) { - topicScreen( - showBackButton = !listDetailNavigator.isListPaneVisible(), - onBackClick = listDetailNavigator::navigateBack, - onTopicClick = ::onTopicClickShowDetailPane, - ) - composable { - TopicDetailPlaceholder() + Box( + modifier = Modifier.clipToBounds() + .layout { measurable, constraints -> + val width = max(minPaneWidth.roundToPx(), constraints.maxWidth) + val placeable = measurable.measure( + constraints.copy( + minWidth = minPaneWidth.roundToPx(), + maxWidth = width, + ), + ) + layout(constraints.maxWidth, placeable.height) { + placeable.placeRelative( + x = constraints.maxWidth - + max(constraints.maxWidth, placeable.width), + y = 0, + ) + } + }, + ) { + AnimatedContent(topicRoute) { route -> + when (route) { + is TopicRoute -> { + TopicScreen( + showBackButton = !listDetailNavigator.isListPaneVisible(), + onBackClick = { + coroutineScope.launch { + listDetailNavigator.navigateBack() + } + }, + onTopicClick = ::onTopicClickShowDetailPane, + viewModel = hiltViewModel( + key = route.id, + ) { factory -> + factory.create(route.id) + }, + ) + } + is TopicPlaceholderRoute -> { + TopicDetailPlaceholder() + } } } } } }, + paneExpansionState = paneExpansionState, + paneExpansionDragHandle = { + VerticalDragHandle( + modifier = Modifier.paneExpansionDraggable( + state = paneExpansionState, + minTouchTargetSize = LocalMinimumInteractiveComponentSize.current, + interactionSource = mutableInteractionSource, + semanticsProperties = paneExpansionState.defaultDragHandleSemantics(), + ), + interactionSource = mutableInteractionSource, + ) + }, ) } diff --git a/app/src/testDemo/screenshots/compactWidth_compactHeight_showsNavigationBar.png b/app/src/testDemo/screenshots/compactWidth_compactHeight_showsNavigationBar.png index 2e6d1037c..7a49b2c32 100644 Binary files a/app/src/testDemo/screenshots/compactWidth_compactHeight_showsNavigationBar.png and b/app/src/testDemo/screenshots/compactWidth_compactHeight_showsNavigationBar.png differ diff --git a/app/src/testDemo/screenshots/compactWidth_expandedHeight_showsNavigationBar.png b/app/src/testDemo/screenshots/compactWidth_expandedHeight_showsNavigationBar.png index 1acb34aba..ab20746cb 100644 Binary files a/app/src/testDemo/screenshots/compactWidth_expandedHeight_showsNavigationBar.png and b/app/src/testDemo/screenshots/compactWidth_expandedHeight_showsNavigationBar.png differ diff --git a/app/src/testDemo/screenshots/compactWidth_mediumHeight_showsNavigationBar.png b/app/src/testDemo/screenshots/compactWidth_mediumHeight_showsNavigationBar.png index d52c844a3..926ce00f1 100644 Binary files a/app/src/testDemo/screenshots/compactWidth_mediumHeight_showsNavigationBar.png and b/app/src/testDemo/screenshots/compactWidth_mediumHeight_showsNavigationBar.png differ diff --git a/app/src/testDemo/screenshots/expandedWidth_compactHeight_showsNavigationBar.png b/app/src/testDemo/screenshots/expandedWidth_compactHeight_showsNavigationBar.png index e6e574347..d793bed51 100644 Binary files a/app/src/testDemo/screenshots/expandedWidth_compactHeight_showsNavigationBar.png and b/app/src/testDemo/screenshots/expandedWidth_compactHeight_showsNavigationBar.png differ diff --git a/app/src/testDemo/screenshots/expandedWidth_expandedHeight_showsNavigationRail.png b/app/src/testDemo/screenshots/expandedWidth_expandedHeight_showsNavigationRail.png index 222fc21aa..b6f89e516 100644 Binary files a/app/src/testDemo/screenshots/expandedWidth_expandedHeight_showsNavigationRail.png and b/app/src/testDemo/screenshots/expandedWidth_expandedHeight_showsNavigationRail.png differ diff --git a/app/src/testDemo/screenshots/expandedWidth_mediumHeight_showsNavigationRail.png b/app/src/testDemo/screenshots/expandedWidth_mediumHeight_showsNavigationRail.png index a33ad8863..2bf46ca4f 100644 Binary files a/app/src/testDemo/screenshots/expandedWidth_mediumHeight_showsNavigationRail.png and b/app/src/testDemo/screenshots/expandedWidth_mediumHeight_showsNavigationRail.png differ diff --git a/app/src/testDemo/screenshots/insets_snackbar_compact_medium.png b/app/src/testDemo/screenshots/insets_snackbar_compact_medium.png index 4e741bdcc..e95e700ba 100644 Binary files a/app/src/testDemo/screenshots/insets_snackbar_compact_medium.png and b/app/src/testDemo/screenshots/insets_snackbar_compact_medium.png differ diff --git a/app/src/testDemo/screenshots/insets_snackbar_compact_medium_noSnackbar.png b/app/src/testDemo/screenshots/insets_snackbar_compact_medium_noSnackbar.png index 2e76d3a68..db6488e34 100644 Binary files a/app/src/testDemo/screenshots/insets_snackbar_compact_medium_noSnackbar.png and b/app/src/testDemo/screenshots/insets_snackbar_compact_medium_noSnackbar.png differ diff --git a/app/src/testDemo/screenshots/insets_snackbar_expanded_expanded.png b/app/src/testDemo/screenshots/insets_snackbar_expanded_expanded.png index d39df7b79..becfe5715 100644 Binary files a/app/src/testDemo/screenshots/insets_snackbar_expanded_expanded.png and b/app/src/testDemo/screenshots/insets_snackbar_expanded_expanded.png differ diff --git a/app/src/testDemo/screenshots/insets_snackbar_medium_medium.png b/app/src/testDemo/screenshots/insets_snackbar_medium_medium.png index ec6377143..578ff0b6d 100644 Binary files a/app/src/testDemo/screenshots/insets_snackbar_medium_medium.png and b/app/src/testDemo/screenshots/insets_snackbar_medium_medium.png differ diff --git a/app/src/testDemo/screenshots/mediumWidth_compactHeight_showsNavigationBar.png b/app/src/testDemo/screenshots/mediumWidth_compactHeight_showsNavigationBar.png index fdbf9ee8b..64cf8f32f 100644 Binary files a/app/src/testDemo/screenshots/mediumWidth_compactHeight_showsNavigationBar.png and b/app/src/testDemo/screenshots/mediumWidth_compactHeight_showsNavigationBar.png differ diff --git a/app/src/testDemo/screenshots/mediumWidth_expandedHeight_showsNavigationRail.png b/app/src/testDemo/screenshots/mediumWidth_expandedHeight_showsNavigationRail.png index 882e62760..679846fc1 100644 Binary files a/app/src/testDemo/screenshots/mediumWidth_expandedHeight_showsNavigationRail.png and b/app/src/testDemo/screenshots/mediumWidth_expandedHeight_showsNavigationRail.png differ diff --git a/app/src/testDemo/screenshots/mediumWidth_mediumHeight_showsNavigationRail.png b/app/src/testDemo/screenshots/mediumWidth_mediumHeight_showsNavigationRail.png index 8ffe73e86..b8ddeb12b 100644 Binary files a/app/src/testDemo/screenshots/mediumWidth_mediumHeight_showsNavigationRail.png and b/app/src/testDemo/screenshots/mediumWidth_mediumHeight_showsNavigationRail.png differ diff --git a/app/src/testDemo/screenshots/snackbar_compact_medium.png b/app/src/testDemo/screenshots/snackbar_compact_medium.png index 3f67285a3..ad12a4173 100644 Binary files a/app/src/testDemo/screenshots/snackbar_compact_medium.png and b/app/src/testDemo/screenshots/snackbar_compact_medium.png differ diff --git a/app/src/testDemo/screenshots/snackbar_compact_medium_noSnackbar.png b/app/src/testDemo/screenshots/snackbar_compact_medium_noSnackbar.png index 893d43d19..bc466edcb 100644 Binary files a/app/src/testDemo/screenshots/snackbar_compact_medium_noSnackbar.png and b/app/src/testDemo/screenshots/snackbar_compact_medium_noSnackbar.png differ diff --git a/app/src/testDemo/screenshots/snackbar_expanded_expanded.png b/app/src/testDemo/screenshots/snackbar_expanded_expanded.png index b429a7315..fc98037a6 100644 Binary files a/app/src/testDemo/screenshots/snackbar_expanded_expanded.png and b/app/src/testDemo/screenshots/snackbar_expanded_expanded.png differ diff --git a/app/src/testDemo/screenshots/snackbar_medium_medium.png b/app/src/testDemo/screenshots/snackbar_medium_medium.png index 00e9e3051..1dfc73e5a 100644 Binary files a/app/src/testDemo/screenshots/snackbar_medium_medium.png and b/app/src/testDemo/screenshots/snackbar_medium_medium.png differ diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 000000000..657ad5422 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,134 @@ +# `:benchmarks` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:bookmarks[bookmarks]:::android-feature + :feature:foryou[foryou]:::android-feature + :feature:interests[interests]:::android-feature + :feature:search[search]:::android-feature + :feature:settings[settings]:::android-feature + :feature:topic[topic]:::android-feature + end + subgraph :sync + direction TB + :sync:work[work]:::android-library + end + :benchmarks[benchmarks]:::android-test + :app[app]:::android-application + + :app -.->|baselineProfile| :benchmarks + :app -.-> :core:analytics + :app -.-> :core:common + :app -.-> :core:data + :app -.-> :core:designsystem + :app -.-> :core:model + :app -.-> :core:ui + :app -.-> :feature:bookmarks + :app -.-> :feature:foryou + :app -.-> :feature:interests + :app -.-> :feature:search + :app -.-> :feature:settings + :app -.-> :feature:topic + :app -.-> :sync:work + :benchmarks -.->|testedApks| :app + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:domain --> :core:data + :core:domain --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:bookmarks -.-> :core:data + :feature:bookmarks -.-> :core:designsystem + :feature:bookmarks -.-> :core:ui + :feature:foryou -.-> :core:data + :feature:foryou -.-> :core:designsystem + :feature:foryou -.-> :core:domain + :feature:foryou -.-> :core:notifications + :feature:foryou -.-> :core:ui + :feature:interests -.-> :core:data + :feature:interests -.-> :core:designsystem + :feature:interests -.-> :core:domain + :feature:interests -.-> :core:ui + :feature:search -.-> :core:data + :feature:search -.-> :core:designsystem + :feature:search -.-> :core:domain + :feature:search -.-> :core:ui + :feature:settings -.-> :core:data + :feature:settings -.-> :core:designsystem + :feature:settings -.-> :core:ui + :feature:topic -.-> :core:data + :feature:topic -.-> :core:designsystem + :feature:topic -.-> :core:ui + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index e36f021b0..258993913 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -45,8 +45,8 @@ android { ) } - testOptions.managedDevices.devices { - create("pixel6Api33") { + testOptions.managedDevices.localDevices { + create("pixel6Api33") { device = "Pixel 6" apiLevel = 33 systemImageSource = "aosp" diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 6d0237010..166b54907 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -37,7 +37,7 @@ kotlin { } dependencies { - compileOnly(libs.android.gradlePlugin) + compileOnly(libs.android.gradleApiPlugin) compileOnly(libs.android.tools.common) compileOnly(libs.compose.gradlePlugin) compileOnly(libs.firebase.crashlytics.gradlePlugin) @@ -114,5 +114,9 @@ gradlePlugin { id = libs.plugins.nowinandroid.jvm.library.get().pluginId implementationClass = "JvmLibraryConventionPlugin" } + register("root") { + id = libs.plugins.nowinandroid.root.get().pluginId + implementationClass = "RootPlugin" + } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 1ab3a2ca0..f45d664b7 100644 --- a/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -16,7 +16,6 @@ import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension -import com.android.build.gradle.BaseExtension import com.google.samples.apps.nowinandroid.configureBadgingTasks import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureKotlinAndroid @@ -44,7 +43,7 @@ class AndroidApplicationConventionPlugin : Plugin { } extensions.configure { configurePrintApksTask(this) - configureBadgingTasks(extensions.getByType(), this) + configureBadgingTasks(extensions.getByType(), this) } } } diff --git a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt index 1af5523c5..343bd4859 100644 --- a/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidFeatureConventionPlugin.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -import com.android.build.gradle.LibraryExtension +import com.android.build.api.dsl.LibraryExtension import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.libs import org.gradle.api.Plugin diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt index 19fabf549..63a992b05 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -import com.android.build.gradle.LibraryExtension +import com.android.build.api.dsl.LibraryExtension import com.google.samples.apps.nowinandroid.configureAndroidCompose import org.gradle.api.Plugin import org.gradle.api.Project diff --git a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt index 3fe727410..0f6fde884 100644 --- a/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt @@ -14,8 +14,8 @@ * limitations under the License. */ +import com.android.build.api.dsl.LibraryExtension import com.android.build.api.variant.LibraryAndroidComponentsExtension -import com.android.build.gradle.LibraryExtension import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureKotlinAndroid @@ -37,7 +37,8 @@ class AndroidLibraryConventionPlugin : Plugin { extensions.configure { configureKotlinAndroid(this) - defaultConfig.targetSdk = 35 + testOptions.targetSdk = 35 + lint.targetSdk = 35 defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testOptions.animationsDisabled = true configureFlavors(this) diff --git a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt index 67933f77d..49c2eecec 100644 --- a/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/AndroidTestConventionPlugin.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -import com.android.build.gradle.TestExtension +import com.android.build.api.dsl.TestExtension import com.google.samples.apps.nowinandroid.configureGradleManagedDevices import com.google.samples.apps.nowinandroid.configureKotlinAndroid import org.gradle.api.Plugin diff --git a/build-logic/convention/src/main/kotlin/RootPlugin.kt b/build-logic/convention/src/main/kotlin/RootPlugin.kt new file mode 100644 index 000000000..b704adf76 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/RootPlugin.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.google.samples.apps.nowinandroid.configureGraphTasks +import org.gradle.api.Plugin +import org.gradle.api.Project + +class RootPlugin : Plugin { + override fun apply(target: Project) { + require(target.path == ":") + target.subprojects { configureGraphTasks() } + } +} diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt index ed2a5289b..3d050d86b 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/AndroidCompose.kt @@ -42,13 +42,6 @@ internal fun Project.configureAndroidCompose( "implementation"(libs.findLibrary("androidx-compose-ui-tooling-preview").get()) "debugImplementation"(libs.findLibrary("androidx-compose-ui-tooling").get()) } - - testOptions { - unitTests { - // For Robolectric - isIncludeAndroidResources = true - } - } } extensions.configure { diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Badging.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Badging.kt index 886c70625..229388001 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Badging.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Badging.kt @@ -18,8 +18,8 @@ package com.google.samples.apps.nowinandroid import com.android.SdkConstants import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension -import com.android.build.gradle.BaseExtension import com.google.common.truth.Truth.assertWithMessage import org.gradle.api.DefaultTask import org.gradle.api.Project @@ -110,7 +110,7 @@ private fun String.capitalized() = replaceFirstChar { } fun Project.configureBadgingTasks( - baseExtension: BaseExtension, + baseExtension: ApplicationExtension, componentsExtension: ApplicationAndroidComponentsExtension, ) { // Registers a callback to be called, when a new variant is configured diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt new file mode 100644 index 000000000..439a50181 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/Graph.kt @@ -0,0 +1,327 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid + +import com.android.utils.associateWithNotNull +import com.google.samples.apps.nowinandroid.PluginType.Unknown +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ProjectDependency +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.MapProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity.NONE +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.withType +import kotlin.text.RegexOption.DOT_MATCHES_ALL + +/** + * Generates module dependency graphs with `graphDump` task, and update the corresponding `README.md` file with `graphUpdate`. + * + * This is not an optimal implementation and could be improved if needed: + * - [Graph.invoke] is **recursively** searching through dependent projects (although in practice it will never reach a stack overflow). + * - [Graph.invoke] is entirely re-executed for all projects, without re-using intermediate values. + * - [Graph.invoke] is always executed during Gradle's Configuration phase (but takes in general less than 1 ms for a project). + * + * The resulting graphs can be configured with `graph.ignoredProjects` and `graph.supportedConfigurations` properties. + */ +private class Graph( + private val root: Project, + private val dependencies: MutableMap>> = mutableMapOf(), + private val plugins: MutableMap = mutableMapOf(), + private val seen: MutableSet = mutableSetOf(), +) { + + private val ignoredProjects = root.providers.gradleProperty("graph.ignoredProjects") + .map { it.split(",").toSet() } + .orElse(emptySet()) + private val supportedConfigurations = + root.providers.gradleProperty("graph.supportedConfigurations") + .map { it.split(",").toSet() } + .orElse(setOf("api", "implementation", "baselineProfile", "testedApks")) + + operator fun invoke(project: Project = root): Graph { + if (project.path in seen) return this + seen += project.path + plugins.putIfAbsent( + project, + PluginType.entries.firstOrNull { project.pluginManager.hasPlugin(it.id) } ?: Unknown, + ) + dependencies.compute(project) { _, u -> u.orEmpty() } + project.configurations + .matching { it.name in supportedConfigurations.get() } + .associateWithNotNull { it.dependencies.withType().ifEmpty { null } } + .flatMap { (c, value) -> value.map { dep -> c to project.project(dep.path) } } + .filter { (_, p) -> p.path !in ignoredProjects.get() } + .forEach { (configuration: Configuration, projectDependency: Project) -> + dependencies.compute(project) { _, u -> u.orEmpty() + (configuration to projectDependency) } + invoke(projectDependency) + } + return this + } + + fun dependencies(): Map>> = dependencies + .mapKeys { it.key.path } + .mapValues { it.value.mapTo(mutableSetOf()) { (c, p) -> c.name to p.path } } + + fun plugins() = plugins.mapKeys { it.key.path } +} + +/** + * Declaration order is important, as only the first match will be retained. + */ +internal enum class PluginType(val id: String, val ref: String, val style: String) { + AndroidApplication( + id = "nowinandroid.android.application", + ref = "android-application", + style = "fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000", + ), + AndroidFeature( + id = "nowinandroid.android.feature", + ref = "android-feature", + style = "fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000", + ), + AndroidLibrary( + id = "nowinandroid.android.library", + ref = "android-library", + style = "fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000", + ), + AndroidTest( + id = "nowinandroid.android.test", + ref = "android-test", + style = "fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000", + ), + Jvm( + id = "nowinandroid.jvm.library", + ref = "jvm-library", + style = "fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000", + ), + Unknown( + id = "?", + ref = "unknown", + style = "fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000", + ), +} + +internal fun Project.configureGraphTasks() { + if (!buildFile.exists()) return // Ignore root modules without build file + val dumpTask = tasks.register("graphDump") { + val graph = Graph(this@configureGraphTasks).invoke() + projectPath = this@configureGraphTasks.path + dependencies = graph.dependencies() + plugins = graph.plugins() + output = this@configureGraphTasks.layout.buildDirectory.file("mermaid/graph.txt") + legend = this@configureGraphTasks.layout.buildDirectory.file("mermaid/legend.txt") + } + tasks.register("graphUpdate") { + projectPath = this@configureGraphTasks.path + input = dumpTask.flatMap { it.output } + legend = dumpTask.flatMap { it.legend } + output = this@configureGraphTasks.layout.projectDirectory.file("README.md") + } +} + +@CacheableTask +private abstract class GraphDumpTask : DefaultTask() { + + @get:Input + abstract val projectPath: Property + + @get:Input + abstract val dependencies: MapProperty>> + + @get:Input + abstract val plugins: MapProperty + + @get:OutputFile + abstract val output: RegularFileProperty + + @get:OutputFile + abstract val legend: RegularFileProperty + + override fun getDescription() = "Dumps project dependencies to a mermaid file." + + @TaskAction + operator fun invoke() { + output.get().asFile.writeText(mermaid()) + legend.get().asFile.writeText(legend()) + logger.lifecycle(output.get().asFile.toPath().toUri().toString()) + } + + private fun mermaid() = buildString { + val dependencies: Set = dependencies.get() + .flatMapTo(mutableSetOf()) { (project, entries) -> entries.map { it.toDependency(project) } } + // FrontMatter configuration (not supported yet on GitHub.com) + appendLine( + // language=YAML + """ + --- + config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE + --- + """.trimIndent(), + ) + // Graph declaration + appendLine("graph TB") + // Nodes and subgraphs (limited to a single nested layer) + val (rootProjects, nestedProjects) = dependencies + .map { listOf(it.project, it.dependency) }.flatten().toSet() + .plus(projectPath.get()) // Special case when this specific module has no other dependency + .groupBy { it.substringBeforeLast(":") } + .entries.partition { it.key.isEmpty() } + nestedProjects.sortedByDescending { it.value.size }.forEach { (group, projects) -> + appendLine(" subgraph $group") + appendLine(" direction TB") + projects.sorted().forEach { + appendLine(it.alias(indent = 4, plugins.get().getValue(it))) + } + appendLine(" end") + } + rootProjects.flatMap { it.value }.sortedDescending().forEach { + appendLine(it.alias(indent = 2, plugins.get().getValue(it))) + } + // Links + if (dependencies.isNotEmpty()) appendLine() + dependencies + .sortedWith(compareBy({ it.project }, { it.dependency }, { it.configuration })) + .forEach { appendLine(it.link(indent = 2)) } + // Classes + appendLine() + PluginType.entries.forEach { appendLine(it.classDef()) } + } + + private fun legend() = buildString { + appendLine("graph TB") + listOf( + "application" to PluginType.AndroidApplication, + "feature" to PluginType.AndroidFeature, + "library" to PluginType.AndroidLibrary, + "jvm" to PluginType.Jvm, + ).forEach { (name, type) -> + appendLine(name.alias(indent = 2, type)) + } + appendLine() + listOf( + Dependency("application", "implementation", "feature"), + Dependency("library", "api", "jvm"), + ).forEach { + appendLine(it.link(indent = 2)) + } + appendLine() + PluginType.entries.forEach { appendLine(it.classDef()) } + } + + private class Dependency(val project: String, val configuration: String, val dependency: String) + + private fun Pair.toDependency(project: String) = + Dependency(project, configuration = first, dependency = second) + + private fun String.alias(indent: Int, pluginType: PluginType): String = buildString { + append(" ".repeat(indent)) + append(this@alias) + append("[").append(substringAfterLast(":")).append("]:::") + append(pluginType.ref) + } + + private fun Dependency.link(indent: Int) = buildString { + append(" ".repeat(indent)) + append(project).append(" ") + append( + when (configuration) { + "api" -> "-->" + "implementation" -> "-.->" + else -> "-.->|$configuration|" + }, + ) + append(" ").append(dependency) + } + + private fun PluginType.classDef() = "classDef $ref $style;" +} + +@CacheableTask +private abstract class GraphUpdateTask : DefaultTask() { + + @get:Input + abstract val projectPath: Property + + @get:InputFile + @get:PathSensitive(NONE) + abstract val input: RegularFileProperty + + @get:InputFile + @get:PathSensitive(NONE) + abstract val legend: RegularFileProperty + + @get:OutputFile + abstract val output: RegularFileProperty + + override fun getDescription() = "Updates Markdown file with the corresponding dependency graph." + + @TaskAction + operator fun invoke() = with(output.get().asFile) { + if (!exists()) { + createNewFile() + writeText( + """ + # `${projectPath.get()}` + + ## Module dependency graph + + + + """.trimIndent(), + ) + } + val mermaid = input.get().asFile.readText().trimTrailingNewLines() + val legend = legend.get().asFile.readText().trimTrailingNewLines() + val regex = """()(.*?)()""".toRegex(DOT_MATCHES_ALL) + val text = readText().replace(regex) { match -> + val (start, _, end) = match.destructured + """ + |$start + |```mermaid + |$mermaid + |``` + | + |
📋 Graph legend + | + |```mermaid + |$legend + |``` + | + |
+ |$end + """.trimMargin() + } + writeText(text) + } + + private fun String.trimTrailingNewLines() = lines() + .dropLastWhile(String::isBlank) + .joinToString(System.lineSeparator()) +} diff --git a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt index 8a41dbfcc..2ac96e556 100644 --- a/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/com/google/samples/apps/nowinandroid/KotlinAndroid.kt @@ -23,7 +23,6 @@ import org.gradle.api.plugins.JavaPluginExtension import org.gradle.kotlin.dsl.assign import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.provideDelegate import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinBaseExtension @@ -39,7 +38,7 @@ internal fun Project.configureKotlinAndroid( compileSdk = 35 defaultConfig { - minSdk = 21 + minSdk = 23 } compileOptions { @@ -78,14 +77,16 @@ internal fun Project.configureKotlinJvm() { private inline fun Project.configureKotlin() = configure { // Treat all Kotlin warnings as errors (disabled by default) // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties - val warningsAsErrors: String? by project + val warningsAsErrors = providers.gradleProperty("warningsAsErrors").map { + it.toBoolean() + }.orElse(false) when (this) { is KotlinAndroidProjectExtension -> compilerOptions is KotlinJvmProjectExtension -> compilerOptions else -> TODO("Unsupported project extension $this ${T::class}") }.apply { jvmTarget = JvmTarget.JVM_11 - allWarningsAsErrors = warningsAsErrors.toBoolean() + allWarningsAsErrors = warningsAsErrors freeCompilerArgs.add( // Enable experimental coroutines APIs, including Flow "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", diff --git a/build.gradle.kts b/build.gradle.kts index b7989bab4..594f7f92e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,28 +14,6 @@ * limitations under the License. */ -buildscript { - repositories { - google { - content { - includeGroupByRegex("com\\.android.*") - includeGroupByRegex("com\\.google.*") - includeGroupByRegex("androidx.*") - } - } - mavenCentral() - - // This is used only for internal Google builds. - maven { url = uri("../nowinandroid-prebuilts/m2repository") } - } - dependencies { - classpath(libs.google.oss.licenses.plugin) { - exclude(group = "com.google.protobuf") - } - } - -} - /* * By listing all the plugins used throughout all subprojects in the root project build script, it * ensures that the build script classpath remains the same for all projects. This avoids potential @@ -58,7 +36,7 @@ plugins { alias(libs.plugins.hilt) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.roborazzi) apply false - alias(libs.plugins.secrets) apply false + alias(libs.plugins.google.osslicenses) apply false alias(libs.plugins.room) apply false - alias(libs.plugins.module.graph) apply true // Plugin applied to allow module graph generation + alias(libs.plugins.nowinandroid.root) } diff --git a/core/analytics/README.md b/core/analytics/README.md index d2bcd1ea7..f6dab3bcc 100644 --- a/core/analytics/README.md +++ b/core/analytics/README.md @@ -1,3 +1,48 @@ -# :core:analytics module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_analytics.svg) +# `:core:analytics` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + end + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/common/README.md b/core/common/README.md index 96558bcc6..2f3865a8e 100644 --- a/core/common/README.md +++ b/core/common/README.md @@ -1,3 +1,48 @@ -# :core:common module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_common.svg) +# `:core:common` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm-library + end + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/data-test/README.md b/core/data-test/README.md index 977ee10e4..b36f5b66d 100644 --- a/core/data-test/README.md +++ b/core/data-test/README.md @@ -1,3 +1,73 @@ -# :core:data-test module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_data_test.svg) +# `:core:data-test` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:data-test[data-test]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:data-test --> :core:data + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/data/README.md b/core/data/README.md index 5d30f1638..0b84940d2 100644 --- a/core/data/README.md +++ b/core/data/README.md @@ -1,3 +1,71 @@ -# :core:data module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_data.svg) +# `:core:data` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index 8c839fa8e..c47d4ee58 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -22,11 +22,7 @@ plugins { android { namespace = "com.google.samples.apps.nowinandroid.core.data" - testOptions { - unitTests { - isIncludeAndroidResources = true - } - } + testOptions.unitTests.isIncludeAndroidResources = true } dependencies { diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt index c7dfd99d0..ac2b5c8af 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/UserNewsResourceTest.kt @@ -24,9 +24,9 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.UserData import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import kotlinx.datetime.Clock -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue class UserNewsResourceTest { diff --git a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt index a3e373918..1c3ec012a 100644 --- a/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt +++ b/core/data/src/test/kotlin/com/google/samples/apps/nowinandroid/core/data/testdoubles/TestNewsResourceDao.kt @@ -36,7 +36,7 @@ class TestNewsResourceDao : NewsResourceDao { private val entitiesStateFlow = MutableStateFlow(emptyList()) - internal var topicCrossReferences: List = listOf() + internal var topicCrossReferences: List = emptyList() override fun getNewsResources( useFilterTopicIds: Boolean, diff --git a/core/database/README.md b/core/database/README.md index 855eab53e..d050c6dbc 100644 --- a/core/database/README.md +++ b/core/database/README.md @@ -1,3 +1,51 @@ -# :core:database module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_database.svg) +# `:core:database` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:database[database]:::android-library + :core:model[model]:::jvm-library + end + + :core:database --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/database/src/main/kotlin/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt b/core/database/src/main/kotlin/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt index 9450a24ad..5aed1d1c2 100644 --- a/core/database/src/main/kotlin/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt +++ b/core/database/src/main/kotlin/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt @@ -49,5 +49,5 @@ fun NewsResourceEntity.asExternalModel() = NewsResource( headerImageUrl = headerImageUrl, publishDate = publishDate, type = type, - topics = listOf(), + topics = emptyList(), ) diff --git a/core/datastore-proto/README.md b/core/datastore-proto/README.md index 19ed58239..859e39756 100644 --- a/core/datastore-proto/README.md +++ b/core/datastore-proto/README.md @@ -1,3 +1,48 @@ -# :core:datastore-proto module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_proto.svg) +# `:core:datastore-proto` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:datastore-proto[datastore-proto]:::android-library + end + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/datastore-test/README.md b/core/datastore-test/README.md index 99cf13f1f..6de8718e8 100644 --- a/core/datastore-test/README.md +++ b/core/datastore-test/README.md @@ -1,3 +1,58 @@ -# :core:datastore-test module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore_test.svg) +# `:core:datastore-test` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:datastore-test[datastore-test]:::android-library + :core:model[model]:::jvm-library + end + + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:datastore-test -.-> :core:common + :core:datastore-test -.-> :core:datastore + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/datastore/README.md b/core/datastore/README.md index 4785c5885..744f60f43 100644 --- a/core/datastore/README.md +++ b/core/datastore/README.md @@ -1,3 +1,55 @@ -# :core:datastore module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_datastore.svg) +# `:core:datastore` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm-library + end + + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/designsystem/README.md b/core/designsystem/README.md index d1778cb14..3194165fd 100644 --- a/core/designsystem/README.md +++ b/core/designsystem/README.md @@ -1,3 +1,48 @@ -# :core:designsystem module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_designsystem.svg) +# `:core:designsystem` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:designsystem[designsystem]:::android-library + end + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/designsystem/build.gradle.kts b/core/designsystem/build.gradle.kts index aac2ddb8f..8a138082b 100644 --- a/core/designsystem/build.gradle.kts +++ b/core/designsystem/build.gradle.kts @@ -22,6 +22,7 @@ plugins { android { namespace = "com.google.samples.apps.nowinandroid.core.designsystem" + testOptions.unitTests.isIncludeAndroidResources = true } dependencies { diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt index f85c65677..ece8e0259 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/component/TopAppBar.kt @@ -45,7 +45,7 @@ fun NiaTopAppBar( actionIcon: ImageVector, actionIconContentDescription: String, modifier: Modifier = Modifier, - colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(), + colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(), onNavigationClick: () -> Unit = {}, onActionClick: () -> Unit = {}, ) { diff --git a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Type.kt b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Type.kt index 82d769863..289f09ce4 100644 --- a/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Type.kt +++ b/core/designsystem/src/main/kotlin/com/google/samples/apps/nowinandroid/core/designsystem/theme/Type.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.text.style.LineHeightStyle.Alignment import androidx.compose.ui.text.style.LineHeightStyle.Trim +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDirection import androidx.compose.ui.unit.sp /** @@ -33,30 +35,40 @@ internal val NiaTypography = Typography( fontSize = 57.sp, lineHeight = 64.sp, letterSpacing = (-0.25).sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), displayMedium = TextStyle( fontWeight = FontWeight.Normal, fontSize = 45.sp, lineHeight = 52.sp, letterSpacing = 0.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), displaySmall = TextStyle( fontWeight = FontWeight.Normal, fontSize = 36.sp, lineHeight = 44.sp, letterSpacing = 0.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), headlineLarge = TextStyle( fontWeight = FontWeight.Normal, fontSize = 32.sp, lineHeight = 40.sp, letterSpacing = 0.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), headlineMedium = TextStyle( fontWeight = FontWeight.Normal, fontSize = 28.sp, lineHeight = 36.sp, letterSpacing = 0.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), headlineSmall = TextStyle( fontWeight = FontWeight.Normal, @@ -67,6 +79,8 @@ internal val NiaTypography = Typography( alignment = Alignment.Bottom, trim = Trim.None, ), + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), titleLarge = TextStyle( fontWeight = FontWeight.Bold, @@ -77,18 +91,24 @@ internal val NiaTypography = Typography( alignment = Alignment.Bottom, trim = Trim.LastLineBottom, ), + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), titleMedium = TextStyle( fontWeight = FontWeight.Bold, fontSize = 18.sp, lineHeight = 24.sp, letterSpacing = 0.1.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), titleSmall = TextStyle( fontWeight = FontWeight.Medium, fontSize = 14.sp, lineHeight = 20.sp, letterSpacing = 0.1.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), // Default text style bodyLarge = TextStyle( @@ -100,18 +120,24 @@ internal val NiaTypography = Typography( alignment = Alignment.Center, trim = Trim.None, ), + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), bodyMedium = TextStyle( fontWeight = FontWeight.Normal, fontSize = 14.sp, lineHeight = 20.sp, letterSpacing = 0.25.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), bodySmall = TextStyle( fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = 16.sp, letterSpacing = 0.4.sp, + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), // Used for Button labelLarge = TextStyle( @@ -123,6 +149,8 @@ internal val NiaTypography = Typography( alignment = Alignment.Center, trim = Trim.LastLineBottom, ), + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), // Used for Navigation items labelMedium = TextStyle( @@ -134,6 +162,8 @@ internal val NiaTypography = Typography( alignment = Alignment.Center, trim = Trim.LastLineBottom, ), + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), // Used for Tag labelSmall = TextStyle( @@ -145,5 +175,7 @@ internal val NiaTypography = Typography( alignment = Alignment.Center, trim = Trim.LastLineBottom, ), + textDirection = TextDirection.Ltr, + textAlign = TextAlign.Left, ), ) diff --git a/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_androidTheme_notDynamic.png index d217e1116..86fce156f 100644 Binary files a/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_dynamic.png index d217e1116..86fce156f 100644 Binary files a/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_notDynamic.png index d217e1116..86fce156f 100644 Binary files a/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/IconButton/IconButton_dark_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/IconButton/IconButton_light_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/IconButton/IconButton_light_androidTheme_notDynamic.png index d217e1116..86fce156f 100644 Binary files a/core/designsystem/src/test/screenshots/IconButton/IconButton_light_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/IconButton/IconButton_light_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_dynamic.png index d217e1116..86fce156f 100644 Binary files a/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_notDynamic.png index d217e1116..86fce156f 100644 Binary files a/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/IconButton/IconButton_light_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_1000.png b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_1000.png index 316d899d2..b88567a42 100644 Binary files a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_1000.png and b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_1000.png differ diff --git a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_115.png b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_115.png index 4705b9beb..3bca04850 100644 Binary files a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_115.png and b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_115.png differ diff --git a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_20.png b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_20.png index 203a2ea2e..a209731e4 100644 Binary files a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_20.png and b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_20.png differ diff --git a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_724.png b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_724.png index 50a822621..d5e563544 100644 Binary files a/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_724.png and b/core/designsystem/src/test/screenshots/LoadingWheel/LoadingWheel_animation_724.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_androidTheme_notDynamic.png index 5e2a27c65..0940873c6 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_dynamic.png index efb1f8756..3575ac09f 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_notDynamic.png index 160a72d61..44bb3b5c6 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_dark_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_fontScale2.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_fontScale2.png index b4b4842c3..16df296d5 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_fontScale2.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_fontScale2.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_light_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_light_androidTheme_notDynamic.png index c3200091b..9409b984d 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_light_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_light_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_dynamic.png index 877c45cd0..233f86b35 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_notDynamic.png index 9fd6fc843..590c878a0 100644 Binary files a/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Navigation/Navigation_light_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_dark_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Tag/Tag_dark_androidTheme_notDynamic.png index 2a065eb57..4897d2a70 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_dark_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Tag/Tag_dark_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_dynamic.png index c532a307e..2e5bcbbbd 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_notDynamic.png index 61d3321b8..dcb18ab95 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Tag/Tag_dark_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_fontScale2.png b/core/designsystem/src/test/screenshots/Tag/Tag_fontScale2.png index 7cfdbb2a7..59a1aabd0 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_fontScale2.png and b/core/designsystem/src/test/screenshots/Tag/Tag_fontScale2.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_light_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Tag/Tag_light_androidTheme_notDynamic.png index fc29b6e11..c9f6523f3 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_light_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Tag/Tag_light_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_dynamic.png index ed825ba71..fb1023ece 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_notDynamic.png index 8acc6b0a8..224f34303 100644 Binary files a/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/Tag/Tag_light_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_androidTheme_notDynamic.png index 3617feab1..727910474 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_dynamic.png index 418e0f88d..2c09fedc3 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_notDynamic.png index 921698d22..cd52d5494 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_dark_defaultTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_fontScale2.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_fontScale2.png index 497561ef7..9e275f470 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_fontScale2.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_fontScale2.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_androidTheme_notDynamic.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_androidTheme_notDynamic.png index 4988252e5..64034e77e 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_androidTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_androidTheme_notDynamic.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_dynamic.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_dynamic.png index 6ab40ebf9..24116fcd2 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_dynamic.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_dynamic.png differ diff --git a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_notDynamic.png b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_notDynamic.png index d9d014a18..3f01e8743 100644 Binary files a/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_notDynamic.png and b/core/designsystem/src/test/screenshots/TopAppBar/TopAppBar_light_defaultTheme_notDynamic.png differ diff --git a/core/domain/README.md b/core/domain/README.md index cc6905846..b23877337 100644 --- a/core/domain/README.md +++ b/core/domain/README.md @@ -1,3 +1,74 @@ -# :core:domain module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_domain.svg) +# `:core:domain` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:domain --> :core:data + :core:domain --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/model/README.md b/core/model/README.md index efd0eec76..9cd7659a8 100644 --- a/core/model/README.md +++ b/core/model/README.md @@ -1,3 +1,48 @@ -# :core:model module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_model.svg) +# `:core:model` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:model[model]:::jvm-library + end + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/network/README.md b/core/network/README.md index 516aa2d38..d52be6270 100644 --- a/core/network/README.md +++ b/core/network/README.md @@ -1,3 +1,53 @@ -# :core:network module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_network.svg) +# `:core:network` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + end + + :core:network --> :core:common + :core:network --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts index d12482a56..edc28ea23 100644 --- a/core/network/build.gradle.kts +++ b/core/network/build.gradle.kts @@ -14,12 +14,15 @@ * limitations under the License. */ +import com.android.build.api.variant.BuildConfigField +import java.io.StringReader +import java.util.Properties + plugins { alias(libs.plugins.nowinandroid.android.library) alias(libs.plugins.nowinandroid.android.library.jacoco) alias(libs.plugins.nowinandroid.hilt) id("kotlinx-serialization") - id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } android { @@ -27,15 +30,7 @@ android { buildConfig = true } namespace = "com.google.samples.apps.nowinandroid.core.network" - testOptions { - unitTests { - isIncludeAndroidResources = true - } - } -} - -secrets { - defaultPropertiesFileName = "secrets.defaults.properties" + testOptions.unitTests.isIncludeAndroidResources = true } dependencies { @@ -52,3 +47,19 @@ dependencies { testImplementation(libs.kotlinx.coroutines.test) } + +val backendUrl = providers.fileContents( + isolated.rootProject.projectDirectory.file("local.properties") +).asText.map { text -> + val properties = Properties() + properties.load(StringReader(text)) + properties["BACKEND_URL"] +}.orElse("http://example.com") + +androidComponents { + onVariants { + it.buildConfigFields!!.put("BACKEND_URL", backendUrl.map { value -> + BuildConfigField(type = "String", value = """"$value"""", comment = null) + }) + } +} diff --git a/core/network/src/main/kotlin/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt b/core/network/src/main/kotlin/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt index 7b66af796..92e8e9ffa 100644 --- a/core/network/src/main/kotlin/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt +++ b/core/network/src/main/kotlin/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt @@ -16,6 +16,7 @@ package com.google.samples.apps.nowinandroid.core.network.model +import android.annotation.SuppressLint import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import kotlinx.datetime.Instant import kotlinx.serialization.Serializable @@ -23,6 +24,7 @@ import kotlinx.serialization.Serializable /** * Network representation of [NewsResource] when fetched from /newsresources */ +@SuppressLint("UnsafeOptInUsageError") @Serializable data class NetworkNewsResource( val id: String, @@ -32,5 +34,5 @@ data class NetworkNewsResource( val headerImageUrl: String, val publishDate: Instant, val type: String, - val topics: List = listOf(), + val topics: List = emptyList(), ) diff --git a/core/notifications/README.md b/core/notifications/README.md index 8f5607bdf..d184a6672 100644 --- a/core/notifications/README.md +++ b/core/notifications/README.md @@ -1,3 +1,53 @@ -# :core:notifications module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_notifications.svg) +# `:core:notifications` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:common[common]:::jvm-library + :core:model[model]:::jvm-library + :core:notifications[notifications]:::android-library + end + + :core:notifications -.-> :core:common + :core:notifications --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/screenshot-testing/README.md b/core/screenshot-testing/README.md index 9bd4f1f9c..793651023 100644 --- a/core/screenshot-testing/README.md +++ b/core/screenshot-testing/README.md @@ -1,3 +1,51 @@ -# :core:screenshot-testing module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_screenshot_testing.svg) +# `:core:screenshot-testing` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:designsystem[designsystem]:::android-library + :core:screenshot-testing[screenshot-testing]:::android-library + end + + :core:screenshot-testing -.-> :core:designsystem + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/testing/README.md b/core/testing/README.md index 5a35d379b..d5925b1a5 100644 --- a/core/testing/README.md +++ b/core/testing/README.md @@ -1,3 +1,77 @@ -# :core:testing module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_testing.svg) +# `:core:testing` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:testing[testing]:::android-library + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:testing --> :core:analytics + :core:testing --> :core:common + :core:testing --> :core:data + :core:testing --> :core:model + :core:testing --> :core:notifications + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/core/ui/README.md b/core/ui/README.md index 38e514d01..c6b365553 100644 --- a/core/ui/README.md +++ b/core/ui/README.md @@ -1,3 +1,55 @@ -# :core:ui module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_core_ui.svg) +# `:core:ui` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm-library + :core:ui[ui]:::android-library + end + + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/docs/ModularizationLearningJourney.md b/docs/ModularizationLearningJourney.md index a9766c68d..5cda61b69 100644 --- a/docs/ModularizationLearningJourney.md +++ b/docs/ModularizationLearningJourney.md @@ -85,7 +85,57 @@ how you can organize your project. In general, you should strive for low couplin ## Types of modules in Now in Android -![Diagram showing types of modules and their dependencies in Now in Android](images/modularization-graph.drawio.png "Diagram showing types of modules and their dependencies in Now in Android") +```mermaid +graph TB + subgraph :core + direction TB + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:topic[topic]:::android-feature + :feature:foryou[foryou]:::android-feature + :feature:interests[interests]:::android-feature + :feature:foo[...]:::android-feature + + end + :app[app]:::android-application + + :app -.-> :feature:foryou + :app -.-> :feature:interests + :app -.-> :feature:topic + :core:data ---> :core:database + :core:data ---> :core:network + :core:database ---> :core:model + :core:network ---> :core:model + :core:ui ---> :core:model + :feature:topic -.-> :core:data + :feature:topic -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application:::android-application -. implementation .-> feature:::android-feature + library:::android-library -- api --> jvm:::jvm-library + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +``` + +
**Top tip**: A module graph (shown above) can be useful during modularization planning for visualizing dependencies between modules. @@ -233,6 +283,9 @@ Using the above modularization strategy, the Now in Android app has the followin +Each module has its own `README.md` file containing a module graph (e.g. [`:app` module graph](../app/README.md#module-dependency-graph)). +When modules dependencies change, module graphs are automatically updated by the [Build.yaml](../.github/workflows/Build.yaml) workflow. +You can also manually update the graphs by running the `graphUpdate` task. ## Modularization in Now in Android diff --git a/docs/images/graphs/dep_graph_app.svg b/docs/images/graphs/dep_graph_app.svg deleted file mode 100644 index 8e5d9d429..000000000 --- a/docs/images/graphs/dep_graph_app.svg +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - :app - - - - :feature:interests - - - - - - - - :feature:foryou - - - - - - - - :feature:bookmarks - - - - - - - - :feature:topic - - - - - - - - :feature:search - - - - - - - - :feature:settings - - - - - - - - :core:common - - - - - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:model - - - - - - - - :core:analytics - - - - - - - - :sync:work - - - - - - - - - - - - - - - - - - - - :core:domain - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_app_nia_catalog.svg b/docs/images/graphs/dep_graph_app_nia_catalog.svg deleted file mode 100644 index 151ee63ad..000000000 --- a/docs/images/graphs/dep_graph_app_nia_catalog.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - :app-nia-catalog - - - - :core:designsystem - - - - - - - - :core:ui - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_analytics.svg b/docs/images/graphs/dep_graph_core_analytics.svg deleted file mode 100644 index 45f1c1eb0..000000000 --- a/docs/images/graphs/dep_graph_core_analytics.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:analytics - - - diff --git a/docs/images/graphs/dep_graph_core_common.svg b/docs/images/graphs/dep_graph_core_common.svg deleted file mode 100644 index 91033eaa0..000000000 --- a/docs/images/graphs/dep_graph_core_common.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:common - - - diff --git a/docs/images/graphs/dep_graph_core_data.svg b/docs/images/graphs/dep_graph_core_data.svg deleted file mode 100644 index ab91bafb2..000000000 --- a/docs/images/graphs/dep_graph_core_data.svg +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - :core:data - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_data_test.svg b/docs/images/graphs/dep_graph_core_data_test.svg deleted file mode 100644 index b9736c859..000000000 --- a/docs/images/graphs/dep_graph_core_data_test.svg +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - :core:data-test - - - - :core:data - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_database.svg b/docs/images/graphs/dep_graph_core_database.svg deleted file mode 100644 index e82d46436..000000000 --- a/docs/images/graphs/dep_graph_core_database.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - :core:database - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_datastore.svg b/docs/images/graphs/dep_graph_core_datastore.svg deleted file mode 100644 index f7502e55b..000000000 --- a/docs/images/graphs/dep_graph_core_datastore.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - :core:datastore - - - - :core:datastore-proto - - - - - - - - :core:model - - - - - - - - :core:common - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_datastore_proto.svg b/docs/images/graphs/dep_graph_core_datastore_proto.svg deleted file mode 100644 index 7fcfb8358..000000000 --- a/docs/images/graphs/dep_graph_core_datastore_proto.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:datastore-proto - - - diff --git a/docs/images/graphs/dep_graph_core_datastore_test.svg b/docs/images/graphs/dep_graph_core_datastore_test.svg deleted file mode 100644 index 37521a05f..000000000 --- a/docs/images/graphs/dep_graph_core_datastore_test.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - :core:datastore-test - - - - :core:common - - - - - - - - :core:datastore - - - - - - - - - - - - :core:datastore-proto - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_designsystem.svg b/docs/images/graphs/dep_graph_core_designsystem.svg deleted file mode 100644 index 737140876..000000000 --- a/docs/images/graphs/dep_graph_core_designsystem.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:designsystem - - - diff --git a/docs/images/graphs/dep_graph_core_domain.svg b/docs/images/graphs/dep_graph_core_domain.svg deleted file mode 100644 index fe3740d2f..000000000 --- a/docs/images/graphs/dep_graph_core_domain.svg +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - :core:domain - - - - :core:data - - - - - - - - :core:model - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_model.svg b/docs/images/graphs/dep_graph_core_model.svg deleted file mode 100644 index 125684a08..000000000 --- a/docs/images/graphs/dep_graph_core_model.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - :core:model - - - diff --git a/docs/images/graphs/dep_graph_core_network.svg b/docs/images/graphs/dep_graph_core_network.svg deleted file mode 100644 index 3022a86ee..000000000 --- a/docs/images/graphs/dep_graph_core_network.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - :core:network - - - - :core:common - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_notifications.svg b/docs/images/graphs/dep_graph_core_notifications.svg deleted file mode 100644 index d96d28769..000000000 --- a/docs/images/graphs/dep_graph_core_notifications.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - :core:notifications - - - - :core:model - - - - - - - - :core:common - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_screenshot_testing.svg b/docs/images/graphs/dep_graph_core_screenshot_testing.svg deleted file mode 100644 index a7d58b0ea..000000000 --- a/docs/images/graphs/dep_graph_core_screenshot_testing.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - :core:screenshot-testing - - - - :core:designsystem - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_testing.svg b/docs/images/graphs/dep_graph_core_testing.svg deleted file mode 100644 index d441858e5..000000000 --- a/docs/images/graphs/dep_graph_core_testing.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - :core:testing - - - - :core:analytics - - - - - - - - :core:common - - - - - - - - :core:data - - - - - - - - :core:model - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_core_ui.svg b/docs/images/graphs/dep_graph_core_ui.svg deleted file mode 100644 index 2cd972357..000000000 --- a/docs/images/graphs/dep_graph_core_ui.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - :core:ui - - - - :core:analytics - - - - - - - - :core:designsystem - - - - - - - - :core:model - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_bookmarks.svg b/docs/images/graphs/dep_graph_feature_bookmarks.svg deleted file mode 100644 index 0391eb39c..000000000 --- a/docs/images/graphs/dep_graph_feature_bookmarks.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - :feature:bookmarks - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_foryou.svg b/docs/images/graphs/dep_graph_feature_foryou.svg deleted file mode 100644 index 63a154a87..000000000 --- a/docs/images/graphs/dep_graph_feature_foryou.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - :feature:foryou - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:domain - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_interests.svg b/docs/images/graphs/dep_graph_feature_interests.svg deleted file mode 100644 index 2de1fc61f..000000000 --- a/docs/images/graphs/dep_graph_feature_interests.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - :feature:interests - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:domain - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_search.svg b/docs/images/graphs/dep_graph_feature_search.svg deleted file mode 100644 index 7f8f29777..000000000 --- a/docs/images/graphs/dep_graph_feature_search.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - :feature:search - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - :core:domain - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_settings.svg b/docs/images/graphs/dep_graph_feature_settings.svg deleted file mode 100644 index 3f0d35df2..000000000 --- a/docs/images/graphs/dep_graph_feature_settings.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - :feature:settings - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_feature_topic.svg b/docs/images/graphs/dep_graph_feature_topic.svg deleted file mode 100644 index b7c7dd26c..000000000 --- a/docs/images/graphs/dep_graph_feature_topic.svg +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - :feature:topic - - - - :core:ui - - - - - - - - :core:designsystem - - - - - - - - :core:data - - - - - - - - - - - - :core:analytics - - - - - - - - :core:model - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_sync_sync_test.svg b/docs/images/graphs/dep_graph_sync_sync_test.svg deleted file mode 100644 index 7a083ba54..000000000 --- a/docs/images/graphs/dep_graph_sync_sync_test.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - :sync:sync-test - - - - :core:data - - - - - - - - :sync:work - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:analytics - - - - - - - - :core:notifications - - - - - - - - - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/graphs/dep_graph_sync_work.svg b/docs/images/graphs/dep_graph_sync_work.svg deleted file mode 100644 index c649f2397..000000000 --- a/docs/images/graphs/dep_graph_sync_work.svg +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - :sync:work - - - - :core:analytics - - - - - - - - :core:data - - - - - - - - - - - - :core:common - - - - - - - - :core:database - - - - - - - - :core:datastore - - - - - - - - :core:network - - - - - - - - :core:notifications - - - - - - - - :core:model - - - - - - - - - - - - - - - - :core:datastore-proto - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/images/modularization-graph.drawio.png b/docs/images/modularization-graph.drawio.png deleted file mode 100644 index fb5bc375b..000000000 Binary files a/docs/images/modularization-graph.drawio.png and /dev/null differ diff --git a/feature/bookmarks/README.md b/feature/bookmarks/README.md index 54cbf91d0..2a2ebe214 100644 --- a/feature/bookmarks/README.md +++ b/feature/bookmarks/README.md @@ -1,3 +1,83 @@ -# :feature:bookmarks module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_bookmarks.svg) +# `:feature:bookmarks` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:bookmarks[bookmarks]:::android-feature + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:bookmarks -.-> :core:data + :feature:bookmarks -.-> :core:designsystem + :feature:bookmarks -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/feature/foryou/README.md b/feature/foryou/README.md index 0f08cb827..7cd42863d 100644 --- a/feature/foryou/README.md +++ b/feature/foryou/README.md @@ -1,3 +1,88 @@ -# :feature:foryou module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_foryou.svg) +# `:feature:foryou` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:foryou[foryou]:::android-feature + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:domain --> :core:data + :core:domain --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:foryou -.-> :core:data + :feature:foryou -.-> :core:designsystem + :feature:foryou -.-> :core:domain + :feature:foryou -.-> :core:notifications + :feature:foryou -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/feature/foryou/build.gradle.kts b/feature/foryou/build.gradle.kts index 59f6844cf..de1af7540 100644 --- a/feature/foryou/build.gradle.kts +++ b/feature/foryou/build.gradle.kts @@ -23,6 +23,7 @@ plugins { android { namespace = "com.google.samples.apps.nowinandroid.feature.foryou" + testOptions.unitTests.isIncludeAndroidResources = true } dependencies { diff --git a/feature/foryou/src/test/screenshots/ForYouScreenLoading_foldable.png b/feature/foryou/src/test/screenshots/ForYouScreenLoading_foldable.png index a699345c2..538c9032c 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenLoading_foldable.png and b/feature/foryou/src/test/screenshots/ForYouScreenLoading_foldable.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenLoading_phone.png b/feature/foryou/src/test/screenshots/ForYouScreenLoading_phone.png index 30c8fdad7..afd7dd708 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenLoading_phone.png and b/feature/foryou/src/test/screenshots/ForYouScreenLoading_phone.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenLoading_tablet.png b/feature/foryou/src/test/screenshots/ForYouScreenLoading_tablet.png index f54966dbc..1c197e8f0 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenLoading_tablet.png and b/feature/foryou/src/test/screenshots/ForYouScreenLoading_tablet.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_foldable.png b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_foldable.png index 3990aee3f..e4ecf6d95 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_foldable.png and b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_foldable.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_tablet.png b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_tablet.png index 3b735462f..53891bdc1 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_tablet.png and b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedAndLoading_tablet.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_foldable.png b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_foldable.png index 0da7e19ac..ba669e8f8 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_foldable.png and b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_foldable.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_phone.png b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_phone.png index a7b775315..1498f9b7b 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_phone.png and b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_phone.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_tablet.png b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_tablet.png index e7f0cc050..e92ae0481 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_tablet.png and b/feature/foryou/src/test/screenshots/ForYouScreenPopulatedFeed_tablet.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_foldable.png b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_foldable.png index f5d68fce2..3ae1bee94 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_foldable.png and b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_foldable.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone.png b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone.png index b04c632c3..0938678b2 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone.png and b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone_dark.png b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone_dark.png index 6c4d66b28..084d031a5 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone_dark.png and b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_phone_dark.png differ diff --git a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_tablet.png b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_tablet.png index f7c20a890..35f59e54c 100644 Binary files a/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_tablet.png and b/feature/foryou/src/test/screenshots/ForYouScreenTopicSelection_tablet.png differ diff --git a/feature/interests/README.md b/feature/interests/README.md index 90a4fbc9c..529f8abe7 100644 --- a/feature/interests/README.md +++ b/feature/interests/README.md @@ -1,3 +1,87 @@ -# :feature:interests module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_interests.svg) +# `:feature:interests` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:interests[interests]:::android-feature + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:domain --> :core:data + :core:domain --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:interests -.-> :core:data + :feature:interests -.-> :core:designsystem + :feature:interests -.-> :core:domain + :feature:interests -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt index 468550878..9b18ac89b 100644 --- a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt +++ b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/InterestsScreen.kt @@ -38,7 +38,7 @@ import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent fun InterestsRoute( onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, - highlightSelectedTopic: Boolean = false, + shouldHighlightSelectedTopic: Boolean = false, viewModel: InterestsViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() @@ -50,7 +50,7 @@ fun InterestsRoute( viewModel.onTopicClick(it) onTopicClick(it) }, - highlightSelectedTopic = highlightSelectedTopic, + shouldHighlightSelectedTopic = shouldHighlightSelectedTopic, modifier = modifier, ) } @@ -61,7 +61,7 @@ internal fun InterestsScreen( followTopic: (String, Boolean) -> Unit, onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, - highlightSelectedTopic: Boolean = false, + shouldHighlightSelectedTopic: Boolean = false, ) { Column( modifier = modifier, @@ -70,7 +70,6 @@ internal fun InterestsScreen( when (uiState) { InterestsUiState.Loading -> NiaLoadingWheel( - modifier = modifier, contentDesc = stringResource(id = R.string.feature_interests_loading), ) @@ -80,8 +79,7 @@ internal fun InterestsScreen( onTopicClick = onTopicClick, onFollowButtonClick = followTopic, selectedTopicId = uiState.selectedTopicId, - highlightSelectedTopic = highlightSelectedTopic, - modifier = modifier, + shouldHighlightSelectedTopic = shouldHighlightSelectedTopic, ) is InterestsUiState.Empty -> InterestsEmptyScreen() diff --git a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/TabContent.kt b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/TabContent.kt index 83058c12e..133c2bedd 100644 --- a/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/TabContent.kt +++ b/feature/interests/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/interests/TabContent.kt @@ -49,7 +49,7 @@ fun TopicsTabContent( modifier: Modifier = Modifier, withBottomSpacer: Boolean = true, selectedTopicId: String? = null, - highlightSelectedTopic: Boolean = false, + shouldHighlightSelectedTopic: Boolean = false, ) { Box( modifier = modifier @@ -66,7 +66,7 @@ fun TopicsTabContent( topics.forEach { followableTopic -> val topicId = followableTopic.topic.id item(key = topicId) { - val isSelected = highlightSelectedTopic && topicId == selectedTopicId + val isSelected = shouldHighlightSelectedTopic && topicId == selectedTopicId InterestsItem( name = followableTopic.topic.name, following = followableTopic.isFollowed, @@ -75,6 +75,7 @@ fun TopicsTabContent( onClick = { onTopicClick(topicId) }, onFollowButtonClick = { onFollowButtonClick(topicId, it) }, isSelected = isSelected, + modifier = Modifier.fillMaxWidth(), ) } } diff --git a/feature/search/README.md b/feature/search/README.md index e205970f0..d8160a627 100644 --- a/feature/search/README.md +++ b/feature/search/README.md @@ -1,3 +1,87 @@ -# :feature:search module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_search.svg) +# `:feature:search` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:domain[domain]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:search[search]:::android-feature + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:domain --> :core:data + :core:domain --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:search -.-> :core:data + :feature:search -.-> :core:designsystem + :feature:search -.-> :core:domain + :feature:search -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/feature/settings/README.md b/feature/settings/README.md index 7a4df04fe..26c65eba0 100644 --- a/feature/settings/README.md +++ b/feature/settings/README.md @@ -1,3 +1,83 @@ -# :feature:settings module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_settings.svg) +# `:feature:settings` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:settings[settings]:::android-feature + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:settings -.-> :core:data + :feature:settings -.-> :core:designsystem + :feature:settings -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/feature/topic/README.md b/feature/topic/README.md index 84588929c..8f88be578 100644 --- a/feature/topic/README.md +++ b/feature/topic/README.md @@ -1,3 +1,83 @@ -# :feature:topic module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_feature_topic.svg) +# `:feature:topic` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:designsystem[designsystem]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + :core:ui[ui]:::android-library + end + subgraph :feature + direction TB + :feature:topic[topic]:::android-feature + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :core:ui --> :core:analytics + :core:ui --> :core:designsystem + :core:ui --> :core:model + :feature:topic -.-> :core:data + :feature:topic -.-> :core:designsystem + :feature:topic -.-> :core:ui + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt index ba8baad14..8865da463 100644 --- a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt +++ b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt @@ -16,10 +16,8 @@ package com.google.samples.apps.nowinandroid.feature.topic -import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.navigation.toRoute import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository @@ -29,7 +27,9 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import com.google.samples.apps.nowinandroid.core.result.Result import com.google.samples.apps.nowinandroid.core.result.asResult -import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted @@ -38,18 +38,14 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class TopicViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, +@HiltViewModel(assistedFactory = TopicViewModel.Factory::class) +class TopicViewModel @AssistedInject constructor( private val userDataRepository: UserDataRepository, topicsRepository: TopicsRepository, userNewsResourceRepository: UserNewsResourceRepository, + @Assisted val topicId: String, ) : ViewModel() { - - val topicId = savedStateHandle.toRoute().id - val topicUiState: StateFlow = topicUiState( topicId = topicId, userDataRepository = userDataRepository, @@ -89,6 +85,13 @@ class TopicViewModel @Inject constructor( userDataRepository.setNewsResourceViewed(newsResourceId, viewed) } } + + @AssistedFactory + interface Factory { + fun create( + topicId: String, + ): TopicViewModel + } } private fun topicUiState( diff --git a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt index fabb82b10..69059c81d 100644 --- a/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt +++ b/feature/topic/src/main/kotlin/com/google/samples/apps/nowinandroid/feature/topic/navigation/TopicNavigation.kt @@ -16,11 +16,14 @@ package com.google.samples.apps.nowinandroid.feature.topic.navigation +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptionsBuilder import androidx.navigation.compose.composable +import androidx.navigation.toRoute import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen +import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel import kotlinx.serialization.Serializable @Serializable data class TopicRoute(val id: String) @@ -36,11 +39,17 @@ fun NavGraphBuilder.topicScreen( onBackClick: () -> Unit, onTopicClick: (String) -> Unit, ) { - composable { + composable { entry -> + val id = entry.toRoute().id TopicScreen( showBackButton = showBackButton, onBackClick = onBackClick, onTopicClick = onTopicClick, + viewModel = hiltViewModel( + key = id, + ) { factory -> + factory.create(id) + }, ) } } diff --git a/feature/topic/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt b/feature/topic/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt index 34f21a59a..58242110d 100644 --- a/feature/topic/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt +++ b/feature/topic/src/test/kotlin/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt @@ -16,8 +16,6 @@ package com.google.samples.apps.nowinandroid.feature.topic -import androidx.lifecycle.SavedStateHandle -import androidx.navigation.testing.invoke import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.NewsResource @@ -26,7 +24,6 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepo import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule -import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first @@ -37,22 +34,13 @@ import kotlinx.datetime.Instant import org.junit.Before import org.junit.Rule import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner import kotlin.test.assertEquals import kotlin.test.assertIs /** * To learn more about how this test handles Flows created with stateIn, see * https://developer.android.com/kotlin/flow/test#statein - * - * These tests use Robolectric because the subject under test (the ViewModel) uses - * `SavedStateHandle.toRoute` which has a dependency on `android.os.Bundle`. - * - * TODO: Remove Robolectric if/when AndroidX Navigation API is updated to remove Android dependency. - * * See b/340966212. */ -@RunWith(RobolectricTestRunner::class) class TopicViewModelTest { @get:Rule @@ -70,12 +58,10 @@ class TopicViewModelTest { @Before fun setup() { viewModel = TopicViewModel( - savedStateHandle = SavedStateHandle( - route = TopicRoute(id = testInputTopics[0].topic.id), - ), userDataRepository = userDataRepository, topicsRepository = topicsRepository, userNewsResourceRepository = userNewsResourceRepository, + topicId = testInputTopics[0].topic.id, ) } diff --git a/generateModuleGraphs.sh b/generateModuleGraphs.sh deleted file mode 100755 index 5307d2932..000000000 --- a/generateModuleGraphs.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/bash -# -# Copyright 2024 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# -# Script to generate dependency graphs for each of the modules. The --exclude-module parameter can -# be used to exclude modules which are not part of the root dependency graph (and which, if included -# would cause the script to fail. -# -# Usage: generateModuleGraphs.sh --exclude-module :benchmarks --exclude-module :lint --exclude-module :ui-test-hilt-manifest - -# Check if the dot command is available -if ! command -v dot &> /dev/null -then - echo "The 'dot' command is not found. This is required to generate SVGs from the Graphviz files." - echo "Installation instructions:" - echo " - On macOS: You can install Graphviz using Homebrew with the command: 'brew install graphviz'" - echo " - On Ubuntu: You can install Graphviz using APT with the command: 'sudo apt install graphviz'" - echo " - Others: Visit https://graphviz.org/download/" - exit 1 -fi - -# Check if the svgo command is available -if ! command -v svgo &> /dev/null -then - echo "The 'svgo' command is not found. This is required to cleanup and compress SVGs." - echo "Installation instructions available at https://github.com/svg/svgo." - exit 1 -fi - -# Check for a version of grep which supports Perl regex. -# On MacOS the OS installed grep doesn't support Perl regex so check for the existence of the -# GNU version instead which is prefixed with 'g' to distinguish it from the OS installed version. - if grep -P "" /dev/null > /dev/null 2>&1; then - GREP_COMMAND=grep -elif command -v ggrep &> /dev/null; then - GREP_COMMAND=ggrep -else - echo "You don't have a version of 'grep' installed which supports Perl regular expressions." - echo "On MacOS you can install one using Homebrew with the command: 'brew install grep'" - exit 1 -fi - -# Initialize an array to store excluded modules -excluded_modules=() - -# Parse command-line arguments for excluded modules -while [[ $# -gt 0 ]]; do - case "$1" in - --exclude-module) - excluded_modules+=("$2") - shift # Past argument - shift # Past value - ;; - *) - echo "Unknown parameter passed: $1" - exit 1 - ;; - esac -done - -# Get the module paths -module_paths=$(${GREP_COMMAND} -oP 'include\("\K[^"]+' settings.gradle.kts) - -# Ensure the output directory exists -mkdir -p docs/images/graphs/ - -# Function to check and create a README.md for modules which don't have one. -check_and_create_readme() { - local module_path="$1" - local file_name="$2" - - local readme_path="${module_path:1}" # Remove leading colon - readme_path=${readme_path//:/\/} # Replace colons with slashes - readme_path="${readme_path}/README.md" #Append the filename - - # Check if README.md exists and create it if not - if [[ ! -f "$readme_path" ]]; then - echo "Creating README.md for ${module_path}" - - # Determine the depth of the module based on the number of colons - local depth=$(awk -F: '{print NF-1}' <<< "${module_path}") - - # Construct the relative image path with the correct number of "../" - local relative_image_path="../" - for ((i=1; i<$depth; i++)); do - relative_image_path+="../" - done - relative_image_path+="docs/images/graphs/${file_name}.svg" - - echo "# ${module_path} module" > "$readme_path" - echo "## Dependency graph" >> "$readme_path" - echo "![Dependency graph](${relative_image_path})" >> "$readme_path" - fi -} - -# Loop through each module path -echo "$module_paths" | while read -r module_path; do - # Check if the module is in the excluded list - if [[ ! " ${excluded_modules[@]} " =~ " ${module_path} " ]]; then - # Derive the filename from the module path - file_name="dep_graph${module_path//:/_}" # Replace colons with underscores - file_name="${file_name//-/_}" # Replace dashes with underscores - - check_and_create_readme "$module_path" "$file_name" - - # Generate the .gv file in a temporary location - # /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c7..e509b2dd8 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/lint/README.md b/lint/README.md new file mode 100644 index 000000000..24d312242 --- /dev/null +++ b/lint/README.md @@ -0,0 +1,45 @@ +# `:lint` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + :lint[lint]:::unknown + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/secrets.defaults.properties b/secrets.defaults.properties deleted file mode 100644 index 3b5457bd9..000000000 --- a/secrets.defaults.properties +++ /dev/null @@ -1,4 +0,0 @@ -## This file provides default values to modules using the secrets-gradle-plugin. It is necessary -# because the secrets properties file is not under source control so CI builds will fail without -# default values. -BACKEND_URL="http://example.com" \ No newline at end of file diff --git a/sync/sync-test/README.md b/sync/sync-test/README.md index 78876290f..69f24aaea 100644 --- a/sync/sync-test/README.md +++ b/sync/sync-test/README.md @@ -1,3 +1,81 @@ -# :sync:sync-test module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_sync_sync_test.svg) +# `:sync:sync-test` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + subgraph :sync + direction TB + :sync:sync-test[sync-test]:::android-library + :sync:work[work]:::android-library + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :sync:sync-test -.-> :core:data + :sync:sync-test -.-> :sync:work + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/sync/work/README.md b/sync/work/README.md index 2fe66d616..91abef4d2 100644 --- a/sync/work/README.md +++ b/sync/work/README.md @@ -1,3 +1,78 @@ -# :sync:work module -## Dependency graph -![Dependency graph](../../docs/images/graphs/dep_graph_sync_work.svg) +# `:sync:work` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + subgraph :core + direction TB + :core:analytics[analytics]:::android-library + :core:common[common]:::jvm-library + :core:data[data]:::android-library + :core:database[database]:::android-library + :core:datastore[datastore]:::android-library + :core:datastore-proto[datastore-proto]:::android-library + :core:model[model]:::jvm-library + :core:network[network]:::android-library + :core:notifications[notifications]:::android-library + end + subgraph :sync + direction TB + :sync:work[work]:::android-library + end + + :core:data -.-> :core:analytics + :core:data --> :core:common + :core:data --> :core:database + :core:data --> :core:datastore + :core:data --> :core:network + :core:data -.-> :core:notifications + :core:database --> :core:model + :core:datastore -.-> :core:common + :core:datastore --> :core:datastore-proto + :core:datastore --> :core:model + :core:network --> :core:common + :core:network --> :core:model + :core:notifications -.-> :core:common + :core:notifications --> :core:model + :sync:work -.-> :core:analytics + :sync:work -.-> :core:data + :sync:work -.-> :core:notifications + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+ diff --git a/ui-test-hilt-manifest/README.md b/ui-test-hilt-manifest/README.md new file mode 100644 index 000000000..eb4e4b1f7 --- /dev/null +++ b/ui-test-hilt-manifest/README.md @@ -0,0 +1,45 @@ +# `:ui-test-hilt-manifest` + +## Module dependency graph + + +```mermaid +--- +config: + layout: elk + elk: + nodePlacementStrategy: SIMPLE +--- +graph TB + :ui-test-hilt-manifest[ui-test-hilt-manifest]:::android-library + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
📋 Graph legend + +```mermaid +graph TB + application[application]:::android-application + feature[feature]:::android-feature + library[library]:::android-library + jvm[jvm]:::jvm-library + + application -.-> feature + library --> jvm + +classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; +classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; +classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; +classDef android-test fill:#A0C4FF,stroke:#000,stroke-width:2px,color:#000; +classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; +classDef unknown fill:#FFADAD,stroke:#000,stroke-width:2px,color:#000; +``` + +
+