From c5f06a9db99999c1a5aa5a37c233a318acaeeb90 Mon Sep 17 00:00:00 2001 From: AlbYoda Date: Thu, 29 May 2025 23:23:06 +0200 Subject: [PATCH] Added some stuff. --- .../java/com/bbc/denadrive/DriveRequester.kt | 5 +- .../com/bbc/denadrive/HomeNotAuthActivity.kt | 3 +- .../java/com/bbc/denadrive/MainActivity.kt | 141 ++++-------------- .../denadrive/apihandlers/ResponsesViewer.kt | 45 +++--- .../denadrive/filehandling/FileDownloader.kt | 41 +++-- .../com/bbc/denadrive/home/DebugScreens.kt | 63 ++++++-- .../bbc/denadrive/oauth/LoadingActivity.kt | 3 +- 7 files changed, 124 insertions(+), 177 deletions(-) diff --git a/app/src/main/java/com/bbc/denadrive/DriveRequester.kt b/app/src/main/java/com/bbc/denadrive/DriveRequester.kt index 75613a1..0cc044a 100644 --- a/app/src/main/java/com/bbc/denadrive/DriveRequester.kt +++ b/app/src/main/java/com/bbc/denadrive/DriveRequester.kt @@ -16,10 +16,9 @@ object DriveRequester { builderModifier: (HttpUrl.Builder) -> Unit, callback: (String?, Exception?) -> Unit ) { - val authPersistence = AuthStatePersistence - val authState = authPersistence.retrieveAuthState(context) + val authState = AuthStatePersistence.retrieveAuthState(context) makeDriveApiCall(context, authState, url, builderModifier, callback) - authPersistence.putAuthState(context, authState) + AuthStatePersistence.putAuthState(context, authState) } fun populateTree( diff --git a/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt b/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt index b34026b..a37bfda 100644 --- a/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt +++ b/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt @@ -80,7 +80,8 @@ class HomeNotAuthActivity : ComponentActivity() { .setScopes( listOf( "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.apps" + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email", ) ) .build() diff --git a/app/src/main/java/com/bbc/denadrive/MainActivity.kt b/app/src/main/java/com/bbc/denadrive/MainActivity.kt index ec8301e..4d367a8 100644 --- a/app/src/main/java/com/bbc/denadrive/MainActivity.kt +++ b/app/src/main/java/com/bbc/denadrive/MainActivity.kt @@ -13,32 +13,24 @@ You should have received a copy of the GNU General Public License along with DeN If not, see . */ +/** + * This file contains the MainActivity activity. + * The activity is responsible for the everyday usage of the app. + * It provides a UI to do all sort of operations + */ + package com.bbc.denadrive -import android.content.Intent import android.os.Bundle import android.util.Log import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.addCallback import androidx.activity.compose.setContent -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.navigation.compose.rememberNavController -import com.bbc.denadrive.apihandlers.DriveResponseBody -import com.bbc.denadrive.apihandlers.MyFile -import com.bbc.denadrive.apihandlers.ResponsesHandler import com.bbc.denadrive.apihandlers.ResponsesViewer -import com.bbc.denadrive.apihandlers.makeDriveApiCall import com.bbc.denadrive.filehandling.FileDownloader import com.bbc.denadrive.home.ScaffoldWithSidebar import com.bbc.denadrive.oauth.AuthStatePersistence -import com.bbc.denadrive.ui.theme.DeNaDriveTheme -import net.openid.appauth.AuthorizationException -import net.openid.appauth.AuthorizationResponse -import okhttp3.HttpUrl class MainActivity : ComponentActivity() { @@ -57,10 +49,7 @@ class MainActivity : ComponentActivity() { DriveRequester.populateTree(this, responsesViewer.folderTree) -// onBackPressedDispatcher.addCallback(this) { -// if (currentPath != "root") goToFolder("", false) -// else finish() -// } + Log.e("vediamo", AuthStatePersistence.retrieveAuthState(this).jsonSerializeString()) onBackPressedDispatcher.addCallback(this) { if (responsesViewer.currentFolderTree.value.parent != null) { @@ -72,7 +61,6 @@ class MainActivity : ComponentActivity() { } val fileDownloader = FileDownloader(this) -// goToFolder(parentFolder = "root", forward = true, isFirstRequest = true) setContent { // val navController = rememberNavController() @@ -84,10 +72,11 @@ class MainActivity : ComponentActivity() { "You pressed the file ${file.name}", Toast.LENGTH_SHORT ).show() - if (file.mimeType.substringAfterLast(".") in exportSupportedFiles) { + /*if (file.mimeType.substringAfterLast(".") in exportSupportedFiles) { + Log.e("MYTAG", "Supported!", ) fileDownloader.downloadFile( - "https://www.googleapis.com/drive/v3/files/${file.id}/export", - "application/pdf" + file, + exported = true ) } else { Toast.makeText( @@ -95,109 +84,31 @@ class MainActivity : ComponentActivity() { "This file has no default action. Download support coming soon", Toast.LENGTH_SHORT ).show() - } + }*/ + fileDownloader.downloadFile( + file, + exported = file.mimeType.substringAfterLast(".") in exportSupportedFiles + ) }, { folder -> responsesViewer.currentFolderTree.value = responsesViewer.currentFolderTree.value.stepForward(folder.id) -// responsesViewer.currentFolderTree.value = -// responsesViewer.currentFolderTree.value.goToPath("$folder/") -// parent -> -// goToFolder(parent, true) } ) { responsesViewer.toggleUpdaters() -// getApps() + DriveRequester.makeNewRequest( + this, + "https://people.googleapis.com/v1/people/me?personFields=emailAddresses", + {}) { resp, ex -> + if (ex != null) { + Log.e("noGood", "$ex") + } else { + Log.e("good", "$resp") + } + } } } } - - - private fun getApps() { - val myUrl = "https://www.googleapis.com/drive/v3/apps" - DriveRequester.makeNewRequest(this, myUrl, { }) { - response, exception -> - if (exception != null) { - Log.e("notGood", "getApps: $exception", ) - } else { - Log.e("GOOD", "getApps: $response", ) - } - } - } - -// private fun askForFolder(folderId: String) { -// val myUrl = "https://www.googleapis.com/drive/v3/files" -// makeNewRequest(myUrl, { builder -> -// builder.addQueryParameter("q", "'$folderId' in parents") -// }) { response, exception -> -// if (exception != null) { -// Log.e("TAG", "askForFolder: Something went wrong") -// } else { -// // fai quel che ti pare -// } -// } -// } -// -// private fun goToFolder( -// parentFolder: String, forward: Boolean, isFirstRequest: Boolean = false -// ) { -// responsesViewer.lastResponseBody.value = null -// val actualFolder: String -// if (!isFirstRequest) { -// if (forward) { -// currentPath += "/$parentFolder" -// actualFolder = parentFolder -// } else { -// currentPath = currentPath.substringBeforeLast("/") -// actualFolder = -// if (currentPath != "root") currentPath.substringAfterLast("/") -// else "root" -// } -// } else actualFolder = parentFolder -// -// val myUrl = "https://www.googleapis.com/drive/v3/files?trashed=false&orderBy=folder" -// makeNewRequest(myUrl, { builder -> -// builder.addQueryParameter("q", "'$actualFolder' in parents") -// }) { response, exception -> -// if (exception != null) { -// Log.e("ECCOLO", "${exception.cause}") -// Log.e("ECCOLO", "${exception.message}") -// } else { -// Log.e("UOOOO", "$response") -// responsesViewer.newResponseArrived(response) -// } -// } -// } -// -// private fun makeNewRequest( -// url: String, -// builderModifier: (HttpUrl.Builder) -> Unit, -// callback: (String?, Exception?) -> Unit -// ) { -// val authPersistence = AuthStatePersistence -// val authState = authPersistence.retrieveAuthState(this) -// makeDriveApiCall(this, authState, url, builderModifier, callback) -// authPersistence.putAuthState(this, authState) -// } - -// override fun onNewIntent(intent: Intent) { -// super.onNewIntent(intent) -// val resp = AuthorizationResponse.fromIntent(intent) -// val ex = AuthorizationException.fromIntent(intent) -// if (resp != null) { -// Toast.makeText(this, "YES", Toast.LENGTH_SHORT).show() -// } else { -// if (ex != null) { -// Toast.makeText(this, "NOPE ${ex.error}", Toast.LENGTH_SHORT).show() -// } -// } -// -// setContent { -//// val navController = rememberNavController() -//// ScaffoldWithSidebar(navController) { } -// Greeting("bah") -// } -// } } //@Composable diff --git a/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesViewer.kt b/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesViewer.kt index a8de4b8..a599457 100644 --- a/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesViewer.kt +++ b/app/src/main/java/com/bbc/denadrive/apihandlers/ResponsesViewer.kt @@ -23,7 +23,7 @@ import com.bbc.denadrive.FolderTree class ResponsesViewer: ViewModel() { - val rootFolder: MyFile = MyFile( + private val rootFolder: MyFile = MyFile( kind = "drive#file", mimeType = "application/vnd.google-apps.folder", id = "root", @@ -42,31 +42,26 @@ class ResponsesViewer: ViewModel() { updater2.value = !updater2.value } -// private var lastResponse: String = "" -// private var isComplete: Boolean = true -// private lateinit var respBuilder: StringBuilder - - fun newResponseArrived(response: String?) { - if (response == null) return - lastResponseBody.value = ResponsesHandler.newResponseArrived(response) + /*private var lastResponse: String = "" + private var isComplete: Boolean = true + private lateinit var respBuilder: StringBuilder + + + private fun checkForCompleteness(): Pair { + return try { + Pair(true, Json.decodeFromString(respBuilder.toString())) + } catch (e: SerializationException) { + Pair(false, null) + } } - -// 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.value = pair.second -// } -// } + private fun updateCompleteness() { + val pair = checkForCompleteness() + isComplete = pair.first + if (isComplete) { + lastResponse = respBuilder.toString() + lastResponseBody.value = pair.second + } + }*/ } \ No newline at end of file diff --git a/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt b/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt index 2cacef2..62cb860 100644 --- a/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt +++ b/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.net.Uri import android.util.Log import androidx.core.content.FileProvider +import com.bbc.denadrive.apihandlers.MyFile import com.bbc.denadrive.oauth.AuthStatePersistence import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -18,40 +19,33 @@ import java.net.URL class FileDownloader(private val context: Context) { - fun downloadFile(fileUrl: String, mimeType: String) { + fun downloadFile(file: MyFile, exported: Boolean) { CoroutineScope(Dispatchers.IO).launch { - val tempFile = downloadIt(fileUrl, mimeType) + val tempFile = downloadIt(file, exported) withContext(Dispatchers.Main) { tempFile?.let { - openFile(it) + openFile(it, exported) } } } } - private fun downloadIt(fileUrl: String, mimeType: String): File? { + private fun downloadIt(file: MyFile, exported: Boolean): File? { var tempFile: File? = null val authState = AuthStatePersistence.retrieveAuthState(context) + val query = if (exported) "export?mimeType=application/pdf" else "download" + val fileUrl = "https://www.googleapis.com/drive/v3/files/${file.id}/$query" + Log.e("SEE", fileUrl, ) try { - tempFile = File.createTempFile("tempFile", ".pdf", context.cacheDir) -// val builder = fileUrl.toHttpUrl().newBuilder() -// builder.addQueryParameter("mimeType", mimeType) -// val urlConnection = builder.build().toUrl().openConnection() as HttpURLConnection - val urlConnection = URL("$fileUrl?mimeType=application/pdf").openConnection() as HttpURLConnection + tempFile = + File.createTempFile(file.name, if (exported) ".pdf" else "", context.cacheDir) + val urlConnection = URL(fileUrl).openConnection() as HttpURLConnection urlConnection.setRequestProperty("Authorization", "Bearer ${authState.accessToken}") urlConnection.connect() -// val inputStream1 = urlConnection.inputStream -// val buffer1 = ByteArray(4) -// inputStream1.read(buffer1) -// val header = String(buffer1) -// if (!header.startsWith("%PDF")) { -// Log.e("FileDownloader", "Downloaded file is not a valid PDF") -// } if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) { - Log.e("MA", "downloadIt: andato", ) val inputStream = urlConnection.inputStream val outputStream = FileOutputStream(tempFile) @@ -65,7 +59,10 @@ class FileDownloader(private val context: Context) { inputStream.close() urlConnection.disconnect() } else { - Log.e("FileDownloader", "Error: ${urlConnection.responseCode} - ${urlConnection.responseMessage}") + Log.e( + "FileDownloader", + "Error: ${urlConnection.responseCode} - ${urlConnection.responseMessage}" + ) } } catch (e: Exception) { @@ -76,10 +73,12 @@ class FileDownloader(private val context: Context) { } - private fun openFile(file: File) { - val uri: Uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file) + private fun openFile(file: File, exported: Boolean) { + val uri: Uri = + FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file) val intent = Intent(Intent.ACTION_VIEW).apply { - setDataAndType(uri, "application/pdf") + if (exported) setDataAndType(uri, "application/pdf") + else setData(uri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } context.startActivity(intent) diff --git a/app/src/main/java/com/bbc/denadrive/home/DebugScreens.kt b/app/src/main/java/com/bbc/denadrive/home/DebugScreens.kt index 0b17188..47823bb 100644 --- a/app/src/main/java/com/bbc/denadrive/home/DebugScreens.kt +++ b/app/src/main/java/com/bbc/denadrive/home/DebugScreens.kt @@ -41,6 +41,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.ui.graphics.painter.Painter import androidx.compose.foundation.Image import androidx.compose.foundation.clickable +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource @@ -182,7 +184,7 @@ fun MyListVisualizer( Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.TopCenter) { LazyColumn { items(fileList) { file -> - val logo = painterResource(id = getId(file.mimeType)) + val logo = painterResource(id = getLogoId(file.mimeType)) val isFolder = file.mimeType.endsWith("folder") val onClick = if (isFolder) onFolderClick else onFileClick @@ -252,7 +254,7 @@ fun AnotherVisualizer( val updater1 = responsesViewer.updater1.value val updater2 = responsesViewer.updater2.value if (currentFolderTree.isLeaf() && (updater1 || updater2)) { - Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.value}", ) + Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.value}") Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(text = "How did you get here? You're inside a file...") } @@ -263,29 +265,49 @@ fun AnotherVisualizer( } else if (currentFolderTree.getChildren().isEmpty()) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text("Empty folder") -// Loading() } } else { + val state = rememberLazyListState() val fileList = currentFolderTree.getChildren().map { tree -> tree.value } -// Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.value}", ) -// Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.getChildren()}", ) Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.TopCenter) { - LazyColumn { - items(fileList) { file -> - val logo = painterResource(id = getId(file.mimeType)) + LazyColumn ( + state = state + ) { + itemsIndexed(fileList) { index, file -> + val logo = painterResource(id = getLogoId(file.mimeType)) val isFolder = file.mimeType.endsWith("folder") val onClick = if (isFolder) onFolderClick else onFileClick - LogoTextBox(logo, file.name) { - onClick(file) + + var mod = Modifier + .fillMaxWidth() + .background(color = MaterialTheme.colorScheme.onBackground) +// .padding(horizontal = 1.dp) + + mod = if (index == 0) { + mod.padding(vertical = 1.dp) + } else { + mod.padding(bottom = 1.dp) } + + mod = mod + .background(color = MaterialTheme.colorScheme.background) + .clickable { + onClick(file) + } + + FileVisualizer( + logo, + file.name, + mod + ) } } } } } -fun getId(mimeType: String): Int { +fun getLogoId(mimeType: String): Int { val extracted = mimeType.substringAfterLast(".") return when (extracted) { "document" -> R.drawable.docslogo_ok @@ -295,6 +317,24 @@ fun getId(mimeType: String): Int { } } +@Composable +fun FileVisualizer( + logoPainter: Painter, + text: String, + modifier: Modifier = Modifier +) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = modifier + ) { + Image( + painter = logoPainter, + contentDescription = "Item logo" + ) + Text(text = text, style = MaterialTheme.typography.titleLarge) + } +} + @Composable fun LogoTextBox( logoPainter: Painter, @@ -335,3 +375,4 @@ fun LogoTextBox( } } } + diff --git a/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt b/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt index 462068a..fc5e7ff 100644 --- a/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt +++ b/app/src/main/java/com/bbc/denadrive/oauth/LoadingActivity.kt @@ -66,7 +66,7 @@ class LoadingActivity : ComponentActivity() { setContent { DeNaDriveTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - LoadingScreen(modifier = Modifier.padding(innerPadding)) + LoadingScreen(text = "Loading...", modifier = Modifier.padding(innerPadding)) } } } @@ -106,6 +106,7 @@ class LoadingActivity : ComponentActivity() { @Composable fun LoadingScreen( + text: String, modifier: Modifier = Modifier ) { // State to control the rotation animation