diff --git a/PennMobile/build.gradle b/PennMobile/build.gradle index c3d8d1e7e..55a05d865 100644 --- a/PennMobile/build.gradle +++ b/PennMobile/build.gradle @@ -76,6 +76,7 @@ dependencies { // If you want the foundation layout, use the bundle or the specific activity compose you have defined implementation libs.androidx.activity.compose implementation libs.androidx.material3.android + implementation libs.androidx.compose.ui.tooling.preview // implementation libs.androidx.foundation.layout ktlintRuleset libs.ktlint @@ -137,6 +138,7 @@ dependencies { implementation libs.bundles.ui implementation libs.bundles.google implementation libs.bundles.hilt + debugImplementation libs.androidx.compose.ui.tooling ksp libs.androidx.room.compiler ksp libs.androidx.hilt.compiler @@ -146,6 +148,8 @@ dependencies { implementation libs.androidx.hilt.android ksp libs.androidx.hilt.compiler + + implementation libs.coil.compose } String getPlatformClientID() { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/adapters/HomeAdapter.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/adapters/HomeAdapter.kt index 643113cb9..0b9ffca90 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/adapters/HomeAdapter.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/adapters/HomeAdapter.kt @@ -18,6 +18,7 @@ import androidx.browser.customtabs.CustomTabsClient import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsServiceConnection import androidx.browser.customtabs.CustomTabsSession +import androidx.compose.ui.platform.ComposeView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat.getColor import androidx.core.content.ContextCompat.startActivity @@ -53,6 +54,7 @@ import com.pennapps.labs.pennmobile.home.classes.CalendarCell import com.pennapps.labs.pennmobile.home.classes.CalendarEvent import com.pennapps.labs.pennmobile.home.classes.HomepageDataModel import com.pennapps.labs.pennmobile.home.classes.NewsCell +import com.pennapps.labs.pennmobile.home.classes.NewsComposableComponent import com.pennapps.labs.pennmobile.home.classes.Poll import com.pennapps.labs.pennmobile.home.classes.PollCell import com.pennapps.labs.pennmobile.home.classes.Post @@ -583,149 +585,10 @@ class HomeAdapter( ) { val article = cell.article - if (article.imageUrl.isNullOrEmpty()) { - holder.itemView.visibility = View.GONE - holder.newsCardContainer.visibility = View.GONE - holder.homeNewsImageView.setImageDrawable(null) - holder.homeNewsTitle.text = "" - holder.homeNewsSubtitle.text = "" - holder.homeNewsTimestamp.text = "" - dataModel.notifyNewsBlurLoaded() - return - } - - holder.homeNewsTitle.text = article.title - holder.homeNewsSubtitle.text = article.subtitle - - holder.homeNewsTimestamp.text = article.timestamp?.trim() - - Glide - .with(mContext) - .load(article.imageUrl) - .fitCenter() - .centerCrop() - .into(holder.homeNewsImageView) - -// /** Adds dynamically generated accent color from the fetched image to the news card */ - var accentColor: Int = getColor(mContext, R.color.black) - mActivity.lifecycleScope.launch(Dispatchers.Default) { - Log.d("HomeAdapter", "Image Url is ${article.imageUrl}") - val bitmap = - withContext(Dispatchers.IO) { - Glide - .with(mContext) - .load(article.imageUrl) - .submit() - .get() - }.toBitmap() - - // Create palette from bitmap - fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate() - val vibrantSwatch: Palette.Swatch? = createPaletteSync(bitmap).darkVibrantSwatch - vibrantSwatch?.rgb?.let { accentColor = it } - - mActivity.runOnUiThread { - // Change all the components to match the accent color palette - vibrantSwatch?.titleTextColor?.let { - DrawableCompat.setTint( - DrawableCompat.wrap(holder.newsCardLogo.drawable), - ColorUtils.setAlphaComponent(it, 150), - ) - DrawableCompat.setTint( - DrawableCompat.wrap(holder.newsInfoIcon.drawable), - it, - ) - DrawableCompat.setTint( - DrawableCompat.wrap(holder.dotDivider.drawable), - it, - ) - holder.newsButton.setTextColor(ColorUtils.setAlphaComponent(it, 150)) - DrawableCompat.setTint( - DrawableCompat.wrap(holder.newsButton.background), - it, - ) - holder.homeNewsTitle.setTextColor( - ColorUtils.setAlphaComponent( - it, - 150, - ), - ) - holder.homeNewsSubtitle.setTextColor(it) - holder.homeNewsTimestamp.setTextColor(it) - } - holder.newsCardContainer.background = - BitmapDrawable( - holder.itemBinding.root.resources, - bitmap, - ) - holder.newsBlurView - .setOverlayColor(ColorUtils.setAlphaComponent(accentColor, 150)) - - // tell model that the news blur view has been loaded - dataModel.notifyNewsBlurLoaded() - } - } - - // Logic for the more info button on the news card - holder.newsInfoIcon.setOnClickListener { - when (holder.homeNewsSubtitle.visibility) { - View.GONE -> { - holder.homeNewsSubtitle.visibility = View.VISIBLE - holder.homeNewsTitle.setPadding(0, 0, 0, 0) - holder.newsBlurView - .setOverlayColor(ColorUtils.setAlphaComponent(accentColor, 250)) - } - - View.VISIBLE -> { - holder.homeNewsSubtitle.visibility = View.GONE - holder.homeNewsTitle.setPadding(0, 0, 0, convertToDp(mContext, 8f)) - holder.newsBlurView - .setOverlayColor(ColorUtils.setAlphaComponent(accentColor, 150)) - } - } - } - - // Sets up blur view on news card - holder.newsBlurView - .setupWith(holder.newsCardContainer, RenderScriptBlur(mContext)) - .setFrameClearDrawable(ColorDrawable(getColor(mContext, R.color.white))) - .setBlurRadius(25f) - - holder.newsButton.setOnClickListener { - val url = article?.articleUrl - - val connection = NewsCustomTabsServiceConnection() - builder = CustomTabsIntent.Builder() - share = Intent(Intent.ACTION_SEND) - share?.type = "text/plain" - builder?.setToolbarColor(0x3E50B4) - builder?.setStartAnimations( - mContext, - androidx.appcompat.R.anim.abc_popup_enter, - androidx.appcompat.R.anim.abc_popup_exit, - ) - CustomTabsClient.bindCustomTabsService( - mContext, - NewsFragment.CUSTOM_TAB_PACKAGE_NAME, - connection, - ) - - if (mContext.isChromeCustomTabsSupported()) { - share?.putExtra(Intent.EXTRA_TEXT, url) - builder?.addMenuItem( - "Share", - PendingIntent.getActivity( - mContext, - 0, - share, - PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE, - ), - ) - customTabsIntent = builder?.build() - customTabsIntent?.launchUrl(mActivity, Uri.parse(url)) - } else { - val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) - startActivity(mContext, browserIntent, null) + val composeView = holder.itemView.findViewById(R.id.news_compose_view) + composeView.apply { + setContent { + NewsComposableComponent(article) } } } diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/classes/NewsCompose.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/classes/NewsCompose.kt new file mode 100644 index 000000000..331a3ac5c --- /dev/null +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/classes/NewsCompose.kt @@ -0,0 +1,138 @@ +package com.pennapps.labs.pennmobile.home.classes + +import android.content.Context +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.blur +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em +import androidx.compose.ui.unit.sp +import coil.compose.rememberAsyncImagePainter + +@Composable +fun NewsComposableComponent( + article: Article, + modifier: Modifier = Modifier, +) { + val uriHandler = LocalUriHandler.current + var url = "https://www.thedp.com/" + article.articleUrl?.let { + url = article.articleUrl + } + + Column( + modifier = + Modifier + .fillMaxWidth() + .aspectRatio(1f) + .padding(16.dp) + .clip(RoundedCornerShape(16.dp)) + .clickable { uriHandler.openUri(url) }, + ) { + Box( + modifier = + Modifier + .weight(1f) + .fillMaxWidth(), + ) { + Image( + painter = rememberAsyncImagePainter(article.imageUrl), + contentDescription = "News Image", + contentScale = ContentScale.Crop, + modifier = + Modifier + .matchParentSize() + .fillMaxWidth() + .fillMaxHeight(), + ) + } + Box( + modifier = + Modifier + .fillMaxWidth(), + ) { + Image( + painter = rememberAsyncImagePainter(article.imageUrl), + contentDescription = "News Image", + contentScale = ContentScale.Crop, + alignment = Alignment.TopCenter, + modifier = + Modifier + .matchParentSize() + .blur(16.dp) + .fillMaxWidth(), + ) + Box( + modifier = + Modifier + .matchParentSize() + .background(Color.Black.copy(alpha = 0.5f)), + ) + Box( + modifier = + Modifier + .fillMaxWidth() + .padding(16.dp), + ) { + Column( + verticalArrangement = Arrangement.spacedBy(6.dp), + ) { + Row( + modifier = Modifier.fillMaxWidth(), + ) { + Text(text = " THE DAILY PENNSYLVANIAN", color = Color.LightGray) + Spacer(Modifier.weight(1f)) + + var time = "1 hour ago" + article.timestamp?.let { + time = article.timestamp + } + Text(time, color = Color.LightGray) + } + + var title = "sample title here" + article.title?.let { + title = article.title + } + + Text( + text = title, + color = Color.White, + fontWeight = FontWeight.Bold, + fontSize = 16.sp, + lineHeight = 1.25.em, + ) + + var description = "sample description here" + article.subtitle?.let { + description = article.subtitle + } + Text(text = description, color = Color.White, lineHeight = 1.15.em) + } + } + } + } +} diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/viewholders/HomeNewsCardHolder.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/viewholders/HomeNewsCardHolder.kt index 8a500c43c..5946cfedf 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/viewholders/HomeNewsCardHolder.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/home/viewholders/HomeNewsCardHolder.kt @@ -5,15 +5,4 @@ import com.pennapps.labs.pennmobile.databinding.HomeNewsCardBinding class HomeNewsCardHolder( val itemBinding: HomeNewsCardBinding, -) : RecyclerView.ViewHolder(itemBinding.root) { - var homeNewsTitle = itemBinding.homeNewsTitle - var homeNewsSubtitle = itemBinding.homeNewsSubtitle - var homeNewsTimestamp = itemBinding.homeNewsTimestamp - var homeNewsImageView = itemBinding.homeNewsIv - var newsCardLogo = itemBinding.newsCardLogo - var newsInfoIcon = itemBinding.newsInfoIcon - var newsBlurView = itemBinding.blurView - var newsCardContainer = itemBinding.newsCardContainer - var newsButton = itemBinding.button - var dotDivider = itemBinding.dotDivider -} +) : RecyclerView.ViewHolder(itemBinding.root) diff --git a/PennMobile/src/main/res/layout/home_news_card.xml b/PennMobile/src/main/res/layout/home_news_card.xml index 60df85168..74de0ae52 100644 --- a/PennMobile/src/main/res/layout/home_news_card.xml +++ b/PennMobile/src/main/res/layout/home_news_card.xml @@ -1,160 +1,16 @@ + android:layout_height="wrap_content"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" /> - - \ No newline at end of file + diff --git a/PennMobile/src/main/res/layout/news_card_compose_view.xml b/PennMobile/src/main/res/layout/news_card_compose_view.xml new file mode 100644 index 000000000..74de0ae52 --- /dev/null +++ b/PennMobile/src/main/res/layout/news_card_compose_view.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 01c66468b..2da54f6c0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -63,6 +63,9 @@ rxandroidVersion = "1.2.1" rxjava1 = "1.3.8" rxJavaCoroutineConverter = "1.8.0" testng = "7.8.0" +uiToolingPreview = "1.10.2" +uiTooling = "1.10.2" +coil = "2.6.0" ktlint = "14.0.1" @@ -141,7 +144,9 @@ reactivex-rxandroid = { module = "io.reactivex:rxandroid", version.ref = "rxandr retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } rxjava = { module = "io.reactivex:rxjava", version.ref = "rxjava1" } testng = { module = "org.testng:testng", version.ref = "testng" } - +androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview", version.ref = "uiToolingPreview" } +androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "uiTooling" } +coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }