diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 56cbb60..20da5f3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,7 +1,7 @@ name: Bug Report description: File a bug report title: "[Bug]: " -labels: ["bug", "triage me"] +labels: [ "bug", "triage me" ] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 49905ce..8775570 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,7 +1,7 @@ name: Feature request description: File a feature request title: "[FR]: " -labels: ["enhancement", "triage me"] +labels: [ "enhancement", "triage me" ] body: - type: markdown attributes: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bcf259e..2897296 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,8 @@ version: 2 updates: -- package-ecosystem: gradle - directory: "/" - schedule: - interval: weekly - time: "11:00" - open-pull-requests-limit: 10 + - package-ecosystem: gradle + directory: "/" + schedule: + interval: weekly + time: "11:00" + open-pull-requests-limit: 10 diff --git a/app/src/main/kotlin/com/d4rk/cleaner/MainComposable.kt b/app/src/main/kotlin/com/d4rk/cleaner/MainComposable.kt index 7748f1f..eff5ea5 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/MainComposable.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/MainComposable.kt @@ -36,7 +36,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.compose.NavHost @@ -59,113 +58,114 @@ import kotlinx.coroutines.launch @Composable fun MainComposable() { val bottomBarItems = listOf( - Screen.Home , Screen.AppManager , Screen.MemoryManager + Screen.Home, Screen.AppManager, Screen.MemoryManager ) val drawerItems = listOf( NavigationItem( - title = R.string.whitelist , selectedIcon = Icons.AutoMirrored.Outlined.ListAlt - ) , + title = R.string.whitelist, selectedIcon = Icons.AutoMirrored.Outlined.ListAlt + ), NavigationItem( - title = R.string.image_optimizer , selectedIcon = Icons.Outlined.Image - ) , + title = R.string.image_optimizer, selectedIcon = Icons.Outlined.Image + ), NavigationItem( - title = R.string.settings , - selectedIcon = Icons.Outlined.Settings , - ) , + title = R.string.settings, + selectedIcon = Icons.Outlined.Settings, + ), NavigationItem( - title = R.string.help_and_feedback , - selectedIcon = Icons.AutoMirrored.Outlined.Help , - ) , + title = R.string.help_and_feedback, + selectedIcon = Icons.AutoMirrored.Outlined.Help, + ), NavigationItem( - title = R.string.updates , - selectedIcon = Icons.AutoMirrored.Outlined.EventNote , - ) , + title = R.string.updates, + selectedIcon = Icons.AutoMirrored.Outlined.EventNote, + ), NavigationItem( - title = R.string.share , selectedIcon = Icons.Outlined.Share - ) , + title = R.string.share, selectedIcon = Icons.Outlined.Share + ), ) val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val scope = rememberCoroutineScope() val navController = rememberNavController() val context = LocalContext.current - val selectedItemIndex by rememberSaveable { mutableIntStateOf(- 1) } - ModalNavigationDrawer(drawerState = drawerState , drawerContent = { + val selectedItemIndex by rememberSaveable { mutableIntStateOf(-1) } + ModalNavigationDrawer(drawerState = drawerState, drawerContent = { ModalDrawerSheet { Spacer(modifier = Modifier.height(16.dp)) - drawerItems.forEachIndexed { index , item -> + drawerItems.forEachIndexed { index, item -> val title = stringResource(item.title) - NavigationDrawerItem(label = { Text(text = title) } , - selected = index == selectedItemIndex , - onClick = { - when (item.title) { - R.string.whitelist -> { - Utils.openActivity( - context , WhitelistActivity::class.java - ) - } + NavigationDrawerItem( + label = { Text(text = title) }, + selected = index == selectedItemIndex, + onClick = { + when (item.title) { + R.string.whitelist -> { + Utils.openActivity( + context, WhitelistActivity::class.java + ) + } - R.string.image_optimizer -> { - Utils.openActivity( - context , ImagePickerActivity::class.java - ) - } + R.string.image_optimizer -> { + Utils.openActivity( + context, ImagePickerActivity::class.java + ) + } - R.string.settings -> { - Utils.openActivity( - context , SettingsActivity::class.java - ) - } + R.string.settings -> { + Utils.openActivity( + context, SettingsActivity::class.java + ) + } - R.string.help_and_feedback -> { - Utils.openActivity( - context , HelpActivity::class.java - ) - } + R.string.help_and_feedback -> { + Utils.openActivity( + context, HelpActivity::class.java + ) + } - R.string.updates -> { - Utils.openUrl( - context , - "https://github.com/D4rK7355608/${context.packageName}/blob/master/CHANGELOG.md" - ) - } + R.string.updates -> { + Utils.openUrl( + context, + "https://github.com/D4rK7355608/${context.packageName}/blob/master/CHANGELOG.md" + ) + } - R.string.share -> { - val shareIntent = Intent().apply { - this.action = Intent.ACTION_SEND - this.putExtra( - Intent.EXTRA_TEXT , context.getString( - R.string.summary_share_message , - "https://play.google.com/store/apps/details?id=${context.packageName}" - ) - ) - this.type = "text/plain" - } - context.startActivity( - Intent.createChooser( - shareIntent , context.resources.getText( - R.string.send_email_using - ) - ) - ) - } - } - scope.launch { - drawerState.close() - } - } , - icon = { - Icon( - item.selectedIcon , contentDescription = title - ) - } , - badge = { - item.badgeCount?.let { - Text(text = item.badgeCount.toString()) - } - } , - modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) + R.string.share -> { + val shareIntent = Intent().apply { + this.action = Intent.ACTION_SEND + this.putExtra( + Intent.EXTRA_TEXT, context.getString( + R.string.summary_share_message, + "https://play.google.com/store/apps/details?id=${context.packageName}" + ) + ) + this.type = "text/plain" + } + context.startActivity( + Intent.createChooser( + shareIntent, context.resources.getText( + R.string.send_email_using + ) + ) + ) + } + } + scope.launch { + drawerState.close() + } + }, + icon = { + Icon( + item.selectedIcon, contentDescription = title + ) + }, + badge = { + item.badgeCount?.let { + Text(text = item.badgeCount.toString()) + } + }, + modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding) ) if (item.title == R.string.image_optimizer) { HorizontalDivider(modifier = Modifier.padding(8.dp)) @@ -173,11 +173,11 @@ fun MainComposable() { } } - } , content = { + }, content = { Scaffold(topBar = { TopAppBar(title = { Text(text = stringResource(R.string.app_name)) - } , navigationIcon = { + }, navigationIcon = { IconButton(onClick = { scope.launch { drawerState.apply { @@ -186,41 +186,41 @@ fun MainComposable() { } }) { Icon( - imageVector = Icons.Default.Menu , contentDescription = "Menu" + imageVector = Icons.Default.Menu, contentDescription = "Menu" ) } - } , actions = { + }, actions = { IconButton(onClick = { - Utils.openActivity(context , SupportActivity::class.java) + Utils.openActivity(context, SupportActivity::class.java) }) { Icon( - Icons.Outlined.VolunteerActivism , + Icons.Outlined.VolunteerActivism, contentDescription = "Support" ) } }) - } , bottomBar = { + }, bottomBar = { NavigationBar { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route bottomBarItems.forEach { screen -> NavigationBarItem(icon = { val iconResource = - if (currentRoute == screen.route) screen.selectedIcon else screen.icon - Icon(iconResource , contentDescription = null) - } , - label = { Text(stringResource(screen.title)) } , - selected = currentRoute == screen.route , - onClick = { - navController.navigate(screen.route) { - popUpTo(navController.graph.startDestinationId) - launchSingleTop = true - } - }) + if (currentRoute == screen.route) screen.selectedIcon else screen.icon + Icon(iconResource, contentDescription = null) + }, + label = { Text(stringResource(screen.title)) }, + selected = currentRoute == screen.route, + onClick = { + navController.navigate(screen.route) { + popUpTo(navController.graph.startDestinationId) + launchSingleTop = true + } + }) } } }) { innerPadding -> - NavHost(navController , startDestination = Screen.Home.route) { + NavHost(navController, startDestination = Screen.Home.route) { composable(Screen.Home.route) { Box(modifier = Modifier.padding(innerPadding)) { HomeComposable() diff --git a/app/src/main/kotlin/com/d4rk/cleaner/adapters/CpuAdapter.kt b/app/src/main/kotlin/com/d4rk/cleaner/adapters/CpuAdapter.kt deleted file mode 100644 index e4e81e8..0000000 --- a/app/src/main/kotlin/com/d4rk/cleaner/adapters/CpuAdapter.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.d4rk.cleaner.adapters - -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.RecyclerView -import com.d4rk.cleaner.data.CpuApp -import com.d4rk.cleaner.data.CpuAppDiffCallback -import com.d4rk.cleaner.databinding.ItemCpuListBinding - -class CpuAdapter(private var apps: List) : - RecyclerView.Adapter() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CpuViewHolder { - val inflater = LayoutInflater.from(parent.context) - val binding = ItemCpuListBinding.inflate(inflater, parent, false) - return CpuViewHolder(binding) - } - - override fun onBindViewHolder(holder: CpuViewHolder, position: Int) { - val app = apps[position] - holder.bind(app) - } - - override fun getItemCount(): Int { - return apps.size - } - - fun updateAppsList(newApps: List) { - val diffCallback = CpuAppDiffCallback(apps, newApps) - val diffResult = DiffUtil.calculateDiff(diffCallback) - apps = newApps - diffResult.dispatchUpdatesTo(this) - } - - inner class CpuViewHolder(private val binding: ItemCpuListBinding) : - RecyclerView.ViewHolder(binding.root) { - fun bind(app: CpuApp) { - binding.appIcon.setImageDrawable(app.icon) - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/NavigationItem.kt b/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/NavigationItem.kt index b643232..db40040 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/NavigationItem.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/NavigationItem.kt @@ -3,5 +3,5 @@ package com.d4rk.cleaner.data.navigation import androidx.compose.ui.graphics.vector.ImageVector data class NavigationItem( - val title : Int , val selectedIcon : ImageVector , val badgeCount : Int? = null + val title: Int, val selectedIcon: ImageVector, val badgeCount: Int? = null ) \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/Screen.kt b/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/Screen.kt index ed36317..4771f6a 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/Screen.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/data/navigation/Screen.kt @@ -11,18 +11,18 @@ import androidx.compose.ui.graphics.vector.ImageVector import com.d4rk.cleaner.R sealed class Screen( - val route : String , val icon : ImageVector , val selectedIcon : ImageVector , val title : Int + val route: String, val icon: ImageVector, val selectedIcon: ImageVector, val title: Int ) { - data object Home : Screen("Home" , Icons.Outlined.Home , Icons.Filled.Home , R.string.home) + data object Home : Screen("Home", Icons.Outlined.Home, Icons.Filled.Home, R.string.home) data object AppManager : Screen( - "App Manager" , - Icons.Sharp.AppRegistration , - Icons.Rounded.AppRegistration , + "App Manager", + Icons.Sharp.AppRegistration, + Icons.Rounded.AppRegistration, R.string.app_manager ) data object MemoryManager : Screen( - "Memory Manager" , Icons.Sharp.Storage , Icons.Rounded.Storage , R.string.memory_manager + "Memory Manager", Icons.Sharp.Storage, Icons.Rounded.Storage, R.string.memory_manager ) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/dialogs/RequireRestartDialog.kt b/app/src/main/kotlin/com/d4rk/cleaner/dialogs/RequireRestartDialog.kt index 9fe6bf2..a45a46c 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/dialogs/RequireRestartDialog.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/dialogs/RequireRestartDialog.kt @@ -27,4 +27,4 @@ class RequireRestartDialog : DialogFragment() { Process.killProcess(Process.myPid()) }.setNegativeButton(android.R.string.cancel, null).show() } -} +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/help/HelpComposable.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/help/HelpComposable.kt index 2393841..d46f184 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/help/HelpComposable.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/help/HelpComposable.kt @@ -150,7 +150,7 @@ fun HelpComposable(activity: HelpActivity) { }, modifier = Modifier .padding(6.dp) - .bounceClick() + .bounceClick() .constrainAs(fabButton) { bottom.linkTo(parent.bottom) end.linkTo(parent.end) diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/home/HomeComposable.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/home/HomeComposable.kt index 1d04449..729f2dc 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/home/HomeComposable.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/home/HomeComposable.kt @@ -60,7 +60,7 @@ import java.io.File @Composable fun HomeComposable() { val context = LocalContext.current - val viewModel : HomeViewModel = viewModel() + val viewModel: HomeViewModel = viewModel() val progress by viewModel.progress.observeAsState(0.3f) val storageUsed by viewModel.storageUsed.observeAsState("0") val storageTotal by viewModel.storageTotal.observeAsState("0") @@ -70,72 +70,71 @@ fun HomeComposable() { ) { Box( modifier = Modifier - .weight(4f) - .fillMaxWidth() + .weight(4f) + .fillMaxWidth() ) { - if (! showCleaningComposable.value) { + if (!showCleaningComposable.value) { CircularDeterminateIndicator( - progress = progress , - storageUsed = storageUsed , - storageTotal = storageTotal , + progress = progress, + storageUsed = storageUsed, + storageTotal = storageTotal, modifier = Modifier - .align(Alignment.TopCenter) - .offset(y = 98.dp) + .align(Alignment.TopCenter) + .offset(y = 98.dp) ) Image( - painter = painterResource(R.drawable.ic_clean) , - contentDescription = null , + painter = painterResource(R.drawable.ic_clean), + contentDescription = null, modifier = Modifier - .align(Alignment.BottomCenter) - .padding(24.dp) - .size(128.dp , 66.dp) + .align(Alignment.BottomCenter) + .padding(24.dp) + .size(128.dp, 66.dp) ) - } - else { + } else { AnalyzeComposable() } } Row( modifier = Modifier - .fillMaxWidth() - .height(102.dp) - .padding(bottom = 16.dp) , + .fillMaxWidth() + .height(102.dp) + .padding(bottom = 16.dp), horizontalArrangement = Arrangement.SpaceEvenly ) { FilledTonalButton( modifier = Modifier - .weight(1f) - .fillMaxHeight() - .padding(start = 16.dp , end = 8.dp) - .bounceClick(), + .weight(1f) + .fillMaxHeight() + .padding(start = 16.dp, end = 8.dp) + .bounceClick(), onClick = { Utils.openActivity( - context , StartupActivity::class.java + context, StartupActivity::class.java ) }, shape = MaterialTheme.shapes.medium ) { Column( - horizontalAlignment = Alignment.CenterHorizontally , - verticalArrangement = Arrangement.Center , + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, modifier = Modifier - .fillMaxSize() - .padding(ButtonDefaults.ContentPadding) + .fillMaxSize() + .padding(ButtonDefaults.ContentPadding) ) { Icon( - painterResource(R.drawable.ic_broom) , - contentDescription = null , + painterResource(R.drawable.ic_broom), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) - Text(text = "Clean" , style = MaterialTheme.typography.bodyMedium) + Text(text = "Clean", style = MaterialTheme.typography.bodyMedium) } } FilledTonalButton( modifier = Modifier - .weight(1f) - .fillMaxHeight() - .padding(start = 8.dp , end = 16.dp) - .bounceClick(), + .weight(1f) + .fillMaxHeight() + .padding(start = 8.dp, end = 16.dp) + .bounceClick(), onClick = { viewModel.analyze() showCleaningComposable.value = true @@ -143,18 +142,18 @@ fun HomeComposable() { shape = MaterialTheme.shapes.medium ) { Column( - horizontalAlignment = Alignment.CenterHorizontally , - verticalArrangement = Arrangement.Center , + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, modifier = Modifier - .fillMaxSize() - .padding(ButtonDefaults.ContentPadding) + .fillMaxSize() + .padding(ButtonDefaults.ContentPadding) ) { Icon( - painterResource(R.drawable.ic_search) , - contentDescription = null , + painterResource(R.drawable.ic_search), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) - Text(text = "Analyze" , style = MaterialTheme.typography.bodyMedium) + Text(text = "Analyze", style = MaterialTheme.typography.bodyMedium) } } } @@ -174,35 +173,35 @@ fun HomeComposable() { */ @Composable fun CircularDeterminateIndicator( - progress : Float , storageUsed : String , storageTotal : String , modifier : Modifier = Modifier + progress: Float, storageUsed: String, storageTotal: String, modifier: Modifier = Modifier ) { val animatedProgress by animateFloatAsState( - targetValue = progress , - animationSpec = tween(durationMillis = 1000 , easing = LinearOutSlowInEasing) , + targetValue = progress, + animationSpec = tween(durationMillis = 1000, easing = LinearOutSlowInEasing), label = "" ) Box( - contentAlignment = Alignment.Center , modifier = modifier.size(240.dp) + contentAlignment = Alignment.Center, modifier = modifier.size(240.dp) ) { CircularProgressIndicator( - progress = { 1f } , - modifier = Modifier.fillMaxSize() , - color = MaterialTheme.colorScheme.primaryContainer , - strokeWidth = 6.dp , + progress = { 1f }, + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.primaryContainer, + strokeWidth = 6.dp, ) CircularProgressIndicator( - progress = { animatedProgress } , + progress = { animatedProgress }, modifier = Modifier - .animateContentSize() - .fillMaxSize() , - color = MaterialTheme.colorScheme.primary , - strokeWidth = 6.dp , - strokeCap = StrokeCap.Round , + .animateContentSize() + .fillMaxSize(), + color = MaterialTheme.colorScheme.primary, + strokeWidth = 6.dp, + strokeCap = StrokeCap.Round, ) Text( - text = "$storageUsed/$storageTotal GB \n Used" , - textAlign = TextAlign.Center , + text = "$storageUsed/$storageTotal GB \n Used", + textAlign = TextAlign.Center, style = MaterialTheme.typography.titleLarge ) } @@ -218,7 +217,7 @@ fun CircularDeterminateIndicator( */ @Composable fun AnalyzeComposable() { - val viewModel : HomeViewModel = viewModel() + val viewModel: HomeViewModel = viewModel() val files by viewModel.scannedFiles.asFlow().collectAsState(initial = listOf()) val allFilesSelected by viewModel.allFilesSelected @@ -228,45 +227,45 @@ fun AnalyzeComposable() { Column( modifier = Modifier - .animateContentSize() - .fillMaxWidth() - .padding(16.dp) , + .animateContentSize() + .fillMaxWidth() + .padding(16.dp), horizontalAlignment = Alignment.End ) { OutlinedCard( modifier = Modifier - .weight(1f) - .fillMaxWidth() , + .weight(1f) + .fillMaxWidth(), ) { Column { LazyColumn( modifier = Modifier - .fillMaxWidth() - .padding(16.dp) + .fillMaxWidth() + .padding(16.dp) ) { items(files) { file -> FileItemComposable( - file = file , - item = file.name , - context = LocalContext.current , - viewModel = viewModel , + file = file, + item = file.name, + context = LocalContext.current, + viewModel = viewModel, ) } } } } Row( - modifier = Modifier.fillMaxWidth() , - verticalAlignment = Alignment.CenterVertically , - horizontalArrangement = Arrangement.SpaceBetween , + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( - text = "Status" , - color = MaterialTheme.colorScheme.primary , + text = "Status", + color = MaterialTheme.colorScheme.primary, ) SelectAllComposable( - checked = allFilesSelected , - onCheckedChange = { viewModel.selectAllFiles(it) } , + checked = allFilesSelected, + onCheckedChange = { viewModel.selectAllFiles(it) }, ) } } @@ -283,34 +282,34 @@ fun AnalyzeComposable() { */ @Composable fun SelectAllComposable( - checked : Boolean , onCheckedChange : (Boolean) -> Unit + checked: Boolean, onCheckedChange: (Boolean) -> Unit ) { Row( modifier = Modifier - .fillMaxWidth() - .animateContentSize() , - verticalAlignment = Alignment.CenterVertically , + .fillMaxWidth() + .animateContentSize(), + verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { val interactionSource = remember { MutableInteractionSource() } FilterChip( modifier = Modifier.bounceClick(), - selected = checked , + selected = checked, onClick = { - onCheckedChange(! checked) - } , - label = { Text("Select All") } , + onCheckedChange(!checked) + }, + label = { Text("Select All") }, leadingIcon = { - AnimatedContent(targetState = checked , label = "") { targetChecked -> + AnimatedContent(targetState = checked, label = "") { targetChecked -> if (targetChecked) { Icon( - imageVector = Icons.Filled.Check , - contentDescription = null , + imageVector = Icons.Filled.Check, + contentDescription = null, ) } } - } , - interactionSource = interactionSource , + }, + interactionSource = interactionSource, ) } } @@ -328,11 +327,11 @@ fun SelectAllComposable( * @param context The Android `Context` used to access resources like file extensions and corresponding icons. */ -val fileIconMap = mutableMapOf() +val fileIconMap = mutableMapOf() @Composable fun FileItemComposable( - file : File , item : String = "" , viewModel : HomeViewModel , context : Context + file: File, item: String = "", viewModel: HomeViewModel, context: Context ) { context.resources.getStringArray(R.array.apk_extensions).forEach { fileIconMap[it] = R.drawable.ic_apk_document @@ -357,25 +356,25 @@ fun FileItemComposable( val iconResource = fileIconMap[fileExtension] ?: R.drawable.ic_file_present Row( - modifier = Modifier.fillMaxWidth() , horizontalArrangement = Arrangement.Center + modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center ) { Icon( - painter = painterResource(iconResource) , - contentDescription = null , + painter = painterResource(iconResource), + contentDescription = null, modifier = Modifier.align(Alignment.CenterVertically) ) Spacer(modifier = Modifier.width(4.dp)) Text( - text = item , modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically) + text = item, modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically) ) Spacer(modifier = Modifier.width(4.dp)) Checkbox( - checked = viewModel.fileSelectionStates[file] ?: false , + checked = viewModel.fileSelectionStates[file] ?: false, onCheckedChange = { isChecked -> viewModel.fileSelectionStates[file] = isChecked - } , + }, modifier = Modifier.align(Alignment.CenterVertically) ) } diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/memory/MemoryFragment.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/memory/MemoryFragment.kt index c9f9185..cfa3e89 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/memory/MemoryFragment.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/memory/MemoryFragment.kt @@ -3,37 +3,37 @@ package com.d4rk.cleaner.ui.memory import androidx.fragment.app.Fragment class MemoryFragment : Fragment() { -/* private lateinit var binding: FragmentMemoryBinding - private lateinit var viewModel: MemoryViewModel - private var updateMemoryJob: Job? = null - private val handler = Handler(Looper.getMainLooper()) - private val updateInterval = 1000L - private lateinit var cpuAdapter: CpuAdapter - private val cpuAppsList = mutableListOf() - private val navController: NavController by lazy { - findNavController() - } + /* private lateinit var binding: FragmentMemoryBinding + private lateinit var viewModel: MemoryViewModel + private var updateMemoryJob: Job? = null + private val handler = Handler(Looper.getMainLooper()) + private val updateInterval = 1000L + private lateinit var cpuAdapter: CpuAdapter + private val cpuAppsList = mutableListOf() + private val navController: NavController by lazy { + findNavController() + } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - binding = FragmentMemoryBinding.inflate(inflater, container, false) - cpuAdapter = CpuAdapter(cpuAppsList) - CoroutineScope(Dispatchers.Main).launch { - updateMemoryInfo() + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentMemoryBinding.inflate(inflater, container, false) + cpuAdapter = CpuAdapter(cpuAppsList) + CoroutineScope(Dispatchers.Main).launch { + updateMemoryInfo() + } + return binding.root } - return binding.root - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - setAnimations() - FastScrollerBuilder(binding.scrollView).useMd2Style().build() - MobileAds.initialize(requireContext()) - binding.adBannerView.loadAd(AdRequest.Builder().build()) - *//* binding.buttonAnalyze.setOnClickListener { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setAnimations() + FastScrollerBuilder(binding.scrollView).useMd2Style().build() + MobileAds.initialize(requireContext()) + binding.adBannerView.loadAd(AdRequest.Builder().build()) + *//* binding.buttonAnalyze.setOnClickListener { navController.navigate(R.id.navigation_home) }*//* } diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt index 13bb2d7..1e1ed15 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/startup/StartupComposable.kt @@ -79,8 +79,8 @@ fun StartupComposable() { } } ExtendedFloatingActionButton(modifier = Modifier - .align(Alignment.BottomEnd) - .bounceClick(), + .align(Alignment.BottomEnd) + .bounceClick(), text = { Text(stringResource(R.string.agree)) }, onClick = { Utils.openActivity( diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/support/SupportComposable.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/support/SupportComposable.kt index 8235de2..9817e2d 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/support/SupportComposable.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/support/SupportComposable.kt @@ -50,67 +50,67 @@ import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SupportComposable(activity : SupportActivity) { +fun SupportComposable(activity: SupportActivity) { val context = LocalContext.current val coroutineScope = rememberCoroutineScope() - val skuDetailsMap = remember { mutableStateMapOf() } - val billingClient = rememberBillingClient(context , coroutineScope , activity , skuDetailsMap) + val skuDetailsMap = remember { mutableStateMapOf() } + val billingClient = rememberBillingClient(context, coroutineScope, activity, skuDetailsMap) val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) - Scaffold(modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) , topBar = { - LargeTopAppBar(title = { Text(stringResource(R.string.support_us)) } , navigationIcon = { + Scaffold(modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { + LargeTopAppBar(title = { Text(stringResource(R.string.support_us)) }, navigationIcon = { IconButton(onClick = { activity.finish() }) { Icon( - Icons.AutoMirrored.Filled.ArrowBack , contentDescription = null + Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null ) } - } , scrollBehavior = scrollBehavior + }, scrollBehavior = scrollBehavior ) }) { paddingValues -> LazyColumn( modifier = Modifier - .fillMaxHeight() - .padding(paddingValues) , + .fillMaxHeight() + .padding(paddingValues), ) { item { Text( - text = stringResource(R.string.paid_support) , - modifier = Modifier.padding(start = 16.dp , top = 16.dp) , - style = MaterialTheme.typography.titleLarge , + text = stringResource(R.string.paid_support), + modifier = Modifier.padding(start = 16.dp, top = 16.dp), + style = MaterialTheme.typography.titleLarge, ) } item { OutlinedCard( modifier = Modifier - .fillMaxWidth() - .padding(16.dp) + .fillMaxWidth() + .padding(16.dp) ) { Column { Text( - text = stringResource(R.string.summary_donations) , + text = stringResource(R.string.summary_donations), modifier = Modifier.padding(16.dp) ) LazyRow( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) , + .fillMaxWidth() + .padding(horizontal = 16.dp), horizontalArrangement = Arrangement.SpaceEvenly ) { item { FilledTonalButton( modifier = Modifier - .fillMaxWidth() - .bounceClick() , + .fillMaxWidth() + .bounceClick(), onClick = { activity.initiatePurchase( - "low_donation" , skuDetailsMap , billingClient + "low_donation", skuDetailsMap, billingClient ) - } , + }, ) { Icon( - painterResource(R.drawable.ic_paid) , - contentDescription = null , + painterResource(R.drawable.ic_paid), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) @@ -120,17 +120,17 @@ fun SupportComposable(activity : SupportActivity) { item { FilledTonalButton( modifier = Modifier - .fillMaxWidth() - .bounceClick() , + .fillMaxWidth() + .bounceClick(), onClick = { activity.initiatePurchase( - "normal_donation" , skuDetailsMap , billingClient + "normal_donation", skuDetailsMap, billingClient ) - } , + }, ) { Icon( - painterResource(R.drawable.ic_paid) , - contentDescription = null , + painterResource(R.drawable.ic_paid), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) @@ -140,24 +140,24 @@ fun SupportComposable(activity : SupportActivity) { } LazyRow( modifier = Modifier - .fillMaxWidth() - .padding(16.dp) , + .fillMaxWidth() + .padding(16.dp), horizontalArrangement = Arrangement.SpaceEvenly ) { item { FilledTonalButton( modifier = Modifier - .fillMaxWidth() - .bounceClick() , + .fillMaxWidth() + .bounceClick(), onClick = { activity.initiatePurchase( - "high_donation" , skuDetailsMap , billingClient + "high_donation", skuDetailsMap, billingClient ) - } , + }, ) { Icon( - painterResource(R.drawable.ic_paid) , - contentDescription = null , + painterResource(R.drawable.ic_paid), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) @@ -168,17 +168,17 @@ fun SupportComposable(activity : SupportActivity) { FilledTonalButton( modifier = Modifier - .fillMaxWidth() - .bounceClick() , + .fillMaxWidth() + .bounceClick(), onClick = { activity.initiatePurchase( - "extreme_donation" , skuDetailsMap , billingClient + "extreme_donation", skuDetailsMap, billingClient ) - } , + }, ) { Icon( - painterResource(R.drawable.ic_paid) , - contentDescription = null , + painterResource(R.drawable.ic_paid), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) @@ -191,24 +191,24 @@ fun SupportComposable(activity : SupportActivity) { } item { Text( - text = stringResource(R.string.non_paid_support) , - modifier = Modifier.padding(start = 16.dp) , - style = MaterialTheme.typography.titleLarge , + text = stringResource(R.string.non_paid_support), + modifier = Modifier.padding(start = 16.dp), + style = MaterialTheme.typography.titleLarge, ) } item { FilledTonalButton( onClick = { - Utils.openUrl(context , "https://bit.ly/3p8bpj") - } , + Utils.openUrl(context, "https://bit.ly/3p8bpj") + }, modifier = Modifier - .fillMaxWidth() - .bounceClick() - .padding(16.dp) , + .fillMaxWidth() + .bounceClick() + .padding(16.dp), ) { Icon( - painterResource(R.drawable.ic_paid) , - contentDescription = null , + painterResource(R.drawable.ic_paid), + contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize) ) Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing)) @@ -222,20 +222,20 @@ fun SupportComposable(activity : SupportActivity) { @Composable fun rememberBillingClient( - context : Context , - coroutineScope : CoroutineScope , - activity : SupportActivity , - skuDetailsMap : SnapshotStateMap -) : BillingClient { + context: Context, + coroutineScope: CoroutineScope, + activity: SupportActivity, + skuDetailsMap: SnapshotStateMap +): BillingClient { val billingClient = remember { - BillingClient.newBuilder(context).setListener { _ , _ -> }.enablePendingPurchases().build() + BillingClient.newBuilder(context).setListener { _, _ -> }.enablePendingPurchases().build() } DisposableEffect(billingClient) { billingClient.startConnection(object : BillingClientStateListener { - override fun onBillingSetupFinished(billingResult : BillingResult) { + override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) { coroutineScope.launch { - activity.querySkuDetails(billingClient , skuDetailsMap) + activity.querySkuDetails(billingClient, skuDetailsMap) } } } diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/viewmodel/MemoryViewModel.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/viewmodel/MemoryViewModel.kt deleted file mode 100644 index 4fcad39..0000000 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/viewmodel/MemoryViewModel.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.d4rk.cleaner.ui.viewmodel - -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancelChildren -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.io.BufferedReader -import java.io.InputStreamReader - -class MemoryViewModel : ViewModel() { - private val cpuTemperatureLiveData = MutableLiveData() - private val viewModelJob = SupervisorJob() - private val viewModelScope = CoroutineScope(Dispatchers.Main + viewModelJob) - private val updateInterval = 1000L - - init { - startCpuTemperatureUpdates() - } - - fun startCpuTemperatureUpdates() { - viewModelScope.launch { - while (isActive) { - val temperature = calculateCpuTemperature() - cpuTemperatureLiveData.postValue(temperature) - delay(updateInterval) - } - } - } - - fun stopCpuTemperatureUpdates() { - viewModelJob.cancelChildren() - } - - fun getCpuTemperature(): Double { - return cpuTemperatureLiveData.value ?: 0.0 - } - - private suspend fun calculateCpuTemperature(): Double? = withContext(Dispatchers.IO) { - var temperature: Double? = null - try { - val process = Runtime.getRuntime().exec("cat /sys/class/thermal/thermal_zone0/temp") - val reader = BufferedReader(InputStreamReader(process.inputStream)) - val tempStr = reader.readLine() - reader.close() - process.waitFor() - if (!tempStr.isNullOrEmpty()) { - val tempMilliCelsius = tempStr.toIntOrNull() - if (tempMilliCelsius != null) { - temperature = tempMilliCelsius / 1000.0 - } - } - } catch (e: Exception) { - e.printStackTrace() - } - return@withContext temperature - } - - override fun onCleared() { - super.onCleared() - viewModelJob.cancel() - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/ui/whitelist/WhitelistActivity.kt b/app/src/main/kotlin/com/d4rk/cleaner/ui/whitelist/WhitelistActivity.kt index ec0f8ce..45fbbdd 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/ui/whitelist/WhitelistActivity.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/ui/whitelist/WhitelistActivity.kt @@ -1,14 +1,26 @@ package com.d4rk.cleaner.ui.whitelist import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity -import com.d4rk.cleaner.databinding.ActivityWhitelistBinding +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.ui.Modifier +import com.d4rk.cleaner.ui.settings.display.theme.AppTheme class WhitelistActivity : AppCompatActivity() { - private lateinit var binding: ActivityWhitelistBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding = ActivityWhitelistBinding.inflate(layoutInflater) - setContentView(binding.root) + enableEdgeToEdge() + setContent { + AppTheme { + Surface( + modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background + ) { + } + } + } } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/utils/ComposablesUtils.kt b/app/src/main/kotlin/com/d4rk/cleaner/utils/ComposablesUtils.kt index e5086b1..3aa4dfa 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/utils/ComposablesUtils.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/utils/ComposablesUtils.kt @@ -42,49 +42,47 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp /** - * Creates a clickable card with a title and a switch within your app's preferences. + * Creates a clickable card with a title and a switch for app preference screens. * - * This composable is useful for displaying settings or preferences that can be toggled on or off. - * When clicked, the card toggles the switch and calls the provided callback function. + * This composable function displays a card with a title and a switch. The entire card is clickable and toggles the switch when clicked, calling the provided `onSwitchToggled` callback function with the new state. + * The switch displays a check icon when it's in the 'on' state. * * @param title The text displayed on the card's title. - * @param switchState A state variable holding the current on/off state of the switch (true for on). - * @param onSwitchToggled A callback function called whenever the switch is toggled. - * This function receives the new state of the switch (boolean) as a parameter. + * @param switchState A state variable holding the current on/off state of the switch. Set to true for on and false for off. + * @param onSwitchToggled A callback function that is called whenever the switch is toggled. This function receives the new state of the switch (boolean) as a parameter. */ @Composable fun SwitchCardComposable( - title : String , switchState : State , onSwitchToggled : (Boolean) -> Unit + title: String, switchState: State, onSwitchToggled: (Boolean) -> Unit ) { Card(modifier = Modifier - .fillMaxWidth() - .padding(24.dp) - .clip(RoundedCornerShape(28.dp)) - .clickable { - onSwitchToggled(! switchState.value) - }) { + .fillMaxWidth() + .padding(24.dp) + .clip(RoundedCornerShape(28.dp)) + .clickable { + onSwitchToggled(!switchState.value) + }) { Row( modifier = Modifier - .fillMaxWidth() - .padding(16.dp) , - horizontalArrangement = Arrangement.SpaceBetween , + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text(text = title) - Switch(checked = switchState.value , - onCheckedChange = onSwitchToggled , - thumbContent = if (switchState.value) { - { - Icon( - Icons.Filled.Check , - contentDescription = null , - modifier = Modifier.size(SwitchDefaults.IconSize) , - ) - } - } - else { - null - }) + Switch(checked = switchState.value, + onCheckedChange = onSwitchToggled, + thumbContent = if (switchState.value) { + { + Icon( + Icons.Filled.Check, + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } + } else { + null + }) } } } @@ -92,61 +90,58 @@ fun SwitchCardComposable( /** * Displays a category header within your app's preference screens. * - * Use this composable within a scrollable container to separate different sections of - * your app's preferences with clear category titles. + * This composable function is used to display a category header in your app's preference screens. It helps in separating different sections of your app's preferences with clear category titles. The title is displayed in a distinct style and color to differentiate it from other preference items. * - * @param title The text to be displayed as the category header. + * @param title The text to be displayed as the category header. This is typically the name of the category. */ @Composable fun PreferenceCategoryItem( - title : String + title: String ) { Text( - text = title , - color = MaterialTheme.colorScheme.primary , - style = MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.SemiBold) , - modifier = Modifier.padding(start = 16.dp , top = 16.dp) + text = title, + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.SemiBold), + modifier = Modifier.padding(start = 16.dp, top = 16.dp) ) } /** * Creates a clickable preference item for app preference screens. * - * This composable displays a preference item with an optional icon, title, and summary. - * Clicking the entire row triggers the provided `onClick` callback function. + * This composable function displays a preference item with an optional icon, title, and summary. The entire row is clickable and triggers the provided `onClick` callback function when clicked. * - * @param icon An optional icon to be displayed at the beginning of the preference item. (Provide a `Painter` object) - * @param title The main title text displayed for the preference item. - * @param summary An optional secondary text displayed below the title for additional information. - * @param onClick A callback function that is called when the entire preference item is clicked. - * Leave this empty if no action is needed on click. + * @param icon An optional icon to be displayed at the start of the preference item. If provided, it should be an `ImageVector` object. + * @param title An optional main title text displayed for the preference item. + * @param summary An optional secondary text displayed below the title for additional information about the preference. + * @param onClick A callback function that is called when the entire preference item is clicked. If no action is needed on click, this can be left empty. */ @Composable fun PreferenceItem( - icon : ImageVector? = null , - title : String? = null , - summary : String? = null , - onClick : () -> Unit = {} + icon: ImageVector? = null, + title: String? = null, + summary: String? = null, + onClick: () -> Unit = {} ) { Row( modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .clickable(onClick = onClick) , verticalAlignment = Alignment.CenterVertically + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .clickable(onClick = onClick), verticalAlignment = Alignment.CenterVertically ) { icon?.let { Spacer(modifier = Modifier.width(16.dp)) - Icon(it , contentDescription = null) + Icon(it, contentDescription = null) Spacer(modifier = Modifier.width(16.dp)) } Column( modifier = Modifier.padding(16.dp) ) { title?.let { - Text(text = it , style = MaterialTheme.typography.titleLarge) + Text(text = it, style = MaterialTheme.typography.titleLarge) } summary?.let { - Text(text = it , style = MaterialTheme.typography.bodyMedium) + Text(text = it, style = MaterialTheme.typography.bodyMedium) } } } @@ -155,49 +150,48 @@ fun PreferenceItem( /** * Creates a clickable preference item with a switch for app preference screens. * - * This composable combines an icon (optional), title, summary (optional), and a switch. Clicking - * the entire row toggles the switch and calls the provided `onCheckedChange` callback function. + * This composable function combines an optional icon, title, optional summary, and a switch into a single row. + * The entire row is clickable and toggles the switch when clicked, calling the provided `onCheckedChange` callback function with the new state. * - * @param icon An optional icon to be displayed at the beginning of the preference item. (Provide a `Painter` object) + * @param icon An optional icon to be displayed at the start of the preference item. If provided, it should be an `ImageVector` object. * @param title The main title text displayed for the preference item. - * @param summary An optional secondary text displayed below the title for additional information. - * @param checked The initial state of the switch (true for on, false for off). - * @param onCheckedChange A callback function called whenever the switch is toggled. - * This function receives the new state of the switch (boolean) as a parameter. + * @param summary An optional secondary text displayed below the title for additional information about the preference. + * @param checked The initial state of the switch. Set to true for on and false for off. + * @param onCheckedChange A callback function that is called whenever the switch is toggled. This function receives the new state of the switch (boolean) as a parameter. */ @Composable fun SwitchPreferenceItem( - icon : ImageVector? = null , - title : String , - summary : String? = null , - checked : Boolean , - onCheckedChange : (Boolean) -> Unit + icon: ImageVector? = null, + title: String, + summary: String? = null, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit ) { Row( modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .clickable(onClick = { onCheckedChange(! checked) }) , + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .clickable(onClick = { onCheckedChange(!checked) }), verticalAlignment = Alignment.CenterVertically ) { icon?.let { Spacer(modifier = Modifier.width(16.dp)) - Icon(it , contentDescription = null) + Icon(it, contentDescription = null) Spacer(modifier = Modifier.width(16.dp)) } Column( modifier = Modifier - .padding(16.dp) - .weight(1f) + .padding(16.dp) + .weight(1f) ) { - Text(text = title , style = MaterialTheme.typography.titleLarge) + Text(text = title, style = MaterialTheme.typography.titleLarge) summary?.let { - Text(text = it , style = MaterialTheme.typography.bodyMedium) + Text(text = it, style = MaterialTheme.typography.bodyMedium) } } Switch( - checked = checked , - onCheckedChange = onCheckedChange , + checked = checked, + onCheckedChange = onCheckedChange, modifier = Modifier.padding(16.dp) ) } @@ -206,91 +200,89 @@ fun SwitchPreferenceItem( /** * Creates a clickable preference item with a switch and a divider for app preference screens. * - * This composable combines an optional icon, title, summary, switch, and a divider. Clicking - * the entire row triggers the provided `onClick` callback function. Toggling the switch calls + * This composable function combines an optional icon, title, summary, switch, and a divider into a single row. + * The entire row is clickable and triggers the provided `onClick` callback function when clicked. + * The switch is toggled on or off based on the `checked` parameter, and any change in its state calls * the `onCheckedChange` callback with the new state. * - * @param icon An optional icon to be displayed at the beginning of the preference item. (Provide a `Painter` object) + * @param icon An optional icon to be displayed at the start of the preference item. If provided, it should be an `ImageVector` object. * @param title The main title text displayed for the preference item. - * @param summary A secondary text displayed below the title for additional information. - * @param checked The initial state of the switch (true for on, false for off). - * @param onCheckedChange A callback function called whenever the switch is toggled. - * This function receives the new state of the switch (boolean) as a parameter. - * @param onClick A callback function that is called when the entire preference item is clicked. - * Leave this empty if no action is needed on click. + * @param summary A secondary text displayed below the title for additional information about the preference. + * @param checked The initial state of the switch. Set to true for on and false for off. + * @param onCheckedChange A callback function that is called whenever the switch is toggled. This function receives the new state of the switch (boolean) as a parameter. + * @param onClick A callback function that is called when the entire preference item is clicked. If no action is needed on click, this can be left empty. */ @Composable fun SwitchPreferenceItemWithDivider( - icon : ImageVector? = null , - title : String , - summary : String , - checked : Boolean , - onCheckedChange : (Boolean) -> Unit , - onClick : () -> Unit + icon: ImageVector? = null, + title: String, + summary: String, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + onClick: () -> Unit ) { Row( modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .clickable(onClick = onClick) , verticalAlignment = Alignment.CenterVertically + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .clickable(onClick = onClick), verticalAlignment = Alignment.CenterVertically ) { icon?.let { Spacer(modifier = Modifier.width(16.dp)) - Icon(it , contentDescription = null) + Icon(it, contentDescription = null) Spacer(modifier = Modifier.width(16.dp)) } Column( modifier = Modifier - .padding(16.dp) - .weight(1f) + .padding(16.dp) + .weight(1f) ) { - Text(text = title , style = MaterialTheme.typography.titleLarge) - Text(text = summary , style = MaterialTheme.typography.bodyMedium) + Text(text = title, style = MaterialTheme.typography.titleLarge) + Text(text = summary, style = MaterialTheme.typography.bodyMedium) } VerticalDivider( modifier = Modifier - .height(32.dp) - .align(Alignment.CenterVertically) , - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f) , + .height(32.dp) + .align(Alignment.CenterVertically), + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f), thickness = 1.dp ) Switch( - checked = checked , - onCheckedChange = onCheckedChange , + checked = checked, + onCheckedChange = onCheckedChange, modifier = Modifier.padding(16.dp) ) } } -enum class ButtonState { Pressed , Idle } +enum class ButtonState { Pressed, Idle } @SuppressLint("ReturnFromAwaitPointerEventScope") @Composable fun Modifier.bounceClick() = composed { var buttonState by remember { mutableStateOf(ButtonState.Idle) } val scale by animateFloatAsState( - if (buttonState == ButtonState.Pressed) 0.95f else 1f , label = "" + if (buttonState == ButtonState.Pressed) 0.95f else 1f, label = "" ) this - .graphicsLayer { - scaleX = scale - scaleY = scale - } - .clickable(interactionSource = remember { MutableInteractionSource() } , - indication = null , - onClick = { }) - .pointerInput(buttonState) { - awaitPointerEventScope { - buttonState = if (buttonState == ButtonState.Pressed) { - waitForUpOrCancellation() - ButtonState.Idle - } - else { - awaitFirstDown(false) - ButtonState.Pressed - } + .graphicsLayer { + scaleX = scale + scaleY = scale + } + .clickable(interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = { }) + .pointerInput(buttonState) { + awaitPointerEventScope { + buttonState = if (buttonState == ButtonState.Pressed) { + waitForUpOrCancellation() + ButtonState.Idle + } else { + awaitFirstDown(false) + ButtonState.Pressed } } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/d4rk/cleaner/utils/FileScanner.kt b/app/src/main/kotlin/com/d4rk/cleaner/utils/FileScanner.kt index 5a5fd24..e8d9aad 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/utils/FileScanner.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/utils/FileScanner.kt @@ -8,13 +8,12 @@ import kotlinx.coroutines.flow.first import java.io.File /** - * Utility class for scanning and filtering files based on specified preferences. + * A utility class for scanning and filtering files based on user-defined preferences. * - * This class scans and filters files based on preferences such as aggressive filtering, generic filtering, - * and other criteria defined by the provided resources. + * This class scans and filters files in the external storage directory based on user preferences such as file types (e.g., generic, archive, APK, audio, video, image files). The preferences are retrieved from a DataStore instance and the file types are defined in the provided Resources instance. * - * @property dataStore DataStore instance for accessing preferences. - * @property resources Resources instance for accessing string arrays. + * @property dataStore A DataStore instance used for accessing user preferences. + * @property resources A Resources instance used for accessing string arrays that define file types. */ class FileScanner(private val dataStore: DataStore, private val resources: Resources) { @@ -24,8 +23,7 @@ class FileScanner(private val dataStore: DataStore, private val resources: Resou /** * Initiates the file scanning process asynchronously. * - * This function loads preferences, retrieves all files, applies filters, and logs the result. - * The scanning process runs on a background thread to avoid blocking the main thread. + * This function loads user preferences, retrieves all files in the external storage directory, applies filters based on the preferences, and stores the filtered files. The scanning process runs asynchronously to avoid blocking the main thread. * * @throws Exception If an error occurs during the scanning process. */ @@ -36,31 +34,25 @@ class FileScanner(private val dataStore: DataStore, private val resources: Resou } /** - * Loads preferences from the data store into the [preferences] map. + * Loads user preferences from the data store into the [preferences] map. + * + * The preferences include whether to filter generic files, archive files, APK files, audio files, video files, and image files. */ private suspend fun loadPreferences() { preferences = mapOf( "generic_extensions" to dataStore.genericFilter.first(), - // "delete_empty_folders" to dataStore.deleteEmptyFolders.first() , "archive_extensions" to dataStore.deleteArchives.first(), - // "delete_invalid_media" to dataStore.deleteInvalidMedia.first() , - // "delete_corpse_files" to dataStore.deleteCorpseFiles.first() , "apk_extensions" to dataStore.deleteApkFiles.first(), "image_extensions" to dataStore.deleteImageFiles.first(), "audio_extensions" to dataStore.deleteAudioFiles.first(), - "video_extensions" to dataStore.deleteVideoFiles.first(), - //"double_checker" to dataStore.doubleChecker.first() , - //"clipboard_clean" to dataStore.clipboardClean.first() , - // "auto_whitelist" to dataStore.autoWhitelist.first() , - //"one_click_clean" to dataStore.oneClickClean.first() , - // "daily_clean" to dataStore.dailyCleaner.first() + "video_extensions" to dataStore.deleteVideoFiles.first() ) } /** * Retrieves all files from the external storage directory recursively. * - * @return List of all files found in the external storage. + * @return A list of all files found in the external storage directory. */ private fun getAllFiles(): List { val files = mutableListOf() @@ -81,13 +73,12 @@ class FileScanner(private val dataStore: DataStore, private val resources: Resou } /** - * Filters files based on defined preferences and returns them as a sequence. + * Filters files based on user-defined preferences and returns them as a sequence. * - * This function takes a list of all files as input and returns a sequence of files that match the defined preferences. - * The sequence allows for real-time display of filtered files as they are discovered during the scanning process. + * This function takes a list of all files as input and returns a sequence of files that match the user-defined preferences. The sequence allows for real-time display of filtered files as they are discovered during the scanning process. * * @param allFiles The list of all files to filter. - * @return A sequence of files filtered based on preferences. + * @return A sequence of files filtered based on user-defined preferences. */ private fun filterFiles(allFiles: List): Sequence { return sequence { @@ -137,6 +128,11 @@ class FileScanner(private val dataStore: DataStore, private val resources: Resou } } + /** + * Returns the list of filtered files. + * + * @return A list of files that match the user-defined preferences. + */ fun getFilteredFiles(): List { return filteredFiles } diff --git a/app/src/main/kotlin/com/d4rk/cleaner/utils/Utils.kt b/app/src/main/kotlin/com/d4rk/cleaner/utils/Utils.kt index b562144..e9f1074 100644 --- a/app/src/main/kotlin/com/d4rk/cleaner/utils/Utils.kt +++ b/app/src/main/kotlin/com/d4rk/cleaner/utils/Utils.kt @@ -6,14 +6,20 @@ import android.net.Uri import android.provider.Settings /** - * Utility object for common operations. + * A utility object for performing common operations such as opening URLs, activities, and app notification settings. + * + * This object provides functions to open a URL in the default browser, open an activity, and open the app's notification settings. + * All operations are performed in the context of an Android application. */ object Utils { /** - * Opens a URL in the default browser. + * Opens a specified URL in the default browser. * - * @param context The Android context. + * This function creates an Intent with the ACTION_VIEW action and the specified URL, and starts an activity with this intent. + * The activity runs in a new task. + * + * @param context The Android context in which the URL should be opened. * @param url The URL to open. */ fun openUrl(context: Context, url: String) { @@ -24,9 +30,11 @@ object Utils { } /** - * Opens an activity. + * Opens a specified activity. + * + * This function creates an Intent with the specified activity class, and starts an activity with this intent. The activity runs in a new task. * - * @param context The Android context. + * @param context The Android context in which the activity should be opened. * @param activityClass The class of the activity to open. */ fun openActivity(context: Context, activityClass: Class<*>) { @@ -37,9 +45,12 @@ object Utils { } /** - * Opens the app notification settings. + * Opens the app's notification settings. + * + * This function creates an Intent with the ACTION_APP_NOTIFICATION_SETTINGS action and the app's package name, and starts an activity with this intent. + * The activity runs in a new task. * - * @param context The Android context. + * @param context The Android context in which the app's notification settings should be opened. */ fun openAppNotificationSettings(context: Context) { val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { diff --git a/app/src/main/res/layout/fragment_memory.xml b/app/src/main/res/layout/fragment_memory.xml index 590c7a6..8054771 100644 --- a/app/src/main/res/layout/fragment_memory.xml +++ b/app/src/main/res/layout/fragment_memory.xml @@ -1,7 +1,4 @@