@@ -11,6 +10,16 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PowerOf10">
+
+
diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/Adapter/FeedAdapter.kt b/PowerOf10/app/src/main/java/com/example/powerof10/Adapter/FeedAdapter.kt
index 459a264..1b4a9b0 100644
--- a/PowerOf10/app/src/main/java/com/example/powerof10/Adapter/FeedAdapter.kt
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/Adapter/FeedAdapter.kt
@@ -49,7 +49,7 @@ class FeedViewHolder(itemView:View):RecyclerView.ViewHolder(itemView),View.OnCli
}
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()
}
diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/AthleteSearch.kt b/PowerOf10/app/src/main/java/com/example/powerof10/AthleteSearch.kt
new file mode 100644
index 0000000..4bf3754
--- /dev/null
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/AthleteSearch.kt
@@ -0,0 +1,319 @@
+package com.example.powerof10
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.WindowInsetsAnimationController
+import android.view.WindowInsetsController
+import android.widget.Toast
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.*
+import androidx.compose.foundation.gestures.scrollable
+import androidx.compose.foundation.layout.*
+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.ExperimentalMaterial3Api
+import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.runtime.*
+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.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.navigation.NavController
+import androidx.navigation.compose.rememberNavController
+import com.example.powerof10.ui.theme.PowerOf10Theme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import org.jsoup.select.Elements
+import tech.devscast.validable.EmailValidable
+import tech.devscast.validable.delegates.validableEmail
+import tech.devscast.validable.withValidable
+import java.io.Serializable
+
+class AthleteSearch : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ PowerOf10Theme {
+ // A surface container using the 'background' color from the theme
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colors.background
+ ) {
+
+ }
+ }
+ }
+ }
+}
+
+suspend fun getHTML(firstName: String, lastName: String, club: String): Document { //retrieves the entire HTML page including tags using search parameters
+ val html= "https://www.thepowerof10.info/athletes/athleteslookup.aspx?surname=$lastName&firstname=$firstName&club=$club"
+
+ return withContext(Dispatchers.IO) {
+ return@withContext Jsoup.connect(html).get()
+ }
+
+}
+
+fun getAthletes(doc: Document,mContext: Context): Serializable? {//serializable = any data structure. Function converts html to a list of elements
+ if (doc.getElementsByAttributeValueContaining("class","athleteprofilesubheader").isNotEmpty()){ //Checks if the link returned the athlete profile due to there being only 1 result
+ val browserIntent = Intent(//opens the browser and takes user to the link
+ Intent.ACTION_VIEW,
+ Uri.parse(
+ "https://www.thepowerof10.info/athletes/" + doc.getElementById("form1")?.attr("action")
+ )
+ )
+ browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)// Starts browser intent to athlete profile
+ mContext.startActivity(browserIntent)
+ //println(doc.getElementById("form1")?.attr("action"))
+ return "athlete found"
+ }
+ else if (doc.getElementsContainingText("Too many athletes found").isEmpty()){//if theres NOT too many records
+ val table = doc.getElementById("cphBody_dgAthletes") // returns the table of athlete search results (NEEDED as the nav bar has the background colour attribute)
+ var records = table?.getElementsByAttributeValueContaining("style","background-color:") //returns all records with a background colour within the results table(Line before)
+ records?.removeAt(0)//removes the heading list(sex,name,etc)
+ return records
+ } else { //otherwise return null usually because theres too many athlete records that were returned
+ return null
+ }
+
+
+
+
+}
+
+
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun AthleteSearch(navController: NavController) {
+ val powerOfTen = painterResource(id = R.drawable.powerof10)
+ var buttonPress by remember { mutableStateOf(0) }//updates the lazy column when the apply button is pressed
+ val scaffoldState = rememberScaffoldState()
+ val scope = rememberCoroutineScope()
+ var firstName by remember { mutableStateOf("") }
+ var lastName by remember { mutableStateOf("") }
+ var club by remember { mutableStateOf("") }
+ var athletesList by remember {mutableStateOf(Elements()) }
+ var context = LocalContext.current
+ LaunchedEffect(buttonPress) { //recomposes on button press
+ if (firstName != ""||lastName != ""){//if the either name fields are not empty
+ val html = getHTML(firstName,lastName,club)//gets html from the searched page
+ var athletesElements = getAthletes(html, context)//this is to check if the result is string, null or Elements()
+ when (athletesElements) {
+ null -> {//if null make a warning/toast
+ Toast.makeText(context,"Too many athletes found. Please change the search criteria.\n",Toast.LENGTH_SHORT).show()
+ }
+ "athlete found" -> {//if only a single athlete is returned
+ Toast.makeText(context,"Athlete found opening on browser",Toast.LENGTH_SHORT).show()
+
+ }
+ else -> {//otherwise just display the records list as usual
+ athletesList = athletesElements as Elements
+ println(athletesList.size)
+ }
+ }
+
+
+ }else{// if both fields are empty
+ Toast.makeText(context,"Please enter your search values",Toast.LENGTH_SHORT).show()
+ }
+
+
+
+
+ }
+ Column {
+
+ Scaffold(
+ scaffoldState = scaffoldState,
+ topBar = {
+ CenterAlignedTopAppBar(modifier = Modifier.fillMaxWidth(),
+ title = {
+ Image(
+ painter = powerOfTen,
+ contentDescription = "Power of Ten Logo",
+ modifier = Modifier,
+ contentScale = ContentScale.FillBounds
+ )
+ },
+ colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
+ Color(0xFFE5383B),
+ navigationIconContentColor = Color.White
+ ),
+ navigationIcon = {
+ IconButton(onClick = { scope.launch { scaffoldState.drawerState.open() } }) {
+ Icon(
+ Icons.Filled.Menu, contentDescription = null,
+ tint = Color.White,
+ modifier = Modifier.size(48.dp)
+ )
+ }
+ }
+ )
+ },
+ drawerContent = {
+ NavDrawerBody(items = listOf(
+ MenuItems(1, "Home",Screen.HomepageRSS.route),
+ MenuItems(2, "Rankings",Screen.RankingPage.route),
+ MenuItems(3, "Athlete Search",Screen.AthleteSearch.route)
+ ), onItemClick = { navController.navigate(route =it.route) }
+ )
+ }, content = {
+
+
+ Column( modifier = Modifier.fillMaxWidth()
+ ){
+
+
+ LazyColumn(content = {
+ item {
+ Column(horizontalAlignment = Alignment.CenterHorizontally,modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(
+ text = "Athlete Search",
+ fontWeight = FontWeight.Bold,
+ fontSize = 24.sp,
+ modifier = Modifier.padding(10.dp)
+ )
+ TextField(
+ value = firstName,
+ onValueChange = { firstName = it },
+ label = { Text("First Name") },
+ modifier = Modifier.padding(0.dp,5.dp)
+ )
+
+ TextField(
+ value = lastName,
+ onValueChange = { lastName = it },
+ label = { Text("Last Name") },
+ modifier = Modifier.padding(0.dp,5.dp)
+ )
+
+ TextField(
+ value = club,
+ onValueChange = { club = it },
+ label = { Text("Club Name") },
+ modifier = Modifier.padding(0.dp,5.dp)
+ )
+ Button(
+ onClick = {
+ if (firstName.length < 3&&lastName.length<3 ){// validates to check fields are atleast 3 chars long
+ Toast.makeText(context,"Please enter at least 3 characters for either First or Last name",Toast.LENGTH_SHORT).show()
+ }else {
+ buttonPress += 1 //recompose view
+ }
+ }, modifier = Modifier
+ .padding(horizontal = 5.dp, vertical = 0.dp)
+ .fillMaxWidth(0.75F)
+
+ ) {
+ Text("Apply")
+
+ }
+ }
+ }
+ items(athletesList.size) {
+
+ AthleteItem(it,athletesList)
+
+
+ }
+ })
+
+ }
+ })
+
+ }
+}
+
+@Composable
+fun AthleteItem(index: Int,athlete:Elements) {
+ val mContext = LocalContext.current
+ val background: Color = if (index%2==1){//alternates the colour
+ Color(0xFFD3D3D3)
+ }
+ else {
+ Color(0xFFF5F3F4)
+ } //alternates the background colour
+ Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier
+ .background(background)
+ .fillMaxWidth()
+ .padding(0.dp, 10.dp)
+ .clickable {
+ val browserIntent = Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse(
+ "https://www.thepowerof10.info/athletes/" + athlete[index]
+ .child(7)
+ .child(0)
+ .attr("href")
+ )
+ )
+ browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)// Starts browser intent to athlete profile
+ mContext.startActivity(browserIntent)
+ }
+ ) {
+
+
+ Column(verticalArrangement = Arrangement.SpaceBetween,modifier = Modifier
+ .fillMaxWidth(0.25f)
+ .padding(start = 5.dp)) {
+
+ Text(text = athlete[index].child(0).text() ,//First Name
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis)
+ Text(text = athlete[index].child(1).text() ,//Last Name
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis)
+ }
+
+ Column(verticalArrangement = Arrangement.SpaceBetween,modifier = Modifier.fillMaxWidth(0.5f)) {
+ Text(text = "Club:" ,//Athlete's club
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis)
+ Text(text = athlete[index].child(6).text() ,//athletes club
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis)
+
+ }
+ Column(modifier = Modifier.fillMaxWidth(0.4f)) {
+ Text(text = athlete[index].child(5).text() ,//Athlete's Gender
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis)
+ Text(text = athlete[index].child(2).text() ,//Athletes Age Group
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis)
+
+
+ }
+ }
+}
+@Preview(name = "PIXEL_4", device = Devices.PIXEL_4)
+//@Preview(name = "PIXEL_42", device = Devices.PIXEL_4)
+@Composable
+fun DefaultPreview3() {
+ PowerOf10Theme {
+ AthleteSearch(rememberNavController())
+ }
+}
\ No newline at end of file
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 1ca96da..3ebb71b 100644
--- a/PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/HomeRSS.kt
@@ -1,5 +1,6 @@
package com.example.powerof10
+import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
@@ -13,6 +14,7 @@ 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.ExperimentalMaterial3Api
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@@ -30,6 +32,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel
import androidx.navigation.NavController
+import androidx.navigation.compose.rememberNavController
import coil.compose.AsyncImage
import com.example.powerof10.ui.theme.PowerOf10Theme
import kotlinx.coroutines.*
@@ -39,6 +42,8 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import tw.ktrssreader.Reader
import tw.ktrssreader.kotlin.model.channel.RssStandardChannelData
+import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
class HomeRSS : ComponentActivity() {
@@ -77,7 +82,7 @@ class RSSLogic {
//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()
}
@@ -85,7 +90,7 @@ fun extractP(description: String?): String {
fun extractImg(description: String?): String {
val doc: Document = Jsoup.parse(description)
val img = doc.select("img").first()
- return img.attr("src")
+ return img!!.attr("src")
}
//
@@ -105,8 +110,10 @@ fun extractImg(description: String?): String {
//@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)
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
+@OptIn(ExperimentalMaterial3Api::class)
+//@Preview(name = "PIXEL_4", device = Devices.PIXEL_4)
+//@Preview(name = "PIXEL_4_XL", device = Devices.PIXEL_4_XL)
@Composable
fun DisplayRssHomepage(navController: NavController) {
var rssitem by remember {// If any changes are made to this variable the screen recomposes also stores the RSS Data
@@ -181,22 +188,23 @@ fun DisplayRssHomepage(navController: NavController) {
NavDrawerBody(items = listOf(
MenuItems(1, "Home",Screen.HomepageRSS.route),
MenuItems(2, "Rankings",Screen.RankingPage.route),
- MenuItems(3, "Settings",Screen.RankingPage.route)
+ MenuItems(3, "Athlete Search",Screen.AthleteSearch.route)
), onItemClick = { navController.navigate(route =it.route) }
)
}, content = {
Column() {
- Text(
- text = "Latest News",
- fontWeight = FontWeight.Bold,
- fontSize = 24.sp,
- modifier = Modifier.padding(10.dp)
- )
+
LazyColumn(content = {
+ item { Text(
+ text = "Latest News",
+ fontWeight = FontWeight.Bold,
+ fontSize = 24.sp,
+ modifier = Modifier.padding(10.dp)
+ ) }
rssitem.items?.let { it ->
items(it.size) {
- RssItem(it, rssitem = rssitem)
+ RssItem(it, rssitem = rssitem,navController)
}
}
})
@@ -217,13 +225,16 @@ Column() {
// The RSS item for the Lazy Column Composable (Recycler View)
@Composable
-fun RssItem(index: Int, rssitem: RssStandardChannelData) {
+fun RssItem(index: Int, rssitem: RssStandardChannelData,navController: NavController) {
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)
+// val browserIntent =
+// Intent(Intent.ACTION_VIEW, Uri.parse(rssitem.items?.get(index)?.link))
+// browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+// mContext.startActivity(browserIntent)
+ val link = Uri.parse(rssitem.items?.get(index)?.link).toString()
+ val encodedUrl = URLEncoder.encode(link, StandardCharsets.UTF_8.toString())//cant pass url as params without encoding first
+ navController.navigate(encodedUrl)//navigates to webview instead of browser
}) {
Box {
AsyncImage( //coil library composable that loads images from the the src url on another thread
diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/MainActivity.kt b/PowerOf10/app/src/main/java/com/example/powerof10/MainActivity.kt
index 9fa2585..60947f6 100644
--- a/PowerOf10/app/src/main/java/com/example/powerof10/MainActivity.kt
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/MainActivity.kt
@@ -1,6 +1,11 @@
package com.example.powerof10
+import android.os.Build
import android.os.Bundle
+import android.view.View
+import android.view.WindowInsets
+import android.view.WindowInsetsController
+import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
@@ -12,8 +17,10 @@ import com.example.powerof10.ui.theme.PowerOf10Theme
class MainActivity : ComponentActivity() {
lateinit var navController: NavHostController
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+
setContent {
PowerOf10Theme {
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 ce7a219..4d16d10 100644
--- a/PowerOf10/app/src/main/java/com/example/powerof10/NavGraph.kt
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/NavGraph.kt
@@ -1,9 +1,13 @@
package com.example.powerof10
import androidx.compose.runtime.Composable
+import androidx.fragment.app.FragmentManager.BackStackEntry
+import androidx.navigation.NamedNavArgument
import androidx.navigation.NavHostController
+import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
+import androidx.navigation.navArgument
@Composable
@@ -29,5 +33,23 @@ fun SetupNavGraph(
DisplayRankingPage(navController)
}
+ composable(
+ route = Screen.AthleteSearch.route
+ ) {
+
+ AthleteSearch(navController)
+ }
+ composable(
+ route = "{link}",//parameter for the articlewebview composable
+ arguments = listOf(navArgument("link"){
+ type = NavType.StringType
+ nullable = false
+ })
+ ) {
+ var id = requireNotNull(it.arguments?.getString("link").toString())
+ ArticleWebView(id)
+ //println(id)
+
+ }
}
}
\ No newline at end of file
diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/RSSArticle.kt b/PowerOf10/app/src/main/java/com/example/powerof10/RSSArticle.kt
new file mode 100644
index 0000000..b891e7c
--- /dev/null
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/RSSArticle.kt
@@ -0,0 +1,53 @@
+package com.example.powerof10
+
+import android.os.Bundle
+import android.webkit.WebView
+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.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.navigation.NavController
+import com.example.powerof10.ui.theme.PowerOf10Theme
+import com.google.accompanist.web.WebView
+import com.google.accompanist.web.rememberWebViewState
+
+class RSSArticle : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ PowerOf10Theme {
+ // A surface container using the 'background' color from the theme
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colors.background
+ ) {
+
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun ArticleWebView( link: String) {
+ val state = rememberWebViewState(link)
+ println(link)
+ WebView(
+ state,
+ onCreated = {
+ it.settings.javaScriptEnabled = true},
+ )
+}
+
+@Preview(showBackground = true)
+@Composable
+fun DefaultPreview4() {
+ PowerOf10Theme {
+
+ }
+}
\ 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 c35c8d4..26c8583 100644
--- a/PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/RankingPage.kt
@@ -15,6 +15,7 @@ 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.ExperimentalMaterial3Api
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
@@ -26,9 +27,11 @@ 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.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
+import androidx.navigation.compose.rememberNavController
import com.example.powerof10.ui.theme.PowerOf10Theme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -106,6 +109,7 @@ fun getNames(doc: Document): Elements {
cleanList.add(it)
}
}
+ println(cleanList)
return cleanList
} //Cleans the HTML by removing the records that are blank (with no name)
@@ -113,32 +117,39 @@ fun getNames(doc: Document): Elements {
-@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 = "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)
-@SuppressLint("MutableCollectionMutableState")
+@SuppressLint("MutableCollectionMutableState", "UnusedMaterialScaffoldPaddingParameter")
@Preview(name = "PIXEL_4", device = Devices.PIXEL_4)
//@Preview(name = "PIXEL_4_XL", device = Devices.PIXEL_4_XL)
-@OptIn(ExperimentalMaterialApi::class)
+@Composable
+fun UserProfilePreview2(){
+ DisplayRankingPage(navController = rememberNavController())
+}
+
+
+@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
+@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
@Composable
fun DisplayRankingPage(navController: NavController) {
//following observable variable descriptions apply to all
var yearExpanded by remember { mutableStateOf(false) }//checks the state of the dropdown (expanded or not)
- val yearOptions = listOf("2022", "2021", "2020", "2019", "2018", "2017", "2016", "2015", "2014", "2013", "2012", "2011", "2010", "2009", "2008", "2007", "2006", "All Time")//variables inside the menu
+ val yearOptions = listOf("2023","2022", "2021", "2020", "2019", "2018", "2017", "2016", "2015", "2014", "2013", "2012", "2011", "2010", "2009", "2008", "2007", "2006", "All Time")//variables inside the menu
var yearSelectedOptionText by remember { mutableStateOf(yearOptions[0]) }//the current object that's selected
var regionExpanded by remember { mutableStateOf(false) }
@@ -240,199 +251,206 @@ fun DisplayRankingPage(navController: NavController) {
NavDrawerBody(items = listOf(
MenuItems(1, "Home",Screen.HomepageRSS.route),
MenuItems(2, "Rankings",Screen.RankingPage.route),
- MenuItems(3, "Settings",Screen.RankingPage.route)
+ MenuItems(3, "Athlete Search",Screen.AthleteSearch.route)
), onItemClick = { navController.navigate(route =it.route) }
)
}, content = {
Column(modifier = Modifier.fillMaxWidth()) {
- Text(
- text = "Rankings",
- fontWeight = FontWeight.Bold,
- fontSize = 24.sp,
- modifier = Modifier.padding(10.dp)
- )
- Row(
- horizontalArrangement = Arrangement.SpaceAround,
- modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 10.dp)
- ) {
- ExposedDropdownMenuBox(
- expanded = yearExpanded,
- modifier = Modifier
- .weight(1f)
- .padding(horizontal = 10.dp, vertical = 0.dp),
- onExpandedChange = { yearExpanded = !yearExpanded },
- ) {
- TextField(
- readOnly = true,
- value = yearSelectedOptionText,
- onValueChange = {},
- label = { Text("1. Year") },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- ExposedDropdownMenu(
- expanded = yearExpanded,
- onDismissRequest = { yearExpanded = false },
- ) {
- yearOptions.forEach { yearSelectionOption ->
- DropdownMenuItem(
- onClick = {
- yearSelectedOptionText = yearSelectionOption
- yearExpanded = false
- }
- ) { Text(text = yearSelectionOption) }
- }
- }
- }
- ExposedDropdownMenuBox(
- expanded = regionExpanded,
- modifier = Modifier
- .weight(1f)
- .padding(horizontal = 10.dp, vertical = 0.dp),
- onExpandedChange = { regionExpanded = !regionExpanded },
- ) {
- TextField(
- readOnly = true,
- value = regionSelectedOptionText,
- onValueChange = {},
- label = { Text("2. Region") },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
+
+ LazyColumn(content = {
+ item {
+ Text(
+ text = "Rankings",
+ fontWeight = FontWeight.Bold,
+ fontSize = 24.sp,
+ modifier = Modifier.padding(10.dp)
)
- ExposedDropdownMenu(
- expanded = regionExpanded,
- onDismissRequest = { regionExpanded = false },
+ Row(
+ horizontalArrangement = Arrangement.SpaceAround,
+ modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 10.dp)
) {
- regionOptions.forEach { regionSelectionOption ->
- DropdownMenuItem(
- onClick = {
- regionSelectedOptionText = regionSelectionOption
- regionExpanded = false
+ ExposedDropdownMenuBox(
+ expanded = yearExpanded,
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 10.dp, vertical = 0.dp),
+ onExpandedChange = { yearExpanded = !yearExpanded },
+ ) {
+ TextField(
+ readOnly = true,
+ value = yearSelectedOptionText,
+ onValueChange = {},
+ label = { Text("1. Year") },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = yearExpanded,
+ onDismissRequest = { yearExpanded = false },
+ ) {
+ yearOptions.forEach { yearSelectionOption ->
+ DropdownMenuItem(
+ onClick = {
+ yearSelectedOptionText = yearSelectionOption
+ yearExpanded = false
+ }
+ ) { Text(text = yearSelectionOption) }
}
- ) { Text(text = regionSelectionOption) }
+ }
}
- }
- }
- ExposedDropdownMenuBox(
- expanded = genderExpanded,
- modifier = Modifier
- .weight(1f)
- .padding(horizontal = 10.dp, vertical = 0.dp),
- onExpandedChange = { genderExpanded = !genderExpanded },
- ) {
- TextField(
- readOnly = true,
- value = genderSelectedOptionText,
- onValueChange = {
- },
- label = { Text("3. Gender") },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- ExposedDropdownMenu(
- expanded = genderExpanded,
- onDismissRequest = { genderExpanded = false },
- ) {
- genderOptions.forEach { selectionOption ->
- DropdownMenuItem(
- onClick = {
- genderSelectedOptionText = selectionOption
- updateOptions += 1
+ ExposedDropdownMenuBox(
+ expanded = regionExpanded,
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 10.dp, vertical = 0.dp),
+ onExpandedChange = { regionExpanded = !regionExpanded },
+ ) {
+ TextField(
+ readOnly = true,
+ value = regionSelectedOptionText,
+ onValueChange = {},
+ label = { Text("2. Region") },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = regionExpanded,
+ onDismissRequest = { regionExpanded = false },
+ ) {
+ regionOptions.forEach { regionSelectionOption ->
+ DropdownMenuItem(
+ onClick = {
+ regionSelectedOptionText = regionSelectionOption
+ regionExpanded = false
+ }
+ ) { Text(text = regionSelectionOption) }
+ }
+ }
+ }
- genderExpanded = false
+ ExposedDropdownMenuBox(
+ expanded = genderExpanded,
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 10.dp, vertical = 0.dp),
+ onExpandedChange = { genderExpanded = !genderExpanded },
+ ) {
+ TextField(
+ readOnly = true,
+ value = genderSelectedOptionText,
+ onValueChange = {
+ },
+ label = { Text("3. Gender") },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = genderExpanded,
+ onDismissRequest = { genderExpanded = false },
+ ) {
+ genderOptions.forEach { selectionOption ->
+ DropdownMenuItem(
+ onClick = {
+ genderSelectedOptionText = selectionOption
+ groupSelectedOptionText="Overall"
+ eventSelectedOptionText="60"
+ updateOptions += 1
+
+
+ genderExpanded = false
+ }
+ ) { Text(text = selectionOption) }
}
- ) { Text(text = selectionOption) }
+ }
}
}
- }
- }
- Row(
- horizontalArrangement = Arrangement.SpaceAround, modifier = Modifier
- .fillMaxWidth()
- .padding(0.dp, 0.dp, 0.dp, 10.dp)
- ) {
- ExposedDropdownMenuBox(
- expanded = groupExpanded,
- modifier = Modifier
- .weight(1f)
- .padding(horizontal = 10.dp, vertical = 0.dp),
- onExpandedChange = { groupExpanded = !groupExpanded },
- ) {
- TextField(
- readOnly = true,
- value = groupSelectedOptionText,
- onValueChange = {},
- label = { Text("4. Group") },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- ExposedDropdownMenu(
- expanded = groupExpanded,
- onDismissRequest = { groupExpanded = false },
+ Row(
+ horizontalArrangement = Arrangement.SpaceAround, modifier = Modifier
+ .fillMaxWidth()
+ .padding(0.dp, 0.dp, 0.dp, 10.dp)
) {
- groupOptions.forEach { selectionOption ->
- DropdownMenuItem(
- onClick = {
- groupSelectedOptionText = selectionOption
- updateOptions += 1
- groupExpanded = false
+ ExposedDropdownMenuBox(
+ expanded = groupExpanded,
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 10.dp, vertical = 0.dp),
+ onExpandedChange = { groupExpanded = !groupExpanded },
+ ) {
+ TextField(
+ readOnly = true,
+ value = groupSelectedOptionText,
+ onValueChange = {},
+ label = { Text("4. Group") },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = groupExpanded,
+ onDismissRequest = { groupExpanded = false },
+ ) {
+ groupOptions.forEach { selectionOption ->
+ DropdownMenuItem(
+ onClick = {
+ groupSelectedOptionText = selectionOption
+ eventSelectedOptionText="60"
+ updateOptions += 1
+ groupExpanded = false
+ }
+ ) { Text(text = selectionOption) }
}
- ) { Text(text = selectionOption) }
+ }
}
- }
- }
- ExposedDropdownMenuBox(
- expanded = eventExpanded,
- modifier = Modifier
- .weight(1f)
- .padding(horizontal = 10.dp, vertical = 0.dp),
- onExpandedChange = { eventExpanded = !eventExpanded },
- ) {
- TextField(
- readOnly = true,
- value = eventSelectedOptionText,
- onValueChange = {},
- label = { Text("5. Event") },
- colors = ExposedDropdownMenuDefaults.textFieldColors(),
- )
- ExposedDropdownMenu(
- expanded = eventExpanded,
- onDismissRequest = { eventExpanded = false },
- ) {
- subList.forEach { selectionOption ->
- DropdownMenuItem(
- onClick = {
- eventSelectedOptionText = selectionOption
- updateOptions += 1
- eventExpanded = false
+ ExposedDropdownMenuBox(
+ expanded = eventExpanded,
+ modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 10.dp, vertical = 0.dp),
+ onExpandedChange = { eventExpanded = !eventExpanded },
+ ) {
+ TextField(
+ readOnly = true,
+ value = eventSelectedOptionText,
+ onValueChange = {},
+ label = { Text("5. Event") },
+ colors = ExposedDropdownMenuDefaults.textFieldColors(),
+ )
+ ExposedDropdownMenu(
+ expanded = eventExpanded,
+ onDismissRequest = { eventExpanded = false },
+ ) {
+ subList.forEach { selectionOption ->
+ DropdownMenuItem(
+ onClick = {
+ eventSelectedOptionText = selectionOption
+ updateOptions += 1
+ eventExpanded = false
+ }
+ ) { Text(text = selectionOption) }
}
- ) { Text(text = selectionOption) }
+ }
}
- }
- }
- Button(
- onClick = { buttonPress += 1 }, modifier = Modifier
- .weight(1f)
- .padding(horizontal = 10.dp, vertical = 0.dp)
- ) {
- Text("Apply")
-
- }
+ Button(
+ onClick = { buttonPress += 1 }, modifier = Modifier
+ .weight(1f)
+ .padding(horizontal = 10.dp, vertical = 0.dp)
+ ) {
+ Text("Apply")
- }
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth()
- ) {
- Text(text = "Rank")
- Text(text = "Club")
- Text(text = "Performance")
- }
+ }
- LazyColumn(content = {
+ }
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(text = "Rank")
+ Text(text = "Club")
+ Text(text = "Performance")
+ }
+ }
items(athletesList.size) {
@@ -463,9 +481,19 @@ fun RankingItem(index: Int, athleteList: Elements){
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier
.background(background)
.fillMaxWidth()
- .clickable { val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.thepowerof10.info/"+athleteList[index].child(6).child(0).attr("href")))
+ .clickable {
+ val browserIntent = Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse(
+ "https://www.thepowerof10.info/" + athleteList[index]
+ .child(6)
+ .child(0)
+ .attr("href")
+ )
+ )
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)// Starts browser intent to athlete profile
- mContext.startActivity(browserIntent) }) {
+ mContext.startActivity(browserIntent)
+ }) {
Column(verticalArrangement = Arrangement.SpaceBetween,modifier = Modifier.fillMaxWidth(0.08f)) {
Text(text = rank )
}
diff --git a/PowerOf10/app/src/main/java/com/example/powerof10/Screen.kt b/PowerOf10/app/src/main/java/com/example/powerof10/Screen.kt
index 8c69ef6..4427e07 100644
--- a/PowerOf10/app/src/main/java/com/example/powerof10/Screen.kt
+++ b/PowerOf10/app/src/main/java/com/example/powerof10/Screen.kt
@@ -4,4 +4,6 @@ sealed class Screen(val route: String) {
object Welcome: Screen(route ="welcome" )
object HomepageRSS: Screen(route = "Homepage_rss")
object RankingPage: Screen(route = "RankingPage")
+ object AthleteSearch: Screen(route = "AthleteSearch")
+ object RSSArticle: Screen(route = "RSSArticle")
}
diff --git a/PowerOf10/app/src/main/res/values/colors.xml b/PowerOf10/app/src/main/res/values/colors.xml
index f8c6127..ddaea49 100644
--- a/PowerOf10/app/src/main/res/values/colors.xml
+++ b/PowerOf10/app/src/main/res/values/colors.xml
@@ -1,6 +1,7 @@
#FFBB86FC
+ #FFE5383B
#FF6200EE
#FF3700B3
#FF03DAC5
diff --git a/PowerOf10/app/src/main/res/values/strings.xml b/PowerOf10/app/src/main/res/values/strings.xml
index 7ca9ea1..7ca6435 100644
--- a/PowerOf10/app/src/main/res/values/strings.xml
+++ b/PowerOf10/app/src/main/res/values/strings.xml
@@ -6,4 +6,6 @@
RSSFEED
RankingPage
NavDrawer
+ AthleteSearch
+ RSSArticle
\ No newline at end of file
diff --git a/PowerOf10/app/src/main/res/values/themes.xml b/PowerOf10/app/src/main/res/values/themes.xml
index 2917b7d..e990fa0 100644
--- a/PowerOf10/app/src/main/res/values/themes.xml
+++ b/PowerOf10/app/src/main/res/values/themes.xml
@@ -2,6 +2,7 @@
\ No newline at end of file
diff --git a/PowerOf10/build.gradle b/PowerOf10/build.gradle
index 46b64bf..f165281 100644
--- a/PowerOf10/build.gradle
+++ b/PowerOf10/build.gradle
@@ -1,14 +1,22 @@
buildscript {
+ ext.kotlin_version = '1.8.0'
ext {
- compose_version = '1.1.1'
- navigationVersion = "2.3.0"
+ compose_version = '1.4.0'
+ navigationVersion = '2.5.3'
}
+ repositories {
+ mavenCentral()
+ maven { url 'https://jitpack.io' }
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id 'com.android.application' version '7.1.3' apply false
- id 'com.android.library' version '7.1.3' apply false
- id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
+ id 'com.android.application' version '7.4.2' apply false
+ id 'com.android.library' version '7.4.2' apply false
+ id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}
task clean(type: Delete) {
diff --git a/PowerOf10/gradle/wrapper/gradle-wrapper.properties b/PowerOf10/gradle/wrapper/gradle-wrapper.properties
index 1c18334..5cd84b2 100644
--- a/PowerOf10/gradle/wrapper/gradle-wrapper.properties
+++ b/PowerOf10/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Mon May 23 03:31:55 BST 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME