Skip to content

Commit

Permalink
Home RSS COmplete
Browse files Browse the repository at this point in the history
Jordan Akinpelu (akinpelud) committed Jun 21, 2022
1 parent 028390f commit d550e27
Showing 4 changed files with 251 additions and 72 deletions.
3 changes: 3 additions & 0 deletions PowerOf10/app/build.gradle
Original file line number Diff line number Diff line change
@@ -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'
179 changes: 122 additions & 57 deletions PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt
Original file line number Diff line number Diff line change
@@ -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<RssStandardChannelData>(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<RssStandardChannelData>(rSSLink)
}

}


}
fun extractP(description: String?):String{
//Extracts the description in the "<p>" tag from the RSS "<description> 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 "<img>" tag from the RSS "<description> 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 {
}
}
Original file line number Diff line number Diff line change
@@ -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()
}
}
}
137 changes: 125 additions & 12 deletions PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt
Original file line number Diff line number Diff line change
@@ -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(), )
}
}

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")
}
}

}


0 comments on commit d550e27

Please sign in to comment.