From b5c6f4fb5417e360499b0909560a9c66adb516c3 Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Mon, 4 Mar 2024 00:45:18 -0800 Subject: [PATCH] feat(HomeScreen): indicate when no installations --- .../manager/ui/screens/home/HomeModel.kt | 51 +++-- .../manager/ui/screens/home/HomeScreen.kt | 210 ++++++++++++++---- app/src/main/res/values/strings.xml | 1 + 3 files changed, 193 insertions(+), 69 deletions(-) diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt index e3c9e2e..bb60afd 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt @@ -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 diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt index 0a2a22c..3ab9d3f 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt @@ -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, + ) + } + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8da966f..3ed961e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,6 +34,7 @@ Grant Permissions 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. + No installations founds! Failed to launch Aliucord Theme