Merge branch 'main' into ja/edge-to-edge-dropshots

ben/dropshots
Jose Alcérreca 6 months ago committed by GitHub
commit 3f6856b148
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -2,8 +2,8 @@ androidx.activity:activity-compose:1.8.2
androidx.activity:activity-ktx:1.8.2 androidx.activity:activity-ktx:1.8.2
androidx.activity:activity:1.8.2 androidx.activity:activity:1.8.2
androidx.annotation:annotation-experimental:1.4.0 androidx.annotation:annotation-experimental:1.4.0
androidx.annotation:annotation-jvm:1.7.1 androidx.annotation:annotation-jvm:1.8.0-rc01
androidx.annotation:annotation:1.7.1 androidx.annotation:annotation:1.8.0-rc01
androidx.appcompat:appcompat-resources:1.6.1 androidx.appcompat:appcompat-resources:1.6.1
androidx.arch.core:core-common:2.2.0 androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0 androidx.arch.core:core-runtime:2.2.0
@ -12,14 +12,18 @@ androidx.browser:browser:1.8.0
androidx.collection:collection-jvm:1.4.0 androidx.collection:collection-jvm:1.4.0
androidx.collection:collection-ktx:1.4.0 androidx.collection:collection-ktx:1.4.0
androidx.collection:collection:1.4.0 androidx.collection:collection:1.4.0
androidx.compose.animation:animation-android:1.6.3 androidx.compose.animation:animation-android:1.7.0-alpha08
androidx.compose.animation:animation-core-android:1.6.3 androidx.compose.animation:animation-core-android:1.7.0-alpha08
androidx.compose.animation:animation-core:1.6.3 androidx.compose.animation:animation-core:1.7.0-alpha08
androidx.compose.animation:animation:1.6.3 androidx.compose.animation:animation:1.7.0-alpha08
androidx.compose.foundation:foundation-android:1.6.3 androidx.compose.foundation:foundation-android:1.7.0-alpha08
androidx.compose.foundation:foundation-layout-android:1.6.3 androidx.compose.foundation:foundation-layout-android:1.7.0-alpha08
androidx.compose.foundation:foundation-layout:1.6.3 androidx.compose.foundation:foundation-layout:1.7.0-alpha08
androidx.compose.foundation:foundation:1.6.3 androidx.compose.foundation:foundation:1.7.0-alpha08
androidx.compose.material3.adaptive:adaptive-android:1.0.0-alpha12
androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.0.0-alpha07
androidx.compose.material3:material3-adaptive-navigation-suite:1.0.0-alpha07
androidx.compose.material3:material3-android:1.2.1 androidx.compose.material3:material3-android:1.2.1
androidx.compose.material3:material3:1.2.1 androidx.compose.material3:material3:1.2.1
androidx.compose.material:material-icons-core-android:1.6.3 androidx.compose.material:material-icons-core-android:1.6.3
@ -28,45 +32,52 @@ androidx.compose.material:material-icons-extended-android:1.6.3
androidx.compose.material:material-icons-extended:1.6.3 androidx.compose.material:material-icons-extended:1.6.3
androidx.compose.material:material-ripple-android:1.6.3 androidx.compose.material:material-ripple-android:1.6.3
androidx.compose.material:material-ripple:1.6.3 androidx.compose.material:material-ripple:1.6.3
androidx.compose.runtime:runtime-android:1.6.3 androidx.compose.runtime:runtime-android:1.7.0-alpha08
androidx.compose.runtime:runtime-saveable-android:1.6.3 androidx.compose.runtime:runtime-saveable-android:1.7.0-alpha08
androidx.compose.runtime:runtime-saveable:1.6.3 androidx.compose.runtime:runtime-saveable:1.7.0-alpha08
androidx.compose.runtime:runtime:1.6.3 androidx.compose.runtime:runtime:1.7.0-alpha08
androidx.compose.ui:ui-android:1.6.3 androidx.compose.ui:ui-android:1.7.0-alpha08
androidx.compose.ui:ui-geometry-android:1.6.3 androidx.compose.ui:ui-geometry-android:1.7.0-alpha08
androidx.compose.ui:ui-geometry:1.6.3 androidx.compose.ui:ui-geometry:1.7.0-alpha08
androidx.compose.ui:ui-graphics-android:1.6.3 androidx.compose.ui:ui-graphics-android:1.7.0-alpha08
androidx.compose.ui:ui-graphics:1.6.3 androidx.compose.ui:ui-graphics:1.7.0-alpha08
androidx.compose.ui:ui-text-android:1.6.3 androidx.compose.ui:ui-text-android:1.7.0-alpha08
androidx.compose.ui:ui-text:1.6.3 androidx.compose.ui:ui-text:1.7.0-alpha08
androidx.compose.ui:ui-tooling-preview-android:1.6.3 androidx.compose.ui:ui-tooling-preview-android:1.7.0-alpha08
androidx.compose.ui:ui-tooling-preview:1.6.3 androidx.compose.ui:ui-tooling-preview:1.7.0-alpha08
androidx.compose.ui:ui-unit-android:1.6.3 androidx.compose.ui:ui-unit-android:1.7.0-alpha08
androidx.compose.ui:ui-unit:1.6.3 androidx.compose.ui:ui-unit:1.7.0-alpha08
androidx.compose.ui:ui-util-android:1.6.3 androidx.compose.ui:ui-util-android:1.7.0-alpha08
androidx.compose.ui:ui-util:1.6.3 androidx.compose.ui:ui-util:1.7.0-alpha08
androidx.compose.ui:ui:1.6.3 androidx.compose.ui:ui:1.7.0-alpha08
androidx.compose:compose-bom:2024.02.02 androidx.compose:compose-bom:2024.02.02
androidx.concurrent:concurrent-futures:1.1.0 androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.12.0 androidx.core:core-ktx:1.13.1
androidx.core:core:1.12.0 androidx.core:core:1.13.1
androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.0.0 androidx.customview:customview:1.0.0
androidx.emoji2:emoji2:1.3.0 androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.7 androidx.exifinterface:exifinterface:1.3.7
androidx.fragment:fragment:1.5.1 androidx.fragment:fragment:1.5.1
androidx.graphics:graphics-path:1.0.1
androidx.interpolator:interpolator:1.0.0 androidx.interpolator:interpolator:1.0.0
androidx.lifecycle:lifecycle-common-java8:2.7.0 androidx.lifecycle:lifecycle-common-java8:2.8.0-rc01
androidx.lifecycle:lifecycle-common:2.7.0 androidx.lifecycle:lifecycle-common-jvm:2.8.0-rc01
androidx.lifecycle:lifecycle-livedata-core-ktx:2.7.0 androidx.lifecycle:lifecycle-common:2.8.0-rc01
androidx.lifecycle:lifecycle-livedata-core:2.7.0 androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.0-rc01
androidx.lifecycle:lifecycle-livedata:2.7.0 androidx.lifecycle:lifecycle-livedata-core:2.8.0-rc01
androidx.lifecycle:lifecycle-process:2.7.0 androidx.lifecycle:lifecycle-livedata:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime-ktx:2.7.0 androidx.lifecycle:lifecycle-process:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime:2.7.0 androidx.lifecycle:lifecycle-runtime-android:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0 androidx.lifecycle:lifecycle-runtime-compose-android:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.7.0 androidx.lifecycle:lifecycle-runtime-compose:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel:2.7.0 androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime-ktx:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-android:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel:2.8.0-rc01
androidx.loader:loader:1.0.0 androidx.loader:loader:1.0.0
androidx.metrics:metrics-performance:1.0.0-alpha04 androidx.metrics:metrics-performance:1.0.0-alpha04
androidx.profileinstaller:profileinstaller:1.3.1 androidx.profileinstaller:profileinstaller:1.3.1
@ -79,6 +90,10 @@ androidx.vectordrawable:vectordrawable-animated:1.1.0
androidx.vectordrawable:vectordrawable:1.1.0 androidx.vectordrawable:vectordrawable:1.1.0
androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.versionedparcelable:versionedparcelable:1.1.1
androidx.viewpager:viewpager:1.0.0 androidx.viewpager:viewpager:1.0.0
androidx.window.extensions.core:core:1.0.0
androidx.window:window-core-android:1.3.0-beta01
androidx.window:window-core:1.3.0-beta01
androidx.window:window:1.3.0-beta01
com.google.accompanist:accompanist-drawablepainter:0.32.0 com.google.accompanist:accompanist-drawablepainter:0.32.0
com.google.code.findbugs:jsr305:3.0.2 com.google.code.findbugs:jsr305:3.0.2
com.google.dagger:dagger-lint-aar:2.51 com.google.dagger:dagger-lint-aar:2.51
@ -94,10 +109,10 @@ io.coil-kt:coil-compose-base:2.6.0
io.coil-kt:coil-compose:2.6.0 io.coil-kt:coil-compose:2.6.0
io.coil-kt:coil:2.6.0 io.coil-kt:coil:2.6.0
javax.inject:javax.inject:1 javax.inject:javax.inject:1
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.22 org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0
org.jetbrains.kotlin:kotlin-stdlib:1.9.22 org.jetbrains.kotlin:kotlin-stdlib:1.9.23
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.7.3
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3

@ -2,8 +2,8 @@ androidx.activity:activity-compose:1.8.2
androidx.activity:activity-ktx:1.8.2 androidx.activity:activity-ktx:1.8.2
androidx.activity:activity:1.8.2 androidx.activity:activity:1.8.2
androidx.annotation:annotation-experimental:1.4.0 androidx.annotation:annotation-experimental:1.4.0
androidx.annotation:annotation-jvm:1.8.0-beta01 androidx.annotation:annotation-jvm:1.8.0-rc01
androidx.annotation:annotation:1.8.0-beta01 androidx.annotation:annotation:1.8.0-rc01
androidx.appcompat:appcompat-resources:1.6.1 androidx.appcompat:appcompat-resources:1.6.1
androidx.appcompat:appcompat:1.6.1 androidx.appcompat:appcompat:1.6.1
androidx.arch.core:core-common:2.2.0 androidx.arch.core:core-common:2.2.0
@ -13,20 +13,22 @@ androidx.browser:browser:1.8.0
androidx.collection:collection-jvm:1.4.0 androidx.collection:collection-jvm:1.4.0
androidx.collection:collection-ktx:1.4.0 androidx.collection:collection-ktx:1.4.0
androidx.collection:collection:1.4.0 androidx.collection:collection:1.4.0
androidx.compose.animation:animation-android:1.7.0-alpha06 androidx.compose.animation:animation-android:1.7.0-alpha08
androidx.compose.animation:animation-core-android:1.7.0-alpha06 androidx.compose.animation:animation-core-android:1.7.0-alpha08
androidx.compose.animation:animation-core:1.7.0-alpha06 androidx.compose.animation:animation-core:1.7.0-alpha08
androidx.compose.animation:animation:1.7.0-alpha06 androidx.compose.animation:animation:1.7.0-alpha08
androidx.compose.foundation:foundation-android:1.7.0-alpha06 androidx.compose.foundation:foundation-android:1.7.0-alpha08
androidx.compose.foundation:foundation-layout-android:1.7.0-alpha06 androidx.compose.foundation:foundation-layout-android:1.7.0-alpha08
androidx.compose.foundation:foundation-layout:1.7.0-alpha06 androidx.compose.foundation:foundation-layout:1.7.0-alpha08
androidx.compose.foundation:foundation:1.7.0-alpha06 androidx.compose.foundation:foundation:1.7.0-alpha08
androidx.compose.material3.adaptive:adaptive-android:1.0.0-alpha10 androidx.compose.material3.adaptive:adaptive-android:1.0.0-alpha12
androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0-alpha10 androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0-alpha12
androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha10 androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha12
androidx.compose.material3.adaptive:adaptive-navigation-android:1.0.0-alpha10 androidx.compose.material3.adaptive:adaptive-navigation-android:1.0.0-alpha12
androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha10 androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha12
androidx.compose.material3.adaptive:adaptive:1.0.0-alpha10 androidx.compose.material3.adaptive:adaptive:1.0.0-alpha12
androidx.compose.material3:material3-adaptive-navigation-suite-android:1.0.0-alpha07
androidx.compose.material3:material3-adaptive-navigation-suite:1.0.0-alpha07
androidx.compose.material3:material3-android:1.2.1 androidx.compose.material3:material3-android:1.2.1
androidx.compose.material3:material3-window-size-class-android:1.2.1 androidx.compose.material3:material3-window-size-class-android:1.2.1
androidx.compose.material3:material3-window-size-class:1.2.1 androidx.compose.material3:material3-window-size-class:1.2.1
@ -37,30 +39,30 @@ androidx.compose.material:material-icons-extended-android:1.6.3
androidx.compose.material:material-icons-extended:1.6.3 androidx.compose.material:material-icons-extended:1.6.3
androidx.compose.material:material-ripple-android:1.6.3 androidx.compose.material:material-ripple-android:1.6.3
androidx.compose.material:material-ripple:1.6.3 androidx.compose.material:material-ripple:1.6.3
androidx.compose.runtime:runtime-android:1.7.0-alpha06 androidx.compose.runtime:runtime-android:1.7.0-alpha08
androidx.compose.runtime:runtime-saveable-android:1.7.0-alpha06 androidx.compose.runtime:runtime-saveable-android:1.7.0-alpha08
androidx.compose.runtime:runtime-saveable:1.7.0-alpha06 androidx.compose.runtime:runtime-saveable:1.7.0-alpha08
androidx.compose.runtime:runtime-tracing:1.0.0-beta01 androidx.compose.runtime:runtime-tracing:1.0.0-beta01
androidx.compose.runtime:runtime:1.7.0-alpha06 androidx.compose.runtime:runtime:1.7.0-alpha08
androidx.compose.ui:ui-android:1.7.0-alpha06 androidx.compose.ui:ui-android:1.7.0-alpha08
androidx.compose.ui:ui-geometry-android:1.7.0-alpha06 androidx.compose.ui:ui-geometry-android:1.7.0-alpha08
androidx.compose.ui:ui-geometry:1.7.0-alpha06 androidx.compose.ui:ui-geometry:1.7.0-alpha08
androidx.compose.ui:ui-graphics-android:1.7.0-alpha06 androidx.compose.ui:ui-graphics-android:1.7.0-alpha08
androidx.compose.ui:ui-graphics:1.7.0-alpha06 androidx.compose.ui:ui-graphics:1.7.0-alpha08
androidx.compose.ui:ui-text-android:1.7.0-alpha06 androidx.compose.ui:ui-text-android:1.7.0-alpha08
androidx.compose.ui:ui-text:1.7.0-alpha06 androidx.compose.ui:ui-text:1.7.0-alpha08
androidx.compose.ui:ui-tooling-preview-android:1.7.0-alpha06 androidx.compose.ui:ui-tooling-preview-android:1.7.0-alpha08
androidx.compose.ui:ui-tooling-preview:1.7.0-alpha06 androidx.compose.ui:ui-tooling-preview:1.7.0-alpha08
androidx.compose.ui:ui-unit-android:1.7.0-alpha06 androidx.compose.ui:ui-unit-android:1.7.0-alpha08
androidx.compose.ui:ui-unit:1.7.0-alpha06 androidx.compose.ui:ui-unit:1.7.0-alpha08
androidx.compose.ui:ui-util-android:1.7.0-alpha06 androidx.compose.ui:ui-util-android:1.7.0-alpha08
androidx.compose.ui:ui-util:1.7.0-alpha06 androidx.compose.ui:ui-util:1.7.0-alpha08
androidx.compose.ui:ui:1.7.0-alpha06 androidx.compose.ui:ui:1.7.0-alpha08
androidx.compose:compose-bom:2024.02.02 androidx.compose:compose-bom:2024.02.02
androidx.concurrent:concurrent-futures:1.1.0 androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.12.0 androidx.core:core-ktx:1.13.1
androidx.core:core-splashscreen:1.0.1 androidx.core:core-splashscreen:1.0.1
androidx.core:core:1.12.0 androidx.core:core:1.13.1
androidx.cursoradapter:cursoradapter:1.0.0 androidx.cursoradapter:cursoradapter:1.0.0
androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.0.0 androidx.customview:customview:1.0.0
@ -74,32 +76,33 @@ androidx.emoji2:emoji2-views-helper:1.3.0
androidx.emoji2:emoji2:1.3.0 androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.7 androidx.exifinterface:exifinterface:1.3.7
androidx.fragment:fragment:1.5.1 androidx.fragment:fragment:1.5.1
androidx.graphics:graphics-path:1.0.0-beta02 androidx.graphics:graphics-path:1.0.1
androidx.hilt:hilt-common:1.1.0 androidx.hilt:hilt-common:1.1.0
androidx.hilt:hilt-navigation-compose:1.2.0 androidx.hilt:hilt-navigation-compose:1.2.0
androidx.hilt:hilt-navigation:1.2.0 androidx.hilt:hilt-navigation:1.2.0
androidx.hilt:hilt-work:1.1.0 androidx.hilt:hilt-work:1.1.0
androidx.interpolator:interpolator:1.0.0 androidx.interpolator:interpolator:1.0.0
androidx.legacy:legacy-support-core-utils:1.0.0 androidx.legacy:legacy-support-core-utils:1.0.0
androidx.lifecycle:lifecycle-common-java8:2.8.0-alpha04 androidx.lifecycle:lifecycle-common-java8:2.8.0-rc01
androidx.lifecycle:lifecycle-common-jvm:2.8.0-alpha04 androidx.lifecycle:lifecycle-common-jvm:2.8.0-rc01
androidx.lifecycle:lifecycle-common:2.8.0-alpha04 androidx.lifecycle:lifecycle-common:2.8.0-rc01
androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.0-alpha04 androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.0-rc01
androidx.lifecycle:lifecycle-livedata-core:2.8.0-alpha04 androidx.lifecycle:lifecycle-livedata-core:2.8.0-rc01
androidx.lifecycle:lifecycle-livedata:2.8.0-alpha04 androidx.lifecycle:lifecycle-livedata:2.8.0-rc01
androidx.lifecycle:lifecycle-process:2.8.0-alpha04 androidx.lifecycle:lifecycle-process:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime-android:2.8.0-alpha04 androidx.lifecycle:lifecycle-runtime-android:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime-compose:2.8.0-alpha04 androidx.lifecycle:lifecycle-runtime-compose-android:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.0-alpha04 androidx.lifecycle:lifecycle-runtime-compose:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime-ktx:2.8.0-alpha04 androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.0-rc01
androidx.lifecycle:lifecycle-runtime:2.8.0-alpha04 androidx.lifecycle:lifecycle-runtime-ktx:2.8.0-rc01
androidx.lifecycle:lifecycle-service:2.8.0-alpha04 androidx.lifecycle:lifecycle-runtime:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-android:2.8.0-alpha04 androidx.lifecycle:lifecycle-service:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.0-alpha04 androidx.lifecycle:lifecycle-viewmodel-android:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0-alpha04 androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-alpha04 androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.0-alpha04 androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel:2.8.0-alpha04 androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.0-rc01
androidx.lifecycle:lifecycle-viewmodel:2.8.0-rc01
androidx.loader:loader:1.0.0 androidx.loader:loader:1.0.0
androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
androidx.metrics:metrics-performance:1.0.0-alpha04 androidx.metrics:metrics-performance:1.0.0-alpha04
@ -129,9 +132,9 @@ androidx.vectordrawable:vectordrawable:1.1.0
androidx.versionedparcelable:versionedparcelable:1.1.1 androidx.versionedparcelable:versionedparcelable:1.1.1
androidx.viewpager:viewpager:1.0.0 androidx.viewpager:viewpager:1.0.0
androidx.window.extensions.core:core:1.0.0 androidx.window.extensions.core:core:1.0.0
androidx.window:window-core-android:1.3.0-alpha03 androidx.window:window-core-android:1.3.0-beta01
androidx.window:window-core:1.3.0-alpha03 androidx.window:window-core:1.3.0-beta01
androidx.window:window:1.3.0-alpha03 androidx.window:window:1.3.0-beta01
androidx.work:work-runtime-ktx:2.9.0 androidx.work:work-runtime-ktx:2.9.0
androidx.work:work-runtime:2.9.0 androidx.work:work-runtime:2.9.0
com.caverock:androidsvg-aar:1.4 com.caverock:androidsvg-aar:1.4
@ -203,10 +206,10 @@ io.coil-kt:coil-svg:2.6.0
io.coil-kt:coil:2.6.0 io.coil-kt:coil:2.6.0
javax.inject:javax.inject:1 javax.inject:javax.inject:1
org.checkerframework:checker-qual:3.12.0 org.checkerframework:checker-qual:3.12.0
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.22 org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0
org.jetbrains.kotlin:kotlin-stdlib:1.9.22 org.jetbrains.kotlin:kotlin-stdlib:1.9.23
org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0
org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.0 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.0
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0 org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0

@ -20,7 +20,6 @@ import androidx.annotation.StringRes
import androidx.compose.ui.test.assertCountEquals import androidx.compose.ui.test.assertCountEquals
import androidx.compose.ui.test.assertIsOn import androidx.compose.ui.test.assertIsOn
import androidx.compose.ui.test.assertIsSelected import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.hasAnyAncestor
import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.AndroidComposeTestRule
@ -225,12 +224,7 @@ class NavigationTest {
onNodeWithText(ok).performClick() onNodeWithText(ok).performClick()
// Check that the saved screen is still visible and selected. // Check that the saved screen is still visible and selected.
onNode( onNode(hasText(saved) and hasTestTag("NiaNavItem")).assertIsSelected()
hasText(saved) and
hasAnyAncestor(
hasTestTag("NiaBottomBar") or hasTestTag("NiaNavRail"),
),
).assertIsSelected()
} }
} }

@ -1,247 +0,0 @@
/*
* Copyright 2022 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.ui
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.ForcedSize
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import com.google.samples.apps.nowinandroid.core.rules.GrantPostNotificationsPermissionRule
import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.uitesthiltmanifest.HiltComponentActivity
import dagger.hilt.android.testing.BindValue
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import javax.inject.Inject
/**
* Tests that the navigation UI is rendered correctly on different screen sizes.
*/
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@HiltAndroidTest
class NavigationUiTest {
/**
* Manages the components' state and is used to perform injection on your test
*/
@get:Rule(order = 0)
val hiltRule = HiltAndroidRule(this)
/**
* Create a temporary folder used to create a Data Store file. This guarantees that
* the file is removed in between each test, preventing a crash.
*/
@BindValue
@get:Rule(order = 1)
val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build()
/**
* Grant [android.Manifest.permission.POST_NOTIFICATIONS] permission.
*/
@get:Rule(order = 2)
val postNotificationsPermission = GrantPostNotificationsPermissionRule()
/**
* Use a test activity to set the content on.
*/
@get:Rule(order = 3)
val composeTestRule = createAndroidComposeRule<HiltComponentActivity>()
val userNewsResourceRepository = CompositeUserNewsResourceRepository(
newsRepository = TestNewsRepository(),
userDataRepository = TestUserDataRepository(),
)
@Inject
lateinit var networkMonitor: NetworkMonitor
@Inject
lateinit var timeZoneMonitor: TimeZoneMonitor
@Before
fun setup() {
hiltRule.inject()
}
@Test
fun compactWidth_compactHeight_showsNavigationBar() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(400.dp, 400.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaBottomBar").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaNavRail").assertDoesNotExist()
}
@Test
fun mediumWidth_compactHeight_showsNavigationRail() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(610.dp, 400.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaNavRail").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaBottomBar").assertDoesNotExist()
}
@Test
fun expandedWidth_compactHeight_showsNavigationRail() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(900.dp, 400.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaNavRail").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaBottomBar").assertDoesNotExist()
}
@Test
fun compactWidth_mediumHeight_showsNavigationBar() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(400.dp, 500.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaBottomBar").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaNavRail").assertDoesNotExist()
}
@Test
fun mediumWidth_mediumHeight_showsNavigationRail() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(610.dp, 500.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaNavRail").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaBottomBar").assertDoesNotExist()
}
@Test
fun expandedWidth_mediumHeight_showsNavigationRail() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(900.dp, 500.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaNavRail").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaBottomBar").assertDoesNotExist()
}
@Test
fun compactWidth_expandedHeight_showsNavigationBar() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(400.dp, 1000.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaBottomBar").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaNavRail").assertDoesNotExist()
}
@Test
fun mediumWidth_expandedHeight_showsNavigationRail() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(610.dp, 1000.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaNavRail").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaBottomBar").assertDoesNotExist()
}
@Test
fun expandedWidth_expandedHeight_showsNavigationRail() {
composeTestRule.setContent {
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(900.dp, 1000.dp)),
) {
BoxWithConstraints {
NiaApp(fakeAppState(maxWidth, maxHeight))
}
}
}
composeTestRule.onNodeWithTag("NiaNavRail").assertIsDisplayed()
composeTestRule.onNodeWithTag("NiaBottomBar").assertDoesNotExist()
}
@Composable
private fun fakeAppState(maxWidth: Dp, maxHeight: Dp) = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(DpSize(maxWidth, maxHeight)),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
}

@ -16,15 +16,11 @@
package com.google.samples.apps.nowinandroid.ui package com.google.samples.apps.nowinandroid.ui
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.ComposeNavigator import androidx.navigation.compose.ComposeNavigator
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
@ -43,7 +39,6 @@ import kotlinx.datetime.TimeZone
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
/** /**
@ -52,7 +47,6 @@ import kotlin.test.assertTrue
* Note: This could become an unit test if Robolectric is added to the project and the Context * Note: This could become an unit test if Robolectric is added to the project and the Context
* is faked. * is faked.
*/ */
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
class NiaAppStateTest { class NiaAppStateTest {
@get:Rule @get:Rule
@ -79,7 +73,6 @@ class NiaAppStateTest {
NiaAppState( NiaAppState(
navController = navController, navController = navController,
coroutineScope = backgroundScope, coroutineScope = backgroundScope,
windowSizeClass = getCompactWindowClass(),
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
@ -102,7 +95,6 @@ class NiaAppStateTest {
fun niaAppState_destinations() = runTest { fun niaAppState_destinations() = runTest {
composeTestRule.setContent { composeTestRule.setContent {
state = rememberNiaAppState( state = rememberNiaAppState(
windowSizeClass = getCompactWindowClass(),
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
@ -115,64 +107,12 @@ class NiaAppStateTest {
assertTrue(state.topLevelDestinations[2].name.contains("interests", true)) assertTrue(state.topLevelDestinations[2].name.contains("interests", true))
} }
@Test
fun niaAppState_showBottomBar_compact() = runTest {
composeTestRule.setContent {
state = NiaAppState(
navController = NavHostController(LocalContext.current),
coroutineScope = backgroundScope,
windowSizeClass = getCompactWindowClass(),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
}
assertTrue(state.shouldShowBottomBar)
assertFalse(state.shouldShowNavRail)
}
@Test
fun niaAppState_showNavRail_medium() = runTest {
composeTestRule.setContent {
state = NiaAppState(
navController = NavHostController(LocalContext.current),
coroutineScope = backgroundScope,
windowSizeClass = WindowSizeClass.calculateFromSize(DpSize(800.dp, 800.dp)),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
}
assertTrue(state.shouldShowNavRail)
assertFalse(state.shouldShowBottomBar)
}
@Test
fun niaAppState_showNavRail_large() = runTest {
composeTestRule.setContent {
state = NiaAppState(
navController = NavHostController(LocalContext.current),
coroutineScope = backgroundScope,
windowSizeClass = WindowSizeClass.calculateFromSize(DpSize(900.dp, 1200.dp)),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
}
assertTrue(state.shouldShowNavRail)
assertFalse(state.shouldShowBottomBar)
}
@Test @Test
fun niaAppState_whenNetworkMonitorIsOffline_StateIsOffline() = runTest(UnconfinedTestDispatcher()) { fun niaAppState_whenNetworkMonitorIsOffline_StateIsOffline() = runTest(UnconfinedTestDispatcher()) {
composeTestRule.setContent { composeTestRule.setContent {
state = NiaAppState( state = NiaAppState(
navController = NavHostController(LocalContext.current), navController = NavHostController(LocalContext.current),
coroutineScope = backgroundScope, coroutineScope = backgroundScope,
windowSizeClass = WindowSizeClass.calculateFromSize(DpSize(900.dp, 1200.dp)),
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
@ -193,7 +133,6 @@ class NiaAppStateTest {
state = NiaAppState( state = NiaAppState(
navController = NavHostController(LocalContext.current), navController = NavHostController(LocalContext.current),
coroutineScope = backgroundScope, coroutineScope = backgroundScope,
windowSizeClass = getCompactWindowClass(),
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
@ -207,8 +146,6 @@ class NiaAppStateTest {
state.currentTimeZone.value, state.currentTimeZone.value,
) )
} }
private fun getCompactWindowClass() = WindowSizeClass.calculateFromSize(DpSize(500.dp, 300.dp))
} }
@Composable @Composable

@ -23,8 +23,7 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
@ -58,7 +57,6 @@ import javax.inject.Inject
private const val TAG = "MainActivity" private const val TAG = "MainActivity"
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@ -134,7 +132,6 @@ class MainActivity : ComponentActivity() {
} }
val appState = rememberNiaAppState( val appState = rememberNiaAppState(
windowSizeClass = calculateWindowSizeClass(this),
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
@ -151,6 +148,7 @@ class MainActivity : ComponentActivity() {
androidTheme = shouldUseAndroidTheme(uiState), androidTheme = shouldUseAndroidTheme(uiState),
disableDynamicTheming = shouldDisableDynamicTheming(uiState), disableDynamicTheming = shouldDisableDynamicTheming(uiState),
) { ) {
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
NiaApp(appState) NiaApp(appState)
} }
} }

@ -18,7 +18,6 @@ package com.google.samples.apps.nowinandroid.ui
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
@ -26,7 +25,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -39,6 +37,9 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult.ActionPerformed import androidx.compose.material3.SnackbarResult.ActionPerformed
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -63,10 +64,7 @@ import androidx.navigation.NavDestination.Companion.hierarchy
import com.google.samples.apps.nowinandroid.R import com.google.samples.apps.nowinandroid.R
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaBackground import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaBackground
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaGradientBackground import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaGradientBackground
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationBar import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationSuiteScaffold
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationBarItem
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationRail
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaNavigationRailItem
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAppBar import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAppBar
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
@ -76,8 +74,13 @@ import com.google.samples.apps.nowinandroid.navigation.NiaNavHost
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import com.google.samples.apps.nowinandroid.feature.settings.R as settingsR import com.google.samples.apps.nowinandroid.feature.settings.R as settingsR
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable @Composable
fun NiaApp(appState: NiaAppState, modifier: Modifier = Modifier) { fun NiaApp(
appState: NiaAppState,
modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
) {
val shouldShowGradientBackground = val shouldShowGradientBackground =
appState.currentTopLevelDestination == TopLevelDestination.FOR_YOU appState.currentTopLevelDestination == TopLevelDestination.FOR_YOU
var showSettingsDialog by rememberSaveable { mutableStateOf(false) } var showSettingsDialog by rememberSaveable { mutableStateOf(false) }
@ -111,13 +114,18 @@ fun NiaApp(appState: NiaAppState, modifier: Modifier = Modifier) {
showSettingsDialog = showSettingsDialog, showSettingsDialog = showSettingsDialog,
onSettingsDismissed = { showSettingsDialog = false }, onSettingsDismissed = { showSettingsDialog = false },
onTopAppBarActionClick = { showSettingsDialog = true }, onTopAppBarActionClick = { showSettingsDialog = true },
windowAdaptiveInfo = windowAdaptiveInfo,
) )
} }
} }
} }
@Composable @Composable
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @OptIn(
ExperimentalMaterial3Api::class,
ExperimentalComposeUiApi::class,
ExperimentalMaterial3AdaptiveApi::class,
)
internal fun NiaApp( internal fun NiaApp(
appState: NiaAppState, appState: NiaAppState,
snackbarHostState: SnackbarHostState, snackbarHostState: SnackbarHostState,
@ -125,59 +133,69 @@ internal fun NiaApp(
onSettingsDismissed: () -> Unit, onSettingsDismissed: () -> Unit,
onTopAppBarActionClick: () -> Unit, onTopAppBarActionClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
) { ) {
val unreadDestinations by appState.topLevelDestinationsWithUnreadResources val unreadDestinations by appState.topLevelDestinationsWithUnreadResources
.collectAsStateWithLifecycle() .collectAsStateWithLifecycle()
val currentDestination = appState.currentDestination
if (showSettingsDialog) { if (showSettingsDialog) {
SettingsDialog( SettingsDialog(
onDismiss = { onSettingsDismissed() }, onDismiss = { onSettingsDismissed() },
) )
} }
Scaffold(
modifier = modifier.semantics { NiaNavigationSuiteScaffold(
testTagsAsResourceId = true navigationSuiteItems = {
}, appState.topLevelDestinations.forEach { destination ->
containerColor = Color.Transparent, val hasUnread = unreadDestinations.contains(destination)
contentColor = MaterialTheme.colorScheme.onBackground, val selected = currentDestination
contentWindowInsets = WindowInsets(0, 0, 0, 0), .isTopLevelDestinationInHierarchy(destination)
snackbarHost = { SnackbarHost(snackbarHostState) }, item(
bottomBar = { selected = selected,
if (appState.shouldShowBottomBar) { onClick = { appState.navigateToTopLevelDestination(destination) },
NiaBottomBar( icon = {
destinations = appState.topLevelDestinations, Icon(
destinationsWithUnreadResources = unreadDestinations, imageVector = destination.unselectedIcon,
onNavigateToDestination = appState::navigateToTopLevelDestination, contentDescription = null,
currentDestination = appState.currentDestination, )
modifier = Modifier.testTag("NiaBottomBar"), },
selectedIcon = {
Icon(
imageVector = destination.selectedIcon,
contentDescription = null,
)
},
label = { Text(stringResource(destination.iconTextId)) },
modifier =
Modifier
.testTag("NiaNavItem")
.then(if (hasUnread) Modifier.notificationDot() else Modifier),
) )
} }
}, },
) { padding -> windowAdaptiveInfo = windowAdaptiveInfo,
Row( ) {
Modifier Scaffold(
.fillMaxSize() modifier = modifier.semantics {
.padding(padding) testTagsAsResourceId = true
.consumeWindowInsets(padding) },
.windowInsetsPadding( containerColor = Color.Transparent,
WindowInsets.safeDrawing.only( contentColor = MaterialTheme.colorScheme.onBackground,
WindowInsetsSides.Horizontal, contentWindowInsets = WindowInsets(0, 0, 0, 0),
snackbarHost = { SnackbarHost(snackbarHostState) },
) { padding ->
Column(
Modifier
.fillMaxSize()
.padding(padding)
.consumeWindowInsets(padding)
.windowInsetsPadding(
WindowInsets.safeDrawing.only(
WindowInsetsSides.Horizontal,
),
), ),
), ) {
) {
if (appState.shouldShowNavRail) {
NiaNavRail(
destinations = appState.topLevelDestinations,
destinationsWithUnreadResources = unreadDestinations,
onNavigateToDestination = appState::navigateToTopLevelDestination,
currentDestination = appState.currentDestination,
modifier = Modifier
.testTag("NiaNavRail")
.safeDrawingPadding(),
)
}
Column(Modifier.fillMaxSize()) {
// Show the top app bar on top level destinations. // Show the top app bar on top level destinations.
val destination = appState.currentTopLevelDestination val destination = appState.currentTopLevelDestination
val shouldShowTopAppBar = destination != null val shouldShowTopAppBar = destination != null
@ -220,80 +238,10 @@ internal fun NiaApp(
}, },
) )
} }
}
// TODO: We may want to add padding or spacer when the snackbar is shown so that
// content doesn't display behind it.
}
}
}
@Composable
private fun NiaNavRail(
destinations: List<TopLevelDestination>,
destinationsWithUnreadResources: Set<TopLevelDestination>,
onNavigateToDestination: (TopLevelDestination) -> Unit,
currentDestination: NavDestination?,
modifier: Modifier = Modifier,
) {
NiaNavigationRail(modifier = modifier) {
destinations.forEach { destination ->
val selected = currentDestination.isTopLevelDestinationInHierarchy(destination)
val hasUnread = destinationsWithUnreadResources.contains(destination)
NiaNavigationRailItem(
selected = selected,
onClick = { onNavigateToDestination(destination) },
icon = {
Icon(
imageVector = destination.unselectedIcon,
contentDescription = null,
)
},
selectedIcon = {
Icon(
imageVector = destination.selectedIcon,
contentDescription = null,
)
},
label = { Text(stringResource(destination.iconTextId)) },
modifier = if (hasUnread) Modifier.notificationDot() else Modifier,
)
}
}
}
@Composable // TODO: We may want to add padding or spacer when the snackbar is shown so that
private fun NiaBottomBar( // content doesn't display behind it.
destinations: List<TopLevelDestination>, }
destinationsWithUnreadResources: Set<TopLevelDestination>,
onNavigateToDestination: (TopLevelDestination) -> Unit,
currentDestination: NavDestination?,
modifier: Modifier = Modifier,
) {
NiaNavigationBar(
modifier = modifier,
) {
destinations.forEach { destination ->
val hasUnread = destinationsWithUnreadResources.contains(destination)
val selected = currentDestination.isTopLevelDestinationInHierarchy(destination)
NiaNavigationBarItem(
selected = selected,
onClick = { onNavigateToDestination(destination) },
icon = {
Icon(
imageVector = destination.unselectedIcon,
contentDescription = null,
)
},
selectedIcon = {
Icon(
imageVector = destination.selectedIcon,
contentDescription = null,
)
},
label = { Text(stringResource(destination.iconTextId)) },
modifier = if (hasUnread) Modifier.notificationDot() else Modifier,
)
} }
} }
} }

@ -16,8 +16,6 @@
package com.google.samples.apps.nowinandroid.ui package com.google.samples.apps.nowinandroid.ui
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -55,7 +53,6 @@ import kotlinx.datetime.TimeZone
@Composable @Composable
fun rememberNiaAppState( fun rememberNiaAppState(
windowSizeClass: WindowSizeClass,
networkMonitor: NetworkMonitor, networkMonitor: NetworkMonitor,
userNewsResourceRepository: UserNewsResourceRepository, userNewsResourceRepository: UserNewsResourceRepository,
timeZoneMonitor: TimeZoneMonitor, timeZoneMonitor: TimeZoneMonitor,
@ -66,7 +63,6 @@ fun rememberNiaAppState(
return remember( return remember(
navController, navController,
coroutineScope, coroutineScope,
windowSizeClass,
networkMonitor, networkMonitor,
userNewsResourceRepository, userNewsResourceRepository,
timeZoneMonitor, timeZoneMonitor,
@ -74,7 +70,6 @@ fun rememberNiaAppState(
NiaAppState( NiaAppState(
navController = navController, navController = navController,
coroutineScope = coroutineScope, coroutineScope = coroutineScope,
windowSizeClass = windowSizeClass,
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
@ -86,7 +81,6 @@ fun rememberNiaAppState(
class NiaAppState( class NiaAppState(
val navController: NavHostController, val navController: NavHostController,
coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
val windowSizeClass: WindowSizeClass,
networkMonitor: NetworkMonitor, networkMonitor: NetworkMonitor,
userNewsResourceRepository: UserNewsResourceRepository, userNewsResourceRepository: UserNewsResourceRepository,
timeZoneMonitor: TimeZoneMonitor, timeZoneMonitor: TimeZoneMonitor,
@ -103,12 +97,6 @@ class NiaAppState(
else -> null else -> null
} }
val shouldShowBottomBar: Boolean
get() = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact
val shouldShowNavRail: Boolean
get() = !shouldShowBottomBar
val isOffline = networkMonitor.isOnline val isOffline = networkMonitor.isOnline
.map(Boolean::not) .map(Boolean::not)
.stateIn( .stateIn(

@ -16,8 +16,9 @@
package com.google.samples.apps.nowinandroid.ui package com.google.samples.apps.nowinandroid.ui
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.material3.adaptive.Posture
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.DeviceConfigurationOverride
@ -27,6 +28,7 @@ import androidx.compose.ui.test.onRoot
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.window.core.layout.WindowSizeClass
import com.github.takahirom.roborazzi.captureRoboImage import com.github.takahirom.roborazzi.captureRoboImage
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
@ -57,7 +59,6 @@ import javax.inject.Inject
/** /**
* Tests that the navigation UI is rendered correctly on different screen sizes. * Tests that the navigation UI is rendered correctly on different screen sizes.
*/ */
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE) @GraphicsMode(GraphicsMode.Mode.NATIVE)
// Configure Robolectric to use a very large screen size that can fit all of the test sizes. // Configure Robolectric to use a very large screen size that can fit all of the test sizes.
@ -122,6 +123,7 @@ class NiaAppScreenSizesScreenshotTests {
TimeZone.setDefault(TimeZone.getTimeZone("UTC")) TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
} }
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
private fun testNiaAppScreenshotWithSize(width: Dp, height: Dp, screenshotName: String) { private fun testNiaAppScreenshotWithSize(width: Dp, height: Dp, screenshotName: String) {
composeTestRule.setContent { composeTestRule.setContent {
CompositionLocalProvider( CompositionLocalProvider(
@ -132,14 +134,20 @@ class NiaAppScreenSizesScreenshotTests {
) { ) {
NiaTheme { NiaTheme {
val fakeAppState = rememberNiaAppState( val fakeAppState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(width, height),
),
networkMonitor = networkMonitor, networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository, userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
) )
NiaApp(fakeAppState) NiaApp(
fakeAppState,
windowAdaptiveInfo = WindowAdaptiveInfo(
windowSizeClass = WindowSizeClass.compute(
width.value,
height.value,
),
windowPosture = Posture(),
),
)
} }
} }
} }
@ -162,20 +170,20 @@ class NiaAppScreenSizesScreenshotTests {
} }
@Test @Test
fun mediumWidth_compactHeight_showsNavigationRail() { fun mediumWidth_compactHeight_showsNavigationBar() {
testNiaAppScreenshotWithSize( testNiaAppScreenshotWithSize(
610.dp, 610.dp,
400.dp, 400.dp,
"mediumWidth_compactHeight_showsNavigationRail", "mediumWidth_compactHeight_showsNavigationBar",
) )
} }
@Test @Test
fun expandedWidth_compactHeight_showsNavigationRail() { fun expandedWidth_compactHeight_showsNavigationBar() {
testNiaAppScreenshotWithSize( testNiaAppScreenshotWithSize(
900.dp, 900.dp,
400.dp, 400.dp,
"expandedWidth_compactHeight_showsNavigationRail", "expandedWidth_compactHeight_showsNavigationBar",
) )
} }

@ -19,8 +19,9 @@ package com.google.samples.apps.nowinandroid.ui
import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.material3.SnackbarDuration.Indefinite import androidx.compose.material3.SnackbarDuration.Indefinite
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.material3.adaptive.Posture
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.LocalInspectionMode
@ -31,6 +32,7 @@ import androidx.compose.ui.test.onRoot
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.window.core.layout.WindowSizeClass
import com.github.takahirom.roborazzi.captureRoboImage import com.github.takahirom.roborazzi.captureRoboImage
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository
@ -63,7 +65,6 @@ import javax.inject.Inject
/** /**
* Tests that the Snackbar is correctly displayed on different screen sizes. * Tests that the Snackbar is correctly displayed on different screen sizes.
*/ */
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@RunWith(RobolectricTestRunner::class) @RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE) @GraphicsMode(GraphicsMode.Mode.NATIVE)
// Configure Robolectric to use a very large screen size that can fit all of the test sizes. // Configure Robolectric to use a very large screen size that can fit all of the test sizes.
@ -191,6 +192,7 @@ class SnackbarScreenshotTests {
} }
} }
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
private fun testSnackbarScreenshotWithSize( private fun testSnackbarScreenshotWithSize(
snackbarHostState: SnackbarHostState, snackbarHostState: SnackbarHostState,
width: Dp, width: Dp,
@ -210,16 +212,26 @@ class SnackbarScreenshotTests {
DeviceConfigurationOverride.ForcedSize(DpSize(width, height)), DeviceConfigurationOverride.ForcedSize(DpSize(width, height)),
) { ) {
BoxWithConstraints { BoxWithConstraints {
val appState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight),
),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
NiaTheme { NiaTheme {
NiaApp(appState, snackbarHostState, false, {}, {}) val appState = rememberNiaAppState(
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
NiaApp(
appState = appState,
snackbarHostState = snackbarHostState,
showSettingsDialog = false,
onSettingsDismissed = {},
onTopAppBarActionClick = {},
windowAdaptiveInfo = WindowAdaptiveInfo(
windowSizeClass = WindowSizeClass.compute(
maxWidth.value,
maxHeight.value,
),
windowPosture = Posture(),
),
)
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

@ -50,13 +50,3 @@ plugins {
alias(libs.plugins.room) 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.module.graph) apply true // Plugin applied to allow module graph generation
} }
// Task to print all the module paths in the project e.g. :core:data
// Used by module graph generator script
tasks.register("printModulePaths") {
subprojects {
if (subprojects.size == 0) {
println(this.path)
}
}
}

@ -34,6 +34,8 @@ dependencies {
api(libs.androidx.compose.foundation.layout) api(libs.androidx.compose.foundation.layout)
api(libs.androidx.compose.material.iconsExtended) api(libs.androidx.compose.material.iconsExtended)
api(libs.androidx.compose.material3) api(libs.androidx.compose.material3)
api(libs.androidx.compose.material3.adaptive)
api(libs.androidx.compose.material3.navigationSuite)
api(libs.androidx.compose.runtime) api(libs.androidx.compose.runtime)
api(libs.androidx.compose.ui.util) api(libs.androidx.compose.ui.util)

@ -23,10 +23,20 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.NavigationDrawerItemDefaults
import androidx.compose.material3.NavigationRail import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.NavigationRailItemDefaults import androidx.compose.material3.NavigationRailItemDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.adaptive.navigationsuite.ExperimentalMaterial3AdaptiveNavigationSuiteApi
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteDefaults
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteItemColors
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScope
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -165,6 +175,101 @@ fun NiaNavigationRail(
) )
} }
/**
* Now in Android navigation suite scaffold with item and content slots.
* Wraps Material 3 [NavigationSuiteScaffold].
*
* @param modifier Modifier to be applied to the navigation suite scaffold.
* @param navigationSuiteItems A slot to display multiple items via [NiaNavigationSuiteScope].
* @param windowAdaptiveInfo The window adaptive info.
* @param content The app content inside the scaffold.
*/
@OptIn(
ExperimentalMaterial3AdaptiveNavigationSuiteApi::class,
ExperimentalMaterial3AdaptiveApi::class,
)
@Composable
fun NiaNavigationSuiteScaffold(
navigationSuiteItems: NiaNavigationSuiteScope.() -> Unit,
modifier: Modifier = Modifier,
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
content: @Composable () -> Unit,
) {
val layoutType = NavigationSuiteScaffoldDefaults
.calculateFromAdaptiveInfo(windowAdaptiveInfo)
val navigationSuiteItemColors = NavigationSuiteItemColors(
navigationBarItemColors = NavigationBarItemDefaults.colors(
selectedIconColor = NiaNavigationDefaults.navigationSelectedItemColor(),
unselectedIconColor = NiaNavigationDefaults.navigationContentColor(),
selectedTextColor = NiaNavigationDefaults.navigationSelectedItemColor(),
unselectedTextColor = NiaNavigationDefaults.navigationContentColor(),
indicatorColor = NiaNavigationDefaults.navigationIndicatorColor(),
),
navigationRailItemColors = NavigationRailItemDefaults.colors(
selectedIconColor = NiaNavigationDefaults.navigationSelectedItemColor(),
unselectedIconColor = NiaNavigationDefaults.navigationContentColor(),
selectedTextColor = NiaNavigationDefaults.navigationSelectedItemColor(),
unselectedTextColor = NiaNavigationDefaults.navigationContentColor(),
indicatorColor = NiaNavigationDefaults.navigationIndicatorColor(),
),
navigationDrawerItemColors = NavigationDrawerItemDefaults.colors(
selectedIconColor = NiaNavigationDefaults.navigationSelectedItemColor(),
unselectedIconColor = NiaNavigationDefaults.navigationContentColor(),
selectedTextColor = NiaNavigationDefaults.navigationSelectedItemColor(),
unselectedTextColor = NiaNavigationDefaults.navigationContentColor(),
),
)
NavigationSuiteScaffold(
navigationSuiteItems = {
NiaNavigationSuiteScope(
navigationSuiteScope = this,
navigationSuiteItemColors = navigationSuiteItemColors,
).run(navigationSuiteItems)
},
layoutType = layoutType,
containerColor = Color.Transparent,
navigationSuiteColors = NavigationSuiteDefaults.colors(
navigationBarContentColor = NiaNavigationDefaults.navigationContentColor(),
navigationRailContainerColor = Color.Transparent,
),
modifier = modifier,
) {
content()
}
}
/**
* A wrapper around [NavigationSuiteScope] to declare navigation items.
*/
@OptIn(ExperimentalMaterial3AdaptiveNavigationSuiteApi::class)
class NiaNavigationSuiteScope internal constructor(
private val navigationSuiteScope: NavigationSuiteScope,
private val navigationSuiteItemColors: NavigationSuiteItemColors,
) {
fun item(
selected: Boolean,
onClick: () -> Unit,
modifier: Modifier = Modifier,
icon: @Composable () -> Unit,
selectedIcon: @Composable () -> Unit = icon,
label: @Composable (() -> Unit)? = null,
) = navigationSuiteScope.item(
selected = selected,
onClick = onClick,
icon = {
if (selected) {
selectedIcon()
} else {
icon()
}
},
label = label,
colors = navigationSuiteItemColors,
modifier = modifier,
)
}
@ThemePreviews @ThemePreviews
@Composable @Composable
fun NiaNavigationBarPreview() { fun NiaNavigationBarPreview() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

@ -31,6 +31,19 @@ then
exit 1 exit 1
fi 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 # Initialize an array to store excluded modules
excluded_modules=() excluded_modules=()
@ -50,7 +63,7 @@ while [[ $# -gt 0 ]]; do
done done
# Get the module paths # Get the module paths
module_paths=$(./gradlew -q printModulePaths --no-configuration-cache) module_paths=$(${GREP_COMMAND} -oP 'include\("\K[^"]+' settings.gradle.kts)
# Ensure the output directory exists # Ensure the output directory exists
mkdir -p docs/images/graphs/ mkdir -p docs/images/graphs/

@ -7,10 +7,11 @@ androidTools = "31.4.0"
androidxActivity = "1.8.2" androidxActivity = "1.8.2"
androidxAppCompat = "1.6.1" androidxAppCompat = "1.6.1"
androidxBrowser = "1.8.0" androidxBrowser = "1.8.0"
androidxComposeAlpha = "1.7.0-alpha08"
androidxComposeBom = "2024.02.02" androidxComposeBom = "2024.02.02"
androidxComposeCompiler = "1.5.8" androidxComposeCompiler = "1.5.12"
androidxComposeUiTest = "1.7.0-alpha06" androidxComposeMaterial3Adaptive = "1.0.0-alpha12"
androidxComposeMaterial3Adaptive = "1.0.0-alpha10" androidxComposeMaterial3AdaptiveNavigationSuite = "1.0.0-alpha07"
androidxComposeRuntimeTracing = "1.0.0-beta01" androidxComposeRuntimeTracing = "1.0.0-beta01"
androidxCore = "1.12.0" androidxCore = "1.12.0"
androidxCoreSplashscreen = "1.0.1" androidxCoreSplashscreen = "1.0.1"
@ -44,11 +45,11 @@ hilt = "2.51"
hiltExt = "1.1.0" hiltExt = "1.1.0"
jacoco = "0.8.7" jacoco = "0.8.7"
junit4 = "4.13.2" junit4 = "4.13.2"
kotlin = "1.9.22" kotlin = "1.9.23"
kotlinxCoroutines = "1.8.0" kotlinxCoroutines = "1.8.0"
kotlinxDatetime = "0.5.0" kotlinxDatetime = "0.5.0"
kotlinxSerializationJson = "1.6.3" kotlinxSerializationJson = "1.6.3"
ksp = "1.9.22-1.0.18" ksp = "1.9.23-1.0.20"
moduleGraph = "2.5.0" moduleGraph = "2.5.0"
okhttp = "4.12.0" okhttp = "4.12.0"
protobuf = "4.26.0" protobuf = "4.26.0"
@ -70,17 +71,18 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" } androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" }
androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" } androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" }
androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "androidxComposeAlpha" }
androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" } androidx-compose-foundation-layout = { group = "androidx.compose.foundation", name = "foundation-layout" }
androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" } androidx-compose-material-iconsExtended = { group = "androidx.compose.material", name = "material-icons-extended" }
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-compose-material3-navigationSuite = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite", version.ref = "androidxComposeMaterial3AdaptiveNavigationSuite" }
androidx-compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive", version.ref = "androidxComposeMaterial3Adaptive" } androidx-compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive", version.ref = "androidxComposeMaterial3Adaptive" }
androidx-compose-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout", version.ref = "androidxComposeMaterial3Adaptive" } androidx-compose-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout", version.ref = "androidxComposeMaterial3Adaptive" }
androidx-compose-material3-adaptive-navigation = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation", version.ref = "androidxComposeMaterial3Adaptive" } androidx-compose-material3-adaptive-navigation = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation", version.ref = "androidxComposeMaterial3Adaptive" }
androidx-compose-material3-windowSizeClass = { group = "androidx.compose.material3", name = "material3-window-size-class" } androidx-compose-material3-windowSizeClass = { group = "androidx.compose.material3", name = "material3-window-size-class" }
androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" }
androidx-compose-runtime-tracing = { group = "androidx.compose.runtime", name = "runtime-tracing", version.ref = "androidxComposeRuntimeTracing" } androidx-compose-runtime-tracing = { group = "androidx.compose.runtime", name = "runtime-tracing", version.ref = "androidxComposeRuntimeTracing" }
androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "androidxComposeUiTest" } androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "androidxComposeAlpha" }
androidx-compose-ui-testManifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-compose-ui-testManifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }

Loading…
Cancel
Save