diff --git a/.gitignore b/.gitignore
index e10ceb9..cc698b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,6 @@
-git *.iml
.gradle
+.idea
/local.properties
-/.idea/caches
-/.idea/libraries
-/.idea/modules.xml
-/.idea/workspace.xml
-/.idea/navEditor.xml
-/.idea/sonarlint
-/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index b589d56..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 0c0c338..0000000
--- a/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index ee7b132..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 44ca2d9..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
deleted file mode 100644
index fdf8d99..0000000
--- a/.idea/kotlinc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
deleted file mode 100644
index f8051a6..0000000
--- a/.idea/migrations.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 0ad17cb..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/sonarlint/issuestore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 b/.idea/sonarlint/issuestore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d b/.idea/sonarlint/issuestore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 b/.idea/sonarlint/issuestore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c b/.idea/sonarlint/issuestore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 b/.idea/sonarlint/issuestore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d b/.idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d
deleted file mode 100644
index 70bf876..0000000
--- a/.idea/sonarlint/issuestore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d
+++ /dev/null
@@ -1,2 +0,0 @@
-
-I xml:S1135"4Complete the task associated to this "TODO" comment.(ÿ°Á‡
\ No newline at end of file
diff --git a/.idea/sonarlint/issuestore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 b/.idea/sonarlint/issuestore/4/9/49845c622cb06d895975c7b1e3f943e320bce688
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f b/.idea/sonarlint/issuestore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d b/.idea/sonarlint/issuestore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df b/.idea/sonarlint/issuestore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 b/.idea/sonarlint/issuestore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e b/.idea/sonarlint/issuestore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 b/.idea/sonarlint/issuestore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b b/.idea/sonarlint/issuestore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e b/.idea/sonarlint/issuestore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 b/.idea/sonarlint/issuestore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 b/.idea/sonarlint/issuestore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b b/.idea/sonarlint/issuestore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 b/.idea/sonarlint/issuestore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/d/2/d2281fbb3027de2722081a53408dd77628bf080e b/.idea/sonarlint/issuestore/d/2/d2281fbb3027de2722081a53408dd77628bf080e
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 b/.idea/sonarlint/issuestore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 b/.idea/sonarlint/issuestore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d b/.idea/sonarlint/issuestore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 b/.idea/sonarlint/issuestore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 b/.idea/sonarlint/issuestore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 b/.idea/sonarlint/issuestore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4 b/.idea/sonarlint/securityhotspotstore/0/4/042c535c429bdd8eb38e72c5823732d8e9fc56f4
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d b/.idea/sonarlint/securityhotspotstore/0/7/078508c831007ccb3938b355f0d30a8368f99a8d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26 b/.idea/sonarlint/securityhotspotstore/2/4/24ce74baca63d400e46baee54dfd1daccb063d26
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c b/.idea/sonarlint/securityhotspotstore/2/a/2a39d64fb5e43e17f8377da18e4dd7cc29d88e6c
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9 b/.idea/sonarlint/securityhotspotstore/2/f/2fe217d36e73005d1fe23b1af3dc3021b9b2bcb9
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d b/.idea/sonarlint/securityhotspotstore/3/b/3bc4db92963be77ebed9d7a4fff09127a1110e4d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/4/9/49845c622cb06d895975c7b1e3f943e320bce688 b/.idea/sonarlint/securityhotspotstore/4/9/49845c622cb06d895975c7b1e3f943e320bce688
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f b/.idea/sonarlint/securityhotspotstore/5/1/51e1c5d383dfaa35e0e7e5873a0a99355a86880f
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d b/.idea/sonarlint/securityhotspotstore/5/5/555c0e66444eb0c348537e60a7e7bf60f2a3f57d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df b/.idea/sonarlint/securityhotspotstore/6/e/6ec7d34b130497a10dc92abcde9b313d370a89df
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50 b/.idea/sonarlint/securityhotspotstore/7/9/7962297d9704dd3414ea37c6c18ad6265dcefd50
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e b/.idea/sonarlint/securityhotspotstore/8/c/8c55c3ccc257e5907959013f99656e4c8ec3903e
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17 b/.idea/sonarlint/securityhotspotstore/8/e/8e27ba16c655f421171956147d0fde89b7d25d17
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b b/.idea/sonarlint/securityhotspotstore/9/6/969faa2a5d9f5e8390e958d2c07f2cfd54676e6b
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e b/.idea/sonarlint/securityhotspotstore/9/c/9c2a853ebd9f87844b147b05656fea1b7325609e
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9 b/.idea/sonarlint/securityhotspotstore/9/e/9e08934d811afe28fbc77aaa3c0d747b94348db9
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302 b/.idea/sonarlint/securityhotspotstore/a/5/a5cc2925ca8258af241be7e5b0381edf30266302
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b b/.idea/sonarlint/securityhotspotstore/a/a/aa8f09dc818431a1d89e3112f6cfbf167cc8ce6b
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32 b/.idea/sonarlint/securityhotspotstore/c/3/c3c1434c45ed15ce4f358f51e25422c2f32f6c32
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376 b/.idea/sonarlint/securityhotspotstore/c/a/ca80fb3fe73b5d731cf9a48f29a9d84a551c1376
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/d/2/d2281fbb3027de2722081a53408dd77628bf080e b/.idea/sonarlint/securityhotspotstore/d/2/d2281fbb3027de2722081a53408dd77628bf080e
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6 b/.idea/sonarlint/securityhotspotstore/d/2/d2a4383452aad84a18429a5844d31330a012a9e6
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884 b/.idea/sonarlint/securityhotspotstore/d/7/d7c93c97f99f4c73287b6fd9dbc30bd6a4e17884
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d b/.idea/sonarlint/securityhotspotstore/d/b/dbcff70658daf80b53ce624f6adcaa529df5ed8d
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8 b/.idea/sonarlint/securityhotspotstore/e/0/e0bc1eda8e2c689cb79d5b6e5cfd11385f06c2b8
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3 b/.idea/sonarlint/securityhotspotstore/e/b/eb7f0f821bde169dd21862705b2b042d2cea69a3
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/sonarlint/securityhotspotstore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4 b/.idea/sonarlint/securityhotspotstore/f/4/f4ccae7b16112b00a2d85965108cf28a4b17a2b4
deleted file mode 100644
index e69de29..0000000
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f46566..2354b92 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,6 +9,8 @@
+
diff --git a/app/src/main/java/com/ss/smartstorage/MainActivity.kt b/app/src/main/java/com/ss/smartstorage/MainActivity.kt
index f766303..0cb29d3 100644
--- a/app/src/main/java/com/ss/smartstorage/MainActivity.kt
+++ b/app/src/main/java/com/ss/smartstorage/MainActivity.kt
@@ -1,5 +1,6 @@
package com.ss.smartstorage
+import android.annotation.SuppressLint
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -8,12 +9,11 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import com.ss.smart_storage.SmartStorage
-import com.ss.smart_storage.util.SmartDirectory
-import com.ss.smart_storage.util.SmartFileType
import com.ss.smartstorage.ui.theme.SmartStorageTheme
class MainActivity : ComponentActivity() {
+ @SuppressLint("NewApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -27,14 +27,14 @@ class MainActivity : ComponentActivity() {
color = MaterialTheme.colorScheme.background
) {
SmartStorageSample(
- onStoreTap = {
- smartStorage.store(
- location = SmartDirectory.CUSTOM,
- fileName = "interstellar",
- fileType = SmartFileType.txt,
- fileData = "Directed by Christopher Nolan".toByteArray()
- )
- },
+ onStoreTap = { fileName, fileType, location ->
+ smartStorage.store(
+ location = location,
+ fileType = fileType,
+ fileName = fileName,
+ fileData = "This is a sample txt file.".toByteArray()
+ )
+ }
)
}
}
diff --git a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt
index ac0401a..3ad8a7c 100644
--- a/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt
+++ b/app/src/main/java/com/ss/smartstorage/SmartStorageSample.kt
@@ -1,23 +1,266 @@
package com.ss.smartstorage
+
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
-import androidx.compose.material3.ElevatedButton
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.Button
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.material3.TextField
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.ss.smart_storage.util.SmartDirectory
+import com.ss.smart_storage.util.SmartFileType
+import kotlinx.coroutines.launch
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun SmartStorageToolBar() {
+ TopAppBar(
+ title = {
+ Text(
+ text = "Smart Storage Demo",
+ textAlign = TextAlign.Center,
+ fontSize = 30.sp,
+ fontWeight = FontWeight.Bold
+ )
+ },
+
+ )
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SmartStorageSample(
- onStoreTap : () -> Unit,
-){
- Column(
- verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally,
- ) {
- ElevatedButton(onClick = {onStoreTap()}) {
- Text(text = "SAVE DUMMY") }
+ onStoreTap: (String, SmartFileType, String) -> Unit
+) {
+ var showBottomSheetD by remember { mutableStateOf(false) }
+
+ val sheetState = rememberModalBottomSheetState()
+ val scope = rememberCoroutineScope()
+
+ var selectedDestination by remember {
+ mutableStateOf("")
+ }
+
+ var isSaveButtonVisible by remember {
+ mutableStateOf(false)
+ }
+
+ var showBottomSheetF by remember {
+ mutableStateOf(false)
+ }
+ var fileName by remember {
+ mutableStateOf("")
+ }
+
+ var selectedFiletype by remember {
+ mutableStateOf(SmartFileType.TXT)
+ }
+ val snackbarHostState = remember { SnackbarHostState() }
+
+ Scaffold(topBar = { SmartStorageToolBar() }, snackbarHost = {
+ SnackbarHost(hostState = snackbarHostState)
+ }, content = { contentPadding ->
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(paddingValues = contentPadding)
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(start = 20.dp, end = 30.dp, top = 10.dp)
+ ) {
+ Column(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(text = "File Name : ")
+ Spacer(modifier = Modifier.height(16.dp))
+
+ Row {
+
+ TextField(
+ value = fileName,
+ onValueChange = {
+ fileName = it
+ },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
+ modifier = Modifier.fillMaxWidth()
+ )
+
+
+ }
+ }
+ Spacer(modifier = Modifier.height(20.dp))
+
+
+ Column(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(text = "File Storage Type : ")
+ Spacer(modifier = Modifier.height(16.dp))
+ OutlinedButton(onClick = { showBottomSheetF = true }) {
+ Text(text = selectedFiletype.toString().ifEmpty { "Select" })
+
+ }
+
+ }
+
+ Spacer(modifier = Modifier.height(20.dp))
+ Column(
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ Text(text = "File Storage Destination : ")
+ Spacer(modifier = Modifier.height(16.dp))
+ OutlinedButton(onClick = { showBottomSheetD = true }) {
+ Text(text = selectedDestination.ifEmpty { "Select" })
+
+ }
+
+ }
+
+ Spacer(modifier = Modifier.height(40.dp))
+
+
+
+ Column(
+ modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center
+ ) {
+ Button(
+ enabled = isSaveButtonVisible, onClick = {
+ onStoreTap(fileName, selectedFiletype, selectedDestination)
+ }, modifier = Modifier.align(Alignment.CenterHorizontally)
+ ) {
+ Text(text = "Save")
+ }
+ }
+ }
+
+ }
+ })
+ if (showBottomSheetF) {
+ ModalBottomSheet(
+ onDismissRequest = { showBottomSheetF = false },
+ sheetState = sheetState,
+ modifier = Modifier.fillMaxSize()
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ ) {
+ Text(
+ text = "Select File Type to store File",
+ style = MaterialTheme.typography.titleMedium
+ )
+
+ Spacer(modifier = Modifier.height(16.dp))
+
+ val fileTypes = listOf(
+ SmartFileType.TXT,
+ SmartFileType.JPEG,
+ SmartFileType.PDF,
+ SmartFileType.PNG,
+ SmartFileType.WEBP
+ )
+
+ fileTypes.forEach { fileType ->
+ TextButton(onClick = {
+ selectedFiletype = fileType
+ scope.launch { sheetState.hide() }.invokeOnCompletion {
+ if (!sheetState.isVisible) {
+ showBottomSheetF = false
+ }
+ }
+ }) {
+ Text(text = fileType.toString())
+ }
+ }
+
+ }
+
+
+ }
+ }
+
+ if (showBottomSheetD) {
+ ModalBottomSheet(
+ onDismissRequest = { showBottomSheetD = false },
+ sheetState = sheetState,
+ modifier = Modifier.fillMaxSize()
+ ) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ ) {
+ Text(
+ text = "Select Destination to store File",
+ style = MaterialTheme.typography.titleMedium
+ )
+
+ Spacer(modifier = Modifier.height(16.dp))
+
+ val destinations = listOf(
+ SmartDirectory.INTERNAL,
+ SmartDirectory.SCOPED_STORAGE,
+ SmartDirectory.CUSTOM,
+ SmartDirectory.DOWNLOADS,
+ SmartDirectory.DOCUMENTS,
+ SmartDirectory.EXTERNAL_PUBLIC
+ )
+
+ destinations.forEach { destination ->
+ TextButton(onClick = {
+ selectedDestination = destination
+ scope.launch { sheetState.hide() }.invokeOnCompletion {
+ if (!sheetState.isVisible) {
+ isSaveButtonVisible = true
+ showBottomSheetD = false
+ }
+ }
+ }) {
+ Text(text = destination)
+ }
+ }
+
+ }
+
+
+ }
}
}
+
+
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127..55344e5 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,10 +1,3 @@
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 086afa8..e343d2b 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,16 +1,16 @@
[versions]
-agp = "8.3.1"
+agp = "8.3.2"
coilCompose = "2.6.0"
kotlin = "1.9.0"
-coreKtx = "1.12.0"
+coreKtx = "1.13.0"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.7.0"
-activityCompose = "1.8.2"
-composeBom = "2023.08.00"
+activityCompose = "1.9.0"
+composeBom = "2024.04.01"
appcompat = "1.6.1"
-lifecycleViewmodelCompose = "2.6.1"
+lifecycleViewmodelCompose = "2.7.0"
material = "1.11.0"
documentfile = "1.0.1"
diff --git a/smart-storage/build.gradle.kts b/smart-storage/build.gradle.kts
index c23da6b..43b5f95 100644
--- a/smart-storage/build.gradle.kts
+++ b/smart-storage/build.gradle.kts
@@ -9,7 +9,6 @@ android {
defaultConfig {
minSdk = 23
-
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
@@ -33,11 +32,7 @@ android {
}
dependencies {
-
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
- testImplementation(libs.junit)
- androidTestImplementation(libs.androidx.junit)
- androidTestImplementation(libs.androidx.espresso.core)
}
\ No newline at end of file
diff --git a/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt
new file mode 100644
index 0000000..f13c97e
--- /dev/null
+++ b/smart-storage/src/main/java/com/ss/smart_storage/PermissionManager.kt
@@ -0,0 +1,105 @@
+package com.ss.smart_storage
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Build.VERSION_CODES.M
+import android.os.Build.VERSION_CODES.Q
+import android.os.Environment
+import androidx.activity.ComponentActivity
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.annotation.RequiresApi
+import androidx.core.content.ContextCompat
+import com.ss.smart_storage.util.PermissionStatus
+import com.ss.smart_storage.util.SmartDirectory
+
+
+class PermissionManager(
+ private val activity: ComponentActivity, val onPermissionGranted: (PermissionStatus) -> Unit
+) {
+ private val requestPermissionLauncher = activity.registerForActivityResult(
+ ActivityResultContracts.RequestPermission()
+ ) { isGranted: Boolean ->
+ if (isGranted) {
+ onPermissionGranted(PermissionStatus.ACCEPTED)
+ } else {
+ onPermissionGranted(PermissionStatus.DENIED)
+ }
+ }
+
+ fun checkLocation(location: String) {
+ when (location) {
+
+ SmartDirectory.CUSTOM -> {
+ onPermissionGranted(PermissionStatus.NOT_APPLICABLE)
+ }
+
+ SmartDirectory.INTERNAL -> {
+ onPermissionGranted(PermissionStatus.NOT_NEEDED)
+ }
+
+ SmartDirectory.DOCUMENTS -> {
+ checkOsForPermissions(location)
+ }
+
+ SmartDirectory.DOWNLOADS -> {
+ checkOsForPermissions(location)
+ }
+
+ SmartDirectory.SCOPED_STORAGE -> {
+ onPermissionGranted(PermissionStatus.NOT_NEEDED)
+ }
+
+ SmartDirectory.EXTERNAL_PUBLIC -> {
+ checkOsForPermissions(location)
+ }
+ }
+ }
+
+ private fun checkOsForPermissions(location: String) {
+ when {
+ Build.VERSION.SDK_INT in M..Q -> {
+ checkIfPermissionGranted(onPermissionGranted = {
+ onPermissionGranted(PermissionStatus.ACCEPTED)
+ })
+ }
+
+ (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && location == SmartDirectory.EXTERNAL_PUBLIC -> {
+
+ checkIfManagePermissionGranted(onPermissionGranted = { granted ->
+ if (granted) onPermissionGranted(PermissionStatus.ACCEPTED)
+ else onPermissionGranted(PermissionStatus.REDIRECT_TO_SETTINGS)
+ })
+
+
+ }
+
+ else -> {
+ onPermissionGranted(PermissionStatus.ACCEPTED)
+ }
+ }
+ }
+
+
+ private fun checkIfPermissionGranted(onPermissionGranted: () -> Unit) {
+ if (ContextCompat.checkSelfPermission(
+ activity, Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ onPermissionGranted()
+ } else {
+ requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.R)
+ private fun checkIfManagePermissionGranted(onPermissionGranted: (Boolean) -> Unit) {
+ if (Environment.isExternalStorageManager()) {
+ onPermissionGranted(true)
+ } else {
+ onPermissionGranted(false)
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt
index 0245dc4..36ff32d 100644
--- a/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt
+++ b/smart-storage/src/main/java/com/ss/smart_storage/SmartStorage.kt
@@ -1,19 +1,21 @@
package com.ss.smart_storage
-import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
-import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
+import android.provider.Settings
+import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
-import androidx.core.content.ContextCompat
+import androidx.annotation.RequiresApi
import androidx.documentfile.provider.DocumentFile
+import com.ss.smart_storage.model.FileDetails
+import com.ss.smart_storage.util.PermissionStatus
import com.ss.smart_storage.util.SmartDirectory
import com.ss.smart_storage.util.SmartFileType
import java.io.File
@@ -21,122 +23,109 @@ import java.io.FileOutputStream
import java.io.IOException
-data class FileDetails(
- val name: String,
- val location: String,
- val fileType: SmartFileType,
- val fileData: ByteArray,
-) {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
- other as FileDetails
- return fileData.contentEquals(other.fileData)
- }
+class SmartStorage(private val activity: ComponentActivity) {
- override fun hashCode(): Int {
- return fileData.contentHashCode()
- }
-}
+ private var baseDocumentTreeUri: Uri? = null
+ private lateinit var fileDetails: FileDetails
-class SmartStorage(private val activity: ComponentActivity) {
+ @SuppressLint("NewApi")
+ private val permissionManager =
+ PermissionManager(activity = activity, onPermissionGranted = { status ->
- private var baseDocumentTreeUri: Uri? = null
- private var fileDetails : FileDetails? = null
+ when (status) {
+ PermissionStatus.NOT_NEEDED -> {
+ callFileDetails()
+ }
+
+ PermissionStatus.ACCEPTED -> {
+ callFileDetails()
+ }
+ PermissionStatus.DENIED -> {
+ Toast.makeText(
+ activity,
+ activity.getString(R.string.perm_denied),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
- private val safLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
- if (result.resultCode == Activity.RESULT_OK) {
- val uri: Uri? = result.data?.data
- if (uri != null) {
- baseDocumentTreeUri = uri
- if(fileDetails!=null){
+ PermissionStatus.NOT_APPLICABLE -> {
+ launchBaseDirectoryPicker()
+ }
+
+ PermissionStatus.REDIRECT_TO_SETTINGS -> {
+ requestFullStorageAccess()
+ }
+ }
+ })
+
+
+ private val safLauncher =
+ activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == Activity.RESULT_OK) {
+ val uri: Uri? = result.data?.data
+ if (uri != null) {
+ baseDocumentTreeUri = uri
writeFileToDocumentTree(
baseDocumentTreeUri,
- fileDetails!!.name,
- fileDetails!!.fileData,
)
}
}
}
- }
-
- private val requestPermissionLauncher = activity.registerForActivityResult(
- ActivityResultContracts.RequestPermission()
- ) { isGranted: Boolean ->
- if (isGranted) {
- callFileDetails()
- } else {
- Toast.makeText(activity, "Permission denied", Toast.LENGTH_SHORT).show()
- }
- }
private fun launchBaseDirectoryPicker() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
safLauncher.launch(intent)
}
-
-//todo : Remove Supress Lint
- @SuppressLint("ObsoleteSdkInt")
- fun isWritePermissionGranted(){
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- if (ContextCompat.checkSelfPermission(
- activity,
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- ) == PackageManager.PERMISSION_GRANTED
- ) {
- callFileDetails()
- } else {
- requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
- }
- } else {
- callFileDetails()
- }
- }
-
- private fun callFileDetails(){
- if(fileDetails != null){
- if(fileDetails!!.location == SmartDirectory.CUSTOM){
- launchBaseDirectoryPicker()
- }
-
- else{
- storeToDirectory(
- fileDetails = fileDetails!!
- )
- }
- }
+ @RequiresApi(Build.VERSION_CODES.R)
+ private fun requestFullStorageAccess(){
+ activity.startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
}
fun store(
location: String, fileName: String? = null, fileType: SmartFileType, fileData: ByteArray
) {
+
val name =
- if (!fileName.isNullOrEmpty()) "$fileName.$fileType" else "smartStorage.${fileType.name}"
+ if(fileName.isNullOrEmpty()) randomFileName(fileType.extension) else fileName.plus(fileType.extension)
fileDetails = FileDetails(
- name = name,
- location = location,
- fileType = fileType,
- fileData = fileData
+ name = name, location = location, fileType = fileType, fileData = fileData
)
- isWritePermissionGranted()
+
+ permissionManager.checkLocation(location)
}
- private fun storeToDirectory(fileDetails: FileDetails){
+
+ private fun callFileDetails() {
+ storeToDirectory(
+ fileDetails = fileDetails
+ )
+ }
+
+ private fun randomFileName(extension : String): String {
+ val alphanumericChars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
+ val randomString = (1..8)
+ .map { alphanumericChars.random() }
+ .joinToString("")
+ return randomString.plus(extension)
+ }
+
+
+ private fun storeToDirectory(fileDetails: FileDetails) {
val directory = handleFileCreation(fileDetails.location, activity.applicationContext)
- if(directory!=null && !directory.exists()){
+ if (directory != null && !directory.exists()) {
directory.mkdirs()
}
val file = File(
directory, fileDetails.name
)
-
+ Log.d("Path to directory:", directory!!.path)
try {
FileOutputStream(file).use { stream ->
stream.write(fileDetails.fileData)
@@ -146,15 +135,22 @@ class SmartStorage(private val activity: ComponentActivity) {
}
}
- private fun writeFileToDocumentTree(baseDocumentTreeUri: Uri?, fileName: String, content: ByteArray) {
+ private fun writeFileToDocumentTree(
+ baseDocumentTreeUri: Uri?
+ ) {
baseDocumentTreeUri?.let { treeUri ->
try {
val directory = DocumentFile.fromTreeUri(activity.applicationContext, treeUri)
- val file = directory?.createFile("text/*", fileName)
- val pfd = file?.let { activity.applicationContext.contentResolver.openFileDescriptor(it.uri, "w") }
+ val file =
+ directory?.createFile(fileDetails.fileType.mimeType, fileDetails.fileType.name)
+ val pfd = file?.let {
+ activity.applicationContext.contentResolver.openFileDescriptor(
+ it.uri, "w"
+ )
+ }
pfd?.use { descriptor ->
val fos = FileOutputStream(descriptor.fileDescriptor)
- fos.write(content)
+ fos.write(fileDetails.fileData)
fos.close()
}
} catch (e: IOException) {
@@ -166,11 +162,18 @@ class SmartStorage(private val activity: ComponentActivity) {
private fun handleFileCreation(location: String, context: Context): File? {
return when (location) {
SmartDirectory.INTERNAL -> context.filesDir
- SmartDirectory.EXTERNAL_APP -> context.getExternalFilesDir(null)
+ SmartDirectory.EXTERNAL_PUBLIC -> Environment.getExternalStoragePublicDirectory(
+ getPackage()
+ )
+
+ SmartDirectory.SCOPED_STORAGE -> context.getExternalFilesDir(null)
else -> Environment.getExternalStoragePublicDirectory(location)
}
}
+ private fun getPackage(): String = activity.packageName.substringAfterLast('.')
+
+
}
diff --git a/smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt b/smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt
new file mode 100644
index 0000000..4c81544
--- /dev/null
+++ b/smart-storage/src/main/java/com/ss/smart_storage/model/FileDetails.kt
@@ -0,0 +1,21 @@
+package com.ss.smart_storage.model
+
+import com.ss.smart_storage.util.SmartFileType
+
+data class FileDetails(
+ val name: String,
+ val location: String,
+ val fileType: SmartFileType,
+ val fileData: ByteArray,
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+ other as FileDetails
+ return fileData.contentEquals(other.fileData)
+ }
+
+ override fun hashCode(): Int {
+ return fileData.contentHashCode()
+ }
+}
diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt
new file mode 100644
index 0000000..60b8a87
--- /dev/null
+++ b/smart-storage/src/main/java/com/ss/smart_storage/util/PermissionStatus.kt
@@ -0,0 +1,5 @@
+package com.ss.smart_storage.util
+
+enum class PermissionStatus {
+ ACCEPTED, DENIED, NOT_APPLICABLE, NOT_NEEDED, REDIRECT_TO_SETTINGS
+}
\ No newline at end of file
diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt
index 3c587cf..fd7465b 100644
--- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt
+++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartDirectory.kt
@@ -1,14 +1,10 @@
package com.ss.smart_storage.util
-
-class SmartDirectory{
- companion object {
- const val INTERNAL: String = "Internal"
- const val EXTERNAL_APP : String = "External_App"
- const val CUSTOM : String = "Custom"
- const val DOWNLOADS: String = "Download"
- const val DOCUMENTS: String = "Documents"
- }
-}
-
-
+object SmartDirectory{
+ const val INTERNAL: String = "Internal"
+ const val SCOPED_STORAGE : String = "Scoped_Storage"
+ const val CUSTOM : String = "Custom"
+ const val DOWNLOADS: String = "Download"
+ const val DOCUMENTS: String = "Documents"
+ const val EXTERNAL_PUBLIC = "External_Public"
+}
\ No newline at end of file
diff --git a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt
index 657fbbd..78a86b6 100644
--- a/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt
+++ b/smart-storage/src/main/java/com/ss/smart_storage/util/SmartFileType.kt
@@ -1,9 +1,12 @@
package com.ss.smart_storage.util
-enum class SmartFileType {
- txt,
- jpeg,
- png,
- pdf,
- webp,
-}
\ No newline at end of file
+
+enum class SmartFileType(val extension: String, val mimeType: String) {
+ TXT(extension = ".txt", mimeType = "text/plain"), JPEG(
+ extension = ".jpeg", mimeType = "image/jpeg"
+ ),
+ PNG(extension = ".png", mimeType = "image/png"), PDF(
+ extension = ".pdf", mimeType = "application/pdf"
+ ),
+ WEBP(extension = ".webp", mimeType = "image/webp"),
+}
diff --git a/smart-storage/src/main/res/values/strings.xml b/smart-storage/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0e1b6de
--- /dev/null
+++ b/smart-storage/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+ Permission Denied
+ Feature not Available
+
+
\ No newline at end of file