From d7dcc504fba3a4fd922fdb0022abca7ab23c961e Mon Sep 17 00:00:00 2001 From: Chris Banes Date: Sat, 22 Aug 2020 10:21:06 +0100 Subject: [PATCH] Update to Compose SNAPSHOT 6765009 Also upgraded to: - Kotlin 1.4 - Coil v1.0.0-rc1 - New insets impl from goo.gle/compose-insets - AndroidX Core 1.5.0-alpha02 --- app/build.gradle | 2 +- .../main/java/app/tivi/home/MainActivity.kt | 1 - build.gradle | 6 +- .../java/app/tivi/buildsrc/dependencies.kt | 23 +- .../java/app/tivi/util/EntryGridFragment.kt | 1 - .../common/imageloading/CoilAppInitializer.kt | 19 +- ...per.kt => EpisodeEntityCoilInterceptor.kt} | 25 +- .../ImageLoadingBindingAdapters.kt | 2 +- .../imageloading/ImageLoadingExtensions.kt | 7 +- .../imageloading/SaturatingTransformation.kt | 8 +- ...r.kt => TmdbImageEntityCoilInterceptor.kt} | 24 +- .../TrimTransparentEdgesTransformation.kt | 2 +- common-ui-compose/build.gradle | 4 +- .../java/app/tivi/common/compose/insets.kt | 512 ++++++++++++------ common-ui-resources/build.gradle | 2 +- common-ui-view/build.gradle | 2 +- .../app/tivi/ui/StatusBarHeightBehavior.kt | 39 -- gradle/wrapper/gradle-wrapper.properties | 2 +- ui-account/build.gradle | 6 +- .../main/java/app/tivi/account/AccountUi.kt | 4 +- ui-discover/build.gradle | 2 +- .../tivi/home/discover/DiscoverFragment.kt | 1 - ui-episodedetails/build.gradle | 6 +- .../app/tivi/episodedetails/EpisodeDetails.kt | 12 +- ui-followed/build.gradle | 2 +- .../tivi/home/followed/FollowedFragment.kt | 1 - ui-popular/build.gradle | 2 +- ui-recommended/build.gradle | 2 +- ui-search/build.gradle | 2 +- .../app/tivi/home/search/SearchFragment.kt | 1 - ui-settings/build.gradle | 2 +- ui-showdetails/build.gradle | 6 +- .../tivi/showdetails/details/ShowDetails.kt | 34 +- .../details/ShowDetailsFragment.kt | 1 - ui-trending/build.gradle | 2 +- ui-watched/build.gradle | 2 +- .../app/tivi/home/watched/WatchedFragment.kt | 1 - 37 files changed, 465 insertions(+), 305 deletions(-) rename common-imageloading/src/main/java/app/tivi/common/imageloading/{EpisodeCoilMapper.kt => EpisodeEntityCoilInterceptor.kt} (60%) rename common-imageloading/src/main/java/app/tivi/common/imageloading/{TmdbImageEntityCoilMapper.kt => TmdbImageEntityCoilInterceptor.kt} (73%) delete mode 100644 common-ui-view/src/main/java/app/tivi/ui/StatusBarHeightBehavior.kt diff --git a/app/build.gradle b/app/build.gradle index e494923f14..454e7eda68 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -199,7 +199,7 @@ dependencies { implementation Libs.AndroidX.Navigation.fragment implementation Libs.AndroidX.Navigation.ui - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Insetter.ktx diff --git a/app/src/main/java/app/tivi/home/MainActivity.kt b/app/src/main/java/app/tivi/home/MainActivity.kt index 59016a4e11..e6c42ec4db 100644 --- a/app/src/main/java/app/tivi/home/MainActivity.kt +++ b/app/src/main/java/app/tivi/home/MainActivity.kt @@ -19,7 +19,6 @@ package app.tivi.home import android.content.Intent import android.os.Bundle import androidx.activity.viewModels -import androidx.lifecycle.observe import androidx.navigation.NavController import app.tivi.AppNavigator import app.tivi.R diff --git a/build.gradle b/build.gradle index 660968e44b..646de90df0 100644 --- a/build.gradle +++ b/build.gradle @@ -20,9 +20,9 @@ import app.tivi.buildsrc.Versions buildscript { ext.buildConfig = [ - 'compileSdk': 29, + 'compileSdk': 30, 'minSdk' : 23, - 'targetSdk' : 29, + 'targetSdk' : 30, ] repositories { @@ -114,6 +114,8 @@ subprojects { freeCompilerArgs += "-Xallow-jvm-ir-dependencies" + freeCompilerArgs += "-Xjvm-default=all" + // Set JVM target to 1.8 jvmTarget = "1.8" } diff --git a/buildSrc/src/main/java/app/tivi/buildsrc/dependencies.kt b/buildSrc/src/main/java/app/tivi/buildsrc/dependencies.kt index f6d43bb244..ee575d9950 100644 --- a/buildSrc/src/main/java/app/tivi/buildsrc/dependencies.kt +++ b/buildSrc/src/main/java/app/tivi/buildsrc/dependencies.kt @@ -44,8 +44,7 @@ object Libs { const val leakCanary = "com.squareup.leakcanary:leakcanary-android:2.4" - // Move back to Store when alpha07 is out - const val store = "com.dropbox.mobile.store:store4:4.0.0-SNAPSHOT" + const val store = "com.dropbox.mobile.store:store4:4.0.0-alpha07" object Insetter { private const val version = "0.3.1" @@ -54,13 +53,17 @@ object Libs { } object Accompanist { - private const val version = "0.1.8.ui-${AndroidX.Compose.snapshot}-SNAPSHOT" + private const val version = "0.1.10.ui-${AndroidX.Compose.snapshot}-SNAPSHOT" const val mdcTheme = "dev.chrisbanes.accompanist:accompanist-mdc-theme:$version" const val coil = "dev.chrisbanes.accompanist:accompanist-coil:$version" } - object Google { + object Mdc { const val material = "com.google.android.material:material:1.1.0" + const val composeThemeAdapter = "com.google.android.material:compose-theme-adapter:0.1.0-dev17" + } + + object Google { const val firebaseCore = "com.google.firebase:firebase-core:17.4.3" const val crashlytics = "com.google.firebase:firebase-crashlytics:17.0.1" @@ -73,14 +76,14 @@ object Libs { } object Kotlin { - private const val version = "1.4.0-rc" + private const val version = "1.4.0" const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version" const val gradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$version" const val extensions = "org.jetbrains.kotlin:kotlin-android-extensions:$version" } object Coroutines { - private const val version = "1.3.8-1.4.0-rc" + private const val version = "1.3.9" const val core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version" const val android = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version" const val test = "org.jetbrains.kotlinx:kotlinx-coroutines-test:$version" @@ -133,7 +136,7 @@ object Libs { const val constraintlayout = "androidx.constraintlayout:constraintlayout:2.0.0-rc1" - const val coreKtx = "androidx.core:core-ktx:1.3.1" + const val coreKtx = "androidx.core:core-ktx:1.5.0-alpha02" object Lifecycle { private const val version = "2.3.0-alpha06" @@ -157,8 +160,8 @@ object Libs { } object Compose { - const val snapshot = "6752477" - const val version = "0.1.0-SNAPSHOT" + const val snapshot = "6765009" + const val version = "1.0.0-SNAPSHOT" @get:JvmStatic val snapshotUrl: String @@ -223,7 +226,7 @@ object Libs { } object Coil { - private const val version = "0.11.0" + private const val version = "1.0.0-rc1" const val coil = "io.coil-kt:coil:$version" } diff --git a/common-entrygrid/src/main/java/app/tivi/util/EntryGridFragment.kt b/common-entrygrid/src/main/java/app/tivi/util/EntryGridFragment.kt index a7f5aa0317..e2e5f868a7 100644 --- a/common-entrygrid/src/main/java/app/tivi/util/EntryGridFragment.kt +++ b/common-entrygrid/src/main/java/app/tivi/util/EntryGridFragment.kt @@ -23,7 +23,6 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.updatePadding import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.observe import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DefaultItemAnimator import app.tivi.FragmentWithBinding diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/CoilAppInitializer.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/CoilAppInitializer.kt index 2490929320..92a7ef3d60 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/CoilAppInitializer.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/CoilAppInitializer.kt @@ -21,15 +21,16 @@ import android.content.Context import app.tivi.appinitializers.AppInitializer import coil.Coil import coil.ImageLoader -import coil.ImageLoaderFactory +import coil.annotation.ExperimentalCoilApi import coil.util.CoilUtils import dagger.hilt.android.qualifiers.ApplicationContext import okhttp3.OkHttpClient import javax.inject.Inject -class CoilAppInitializer @Inject constructor( - private val tmdbImageEntityMapper: TmdbImageEntityCoilMapper, - private val episodeEntityMapper: EpisodeCoilMapper, +class CoilAppInitializer @OptIn(ExperimentalCoilApi::class) +@Inject constructor( + private val tmdbImageEntityInterceptor: TmdbImageEntityCoilInterceptor, + private val episodeEntityInterceptor: EpisodeEntityCoilInterceptor, private val okHttpClient: OkHttpClient, @ApplicationContext private val context: Context ) : AppInitializer { @@ -37,19 +38,19 @@ class CoilAppInitializer @Inject constructor( val coilOkHttpClient = okHttpClient.newBuilder() .cache(CoilUtils.createDefaultCache(context)) .build() - Coil.setImageLoader(object : ImageLoaderFactory { - override fun newImageLoader(): ImageLoader = ImageLoader.Builder(application) + Coil.setImageLoader { + ImageLoader.Builder(application) // Hardware bitmaps break with our transitions, disable them for now .allowHardware(false) // Since we don't use hardware bitmaps, we can pool bitmaps and use a higher // ratio of memory .bitmapPoolPercentage(0.5) .componentRegistry { - add(tmdbImageEntityMapper) - add(episodeEntityMapper) + add(tmdbImageEntityInterceptor) + add(episodeEntityInterceptor) } .okHttpClient(coilOkHttpClient) .build() - }) + } } } diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/EpisodeCoilMapper.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/EpisodeEntityCoilInterceptor.kt similarity index 60% rename from common-imageloading/src/main/java/app/tivi/common/imageloading/EpisodeCoilMapper.kt rename to common-imageloading/src/main/java/app/tivi/common/imageloading/EpisodeEntityCoilInterceptor.kt index ccfe22319e..19bf396949 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/EpisodeCoilMapper.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/EpisodeEntityCoilInterceptor.kt @@ -18,7 +18,9 @@ package app.tivi.common.imageloading import app.tivi.data.entities.Episode import app.tivi.tmdb.TmdbImageUrlProvider -import coil.map.MeasuredMapper +import coil.annotation.ExperimentalCoilApi +import coil.intercept.Interceptor +import coil.request.ImageResult import coil.size.PixelSize import coil.size.Size import okhttp3.HttpUrl @@ -26,13 +28,26 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import javax.inject.Inject import javax.inject.Provider -class EpisodeCoilMapper @Inject constructor( +@ExperimentalCoilApi +class EpisodeEntityCoilInterceptor @Inject constructor( private val tmdbImageUrlProvider: Provider -) : MeasuredMapper { +) : Interceptor { + override suspend fun intercept(chain: Interceptor.Chain): ImageResult { + val data = chain.request.data + val request = when { + data is Episode && handles(data) -> { + chain.request.newBuilder() + .data(map(data, chain.size)) + .build() + } + else -> chain.request + } + return chain.proceed(request) + } - override fun handles(data: Episode): Boolean = data.tmdbBackdropPath != null + private fun handles(data: Episode): Boolean = data.tmdbBackdropPath != null - override fun map(data: Episode, size: Size): HttpUrl { + private fun map(data: Episode, size: Size): HttpUrl { val width = if (size is PixelSize) size.width else 0 val urlProvider = tmdbImageUrlProvider.get() return urlProvider.getBackdropUrl(data.tmdbBackdropPath!!, width).toHttpUrl() diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingBindingAdapters.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingBindingAdapters.kt index 579a84287b..40f8f9e109 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingBindingAdapters.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingBindingAdapters.kt @@ -22,7 +22,7 @@ import app.tivi.data.entities.ImageType import app.tivi.data.entities.ShowTmdbImage import app.tivi.data.entities.TmdbImageEntity import coil.annotation.ExperimentalCoilApi -import coil.api.loadAny +import coil.loadAny import coil.transform.RoundedCornersTransformation import coil.transform.Transformation diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingExtensions.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingExtensions.kt index 246dfc89a8..dbf6d6bb16 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingExtensions.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/ImageLoadingExtensions.kt @@ -20,14 +20,14 @@ import android.content.Context import android.view.MenuItem import app.tivi.extensions.resolveThemeDimensionPixelSize import coil.Coil -import coil.request.LoadRequest +import coil.request.ImageRequest import coil.size.PixelSize import coil.size.Size import coil.size.SizeResolver import coil.transform.CircleCropTransformation fun MenuItem.loadImageUrl(context: Context, url: String, circleCrop: Boolean = true) { - val request = LoadRequest.Builder(context) + val request = ImageRequest.Builder(context) .data(url) .size(object : SizeResolver { override suspend fun size(): Size { @@ -42,5 +42,6 @@ fun MenuItem.loadImageUrl(context: Context, url: String, circleCrop: Boolean = t } } .build() - Coil.execute(request) + + Coil.enqueue(request) } diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/SaturatingTransformation.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/SaturatingTransformation.kt index 1be4f06a8b..875c0f4216 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/SaturatingTransformation.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/SaturatingTransformation.kt @@ -22,7 +22,7 @@ import app.tivi.ui.animations.saturateDrawableAnimator import coil.annotation.ExperimentalCoilApi import coil.decode.DataSource import coil.request.ErrorResult -import coil.request.RequestResult +import coil.request.ImageResult import coil.request.SuccessResult import coil.transition.Transition import coil.transition.TransitionTarget @@ -38,11 +38,11 @@ class SaturatingTransformation( } override suspend fun transition( - target: TransitionTarget<*>, - result: RequestResult + target: TransitionTarget, + result: ImageResult ) { // Don't animate if the request was fulfilled by the memory cache. - if (result is SuccessResult && result.source == DataSource.MEMORY_CACHE) { + if (result is SuccessResult && result.metadata.dataSource == DataSource.MEMORY_CACHE) { target.onSuccess(result.drawable) return } diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/TmdbImageEntityCoilMapper.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/TmdbImageEntityCoilInterceptor.kt similarity index 73% rename from common-imageloading/src/main/java/app/tivi/common/imageloading/TmdbImageEntityCoilMapper.kt rename to common-imageloading/src/main/java/app/tivi/common/imageloading/TmdbImageEntityCoilInterceptor.kt index 459549607e..460550365c 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/TmdbImageEntityCoilMapper.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/TmdbImageEntityCoilInterceptor.kt @@ -21,7 +21,9 @@ import app.tivi.data.entities.TmdbImageEntity import app.tivi.tmdb.TmdbImageUrlProvider import app.tivi.util.PowerController import app.tivi.util.SaveData -import coil.map.MeasuredMapper +import coil.annotation.ExperimentalCoilApi +import coil.intercept.Interceptor +import coil.request.ImageResult import coil.size.PixelSize import coil.size.Size import okhttp3.HttpUrl @@ -29,14 +31,24 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import javax.inject.Inject import javax.inject.Provider -class TmdbImageEntityCoilMapper @Inject constructor( +@ExperimentalCoilApi +class TmdbImageEntityCoilInterceptor @Inject constructor( private val tmdbImageUrlProvider: Provider, private val powerController: PowerController -) : MeasuredMapper { - - override fun handles(data: TmdbImageEntity): Boolean = true +) : Interceptor { + override suspend fun intercept(chain: Interceptor.Chain): ImageResult { + val request = when (val data = chain.request.data) { + is TmdbImageEntity -> { + chain.request.newBuilder() + .data(map(data, chain.size)) + .build() + } + else -> chain.request + } + return chain.proceed(request) + } - override fun map(data: TmdbImageEntity, size: Size): HttpUrl { + private fun map(data: TmdbImageEntity, size: Size): HttpUrl { val width = if (size is PixelSize) { when (powerController.shouldSaveData()) { is SaveData.Disabled -> size.width diff --git a/common-imageloading/src/main/java/app/tivi/common/imageloading/TrimTransparentEdgesTransformation.kt b/common-imageloading/src/main/java/app/tivi/common/imageloading/TrimTransparentEdgesTransformation.kt index 189a486d6e..fbf055373a 100644 --- a/common-imageloading/src/main/java/app/tivi/common/imageloading/TrimTransparentEdgesTransformation.kt +++ b/common-imageloading/src/main/java/app/tivi/common/imageloading/TrimTransparentEdgesTransformation.kt @@ -20,7 +20,7 @@ import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Rect import androidx.core.graphics.alpha -import coil.bitmappool.BitmapPool +import coil.bitmap.BitmapPool import coil.size.Size import coil.transform.Transformation diff --git a/common-ui-compose/build.gradle b/common-ui-compose/build.gradle index 91104ad9ed..bf26fa39c7 100644 --- a/common-ui-compose/build.gradle +++ b/common-ui-compose/build.gradle @@ -59,9 +59,7 @@ dependencies { implementation Libs.AndroidX.Compose.tooling implementation Libs.AndroidX.Compose.livedata - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Kotlin.stdlib - - } \ No newline at end of file diff --git a/common-ui-compose/src/main/java/app/tivi/common/compose/insets.kt b/common-ui-compose/src/main/java/app/tivi/common/compose/insets.kt index dd1be0fd78..bd167520db 100644 --- a/common-ui-compose/src/main/java/app/tivi/common/compose/insets.kt +++ b/common-ui-compose/src/main/java/app/tivi/common/compose/insets.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -@file:Suppress("NOTHING_TO_INLINE") +@file:Suppress("NOTHING_TO_INLINE", "unused") package app.tivi.common.compose import android.view.View +import androidx.compose.foundation.layout.InnerPadding import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.runtime.Providers import androidx.compose.runtime.Stable @@ -35,55 +35,101 @@ import androidx.compose.ui.Measurable import androidx.compose.ui.MeasureScope import androidx.compose.ui.Modifier import androidx.compose.ui.composed -import androidx.compose.ui.layout import androidx.compose.ui.layout.IntrinsicMeasurable import androidx.compose.ui.layout.IntrinsicMeasureScope +import androidx.compose.ui.platform.DensityAmbient +import androidx.compose.ui.platform.LayoutDirectionAmbient import androidx.compose.ui.platform.ViewAmbient import androidx.compose.ui.unit.Constraints +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.offset import androidx.core.view.ViewCompat -import kotlin.math.min +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsCompat.Type + +/** + * Taken from https://goo.gle/compose-insets. Requires androidx.core:core v1.5.0-alpha02+ + */ /** * Main holder of our inset values. */ @Stable class DisplayInsets { + /** + * Inset values which match [WindowInsetsCompat.Type.systemBars] + */ val systemBars = Insets() + + /** + * Inset values which match [WindowInsetsCompat.Type.systemGestures] + */ val systemGestures = Insets() + + /** + * Inset values which match [WindowInsetsCompat.Type.navigationBars] + */ + val navigationBars = Insets() + + /** + * Inset values which match [WindowInsetsCompat.Type.statusBars] + */ + val statusBars = Insets() + + /** + * Inset values which match [WindowInsetsCompat.Type.ime] + */ + val ime = Insets() } @Stable class Insets { + /** + * The left dimension of these insets in pixels. + */ var left by mutableStateOf(0) internal set + + /** + * The top dimension of these insets in pixels. + */ var top by mutableStateOf(0) internal set + + /** + * The right dimension of these insets in pixels. + */ var right by mutableStateOf(0) internal set + + /** + * The bottom dimension of these insets in pixels. + */ var bottom by mutableStateOf(0) internal set /** - * TODO: doesn't currently work + * Whether the insets are currently visible. */ - var visible by mutableStateOf(true) + var isVisible by mutableStateOf(true) internal set } -val DisplayInsetsAmbient = staticAmbientOf() +val InsetsAmbient = staticAmbientOf() /** - * Setup and provide [DisplayInsets] to [DisplayInsetsAmbient]. + * Applies any [WindowInsetsCompat] values to [InsetsAmbient], which are then available + * within [content]. * - * This will automatically listen for [androidx.core.view.WindowInsetsCompat] on the host view. - * - * @param consumeInsets Whether to consume the insets which are dispatched to the host view. + * @param consumeWindowInsets Whether to consume any [WindowInsetsCompat]s which are dispatched to + * the host view. Defaults to `true`. */ @Composable fun ProvideDisplayInsets( - consumeInsets: Boolean = true, + consumeWindowInsets: Boolean = true, content: @Composable () -> Unit ) { val view = ViewAmbient.current @@ -92,16 +138,13 @@ fun ProvideDisplayInsets( onCommit(view) { ViewCompat.setOnApplyWindowInsetsListener(view) { _, windowInsets -> - displayInsets.systemBars.updateFrom(windowInsets.systemWindowInsets) - displayInsets.systemGestures.updateFrom(windowInsets.systemGestureInsets) + displayInsets.systemBars.updateFrom(windowInsets, Type.systemBars()) + displayInsets.systemGestures.updateFrom(windowInsets, Type.systemGestures()) + displayInsets.statusBars.updateFrom(windowInsets, Type.statusBars()) + displayInsets.navigationBars.updateFrom(windowInsets, Type.navigationBars()) + displayInsets.ime.updateFrom(windowInsets, Type.ime()) - if (consumeInsets) { - // TODO: Move this to WindowInsetsCompat.CONSUMED - windowInsets.consumeSystemWindowInsets() - } else { - // Return the unconsumed insets - windowInsets - } + if (consumeWindowInsets) WindowInsetsCompat.CONSUMED else windowInsets } // Add an OnAttachStateChangeListener to request an inset pass each time we're attached @@ -118,185 +161,304 @@ fun ProvideDisplayInsets( } onDispose { - // Once we leave the composition, remove our OnAttachStateChangeListener view.removeOnAttachStateChangeListener(attachListener) } } - Providers(DisplayInsetsAmbient provides displayInsets) { + Providers(InsetsAmbient provides displayInsets) { content() } } /** - * Selectively apply padding which matches the width/height of any system bars present + * Updates our mutable state backed [Insets] from an Android system insets. + */ +private fun Insets.updateFrom(windowInsets: WindowInsetsCompat, type: Int) { + val insets = windowInsets.getInsets(type) + left = insets.left + top = insets.top + right = insets.right + bottom = insets.bottom + + isVisible = windowInsets.isVisible(type) +} + +/** + * Selectively apply additional space which matches the width/height of any system bars present * on the respective edges of the screen. * - * @param enabled Whether to apply padding using the system bar dimensions on the respective edges. + * @param enabled Whether to apply padding using the system bars dimensions on the respective edges. * Defaults to `true`. */ -fun Modifier.systemBarsPadding(enabled: Boolean = true) = when { - enabled -> composed { - insetsPadding( - insets = DisplayInsetsAmbient.current.systemBars, - applyLeft = enabled, - applyTop = enabled, - applyRight = enabled, - applyBottom = enabled - ) - } - else -> this +fun Modifier.systemBarsPadding(enabled: Boolean = true) = composed { + insetsPadding( + insets = InsetsAmbient.current.systemBars, + left = enabled, + top = enabled, + right = enabled, + bottom = enabled + ) } /** - * Apply padding which matches the height of the status height along the top edge + * Apply additional space which matches the height of the status bars height along the top edge * of the content. */ -fun Modifier.statusBarPadding() = composed { - insetsPadding(insets = DisplayInsetsAmbient.current.systemBars, applyTop = true) +fun Modifier.statusBarsPadding() = composed { + insetsPadding(insets = InsetsAmbient.current.statusBars, top = true) } /** - * Apply bottom padding which matches the height of the navigation bar if the navigation bar - * is along the bottom of the screen, and applies left & right padding matching the navigation - * bar width if the navigation bar is along the left or right edge of the screen. + * Apply additional space which matches the height of the navigation bars height + * along the [bottom] edge of the content, and additional space which matches the width of + * the navigation bars on the respective [left] and [right] edges. * - * @param bottom Whether to apply padding to the bottom edge, which matches the navigation bar + * @param bottom Whether to apply padding to the bottom edge, which matches the navigation bars * height (if present) at the bottom edge of the screen. Defaults to `true`. - * @param left Whether to apply padding to the left edge, which matches the navigation bar width + * @param left Whether to apply padding to the left edge, which matches the navigation bars width * (if present) on the left edge of the screen. Defaults to `true`. - * @param right Whether to apply padding to the right edge, which matches the navigation bar width + * @param right Whether to apply padding to the right edge, which matches the navigation bars width * (if present) on the right edge of the screen. Defaults to `true`. */ -fun Modifier.navigationBarPadding( +fun Modifier.navigationBarsPadding( bottom: Boolean = true, left: Boolean = true, right: Boolean = true ) = composed { insetsPadding( - insets = DisplayInsetsAmbient.current.systemBars, - applyLeft = left, - applyRight = right, - applyBottom = bottom + insets = InsetsAmbient.current.navigationBars, + left = left, + right = right, + bottom = bottom ) } /** - * Updates our mutable state backed [Insets] from an Android system insets. + * Declare the height of the content to match the height of the status bars exactly. + * + * This is very handy when used with `Spacer` to push content below the status bars: + * ``` + * Column { + * Spacer(Modifier.statusBarHeight()) + * + * // Content to be drawn below status bars (y-axis) + * } + * ``` + * + * It's also useful when used to draw a scrim which matches the status bars: + * ``` + * Spacer( + * Modifier.statusBarHeight() + * .fillMaxWidth() + * .drawBackground(MaterialTheme.colors.background.copy(alpha = 0.3f) + * ) + * ``` + * + * Internally this matches the behavior of the [Modifier.height] modifier. + * + * @param additional Any additional height to add to the status bars size. */ -private fun Insets.updateFrom(insets: androidx.core.graphics.Insets) { - left = insets.left - top = insets.top - right = insets.right - bottom = insets.bottom +fun Modifier.statusBarsHeight(additional: Dp = 0.dp) = composed { + InsetsSizeModifier( + insets = InsetsAmbient.current.statusBars, + heightSide = VerticalSide.Top, + additionalHeight = additional + ) } /** - * Declare the height of the content to match the height of the status bar exactly. + * Declare the height of the content to match the height of the status bars exactly. * - * This is very handy when used with `Spacer` to push content below the status bar: + * This is very handy when used with `Spacer` to push content below the status bars: * ``` * Column { * Spacer(Modifier.statusBarHeight()) * - * // Content to be drawn below status bar (y-axis) + * // Content to be drawn below status bars (y-axis) * } * ``` * - * It's also useful when used to draw a scrim which matches the status bar: + * It's also useful when used to draw a scrim which matches the status bars: * ``` * Spacer( * Modifier.statusBarHeight() * .fillMaxWidth() - * .background(MaterialTheme.colors.background.copy(alpha = 0.3f) + * .drawBackground(MaterialTheme.colors.background.copy(alpha = 0.3f) * ) * ``` * - * Internally this uses [Modifier.height] so has the same characteristics with regards to incoming - * layout constraints. + * Internally this matches the behavior of the [Modifier.height] modifier. + */ +inline fun Modifier.statusBarsHeight() = statusBarsHeightPlus(0.dp) + +/** + * Declare the height of the content to match the height of the status bars, plus some + * additional height passed in via [additional]. + * + * As an example, this could be used with `Spacer` to push content below the status bar + * and app bars: + * + * ``` + * Column { + * Spacer(Modifier.statusBarHeightPlus(56.dp)) + * + * // Content to be drawn below status bars and app bar (y-axis) + * } + * ``` + * + * Internally this matches the behavior of the [Modifier.height] modifier. + * + * @param additional Any additional height to add to the status bars size. */ -fun Modifier.statusBarHeight() = composed { - // TODO: Move to Android 11 WindowInsets APIs when they land in AndroidX. - // It currently assumes that status bar == top which is probably fine, but doesn't work - // in multi-window, etc. +fun Modifier.statusBarsHeightPlus(additional: Dp) = composed { InsetsSizeModifier( - insets = DisplayInsetsAmbient.current.systemBars, - heightSide = VerticalSide.Top + insets = InsetsAmbient.current.statusBars, + heightSide = VerticalSide.Top, + additionalHeight = additional ) } /** - * Declare the preferred height of the content to match the height of the navigation bar when present at the bottom of the screen. + * Declare the preferred height of the content to match the height of the navigation bars when + * present at the bottom of the screen. * - * This is very handy when used with `Spacer` to push content below the navigation bar: + * This is very handy when used with `Spacer` to push content below the navigation bars: * ``` * Column { - * // Content to be drawn above status bar (y-axis) + * // Content to be drawn above status bars (y-axis) * Spacer(Modifier.navigationBarHeight()) * } * ``` * - * It's also useful when used to draw a scrim which matches the navigation bar: + * It's also useful when used to draw a scrim which matches the navigation bars: * ``` * Spacer( * Modifier.navigationBarHeight() * .fillMaxWidth() - * .background(MaterialTheme.colors.background.copy(alpha = 0.3f) + * .drawBackground(MaterialTheme.colors.background.copy(alpha = 0.3f) * ) * ``` * - * Internally this uses [Modifier.height] so has the same characteristics with regards to incoming - * layout constraints. + * Internally this matches the behavior of the [Modifier.height] modifier. */ -fun Modifier.navigationBarHeight() = composed { - // TODO: Move to Android 11 WindowInsets APIs when they land in AndroidX. - // It currently assumes that nav bar == bottom, which is wrong in landscape. - // It also doesn't handle the IME correctly. +inline fun Modifier.navigationBarsHeight() = navigationBarsHeightPlus(0.dp) + +/** + * Declare the height of the content to match the height of the navigation bars, plus some + * additional height passed in via [additional] + * + * As an example, this could be used with `Spacer` to push content above the navigation bar + * and bottom app bars: + * + * ``` + * Column { + * // Content to be drawn above navigation bars and bottom app bar (y-axis) + * + * Spacer(Modifier.statusBarHeightPlus(48.dp)) + * } + * ``` + * + * Internally this matches the behavior of the [Modifier.height] modifier. + * + * @param additional Any additional height to add to the status bars size. + */ +fun Modifier.navigationBarsHeightPlus(additional: Dp) = composed { InsetsSizeModifier( - insets = DisplayInsetsAmbient.current.systemBars, - heightSide = VerticalSide.Bottom + insets = InsetsAmbient.current.navigationBars, + heightSide = VerticalSide.Bottom, + additionalHeight = additional ) } -enum class HorizontalSide { Start, End } +enum class HorizontalSide { Left, Right } enum class VerticalSide { Top, Bottom } /** - * Declare the preferred width of the content to match the width of the navigation bar, + * Declare the preferred width of the content to match the width of the navigation bars, * on the given [side]. * * This is very handy when used with `Spacer` to push content inside from any vertical * navigation bars (typically when the device is in landscape): * ``` * Row { - * Spacer(Modifier.navigationBarWidth(HorizontalSide.Start)) + * Spacer(Modifier.navigationBarWidth(HorizontalSide.Left)) * * // Content to be inside the navigation bars (x-axis) * - * Spacer(Modifier.navigationBarWidth(HorizontalSide.End)) + * Spacer(Modifier.navigationBarWidth(HorizontalSide.Right)) * } * ``` * - * It's also useful when used to draw a scrim which matches the navigation bar: + * It's also useful when used to draw a scrim which matches the navigation bars: * ``` * Spacer( - * Modifier.navigationBarWidth(HorizontalSide.Start) + * Modifier.navigationBarWidth(HorizontalSide.Left) * .fillMaxHeight() - * .background(MaterialTheme.colors.background.copy(alpha = 0.3f) + * .drawBackground(MaterialTheme.colors.background.copy(alpha = 0.3f) * ) * ``` * - * Internally this uses [Modifier.width] so has the same characteristics with regards to incoming - * layout constraints. + * Internally this matches the behavior of the [Modifier.height] modifier. * * @param side The navigation bar side to use as the source for the width. */ -fun Modifier.navigationBarWidth(side: HorizontalSide) = composed { - // TODO: Move to Android 11 WindowInsets APIs when they land in AndroidX. - // It currently assumes that nav bar == left/right +inline fun Modifier.navigationBarWidth(side: HorizontalSide) = navigationBarsWidthPlus(side, 0.dp) + +/** + * Declare the preferred width of the content to match the width of the navigation bars, + * on the given [side], plus additional width passed in via [additional]. + * + * Internally this matches the behavior of the [Modifier.height] modifier. + * + * @param side The navigation bar side to use as the source for the width. + * @param additional Any additional width to add to the status bars size. + */ +fun Modifier.navigationBarsWidthPlus( + side: HorizontalSide, + additional: Dp +) = composed { InsetsSizeModifier( - insets = DisplayInsetsAmbient.current.systemBars, - widthSide = side + insets = InsetsAmbient.current.navigationBars, + widthSide = side, + additionalWidth = additional + ) +} + +/** + * Returns the current insets converted into a [InnerPadding]. + * + * @param start Whether to apply the inset on the start dimension. + * @param top Whether to apply the inset on the top dimension. + * @param end Whether to apply the inset on the end dimension. + * @param bottom Whether to apply the inset on the bottom dimension. + */ +@Composable +fun Insets.toInnerPadding( + start: Boolean = true, + top: Boolean = true, + end: Boolean = true, + bottom: Boolean = true +): InnerPadding = with(DensityAmbient.current) { + val layoutDirection = LayoutDirectionAmbient.current + InnerPadding( + start = when { + start && layoutDirection == LayoutDirection.Ltr -> this@toInnerPadding.left.toDp() + start && layoutDirection == LayoutDirection.Rtl -> this@toInnerPadding.right.toDp() + else -> 0.dp + }, + top = when { + top -> this@toInnerPadding.top.toDp() + else -> 0.dp + }, + end = when { + end && layoutDirection == LayoutDirection.Ltr -> this@toInnerPadding.right.toDp() + end && layoutDirection == LayoutDirection.Rtl -> this@toInnerPadding.left.toDp() + else -> 0.dp + }, + bottom = when { + bottom -> this@toInnerPadding.bottom.toDp() + else -> 0.dp + } ) } @@ -305,76 +467,108 @@ fun Modifier.navigationBarWidth(side: HorizontalSide) = composed { */ private inline fun Modifier.insetsPadding( insets: Insets, - applyLeft: Boolean = false, - applyTop: Boolean = false, - applyRight: Boolean = false, - applyBottom: Boolean = false -) = layout { measurable, constraints -> - val left = if (applyLeft) insets.left else 0 - val top = if (applyTop) insets.top else 0 - val right = if (applyRight) insets.right else 0 - val bottom = if (applyBottom) insets.bottom else 0 - val horizontal = left + right - val vertical = top + bottom - - val placeable = measurable.measure(constraints.offset(-horizontal, -vertical)) - - val width = (placeable.width + horizontal) - .coerceIn(constraints.minWidth, constraints.maxWidth) - val height = (placeable.height + vertical) - .coerceIn(constraints.minHeight, constraints.maxHeight) - layout(width, height) { - placeable.place(left, top) + left: Boolean = false, + top: Boolean = false, + right: Boolean = false, + bottom: Boolean = false +) = this then InsetsPaddingModifier(insets, left, top, right, bottom) + +private data class InsetsPaddingModifier( + private val insets: Insets, + private val applyLeft: Boolean = false, + private val applyTop: Boolean = false, + private val applyRight: Boolean = false, + private val applyBottom: Boolean = false +) : LayoutModifier { + override fun MeasureScope.measure( + measurable: Measurable, + constraints: Constraints + ): MeasureScope.MeasureResult { + val left = if (applyLeft) insets.left else 0 + val top = if (applyTop) insets.top else 0 + val right = if (applyRight) insets.right else 0 + val bottom = if (applyBottom) insets.bottom else 0 + val horizontal = left + right + val vertical = top + bottom + + val placeable = measurable.measure(constraints.offset(-horizontal, -vertical)) + + val width = (placeable.width + horizontal) + .coerceIn(constraints.minWidth, constraints.maxWidth) + val height = (placeable.height + vertical) + .coerceIn(constraints.minHeight, constraints.maxHeight) + return layout(width, height) { + placeable.place(left, top) + } } } private data class InsetsSizeModifier( private val insets: Insets, private val widthSide: HorizontalSide? = null, - private val heightSide: VerticalSide? = null + private val additionalWidth: Dp = 0.dp, + private val heightSide: VerticalSide? = null, + private val additionalHeight: Dp = 0.dp ) : LayoutModifier { - private val targetConstraints - get() = Constraints( - // Calculate below since we need to resolve layoutdirection - minWidth = 0, - minHeight = when (heightSide) { - VerticalSide.Top -> insets.top - VerticalSide.Bottom -> insets.bottom - null -> 0 - }, - // Calculated below since we need to resolve layoutdirection - maxWidth = Constraints.Infinity, - maxHeight = when (heightSide) { - VerticalSide.Top -> insets.top - VerticalSide.Bottom -> insets.bottom - null -> Constraints.Infinity - } - ) + private val Density.targetConstraints: Constraints + get() { + val additionalWidthPx = additionalWidth.toIntPx() + val additionalHeightPx = additionalHeight.toIntPx() + return Constraints( + minWidth = additionalWidthPx + when (widthSide) { + HorizontalSide.Left -> insets.left + HorizontalSide.Right -> insets.right + null -> 0 + }, + minHeight = additionalHeightPx + when (heightSide) { + VerticalSide.Top -> insets.top + VerticalSide.Bottom -> insets.bottom + null -> 0 + }, + maxWidth = when (widthSide) { + HorizontalSide.Left -> insets.left + additionalWidthPx + HorizontalSide.Right -> insets.right + additionalWidthPx + null -> Constraints.Infinity + }, + maxHeight = when (heightSide) { + VerticalSide.Top -> insets.top + additionalHeightPx + VerticalSide.Bottom -> insets.bottom + additionalHeightPx + null -> Constraints.Infinity + } + ) + } override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureScope.MeasureResult { val wrappedConstraints = targetConstraints.let { targetConstraints -> - val resolvedMinWidth = when { - widthSide != null -> resolveInsetWidth(widthSide, layoutDirection) - else -> min(constraints.minWidth, targetConstraints.maxWidth) + val resolvedMinWidth = if (widthSide != null) { + targetConstraints.minWidth + } else { + constraints.minWidth.coerceAtMost(targetConstraints.maxWidth) } - val resolvedMaxWidth = when { - widthSide != null -> resolveInsetWidth(widthSide, layoutDirection) - else -> min(constraints.maxWidth, targetConstraints.minWidth) + val resolvedMaxWidth = if (widthSide != null) { + targetConstraints.maxWidth + } else { + constraints.maxWidth.coerceAtLeast(targetConstraints.minWidth) } val resolvedMinHeight = if (heightSide != null) { targetConstraints.minHeight } else { - min(constraints.minHeight, targetConstraints.maxHeight) + constraints.minHeight.coerceAtMost(targetConstraints.maxHeight) } val resolvedMaxHeight = if (heightSide != null) { targetConstraints.maxHeight } else { - min(constraints.maxHeight, targetConstraints.minHeight) + constraints.maxHeight.coerceAtLeast(targetConstraints.minHeight) } - Constraints(resolvedMinWidth, resolvedMaxWidth, resolvedMinHeight, resolvedMaxHeight) + Constraints( + resolvedMinWidth, + resolvedMaxWidth, + resolvedMinHeight, + resolvedMaxHeight + ) } val placeable = measurable.measure(wrappedConstraints) return layout(placeable.width, placeable.height) { @@ -385,25 +579,17 @@ private data class InsetsSizeModifier( override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int - ) = when { - widthSide != null -> resolveInsetWidth(widthSide, layoutDirection) - else -> { - val constraints = targetConstraints - measurable.minIntrinsicWidth(height) - .coerceIn(constraints.minWidth, constraints.maxWidth) - } + ) = measurable.minIntrinsicWidth(height).let { + val constraints = targetConstraints + it.coerceIn(constraints.minWidth, constraints.maxWidth) } override fun IntrinsicMeasureScope.maxIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int - ): Int = when { - widthSide != null -> resolveInsetWidth(widthSide, layoutDirection) - else -> { - val constraints = targetConstraints - measurable.maxIntrinsicWidth(height) - .coerceIn(constraints.minWidth, constraints.maxWidth) - } + ) = measurable.maxIntrinsicWidth(height).let { + val constraints = targetConstraints + it.coerceIn(constraints.minWidth, constraints.maxWidth) } override fun IntrinsicMeasureScope.minIntrinsicHeight( @@ -421,16 +607,4 @@ private data class InsetsSizeModifier( val constraints = targetConstraints it.coerceIn(constraints.minHeight, constraints.maxHeight) } - - private fun resolveInsetWidth( - widthSide: HorizontalSide, - layoutDirection: LayoutDirection - ): Int = when (layoutDirection) { - LayoutDirection.Ltr -> { - if (widthSide == HorizontalSide.Start) insets.left else insets.right - } - LayoutDirection.Rtl -> { - if (widthSide == HorizontalSide.Start) insets.right else insets.left - } - } } diff --git a/common-ui-resources/build.gradle b/common-ui-resources/build.gradle index 78acaa4669..360ca65b34 100644 --- a/common-ui-resources/build.gradle +++ b/common-ui-resources/build.gradle @@ -48,7 +48,7 @@ dependencies { implementation Libs.AndroidX.Lifecycle.viewmodel api Libs.AndroidX.appcompat - api Libs.Google.material + api Libs.Mdc.material implementation Libs.AndroidX.recyclerview implementation Libs.AndroidX.constraintlayout diff --git a/common-ui-view/build.gradle b/common-ui-view/build.gradle index 3eede574f3..c5343fa03b 100644 --- a/common-ui-view/build.gradle +++ b/common-ui-view/build.gradle @@ -61,5 +61,5 @@ dependencies { implementation Libs.Hilt.library - api Libs.Google.material + api Libs.Mdc.material } \ No newline at end of file diff --git a/common-ui-view/src/main/java/app/tivi/ui/StatusBarHeightBehavior.kt b/common-ui-view/src/main/java/app/tivi/ui/StatusBarHeightBehavior.kt deleted file mode 100644 index 13ff94d27e..0000000000 --- a/common-ui-view/src/main/java/app/tivi/ui/StatusBarHeightBehavior.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2017 Google LLC - * - * 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 - * - * http://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 app.tivi.ui - -import android.content.Context -import android.util.AttributeSet -import android.view.View -import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.core.view.WindowInsetsCompat - -class StatusBarHeightBehavior( - context: Context, - attrs: AttributeSet? -) : CoordinatorLayout.Behavior(context, attrs) { - override fun onApplyWindowInsets( - coordinatorLayout: CoordinatorLayout, - child: View, - insets: WindowInsetsCompat - ): WindowInsetsCompat { - val lp = child.layoutParams - lp.height = insets.systemWindowInsetTop - child.layoutParams = lp - return insets.consumeSystemWindowInsets() - } -} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bb8b2fc26b..6c9a224775 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/ui-account/build.gradle b/ui-account/build.gradle index 6d0cfc1075..d741ef9bc2 100644 --- a/ui-account/build.gradle +++ b/ui-account/build.gradle @@ -78,10 +78,10 @@ dependencies { implementation Libs.AndroidX.Compose.livedata implementation Libs.AndroidX.Compose.iconsExtended - implementation Libs.Accompanist.mdcTheme - implementation Libs.Accompanist.coil + implementation Libs.Mdc.material + implementation Libs.Mdc.composeThemeAdapter - implementation Libs.Google.material + implementation Libs.Accompanist.coil implementation Libs.Kotlin.stdlib diff --git a/ui-account/src/main/java/app/tivi/account/AccountUi.kt b/ui-account/src/main/java/app/tivi/account/AccountUi.kt index 9d22326bf3..bf0e55761f 100644 --- a/ui-account/src/main/java/app/tivi/account/AccountUi.kt +++ b/ui-account/src/main/java/app/tivi/account/AccountUi.kt @@ -58,8 +58,8 @@ import app.tivi.common.compose.VectorImage import app.tivi.data.entities.TraktUser import app.tivi.trakt.TraktAuthState import app.tivi.util.TiviDateFormatter +import com.google.android.material.composethemeadapter.MdcTheme import dev.chrisbanes.accompanist.coil.CoilImageWithCrossfade -import dev.chrisbanes.accompanist.mdctheme.MaterialThemeFromMdcTheme import org.threeten.bp.OffsetDateTime import org.threeten.bp.ZoneOffset @@ -69,7 +69,7 @@ fun composeAccountUi( actioner: (AccountUiAction) -> Unit, tiviDateFormatter: TiviDateFormatter ): Any = viewGroup.setContent(Recomposer.current()) { - MaterialThemeFromMdcTheme { + MdcTheme { Providers(TiviDateFormatterAmbient provides tiviDateFormatter) { ProvideDisplayInsets { val viewState by state.observeAsState() diff --git a/ui-discover/build.gradle b/ui-discover/build.gradle index 0e969efd06..3ff1c8666a 100644 --- a/ui-discover/build.gradle +++ b/ui-discover/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation Libs.AndroidX.Fragment.fragmentKtx implementation Libs.AndroidX.Navigation.fragment - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-discover/src/main/java/app/tivi/home/discover/DiscoverFragment.kt b/ui-discover/src/main/java/app/tivi/home/discover/DiscoverFragment.kt index 9eda97b997..c6e742e160 100644 --- a/ui-discover/src/main/java/app/tivi/home/discover/DiscoverFragment.kt +++ b/ui-discover/src/main/java/app/tivi/home/discover/DiscoverFragment.kt @@ -22,7 +22,6 @@ import android.view.ViewGroup import androidx.core.net.toUri import androidx.core.view.updatePadding import androidx.fragment.app.viewModels -import androidx.lifecycle.observe import androidx.navigation.fragment.findNavController import app.tivi.FragmentWithBinding import app.tivi.common.imageloading.loadImageUrl diff --git a/ui-episodedetails/build.gradle b/ui-episodedetails/build.gradle index 25158600ee..8a8a9fc655 100644 --- a/ui-episodedetails/build.gradle +++ b/ui-episodedetails/build.gradle @@ -83,10 +83,10 @@ dependencies { implementation Libs.AndroidX.Compose.livedata implementation Libs.AndroidX.Compose.iconsExtended - implementation Libs.Accompanist.mdcTheme - implementation Libs.Accompanist.coil + implementation Libs.Mdc.material + implementation Libs.Mdc.composeThemeAdapter - implementation Libs.Google.material + implementation Libs.Accompanist.coil implementation Libs.Kotlin.stdlib diff --git a/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt b/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt index 1194f70e4e..81815b555c 100644 --- a/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt +++ b/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt @@ -94,8 +94,8 @@ import app.tivi.common.compose.SwipeToDismiss import app.tivi.common.compose.TiviAlertDialog import app.tivi.common.compose.TiviDateFormatterAmbient import app.tivi.common.compose.boundsInParent -import app.tivi.common.compose.navigationBarHeight -import app.tivi.common.compose.navigationBarPadding +import app.tivi.common.compose.navigationBarsHeight +import app.tivi.common.compose.navigationBarsPadding import app.tivi.common.compose.onPositionInParentChanged import app.tivi.common.compose.rememberMutableState import app.tivi.data.entities.Episode @@ -104,8 +104,8 @@ import app.tivi.data.entities.PendingAction import app.tivi.data.entities.Season import app.tivi.ui.animations.lerp import app.tivi.util.TiviDateFormatter +import com.google.android.material.composethemeadapter.MdcTheme import dev.chrisbanes.accompanist.coil.CoilImageWithCrossfade -import dev.chrisbanes.accompanist.mdctheme.MaterialThemeFromMdcTheme import org.threeten.bp.OffsetDateTime import kotlin.math.hypot @@ -121,7 +121,7 @@ fun ViewGroup.composeEpisodeDetails( actioner: (EpisodeDetailsAction) -> Unit, tiviDateFormatter: TiviDateFormatter ): Any = setContent(Recomposer.current()) { - MaterialThemeFromMdcTheme { + MdcTheme { Providers(TiviDateFormatterAmbient provides tiviDateFormatter) { ProvideDisplayInsets { val viewState by state.observeAsState() @@ -222,7 +222,7 @@ private fun EpisodeDetails( } Spacer(Modifier.preferredHeight(8.dp)) - Spacer(Modifier.navigationBarHeight()) + Spacer(Modifier.navigationBarsHeight()) } } } @@ -231,7 +231,7 @@ private fun EpisodeDetails( Column( modifier = Modifier.fillMaxWidth() .gravity(Alignment.BottomCenter) - .navigationBarPadding() + .navigationBarsPadding() ) { Crossfade(current = viewState.error) { error -> if (error != null) { diff --git a/ui-followed/build.gradle b/ui-followed/build.gradle index a470bcb67c..34a04a22da 100644 --- a/ui-followed/build.gradle +++ b/ui-followed/build.gradle @@ -72,7 +72,7 @@ dependencies { implementation Libs.AndroidX.Fragment.fragmentKtx implementation Libs.AndroidX.Navigation.fragment - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-followed/src/main/java/app/tivi/home/followed/FollowedFragment.kt b/ui-followed/src/main/java/app/tivi/home/followed/FollowedFragment.kt index b44087f2c2..9cab3f6e03 100644 --- a/ui-followed/src/main/java/app/tivi/home/followed/FollowedFragment.kt +++ b/ui-followed/src/main/java/app/tivi/home/followed/FollowedFragment.kt @@ -26,7 +26,6 @@ import androidx.core.net.toUri import androidx.core.view.updatePadding import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.observe import androidx.navigation.fragment.findNavController import app.tivi.FragmentWithBinding import app.tivi.common.imageloading.loadImageUrl diff --git a/ui-popular/build.gradle b/ui-popular/build.gradle index 3c26ee1a77..66aadade25 100644 --- a/ui-popular/build.gradle +++ b/ui-popular/build.gradle @@ -67,7 +67,7 @@ dependencies { implementation Libs.AndroidX.Fragment.fragmentKtx implementation Libs.AndroidX.Navigation.fragment - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-recommended/build.gradle b/ui-recommended/build.gradle index ca2c84fa8f..be2c9a7986 100644 --- a/ui-recommended/build.gradle +++ b/ui-recommended/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation Libs.AndroidX.Navigation.fragment implementation Libs.AndroidX.Navigation.ui - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-search/build.gradle b/ui-search/build.gradle index db81132962..f3313de62d 100644 --- a/ui-search/build.gradle +++ b/ui-search/build.gradle @@ -72,7 +72,7 @@ dependencies { implementation Libs.AndroidX.Fragment.fragmentKtx implementation Libs.AndroidX.Navigation.fragment - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-search/src/main/java/app/tivi/home/search/SearchFragment.kt b/ui-search/src/main/java/app/tivi/home/search/SearchFragment.kt index aaba2f304b..fb2af3267b 100644 --- a/ui-search/src/main/java/app/tivi/home/search/SearchFragment.kt +++ b/ui-search/src/main/java/app/tivi/home/search/SearchFragment.kt @@ -24,7 +24,6 @@ import androidx.core.net.toUri import androidx.core.view.marginBottom import androidx.core.view.updatePadding import androidx.fragment.app.viewModels -import androidx.lifecycle.observe import androidx.navigation.fragment.findNavController import app.tivi.FragmentWithBinding import app.tivi.data.entities.TiviShow diff --git a/ui-settings/build.gradle b/ui-settings/build.gradle index 189ae712cb..7754618751 100644 --- a/ui-settings/build.gradle +++ b/ui-settings/build.gradle @@ -62,7 +62,7 @@ dependencies { implementation Libs.AndroidX.Fragment.fragment implementation Libs.AndroidX.Fragment.fragmentKtx - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-showdetails/build.gradle b/ui-showdetails/build.gradle index 467b5a1e83..430b4b6164 100644 --- a/ui-showdetails/build.gradle +++ b/ui-showdetails/build.gradle @@ -88,10 +88,10 @@ dependencies { implementation Libs.AndroidX.Compose.livedata implementation Libs.AndroidX.Compose.iconsExtended - implementation Libs.Accompanist.mdcTheme - implementation Libs.Accompanist.coil + implementation Libs.Mdc.material + implementation Libs.Mdc.composeThemeAdapter - implementation Libs.Google.material + implementation Libs.Accompanist.coil implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetails.kt b/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetails.kt index 007081d7d8..39535df291 100644 --- a/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetails.kt +++ b/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetails.kt @@ -24,9 +24,9 @@ import androidx.compose.foundation.Icon import androidx.compose.foundation.ScrollState import androidx.compose.foundation.ScrollableColumn import androidx.compose.foundation.Text +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.contentColor -import androidx.compose.foundation.drawBorder import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ConstraintLayout @@ -97,9 +97,9 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.LiveData import androidx.ui.tooling.preview.Preview import app.tivi.common.compose.AutoSizedCircularProgressIndicator -import app.tivi.common.compose.DisplayInsetsAmbient import app.tivi.common.compose.ExpandableFloatingActionButton import app.tivi.common.compose.ExpandingText +import app.tivi.common.compose.InsetsAmbient import app.tivi.common.compose.LogCompositions import app.tivi.common.compose.PopupMenu import app.tivi.common.compose.PopupMenuItem @@ -109,7 +109,7 @@ import app.tivi.common.compose.VectorImage import app.tivi.common.compose.offset import app.tivi.common.compose.onSizeChanged import app.tivi.common.compose.rememberMutableState -import app.tivi.common.compose.statusBarHeight +import app.tivi.common.compose.statusBarsHeight import app.tivi.common.compose.systemBarsPadding import app.tivi.common.imageloading.TrimTransparentEdgesTransformation import app.tivi.data.entities.Episode @@ -131,10 +131,10 @@ import app.tivi.data.resultentities.numberWatched import app.tivi.data.views.FollowedShowsWatchStats import app.tivi.ui.animations.lerp import app.tivi.util.TiviDateFormatter -import coil.request.GetRequest +import coil.request.ImageRequest +import com.google.android.material.composethemeadapter.MdcTheme import dev.chrisbanes.accompanist.coil.CoilImage import dev.chrisbanes.accompanist.coil.CoilImageWithCrossfade -import dev.chrisbanes.accompanist.mdctheme.MaterialThemeFromMdcTheme import org.threeten.bp.OffsetDateTime val ShowDetailsTextCreatorAmbient = staticAmbientOf() @@ -149,8 +149,8 @@ fun ViewGroup.composeShowDetails( TiviDateFormatterAmbient provides tiviDateFormatter, ShowDetailsTextCreatorAmbient provides textCreator ) { - MaterialThemeFromMdcTheme { - LogCompositions("MaterialThemeFromMdcTheme") + MdcTheme { + LogCompositions("MdcTheme") ProvideDisplayInsets { LogCompositions("ProvideInsets") @@ -199,7 +199,7 @@ fun ShowDetails( } OverlaidStatusBarAppBar( - scrollState = scrollState.value, + scrollPosition = scrollState.value, backdropHeight = backdropHeight, appBar = { ShowDetailsAppBar( @@ -380,30 +380,30 @@ private fun ShowDetailsScrollingContent( @Composable private fun OverlaidStatusBarAppBar( - scrollState: Float, + scrollPosition: Float, backdropHeight: Int, modifier: Modifier = Modifier, appBar: @Composable () -> Unit ) { LogCompositions("OverlaidStatusBarAppBar") - val insets = DisplayInsetsAmbient.current + val insets = InsetsAmbient.current val trigger = (backdropHeight - insets.systemBars.top).coerceAtLeast(0) val alpha = lerp( startValue = 0.5f, endValue = 1f, - fraction = if (trigger > 0) (scrollState / trigger).coerceIn(0f, 1f) else 0f + fraction = if (trigger > 0) (scrollPosition / trigger).coerceIn(0f, 1f) else 0f ) Surface( color = MaterialTheme.colors.surface.copy(alpha = alpha), - elevation = if (scrollState >= trigger) 2.dp else 0.dp, + elevation = if (scrollPosition >= trigger) 2.dp else 0.dp, modifier = modifier ) { Column(Modifier.fillMaxWidth()) { - Spacer(Modifier.statusBarHeight()) - if (scrollState >= trigger) { + Spacer(Modifier.statusBarsHeight()) + if (scrollPosition >= trigger) { appBar() } } @@ -430,7 +430,7 @@ private fun NetworkInfoPanel( } CoilImage( - request = GetRequest.Builder(ContextAmbient.current) + request = ImageRequest.Builder(ContextAmbient.current) .data(tmdbImage) .transformations(TrimTransparentEdgesTransformation) .build(), @@ -505,8 +505,8 @@ private fun CertificateInfoPanel( Text( text = certification, style = MaterialTheme.typography.body2, - modifier = Modifier.drawBorder( - size = 1.dp, + modifier = Modifier.border( + width = 1.dp, color = MaterialTheme.colors.onSurface, shape = RoundedCornerShape(2.dp) ).padding(horizontal = 4.dp, vertical = 2.dp) diff --git a/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetailsFragment.kt b/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetailsFragment.kt index d629faa9b5..ba4dab4345 100644 --- a/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetailsFragment.kt +++ b/ui-showdetails/src/main/java/app/tivi/showdetails/details/ShowDetailsFragment.kt @@ -26,7 +26,6 @@ import androidx.core.net.toUri import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.observe import androidx.navigation.fragment.findNavController import app.tivi.extensions.scheduleStartPostponedTransitions import app.tivi.extensions.viewModelProviderFactoryOf diff --git a/ui-trending/build.gradle b/ui-trending/build.gradle index 3c26ee1a77..66aadade25 100644 --- a/ui-trending/build.gradle +++ b/ui-trending/build.gradle @@ -67,7 +67,7 @@ dependencies { implementation Libs.AndroidX.Fragment.fragmentKtx implementation Libs.AndroidX.Navigation.fragment - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-watched/build.gradle b/ui-watched/build.gradle index 997c2f8220..a0c3ca6788 100644 --- a/ui-watched/build.gradle +++ b/ui-watched/build.gradle @@ -73,7 +73,7 @@ dependencies { implementation Libs.AndroidX.Navigation.fragment implementation Libs.AndroidX.Navigation.ui - implementation Libs.Google.material + implementation Libs.Mdc.material implementation Libs.Hilt.library kapt Libs.Hilt.compiler diff --git a/ui-watched/src/main/java/app/tivi/home/watched/WatchedFragment.kt b/ui-watched/src/main/java/app/tivi/home/watched/WatchedFragment.kt index cce1278fed..0c157c94d6 100644 --- a/ui-watched/src/main/java/app/tivi/home/watched/WatchedFragment.kt +++ b/ui-watched/src/main/java/app/tivi/home/watched/WatchedFragment.kt @@ -26,7 +26,6 @@ import androidx.core.net.toUri import androidx.core.view.updatePadding import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.observe import androidx.navigation.fragment.findNavController import app.tivi.FragmentWithBinding import app.tivi.common.imageloading.loadImageUrl