From 2dabdbdc3933569162cd3845671e04ce75f570df Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Sun, 22 Jan 2017 17:15:26 +0800 Subject: [PATCH] moved google drive sync into app folder (not visible to user) --- .../activity/sync/GoogleDriveAuthActivity.kt | 2 +- .../google/GoogleDriveDraftsSyncAction.kt | 12 ++-- .../GoogleDriveFiltersDataSyncAction.kt | 7 ++- .../GoogleDrivePreferencesValuesSyncAction.kt | 7 ++- .../sync/google/GoogleDriveSyncCommons.kt | 55 ++++++++++++------- .../sync/google/GoogleDriveUploadSession.kt | 3 +- 6 files changed, 55 insertions(+), 31 deletions(-) diff --git a/twidere/src/google/kotlin/org/mariotaku/twidere/activity/sync/GoogleDriveAuthActivity.kt b/twidere/src/google/kotlin/org/mariotaku/twidere/activity/sync/GoogleDriveAuthActivity.kt index 0e9b9e9a0..a3144befb 100644 --- a/twidere/src/google/kotlin/org/mariotaku/twidere/activity/sync/GoogleDriveAuthActivity.kt +++ b/twidere/src/google/kotlin/org/mariotaku/twidere/activity/sync/GoogleDriveAuthActivity.kt @@ -30,7 +30,7 @@ class GoogleDriveAuthActivity : BaseActivity(), GoogleApiClient.ConnectionCallba super.onCreate(savedInstanceState) val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestScopes(Scope(DriveScopes.DRIVE)) + .requestScopes(Scope(DriveScopes.DRIVE_APPDATA)) .requestServerAuthCode(GoogleDriveSyncProviderInfo.WEB_CLIENT_ID, true) .build() diff --git a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveDraftsSyncAction.kt b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveDraftsSyncAction.kt index f5e7f5b5c..8c20f6ba8 100644 --- a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveDraftsSyncAction.kt +++ b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveDraftsSyncAction.kt @@ -19,7 +19,7 @@ internal class GoogleDriveDraftsSyncAction( val drive: Drive ) : FileBasedDraftsSyncAction(context) { - val draftsDirName = "Drafts" + val draftsFolderName = "Drafts" val draftMimeType = "message/rfc822" private lateinit var folderId: String @@ -37,7 +37,8 @@ internal class GoogleDriveDraftsSyncAction( val file = if (driveId != null) { drive.files().performUpdate(driveId, filename, draftMimeType, stream = `is`, fileConfig = fileConfig) } else { - drive.updateOrCreate(filename, draftMimeType, folderId, stream = `is`, fileConfig = fileConfig) + drive.updateOrCreate(name = filename, mimeType = draftMimeType, parent = folderId, + spaces = appDataFolderSpace, stream = `is`, fileConfig = fileConfig) } return DriveFileInfo(file.id, file.name, Date(file.modifiedTime.value)) } @@ -84,8 +85,7 @@ internal class GoogleDriveDraftsSyncAction( val result = ArrayList() var nextPageToken: String? = null do { - val listResult = files.list().apply { - this.fields = requiredFilesRequestFields + val listResult = files.basicList(appDataFolderSpace).apply { this.q = "'$folderId' in parents and mimeType = '$draftMimeType' and trashed = false" if (nextPageToken != null) { this.pageToken = nextPageToken @@ -102,7 +102,9 @@ internal class GoogleDriveDraftsSyncAction( } override fun setup(): Boolean { - folderId = drive.getFileOrCreate(draftsDirName, folderMimeType, conflictResolver = ::resolveFoldersConflict).id + folderId = drive.getFileOrCreate(name = draftsFolderName, mimeType = folderMimeType, + parent = appDataFolderName, spaces = appDataFolderSpace, + conflictResolver = ::resolveFoldersConflict).id return true } diff --git a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveFiltersDataSyncAction.kt b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveFiltersDataSyncAction.kt index 954931920..587fd55ea 100644 --- a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveFiltersDataSyncAction.kt +++ b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveFiltersDataSyncAction.kt @@ -26,7 +26,8 @@ internal class GoogleDriveFiltersDataSyncAction( private val files = drive.files() override fun newLoadFromRemoteSession(): CloseableAny { - val file = drive.getFileOrNull(fileName, xmlMimeType, commonFolderId, + val file = drive.getFileOrNull(name = fileName, mimeType = xmlMimeType, + parent = commonFolderId, spaces = appDataFolderSpace, conflictResolver = ::resolveFilesConflict) ?: run { throw FileNotFoundException() } @@ -64,7 +65,9 @@ internal class GoogleDriveFiltersDataSyncAction( override fun setup(): Boolean { - commonFolderId = drive.getFileOrCreate("Common", folderMimeType, conflictResolver = ::resolveFoldersConflict).id + commonFolderId = drive.getFileOrCreate(name = commonFolderName, mimeType = folderMimeType, + parent = appDataFolderName, spaces = appDataFolderSpace, + conflictResolver = ::resolveFoldersConflict).id return true } diff --git a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDrivePreferencesValuesSyncAction.kt b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDrivePreferencesValuesSyncAction.kt index e0745b6a9..ddf020464 100644 --- a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDrivePreferencesValuesSyncAction.kt +++ b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDrivePreferencesValuesSyncAction.kt @@ -27,7 +27,8 @@ internal class GoogleDrivePreferencesValuesSyncAction( private val files = drive.files() override fun newLoadFromRemoteSession(): CloseableAny { - val file = drive.getFileOrNull(fileName, xmlMimeType, commonFolderId, + val file = drive.getFileOrNull(name = fileName, mimeType = xmlMimeType, + parent = commonFolderId, spaces = appDataFolderSpace, conflictResolver = ::resolveFilesConflict) ?: run { throw FileNotFoundException() } @@ -64,7 +65,9 @@ internal class GoogleDrivePreferencesValuesSyncAction( } override fun setup(): Boolean { - commonFolderId = drive.getFileOrCreate("Common", folderMimeType, conflictResolver = ::resolveFoldersConflict).id + commonFolderId = drive.getFileOrCreate(name = commonFolderName, mimeType = folderMimeType, + parent = appDataFolderName, spaces = appDataFolderSpace, + conflictResolver = ::resolveFoldersConflict).id return true } } \ No newline at end of file diff --git a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveSyncCommons.kt b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveSyncCommons.kt index 2582a84f5..0b22e3361 100644 --- a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveSyncCommons.kt +++ b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveSyncCommons.kt @@ -21,17 +21,22 @@ internal const val folderMimeType = "application/vnd.google-apps.folder" internal const val xmlMimeType = "application/xml" internal const val requiredRequestFields = "id, name, parents, mimeType, modifiedTime" internal const val requiredFilesRequestFields = "files($requiredRequestFields)" +internal const val commonFolderName = "Common" +internal const val appDataFolderName = "appDataFolder" +internal const val rootFolderName = "root" +internal const val appDataFolderSpace = appDataFolderName internal fun Drive.getFileOrNull( name: String, mimeType: String?, - parent: String? = "root", + parent: String? = rootFolderName, + spaces: String? = null, trashed: Boolean = false, - conflictResolver: ((Drive, List) -> File)? = null + conflictResolver: ((Drive, List, String?) -> File)? = null ): File? { - val result = findFilesOrNull(name, mimeType, parent, trashed) ?: return null + val result = findFilesOrNull(name, mimeType, parent, spaces, trashed) ?: return null if (result.size > 1 && conflictResolver != null) { - return conflictResolver(this, result) + return conflictResolver(this, result, spaces) } return result.firstOrNull() } @@ -39,10 +44,11 @@ internal fun Drive.getFileOrNull( internal fun Drive.findFilesOrNull( name: String, mimeType: String?, - parent: String? = "root", + parent: String? = rootFolderName, + spaces: String? = null, trashed: Boolean = false ): List? { - val find = files().list() + val find = files().basicList(spaces) var query = "name = '$name'" if (parent != null) { query += " and '$parent' in parents" @@ -52,7 +58,6 @@ internal fun Drive.findFilesOrNull( } query += " and trashed = $trashed" find.q = query - find.fields = requiredFilesRequestFields try { val files = find.execute().files if (files.isEmpty()) return null @@ -69,13 +74,14 @@ internal fun Drive.findFilesOrNull( internal fun Drive.getFileOrCreate( name: String, mimeType: String, - parent: String = "root", + parent: String = rootFolderName, + spaces: String? = null, trashed: Boolean = false, - conflictResolver: ((Drive, List) -> File)? = null + conflictResolver: ((Drive, List, String?) -> File)? = null ): File { - val result = findFilesOrCreate(name, mimeType, parent, trashed) + val result = findFilesOrCreate(name, mimeType, parent, spaces, trashed) if (result.size > 1 && conflictResolver != null) { - return conflictResolver(this, result) + return conflictResolver(this, result, spaces) } return result.first() } @@ -83,10 +89,11 @@ internal fun Drive.getFileOrCreate( internal fun Drive.findFilesOrCreate( name: String, mimeType: String, - parent: String = "root", + parent: String = rootFolderName, + spaces: String? = null, trashed: Boolean = false ): List { - return findFilesOrNull(name, mimeType, parent, trashed) ?: run { + return findFilesOrNull(name, mimeType, parent, spaces, trashed) ?: run { val file = File() file.name = name file.mimeType = mimeType @@ -99,16 +106,16 @@ internal fun Drive.findFilesOrCreate( internal fun Drive.updateOrCreate( name: String, mimeType: String, - parent: String = "root", + parent: String = rootFolderName, + spaces: String? = null, trashed: Boolean = false, stream: InputStream, fileConfig: ((file: File) -> Unit)? = null ): File { val files = files() return run { - val find = files.list() + val find = files.basicList(spaces) find.q = "name = '$name' and '$parent' in parents and mimeType = '$mimeType' and trashed = $trashed" - find.fields = requiredFilesRequestFields val fileId = try { find.execute().files.firstOrNull()?.id ?: return@run null } catch (e: GoogleJsonResponseException) { @@ -147,7 +154,7 @@ internal fun Drive.Files.performUpdate( return update.execute() } -internal fun resolveFilesConflict(client: Drive, list: List): File { +internal fun resolveFilesConflict(client: Drive, list: List, spaces: String?): File { // Pick newest file val newest = list.maxBy { it.modifiedTime.value }!! @@ -160,7 +167,7 @@ internal fun resolveFilesConflict(client: Drive, list: List): File { return newest } -internal fun resolveFoldersConflict(client: Drive, list: List): File { +internal fun resolveFoldersConflict(client: Drive, list: List, spaces: String?): File { val files = client.files() // Pick newest folder @@ -173,9 +180,8 @@ internal fun resolveFoldersConflict(client: Drive, list: List): File { val conflictFilesMap = HashMultimap.create() var nextPageToken: String? = null do { - val result = files.list().apply { + val result = files.basicList(spaces).apply { this.q = query - this.fields = requiredFilesRequestFields if (nextPageToken != null) { this.pageToken = nextPageToken } @@ -242,4 +248,13 @@ internal fun resolveFoldersConflict(client: Drive, list: List): File { return newest +} + +internal fun Drive.Files.basicList(spaces: String? = null): Drive.Files.List { + return list().apply { + this.fields = requiredFilesRequestFields + if (spaces != null) { + this.spaces = spaces + } + } } \ No newline at end of file diff --git a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveUploadSession.kt b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveUploadSession.kt index 4689aae26..02d212094 100644 --- a/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveUploadSession.kt +++ b/twidere/src/google/kotlin/org/mariotaku/twidere/util/sync/google/GoogleDriveUploadSession.kt @@ -25,7 +25,8 @@ abstract internal class GoogleDriveUploadSession( abstract fun Data.toInputStream(): InputStream fun uploadData(data: Data): Boolean { - drive.updateOrCreate(name, mimeType, parentId, stream = data.toInputStream(), fileConfig = { + drive.updateOrCreate(name = name, mimeType = mimeType, parent = parentId, + spaces = appDataFolderSpace, stream = data.toInputStream(), fileConfig = { it.modifiedTime = DateTime(localModifiedTime) }) return true