ONLY FUNCTIONAL STUFF MISSING!
This commit is contained in:
parent
e202eeafeb
commit
0a2de2cd06
12 changed files with 198 additions and 147 deletions
|
@ -2,6 +2,7 @@ plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
alias(libs.plugins.kotlin.compose)
|
alias(libs.plugins.kotlin.compose)
|
||||||
|
kotlin("plugin.serialization")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.bbc.denadrive
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
@ -26,36 +25,18 @@ import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKey
|
|
||||||
import com.bbc.denadrive.oauth.LoadingActivity
|
import com.bbc.denadrive.oauth.LoadingActivity
|
||||||
import com.bbc.denadrive.oauth.retrieveAuthServConf
|
import com.bbc.denadrive.oauth.retrieveAuthServConf
|
||||||
import com.bbc.denadrive.ui.theme.DeNaDriveTheme
|
import com.bbc.denadrive.ui.theme.DeNaDriveTheme
|
||||||
import net.openid.appauth.AuthState
|
|
||||||
import net.openid.appauth.AuthorizationRequest
|
import net.openid.appauth.AuthorizationRequest
|
||||||
import net.openid.appauth.AuthorizationService
|
import net.openid.appauth.AuthorizationService
|
||||||
import net.openid.appauth.ResponseTypeValues
|
import net.openid.appauth.ResponseTypeValues
|
||||||
|
|
||||||
class HomeNotAuthActivity : ComponentActivity() {
|
class HomeNotAuthActivity : ComponentActivity() {
|
||||||
|
|
||||||
private lateinit var preferences: SharedPreferences
|
|
||||||
private lateinit var masterKey: MasterKey
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
masterKey = MasterKey.Builder(this)
|
|
||||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
preferences = EncryptedSharedPreferences.create(
|
|
||||||
this,
|
|
||||||
"authState",
|
|
||||||
masterKey,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
DeNaDriveTheme {
|
DeNaDriveTheme {
|
||||||
|
@ -66,19 +47,14 @@ class HomeNotAuthActivity : ComponentActivity() {
|
||||||
caption = "DeNa Drive",
|
caption = "DeNa Drive",
|
||||||
buttonText = "Log in",
|
buttonText = "Log in",
|
||||||
modifier = Modifier.padding(innerPadding)
|
modifier = Modifier.padding(innerPadding)
|
||||||
) { handleAuthStuff(preferences) }
|
) { handleAuthStuff() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleAuthStuff(preferences: SharedPreferences) {
|
private fun handleAuthStuff() {
|
||||||
val serviceConfig = retrieveAuthServConf()
|
val serviceConfig = retrieveAuthServConf()
|
||||||
val authState = AuthState(serviceConfig)
|
|
||||||
with (preferences.edit()) {
|
|
||||||
this.putString("authState", authState.jsonSerializeString())
|
|
||||||
this.apply()
|
|
||||||
}
|
|
||||||
val authRequestBuilder = AuthorizationRequest.Builder(
|
val authRequestBuilder = AuthorizationRequest.Builder(
|
||||||
serviceConfig,
|
serviceConfig,
|
||||||
"722393551256-pum20gbvb1es723kt3ek9lmtrdimr0os.apps.googleusercontent.com",
|
"722393551256-pum20gbvb1es723kt3ek9lmtrdimr0os.apps.googleusercontent.com",
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.bbc.denadrive
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
@ -13,14 +12,15 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import com.bbc.denadrive.apihandlers.DriveResponseBody
|
||||||
import androidx.security.crypto.MasterKey
|
import com.bbc.denadrive.apihandlers.ResponsesHandler
|
||||||
import com.bbc.denadrive.apihandlers.makeDriveApiCall
|
import com.bbc.denadrive.apihandlers.makeDriveApiCall
|
||||||
import com.bbc.denadrive.home.ScaffoldWithSidebar
|
import com.bbc.denadrive.home.ScaffoldWithSidebar
|
||||||
|
import com.bbc.denadrive.oauth.AuthStatePersistence
|
||||||
import com.bbc.denadrive.oauth.retrieveAuthServConf
|
import com.bbc.denadrive.oauth.retrieveAuthServConf
|
||||||
import com.bbc.denadrive.ui.theme.DeNaDriveTheme
|
import com.bbc.denadrive.ui.theme.DeNaDriveTheme
|
||||||
import net.openid.appauth.AuthState
|
|
||||||
import net.openid.appauth.AuthorizationException
|
import net.openid.appauth.AuthorizationException
|
||||||
import net.openid.appauth.AuthorizationRequest
|
import net.openid.appauth.AuthorizationRequest
|
||||||
import net.openid.appauth.AuthorizationResponse
|
import net.openid.appauth.AuthorizationResponse
|
||||||
|
@ -29,42 +29,17 @@ import net.openid.appauth.ResponseTypeValues
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
private lateinit var masterKey: MasterKey
|
private lateinit var responsesHandler: ResponsesHandler
|
||||||
private lateinit var preferences: SharedPreferences
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
masterKey = MasterKey.Builder(this)
|
val authPersistence = AuthStatePersistence
|
||||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
val authState = authPersistence.retrieveAuthState(this)
|
||||||
.build()
|
responsesHandler = ResponsesHandler()
|
||||||
|
|
||||||
preferences = EncryptedSharedPreferences.create(
|
|
||||||
this,
|
|
||||||
"authState",
|
|
||||||
masterKey,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val authState = preferences.getString("authState", "bah")
|
|
||||||
?.let { AuthState.jsonDeserialize(it) }
|
|
||||||
|
|
||||||
val authService = AuthorizationService(this)
|
|
||||||
|
|
||||||
// authState?.let {
|
|
||||||
// it.performActionWithFreshTokens(authService) { accessToken, idToken, ex ->
|
|
||||||
// if (ex != null) {
|
|
||||||
// Log.e("TELLINGYA", "${ex.error}")
|
|
||||||
// return@performActionWithFreshTokens
|
|
||||||
// }
|
|
||||||
// Log.e("TOLD", "okay I guess")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
authState?.let {
|
|
||||||
val myUrl = "https://www.googleapis.com/drive/v3/files?trashed=false&orderBy=folder"
|
val myUrl = "https://www.googleapis.com/drive/v3/files?trashed=false&orderBy=folder"
|
||||||
makeDriveApiCall(this, it, myUrl, "root") {
|
makeDriveApiCall(this, authState, myUrl, "root") {
|
||||||
response, exception ->
|
response, exception ->
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
Log.e("ECCOLO", "${exception.cause}")
|
Log.e("ECCOLO", "${exception.cause}")
|
||||||
|
@ -72,19 +47,15 @@ class MainActivity : ComponentActivity() {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.e("UOOOO", "$response")
|
Log.e("UOOOO", "$response")
|
||||||
|
responsesHandler.newResponseArrived(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
with(preferences.edit()) {
|
authPersistence.putAuthState(this, authState)
|
||||||
this.remove("authState")
|
|
||||||
this.putString("authState", it.jsonSerializeString())
|
|
||||||
this.apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
ScaffoldWithSidebar(navController) {
|
ScaffoldWithSidebar(navController, responsesHandler) {
|
||||||
Log.e("LETTINGYOUKNOW", "authstate: ${authState?.jsonSerializeString()}")
|
Log.e("LETTINGYOUKNOW", "authstate: ${authState.jsonSerializeString()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
package com.bbc.denadrive
|
package com.bbc.denadrive
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
|
import com.bbc.denadrive.apihandlers.DriveResponseBody
|
||||||
|
import com.bbc.denadrive.apihandlers.ResponsesHandler
|
||||||
import com.bbc.denadrive.home.DetailsScreen
|
import com.bbc.denadrive.home.DetailsScreen
|
||||||
import com.bbc.denadrive.home.HomeScreen
|
import com.bbc.denadrive.home.HomeScreen
|
||||||
import com.bbc.denadrive.home.MyListVisualizer
|
import com.bbc.denadrive.home.MyListVisualizer
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NavigationGraph(navController: NavHostController) {
|
fun NavigationGraph(navController: NavHostController, responsesHandler: ResponsesHandler) {
|
||||||
// Create a NavHost that defines the navigation graph
|
// Create a NavHost that defines the navigation graph
|
||||||
NavHost(navController = navController, startDestination = "prova") {
|
NavHost(navController = navController, startDestination = "prova") {
|
||||||
// Define the home screen destination
|
// Define the home screen destination
|
||||||
|
@ -23,6 +27,6 @@ fun NavigationGraph(navController: NavHostController) {
|
||||||
DetailsScreen(itemId, navController)
|
DetailsScreen(itemId, navController)
|
||||||
}
|
}
|
||||||
|
|
||||||
composable("prova") { MyListVisualizer() }
|
composable("prova") { MyListVisualizer(responsesHandler) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
package com.bbc.denadrive.apihandlers
|
package com.bbc.denadrive.apihandlers
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class DriveResponseBody(
|
data class DriveResponseBody(
|
||||||
val nextPageToken: String?,
|
// val nextPageToken: String?,
|
||||||
val kind: String,
|
val kind: String,
|
||||||
val incompleteSearch: Boolean,
|
val incompleteSearch: Boolean,
|
||||||
val files: List<MyFile>
|
val files: List<MyFile>
|
||||||
)
|
) {
|
||||||
|
fun toList(): List<String> {
|
||||||
|
return files.map { it.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package com.bbc.denadrive.apihandlers
|
package com.bbc.denadrive.apihandlers
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class MyFile(
|
data class MyFile(
|
||||||
val kind: String,
|
val kind: String,
|
||||||
val mimeType: String,
|
val mimeType: String,
|
||||||
|
|
|
@ -1,31 +1,45 @@
|
||||||
package com.bbc.denadrive.apihandlers
|
package com.bbc.denadrive.apihandlers
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
//import androidx.lifecycle.LiveData
|
||||||
|
//import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Response
|
|
||||||
|
|
||||||
class ResponsesHandler: ViewModel() {
|
class ResponsesHandler: ViewModel() {
|
||||||
|
|
||||||
var lastResponse: String = ""
|
// private val _lastResponseBody = MutableLiveData<DriveResponseBody?>(null)
|
||||||
var isComplete: Boolean = true
|
// val lastResponseBody: LiveData<DriveResponseBody?> get() = _lastResponseBody
|
||||||
private lateinit var respBuilder: StringBuilder
|
val lastResponseBody: MutableState<DriveResponseBody?> = mutableStateOf(null)
|
||||||
private lateinit var lastResponseBody: DriveResponseBody
|
|
||||||
|
|
||||||
fun newResponseArrived(response: Response) {
|
private var lastResponse: String = ""
|
||||||
if (isComplete) {
|
private var isComplete: Boolean = true
|
||||||
respBuilder = StringBuilder("$response")
|
private lateinit var respBuilder: StringBuilder
|
||||||
|
|
||||||
|
fun newResponseArrived(response: String?) {
|
||||||
|
if (isComplete && response != null) {
|
||||||
|
respBuilder = StringBuilder(response)
|
||||||
|
updateCompleteness()
|
||||||
|
Log.e("OLE", "newResponseArrived: $response")
|
||||||
}
|
}
|
||||||
else {
|
else if (response != null) {
|
||||||
respBuilder.append("$response")
|
respBuilder.append(response)
|
||||||
|
Log.e("OLE2", "newResponseArrived: $response")
|
||||||
updateCompleteness()
|
updateCompleteness()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForCompleteness(): Pair<Boolean, DriveResponseBody?> {
|
private fun checkForCompleteness(): Pair<Boolean, DriveResponseBody?> {
|
||||||
return try {
|
return try {
|
||||||
|
Log.e("ASSURDO", "newResponseArrived: $respBuilder")
|
||||||
Pair(true, Json.decodeFromString<DriveResponseBody>(respBuilder.toString()))
|
Pair(true, Json.decodeFromString<DriveResponseBody>(respBuilder.toString()))
|
||||||
} catch (e: SerializationException) {
|
} catch (e: SerializationException) {
|
||||||
|
Log.e("EDECCOCE", "newResponseArrived: $respBuilder")
|
||||||
|
Log.e("EDECCOCE", "errore: ${e.cause}")
|
||||||
|
Log.e("EDECCOCE", "errore: ${e.message}")
|
||||||
Pair(false, null)
|
Pair(false, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +49,8 @@ class ResponsesHandler: ViewModel() {
|
||||||
isComplete = pair.first
|
isComplete = pair.first
|
||||||
if (isComplete) {
|
if (isComplete) {
|
||||||
lastResponse = respBuilder.toString()
|
lastResponse = respBuilder.toString()
|
||||||
lastResponseBody = pair.second!!
|
Log.e("NONSOCHESUCCEDA", "${pair.second}", )
|
||||||
|
lastResponseBody.value = pair.second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.bbc.denadrive.home
|
package com.bbc.denadrive.home
|
||||||
|
|
||||||
|
import android.media.tv.TvContract.Channels.Logo
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
@ -23,7 +25,13 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import com.bbc.denadrive.NavigationGraph
|
import com.bbc.denadrive.NavigationGraph
|
||||||
|
import com.bbc.denadrive.R
|
||||||
|
import com.bbc.denadrive.apihandlers.ResponsesHandler
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen(navController: NavHostController) {
|
fun HomeScreen(navController: NavHostController) {
|
||||||
|
@ -42,6 +50,7 @@ fun DetailsScreen(itemId: String?, navController: NavHostController) {
|
||||||
@Composable
|
@Composable
|
||||||
fun ScaffoldWithSidebar(
|
fun ScaffoldWithSidebar(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
|
responsesHandler: ResponsesHandler,
|
||||||
doIt: () -> Unit,
|
doIt: () -> Unit,
|
||||||
// toBeDisplayed: @Composable () -> Unit
|
// toBeDisplayed: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
|
@ -97,9 +106,9 @@ fun ScaffoldWithSidebar(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(innerPadding)
|
.padding(innerPadding)
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.TopCenter,
|
||||||
) {
|
) {
|
||||||
NavigationGraph(navController)
|
NavigationGraph(navController, responsesHandler)
|
||||||
// toBeDisplayed()
|
// toBeDisplayed()
|
||||||
// Text("Main Content", fontSize = 24.sp)
|
// Text("Main Content", fontSize = 24.sp)
|
||||||
}
|
}
|
||||||
|
@ -144,10 +153,66 @@ fun RectangularButton(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MyListVisualizer () {
|
fun MyListVisualizer(responsesHandler: ResponsesHandler) {
|
||||||
val lista = listOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z")
|
Log.e("CHECKING", "MyListVisualizer: REDRAWN", )
|
||||||
|
val fileList = mutableListOf<String>()
|
||||||
|
if (responsesHandler.lastResponseBody.value == null) {
|
||||||
|
fileList.clear()
|
||||||
|
fileList.addAll(
|
||||||
|
listOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
||||||
|
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
fileList.clear()
|
||||||
|
fileList.addAll(
|
||||||
|
responsesHandler.lastResponseBody.value!!.toList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// val fileList = driveResponseBody.value?.toList()
|
||||||
|
// ?: listOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
||||||
|
// "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z")
|
||||||
|
// LazyColumn {
|
||||||
|
// items(fileList) { name -> Text(text=name, fontSize = 30.sp) }
|
||||||
|
// }
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
items(lista) { messaggio -> Text(text=messaggio, fontSize = 30.sp) }
|
items(fileList) { name ->
|
||||||
|
val logo = painterResource(id = R.drawable.vecchiaicona_)
|
||||||
|
LogoTextBox(logo, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LogoTextBox(logoPainter: Painter, text: String) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// Logo on the left
|
||||||
|
Image(
|
||||||
|
painter = logoPainter,
|
||||||
|
contentDescription = "Logo",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(40.dp) // Adjust size as needed
|
||||||
|
.padding(end = 16.dp) // Space between logo and text
|
||||||
|
)
|
||||||
|
|
||||||
|
// Text to the right of the logo
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
color = Color.Black
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,36 +20,22 @@ import androidx.security.crypto.MasterKey
|
||||||
import com.bbc.denadrive.HomeNotAuthActivity
|
import com.bbc.denadrive.HomeNotAuthActivity
|
||||||
import com.bbc.denadrive.MainActivity
|
import com.bbc.denadrive.MainActivity
|
||||||
import com.bbc.denadrive.home.ui.theme.DeNaDriveTheme
|
import com.bbc.denadrive.home.ui.theme.DeNaDriveTheme
|
||||||
|
import com.bbc.denadrive.oauth.AuthStatePersistence
|
||||||
import net.openid.appauth.AuthState
|
import net.openid.appauth.AuthState
|
||||||
|
|
||||||
class NeverLoggedInLogic : ComponentActivity() {
|
class NeverLoggedInLogic : ComponentActivity() {
|
||||||
|
|
||||||
private lateinit var preferences: SharedPreferences
|
|
||||||
private lateinit var masterKey: MasterKey
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
masterKey = MasterKey.Builder(this)
|
val authPersistence = AuthStatePersistence
|
||||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
preferences = EncryptedSharedPreferences.create(
|
|
||||||
this,
|
|
||||||
"authState",
|
|
||||||
masterKey,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val authStateString = preferences.getString("authState", "unset")
|
|
||||||
|
|
||||||
val intent: Intent
|
val intent: Intent
|
||||||
if (authStateString == "unset") {
|
if (!authPersistence.isAuthStateSet(this)) {
|
||||||
intent = Intent(this, HomeNotAuthActivity::class.java)
|
intent = Intent(this, HomeNotAuthActivity::class.java)
|
||||||
} else {
|
} else {
|
||||||
val authState = authStateString?.let { AuthState.jsonDeserialize(it) }
|
val authState = authPersistence.retrieveAuthState(this)
|
||||||
intent = if (authState?.isAuthorized == true) {
|
intent = if (authState.isAuthorized) {
|
||||||
Intent(this, MainActivity::class.java)
|
Intent(this, MainActivity::class.java)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -59,7 +45,6 @@ class NeverLoggedInLogic : ComponentActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
// Toast.makeText(this, "should not make it here", Toast.LENGTH_SHORT).show()
|
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
|
|
|
@ -1,29 +1,76 @@
|
||||||
package com.bbc.denadrive.oauth
|
package com.bbc.denadrive.oauth
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
import androidx.security.crypto.MasterKey
|
import androidx.security.crypto.MasterKey
|
||||||
import net.openid.appauth.AuthState
|
import net.openid.appauth.AuthState
|
||||||
|
import net.openid.appauth.AuthorizationException
|
||||||
|
import net.openid.appauth.AuthorizationResponse
|
||||||
|
import net.openid.appauth.RegistrationResponse
|
||||||
|
import net.openid.appauth.TokenResponse
|
||||||
|
|
||||||
object AuthStatePersistence {
|
object AuthStatePersistence {
|
||||||
|
|
||||||
fun retrieveAuthState(context: Context): AuthState {
|
private fun getAuthStatePrefs(context: Context): SharedPreferences {
|
||||||
val masterKey = MasterKey.Builder(context)
|
val masterKey = MasterKey.Builder(context)
|
||||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val preferences = EncryptedSharedPreferences.create(
|
return EncryptedSharedPreferences.create(
|
||||||
context,
|
context,
|
||||||
"authState",
|
"authState",
|
||||||
masterKey,
|
masterKey,
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAuthStateSet(context: Context): Boolean {
|
||||||
|
return getAuthStatePrefs(context).getString("authState", null) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun retrieveAuthState(context: Context): AuthState {
|
||||||
|
val preferences = getAuthStatePrefs(context)
|
||||||
|
|
||||||
preferences.getString("authState", null)?.let {
|
preferences.getString("authState", null)?.let {
|
||||||
return AuthState.jsonDeserialize(it)
|
return AuthState.jsonDeserialize(it)
|
||||||
}
|
}
|
||||||
return AuthState(retrieveAuthServConf())
|
val newAuthState = AuthState(retrieveAuthServConf())
|
||||||
|
putAuthState(preferences, newAuthState)
|
||||||
|
return newAuthState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun putAuthState(context: Context, authState: AuthState) {
|
||||||
|
val preferences = getAuthStatePrefs(context)
|
||||||
|
putAuthState(preferences, authState)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun putAuthState(preferences: SharedPreferences, authState: AuthState) {
|
||||||
|
with (preferences.edit()) {
|
||||||
|
this.remove("authState")
|
||||||
|
this.putString("authState", authState.jsonSerializeString())
|
||||||
|
this.apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(context: Context, authState: AuthState,
|
||||||
|
authorizationResponse: AuthorizationResponse?,
|
||||||
|
authorizationException: AuthorizationException?) {
|
||||||
|
authState.update(authorizationResponse, authorizationException)
|
||||||
|
putAuthState(context, authState)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(context: Context, authState: AuthState,
|
||||||
|
tokenResponse: TokenResponse?,
|
||||||
|
authorizationException: AuthorizationException?) {
|
||||||
|
authState.update(tokenResponse, authorizationException)
|
||||||
|
putAuthState(context, authState)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(context: Context, authState: AuthState,
|
||||||
|
registrationResponse: RegistrationResponse?) {
|
||||||
|
authState.update(registrationResponse)
|
||||||
|
putAuthState(context, authState)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -44,9 +44,6 @@ import net.openid.appauth.AuthorizationService
|
||||||
|
|
||||||
class LoadingActivity : ComponentActivity() {
|
class LoadingActivity : ComponentActivity() {
|
||||||
|
|
||||||
private lateinit var masterKey: MasterKey
|
|
||||||
private lateinit var preferences: SharedPreferences
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -59,32 +56,16 @@ class LoadingActivity : ComponentActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
masterKey = MasterKey.Builder(this)
|
val authPersistence = AuthStatePersistence
|
||||||
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
preferences = EncryptedSharedPreferences.create(
|
val authState = authPersistence.retrieveAuthState(this)
|
||||||
this,
|
|
||||||
"authState",
|
|
||||||
masterKey,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val authState = preferences.getString("authState", "bah")
|
|
||||||
?.let { AuthState.jsonDeserialize(it) }
|
|
||||||
|
|
||||||
val response = AuthorizationResponse.fromIntent(intent)
|
val response = AuthorizationResponse.fromIntent(intent)
|
||||||
val exception = AuthorizationException.fromIntent(intent)
|
val exception = AuthorizationException.fromIntent(intent)
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
Toast.makeText(this, "Done!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "Done!", Toast.LENGTH_SHORT).show()
|
||||||
authState?.update(response, exception)
|
authPersistence.update(this, authState, response, exception)
|
||||||
Log.e("MainActivity", "authState: ${authState?.jsonSerializeString()}", )
|
Log.e("MainActivity", "authState: ${authState.jsonSerializeString()}", )
|
||||||
with (preferences.edit()) {
|
|
||||||
this.remove("authState")
|
|
||||||
this.putString("authState", "${authState?.jsonSerializeString()}")
|
|
||||||
this.apply()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "Not done :( ${exception?.error}", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "Not done :( ${exception?.error}", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
@ -95,12 +76,7 @@ class LoadingActivity : ComponentActivity() {
|
||||||
it
|
it
|
||||||
) { resp, ex ->
|
) { resp, ex ->
|
||||||
if (resp != null) {
|
if (resp != null) {
|
||||||
authState?.update(resp, ex)
|
authPersistence.update(this, authState, resp, ex)
|
||||||
with(preferences.edit()) {
|
|
||||||
this.remove("authState")
|
|
||||||
this.putString("authState", "${authState?.jsonSerializeString()}")
|
|
||||||
this.apply()
|
|
||||||
}
|
|
||||||
val intent = Intent(this, MainActivity::class.java)
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,4 +3,5 @@ plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
alias(libs.plugins.kotlin.android) apply false
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
alias(libs.plugins.kotlin.compose) apply false
|
alias(libs.plugins.kotlin.compose) apply false
|
||||||
|
kotlin("plugin.serialization") version "1.8.0"
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue