diff --git a/core/network/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/network/ApplicationComponent.kt b/core/network/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/network/ApplicationComponent.kt new file mode 100644 index 000000000..f288f5b63 --- /dev/null +++ b/core/network/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/network/ApplicationComponent.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid.core.network + +import android.content.Context +import me.tatarka.inject.annotations.Component +import me.tatarka.inject.annotations.Provides + +@Component +abstract class ApplicationComponent ( + @get:Provides val context: Context, +): PlatformComponent + +interface ApplicationComponentProvider { + val component: ApplicationComponent +} + +val Context.applicationComponent get() = (applicationContext as ApplicationComponentProvider).component \ No newline at end of file diff --git a/core/network/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/network/PlatformComponent.kt b/core/network/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/network/PlatformComponent.kt new file mode 100644 index 000000000..e2a0681fa --- /dev/null +++ b/core/network/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/network/PlatformComponent.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid.core.network + +import android.content.Context +import coil3.PlatformContext +import me.tatarka.inject.annotations.Provides + +interface PlatformComponent { + @Provides + fun providePlatformContext(context: Context): PlatformContext = context +} \ No newline at end of file diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index 084700bf2..034bf97a2 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -14,8 +14,8 @@ * limitations under the License. */ plugins { - alias(libs.plugins.nowinandroid.android.library) - alias(libs.plugins.nowinandroid.android.library.compose) + alias(libs.plugins.nowinandroid.kmp.library) + alias(libs.plugins.jetbrains.compose) alias(libs.plugins.nowinandroid.android.library.jacoco) } @@ -26,15 +26,24 @@ android { namespace = "com.google.samples.apps.nowinandroid.core.ui" } -dependencies { - api(libs.androidx.metrics) - api(projects.core.analytics) - api(projects.core.designsystem) - api(projects.core.model) - - implementation(libs.androidx.browser) - implementation(libs.coil) - implementation(libs.coil.compose) - - androidTestImplementation(projects.core.testing) +kotlin { + sourceSets { + androidMain.dependencies { + api(libs.androidx.metrics) + implementation(libs.androidx.browser) + } + commonMain.dependencies { + api(projects.core.analytics) + api(projects.core.designsystem) + api(projects.core.model) + implementation(libs.coil) + implementation(libs.coil.compose) + implementation(compose.material3) + implementation(compose.components.resources) + implementation(compose.components.uiToolingPreview) + } + androidInstrumentedTest.dependencies { + implementation(projects.core.testing) + } + } } diff --git a/core/ui/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt b/core/ui/src/androidInstrumentedTest/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt similarity index 96% rename from core/ui/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt rename to core/ui/src/androidInstrumentedTest/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt index d0a124316..64ce05957 100644 --- a/core/ui/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt +++ b/core/ui/src/androidInstrumentedTest/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardTest.kt @@ -24,6 +24,8 @@ import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import com.google.samples.apps.nowinandroid.core.testing.data.followableTopicTestData import com.google.samples.apps.nowinandroid.core.testing.data.userNewsResourcesTestData +import nowinandroid.core.ui.generated.resources.Res +import nowinandroid.core.ui.generated.resources.core_ui_card_meta_data_text import org.junit.Rule import org.junit.Test @@ -52,7 +54,7 @@ class NewsResourceCardTest { composeTestRule .onNodeWithText( composeTestRule.activity.getString( - R.string.core_ui_card_meta_data_text, + Res.string.core_ui_card_meta_data_text, dateFormatted, newsWithKnownResourceType.type, ), diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt b/core/ui/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt similarity index 100% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt rename to core/ui/src/androidMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/commonMain/composeResources/values/strings.xml similarity index 100% rename from core/ui/src/main/res/values/strings.xml rename to core/ui/src/commonMain/composeResources/values/strings.xml diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/AnalyticsExtensions.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/AnalyticsExtensions.kt similarity index 100% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/AnalyticsExtensions.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/AnalyticsExtensions.kt diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/DevicePreviews.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/DevicePreviews.kt similarity index 65% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/DevicePreviews.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/DevicePreviews.kt index bb2b59466..2e29d6886 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/DevicePreviews.kt +++ b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/DevicePreviews.kt @@ -16,14 +16,15 @@ package com.google.samples.apps.nowinandroid.core.ui -import androidx.compose.ui.tooling.preview.Preview +import org.jetbrains.compose.ui.tooling.preview.Preview /** * Multipreview annotation that represents various device sizes. Add this annotation to a composable * to render various devices. */ -@Preview(name = "phone", device = "spec:shape=Normal,width=360,height=640,unit=dp,dpi=480") -@Preview(name = "landscape", device = "spec:shape=Normal,width=640,height=360,unit=dp,dpi=480") -@Preview(name = "foldable", device = "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480") -@Preview(name = "tablet", device = "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=480") +//@Preview(name = "phone", device = "spec:shape=Normal,width=360,height=640,unit=dp,dpi=480") +//@Preview(name = "landscape", device = "spec:shape=Normal,width=640,height=360,unit=dp,dpi=480") +//@Preview(name = "foldable", device = "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480") +//@Preview(name = "tablet", device = "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=480") +@Preview annotation class DevicePreviews diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/FollowableTopicPreviewParameterProvider.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/FollowableTopicPreviewParameterProvider.kt similarity index 98% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/FollowableTopicPreviewParameterProvider.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/FollowableTopicPreviewParameterProvider.kt index 16ae1eced..2ae812dfd 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/FollowableTopicPreviewParameterProvider.kt +++ b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/FollowableTopicPreviewParameterProvider.kt @@ -18,9 +18,9 @@ package com.google.samples.apps.nowinandroid.core.ui -import androidx.compose.ui.tooling.preview.PreviewParameterProvider import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.Topic +import org.jetbrains.compose.ui.tooling.preview.PreviewParameterProvider /** * This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider) diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/LocalTimeZone.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/LocalTimeZone.kt similarity index 100% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/LocalTimeZone.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/LocalTimeZone.kt diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt similarity index 80% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt index afdb584a2..474226f09 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt +++ b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsFeed.kt @@ -16,11 +16,6 @@ package com.google.samples.apps.nowinandroid.core.ui -import android.content.Context -import android.net.Uri -import androidx.annotation.ColorInt -import androidx.browser.customtabs.CustomTabColorSchemeParams -import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListScope @@ -28,18 +23,14 @@ import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridScope import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells import androidx.compose.foundation.lazy.staggeredgrid.items -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.tooling.preview.Devices -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import com.google.samples.apps.nowinandroid.core.analytics.LocalAnalyticsHelper import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.compose.ui.tooling.preview.PreviewParameter /** * An extension on [LazyListScope] defining a feed with news resources. @@ -61,10 +52,7 @@ fun LazyStaggeredGridScope.newsFeed( key = { it.id }, contentType = { "newsFeedItem" }, ) { userNewsResource -> - val context = LocalContext.current val analyticsHelper = LocalAnalyticsHelper.current - val backgroundColor = MaterialTheme.colorScheme.background.toArgb() - NewsResourceCardExpanded( userNewsResource = userNewsResource, isBookmarked = userNewsResource.isSaved, @@ -73,7 +61,7 @@ fun LazyStaggeredGridScope.newsFeed( analyticsHelper.logNewsResourceOpened( newsResourceId = userNewsResource.id, ) - launchCustomChromeTab(context, Uri.parse(userNewsResource.url), backgroundColor) + launchCustomChromeTab(userNewsResource.url) onNewsResourceViewed(userNewsResource.id) }, @@ -94,14 +82,8 @@ fun LazyStaggeredGridScope.newsFeed( } } -fun launchCustomChromeTab(context: Context, uri: Uri, @ColorInt toolbarColor: Int) { - val customTabBarColor = CustomTabColorSchemeParams.Builder() - .setToolbarColor(toolbarColor).build() - val customTabsIntent = CustomTabsIntent.Builder() - .setDefaultColorSchemeParams(customTabBarColor) - .build() - - customTabsIntent.launchUrl(context, uri) +fun launchCustomChromeTab(uri: String) { + // Empty implementation } /** @@ -140,7 +122,7 @@ private fun NewsFeedLoadingPreview() { } @Preview -@Preview(device = Devices.TABLET) +//@Preview(device = Devices.TABLET) @Composable private fun NewsFeedContentPreview( @PreviewParameter(UserNewsResourcePreviewParameterProvider::class) diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt similarity index 82% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt index e60c498eb..1641fafc5 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt +++ b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(ExperimentalResourceApi::class) + package com.google.samples.apps.nowinandroid.core.ui import androidx.compose.foundation.Canvas @@ -48,17 +50,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.unit.dp -import coil.compose.AsyncImagePainter -import coil.compose.rememberAsyncImagePainter -import com.google.samples.apps.nowinandroid.core.designsystem.R.drawable +import coil3.ImageLoader +import coil3.PlatformContext +import coil3.compose.AsyncImagePainter +import coil3.compose.rememberAsyncImagePainter import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaIconToggleButton import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopicTag import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons @@ -67,16 +67,22 @@ import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import kotlinx.datetime.Instant -import kotlinx.datetime.toJavaInstant -import kotlinx.datetime.toJavaZoneId -import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle -import java.util.Locale +import nowinandroid.core.ui.generated.resources.Res +import nowinandroid.core.ui.generated.resources.core_ui_bookmark +import nowinandroid.core.ui.generated.resources.core_ui_card_meta_data_text +import nowinandroid.core.ui.generated.resources.core_ui_card_tap_action +import nowinandroid.core.ui.generated.resources.core_ui_topic_chip_content_description_when_followed +import nowinandroid.core.ui.generated.resources.core_ui_topic_chip_content_description_when_not_followed +import nowinandroid.core.ui.generated.resources.core_ui_unbookmark +import nowinandroid.core.ui.generated.resources.core_ui_unread_resource_dot_content_description +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.compose.ui.tooling.preview.PreviewParameter /** * [NewsResource] card used on the following screens: For You, Saved */ - @Composable fun NewsResourceCardExpanded( userNewsResource: UserNewsResource, @@ -87,7 +93,7 @@ fun NewsResourceCardExpanded( onTopicClick: (String) -> Unit, modifier: Modifier = Modifier, ) { - val clickActionLabel = stringResource(R.string.core_ui_card_tap_action) + val clickActionLabel = stringResource(Res.string.core_ui_card_tap_action) Card( onClick = onClick, shape = RoundedCornerShape(16.dp), @@ -147,12 +153,13 @@ fun NewsResourceHeaderImage( ) { var isLoading by remember { mutableStateOf(true) } var isError by remember { mutableStateOf(false) } - val imageLoader = rememberAsyncImagePainter( + val imagePainter = rememberAsyncImagePainter( model = headerImageUrl, onState = { state -> isLoading = state is AsyncImagePainter.State.Loading isError = state is AsyncImagePainter.State.Error }, + imageLoader = imageLoader, ) val isLocalInspection = LocalInspectionMode.current Box( @@ -176,11 +183,12 @@ fun NewsResourceHeaderImage( .fillMaxWidth() .height(180.dp), contentScale = ContentScale.Crop, - painter = if (isError.not() && !isLocalInspection) { - imageLoader - } else { - painterResource(drawable.core_designsystem_ic_placeholder_default) - }, + painter = +// if (isError.not() && !isLocalInspection) { + imagePainter, +// } else { +// painterResource(drawable.core_designsystem_ic_placeholder_default) +// }, // TODO b/226661685: Investigate using alt text of image to populate content description // decorative image, contentDescription = null, @@ -209,13 +217,13 @@ fun BookmarkButton( icon = { Icon( imageVector = NiaIcons.BookmarkBorder, - contentDescription = stringResource(R.string.core_ui_bookmark), + contentDescription = stringResource(Res.string.core_ui_bookmark), ) }, checkedIcon = { Icon( imageVector = NiaIcons.Bookmark, - contentDescription = stringResource(R.string.core_ui_unbookmark), + contentDescription = stringResource(Res.string.core_ui_unbookmark), ) }, ) @@ -226,7 +234,7 @@ fun NotificationDot( color: Color, modifier: Modifier = Modifier, ) { - val description = stringResource(R.string.core_ui_unread_resource_dot_content_description) + val description = stringResource(Res.string.core_ui_unread_resource_dot_content_description) Canvas( modifier = modifier .semantics { contentDescription = description }, @@ -240,11 +248,7 @@ fun NotificationDot( } @Composable -fun dateFormatted(publishDate: Instant): String = DateTimeFormatter - .ofLocalizedDate(FormatStyle.MEDIUM) - .withLocale(Locale.getDefault()) - .withZone(LocalTimeZone.current.toJavaZoneId()) - .format(publishDate.toJavaInstant()) +fun dateFormatted(publishDate: Instant): String = publishDate.toString() @Composable fun NewsResourceMetaData( @@ -254,7 +258,7 @@ fun NewsResourceMetaData( val formattedDate = dateFormatted(publishDate) Text( if (resourceType.isNotBlank()) { - stringResource(R.string.core_ui_card_meta_data_text, formattedDate, resourceType) + stringResource(Res.string.core_ui_card_meta_data_text, formattedDate, resourceType) } else { formattedDate }, @@ -287,17 +291,17 @@ fun NewsResourceTopics( text = { val contentDescription = if (followableTopic.isFollowed) { stringResource( - R.string.core_ui_topic_chip_content_description_when_followed, + Res.string.core_ui_topic_chip_content_description_when_followed, followableTopic.topic.name, ) } else { stringResource( - R.string.core_ui_topic_chip_content_description_when_not_followed, + Res.string.core_ui_topic_chip_content_description_when_not_followed, followableTopic.topic.name, ) } Text( - text = followableTopic.topic.name.uppercase(Locale.getDefault()), + text = followableTopic.topic.name.uppercase(), modifier = Modifier.semantics { this.contentDescription = contentDescription }, @@ -308,7 +312,8 @@ fun NewsResourceTopics( } } -@Preview("Bookmark Button") +//@Preview("Bookmark Button") +@Preview @Composable private fun BookmarkButtonPreview() { NiaTheme { @@ -318,7 +323,8 @@ private fun BookmarkButtonPreview() { } } -@Preview("Bookmark Button Bookmarked") +//@Preview("Bookmark Button Bookmarked") +@Preview @Composable private fun BookmarkButtonBookmarkedPreview() { NiaTheme { @@ -328,7 +334,8 @@ private fun BookmarkButtonBookmarkedPreview() { } } -@Preview("NewsResourceCardExpanded") +@Preview +//@Preview("NewsResourceCardExpanded") @Composable private fun ExpandedNewsResourcePreview( @PreviewParameter(UserNewsResourcePreviewParameterProvider::class) diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt similarity index 97% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt index ea1c09d01..2074499d2 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt +++ b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCardList.kt @@ -16,13 +16,11 @@ package com.google.samples.apps.nowinandroid.core.ui -import android.net.Uri import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items import androidx.compose.material3.MaterialTheme import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext import com.google.samples.apps.nowinandroid.core.analytics.LocalAnalyticsHelper import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/UserNewsResourcePreviewParameterProvider.kt b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/UserNewsResourcePreviewParameterProvider.kt similarity index 99% rename from core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/UserNewsResourcePreviewParameterProvider.kt rename to core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/UserNewsResourcePreviewParameterProvider.kt index 3189e8403..074f522d5 100644 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/UserNewsResourcePreviewParameterProvider.kt +++ b/core/ui/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/ui/UserNewsResourcePreviewParameterProvider.kt @@ -18,7 +18,6 @@ package com.google.samples.apps.nowinandroid.core.ui -import androidx.compose.ui.tooling.preview.PreviewParameterProvider import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig import com.google.samples.apps.nowinandroid.core.model.data.NewsResource import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand @@ -30,6 +29,7 @@ import kotlinx.datetime.Instant import kotlinx.datetime.LocalDateTime import kotlinx.datetime.TimeZone import kotlinx.datetime.toInstant +import org.jetbrains.compose.ui.tooling.preview.PreviewParameterProvider /** * This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider) diff --git a/core/ui/src/main/AndroidManifest.xml b/core/ui/src/main/AndroidManifest.xml deleted file mode 100644 index 51d0cfc2e..000000000 --- a/core/ui/src/main/AndroidManifest.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - \ No newline at end of file diff --git a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/InterestsItem.kt b/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/InterestsItem.kt deleted file mode 100644 index 28cd8d938..000000000 --- a/core/ui/src/main/kotlin/com/google/samples/apps/nowinandroid/core/ui/InterestsItem.kt +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.samples.apps.nowinandroid.core.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Icon -import androidx.compose.material3.ListItem -import androidx.compose.material3.ListItemDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.selected -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.google.samples.apps.nowinandroid.core.designsystem.component.DynamicAsyncImage -import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaIconToggleButton -import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons -import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme -import com.google.samples.apps.nowinandroid.core.ui.R.string - -@Composable -fun InterestsItem( - name: String, - following: Boolean, - topicImageUrl: String, - onClick: () -> Unit, - onFollowButtonClick: (Boolean) -> Unit, - modifier: Modifier = Modifier, - iconModifier: Modifier = Modifier, - description: String = "", - isSelected: Boolean = false, -) { - ListItem( - leadingContent = { - InterestsIcon(topicImageUrl, iconModifier.size(64.dp)) - }, - headlineContent = { - Text(text = name) - }, - supportingContent = { - Text(text = description) - }, - trailingContent = { - NiaIconToggleButton( - checked = following, - onCheckedChange = onFollowButtonClick, - icon = { - Icon( - imageVector = NiaIcons.Add, - contentDescription = stringResource( - id = string.core_ui_interests_card_follow_button_content_desc, - ), - ) - }, - checkedIcon = { - Icon( - imageVector = NiaIcons.Check, - contentDescription = stringResource( - id = string.core_ui_interests_card_unfollow_button_content_desc, - ), - ) - }, - ) - }, - colors = ListItemDefaults.colors( - containerColor = if (isSelected) { - MaterialTheme.colorScheme.surfaceVariant - } else { - Color.Transparent - }, - ), - modifier = modifier - .semantics(mergeDescendants = true) { - selected = isSelected - } - .clickable(enabled = true, onClick = onClick), - ) -} - -@Composable -private fun InterestsIcon(topicImageUrl: String, modifier: Modifier = Modifier) { - if (topicImageUrl.isEmpty()) { - Icon( - modifier = modifier - .background(MaterialTheme.colorScheme.surface) - .padding(4.dp), - imageVector = NiaIcons.Person, - // decorative image - contentDescription = null, - ) - } else { - DynamicAsyncImage( - imageUrl = topicImageUrl, - contentDescription = null, - modifier = modifier, - ) - } -} - -@Preview -@Composable -private fun InterestsCardPreview() { - NiaTheme { - Surface { - InterestsItem( - name = "Compose", - description = "Description", - following = false, - topicImageUrl = "", - onClick = { }, - onFollowButtonClick = { }, - ) - } - } -} - -@Preview -@Composable -private fun InterestsCardLongNamePreview() { - NiaTheme { - Surface { - InterestsItem( - name = "This is a very very very very long name", - description = "Description", - following = true, - topicImageUrl = "", - onClick = { }, - onFollowButtonClick = { }, - ) - } - } -} - -@Preview -@Composable -private fun InterestsCardLongDescriptionPreview() { - NiaTheme { - Surface { - InterestsItem( - name = "Compose", - description = "This is a very very very very very very very " + - "very very very long description", - following = false, - topicImageUrl = "", - onClick = { }, - onFollowButtonClick = { }, - ) - } - } -} - -@Preview -@Composable -private fun InterestsCardWithEmptyDescriptionPreview() { - NiaTheme { - Surface { - InterestsItem( - name = "Compose", - description = "", - following = true, - topicImageUrl = "", - onClick = { }, - onFollowButtonClick = { }, - ) - } - } -} - -@Preview -@Composable -private fun InterestsCardSelectedPreview() { - NiaTheme { - Surface { - InterestsItem( - name = "Compose", - description = "", - following = true, - topicImageUrl = "", - onClick = { }, - onFollowButtonClick = { }, - isSelected = true, - ) - } - } -}