diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3aecb6d..89a4a2f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -26,6 +26,16 @@ android:supportsRtl="true" android:theme="@style/Theme.DeNaDrive" tools:targetApi="31"> + + + + - Log.e("MOO", "populateTree: and here", ) if (exception != null) { - Log.e("RESPONSE EXCEPTION", "populateTree: ${exception.message}", ) + Log.e("RESPONSE EXCEPTION", "populateTree: ${exception.message}") } else { val responseBody = ResponsesHandler.newResponseArrived(response) if (responseBody != null) { tree.addChildren( - responseBody.files.map { file -> FolderTree( - value = file, - ownPath = "${tree.ownPath}/${file.id}", - parent = tree - ) } + responseBody.files.map { file -> + FolderTree( + value = file, + ownPath = "${tree.ownPath}/${file.id}", + parent = tree + ) + } ) - Log.e("CURRENT", "populateTree: ${tree.value}", ) - Log.e("CHILDREN", "populateTree: ${responseBody.files}", ) + tree.loaded = true for (child in tree.getChildren()) { if (!child.isLeaf()) populateTree(context, child) } - Log.e("MOO", "populateTree: also here?", ) } } } diff --git a/app/src/main/java/com/bbc/denadrive/FolderTree.kt b/app/src/main/java/com/bbc/denadrive/FolderTree.kt index bc04d0e..56d158a 100644 --- a/app/src/main/java/com/bbc/denadrive/FolderTree.kt +++ b/app/src/main/java/com/bbc/denadrive/FolderTree.kt @@ -23,7 +23,8 @@ class FolderTree( val value: MyFile, val ownPath: String = value.id, private val children: MutableList = mutableListOf(), - val parent: FolderTree? = null + val parent: FolderTree? = null, + var loaded: Boolean = false ) { fun isLeaf(): Boolean { diff --git a/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt b/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt index 6f2e6d5..b34026b 100644 --- a/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt +++ b/app/src/main/java/com/bbc/denadrive/HomeNotAuthActivity.kt @@ -57,7 +57,7 @@ class HomeNotAuthActivity : ComponentActivity() { DeNaDriveTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> val logo = painterResource(id = R.drawable.vecchiaicona_) - LogoWithCaptionAndButton ( + LogoWithCaptionAndButton( logo = logo, caption = "DeNa Drive", buttonText = "Log in", @@ -77,16 +77,25 @@ class HomeNotAuthActivity : ComponentActivity() { "com.bbc.denadrive:/oauth2redirect".toUri() ) val authRequest = authRequestBuilder - .setScope("https://www.googleapis.com/auth/drive") + .setScopes( + listOf( + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.apps" + ) + ) .build() val authService = AuthorizationService(this) authService.performAuthorizationRequest( authRequest, - PendingIntent.getActivity(this, 0, Intent(this, LoadingActivity::class.java), - PendingIntent.FLAG_MUTABLE), - PendingIntent.getActivity(this, 0, Intent(this, HomeNotAuthActivity::class.java), - PendingIntent.FLAG_MUTABLE) + PendingIntent.getActivity( + this, 0, Intent(this, LoadingActivity::class.java), + PendingIntent.FLAG_MUTABLE + ), + PendingIntent.getActivity( + this, 0, Intent(this, HomeNotAuthActivity::class.java), + PendingIntent.FLAG_MUTABLE + ) ) } } diff --git a/app/src/main/java/com/bbc/denadrive/MainActivity.kt b/app/src/main/java/com/bbc/denadrive/MainActivity.kt index 15b3f6e..ec8301e 100644 --- a/app/src/main/java/com/bbc/denadrive/MainActivity.kt +++ b/app/src/main/java/com/bbc/denadrive/MainActivity.kt @@ -32,6 +32,7 @@ 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 @@ -42,7 +43,12 @@ import okhttp3.HttpUrl class MainActivity : ComponentActivity() { private lateinit var responsesViewer: ResponsesViewer - private var currentPath: String = "root" + private val exportSupportedFiles: List = listOf( + "document", + "drawing", + "presentation", + "spreadsheet", + ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -64,6 +70,7 @@ class MainActivity : ComponentActivity() { finish() } } + val fileDownloader = FileDownloader(this) // goToFolder(parentFolder = "root", forward = true, isFirstRequest = true) @@ -71,16 +78,28 @@ class MainActivity : ComponentActivity() { // val navController = rememberNavController() ScaffoldWithSidebar( responsesViewer, - { name -> + { file -> Toast.makeText( this, - "You pressed the file $name", + "You pressed the file ${file.name}", Toast.LENGTH_SHORT ).show() + if (file.mimeType.substringAfterLast(".") in exportSupportedFiles) { + fileDownloader.downloadFile( + "https://www.googleapis.com/drive/v3/files/${file.id}/export", + "application/pdf" + ) + } else { + Toast.makeText( + this, + "This file has no default action. Download support coming soon", + Toast.LENGTH_SHORT + ).show() + } }, { folder -> responsesViewer.currentFolderTree.value = - responsesViewer.currentFolderTree.value.stepForward(folder) + responsesViewer.currentFolderTree.value.stepForward(folder.id) // responsesViewer.currentFolderTree.value = // responsesViewer.currentFolderTree.value.goToPath("$folder/") // parent -> @@ -94,10 +113,17 @@ class MainActivity : ComponentActivity() { } -// private fun getApps() { -// val myUrl = "https://www.googleapis.com/drive/v3/apps" -// makeNewRequest(myUrl) { } -// } + 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" diff --git a/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt b/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt index 874809b..f480905 100644 --- a/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt +++ b/app/src/main/java/com/bbc/denadrive/apihandlers/ApiCalls.kt @@ -32,8 +32,9 @@ fun makeDriveApiCall( authState: AuthState, url: String, // folderId: String, - builderModifier:(HttpUrl.Builder) -> Unit, - callback: (String?, Exception?) -> Unit) { + builderModifier: (HttpUrl.Builder) -> Unit, + callback: (String?, Exception?) -> Unit +) { val authService = AuthorizationService(context) // _ = idToken authState.performActionWithFreshTokens(authService) { accessToken, _, ex -> diff --git a/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt b/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt new file mode 100644 index 0000000..2cacef2 --- /dev/null +++ b/app/src/main/java/com/bbc/denadrive/filehandling/FileDownloader.kt @@ -0,0 +1,88 @@ +package com.bbc.denadrive.filehandling + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.util.Log +import androidx.core.content.FileProvider +import com.bbc.denadrive.oauth.AuthStatePersistence +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.HttpUrl.Companion.toHttpUrl +import java.io.File +import java.io.FileOutputStream +import java.net.HttpURLConnection +import java.net.URL + +class FileDownloader(private val context: Context) { + + fun downloadFile(fileUrl: String, mimeType: String) { + CoroutineScope(Dispatchers.IO).launch { + val tempFile = downloadIt(fileUrl, mimeType) + withContext(Dispatchers.Main) { + tempFile?.let { + openFile(it) + } + } + } + } + + private fun downloadIt(fileUrl: String, mimeType: String): File? { + var tempFile: File? = null + val authState = AuthStatePersistence.retrieveAuthState(context) + + 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 + 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) + + val buffer = ByteArray(1024) + var bytesRead: Int + while (inputStream.read(buffer).also { bytesRead = it } != -1) { + outputStream.write(buffer, 0, bytesRead) + } + + outputStream.close() + inputStream.close() + urlConnection.disconnect() + } else { + Log.e("FileDownloader", "Error: ${urlConnection.responseCode} - ${urlConnection.responseMessage}") + } + + } catch (e: Exception) { + Log.e("FileDownloader", "downloadIt: download failed", e) + } + + return tempFile + } + + + private fun openFile(file: File) { + val uri: Uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file) + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(uri, "application/pdf") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + context.startActivity(intent) + } + +} \ No newline at end of file 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 e6fe402..0b17188 100644 --- a/app/src/main/java/com/bbc/denadrive/home/DebugScreens.kt +++ b/app/src/main/java/com/bbc/denadrive/home/DebugScreens.kt @@ -53,8 +53,8 @@ import com.bbc.denadrive.apihandlers.ResponsesViewer @Composable fun ScaffoldWithSidebar( responsesViewer: ResponsesViewer, - onFileClick: (String) -> Unit, - onFolderClick: (String) -> Unit, + onFileClick: (MyFile) -> Unit, + onFolderClick: (MyFile) -> Unit, doIt: () -> Unit, ) { // State to control the drawer @@ -245,8 +245,8 @@ fun Loading( @Composable fun AnotherVisualizer( responsesViewer: ResponsesViewer, - onFileClick: (String) -> Unit, - onFolderClick: (String) -> Unit + onFileClick: (MyFile) -> Unit, + onFolderClick: (MyFile) -> Unit ) { val currentFolderTree = responsesViewer.currentFolderTree.value val updater1 = responsesViewer.updater1.value @@ -256,6 +256,10 @@ fun AnotherVisualizer( Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text(text = "How did you get here? You're inside a file...") } + } else if (!currentFolderTree.loaded) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Loading() + } } else if (currentFolderTree.getChildren().isEmpty()) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text("Empty folder") @@ -263,8 +267,8 @@ fun AnotherVisualizer( } } else { val fileList = currentFolderTree.getChildren().map { tree -> tree.value } - Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.value}", ) - Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.getChildren()}", ) +// Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.value}", ) +// Log.e("Visualizer", "AnotherVisualizer: ${currentFolderTree.getChildren()}", ) Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.TopCenter) { LazyColumn { items(fileList) { file -> @@ -273,9 +277,7 @@ fun AnotherVisualizer( val onClick = if (isFolder) onFolderClick else onFileClick LogoTextBox(logo, file.name) { - onClick( - if (isFolder) file.id else file.name - ) + onClick(file) } } } @@ -284,7 +286,7 @@ fun AnotherVisualizer( } fun getId(mimeType: String): Int { - val extracted = mimeType.drop("application/vnd.google-apps.".length) + val extracted = mimeType.substringAfterLast(".") return when (extracted) { "document" -> R.drawable.docslogo_ok "presentation" -> R.drawable.slideslogo_ok diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..d2e2c8d --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,4 @@ + + + +