From f55898d9e87cca7d7cae5c3152f632383b33545d Mon Sep 17 00:00:00 2001 From: Chris Banes Date: Sat, 22 Aug 2020 11:29:53 +0100 Subject: [PATCH 1/3] Remove icons-extended It's *very* large, which really slows down dexing time. Migrated to using vector resources. --- app/src/main/res/menu/home_bottomnav.xml | 2 +- .../java/app/tivi/buildsrc/dependencies.kt | 1 - .../main/res/drawable/ic_calendar_today.xml | 26 +++++++++++++++++++ .../src/main/res/drawable/ic_cloud_upload.xml | 21 +++++++++++++++ .../src/main/res/drawable/ic_delete_sweep.xml | 26 +++++++++++++++++++ .../src/main/res/drawable/ic_publish.xml | 26 +++++++++++++++++++ .../{ic_eye_24dp.xml => ic_visibility.xml} | 0 .../main/res/drawable/ic_visibility_off.xml | 21 +++++++++++++++ ui-account/build.gradle | 1 - ui-episodedetails/build.gradle | 2 +- .../app/tivi/episodedetails/EpisodeDetails.kt | 15 ++++------- ui-showdetails/build.gradle | 1 - .../tivi/showdetails/details/ShowDetails.kt | 10 +++---- 13 files changed, 131 insertions(+), 21 deletions(-) create mode 100644 common-ui-resources/src/main/res/drawable/ic_calendar_today.xml create mode 100644 common-ui-resources/src/main/res/drawable/ic_cloud_upload.xml create mode 100644 common-ui-resources/src/main/res/drawable/ic_delete_sweep.xml create mode 100644 common-ui-resources/src/main/res/drawable/ic_publish.xml rename common-ui-resources/src/main/res/drawable/{ic_eye_24dp.xml => ic_visibility.xml} (100%) create mode 100644 common-ui-resources/src/main/res/drawable/ic_visibility_off.xml diff --git a/app/src/main/res/menu/home_bottomnav.xml b/app/src/main/res/menu/home_bottomnav.xml index 8b41a69c28..a084f1f0eb 100644 --- a/app/src/main/res/menu/home_bottomnav.xml +++ b/app/src/main/res/menu/home_bottomnav.xml @@ -29,7 +29,7 @@ + + + + diff --git a/common-ui-resources/src/main/res/drawable/ic_cloud_upload.xml b/common-ui-resources/src/main/res/drawable/ic_cloud_upload.xml new file mode 100644 index 0000000000..7efb53a506 --- /dev/null +++ b/common-ui-resources/src/main/res/drawable/ic_cloud_upload.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/common-ui-resources/src/main/res/drawable/ic_delete_sweep.xml b/common-ui-resources/src/main/res/drawable/ic_delete_sweep.xml new file mode 100644 index 0000000000..5c955685af --- /dev/null +++ b/common-ui-resources/src/main/res/drawable/ic_delete_sweep.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/common-ui-resources/src/main/res/drawable/ic_publish.xml b/common-ui-resources/src/main/res/drawable/ic_publish.xml new file mode 100644 index 0000000000..c185085508 --- /dev/null +++ b/common-ui-resources/src/main/res/drawable/ic_publish.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/common-ui-resources/src/main/res/drawable/ic_eye_24dp.xml b/common-ui-resources/src/main/res/drawable/ic_visibility.xml similarity index 100% rename from common-ui-resources/src/main/res/drawable/ic_eye_24dp.xml rename to common-ui-resources/src/main/res/drawable/ic_visibility.xml diff --git a/common-ui-resources/src/main/res/drawable/ic_visibility_off.xml b/common-ui-resources/src/main/res/drawable/ic_visibility_off.xml new file mode 100644 index 0000000000..327d12bd59 --- /dev/null +++ b/common-ui-resources/src/main/res/drawable/ic_visibility_off.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/ui-account/build.gradle b/ui-account/build.gradle index d741ef9bc2..2a3c51b8bc 100644 --- a/ui-account/build.gradle +++ b/ui-account/build.gradle @@ -76,7 +76,6 @@ dependencies { implementation Libs.AndroidX.Compose.animation implementation Libs.AndroidX.Compose.tooling implementation Libs.AndroidX.Compose.livedata - implementation Libs.AndroidX.Compose.iconsExtended implementation Libs.Mdc.material implementation Libs.Mdc.composeThemeAdapter diff --git a/ui-episodedetails/build.gradle b/ui-episodedetails/build.gradle index 8a8a9fc655..17c49e17f1 100644 --- a/ui-episodedetails/build.gradle +++ b/ui-episodedetails/build.gradle @@ -63,6 +63,7 @@ dependencies { implementation project(':base-android') implementation project(':domain') implementation project(':common-ui-view') + implementation project(':common-ui-view') implementation project(':common-ui-compose') implementation Libs.AndroidX.Lifecycle.livedata @@ -81,7 +82,6 @@ dependencies { implementation Libs.AndroidX.Compose.animation implementation Libs.AndroidX.Compose.tooling implementation Libs.AndroidX.Compose.livedata - implementation Libs.AndroidX.Compose.iconsExtended implementation Libs.Mdc.material implementation Libs.Mdc.composeThemeAdapter 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 81815b555c..e5427d0da4 100644 --- a/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt +++ b/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt @@ -53,14 +53,10 @@ import androidx.compose.material.Snackbar import androidx.compose.material.Surface import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.CalendarToday import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Delete -import androidx.compose.material.icons.filled.DeleteSweep -import androidx.compose.material.icons.filled.Publish import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Star -import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.runtime.Composable import androidx.compose.runtime.Providers import androidx.compose.runtime.Recomposer @@ -68,7 +64,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.runtime.state import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.drawWithContent @@ -81,8 +76,8 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.ConfigurationAmbient import androidx.compose.ui.platform.setContent import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.center import androidx.compose.ui.unit.dp import androidx.lifecycle.LiveData import androidx.ui.tooling.preview.Preview @@ -318,7 +313,7 @@ private fun InfoPanes(episode: Episode) { episode.firstAired?.let { firstAired -> val formatter = TiviDateFormatterAmbient.current InfoPane( - icon = Icons.Default.CalendarToday, + icon = vectorResource(R.drawable.ic_calendar_today), label = formatter.formatShortRelativeTime(firstAired), modifier = Modifier.weight(1f) ) @@ -370,7 +365,7 @@ private fun EpisodeWatchesHeader(onSweepWatchesClick: () -> Unit) { modifier = Modifier.padding(end = 4.dp), onClick = { onSweepWatchesClick() } ) { - Icon(asset = Icons.Default.DeleteSweep) + Icon(vectorResource(R.drawable.ic_delete_sweep)) } } } @@ -395,14 +390,14 @@ private fun EpisodeWatch(episodeWatchEntry: EpisodeWatchEntry) { ProvideEmphasis(emphasis = EmphasisAmbient.current.medium) { if (episodeWatchEntry.pendingAction != PendingAction.NOTHING) { Icon( - asset = Icons.Filled.Publish, + asset = vectorResource(R.drawable.ic_publish), modifier = Modifier.padding(start = 8.dp).gravity(Alignment.CenterVertically) ) } if (episodeWatchEntry.pendingAction == PendingAction.DELETE) { Icon( - asset = Icons.Filled.VisibilityOff, + asset = vectorResource(R.drawable.ic_visibility_off), modifier = Modifier.padding(start = 8.dp).gravity(Alignment.CenterVertically) ) } diff --git a/ui-showdetails/build.gradle b/ui-showdetails/build.gradle index 430b4b6164..1a4949bfef 100644 --- a/ui-showdetails/build.gradle +++ b/ui-showdetails/build.gradle @@ -86,7 +86,6 @@ dependencies { implementation Libs.AndroidX.Compose.animation implementation Libs.AndroidX.Compose.tooling implementation Libs.AndroidX.Compose.livedata - implementation Libs.AndroidX.Compose.iconsExtended implementation Libs.Mdc.material implementation Libs.Mdc.composeThemeAdapter 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 39535df291..80e57ddcb4 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 @@ -65,14 +65,11 @@ import androidx.compose.material.Surface import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material.icons.filled.CloudUpload import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Star -import androidx.compose.material.icons.filled.Visibility -import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.runtime.Composable import androidx.compose.runtime.Providers import androidx.compose.runtime.Recomposer @@ -91,6 +88,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.ContextAmbient import androidx.compose.ui.platform.setContent import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp @@ -887,7 +885,7 @@ private fun EpisodeWithWatchesRow( var needSpacer = false if (hasPending) { Icon( - asset = Icons.Default.CloudUpload, + asset = vectorResource(R.drawable.ic_cloud_upload), modifier = Modifier.gravity(Alignment.CenterVertically) ) needSpacer = true @@ -898,8 +896,8 @@ private fun EpisodeWithWatchesRow( } Icon( asset = when { - onlyPendingDeletes -> Icons.Default.VisibilityOff - else -> Icons.Default.Visibility + onlyPendingDeletes -> vectorResource(R.drawable.ic_visibility_off) + else -> vectorResource(R.drawable.ic_visibility) }, modifier = Modifier.gravity(Alignment.CenterVertically) ) From ea2ee61c84e1e67c6f9e9befaf74a00473b8747b Mon Sep 17 00:00:00 2001 From: Chris Banes Date: Sat, 22 Aug 2020 11:48:38 +0100 Subject: [PATCH 2/3] Migrate to using loadVectorResource() vectorResource() will fetch and parse the vector on the main thread, so we want to avoid that as much as possible. --- .../app/tivi/common/compose/DeferredIcon.kt | 45 +++++++++++++++++++ .../java/app/tivi/common/compose/vector.kt | 19 ++++---- .../app/tivi/episodedetails/EpisodeDetails.kt | 35 +++++++++------ .../tivi/showdetails/details/ShowDetails.kt | 14 +++--- 4 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 common-ui-compose/src/main/java/app/tivi/common/compose/DeferredIcon.kt diff --git a/common-ui-compose/src/main/java/app/tivi/common/compose/DeferredIcon.kt b/common-ui-compose/src/main/java/app/tivi/common/compose/DeferredIcon.kt new file mode 100644 index 0000000000..5b60a1a891 --- /dev/null +++ b/common-ui-compose/src/main/java/app/tivi/common/compose/DeferredIcon.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2020 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.common.compose + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Icon +import androidx.compose.foundation.contentColor +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.DeferredResource +import androidx.compose.ui.res.loadVectorResource + +@Composable +fun IconResource( + @DrawableRes resourceId: Int, + modifier: Modifier = Modifier, + tint: Color = contentColor() +) { + val deferredResource = loadVectorResource(resourceId) + deferredResource.onLoadRun { asset -> + Icon(asset = asset, modifier = modifier, tint = tint) + } +} + +inline fun DeferredResource.onLoadRun(block: (T) -> Unit) { + val res = resource.resource + if (res != null) { + block(res) + } +} diff --git a/common-ui-compose/src/main/java/app/tivi/common/compose/vector.kt b/common-ui-compose/src/main/java/app/tivi/common/compose/vector.kt index 778725dda3..5179a51c72 100644 --- a/common-ui-compose/src/main/java/app/tivi/common/compose/vector.kt +++ b/common-ui-compose/src/main/java/app/tivi/common/compose/vector.kt @@ -30,7 +30,7 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.VectorAsset import androidx.compose.ui.graphics.vector.VectorPainter import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.res.loadVectorResource @Composable fun VectorImage( @@ -40,13 +40,16 @@ fun VectorImage( tintColor: Color = contentColor(), modifier: Modifier = Modifier.wrapContentSize(align = alignment) ) { - VectorImage( - vector = vectorResource(id = id), - alignment = alignment, - contentScale = contentScale, - tintColor = tintColor, - modifier = modifier - ) + val deferred = loadVectorResource(id) + deferred.onLoadRun { asset -> + VectorImage( + vector = asset, + alignment = alignment, + contentScale = contentScale, + tintColor = tintColor, + modifier = modifier + ) + } } @Composable 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 e5427d0da4..69b44c0331 100644 --- a/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt +++ b/ui-episodedetails/src/main/java/app/tivi/episodedetails/EpisodeDetails.kt @@ -75,14 +75,15 @@ import androidx.compose.ui.graphics.vector.VectorAsset import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.ConfigurationAmbient import androidx.compose.ui.platform.setContent +import androidx.compose.ui.res.loadVectorResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.Dp 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.ExpandingText +import app.tivi.common.compose.IconResource import app.tivi.common.compose.ProvideDisplayInsets import app.tivi.common.compose.SwipeDirection import app.tivi.common.compose.SwipeToDismiss @@ -91,6 +92,7 @@ import app.tivi.common.compose.TiviDateFormatterAmbient import app.tivi.common.compose.boundsInParent import app.tivi.common.compose.navigationBarsHeight import app.tivi.common.compose.navigationBarsPadding +import app.tivi.common.compose.onLoadRun import app.tivi.common.compose.onPositionInParentChanged import app.tivi.common.compose.rememberMutableState import app.tivi.data.entities.Episode @@ -312,11 +314,14 @@ private fun InfoPanes(episode: Episode) { episode.firstAired?.let { firstAired -> val formatter = TiviDateFormatterAmbient.current - InfoPane( - icon = vectorResource(R.drawable.ic_calendar_today), - label = formatter.formatShortRelativeTime(firstAired), - modifier = Modifier.weight(1f) - ) + val deferredIcon = loadVectorResource(id = R.drawable.ic_calendar_today) + deferredIcon.onLoadRun { asset -> + InfoPane( + icon = asset, + label = formatter.formatShortRelativeTime(firstAired), + modifier = Modifier.weight(1f) + ) + } } } } @@ -365,7 +370,7 @@ private fun EpisodeWatchesHeader(onSweepWatchesClick: () -> Unit) { modifier = Modifier.padding(end = 4.dp), onClick = { onSweepWatchesClick() } ) { - Icon(vectorResource(R.drawable.ic_delete_sweep)) + IconResource(R.drawable.ic_delete_sweep) } } } @@ -389,16 +394,20 @@ private fun EpisodeWatch(episodeWatchEntry: EpisodeWatchEntry) { ProvideEmphasis(emphasis = EmphasisAmbient.current.medium) { if (episodeWatchEntry.pendingAction != PendingAction.NOTHING) { - Icon( - asset = vectorResource(R.drawable.ic_publish), - modifier = Modifier.padding(start = 8.dp).gravity(Alignment.CenterVertically) + IconResource( + resourceId = R.drawable.ic_publish, + modifier = Modifier + .padding(start = 8.dp) + .gravity(Alignment.CenterVertically) ) } if (episodeWatchEntry.pendingAction == PendingAction.DELETE) { - Icon( - asset = vectorResource(R.drawable.ic_visibility_off), - modifier = Modifier.padding(start = 8.dp).gravity(Alignment.CenterVertically) + IconResource( + resourceId = R.drawable.ic_visibility_off, + modifier = Modifier + .padding(start = 8.dp) + .gravity(Alignment.CenterVertically) ) } } 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 80e57ddcb4..dc81661586 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 @@ -88,7 +88,6 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.ContextAmbient import androidx.compose.ui.platform.setContent import androidx.compose.ui.res.stringResource -import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp @@ -97,6 +96,7 @@ import androidx.ui.tooling.preview.Preview import app.tivi.common.compose.AutoSizedCircularProgressIndicator import app.tivi.common.compose.ExpandableFloatingActionButton import app.tivi.common.compose.ExpandingText +import app.tivi.common.compose.IconResource import app.tivi.common.compose.InsetsAmbient import app.tivi.common.compose.LogCompositions import app.tivi.common.compose.PopupMenu @@ -884,8 +884,8 @@ private fun EpisodeWithWatchesRow( ProvideEmphasis(EmphasisAmbient.current.medium) { var needSpacer = false if (hasPending) { - Icon( - asset = vectorResource(R.drawable.ic_cloud_upload), + IconResource( + resourceId = R.drawable.ic_cloud_upload, modifier = Modifier.gravity(Alignment.CenterVertically) ) needSpacer = true @@ -894,10 +894,10 @@ private fun EpisodeWithWatchesRow( if (needSpacer) { Spacer(Modifier.preferredWidth(4.dp)) } - Icon( - asset = when { - onlyPendingDeletes -> vectorResource(R.drawable.ic_visibility_off) - else -> vectorResource(R.drawable.ic_visibility) + IconResource( + resourceId = when { + onlyPendingDeletes -> R.drawable.ic_visibility_off + else -> R.drawable.ic_visibility }, modifier = Modifier.gravity(Alignment.CenterVertically) ) From 1f30074c491be6d648ff86a61d7153ffcbd78012 Mon Sep 17 00:00:00 2001 From: Chris Banes Date: Sat, 22 Aug 2020 11:53:13 +0100 Subject: [PATCH 3/3] Fux duplicated project dependency --- ui-episodedetails/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-episodedetails/build.gradle b/ui-episodedetails/build.gradle index 17c49e17f1..b73cc362e7 100644 --- a/ui-episodedetails/build.gradle +++ b/ui-episodedetails/build.gradle @@ -63,7 +63,6 @@ dependencies { implementation project(':base-android') implementation project(':domain') implementation project(':common-ui-view') - implementation project(':common-ui-view') implementation project(':common-ui-compose') implementation Libs.AndroidX.Lifecycle.livedata