diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3abe2b6..48e55b4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,10 +19,6 @@
-
-
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 355c154..535cd86 100644
--- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt
+++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/MainActivity.kt
@@ -18,16 +18,36 @@
package com.mateusrodcosta.apps.share2storage
import android.os.Bundle
+import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
-import com.mateusrodcosta.apps.share2storage.screens.MainScreen
+import androidx.activity.result.contract.ActivityResultContracts
+import com.mateusrodcosta.apps.share2storage.screens.AppNavigation
class MainActivity : ComponentActivity() {
+
+ private val settingsViewModel: SettingsViewModel = SettingsViewModel()
+
+ private val getSaveLocationDirIntent =
+ registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
+ if (uri == null) return@registerForActivityResult
+
+ Log.d("settings] getSaveLocationDir] uri", uri.toString())
+ Log.d("settings] getSaveLocationDir] uri.path", uri.path.toString())
+
+ settingsViewModel.updateDefaultSaveLocation(uri)
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
- setContent { MainScreen() }
+
+ settingsViewModel.receiveContext(applicationContext)
+ settingsViewModel.assignSaveLocationDirIntent(getSaveLocationDirIntent)
+ settingsViewModel.initPreferences()
+
+ setContent { AppNavigation(settingsViewModel) }
}
}
diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsActivity.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsActivity.kt
deleted file mode 100644
index 0b23b9a..0000000
--- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsActivity.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2022 - 2024 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.os.Bundle
-import android.util.Log
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.activity.enableEdgeToEdge
-import androidx.activity.result.contract.ActivityResultContracts
-import com.mateusrodcosta.apps.share2storage.screens.SettingsScreen
-
-class SettingsActivity : ComponentActivity() {
-
- private val settingsViewModel: SettingsViewModel = SettingsViewModel()
-
- private val getSaveLocationDirIntent =
- registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
- if (uri == null) return@registerForActivityResult
-
- Log.d("settings] getSaveLocationDir] uri", uri.toString())
- Log.d("settings] getSaveLocationDir] uri.path", uri.path.toString())
-
- settingsViewModel.updateDefaultSaveLocation(uri)
- }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- enableEdgeToEdge()
- super.onCreate(savedInstanceState)
-
- settingsViewModel.receiveContext(applicationContext)
- settingsViewModel.initPreferences()
-
- setContent {
- SettingsScreen(
- spDefaultSaveLocation = settingsViewModel.defaultSaveLocation,
- spSkipFileDetails = settingsViewModel.skipFileDetails,
- launchFilePicker = { getSaveLocationDirIntent.launch(null) },
- clearSaveDirectory = { settingsViewModel.clearSaveDirectory() },
- updateSkipFileDetails = { value: Boolean ->
- settingsViewModel.updateSkipFileDetails(value)
- },
- closeActivity = { this.finish() }
- )
- }
- }
-}
diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsViewModel.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsViewModel.kt
index a316c5f..0ea1024 100644
--- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsViewModel.kt
+++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/SettingsViewModel.kt
@@ -23,6 +23,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.util.Log
+import androidx.activity.result.ActivityResultLauncher
import androidx.core.content.edit
import androidx.lifecycle.ViewModel
import androidx.preference.PreferenceManager
@@ -34,6 +35,7 @@ class SettingsViewModel : ViewModel() {
private lateinit var sharedPreferences: SharedPreferences
private lateinit var contentResolver: ContentResolver
+ private lateinit var getSaveLocationDirIntent: ActivityResultLauncher
private val _defaultSaveLocation = MutableStateFlow(null)
val defaultSaveLocation: StateFlow = _defaultSaveLocation
@@ -41,6 +43,14 @@ class SettingsViewModel : ViewModel() {
private val _skipFileDetails = MutableStateFlow(false)
val skipFileDetails: StateFlow = _skipFileDetails
+ fun assignSaveLocationDirIntent(intent: ActivityResultLauncher) {
+ getSaveLocationDirIntent = intent
+ }
+
+ fun getSaveLocationDirIntent(): ActivityResultLauncher {
+ return getSaveLocationDirIntent
+ }
+
fun receiveContext(context: Context) {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
contentResolver = context.contentResolver
diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/AppNavigation.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/AppNavigation.kt
new file mode 100644
index 0000000..c9f33af
--- /dev/null
+++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/AppNavigation.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 - 2024 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.screens
+
+import androidx.compose.runtime.Composable
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import com.mateusrodcosta.apps.share2storage.SettingsViewModel
+
+@Composable
+fun AppNavigation(settingsViewModel: SettingsViewModel) {
+ val navController = rememberNavController()
+
+ NavHost(navController = navController, startDestination = "main") {
+ composable("main") { MainScreen(navController) }
+ composable("settings") { SettingsScreen(navController, settingsViewModel) }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/MainScreen.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/MainScreen.kt
index f8862a4..574700e 100644
--- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/MainScreen.kt
+++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/MainScreen.kt
@@ -17,7 +17,6 @@
package com.mateusrodcosta.apps.share2storage.screens
-import android.content.Intent
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
@@ -46,15 +45,14 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.navigation.NavController
import com.mateusrodcosta.apps.share2storage.R
-import com.mateusrodcosta.apps.share2storage.SettingsActivity
import com.mateusrodcosta.apps.share2storage.ui.theme.AppTheme
import com.mateusrodcosta.apps.share2storage.utils.AppBasicDivider
import com.mateusrodcosta.apps.share2storage.utils.appTopAppBarColors
@@ -62,22 +60,23 @@ import com.mateusrodcosta.apps.share2storage.utils.appTopAppBarColors
@Preview(apiLevel = 33, showBackground = true)
@Composable
fun MainScreenPreview() {
- MainScreen()
+ MainScreenContent(navController = null)
+}
+
+@Composable
+fun MainScreen(navController: NavController) {
+ MainScreenContent(navController = navController)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun MainScreen() {
- val context = LocalContext.current
+fun MainScreenContent(navController: NavController?) {
AppTheme {
Scaffold(topBar = {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
actions = {
- IconButton(onClick = {
- val intent = Intent(context, SettingsActivity::class.java)
- context.startActivity(intent)
- }) {
+ IconButton(onClick = { navController?.navigate("settings") }) {
Icon(Icons.Rounded.Settings, stringResource(id = R.string.settings))
}
},
diff --git a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/SettingsScreen.kt b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/SettingsScreen.kt
index 6b5444b..e1666dd 100644
--- a/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/SettingsScreen.kt
+++ b/app/src/main/kotlin/com/mateusrodcosta/apps/share2storage/screens/SettingsScreen.kt
@@ -49,7 +49,9 @@ 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.navigation.NavController
import com.mateusrodcosta.apps.share2storage.R
+import com.mateusrodcosta.apps.share2storage.SettingsViewModel
import com.mateusrodcosta.apps.share2storage.ui.theme.AppTheme
import com.mateusrodcosta.apps.share2storage.utils.AppBasicDivider
import com.mateusrodcosta.apps.share2storage.utils.appTopAppBarColors
@@ -62,29 +64,40 @@ fun SettingsScreenPreview() {
val mockDefaultSaveLocation = MutableStateFlow(null)
val mockSkipFileDetails = MutableStateFlow(false)
- SettingsScreen(
+ SettingsScreenContent(
+ navController = null,
spDefaultSaveLocation = mockDefaultSaveLocation,
spSkipFileDetails = mockSkipFileDetails,
launchFilePicker = {},
clearSaveDirectory = {},
- updateSkipFileDetails = { _ -> },
- closeActivity = {},
+ updateSkipFileDetails = {},
+ )
+}
+
+@Composable
+fun SettingsScreen(navController: NavController, settingsViewModel: SettingsViewModel) {
+ SettingsScreenContent(
+ navController = navController,
+ spDefaultSaveLocation = settingsViewModel.defaultSaveLocation,
+ spSkipFileDetails = settingsViewModel.skipFileDetails,
+ launchFilePicker = { settingsViewModel.getSaveLocationDirIntent().launch(null) },
+ clearSaveDirectory = { settingsViewModel.clearSaveDirectory() },
+ updateSkipFileDetails = { value: Boolean ->
+ settingsViewModel.updateSkipFileDetails(value)
+ },
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun SettingsScreen(
+fun SettingsScreenContent(
+ navController: NavController?,
spDefaultSaveLocation: StateFlow,
spSkipFileDetails: StateFlow,
- launchFilePicker: (() -> Unit),
- clearSaveDirectory: (() -> Unit),
- updateSkipFileDetails: ((Boolean) -> Unit),
- closeActivity: () -> Unit,
+ launchFilePicker: () -> Unit,
+ clearSaveDirectory: () -> Unit,
+ updateSkipFileDetails: (Boolean) -> Unit,
) {
- val defaultSaveLocation by spDefaultSaveLocation.collectAsState()
- val skipFileDetails by spSkipFileDetails.collectAsState()
-
val settingsPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
AppTheme {
@@ -92,7 +105,7 @@ fun SettingsScreen(
TopAppBar(title = { Text(stringResource(R.string.settings)) },
colors = appTopAppBarColors(),
navigationIcon = {
- IconButton(onClick = { closeActivity() }) {
+ IconButton(onClick = { navController?.navigateUp() }) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
stringResource(id = R.string.back_arrow)
@@ -110,14 +123,14 @@ fun SettingsScreen(
Column {
SkipFileDetailsSetting(
updateSkipFileDetails = updateSkipFileDetails,
- skipFileDetails = skipFileDetails,
+ spSkipFileDetails = spSkipFileDetails,
paddingValues = settingsPadding,
)
AppBasicDivider()
DefaultSaveLocationSetting(
launchFilePicker = launchFilePicker,
clearSaveDirectory = clearSaveDirectory,
- defaultSaveLocation = defaultSaveLocation,
+ spDefaultSaveLocation = spDefaultSaveLocation,
paddingValues = settingsPadding,
)
AppBasicDivider()
@@ -130,10 +143,12 @@ fun SettingsScreen(
@Composable
fun SkipFileDetailsSetting(
- updateSkipFileDetails: ((Boolean) -> Unit),
- skipFileDetails: Boolean,
+ updateSkipFileDetails: (Boolean) -> Unit,
+ spSkipFileDetails: StateFlow,
paddingValues: PaddingValues,
) {
+ val skipFileDetails by spSkipFileDetails.collectAsState()
+
Row(modifier = Modifier
.clickable { updateSkipFileDetails(!skipFileDetails) }
.padding(paddingValues)
@@ -158,11 +173,13 @@ fun SkipFileDetailsSetting(
@Composable
fun DefaultSaveLocationSetting(
- launchFilePicker: (() -> Unit),
- clearSaveDirectory: (() -> Unit),
- defaultSaveLocation: Uri?,
+ launchFilePicker: () -> Unit,
+ clearSaveDirectory: () -> Unit,
+ spDefaultSaveLocation: StateFlow,
paddingValues: PaddingValues,
) {
+ val defaultSaveLocation by spDefaultSaveLocation.collectAsState()
+
Row(modifier = Modifier
.clickable { launchFilePicker() }
.padding(paddingValues)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ed97338..08955a4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -7,6 +7,7 @@ preference-ktx = "1.2.1"
composeBom = "2024.01.00"
composeMaterial3WindowSizeClass = "1.1.2"
activityCompose = "1.8.2"
+navigationCompose = "2.7.7"
junit = "4.13.2"
androidxTestRunner = "1.5.2"
androidxTestRules = "1.5.0"
@@ -23,6 +24,7 @@ compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling
compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
+androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
junit-junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-runner = { group = "androidx.test", name="runner", version.ref = "androidxTestRunner" }
androidx-test-rules = { group = "androidx.test", name="rules", version.ref = "androidxTestRules" }
@@ -31,7 +33,7 @@ androidx-test-rules = { group = "androidx.test", name="rules", version.ref = "an
androidx-ktx = ["androidx.core.ktx", "androidx.preference.ktx"]
compose = ["compose.material3", "compose.material3.window.size.classes", "compose.ui.tooling.preview", "compose.ui.material.icons.extended"]
compose-debug = ["compose.ui.tooling", "compose.ui.test.manifest"]
-androidx-compose-integration = ["androidx.activity.compose"]
+androidx-compose-integration = ["androidx.activity.compose", "androidx.navigation.compose"]
testing = ["junit.junit"]
ui-testing = ["androidx.test.runner", "androidx.test.rules", "compose.ui.test.junit4"]