From 45a19ce95e04c2991657409ec9c1f900ab79192e Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sun, 9 Feb 2025 12:54:20 +0100 Subject: [PATCH] Remove Google integration --- app/app/build.gradle.kts | 1 - app/ui/build.gradle.kts | 1 - .../launcher2/ui/settings/SettingsActivity.kt | 4 - .../buildinfo/BuildInfoSettingsScreenVM.kt | 4 - .../filesearch/FileSearchSettingsScreen.kt | 34 --- .../filesearch/FileSearchSettingsScreenVM.kt | 4 - .../settings/google/GoogleSettingsScreen.kt | 157 ----------- .../settings/google/GoogleSettingsScreenVM.kt | 44 --- .../IntegrationsSettingsScreen.kt | 76 ------ .../IntegrationsSettingsScreenVM.kt | 3 - .../launcher2/licenses/OpenSourceLicenses.kt | 15 -- data/files/build.gradle.kts | 1 - .../mm20/launcher2/files/FileSerialization.kt | 61 ----- .../mm20/launcher2/files/FilesRepository.kt | 2 - .../java/de/mm20/launcher2/files/Module.kt | 2 - .../launcher2/files/providers/GDriveFile.kt | 56 ---- .../files/providers/GDriveFileProvider.kt | 42 --- .../developer-guide/external-apis/google.md | 24 -- gradle/libs.versions.toml | 5 - gradle/wrapper/gradle-wrapper.properties | 4 +- libs/g-services/.gitignore | 2 - libs/g-services/build.gradle.kts | 51 ---- libs/g-services/consumer-rules.pro | 29 -- libs/g-services/proguard-rules.pro | 23 -- libs/g-services/src/main/AndroidManifest.xml | 20 -- .../de/mm20/launcher2/gservices/DriveFile.kt | 40 --- .../mm20/launcher2/gservices/GoogleAccount.kt | 5 - .../launcher2/gservices/GoogleApiHelper.kt | 251 ------------------ .../gservices/GoogleAuthRedirectActivity.kt | 24 -- .../src/main/res/drawable/ic_google_g.xml | 30 --- .../g-services/src/main/res/values/styles.xml | 10 - .../release/res/raw/g_services_example.json | 1 - services/accounts/build.gradle.kts | 1 - .../de/mm20/launcher2/accounts/AccountType.kt | 1 - .../launcher2/accounts/AccountsRepository.kt | 20 -- settings.gradle.kts | 1 - 36 files changed, 2 insertions(+), 1047 deletions(-) delete mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreen.kt delete mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreenVM.kt delete mode 100644 data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFile.kt delete mode 100644 data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt delete mode 100644 docs/docs/developer-guide/external-apis/google.md delete mode 100644 libs/g-services/.gitignore delete mode 100644 libs/g-services/build.gradle.kts delete mode 100644 libs/g-services/consumer-rules.pro delete mode 100644 libs/g-services/proguard-rules.pro delete mode 100644 libs/g-services/src/main/AndroidManifest.xml delete mode 100644 libs/g-services/src/main/java/de/mm20/launcher2/gservices/DriveFile.kt delete mode 100644 libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAccount.kt delete mode 100644 libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleApiHelper.kt delete mode 100644 libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAuthRedirectActivity.kt delete mode 100644 libs/g-services/src/main/res/drawable/ic_google_g.xml delete mode 100644 libs/g-services/src/main/res/values/styles.xml delete mode 100644 libs/g-services/src/release/res/raw/g_services_example.json diff --git a/app/app/build.gradle.kts b/app/app/build.gradle.kts index 2bf78aa3..8a4d9e19 100644 --- a/app/app/build.gradle.kts +++ b/app/app/build.gradle.kts @@ -143,7 +143,6 @@ dependencies { implementation(project(":data:plugins")) implementation(project(":data:themes")) implementation(project(":data:files")) - implementation(project(":libs:g-services")) implementation(project(":core:i18n")) implementation(project(":services:icons")) implementation(project(":core:ktx")) diff --git a/app/ui/build.gradle.kts b/app/ui/build.gradle.kts index eb5efb63..77bfcee0 100644 --- a/app/ui/build.gradle.kts +++ b/app/ui/build.gradle.kts @@ -146,7 +146,6 @@ dependencies { implementation(project(":data:websites")) implementation(project(":data:unitconverter")) implementation(project(":libs:nextcloud")) - implementation(project(":libs:g-services")) implementation(project(":libs:owncloud")) implementation(project(":services:accounts")) implementation(project(":services:plugins")) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt index b2fe25ba..88e2d721 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt @@ -48,7 +48,6 @@ import de.mm20.launcher2.ui.settings.favorites.FavoritesSettingsScreen import de.mm20.launcher2.ui.settings.filesearch.FileSearchSettingsScreen import de.mm20.launcher2.ui.settings.filterbar.FilterBarSettingsScreen import de.mm20.launcher2.ui.settings.gestures.GestureSettingsScreen -import de.mm20.launcher2.ui.settings.google.GoogleSettingsScreen import de.mm20.launcher2.ui.settings.hiddenitems.HiddenItemsSettingsScreen import de.mm20.launcher2.ui.settings.homescreen.HomescreenSettingsScreen import de.mm20.launcher2.ui.settings.icons.IconsSettingsScreen @@ -226,9 +225,6 @@ class SettingsActivity : BaseActivity() { composable("settings/integrations/owncloud") { OwncloudSettingsScreen() } - composable("settings/integrations/google") { - GoogleSettingsScreen() - } composable("settings/plugins") { PluginsSettingsScreen() } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/buildinfo/BuildInfoSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/buildinfo/BuildInfoSettingsScreenVM.kt index 6f1a4c4a..520c65ef 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/buildinfo/BuildInfoSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/buildinfo/BuildInfoSettingsScreenVM.kt @@ -1,22 +1,18 @@ package de.mm20.launcher2.ui.settings.buildinfo import androidx.lifecycle.ViewModel -import de.mm20.launcher2.accounts.AccountType -import de.mm20.launcher2.accounts.AccountsRepository import de.mm20.launcher2.weather.WeatherRepository import kotlinx.coroutines.flow.map import org.koin.core.component.KoinComponent import org.koin.core.component.inject class BuildInfoSettingsScreenVM : ViewModel(), KoinComponent { - private val accountsRepository: AccountsRepository by inject() private val weatherRepository: WeatherRepository by inject() private val availableWeatherProviders = weatherRepository.getProviders() val buildFeatures = availableWeatherProviders.map { mapOf( - "Accounts: Google" to accountsRepository.isSupported(AccountType.Google), "Weather providers: HERE" to it.any { it.id == "here" }, "Weather providers: Met No" to it.any { it.id == "metno" }, "Weather providers: OpenWeatherMap" to it.any { it.id == "owm" }, diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreen.kt index a6add212..0113df1a 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreen.kt @@ -153,40 +153,6 @@ fun FileSearchSettingsScreen() { enabled = owncloudAccount != null ) - if (viewModel.googleAvailable) { - val gdrive by viewModel.gdrive.collectAsState() - val googleAccount by viewModel.googleAccount - AnimatedVisibility(googleAccount == null) { - Banner( - text = stringResource(R.string.no_account_google), - icon = Icons.Rounded.AccountBox, - primaryAction = { - TextButton(onClick = { - viewModel.login( - context as AppCompatActivity, - AccountType.Google - ) - }) { - Text( - stringResource(R.string.connect_account), - ) - } - }, - modifier = Modifier.padding(16.dp) - ) - } - SwitchPreference( - title = stringResource(R.string.preference_search_gdrive), - summary = googleAccount?.let { - stringResource(R.string.preference_search_gdrive_summary, it.userName) - } ?: stringResource(R.string.preference_summary_not_logged_in), - value = gdrive == true && googleAccount != null, - onValueChanged = { - viewModel.setGdrive(it) - }, - enabled = googleAccount != null - ) - } for (plugin in plugins) { val state = plugin.state if (state is PluginState.SetupRequired) { diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreenVM.kt index daa1259a..8150f016 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/filesearch/FileSearchSettingsScreenVM.kt @@ -30,9 +30,6 @@ class FileSearchSettingsScreenVM : ViewModel(), KoinComponent { val loading = mutableStateOf(true) val nextcloudAccount = mutableStateOf(null) val owncloudAccount = mutableStateOf(null) - val googleAccount = mutableStateOf(null) - - val googleAvailable = accountsRepository.isSupported(AccountType.Google) val availablePlugins = pluginService.getPluginsWithState( type = PluginType.FileSearch, @@ -48,7 +45,6 @@ class FileSearchSettingsScreenVM : ViewModel(), KoinComponent { accountsRepository.getCurrentlySignedInAccount(AccountType.Nextcloud) owncloudAccount.value = accountsRepository.getCurrentlySignedInAccount(AccountType.Owncloud) - googleAccount.value = accountsRepository.getCurrentlySignedInAccount(AccountType.Google) loading.value = false } } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreen.kt deleted file mode 100644 index 63fc4df0..00000000 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreen.kt +++ /dev/null @@ -1,157 +0,0 @@ -package de.mm20.launcher2.ui.settings.google - -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.rounded.Logout -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.compose.LocalLifecycleOwner -import androidx.lifecycle.repeatOnLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel -import de.mm20.launcher2.ui.R -import de.mm20.launcher2.ui.component.preferences.PreferenceScreen -import de.mm20.launcher2.ui.component.preferences.SwitchPreference -import de.mm20.launcher2.ui.locals.LocalNavController -import de.mm20.launcher2.ui.settings.integrations.GoogleSigninButton - -@Composable -fun GoogleSettingsScreen() { - - val viewModel: GoogleSettingsScreenVM = viewModel() - val lifecycleOwner = LocalLifecycleOwner.current - val navController = LocalNavController.current - - val googleUser by viewModel.googleUser - val loading by viewModel.loading - val searchFiles by viewModel.searchFiles.collectAsState(null) - - LaunchedEffect(null) { - lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) { - viewModel.onResume() - } - } - PreferenceScreen(title = stringResource(R.string.preference_google)) { - if (loading) return@PreferenceScreen - - if (googleUser != null) { - item { - Column( - modifier = Modifier - .background(MaterialTheme.colorScheme.secondaryContainer) - .fillParentMaxWidth() - .padding(vertical = 64.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .size(72.dp) - .background(MaterialTheme.colorScheme.secondary, CircleShape) - .border( - 2.dp, - MaterialTheme.colorScheme.onSecondaryContainer, - CircleShape - ), - ) { - Text( - text = googleUser!!.userName.split(" ") - .map { it.first() } - .joinToString("").let { - if (it.length >= 2) it.first().toString() + it.last().toString() - else it.first().toString() - }, - color = MaterialTheme.colorScheme.onSecondary, - style = MaterialTheme.typography.headlineMedium, - ) - } - Text( - modifier = Modifier.padding(top = 24.dp), - text = stringResource( - R.string.preference_signin_user, - googleUser!!.userName - ), - color = MaterialTheme.colorScheme.onSecondaryContainer, - style = MaterialTheme.typography.bodyLarge, - ) - Button( - modifier = Modifier.padding(top = 32.dp), - onClick = { - viewModel.signOut() - }, - contentPadding = ButtonDefaults.ButtonWithIconContentPadding, - ) { - Icon( - Icons.AutoMirrored.Rounded.Logout, - modifier = Modifier - .padding(end = ButtonDefaults.IconSpacing) - .size(ButtonDefaults.IconSize), - contentDescription = null - ) - Text(text = stringResource(R.string.preference_signout)) - } - } - } - item { - HorizontalDivider() - } - - item { - SwitchPreference( - title = stringResource(R.string.plugin_type_filesearch), - summary = stringResource( - R.string.preference_search_cloud_summary, - googleUser!!.userName - ), - value = searchFiles == true, - onValueChanged = { - viewModel.setSearchFiles(it) - }, - iconPadding = false, - ) - } - } else { - item { - val activity = LocalContext.current as AppCompatActivity - Column( - modifier = Modifier - .fillParentMaxWidth() - .padding(vertical = 64.dp, horizontal = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - GoogleSigninButton( - onClick = { - viewModel.signIn(activity) - } - ) - } - } - item { - HorizontalDivider() - } - } - } -} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreenVM.kt deleted file mode 100644 index 2b93282e..00000000 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/google/GoogleSettingsScreenVM.kt +++ /dev/null @@ -1,44 +0,0 @@ -package de.mm20.launcher2.ui.settings.google - -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import de.mm20.launcher2.accounts.Account -import de.mm20.launcher2.accounts.AccountType -import de.mm20.launcher2.accounts.AccountsRepository -import de.mm20.launcher2.preferences.search.FileSearchSettings -import kotlinx.coroutines.launch -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject - -class GoogleSettingsScreenVM: ViewModel(), KoinComponent { - private val accountsRepository: AccountsRepository by inject() - private val fileSearchSettings: FileSearchSettings by inject() - - val googleUser = mutableStateOf(null) - val loading = mutableStateOf(true) - - fun onResume() { - viewModelScope.launch { - loading.value = true - googleUser.value = accountsRepository.getCurrentlySignedInAccount(AccountType.Google) - loading.value = false - } - } - - fun signIn(activity: AppCompatActivity) { - accountsRepository.signin(activity, AccountType.Google) - } - - fun signOut() { - accountsRepository.signout(AccountType.Google) - googleUser.value = null - } - - val searchFiles = fileSearchSettings.gdriveFiles - - fun setSearchFiles(value: Boolean) { - fileSearchSettings.setGdriveFiles(value) - } -} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreen.kt index 373e1475..e86ed114 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreen.kt @@ -1,45 +1,16 @@ package de.mm20.launcher2.ui.settings.integrations -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.LightMode import androidx.compose.material.icons.rounded.PlayCircleOutline -import androidx.compose.material3.LinearProgressIndicator -import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.viewmodel.compose.viewModel -import de.mm20.launcher2.accounts.AccountType import de.mm20.launcher2.icons.Google import de.mm20.launcher2.icons.Nextcloud import de.mm20.launcher2.icons.Owncloud import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.preferences.Preference -import de.mm20.launcher2.ui.component.preferences.PreferenceCategory import de.mm20.launcher2.ui.component.preferences.PreferenceScreen import de.mm20.launcher2.ui.locals.LocalNavController @@ -78,53 +49,6 @@ fun IntegrationsSettingsScreen() { navController?.navigate("settings/integrations/owncloud") } ) - if (viewModel.isGoogleAvailable) { - Preference( - title = stringResource(R.string.preference_google), - icon = Icons.Rounded.Google, - onClick = { - navController?.navigate("settings/integrations/google") - } - ) - } - } - } -} - -@Composable -fun GoogleSigninButton( - onClick: () -> Unit, -) { - Surface( - modifier = Modifier.height(40.dp), - shadowElevation = 1.dp, - color = Color.White, - shape = RoundedCornerShape(2.dp), - onClick = onClick - ) { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Box( - modifier = Modifier - .size(40.dp) - .background(Color.White), - contentAlignment = Alignment.Center - ) { - Image( - modifier = Modifier.size(18.dp), - painter = painterResource(id = R.drawable.ic_google_g), - contentDescription = null - ) - } - Text( - modifier = Modifier.padding(start = 13.dp, end = 8.dp), - text = stringResource(id = R.string.preference_google_signin), - fontFamily = FontFamily.SansSerif, - color = Color(0f, 0f, 0f, 0.54f), - fontSize = 14.sp, - fontWeight = FontWeight.Medium - ) } } } \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreenVM.kt index 851f3f92..bb0dad38 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/integrations/IntegrationsSettingsScreenVM.kt @@ -7,7 +7,4 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.inject class IntegrationsSettingsScreenVM : ViewModel(), KoinComponent { - private val accountsRepository: AccountsRepository by inject() - - val isGoogleAvailable = accountsRepository.isSupported(AccountType.Google) } \ No newline at end of file diff --git a/core/base/src/main/java/de/mm20/launcher2/licenses/OpenSourceLicenses.kt b/core/base/src/main/java/de/mm20/launcher2/licenses/OpenSourceLicenses.kt index 38006787..8bc54397 100644 --- a/core/base/src/main/java/de/mm20/launcher2/licenses/OpenSourceLicenses.kt +++ b/core/base/src/main/java/de/mm20/launcher2/licenses/OpenSourceLicenses.kt @@ -107,21 +107,6 @@ val OpenSourceLicenses = arrayOf( copyrightNote = "Copyright 2010 - 2020 Mariusz Gromada. All rights reserved.", url = "https://mathparser.org/" ), - OpenSourceLibrary( - name = "Google Auth Library", - description = "Open source authentication client library for Java.", - licenseName = R.string.bsd_3clause_name, - licenseText = R.raw.license_bsd_3clause, - copyrightNote = "Copyright 2014, Google Inc. All rights reserved.", - url = "https://github.com/googleapis/google-auth-library-java" - ), - OpenSourceLibrary( - name = "Google APIs Client Library for Android", - description = "The Google APIs Client Library for Java is a flexible, efficient, and powerful Java client library for accessing any HTTP-based API on the web, not just Google APIs.", - licenseName = R.string.apache_license_name, - licenseText = R.raw.license_apache_2, - url = "https://github.com/googleapis/google-api-java-client" - ), OpenSourceLibrary( name = "CrashReporter", description = "CrashReporter is a handy tool to capture app crashes and save them in a file.", diff --git a/data/files/build.gradle.kts b/data/files/build.gradle.kts index 0aa2590b..5b127e64 100644 --- a/data/files/build.gradle.kts +++ b/data/files/build.gradle.kts @@ -49,7 +49,6 @@ dependencies { implementation(project(":core:base")) implementation(project(":core:ktx")) - implementation(project(":libs:g-services")) implementation(project(":libs:nextcloud")) implementation(project(":libs:owncloud")) implementation(project(":core:i18n")) diff --git a/data/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt b/data/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt index a101ef3d..5526ea25 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt @@ -4,7 +4,6 @@ import android.content.Context import android.net.Uri import android.provider.MediaStore import androidx.core.database.getStringOrNull -import de.mm20.launcher2.files.providers.GDriveFile import de.mm20.launcher2.files.providers.LocalFile import de.mm20.launcher2.files.providers.NextcloudFile import de.mm20.launcher2.files.providers.OwncloudFile @@ -107,66 +106,6 @@ internal class LocalFileDeserializer( } } -internal class GDriveFileSerializer : SearchableSerializer { - override fun serialize(searchable: SavableSearchable): String { - searchable as GDriveFile - return jsonObjectOf( - "id" to searchable.fileId, - "label" to searchable.label, - "path" to searchable.path, - "mimeType" to searchable.mimeType, - "size" to searchable.size, - "directory" to searchable.isDirectory, - "color" to searchable.directoryColor, - "uri" to searchable.viewUri - ).apply { - for ((k, v) in searchable.metaData) { - put( - when (k) { - FileMetaType.Owner -> "owner" - FileMetaType.Dimensions -> "dimensions" - else -> "other" - }, v - ) - } - }.toString() - } - - override val typePrefix: String - get() = "gdrive" -} - -internal class GDriveFileDeserializer : SearchableDeserializer { - override suspend fun deserialize(serialized: String): SavableSearchable { - val json = JSONObject(serialized) - val id = json.getString("id") - val label = json.getString("label") - val path = json.getString("path") - val mimeType = json.getString("mimeType") - val size = json.getLong("size") - val directory = json.getBoolean("directory") - val color = json.optString("color") - val uri = json.getString("uri") - val owner = json.optString("owner") - val dimensions = json.optString("dimensions") - val metaData = mutableMapOf() - owner.takeIf { it.isNotEmpty() }?.let { metaData[FileMetaType.Owner] = it } - dimensions.takeIf { it.isNotEmpty() } - ?.let { metaData[FileMetaType.Dimensions] = it } - return GDriveFile( - fileId = id, - label = label, - path = path, - mimeType = mimeType, - size = size, - directoryColor = color, - isDirectory = directory, - viewUri = uri, - metaData = metaData.toImmutableMap() - ) - } -} - internal class NextcloudFileSerializer : SearchableSerializer { override fun serialize(searchable: SavableSearchable): String { searchable as NextcloudFile diff --git a/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt b/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt index b77512b8..72bfbc7a 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt @@ -1,7 +1,6 @@ package de.mm20.launcher2.files import android.content.Context -import de.mm20.launcher2.files.providers.GDriveFileProvider import de.mm20.launcher2.files.providers.LocalFileProvider import de.mm20.launcher2.files.providers.NextcloudFileProvider import de.mm20.launcher2.files.providers.OwncloudFileProvider @@ -64,7 +63,6 @@ internal class FileRepository( permissionsManager ) else null - "gdrive" -> GDriveFileProvider(context) "nextcloud" -> NextcloudFileProvider(nextcloudClient) "owncloud" -> OwncloudFileProvider(owncloudClient) else -> PluginFileProvider(context, it) diff --git a/data/files/src/main/java/de/mm20/launcher2/files/Module.kt b/data/files/src/main/java/de/mm20/launcher2/files/Module.kt index 35d655a9..a9e0d663 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/Module.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/Module.kt @@ -1,6 +1,5 @@ package de.mm20.launcher2.files -import de.mm20.launcher2.files.providers.GDriveFile import de.mm20.launcher2.files.providers.LocalFile import de.mm20.launcher2.files.providers.NextcloudFile import de.mm20.launcher2.files.providers.OwncloudFile @@ -23,7 +22,6 @@ val filesModule = module { factory(named(LocalFile.Domain)) { LocalFileDeserializer(androidContext()) } factory(named(OwncloudFile.Domain)) { OwncloudFileDeserializer() } factory(named(NextcloudFile.Domain)) { NextcloudFileDeserializer() } - factory(named(GDriveFile.Domain)) { GDriveFileDeserializer() } factory(named(PluginFile.Domain)) { PluginFileDeserializer( androidContext(), diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFile.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFile.kt deleted file mode 100644 index 454fd123..00000000 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFile.kt +++ /dev/null @@ -1,56 +0,0 @@ -package de.mm20.launcher2.files.providers - -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import de.mm20.launcher2.files.GDriveFileSerializer -import de.mm20.launcher2.files.R -import de.mm20.launcher2.ktx.tryStartActivity -import de.mm20.launcher2.search.File -import de.mm20.launcher2.search.FileMetaType -import de.mm20.launcher2.search.SearchableSerializer -import kotlinx.collections.immutable.ImmutableMap - -internal data class GDriveFile( - val fileId: String, - override val label: String, - override val path: String, - override val mimeType: String, - override val size: Long, - override val isDirectory: Boolean, - override val metaData: ImmutableMap, - val directoryColor: String?, - val viewUri: String, - override val labelOverride: String? = null, -) : File { - - override fun overrideLabel(label: String): GDriveFile { - return this.copy(labelOverride = label) - } - - override val domain: String = Domain - - override val key: String = "$domain://$fileId" - - override val providerIconRes = R.drawable.ic_badge_gdrive - - private fun getLaunchIntent(): Intent { - return Intent(Intent.ACTION_VIEW).apply { - data = Uri.parse(viewUri) - flags = Intent.FLAG_ACTIVITY_NEW_TASK - } - } - - override fun launch(context: Context, options: Bundle?): Boolean { - return context.tryStartActivity(getLaunchIntent(), options) - } - - override fun getSerializer(): SearchableSerializer { - return GDriveFileSerializer() - } - - companion object { - const val Domain = "gdrive" - } -} \ No newline at end of file diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt deleted file mode 100644 index 6f8266e2..00000000 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt +++ /dev/null @@ -1,42 +0,0 @@ -package de.mm20.launcher2.files.providers - -import android.content.Context -import de.mm20.launcher2.files.R -import de.mm20.launcher2.gservices.DriveFileMeta -import de.mm20.launcher2.gservices.GoogleApiHelper -import de.mm20.launcher2.search.File -import de.mm20.launcher2.search.FileMetaType -import kotlinx.collections.immutable.ImmutableMap -import kotlinx.collections.immutable.toImmutableMap - -internal class GDriveFileProvider( - private val context: Context -) : FileProvider { - override suspend fun search(query: String, allowNetwork: Boolean): List { - if (query.length < 4 || !allowNetwork) return emptyList() - val driveFiles = GoogleApiHelper.getInstance(context).queryGDriveFiles(query) - return driveFiles.map { - GDriveFile( - fileId = it.fileId, - label = it.label, - size = it.size, - mimeType = it.mimeType, - isDirectory = it.isDirectory, - path = "", - directoryColor = it.directoryColor, - viewUri = it.viewUri, - metaData = getMetadata(it.metadata) - ) - } - } - - private fun getMetadata(file: DriveFileMeta): ImmutableMap { - val metaData = mutableMapOf() - val owners = file.owners - metaData[FileMetaType.Owner] = owners.joinToString(separator = ", ") - val width = file.width - val height = file.height - if (width != null && height != null) metaData[FileMetaType.Dimensions] = "${width}x${height}" - return metaData.toImmutableMap() - } -} \ No newline at end of file diff --git a/docs/docs/developer-guide/external-apis/google.md b/docs/docs/developer-guide/external-apis/google.md deleted file mode 100644 index 5c6f3626..00000000 --- a/docs/docs/developer-guide/external-apis/google.md +++ /dev/null @@ -1,24 +0,0 @@ -# Google Cloud Services - -Google Cloud Services are used for Google Drive search. To enable Google Drive integration in your builds, follow these steps: - -1. Go to the [Google Cloud Console](https://console.cloud.google.com) -1. Create a new project. -1. Enable the Drive API: - 1. Go to APIs & Services > Library and search for the Google Drive API. - 1. Enable this API for your project. -1. Setup your OAuth consent screen - 1. Go to APIs & Services > OAuth consent screen - 1. On the Oauth consent screen page, fill out all the required fields - 1. On the Scopes page, click add or remove scopes and add the following scopes: `userinfo.profile` and `drive.metadata.readonly` -1. Create a new Oauth 2.0 client (you need to do this twice, for debug builds and for release builds) - 1. Go to APIs & Services > Credentials - 1. Click on Create Credentials > OAuth client ID - 1. Choose application type Android - 1. Enter the package name (`de.mm20.launcher2.debug` for debug builds or `de.mm20.launcher2.release` for release builds) - 1. Enter the SHA-1 certificate fingerprint of your APK signing key - 1. Click on create -1. Download the client config file (repeat this step for both the debug and the release client) - 1. On the APIs & Services > Credentials page, find your OAuth client in the list under OAuth 2.0 Client IDs. - 1. Click on the download icon to download a `client_config.json` - 1. Place this file under `g-services/src/debug/res/raw/g_services.json` or `g-services/src/release/res/raw/g_services.json` diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4e3f8fcc..5cc75b1f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -127,11 +127,6 @@ stringsimilarity = { group = "com.aallam.similarity", name = "string-similarity- # 4.4.2 is the last GPL compatible version, don't update to 5.x mathparser = { group = "org.mariuszgromada.math", name = "MathParser.org-mXparser", version = "4.4.2" } -google-auth = { group = "com.google.auth", name = "google-auth-library-oauth2-http", version = "1.14.0" } -google-apiclient = { group = "com.google.api-client", name = "google-api-client", version = "2.1.2" } -google-drive = { group = "com.google.apis", name = "google-api-services-drive", version = "v3-rev20221219-2.0.0" } -google-oauth2 = { group = "com.google.apis", name = "google-api-services-oauth2", version = "v2-rev20200213-2.0.0" } - koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" } koin-androidxcompose = { group = "io.insert-koin", name = "koin-androidx-compose", version.ref = "koin" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5561c434..bfe16dda 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 12 19:53:45 CET 2022 +#Sun Feb 09 12:41:42 CET 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/libs/g-services/.gitignore b/libs/g-services/.gitignore deleted file mode 100644 index bcb56ceb..00000000 --- a/libs/g-services/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/build -*/**/g_services.json diff --git a/libs/g-services/build.gradle.kts b/libs/g-services/build.gradle.kts deleted file mode 100644 index ca98d6ab..00000000 --- a/libs/g-services/build.gradle.kts +++ /dev/null @@ -1,51 +0,0 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - minSdk = libs.versions.minSdk.get().toInt() - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - consumerProguardFiles("proguard-rules.pro") - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = "1.8" - } - namespace = "de.mm20.launcher2.gservices" -} - -dependencies { - implementation(libs.bundles.kotlin) - implementation(libs.androidx.core) - implementation(libs.androidx.appcompat) - implementation(libs.androidx.browser) - implementation(libs.bundles.androidx.lifecycle) - - implementation(libs.google.auth) - implementation(libs.google.apiclient) - implementation(libs.google.drive) - implementation(libs.google.oauth2) - - implementation(project(":core:i18n")) - implementation(project(":core:crashreporter")) -} \ No newline at end of file diff --git a/libs/g-services/consumer-rules.pro b/libs/g-services/consumer-rules.pro deleted file mode 100644 index f0b51ac5..00000000 --- a/libs/g-services/consumer-rules.pro +++ /dev/null @@ -1,29 +0,0 @@ --keep class org.apache.** { *; } --dontwarn edu.umd.cs.findbugs.annotations.Nullable --dontwarn java.lang.reflect.AnnotatedType --dontwarn javax.lang.model.element.Modifier --dontwarn javax.script.ScriptEngine --dontwarn javax.script.ScriptEngineManager --dontwarn org.apache.http.client.config.RequestConfig$Builder --dontwarn org.apache.http.client.config.RequestConfig --dontwarn org.apache.http.client.methods.HttpPatch --dontwarn org.apache.http.conn.DnsResolver --dontwarn org.apache.http.conn.HttpClientConnectionManager --dontwarn org.apache.http.conn.HttpConnectionFactory --dontwarn org.apache.http.conn.SchemePortResolver --dontwarn org.apache.http.conn.socket.LayeredConnectionSocketFactory --dontwarn org.apache.http.conn.socket.PlainConnectionSocketFactory --dontwarn org.apache.http.conn.ssl.SSLConnectionSocketFactory --dontwarn org.apache.http.impl.client.CloseableHttpClient --dontwarn org.apache.http.impl.client.HttpClientBuilder --dontwarn org.apache.http.impl.conn.PoolingHttpClientConnectionManager --dontwarn org.apache.http.impl.conn.SystemDefaultRoutePlanner --dontwarn org.bouncycastle.jsse.BCSSLParameters --dontwarn org.bouncycastle.jsse.BCSSLSocket --dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider --dontwarn org.conscrypt.Conscrypt$Version --dontwarn org.conscrypt.Conscrypt --dontwarn org.conscrypt.ConscryptHostnameVerifier --dontwarn org.openjsse.javax.net.ssl.SSLParameters --dontwarn org.openjsse.javax.net.ssl.SSLSocket --dontwarn org.openjsse.net.ssl.OpenJSSE \ No newline at end of file diff --git a/libs/g-services/proguard-rules.pro b/libs/g-services/proguard-rules.pro deleted file mode 100644 index 42c52610..00000000 --- a/libs/g-services/proguard-rules.pro +++ /dev/null @@ -1,23 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile - --keep class com.google.** { *; } \ No newline at end of file diff --git a/libs/g-services/src/main/AndroidManifest.xml b/libs/g-services/src/main/AndroidManifest.xml deleted file mode 100644 index 6033eb75..00000000 --- a/libs/g-services/src/main/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/DriveFile.kt b/libs/g-services/src/main/java/de/mm20/launcher2/gservices/DriveFile.kt deleted file mode 100644 index d21e6c5c..00000000 --- a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/DriveFile.kt +++ /dev/null @@ -1,40 +0,0 @@ -package de.mm20.launcher2.gservices - -import com.google.api.services.drive.model.File -import java.util.* - -data class DriveFile( - val fileId : String, - val label: String, - val size: Long, - val mimeType : String, - val isDirectory : Boolean, - val directoryColor: String?, - val viewUri: String, - val metadata: DriveFileMeta -) { - companion object { - fun fromApiDriveFile(file: File): DriveFile { - return DriveFile( - fileId = file.id, - label = file.name, - size = file.getSize() ?: 0, - isDirectory = file.mimeType == "application/vnd.google-apps.folder", - mimeType = file.mimeType, - metadata = DriveFileMeta( - owners = file.owners?.map { it.displayName ?: it.emailAddress ?: "" } ?: emptyList(), - width = file.imageMediaMetadata?.width ?: file.videoMediaMetadata?.width, - height = file.imageMediaMetadata?.height ?: file.videoMediaMetadata?.height - ), - directoryColor = file.folderColorRgb?.lowercase(Locale.ROOT), - viewUri = file.webViewLink ?: "" - ) - } - } -} - -data class DriveFileMeta( - val owners : List, - val width: Int?, - val height: Int? -) \ No newline at end of file diff --git a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAccount.kt b/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAccount.kt deleted file mode 100644 index e6cdc69f..00000000 --- a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAccount.kt +++ /dev/null @@ -1,5 +0,0 @@ -package de.mm20.launcher2.gservices - -data class GoogleAccount( - val name: String -) \ No newline at end of file diff --git a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleApiHelper.kt b/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleApiHelper.kt deleted file mode 100644 index 56adbed2..00000000 --- a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleApiHelper.kt +++ /dev/null @@ -1,251 +0,0 @@ -package de.mm20.launcher2.gservices - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.util.Log -import androidx.browser.customtabs.* -import androidx.core.content.edit -import com.google.api.client.auth.oauth2.Credential -import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow -import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets -import com.google.api.client.http.HttpRequestInitializer -import com.google.api.client.http.javanet.NetHttpTransport -import com.google.api.client.json.gson.GsonFactory -import com.google.api.client.util.store.FileDataStoreFactory -import com.google.api.services.drive.Drive -import com.google.api.services.oauth2.Oauth2 -import de.mm20.launcher2.crashreporter.CrashReporter -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext -import java.io.File -import java.io.IOException - -class GoogleApiHelper private constructor(private val context: Context) { - - val transport by lazy { - NetHttpTransport() - } - - suspend fun queryGDriveFiles(query: String): List { - val requestInitializer = getRequestInitializer() ?: return emptyList() - val jsonFactory = GsonFactory.getDefaultInstance() - return withContext(Dispatchers.IO) { - try { - val drive = - Drive.Builder(transport, jsonFactory, requestInitializer).build() - val request = drive.files().list() - request.q = "name contains '${query.replace("'", "")}'" - request.pageSize = 10 - request.fields = - "files(id, webViewLink, size, name, mimeType, owners, imageMediaMetadata, videoMediaMetadata, folderColorRgb)" - request.corpora = "user" - val response = request.execute() - val files = response.files ?: return@withContext emptyList() - files.map { DriveFile.fromApiDriveFile(it) } - - } catch (e: IOException) { - emptyList() - } catch (e: Error) { - emptyList() - } - } - } - - private suspend fun getCredential(): Credential? { - val authFlow = getAuthFlow() ?: return null - return withContext(Dispatchers.IO) { - val credential: Credential? = authFlow.loadCredential(USER_ID) - if ((credential?.expiresInSeconds ?: 0) < 5 * 60) { - try { - if (credential?.refreshToken() == false) return@withContext null - } catch (e: IOException) { - CrashReporter.logException(e) - } - } - return@withContext credential - } - } - - private suspend fun getRequestInitializer(): HttpRequestInitializer? { - val credential = getCredential() ?: return null - - return HttpRequestInitializer { request -> - credential.initialize(request) - request?.connectTimeout = 5000 - request?.readTimeout = 10000 - } - } - - suspend fun getAccount(): GoogleAccount? { - - val name = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).getString( - PREF_ACCOUNT_NAME, - null - ) ?: loadAccountName() - - - return name?.let { - GoogleAccount(name = it) - } - } - - fun isAvailable(): Boolean { - return getConfigResId() != 0 - } - - private fun getConfigResId(): Int { - return context.resources.getIdentifier("g_services", "raw", context.packageName) - } - - - private fun getAuthFlow(throwErrors: Boolean = false): GoogleAuthorizationCodeFlow? { - val configResId = getConfigResId() - if (configResId == 0) return null - val jsonFactory = GsonFactory.getDefaultInstance() - try { - return GoogleAuthorizationCodeFlow.Builder( - NetHttpTransport(), - jsonFactory, - GoogleClientSecrets.load( - jsonFactory, - context.resources.openRawResource(configResId).reader() - ), - SCOPES - ) - .setCredentialDataStore( - FileDataStoreFactory(context.filesDir).getDataStore( - "google_signin" - ) - ) - .build() - } catch (e: IOException) { - if (throwErrors) throw e - else { - File(context.filesDir, "google_signin").delete() - context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit { - putString(PREF_ACCOUNT_NAME, null) - } - Log.e("MM20", "Google account has been reset because data store couldn't be readg") - CrashReporter.logException(e) - return getAuthFlow(true) - } - } - } - - private var callback: (() -> Unit)? = null - - suspend fun login(activity: Activity) { - val authFlow = getAuthFlow() ?: return - - suspendCancellableCoroutine { - val url = authFlow - .newAuthorizationUrl() - .setRedirectUri(getRedirectUri()) - .toString() - val themeColor = 0xFF4285f4.toInt() - - val customTabsIntent = CustomTabsIntent - .Builder() - .setDefaultColorSchemeParams( - CustomTabColorSchemeParams.Builder() - .setToolbarColor(themeColor) - .setNavigationBarColor(themeColor) - .build() - ) - .build() - - callingActivity = activity.javaClass - callback = { - it.resumeWith(Result.success(Unit)) - } - it.invokeOnCancellation { - callback = null - Log.d("MM20", "Google Signin has been canceled") - } - - customTabsIntent.intent.flags = Intent.FLAG_ACTIVITY_NO_HISTORY - customTabsIntent.launchUrl(activity, Uri.parse(url)) - - } - } - - suspend fun finishAuthFlow(activity: Activity, code: String) { - val authFlow = getAuthFlow() ?: return - withContext(Dispatchers.IO) { - val tokenResponse = try { - authFlow.newTokenRequest(code).setRedirectUri(getRedirectUri()).execute() - } catch (e: IOException) { - CrashReporter.logException(e) - return@withContext - } - authFlow.createAndStoreCredential(tokenResponse, USER_ID) - } - loadAccountName() - returnToPreviousActivity(activity) - } - - fun cancelAuthFlow(activity: Activity) { - returnToPreviousActivity(activity) - } - - private fun returnToPreviousActivity(activity: Activity) { - val intent = Intent(activity, callingActivity) - callingActivity = null - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) - activity.startActivity(intent) - callback?.invoke() - } - - private suspend fun loadAccountName(): String? { - val requestInitializer = getRequestInitializer() ?: return null - val jsonFactory = GsonFactory.getDefaultInstance() - val oauth2 = Oauth2.Builder(transport, jsonFactory, requestInitializer).build() - try { - val meResponse = withContext(Dispatchers.IO) { - oauth2.userinfo().v2().me().get().execute() - } - if (meResponse != null) { - val name = meResponse.name - context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit { - putString(PREF_ACCOUNT_NAME, name) - } - return name - } - } catch (e: IOException) { - CrashReporter.logException(e) - } - return null - } - - - fun logout() { - val authFlow = getAuthFlow() ?: return - authFlow.credentialDataStore.clear() - context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit { - putString(PREF_ACCOUNT_NAME, null) - } - } - - private fun getRedirectUri(): String { - return "${context.packageName}:/google-auth-redirect" - } - - companion object { - private lateinit var instance: GoogleApiHelper - - fun getInstance(context: Context): GoogleApiHelper { - if (!::instance.isInitialized) instance = GoogleApiHelper(context.applicationContext) - return instance - } - - val SCOPES = setOf("https://www.googleapis.com/auth/drive.metadata.readonly", "profile") - const val USER_ID = "google-user" - const val PREFS = "google-account" - const val PREF_ACCOUNT_NAME = "name" - - private var callingActivity: Class? = null - } -} \ No newline at end of file diff --git a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAuthRedirectActivity.kt b/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAuthRedirectActivity.kt deleted file mode 100644 index 0c60de11..00000000 --- a/libs/g-services/src/main/java/de/mm20/launcher2/gservices/GoogleAuthRedirectActivity.kt +++ /dev/null @@ -1,24 +0,0 @@ -package de.mm20.launcher2.gservices - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.lifecycleScope -import kotlinx.coroutines.launch - -class GoogleAuthRedirectActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val gServiceHelper = GoogleApiHelper.getInstance(this) - val code = intent.data?.getQueryParameter("code") - if (code == null) { - gServiceHelper.cancelAuthFlow(this) - finish() - } - else { - lifecycleScope.launch { - gServiceHelper.finishAuthFlow(this@GoogleAuthRedirectActivity, code) - finish() - } - } - } -} \ No newline at end of file diff --git a/libs/g-services/src/main/res/drawable/ic_google_g.xml b/libs/g-services/src/main/res/drawable/ic_google_g.xml deleted file mode 100644 index 75879004..00000000 --- a/libs/g-services/src/main/res/drawable/ic_google_g.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - diff --git a/libs/g-services/src/main/res/values/styles.xml b/libs/g-services/src/main/res/values/styles.xml deleted file mode 100644 index b8c8d4eb..00000000 --- a/libs/g-services/src/main/res/values/styles.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/libs/g-services/src/release/res/raw/g_services_example.json b/libs/g-services/src/release/res/raw/g_services_example.json deleted file mode 100644 index 71718eec..00000000 --- a/libs/g-services/src/release/res/raw/g_services_example.json +++ /dev/null @@ -1 +0,0 @@ -{"installed":{"client_id":"xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com","project_id":"xxxxx-xxxxxxxxxxxxx","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} diff --git a/services/accounts/build.gradle.kts b/services/accounts/build.gradle.kts index eddd8d09..b1741d12 100644 --- a/services/accounts/build.gradle.kts +++ b/services/accounts/build.gradle.kts @@ -39,7 +39,6 @@ dependencies { implementation(libs.koin.android) - implementation(project(":libs:g-services")) implementation(project(":libs:owncloud")) implementation(project(":libs:nextcloud")) diff --git a/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountType.kt b/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountType.kt index bef71441..65e09f0b 100644 --- a/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountType.kt +++ b/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountType.kt @@ -1,7 +1,6 @@ package de.mm20.launcher2.accounts enum class AccountType { - Google, Nextcloud, Owncloud, } \ No newline at end of file diff --git a/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountsRepository.kt b/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountsRepository.kt index 9663c819..5aec38bc 100644 --- a/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountsRepository.kt +++ b/services/accounts/src/main/java/de/mm20/launcher2/accounts/AccountsRepository.kt @@ -2,7 +2,6 @@ package de.mm20.launcher2.accounts import android.app.Activity import android.content.Context -import de.mm20.launcher2.gservices.GoogleApiHelper import de.mm20.launcher2.nextcloud.NextcloudApiHelper import de.mm20.launcher2.owncloud.OwncloudClient import kotlinx.coroutines.CoroutineScope @@ -27,17 +26,11 @@ internal class AccountsRepositoryImpl( ) : AccountsRepository { private val scope = CoroutineScope(Job() + Dispatchers.Default) - private val googleApiHelper = GoogleApiHelper.getInstance(context) private val nextcloudApiHelper = NextcloudApiHelper(context) private val owncloudApiHelper = OwncloudClient(context) override fun signin(context: Activity, accountType: AccountType) { when (accountType) { - AccountType.Google -> { - scope.launch { - googleApiHelper.login(context) - } - } AccountType.Nextcloud -> scope.launch { nextcloudApiHelper.login(context) @@ -51,9 +44,6 @@ internal class AccountsRepositoryImpl( override fun signout(accountType: AccountType) { when (accountType) { - AccountType.Google -> { - googleApiHelper.logout() - } AccountType.Nextcloud -> { scope.launch { nextcloudApiHelper.logout() @@ -67,7 +57,6 @@ internal class AccountsRepositoryImpl( override fun isSupported(accountType: AccountType): Boolean { return when (accountType) { - AccountType.Google -> googleApiHelper.isAvailable() AccountType.Nextcloud -> true AccountType.Owncloud -> true } @@ -75,9 +64,6 @@ internal class AccountsRepositoryImpl( override suspend fun getCurrentlySignedInAccount(accountType: AccountType): Account? { return when (accountType) { - AccountType.Google -> { - getGoogleAccount() - } AccountType.Nextcloud -> { getNextcloudAccount() } @@ -87,12 +73,6 @@ internal class AccountsRepositoryImpl( } } - private suspend fun getGoogleAccount(): Account? { - return googleApiHelper.getAccount()?.let { - Account(it.name, AccountType.Google) - } - } - private suspend fun getNextcloudAccount(): Account? { return nextcloudApiHelper.getLoggedInUser()?.let { Account(it.displayName, AccountType.Nextcloud) diff --git a/settings.gradle.kts b/settings.gradle.kts index 9f804123..a4d80bc6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -57,7 +57,6 @@ include(":libs:material-color-utilities") include(":libs:nextcloud") include(":libs:owncloud") include(":libs:webdav") -include(":libs:g-services") include(":libs:address-formatter") include(":services:global-actions") include(":services:widgets")