Added some stuff.

This commit is contained in:
AlbYoda 2025-05-29 23:23:06 +02:00
parent a92f970aaf
commit c5f06a9db9
Signed by untrusted user who does not match committer: AlbYoda
GPG key ID: A539D876452F16FF
7 changed files with 124 additions and 177 deletions

View file

@ -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(

View file

@ -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()

View file

@ -13,32 +13,24 @@ You should have received a copy of the GNU General Public License along with DeN
If not, see <https://www.gnu.org/licenses/>.
*/
/**
* 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

View file

@ -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<DriveResponseBody>(response)
/*private var lastResponse: String = ""
private var isComplete: Boolean = true
private lateinit var respBuilder: StringBuilder
private fun checkForCompleteness(): Pair<Boolean, DriveResponseBody?> {
return try {
Pair(true, Json.decodeFromString<DriveResponseBody>(respBuilder.toString()))
} catch (e: SerializationException) {
Pair(false, null)
}
}
// private fun checkForCompleteness(): Pair<Boolean, DriveResponseBody?> {
// return try {
// Pair(true, Json.decodeFromString<DriveResponseBody>(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
}
}*/
}

View file

@ -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)

View file

@ -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(
}
}
}

View file

@ -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