diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index a78e517..11529b6 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -39,7 +39,7 @@ android {
compose = true
}
packaging {
- resources.excludes.add("META-INF-DEPENDENCIES")
+ resources.pickFirsts.add("META-INF/DEPENDENCIES")
}
}
@@ -69,11 +69,7 @@ dependencies {
implementation(libs.appauth)
implementation(libs.androidx.security.crypto)
-
-
-// implementation(libs.google.api.client.android)
-// implementation(libs.google.api.services.drive)
-// implementation(libs.google.oauth.client.jetty)
-
+ implementation(libs.google.auth.library.oauth2.http)
+ implementation(libs.kotlinx.serialization.json)
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1857486..c0be5f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,16 +15,26 @@
android:theme="@style/Theme.DeNaDrive"
tools:targetApi="31">
+
-
-
+ android:theme="@style/Theme.DeNaDrive">
+
+
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
diff --git a/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt b/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt
index 5060902..07c54b4 100644
--- a/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt
+++ b/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt
@@ -2,6 +2,7 @@ package com.bbc.denadrive
import android.app.PendingIntent
import android.content.Intent
+import android.content.SharedPreferences
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -25,16 +26,36 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
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.retrieveAuthServConf
import com.bbc.denadrive.ui.theme.DeNaDriveTheme
+import net.openid.appauth.AuthState
import net.openid.appauth.AuthorizationRequest
import net.openid.appauth.AuthorizationService
import net.openid.appauth.ResponseTypeValues
class HomeNotAuthActivity : ComponentActivity() {
+
+ private lateinit var preferences: SharedPreferences
+ private lateinit var masterKey: MasterKey
+
override fun onCreate(savedInstanceState: Bundle?) {
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()
setContent {
DeNaDriveTheme {
@@ -42,18 +63,22 @@ class HomeNotAuthActivity : ComponentActivity() {
val logo = painterResource(id = R.drawable.vecchiaicona_)
LogoWithCaptionAndButton (
logo = logo,
- caption = "Android",
- buttonText = "PressMe",
+ caption = "DeNa Drive",
+ buttonText = "Log in",
modifier = Modifier.padding(innerPadding)
- ) { handleAuthStuff() }
+ ) { handleAuthStuff(preferences) }
}
}
}
}
- private fun handleAuthStuff() {
+ private fun handleAuthStuff(preferences: SharedPreferences) {
val serviceConfig = retrieveAuthServConf()
-// val authState = AuthState(serviceConfig)
+ val authState = AuthState(serviceConfig)
+ with (preferences.edit()) {
+ this.putString("authState", authState.jsonSerializeString())
+ this.apply()
+ }
val authRequestBuilder = AuthorizationRequest.Builder(
serviceConfig,
"722393551256-pum20gbvb1es723kt3ek9lmtrdimr0os.apps.googleusercontent.com",
@@ -67,7 +92,7 @@ class HomeNotAuthActivity : ComponentActivity() {
val authService = AuthorizationService(this)
authService.performAuthorizationRequest(
authRequest,
- PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java),
+ PendingIntent.getActivity(this, 0, Intent(this, LoadingActivity::class.java),
PendingIntent.FLAG_MUTABLE),
PendingIntent.getActivity(this, 0, Intent(this, HomeNotAuthActivity::class.java),
PendingIntent.FLAG_MUTABLE)
@@ -110,7 +135,7 @@ fun LogoWithCaptionAndButton(
Image(
painter = logo,
contentDescription = "Logo",
- modifier = Modifier.size(100.dp) // Adjust size as needed
+ modifier = Modifier.size(200.dp) // Adjust size as needed
)
Spacer(modifier = Modifier.height(16.dp)) // Space between logo and caption
diff --git a/app/src/main/java/com/bbc/denadrive/MainActivity.kt b/app/src/main/java/com/bbc/denadrive/MainActivity.kt
index ef5a777..377d1a0 100644
--- a/app/src/main/java/com/bbc/denadrive/MainActivity.kt
+++ b/app/src/main/java/com/bbc/denadrive/MainActivity.kt
@@ -2,7 +2,9 @@ package com.bbc.denadrive
import android.app.PendingIntent
import android.content.Intent
+import android.content.SharedPreferences
import android.os.Bundle
+import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -12,9 +14,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.net.toUri
import androidx.navigation.compose.rememberNavController
+import androidx.security.crypto.EncryptedSharedPreferences
+import androidx.security.crypto.MasterKey
+import com.bbc.denadrive.apihandlers.makeDriveApiCall
import com.bbc.denadrive.home.ScaffoldWithSidebar
import com.bbc.denadrive.oauth.retrieveAuthServConf
import com.bbc.denadrive.ui.theme.DeNaDriveTheme
+import net.openid.appauth.AuthState
import net.openid.appauth.AuthorizationException
import net.openid.appauth.AuthorizationRequest
import net.openid.appauth.AuthorizationResponse
@@ -22,27 +28,65 @@ import net.openid.appauth.AuthorizationService
import net.openid.appauth.ResponseTypeValues
class MainActivity : ComponentActivity() {
-override fun onCreate(savedInstanceState: Bundle?) {
+
+ private lateinit var masterKey: MasterKey
+ private lateinit var preferences: SharedPreferences
+
+ override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-// handleAuthStuff()
+ masterKey = MasterKey.Builder(this)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build()
+
+ 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"
+ makeDriveApiCall(this, it, myUrl, "root") {
+ response, exception ->
+ if (exception != null) {
+ Log.e("ECCOLO", "${exception.cause}")
+ Log.e("ECCOLO", "${exception.message}")
+ }
+ else {
+ Log.e("UOOOO", "$response")
+ }
+ }
+ with(preferences.edit()) {
+ this.remove("authState")
+ this.putString("authState", it.jsonSerializeString())
+ this.apply()
+ }
+ }
setContent {
val navController = rememberNavController()
- ScaffoldWithSidebar(navController) { }
-// NavigationGraph(navController)
+ ScaffoldWithSidebar(navController) {
+ Log.e("LETTINGYOUKNOW", "authstate: ${authState?.jsonSerializeString()}")
+ }
}
-// enableEdgeToEdge()
-// setContent {
-// DeNaDriveTheme {
-// Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
-// Greeting(
-// name = "Android",
-// modifier = Modifier.padding(innerPadding)
-// )
-// }
-// }
-// }
}
@@ -62,10 +106,10 @@ override fun onCreate(savedInstanceState: Bundle?) {
val authService = AuthorizationService(this)
authService.performAuthorizationRequest(
authRequest,
- PendingIntent.getActivity(this, 0, Intent(this, TestActivity::class.java),
- PendingIntent.FLAG_MUTABLE),
- PendingIntent.getActivity(this, 0, Intent(this, TestBah::class.java),
- PendingIntent.FLAG_MUTABLE)
+ PendingIntent.getActivity(this, 0, Intent(this,
+ TestActivity::class.java), PendingIntent.FLAG_MUTABLE),
+ PendingIntent.getActivity(this, 0, Intent(this,
+ TestBah::class.java), PendingIntent.FLAG_MUTABLE)
)
}
@@ -83,8 +127,9 @@ override fun onCreate(savedInstanceState: Bundle?) {
}
setContent {
- val navController = rememberNavController()
- ScaffoldWithSidebar(navController) { }
+// val navController = rememberNavController()
+// ScaffoldWithSidebar(navController) { }
+ Greeting("bah")
}
}
}
diff --git a/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt b/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt
new file mode 100644
index 0000000..35024d5
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt
@@ -0,0 +1,45 @@
+package com.bbc.denadrive.apihandlers
+
+import android.content.Context
+import net.openid.appauth.AuthState
+import net.openid.appauth.AuthorizationService
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.Response
+import okhttp3.HttpUrl.Companion.toHttpUrl
+import java.io.IOException
+
+fun makeDriveApiCall(context: Context, authState: AuthState, url: String, folderId: String,
+ callback: (String?, Exception?) -> Unit) {
+ val authService = AuthorizationService(context)
+ // _ = idToken
+ authState.performActionWithFreshTokens(authService) { accessToken, _, ex ->
+ authService.dispose()
+ if (ex != null) {
+ callback(null, ex)
+ return@performActionWithFreshTokens
+ }
+
+ val urlBuilder = url.toHttpUrl().newBuilder()
+ urlBuilder.addQueryParameter("q", "'$folderId' in parents")
+ val updatedUrl = urlBuilder.build()
+
+ val request = Request.Builder()
+ .url(updatedUrl)
+ .header("Authorization", "Bearer $accessToken")
+ .build()
+
+ OkHttpClient().newCall(request).enqueue(object : Callback {
+ override fun onFailure(call: Call, e: IOException) {
+ callback(null, e)
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ val responseBody = response.body?.string()
+ callback(responseBody, null)
+ }
+ })
+ }
+}
diff --git a/app/src/main/java/com/bbc/denadrive/apihandlers/DriveResponseBody.kt b/app/src/main/java/com/bbc/denadrive/apihandlers/DriveResponseBody.kt
new file mode 100644
index 0000000..3f70d23
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/apihandlers/DriveResponseBody.kt
@@ -0,0 +1,8 @@
+package com.bbc.denadrive.apihandlers
+
+data class DriveResponseBody(
+ val nextPageToken: String?,
+ val kind: String,
+ val incompleteSearch: Boolean,
+ val files: List
+)
diff --git a/app/src/main/java/com/bbc/denadrive/apihandlers/MyFile.kt b/app/src/main/java/com/bbc/denadrive/apihandlers/MyFile.kt
new file mode 100644
index 0000000..22dec49
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/apihandlers/MyFile.kt
@@ -0,0 +1,8 @@
+package com.bbc.denadrive.apihandlers
+
+data class MyFile(
+ val kind: String,
+ val mimeType: String,
+ val id: String,
+ val name: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesHandler.kt b/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesHandler.kt
new file mode 100644
index 0000000..b140809
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesHandler.kt
@@ -0,0 +1,42 @@
+package com.bbc.denadrive.apihandlers
+
+import androidx.lifecycle.ViewModel
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.json.Json
+import okhttp3.Response
+
+class ResponsesHandler: ViewModel() {
+
+ var lastResponse: String = ""
+ var isComplete: Boolean = true
+ private lateinit var respBuilder: StringBuilder
+ private lateinit var lastResponseBody: DriveResponseBody
+
+ fun newResponseArrived(response: Response) {
+ if (isComplete) {
+ respBuilder = StringBuilder("$response")
+ }
+ else {
+ respBuilder.append("$response")
+ updateCompleteness()
+ }
+ }
+
+ private fun checkForCompleteness(): Pair {
+ return try {
+ Pair(true, Json.decodeFromString(respBuilder.toString()))
+ } catch (e: SerializationException) {
+ Pair(false, null)
+ }
+ }
+
+ private fun updateCompleteness() {
+ val pair = checkForCompleteness()
+ isComplete = pair.first
+ if (isComplete) {
+ lastResponse = respBuilder.toString()
+ lastResponseBody = pair.second!!
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/home/NeverLoggedInLogic.kt b/app/src/main/java/com/bbc/denadrive/home/NeverLoggedInLogic.kt
new file mode 100644
index 0000000..59567e6
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/home/NeverLoggedInLogic.kt
@@ -0,0 +1,92 @@
+package com.bbc.denadrive.home
+
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.util.Log
+import android.widget.Toast
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.security.crypto.EncryptedSharedPreferences
+import androidx.security.crypto.MasterKey
+import com.bbc.denadrive.HomeNotAuthActivity
+import com.bbc.denadrive.MainActivity
+import com.bbc.denadrive.home.ui.theme.DeNaDriveTheme
+import net.openid.appauth.AuthState
+
+class NeverLoggedInLogic : ComponentActivity() {
+
+ private lateinit var preferences: SharedPreferences
+ private lateinit var masterKey: MasterKey
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ 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
+ )
+
+ val authStateString = preferences.getString("authState", "unset")
+
+ val intent: Intent
+ if (authStateString == "unset") {
+ intent = Intent(this, HomeNotAuthActivity::class.java)
+ } else {
+ val authState = authStateString?.let { AuthState.jsonDeserialize(it) }
+ intent = if (authState?.isAuthorized == true) {
+ Intent(this, MainActivity::class.java)
+ }
+ else {
+ Toast.makeText(this, "Session expired, please log in again",
+ Toast.LENGTH_SHORT).show()
+ Intent(this, HomeNotAuthActivity::class.java)
+ }
+ }
+ startActivity(intent)
+// Toast.makeText(this, "should not make it here", Toast.LENGTH_SHORT).show()
+
+ enableEdgeToEdge()
+ setContent {
+ DeNaDriveTheme {
+ Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
+ Greeting5(
+ name = "Android",
+ modifier = Modifier.padding(innerPadding)
+ )
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun Greeting5(name: String, modifier: Modifier = Modifier) {
+ Text(
+ text = "Hello $name!",
+ modifier = modifier
+ )
+}
+
+@Preview(showBackground = true)
+@Composable
+fun GreetingPreview5() {
+ DeNaDriveTheme {
+ Greeting5("Android")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/home/ui/theme/Color.kt b/app/src/main/java/com/bbc/denadrive/home/ui/theme/Color.kt
new file mode 100644
index 0000000..6fe42a1
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/home/ui/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.bbc.denadrive.home.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val Purple40 = Color(0xFF6650a4)
+val PurpleGrey40 = Color(0xFF625b71)
+val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/home/ui/theme/Theme.kt b/app/src/main/java/com/bbc/denadrive/home/ui/theme/Theme.kt
new file mode 100644
index 0000000..8466dab
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/home/ui/theme/Theme.kt
@@ -0,0 +1,58 @@
+package com.bbc.denadrive.home.ui.theme
+
+import android.app.Activity
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+
+private val DarkColorScheme = darkColorScheme(
+ primary = Purple80,
+ secondary = PurpleGrey80,
+ tertiary = Pink80
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = Purple40,
+ secondary = PurpleGrey40,
+ tertiary = Pink40
+
+ /* Other default colors to override
+ background = Color(0xFFFFFBFE),
+ surface = Color(0xFFFFFBFE),
+ onPrimary = Color.White,
+ onSecondary = Color.White,
+ onTertiary = Color.White,
+ onBackground = Color(0xFF1C1B1F),
+ onSurface = Color(0xFF1C1B1F),
+ */
+)
+
+@Composable
+fun DeNaDriveTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/home/ui/theme/Type.kt b/app/src/main/java/com/bbc/denadrive/home/ui/theme/Type.kt
new file mode 100644
index 0000000..1942d92
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/home/ui/theme/Type.kt
@@ -0,0 +1,34 @@
+package com.bbc.denadrive.home.ui.theme
+
+import androidx.compose.material3.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ )
+ /* Other default text styles to override
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 22.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+ */
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/oauth/AuthStatePersistence.kt b/app/src/main/java/com/bbc/denadrive/oauth/AuthStatePersistence.kt
index 80b0e7d..3c3c974 100644
--- a/app/src/main/java/com/bbc/denadrive/oauth/AuthStatePersistence.kt
+++ b/app/src/main/java/com/bbc/denadrive/oauth/AuthStatePersistence.kt
@@ -1,2 +1,29 @@
package com.bbc.denadrive.oauth
+import android.content.Context
+import androidx.security.crypto.EncryptedSharedPreferences
+import androidx.security.crypto.MasterKey
+import net.openid.appauth.AuthState
+
+object AuthStatePersistence {
+
+ fun retrieveAuthState(context: Context): AuthState {
+ val masterKey = MasterKey.Builder(context)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build()
+
+ val preferences = EncryptedSharedPreferences.create(
+ context,
+ "authState",
+ masterKey,
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
+ )
+
+ preferences.getString("authState", null)?.let {
+ return AuthState.jsonDeserialize(it)
+ }
+ return AuthState(retrieveAuthServConf())
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt b/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt
new file mode 100644
index 0000000..5c8cc1e
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt
@@ -0,0 +1,175 @@
+package com.bbc.denadrive.oauth
+
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.util.Log
+import android.widget.Toast
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.graphicsLayer
+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 androidx.security.crypto.EncryptedSharedPreferences
+import androidx.security.crypto.MasterKey
+import com.bbc.denadrive.HomeNotAuthActivity
+import com.bbc.denadrive.MainActivity
+import com.bbc.denadrive.oauth.ui.theme.DeNaDriveTheme
+import net.openid.appauth.AuthState
+import net.openid.appauth.AuthorizationException
+import net.openid.appauth.AuthorizationResponse
+import net.openid.appauth.AuthorizationService
+
+class LoadingActivity : ComponentActivity() {
+
+ private lateinit var masterKey: MasterKey
+ private lateinit var preferences: SharedPreferences
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ enableEdgeToEdge()
+ setContent {
+ DeNaDriveTheme {
+ Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
+ LoadingScreen(modifier = Modifier.padding(innerPadding))
+ }
+ }
+ }
+
+ masterKey = MasterKey.Builder(this)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build()
+
+ 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 response = AuthorizationResponse.fromIntent(intent)
+ val exception = AuthorizationException.fromIntent(intent)
+ if (response != null) {
+ Toast.makeText(this, "Done!", Toast.LENGTH_SHORT).show()
+ authState?.update(response, exception)
+ Log.e("MainActivity", "authState: ${authState?.jsonSerializeString()}", )
+ with (preferences.edit()) {
+ this.remove("authState")
+ this.putString("authState", "${authState?.jsonSerializeString()}")
+ this.apply()
+ }
+ } else {
+ Toast.makeText(this, "Not done :( ${exception?.error}", Toast.LENGTH_SHORT).show()
+ }
+
+ val authService = AuthorizationService(this)
+ response?.createTokenExchangeRequest()?.let {
+ authService.performTokenRequest(
+ it
+ ) { resp, ex ->
+ if (resp != null) {
+ authState?.update(resp, ex)
+ with(preferences.edit()) {
+ this.remove("authState")
+ this.putString("authState", "${authState?.jsonSerializeString()}")
+ this.apply()
+ }
+ val intent = Intent(this, MainActivity::class.java)
+ startActivity(intent)
+ } else {
+ val intent = Intent(this, HomeNotAuthActivity::class.java)
+ startActivity(intent)
+ }
+ }
+ }
+
+ }
+}
+
+@Composable
+fun LoadingScreen(
+ modifier: Modifier = Modifier
+) {
+ // State to control the rotation animation
+ val rotation = remember { mutableFloatStateOf(0f) }
+
+ // Animate the rotation
+ LaunchedEffect(Unit) {
+ while (true) {
+ rotation.floatValue += 10f
+ if (rotation.floatValue >= 360f) rotation.floatValue = 0f
+ kotlinx.coroutines.delay(16) // Approximately 60 FPS
+ }
+ }
+
+ Box(
+ modifier = modifier
+ .fillMaxSize()
+ .padding(16.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center
+ ) {
+ // Rotating Circular Progress Indicator
+ CircularProgressIndicator(
+ modifier = Modifier
+ .size(64.dp)
+ .graphicsLayer(rotationZ = rotation.floatValue),
+ color = Color.Blue
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ // Loading text
+ Text(
+ text = "Loading",
+ fontSize = 20.sp,
+ fontWeight = FontWeight.Bold,
+ color = Color.Black
+ )
+ }
+ }
+}
+
+@Composable
+fun Greeting6(name: String, modifier: Modifier = Modifier) {
+ Text(
+ text = "Hello $name!",
+ modifier = modifier
+ )
+}
+
+@Preview(showBackground = true)
+@Composable
+fun GreetingPreview6() {
+ DeNaDriveTheme {
+ Greeting6("Android")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Color.kt b/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Color.kt
new file mode 100644
index 0000000..39fed0d
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.bbc.denadrive.oauth.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val Purple40 = Color(0xFF6650a4)
+val PurpleGrey40 = Color(0xFF625b71)
+val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Theme.kt b/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Theme.kt
new file mode 100644
index 0000000..f42f26c
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Theme.kt
@@ -0,0 +1,58 @@
+package com.bbc.denadrive.oauth.ui.theme
+
+import android.app.Activity
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+
+private val DarkColorScheme = darkColorScheme(
+ primary = Purple80,
+ secondary = PurpleGrey80,
+ tertiary = Pink80
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = Purple40,
+ secondary = PurpleGrey40,
+ tertiary = Pink40
+
+ /* Other default colors to override
+ background = Color(0xFFFFFBFE),
+ surface = Color(0xFFFFFBFE),
+ onPrimary = Color.White,
+ onSecondary = Color.White,
+ onTertiary = Color.White,
+ onBackground = Color(0xFF1C1B1F),
+ onSurface = Color(0xFF1C1B1F),
+ */
+)
+
+@Composable
+fun DeNaDriveTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Type.kt b/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Type.kt
new file mode 100644
index 0000000..91e7124
--- /dev/null
+++ b/app/src/main/java/com/bbc/denadrive/oauth/ui/theme/Type.kt
@@ -0,0 +1,34 @@
+package com.bbc.denadrive.oauth.ui.theme
+
+import androidx.compose.material3.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ )
+ /* Other default text styles to override
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 22.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+ */
+)
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7a4ba83..79a47a2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -4,4 +4,6 @@
TestBah
Speremm
HomeNotAuthActivity
+ NeverLoggedInLogic
+ LoadingActivity
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index c35a82c..52d922a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,11 +2,13 @@
agp = "8.9.0"
appauth = "0.11.1"
converterGson = "2.9.0"
+googleAuthLibraryOauth2Http = "1.15.0"
kotlin = "2.0.21"
coreKtx = "1.15.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
+kotlinxSerializationJson = "1.5.0"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.10.1"
composeBom = "2025.02.00"
@@ -20,6 +22,7 @@ androidx-navigation-compose = { module = "androidx.navigation:navigation-compose
androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "securityCrypto" }
appauth = { module = "net.openid:appauth", version.ref = "appauth" }
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
+google-auth-library-oauth2-http = { module = "com.google.auth:google-auth-library-oauth2-http", version.ref = "googleAuthLibraryOauth2Http" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
@@ -33,6 +36,7 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "converterGson" }