From d550e276e64bff95d0d65c819fefbff34386ffec Mon Sep 17 00:00:00 2001 From: "Jordan Akinpelu (akinpelud)" Date: Tue, 21 Jun 2022 02:31:56 +0100 Subject: [PATCH] Home RSS COmplete --- PowerOf10/app/build.gradle | 3 + .../java/com/example/powerof10/HomeRSS.kt | 179 ++++++++++++------ .../java/com/example/powerof10/NavGraph.kt | 4 +- .../java/com/example/powerof10/RankingPage.kt | 137 ++++++++++++-- 4 files changed, 251 insertions(+), 72 deletions(-) diff --git a/PowerOf10/app/build.gradle b/PowerOf10/app/build.gradle index d819c0c..252282f 100644 --- a/PowerOf10/app/build.gradle +++ b/PowerOf10/app/build.gradle @@ -53,6 +53,9 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9") implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" + implementation 'com.google.android.material:material:1.5.0' + implementation("androidx.compose.material3:material3:1.0.0-alpha13") + implementation("androidx.compose.material3:material3-window-size-class:1.0.0-alpha13") implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' implementation 'androidx.activity:activity-compose:1.3.1' diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt b/PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt index ae845c8..fcfe1f1 100644 --- a/PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt +++ b/PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt @@ -1,7 +1,7 @@ package com.example.powerof10 -import android.annotation.SuppressLint -import android.os.AsyncTask +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity @@ -12,33 +12,33 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.ViewModel import coil.compose.AsyncImage -import com.example.powerof10.Common.HTTPDataHandler -import com.example.powerof10.Model.RSSObject import com.example.powerof10.ui.theme.PowerOf10Theme -import com.google.gson.Gson import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers.IO import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element -import org.jsoup.select.Elements import tw.ktrssreader.Reader import tw.ktrssreader.kotlin.model.channel.RssStandardChannelData -import tw.ktrssreader.kotlin.model.item.RssStandardItemData + class HomeRSS : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -56,66 +56,114 @@ class HomeRSS : ComponentActivity() { } } } -@Composable -fun test(){ - displayRSS() -} -class RSSLogic : ViewModel() { - var rss = 0 - val RSS_link = "https://athleticsweekly.com/feed/" - val RSS_toJsonAPI = "https://api.rss2json.com/v1/api.json?rss_url=" - val rssSource = RSS_toJsonAPI+RSS_link - - suspend fun assignresult(): RssStandardChannelData { - return withContext(IO){ val result = Reader.coRead(RSS_link) - println(extractP(result.items?.get(0)?.description)) - Log.d("KtRssReader", result.items?.get(0)?.source.toString()) - return@withContext result +class RSSLogic : ViewModel() { + private val rSSLink = "https://athleticsweekly.com/feed/" + // val RSS_toJsonAPI = "https://api.rss2json.com/v1/api.json?rss_url=" + + //Returns and parses the RSS feed using the KTRSSReader library + //Does this using the IO dispatcher thread + suspend fun assignResult(): RssStandardChannelData { + return withContext(IO) { + return@withContext Reader.coRead(rSSLink) } } } -fun extractP(description: String?):String{ +//Extracts the description in the "

" tag from the RSS " tag" +fun extractP(description: String?): String { val doc: Document = Jsoup.parse(description) - val p : Element = doc.select("p").first() + val p: Element = doc.select("p").first() return p.text() +} + +//Extracts the image source src attribute within the "" tag from the RSS " tag" +fun extractImg(description: String?): String { + val doc: Document = Jsoup.parse(description) + val img = doc.select("img").first() + return img.attr("src") } -@Composable -fun displayRSS() { -var rssitem by remember { mutableStateOf(RssStandardChannelData(null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null)) } +@Preview(name = "NEXUS_7_2013", device = Devices.NEXUS_7_2013) +@Preview(name = "NEXUS_5", device = Devices.NEXUS_5) +@Preview(name = "NEXUS_6", device = Devices.NEXUS_6) +@Preview(name = "NEXUS_9", device = Devices.NEXUS_9) +@Preview(name = "NEXUS_10", device = Devices.NEXUS_10) +@Preview(name = "NEXUS_5X", device = Devices.NEXUS_5X) +@Preview(name = "NEXUS_6P", device = Devices.NEXUS_6P) +@Preview(name = "PIXEL_C", device = Devices.PIXEL_C) +@Preview(name = "PIXEL", device = Devices.PIXEL) +@Preview(name = "PIXEL_XL", device = Devices.PIXEL_XL) +@Preview(name = "PIXEL_2", device = Devices.PIXEL_2) +@Preview(name = "PIXEL_2_XL", device = Devices.PIXEL_2_XL) +@Preview(name = "PIXEL_3", device = Devices.PIXEL_3) +@Preview(name = "PIXEL_3_XL", device = Devices.PIXEL_3_XL) +@Preview(name = "PIXEL_3A", device = Devices.PIXEL_3A) +@Preview(name = "PIXEL_3A_XL", device = Devices.PIXEL_3A_XL) +@Preview(name = "PIXEL_4", device = Devices.PIXEL_4) +@Preview(name = "PIXEL_4_XL", device = Devices.PIXEL_4_XL) +@Composable +fun DisplayRssHomepage() { + var rssitem by remember {// If any changes are made to this variable the screen recomposes also stores the RSS Data + mutableStateOf( + RssStandardChannelData( + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ) + ) + } + var isRSSLoading by remember { mutableStateOf(true) } //the state of whether the rss data has loaded yet Log.d("test", "composed") LaunchedEffect(Unit) { - rssitem=RSSLogic().assignresult() - - Log.d("LE", "Launchd") + rssitem = RSSLogic().assignResult() //returns rss data as RssDataStandardData Object + isRSSLoading = false //disables loading circle } - //Log.d("test", newObject) + val powerOfTen = painterResource(id = R.drawable.powerof10) Column { - TopAppBar( + + CenterAlignedTopAppBar(modifier = Modifier.fillMaxWidth(), title = { Image( painter = powerOfTen, contentDescription = "Power of Ten Logo", - modifier = Modifier - .scale(1.1F) - .padding(20.dp, 0.dp, 0.dp, 0.dp) + modifier = Modifier, + contentScale = ContentScale.FillBounds ) }, - backgroundColor = Color(0xFFE5383B), - contentColor = Color.White, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + Color(0xFFE5383B), + navigationIconContentColor = Color.White + ), navigationIcon = { IconButton(onClick = { /* doSomething() */ }) { Icon( Icons.Filled.Menu, contentDescription = null, - modifier = Modifier.scale(1.2F) + tint = Color.White, + modifier = Modifier.size(48.dp) ) } } @@ -128,30 +176,49 @@ var rssitem by remember { mutableStateOf(RssStandardChannelData(null,null,null,n ) LazyColumn(content = { - rssitem.items?.let { + rssitem.items?.let { it -> items(it.size) { - rssItem(it, rssitem = rssitem) + RssItem(it, rssitem = rssitem) } } }) } + if (isRSSLoading) {// if the RSS hasn't loaded circular progress indicator will appear + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.fillMaxSize() + ) { + CircularProgressIndicator() + } + } } - +// The RSS item for the Lazy Column Composable (Recycler View) @Composable -private fun rssItem(index: Int, rssitem: RssStandardChannelData) { - Column() { - Box() { - AsyncImage( - model = rssitem.items?.get(index)?.source, +private fun RssItem(index: Int, rssitem: RssStandardChannelData) { + val mContext = LocalContext.current + Column(modifier = Modifier.clickable {// On click a browser intent is started to the link of the article + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(rssitem.items?.get(index)?.link)) + browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + mContext.startActivity(browserIntent) + }) { + Box{ + AsyncImage( //coil library composable that loads images from the the src url on another thread + model = extractImg(rssitem.items?.get(index)?.description), contentDescription = "Rss Image", - modifier = Modifier.fillMaxWidth() + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() ) - Text( - text = " " + (rssitem.items?.get(index)?.title), color = Color.White, maxLines = 1, overflow = TextOverflow.Ellipsis, fontSize = 24.sp, modifier = Modifier + Text(//Title + text = " " + (rssitem.items?.get(index)?.title), + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + fontSize = 24.sp, + modifier = Modifier .background( brush = Brush.verticalGradient( colors = listOf( @@ -167,15 +234,13 @@ private fun rssItem(index: Int, rssitem: RssStandardChannelData) { ) } - Text(text = " " + extractP(rssitem.items?.get(index)?.description), fontSize = 16.sp, modifier = Modifier) + Text( //description + text = " " + extractP(rssitem.items?.get(index)?.description), + fontSize = 16.sp, + modifier = Modifier + ) } } - -@Composable -fun DefaultPreview2() { - PowerOf10Theme { - } -} \ No newline at end of file diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/NavGraph.kt b/PowerOf10/app/src/main/java/com/example/powerof10/NavGraph.kt index 2a41e83..144ba5d 100644 --- a/PowerOf10/app/src/main/java/com/example/powerof10/NavGraph.kt +++ b/PowerOf10/app/src/main/java/com/example/powerof10/NavGraph.kt @@ -1,8 +1,6 @@ package com.example.powerof10 -import android.content.Intent import androidx.compose.runtime.Composable -import androidx.core.content.ContextCompat.startActivity import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -25,7 +23,7 @@ fun SetupNavGraph( route = Screen.HomepageRSS.route ){ - test() + DisplayRssHomepage() } } } \ No newline at end of file diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt b/PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt index 3af1fb6..1375150 100644 --- a/PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt +++ b/PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt @@ -1,15 +1,30 @@ package com.example.powerof10 import android.os.Bundle +import android.view.Display import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface -import androidx.compose.material.Text +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.example.powerof10.ui.theme.PowerOf10Theme class RankingPage : ComponentActivity() { @@ -22,22 +37,120 @@ class RankingPage : ComponentActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background ) { - Greeting("Android") + } } } } } +@Preview(showSystemUi = true) @Composable -fun Greeting(name: String) { - Text(text = "Hello $name!") +fun DisplayRankingPage() { + Column(modifier = Modifier.fillMaxWidth()) { + + + CenterAlignedTopAppBar(modifier = Modifier.fillMaxWidth(), + title = { + Image( + painter = painterResource(id = R.drawable.powerof10 ), + contentDescription = "Power of Ten Logo", + modifier = Modifier, + contentScale = ContentScale.FillBounds + ) + }, + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + Color(0xFFE5383B), + navigationIconContentColor = Color.White + ), + navigationIcon = { + IconButton(onClick = { /* doSomething() */ }) { + Icon( + Icons.Filled.Menu, contentDescription = null, + tint = Color.White, + modifier = Modifier.size(48.dp) + ) + } + } + ) + Row( modifier = Modifier.fillMaxWidth()){ + Button(onClick = { /*TODO*/ }) { + + } + + Button(onClick = { /*TODO*/ }) { + + } + + Button(onClick = { /*TODO*/ }) { + + } + } + Row(horizontalArrangement = Arrangement.Center,modifier = Modifier.fillMaxWidth()) { + Button(onClick = { /*TODO*/ }) { + + } + + Button(onClick = { /*TODO*/ }) { + + } + + Button(onClick = { /*TODO*/ }) { + + } + + } + Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) { + Text(text = "Rank") + Text(text = "Club") + Text(text = "Performance") + } + LazyColumn(content = { + itemsIndexed((0..5).toList()) { index, item -> + RankingItem(index) + } + }) + + + + + } } -@Preview(showBackground = true) @Composable -fun DefaultPreview3() { - PowerOf10Theme { - Greeting("Android") +fun RankingItem(index: Int){ + var background = Color(0xFFD3D3D3) + if (index%2==1){ + background = Color(0xFFD3D3D3) + } + else { + background = Color(0xFFF5F3F4) + } +Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier + .background(background) + .fillMaxWidth()) { + Column(verticalArrangement = Arrangement.SpaceBetween) { + Text(text = (index+1).toString(), ) } -} \ No newline at end of file + + Column(verticalArrangement = Arrangement.SpaceBetween) { + Text(text = "Chijindu \n" + + "Ujah") + Text(text = "(9.96)") + } + + Column(verticalArrangement = Arrangement.SpaceBetween) { + Text(text = "Enfield & Haringey") + Text(text = "Ryan Freckleton") + + } + Column() { + Text(text = "10.03 1.9") + Text(text = "Walnut CA, USA") + Text(text = "9 May 21") + } +} + +} + +