Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

Commit

Permalink
Add downloadPath
Browse files Browse the repository at this point in the history
  • Loading branch information
SanmerDev committed Nov 16, 2023
1 parent f678204 commit 476d776
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 71 deletions.
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="29"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"/>

<application
android:name=".App"
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/kotlin/com/sanmer/mrepo/app/Const.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.sanmer.mrepo.app

import android.os.Environment
import java.io.File

object Const {
// MODULES
// DIR
const val MODULE_PATH = "/data/adb/modules"
val PUBLIC_DOWNLOADS: File = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS
)

// URL
const val MY_GITHUB_URL = "https://github.com/SanmerDev"
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/kotlin/com/sanmer/mrepo/app/utils/MediaStoreUtils.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
package com.sanmer.mrepo.app.utils

import android.Manifest
import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import android.system.Os
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.core.net.toFile
import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.sanmer.mrepo.utils.extensions.tmpDir
import com.sanmer.mrepo.utils.extensions.toFile
import java.io.File

object MediaStoreUtils {
@Composable
fun PermissionState() {
val permissionState = rememberPermissionState(Manifest.permission.WRITE_EXTERNAL_STORAGE)

SideEffect {
if (!permissionState.status.isGranted) {
permissionState.launchPermissionRequest()
}
}
}

fun getDisplayNameForUri(context: Context, uri: Uri): String {
if (uri.scheme == "file") {
return uri.toFile().name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ class UserPreferencesDataSource @Inject constructor(
}
}

suspend fun setDownloadPath(value: String) = withContext(Dispatchers.IO) {
userPreferences.updateData {
it.new {
downloadPath = value
}
}
}

suspend fun setRepositoryMenu(value: RepositoryMenuExt) = withContext(Dispatchers.IO) {
userPreferences.updateData {
it.new {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.sanmer.mrepo.datastore

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import com.sanmer.mrepo.app.Const
import com.sanmer.mrepo.app.utils.OsUtils
import com.sanmer.mrepo.datastore.modules.ModulesMenuExt
import com.sanmer.mrepo.datastore.modules.toExt
Expand All @@ -10,6 +11,7 @@ import com.sanmer.mrepo.datastore.repository.RepositoryMenuExt
import com.sanmer.mrepo.datastore.repository.toExt
import com.sanmer.mrepo.datastore.repository.toProto
import com.sanmer.mrepo.ui.theme.Colors
import java.io.File

data class UserPreferencesExt(
val workingMode: WorkingMode,
Expand All @@ -20,6 +22,7 @@ data class UserPreferencesExt(
val themeColor: Int,
val deleteZipFile: Boolean,
val useDoh: Boolean,
val downloadPath: File,
val repositoryMenu: RepositoryMenuExt,
val modulesMenu: ModulesMenuExt
) {
Expand All @@ -30,6 +33,7 @@ data class UserPreferencesExt(
themeColor = if (OsUtils.atLeastS) Colors.Dynamic.id else Colors.Sakura.id,
deleteZipFile = false,
useDoh = false,
downloadPath = Const.PUBLIC_DOWNLOADS,
repositoryMenu = RepositoryMenuExt.default(),
modulesMenu = ModulesMenuExt.default()
)
Expand All @@ -49,6 +53,7 @@ fun UserPreferencesExt.toProto(): UserPreferences = UserPreferences.newBuilder()
.setThemeColor(themeColor)
.setDeleteZipFile(deleteZipFile)
.setUseDoh(useDoh)
.setDownloadPath(downloadPath.absolutePath)
.setRepositoryMenu(repositoryMenu.toProto())
.setModulesMenu(modulesMenu.toProto())
.build()
Expand All @@ -59,6 +64,7 @@ fun UserPreferences.toExt() = UserPreferencesExt(
themeColor = themeColor,
deleteZipFile = deleteZipFile,
useDoh = useDoh,
downloadPath = downloadPath.ifEmpty{ Const.PUBLIC_DOWNLOADS.absolutePath }.let(::File),
repositoryMenu = repositoryMenuOrNull?.toExt() ?: RepositoryMenuExt.default(),
modulesMenu = modulesMenuOrNull?.toExt() ?: ModulesMenuExt.default()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.sanmer.mrepo.datastore.repository.RepositoryMenuExt
import com.sanmer.mrepo.di.ApplicationScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject
import javax.inject.Singleton

Expand Down Expand Up @@ -38,6 +39,10 @@ class UserPreferencesRepository @Inject constructor(
userPreferencesDataSource.setUseDoh(value)
}

fun setDownloadPath(value: File) = applicationScope.launch {
userPreferencesDataSource.setDownloadPath(value.absolutePath)
}

fun setRepositoryMenu(value: RepositoryMenuExt) = applicationScope.launch {
userPreferencesDataSource.setRepositoryMenu(value)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.work.WorkManager
import com.sanmer.mrepo.app.Const
import com.sanmer.mrepo.app.isNon
import com.sanmer.mrepo.app.isSucceeded
import com.sanmer.mrepo.app.utils.MediaStoreUtils
import com.sanmer.mrepo.app.utils.NotificationUtils
import com.sanmer.mrepo.app.utils.OsUtils
import com.sanmer.mrepo.database.entity.toRepo
Expand Down Expand Up @@ -68,6 +69,7 @@ class MainActivity : ComponentActivity() {
if (OsUtils.atLeastT) {
NotificationUtils.PermissionState()
}
MediaStoreUtils.PermissionState()

LaunchedEffect(userPreferences) {
if (!isReady) return@LaunchedEffect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
Expand All @@ -54,20 +53,20 @@ import com.sanmer.mrepo.ui.component.PageIndicator
import com.sanmer.mrepo.ui.component.SearchTopBar
import com.sanmer.mrepo.ui.component.TopAppBarTitle
import com.sanmer.mrepo.ui.providable.LocalSuState
import com.sanmer.mrepo.ui.providable.LocalUserPreferences
import com.sanmer.mrepo.ui.utils.isScrollingUp
import com.sanmer.mrepo.ui.utils.navigateSingleTopTo
import com.sanmer.mrepo.ui.utils.none
import com.sanmer.mrepo.viewmodel.InstallViewModel
import com.sanmer.mrepo.viewmodel.ModulesViewModel
import kotlinx.coroutines.launch

@Composable
fun ModulesScreen(
navController: NavController,
viewModel: ModulesViewModel = hiltViewModel()
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val userPreferences = LocalUserPreferences.current
val suState = LocalSuState.current

val list by viewModel.local.collectAsStateWithLifecycle()
Expand All @@ -87,27 +86,14 @@ fun ModulesScreen(
onRefresh = { viewModel.getLocalAll() }
)

var zipFile by remember { mutableStateOf(context.cacheDir) }
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.CreateDocument("application/zip")
) { uri ->
if (uri == null) return@rememberLauncherForActivityResult

scope.launch {
viewModel.saveZipFile(context, zipFile, uri)
}
}

val download: (String, VersionItem, Boolean) -> Unit = { prefix, item, install ->
viewModel.setFilePrefix(prefix)
viewModel.downloader(context, item) {
zipFile = context.cacheDir.resolve(it)
val zipFile = userPreferences.downloadPath.resolve(it)
if (install) {
navController.navigateSingleTopTo(
InstallViewModel.putPath(zipFile)
)
} else {
launcher.launch(zipFile.nameWithoutExtension)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.sanmer.mrepo.ui.screens.repository.view

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -10,58 +8,40 @@ import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.Scaffold
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.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.sanmer.mrepo.model.online.VersionItem
import com.sanmer.mrepo.ui.component.CollapsingTopAppBarDefaults
import com.sanmer.mrepo.ui.providable.LocalUserPreferences
import com.sanmer.mrepo.ui.screens.repository.view.pages.AboutPage
import com.sanmer.mrepo.ui.screens.repository.view.pages.OverviewPage
import com.sanmer.mrepo.ui.screens.repository.view.pages.VersionsPage
import com.sanmer.mrepo.ui.utils.navigateSingleTopTo
import com.sanmer.mrepo.ui.utils.none
import com.sanmer.mrepo.viewmodel.InstallViewModel
import com.sanmer.mrepo.viewmodel.ModuleViewModel
import kotlinx.coroutines.launch

@Composable
fun ViewScreen(
navController: NavController,
viewModel: ModuleViewModel = hiltViewModel()
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val userPreferences = LocalUserPreferences.current

val scrollBehavior = CollapsingTopAppBarDefaults.scrollBehavior()
val pagerState = rememberPagerState { if (viewModel.isEmptyAbout) 2 else 3 }

var zipFile by remember { mutableStateOf(context.cacheDir) }
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.CreateDocument("application/zip")
) { uri ->
if (uri == null) return@rememberLauncherForActivityResult

scope.launch {
viewModel.saveZipFile(context, zipFile, uri)
}
}

val download: (VersionItem, Boolean) -> Unit = { item, install ->
viewModel.downloader(context, item) {
zipFile = context.cacheDir.resolve(it)
val zipFile = userPreferences.downloadPath.resolve(it)
if (install) {
navController.navigateSingleTopTo(
InstallViewModel.putPath(zipFile)
)
} else {
launcher.launch(zipFile.nameWithoutExtension)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.sanmer.mrepo.ui.component.NavigateUpTopBar
import com.sanmer.mrepo.ui.component.SettingSwitchItem
import com.sanmer.mrepo.ui.providable.LocalUserPreferences
import com.sanmer.mrepo.ui.screens.settings.app.items.AppThemeItem
import com.sanmer.mrepo.ui.screens.settings.app.items.DownloadPathItem
import com.sanmer.mrepo.ui.utils.none
import com.sanmer.mrepo.viewmodel.SettingsViewModel

Expand Down Expand Up @@ -56,6 +57,11 @@ fun AppScreen(
onDarkModeChange = viewModel::setDarkTheme
)

DownloadPathItem(
downloadPath = userPreferences.downloadPath,
onChange = viewModel::setDownloadPath
)

SettingSwitchItem(
icon = R.drawable.file_type_zip,
title = stringResource(id = R.string.settings_delete_zip),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.sanmer.mrepo.ui.screens.settings.app.items

import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
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.res.stringResource
import androidx.compose.ui.unit.dp
import com.sanmer.mrepo.R
import com.sanmer.mrepo.app.Const
import com.sanmer.mrepo.ui.component.SettingNormalItem
import com.sanmer.mrepo.ui.component.TextFieldDialog
import java.io.File

@Composable
fun DownloadPathItem(
downloadPath: File,
onChange: (File) -> Unit
) {
var edit by remember { mutableStateOf(false) }
if (edit) OpenDocumentTreeDialog(
path = downloadPath,
onClose = { edit = false },
onConfirm = { if (it != downloadPath) onChange(it) }
)

SettingNormalItem(
icon = R.drawable.files,
title = stringResource(id = R.string.settings_download_path),
desc = downloadPath.absolutePath,
onClick = { edit = true }
)
}

@Composable
private fun OpenDocumentTreeDialog(
path : File,
onClose: () -> Unit,
onConfirm: (File) -> Unit
) {
var name by remember {
mutableStateOf(path.toRelativeString(Const.PUBLIC_DOWNLOADS))
}

TextFieldDialog(
shape = RoundedCornerShape(20.dp),
onDismissRequest = onClose,
title = { Text(text = stringResource(id = R.string.settings_download_path)) },
confirmButton = {
TextButton(
onClick = {
val new = Const.PUBLIC_DOWNLOADS.resolve(name)
onConfirm(new)
onClose()
},
) {
Text(text = stringResource(id = R.string.dialog_ok))
}
},
dismissButton = {
TextButton(
onClick = onClose
) {
Text(text = stringResource(id = R.string.dialog_cancel))
}
},
launchKeyboard = false
) {
OutlinedTextField(
textStyle = MaterialTheme.typography.bodyLarge,
value = name,
onValueChange = { name = it },
shape = RoundedCornerShape(15.dp),
label = { Text(text = Const.PUBLIC_DOWNLOADS.absolutePath) },
singleLine = true
)
}
}
Loading

0 comments on commit 476d776

Please sign in to comment.