feat(HomeScreen): indicate when no installations
This commit is contained in:
parent
52e24e742e
commit
b5c6f4fb54
3 changed files with 193 additions and 69 deletions
|
|
@ -108,33 +108,36 @@ class HomeModel(
|
|||
isAliucordPkg || hasAliucordMeta
|
||||
}
|
||||
|
||||
val aliucordInstallations = aliucordPackages
|
||||
.map {
|
||||
// `longVersionCode` is unnecessary since Discord doesn't use `versionCodeMajor`
|
||||
@Suppress("DEPRECATION")
|
||||
val versionCode = it.versionCode
|
||||
val aliucordInstallations = aliucordPackages.map {
|
||||
// `longVersionCode` is unnecessary since Discord doesn't use `versionCodeMajor`
|
||||
@Suppress("DEPRECATION")
|
||||
val versionCode = it.versionCode
|
||||
|
||||
val baseVersion = it.applicationInfo.metaData?.getInt("aliucordBaseVersion")
|
||||
val isBaseUpdated = /* TODO: remote data json instead */ baseVersion == 0
|
||||
val baseVersion = it.applicationInfo.metaData?.getInt("aliucordBaseVersion")
|
||||
val isBaseUpdated = /* TODO: remote data json instead */ baseVersion == 0
|
||||
|
||||
InstallData(
|
||||
name = packageManager.getApplicationLabel(it.applicationInfo).toString(),
|
||||
packageName = it.packageName,
|
||||
baseUpdated = isBaseUpdated,
|
||||
icon = packageManager
|
||||
.getApplicationIcon(it.applicationInfo)
|
||||
.toBitmap()
|
||||
.asImageBitmap()
|
||||
.let(::BitmapPainter),
|
||||
version = DiscordVersion.Existing(
|
||||
type = DiscordVersion.parseVersionType(versionCode),
|
||||
name = it.versionName.split("-")[0].trim(),
|
||||
code = versionCode,
|
||||
),
|
||||
)
|
||||
}
|
||||
InstallData(
|
||||
name = packageManager.getApplicationLabel(it.applicationInfo).toString(),
|
||||
packageName = it.packageName,
|
||||
baseUpdated = isBaseUpdated,
|
||||
icon = packageManager
|
||||
.getApplicationIcon(it.applicationInfo)
|
||||
.toBitmap()
|
||||
.asImageBitmap()
|
||||
.let(::BitmapPainter),
|
||||
version = DiscordVersion.Existing(
|
||||
type = DiscordVersion.parseVersionType(versionCode),
|
||||
name = it.versionName.split("-")[0].trim(),
|
||||
code = versionCode,
|
||||
),
|
||||
)
|
||||
}.toImmutableList()
|
||||
|
||||
installations = InstallsState.Fetched(data = aliucordInstallations.toImmutableList())
|
||||
installations = if (aliucordInstallations.isNotEmpty()) {
|
||||
InstallsState.Fetched(data = aliucordInstallations)
|
||||
} else {
|
||||
InstallsState.None
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
Log.e(BuildConfig.TAG, "Failed to query Aliucord installations", t)
|
||||
installations = InstallsState.Error
|
||||
|
|
|
|||
|
|
@ -10,16 +10,21 @@ import androidx.compose.animation.*
|
|||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import cafe.adriel.voyager.koin.getScreenModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.ui.components.AnimatedVersionDisplay
|
||||
import com.aliucord.manager.ui.components.ProjectHeader
|
||||
import com.aliucord.manager.ui.components.dialogs.NetworkWarningDialog
|
||||
|
|
@ -70,53 +75,32 @@ class HomeScreen : Screen {
|
|||
|
||||
Scaffold(
|
||||
topBar = { HomeAppBar() },
|
||||
) { paddingValues ->
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
contentPadding = paddingValues
|
||||
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues.exclude(PaddingValuesSides.Bottom))
|
||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
|
||||
) {
|
||||
item(key = "PROJECT_HEADER") {
|
||||
ProjectHeader()
|
||||
}
|
||||
) { padding ->
|
||||
when (model.installations) {
|
||||
is InstallsState.Fetching,
|
||||
is InstallsState.Fetched,
|
||||
-> PresentInstallsContent(
|
||||
model = model,
|
||||
padding = padding,
|
||||
onClickInstall = onClickInstall,
|
||||
)
|
||||
|
||||
item(key = "ADD_INSTALL_BUTTON") {
|
||||
InstallButton(
|
||||
onClick = onClickInstall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 10.dp)
|
||||
)
|
||||
}
|
||||
InstallsState.None -> NoInstallsContent(
|
||||
supportedVersion = model.supportedVersion,
|
||||
onClickInstall = onClickInstall,
|
||||
modifier = Modifier
|
||||
.padding(padding.exclude(PaddingValuesSides.Bottom)),
|
||||
)
|
||||
|
||||
item(key = "SUPPORTED_VERSION") {
|
||||
AnimatedVersionDisplay(
|
||||
version = model.supportedVersion,
|
||||
modifier = Modifier.padding(bottom = 22.dp),
|
||||
)
|
||||
}
|
||||
|
||||
val installations = (model.installations as? InstallsState.Fetched)?.data
|
||||
?: return@LazyColumn
|
||||
|
||||
items(installations, key = { it.packageName }) {
|
||||
AnimatedVisibility(
|
||||
enter = fadeIn() + slideInHorizontally { it * -2 },
|
||||
exit = fadeOut() + slideOutHorizontally { it * 2 },
|
||||
visible = model.supportedVersion !is DiscordVersion.None,
|
||||
InstallsState.Error -> {
|
||||
// This is ugly asf but it should never happen
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.padding(padding),
|
||||
) {
|
||||
InstalledItemCard(
|
||||
data = it,
|
||||
onUpdate = ::TODO, // TODO: prefilled install options screen
|
||||
onOpenApp = { model.launchApp(it.packageName) },
|
||||
onOpenInfo = { model.openAppInfo(it.packageName) },
|
||||
onOpenPlugins = { navigator.push(PluginsScreen()) }, // TODO: install-specific plugins
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
Text(
|
||||
text = "Failed to fetch installations",
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -124,3 +108,139 @@ class HomeScreen : Screen {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun PresentInstallsContent(
|
||||
model: HomeModel,
|
||||
padding: PaddingValues,
|
||||
onClickInstall: () -> Unit,
|
||||
) {
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
contentPadding = padding
|
||||
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(padding.exclude(PaddingValuesSides.Bottom))
|
||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
|
||||
) {
|
||||
item(key = "PROJECT_HEADER") {
|
||||
ProjectHeader()
|
||||
}
|
||||
|
||||
item(key = "ADD_INSTALL_BUTTON") {
|
||||
InstallButton(
|
||||
onClick = onClickInstall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 10.dp)
|
||||
)
|
||||
}
|
||||
|
||||
item(key = "SUPPORTED_VERSION") {
|
||||
AnimatedVersionDisplay(
|
||||
version = model.supportedVersion,
|
||||
modifier = Modifier.padding(bottom = 22.dp),
|
||||
)
|
||||
}
|
||||
|
||||
val installations = (model.installations as? InstallsState.Fetched)?.data
|
||||
?: return@LazyColumn
|
||||
|
||||
items(installations, key = { it.packageName }) {
|
||||
AnimatedVisibility(
|
||||
enter = fadeIn() + slideInHorizontally { it * -2 },
|
||||
exit = fadeOut() + slideOutHorizontally { it * 2 },
|
||||
visible = model.supportedVersion !is DiscordVersion.None,
|
||||
) {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
InstalledItemCard(
|
||||
data = it,
|
||||
onUpdate = ::TODO, // TODO: prefilled install options screen
|
||||
onOpenApp = { model.launchApp(it.packageName) },
|
||||
onOpenInfo = { model.openAppInfo(it.packageName) },
|
||||
onOpenPlugins = { navigator.push(PluginsScreen()) }, // TODO: install-specific plugins
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NoInstallsContent(
|
||||
supportedVersion: DiscordVersion,
|
||||
onClickInstall: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
|
||||
) {
|
||||
ProjectHeader()
|
||||
|
||||
InstallButton(
|
||||
onClick = onClickInstall,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 10.dp)
|
||||
)
|
||||
|
||||
AnimatedVersionDisplay(
|
||||
version = supportedVersion,
|
||||
modifier = Modifier.padding(bottom = 22.dp),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||
modifier = Modifier
|
||||
.alpha(.1f)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
for (i in 0..<3) key(i) {
|
||||
Surface(
|
||||
content = {},
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
tonalElevation = 2.dp,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(195.dp)
|
||||
.shadow(
|
||||
clip = false,
|
||||
elevation = 2.dp,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(14.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.alpha(.8f)
|
||||
.align(Alignment.Center)
|
||||
.padding(bottom = 80.dp),
|
||||
) {
|
||||
Text(
|
||||
text = """ /ᐠﹷ ‸ ﹷ ᐟ\ノ""",
|
||||
style = MaterialTheme.typography.labelLarge
|
||||
.copy(fontSize = 38.sp),
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.installs_no_installs),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
<string name="permissions_grant_title">Grant Permissions</string>
|
||||
<string name="permissions_grant_body">In order for Aliucord Manager to function, file permissions are required. Since shared data is stored in ~/Aliucord, permissions are required in order to access it.</string>
|
||||
|
||||
<string name="installs_no_installs">No installations founds!</string>
|
||||
<string name="launch_aliucord_fail">Failed to launch Aliucord</string>
|
||||
|
||||
<string name="settings_theme">Theme</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue