Skip to content

Conversation

@SmilingPixel
Copy link
Owner

This pull request introduces Google Drive integration into the application, enabling users to authorize, access, and manage their files in Google Drive from within the app. The changes include new client interfaces, Android implementation, UI updates for authorization, and necessary dependency and configuration updates.

Google Drive Integration

  • Added a multiplatform CloudDriveClient interface, including models for DriveFile and UserInfo, to abstract cloud drive operations (composeApp/src/commonMain/kotlin/io/github/smiling_pixel/client/CloudDriveClient.kt).
  • Implemented the Android-specific GoogleDriveClient with full support for authorization, file/folder management, and user info retrieval, using Google APIs (composeApp/src/androidMain/kotlin/io/github/smiling_pixel/client/GoogleDriveClient.kt).
  • Added GoogleSignInHelper to handle Google Sign-In flows and activity result management on Android (composeApp/src/androidMain/kotlin/io/github/smiling_pixel/client/GoogleSignInHelper.kt).

UI Enhancements

  • Updated the SettingsScreen to allow users to authorize Google Drive, view account info, and revoke access, reflecting authorization state and user details in the UI (composeApp/src/commonMain/kotlin/io/github/smiling_pixel/SettingsScreen.kt). [1] [2] [3]
  • Registered the Google Sign-In launcher in MainActivity to support the authorization flow (composeApp/src/androidMain/kotlin/io/github/smiling_pixel/MainActivity.kt).

Dependency and Configuration Updates

  • Added required Google Drive and Google Sign-In libraries to Android and JVM targets in build.gradle.kts (composeApp/build.gradle.kts). [1] [2]
  • Updated application namespace, package name, and application ID to io.github.smiling_pixel.mark_day for consistency across Android and desktop builds (composeApp/build.gradle.kts, AndroidManifest.xml). [1] [2] [3]

Copilot AI review requested due to automatic review settings January 22, 2026 01:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Google Drive integration to the multiplatform application, enabling cloud storage and synchronization capabilities. The implementation includes platform-specific clients for Android and JVM (desktop), with stub implementations for Web and a missing iOS implementation.

Changes:

  • Added a multiplatform CloudDriveClient interface with platform-specific implementations
  • Integrated Google Drive SDK dependencies for Android and JVM targets
  • Updated SettingsScreen UI to support Google Drive authorization and account management
  • Updated application namespace and package identifiers to io.github.smiling_pixel.mark_day

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Added Google Drive and OAuth client library dependencies
composeApp/src/commonMain/kotlin/io/github/smiling_pixel/client/CloudDriveClient.kt Defined common CloudDriveClient interface with DriveFile and UserInfo models
composeApp/src/androidMain/kotlin/io/github/smiling_pixel/client/GoogleDriveClient.kt Android implementation using Google Play Services Auth and Drive API
composeApp/src/androidMain/kotlin/io/github/smiling_pixel/client/GoogleSignInHelper.kt Helper object for managing Google Sign-In flow via ActivityResult API
composeApp/src/jvmMain/kotlin/io/github/smiling_pixel/client/GoogleDriveClient.kt JVM implementation using OAuth2 with browser-based authorization
composeApp/src/wasmJsMain/kotlin/io/github/smiling_pixel/client/GoogleDriveClient.kt Stub implementation with NotImplementedError responses
composeApp/src/commonMain/kotlin/io/github/smiling_pixel/SettingsScreen.kt Added Google Drive authorization UI with sign-in/sign-out functionality
composeApp/src/androidMain/kotlin/io/github/smiling_pixel/MainActivity.kt Registered ActivityResultLauncher for Google Sign-In flow
composeApp/src/androidMain/AndroidManifest.xml Updated activity name to use fully qualified package
composeApp/build.gradle.kts Added Google Drive dependencies and updated namespace/applicationId

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +48 to +52
private val CREDENTIALS_FILE_PATH = "/credentials.json"

private fun getFlow(httpTransport: NetHttpTransport): GoogleAuthorizationCodeFlow {
val inputStream = GoogleDriveClient::class.java.getResourceAsStream(CREDENTIALS_FILE_PATH)
?: throw FileNotFoundException("Resource not found: $CREDENTIALS_FILE_PATH. Please obtain credentials.json from Google Cloud Console.")
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JVM implementation requires a credentials.json file in the resources directory to function, but this dependency is not documented. Consider adding documentation (in comments, README, or error messages) explaining how to obtain and configure this file from the Google Cloud Console, or the application will fail at runtime for JVM users.

Copilot uses AI. Check for mistakes.
val result = GoogleSignInHelper.launchSignIn(signInIntent)

if (result != null && result.resultCode == android.app.Activity.RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation on line 86. The line uses an extra space before the val keyword, while lines 87-95 have proper indentation. This should be aligned with the surrounding code for consistency.

Suggested change
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)

Copilot uses AI. Check for mistakes.
Comment on lines +87 to +98
try {
val account = task.getResult(ApiException::class.java)
if (account != null) {
val email = account.email
if (email != null) {
initService(email)
return@withContext true
}
}
} catch (e: Exception) {
e.printStackTrace()
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation on lines 87-88 and 96-97. These lines use an extra space before the keywords, while surrounding code has proper indentation. The indentation should be aligned consistently with the rest of the code block.

Copilot uses AI. Check for mistakes.
Comment on lines +213 to +214
e.printStackTrace()
false
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation on line 213. The line uses an extra space before the e.printStackTrace() statement. This should be aligned with the surrounding code for consistency.

Suggested change
e.printStackTrace()
false
e.printStackTrace()
false

Copilot uses AI. Check for mistakes.
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
import com.google.api.client.extensions.android.http.AndroidHttp
import com.google.api.client.http.ByteArrayContent
import com.google.api.client.http.javanet.NetHttpTransport
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import com.google.api.client.http.javanet.NetHttpTransport is unused in the Android implementation. This import is only relevant for JVM-based implementations. Consider removing it to keep the imports clean.

Suggested change
import com.google.api.client.http.javanet.NetHttpTransport

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +29
suspend fun launchSignIn(intent: Intent): ActivityResult? {
val l = launcher ?: return null
val deferred = CompletableDeferred<ActivityResult>()
authDeferred = deferred
l.launch(intent)
return deferred.await()
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GoogleSignInHelper object has a potential race condition. If multiple coroutines call launchSignIn simultaneously, the second call will overwrite authDeferred before the first completes, causing the first caller to never receive its result. Consider using a thread-safe queue or mutex to handle concurrent authorization requests.

Copilot uses AI. Check for mistakes.
import android.content.Intent
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import androidx.activity.result.IntentSenderRequest is unused in this file. Consider removing it to keep the imports clean.

Suggested change
import androidx.activity.result.IntentSenderRequest

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,30 @@
package io.github.smiling_pixel.client

import android.app.Activity
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import android.app.Activity is unused in this file. Consider removing it to keep the imports clean.

Suggested change
import android.app.Activity

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +110
driveService = null
deferred.complete(Unit)
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is inconsistent indentation on lines 108-110. These lines use an extra space before the keywords, while surrounding code has proper indentation. The indentation should be aligned consistently with the rest of the code block.

Suggested change
driveService = null
deferred.complete(Unit)
driveService = null
deferred.complete(Unit)

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +76
expect fun getCloudDriveClient(): CloudDriveClient

Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The iOS target is missing an implementation of the getCloudDriveClient() expected function. The common code defines expect fun getCloudDriveClient(): CloudDriveClient, and while Android, JVM, and wasmJs provide actual implementations, iOS does not. This will cause a compilation error for iOS targets. You need to add an iOS-specific implementation file similar to the wasmJs stub implementation.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants