diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5096765..be45f12 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,7 +78,7 @@ android { } dependencies { - implementation(libs.androidx.ktx) + implementation(libs.bundles.androidx.ktx) val composeBom = platform(libs.compose.bom) implementation(composeBom) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 55dfba4..29d5780 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,24 +10,35 @@ + + + + android:name=".SettingsActivity" + android:exported="true" /> + + + + + + diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/ShareActivity.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt similarity index 87% rename from app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/ShareActivity.kt rename to app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt index c8712de..1fcd9d8 100644 --- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/ShareActivity.kt +++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/DetailsActivity.kt @@ -63,20 +63,25 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import androidx.preference.PreferenceManager import com.mateusrodcosta.apps.share2storage.model.SampleUriDataProvider import com.mateusrodcosta.apps.share2storage.model.UriData import com.mateusrodcosta.apps.share2storage.theme.AppTheme import com.mateusrodcosta.apps.share2storage.utils.AppBasicDivider import com.mateusrodcosta.apps.share2storage.utils.getUriData import com.mateusrodcosta.apps.share2storage.utils.saveFile +import com.mateusrodcosta.apps.share2storage.utils.spSkipFileDetailsKey -class ShareActivity : ComponentActivity() { +class DetailsActivity : ComponentActivity() { private var createFile: ActivityResultLauncher? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) + val skipFileDetails = sharedPreferences.getBoolean(spSkipFileDetailsKey, false) + var uriData: UriData? = null if (intent?.action == Intent.ACTION_SEND) { @@ -103,34 +108,33 @@ class ShareActivity : ComponentActivity() { R.string.toast_saved_file_failure }, Toast.LENGTH_LONG ).show() + if (skipFileDetails) finish() }) } } - setContent { ShareScreen(uriData) } + setContent { DetailsScreen(uriData) } + + if (skipFileDetails) createFile?.launch(uriData?.displayName ?: "") } @OptIn(ExperimentalMaterial3Api::class) @Composable @Preview - fun ShareScreen(@PreviewParameter(SampleUriDataProvider::class) uriData: UriData?) { + fun DetailsScreen(@PreviewParameter(SampleUriDataProvider::class) uriData: UriData?) { AppTheme { - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.file_details)) } + Scaffold(topBar = { + TopAppBar(title = { Text(stringResource(R.string.file_details)) }) + }, floatingActionButton = { + FloatingActionButton(onClick = { + createFile?.launch(uriData?.displayName ?: "") + }, content = { + Image( + imageVector = Icons.Rounded.Download, + contentDescription = stringResource(R.string.save_button) ) - }, - floatingActionButton = { - FloatingActionButton(onClick = { - createFile?.launch(uriData?.displayName ?: "") - }, content = { - Image( - imageVector = Icons.Rounded.Download, - contentDescription = stringResource(R.string.save_button) - ) - }) - }) { paddingValues -> + }) + }) { paddingValues -> Box( contentAlignment = Alignment.Center, modifier = Modifier diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt index 54df5eb..cf7d83c 100644 --- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt +++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt @@ -38,7 +38,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Settings import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -69,14 +73,16 @@ class MainActivity : ComponentActivity() { fun MainScreen() { val context = this AppTheme { - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.app_name)) } - ) - } - ) - { paddingValues -> + Scaffold(topBar = { + TopAppBar(title = { Text(stringResource(R.string.app_name)) }, actions = { + IconButton(onClick = { + val i = Intent(context, SettingsActivity::class.java) + startActivity(i) + }) { + Icon(Icons.Rounded.Settings, stringResource(id = R.string.settings)) + } + }) + }) { paddingValues -> Box(modifier = Modifier.padding(paddingValues)) { Column( modifier = Modifier diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsActivity.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsActivity.kt new file mode 100644 index 0000000..32ff9b6 --- /dev/null +++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsActivity.kt @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2022 - 2023 Mateus Rodrigues Costa + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.mateusrodcosta.apps.share2storage + +import android.content.SharedPreferences +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.core.content.edit +import androidx.preference.PreferenceManager +import com.mateusrodcosta.apps.share2storage.theme.AppTheme +import com.mateusrodcosta.apps.share2storage.utils.spSkipFileDetailsKey + + +class SettingsActivity : ComponentActivity() { + + private lateinit var sharedPreferences: SharedPreferences + + private var spSkipFileDetails: Boolean = false + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + initSharedPreferences() + setContent { SettingsScreen() } + } + + private fun initSharedPreferences() { + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) + spSkipFileDetails = sharedPreferences.getBoolean(spSkipFileDetailsKey, false) + } + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + @Preview + fun SettingsScreen() { + var skipFileDetails by remember { mutableStateOf(spSkipFileDetails) } + + val updateSkipFileDetails: (Boolean) -> Unit = { value -> + sharedPreferences.edit(commit = true) { + putBoolean(spSkipFileDetailsKey, value) + } + skipFileDetails = value + } + AppTheme { + Scaffold(topBar = { + TopAppBar( + title = { Text(stringResource(R.string.settings)) }, + navigationIcon = { + IconButton(onClick = { finish() }) { + Icon( + Icons.Filled.ArrowBack, stringResource(id = R.string.back_arrow) + ) + } + }, + ) + }) { paddingValues -> + Box(modifier = Modifier.padding(paddingValues)) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Column { + Row(modifier = Modifier + .clickable { updateSkipFileDetails(!skipFileDetails) } + .padding(PaddingValues(horizontal = 16.dp, vertical = 8.dp)) + .heightIn(min = 48.dp), + verticalAlignment = Alignment.CenterVertically) { + Column( + modifier = Modifier.weight(1.0f), + ) { + Text( + stringResource(id = R.string.settings_skip_file_details_page), + style = MaterialTheme.typography.titleLarge, + ) + Text( + stringResource(R.string.settings_skip_file_details_page_info), + style = MaterialTheme.typography.bodyLarge + ) + } + Spacer(modifier = Modifier.width(8.dp)) + Switch( + checked = skipFileDetails, + onCheckedChange = updateSkipFileDetails + ) + + } + } + } + } + } + } + } +} + diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/utils/Utils.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/utils/Utils.kt index 7a64981..782a32b 100644 --- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/utils/Utils.kt +++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/utils/Utils.kt @@ -26,6 +26,8 @@ import android.provider.OpenableColumns import com.mateusrodcosta.apps.share2storage.model.UriData import java.io.* +const val spSkipFileDetailsKey: String = "skip_file_details" + fun getUriData(contentResolver: ContentResolver, uri: Uri?): UriData? { if (uri == null) return null val type = contentResolver.getType(uri) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6dd5198..bfaaeaa 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -12,6 +12,10 @@ Desenvolvido por Mateus Rodrigues Costa, licenciado sob AGPLv3+ Código-fonte disponível no Github em https://github.com/MateusRodCosta/Share2Storage + Settings + Pular página de Detalhes do arquivo + Abrir seletor de arquivos assim que receber arquivo + Salvar Nenhum arquivo @@ -23,4 +27,6 @@ Arquivo salvo com sucesso! Ocorreu um erro ao salvar o arquivo. + + Voltar \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 611a475..bf259cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,6 +12,10 @@ Developed by Mateus Rodrigues Costa, licensed under AGPLv3+ Source code available on Github at https://github.com/MateusRodCosta/Share2Storage + Settings + Skip File Details page + Open file picker as soon as file is received + Save No file found @@ -23,4 +27,6 @@ File saved successfully! An error occurred while saving the file. + + Back Arrow \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d3f6ded..d90e844 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ androidGradlePlugin = "8.2.0" kotlin = "1.9.21" ktx = "1.12.0" +preference-ktx = "1.2.1" composeBom = "2023.10.01" activityCompose = "1.8.2" junit = "4.13.2" @@ -9,7 +10,8 @@ androidxTestRunner = "1.5.2" androidxTestRules = "1.5.0" [libraries] -androidx-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx" } +androidx-preference-ktx = { group = "androidx.preference", name = "preference-ktx", version.ref = "preference-ktx" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } compose-material3 = { group = "androidx.compose.material3", name = "material3" } compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } @@ -23,6 +25,7 @@ androidx-test-runner = { group = "androidx.test", name="runner", version.ref = " androidx-test-rules = { group = "androidx.test", name="rules", version.ref = "androidxTestRules" } [bundles] +androidx-ktx = ["androidx.core.ktx", "androidx.preference.ktx"] compose = ["compose.material3", "compose.ui.tooling.preview", "compose.ui.material.icons.extended"] compose-debug = ["compose.ui.tooling", "compose.ui.test.manifest"] testing = ["junit.junit"]