Skip to content

Commit

Permalink
Improved the app manager
Browse files Browse the repository at this point in the history
  • Loading branch information
D4rK7355608 committed Jul 10, 2024
1 parent c8f93ad commit 6f76ae5
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.d4rk.cleaner.data.model.ui
package com.d4rk.cleaner.data.model.ui.appmanager.ui

data class ApkInfo(
val id: Long,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.d4rk.cleaner.data.model.ui.appmanager.ui

sealed class UiState<out T : Any> {
object Loading : UiState<Nothing>()
data class Success<out T : Any>(val data: T) : UiState<T>()
data class Error(val exception: Exception) : UiState<Nothing>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.provider.Settings
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.updateTransition

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand All @@ -24,6 +28,7 @@ import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
Expand All @@ -45,6 +50,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
Expand All @@ -55,7 +61,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.d4rk.cleaner.R
import com.d4rk.cleaner.data.model.ui.ApkInfo
import com.d4rk.cleaner.data.model.ui.appmanager.ui.ApkInfo
import com.d4rk.cleaner.utils.PermissionsUtils
import kotlinx.coroutines.launch
import java.io.File
Expand All @@ -73,56 +79,73 @@ fun AppManagerComposable() {
val tabs = listOf("Installed Apps", "System Apps", "App Install Files")
val pagerState = rememberPagerState(pageCount = { tabs.size })
val coroutineScope = rememberCoroutineScope()
val isLoading by viewModel.isLoading.collectAsState()
val transition = updateTransition(targetState = ! isLoading, label = "LoadingTransition")

val contentAlpha by transition.animateFloat(label = "Content Alpha") {
if (it) 1f else 0f
}

LaunchedEffect(context) {
if (!PermissionsUtils.hasStoragePermissions(context)) {
PermissionsUtils.requestStoragePermissions(context as Activity)
}
}

Column {
TabRow(
selectedTabIndex = pagerState.currentPage,
indicator = { tabPositions ->
TabRowDefaults.PrimaryIndicator(
modifier = Modifier.tabIndicatorOffset(tabPositions[pagerState.currentPage]),
shape = RoundedCornerShape(
topStart = 3.dp, topEnd = 3.dp, bottomEnd = 0.dp, bottomStart = 0.dp
),
)
},
if (isLoading) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
tabs.forEachIndexed { index, title ->
Tab(
text = {
Text(
text = title,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = MaterialTheme.colorScheme.onSurface
)
},
selected = pagerState.currentPage == index,
onClick = {
coroutineScope.launch {
pagerState.animateScrollToPage(index)
CircularProgressIndicator()
}
} else {
Column(
modifier = Modifier.alpha(contentAlpha),
) {
TabRow(
selectedTabIndex = pagerState.currentPage,
indicator = { tabPositions ->
TabRowDefaults.PrimaryIndicator(
modifier = Modifier.tabIndicatorOffset(tabPositions[pagerState.currentPage]),
shape = RoundedCornerShape(
topStart = 3.dp, topEnd = 3.dp, bottomEnd = 0.dp, bottomStart = 0.dp
),
)
},
) {
tabs.forEachIndexed { index, title ->
Tab(
text = {
Text(
text = title,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = MaterialTheme.colorScheme.onSurface
)
},
selected = pagerState.currentPage == index,
onClick = {
coroutineScope.launch {
pagerState.animateScrollToPage(index)
}
}
}
)
)
}
}
}

HorizontalPager(
state = pagerState, // Only provide pagerState here
) { page ->
when (page) {
0 -> AppsComposable(
apps = viewModel.installedApps.collectAsState().value.filter { it.flags and ApplicationInfo.FLAG_SYSTEM == 0 }
)
1 -> AppsComposable(
apps = viewModel.installedApps.collectAsState().value.filter { it.flags and ApplicationInfo.FLAG_SYSTEM != 0 }
)
2 -> ApksComposable(apkFiles = viewModel.apkFiles.collectAsState().value)
HorizontalPager(
state = pagerState,
) { page ->
when (page) {
0 -> AppsComposable(
apps = viewModel.installedApps.collectAsState().value.filter { it.flags and ApplicationInfo.FLAG_SYSTEM == 0 }
)
1 -> AppsComposable(
apps = viewModel.installedApps.collectAsState().value.filter { it.flags and ApplicationInfo.FLAG_SYSTEM != 0 }
)
2 -> ApksComposable(apkFiles = viewModel.apkFiles.collectAsState().value)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import android.net.Uri
import android.provider.MediaStore
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.d4rk.cleaner.data.model.ui.ApkInfo
import com.d4rk.cleaner.data.model.ui.appmanager.ui.ApkInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand All @@ -23,10 +25,25 @@ class AppManagerViewModel(private val application: Application) : ViewModel() {
private val _apkFiles = MutableStateFlow<List<ApkInfo>>(emptyList())
val apkFiles: StateFlow<List<ApkInfo>> = _apkFiles.asStateFlow()

private val _isLoading = MutableStateFlow(true)
val isLoading : StateFlow<Boolean> = _isLoading.asStateFlow()

init {
loadInstalledApps()
loadApkFiles()
loadAppData()
}

private fun loadAppData() {
viewModelScope.launch {
_isLoading.value = true
try {
awaitAll(
async { loadInstalledApps() },
async { loadApkFiles() }
)
} finally {
_isLoading.value = false
}
}
}

private fun loadInstalledApps() {
Expand Down

0 comments on commit 6f76ae5

Please sign in to comment.