Skip to content

Commit b5c6f4f

Browse files
committed
feat(HomeScreen): indicate when no installations
1 parent 52e24e7 commit b5c6f4f

File tree

3 files changed

+191
-67
lines changed

3 files changed

+191
-67
lines changed

app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt

+29-26
Original file line numberDiff line numberDiff line change
@@ -108,33 +108,36 @@ class HomeModel(
108108
isAliucordPkg || hasAliucordMeta
109109
}
110110

111-
val aliucordInstallations = aliucordPackages
112-
.map {
113-
// `longVersionCode` is unnecessary since Discord doesn't use `versionCodeMajor`
114-
@Suppress("DEPRECATION")
115-
val versionCode = it.versionCode
116-
117-
val baseVersion = it.applicationInfo.metaData?.getInt("aliucordBaseVersion")
118-
val isBaseUpdated = /* TODO: remote data json instead */ baseVersion == 0
119-
120-
InstallData(
121-
name = packageManager.getApplicationLabel(it.applicationInfo).toString(),
122-
packageName = it.packageName,
123-
baseUpdated = isBaseUpdated,
124-
icon = packageManager
125-
.getApplicationIcon(it.applicationInfo)
126-
.toBitmap()
127-
.asImageBitmap()
128-
.let(::BitmapPainter),
129-
version = DiscordVersion.Existing(
130-
type = DiscordVersion.parseVersionType(versionCode),
131-
name = it.versionName.split("-")[0].trim(),
132-
code = versionCode,
133-
),
134-
)
135-
}
111+
val aliucordInstallations = aliucordPackages.map {
112+
// `longVersionCode` is unnecessary since Discord doesn't use `versionCodeMajor`
113+
@Suppress("DEPRECATION")
114+
val versionCode = it.versionCode
115+
116+
val baseVersion = it.applicationInfo.metaData?.getInt("aliucordBaseVersion")
117+
val isBaseUpdated = /* TODO: remote data json instead */ baseVersion == 0
118+
119+
InstallData(
120+
name = packageManager.getApplicationLabel(it.applicationInfo).toString(),
121+
packageName = it.packageName,
122+
baseUpdated = isBaseUpdated,
123+
icon = packageManager
124+
.getApplicationIcon(it.applicationInfo)
125+
.toBitmap()
126+
.asImageBitmap()
127+
.let(::BitmapPainter),
128+
version = DiscordVersion.Existing(
129+
type = DiscordVersion.parseVersionType(versionCode),
130+
name = it.versionName.split("-")[0].trim(),
131+
code = versionCode,
132+
),
133+
)
134+
}.toImmutableList()
136135

137-
installations = InstallsState.Fetched(data = aliucordInstallations.toImmutableList())
136+
installations = if (aliucordInstallations.isNotEmpty()) {
137+
InstallsState.Fetched(data = aliucordInstallations)
138+
} else {
139+
InstallsState.None
140+
}
138141
} catch (t: Throwable) {
139142
Log.e(BuildConfig.TAG, "Failed to query Aliucord installations", t)
140143
installations = InstallsState.Error

app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt

+161-41
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@ import androidx.compose.animation.*
1010
import androidx.compose.foundation.layout.*
1111
import androidx.compose.foundation.lazy.LazyColumn
1212
import androidx.compose.foundation.lazy.items
13-
import androidx.compose.material3.Scaffold
13+
import androidx.compose.material3.*
1414
import androidx.compose.runtime.*
1515
import androidx.compose.ui.Alignment
1616
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.draw.alpha
18+
import androidx.compose.ui.draw.shadow
19+
import androidx.compose.ui.res.stringResource
1720
import androidx.compose.ui.unit.dp
21+
import androidx.compose.ui.unit.sp
1822
import androidx.lifecycle.compose.LifecycleResumeEffect
1923
import cafe.adriel.voyager.core.screen.Screen
2024
import cafe.adriel.voyager.koin.getScreenModel
2125
import cafe.adriel.voyager.navigator.LocalNavigator
2226
import cafe.adriel.voyager.navigator.currentOrThrow
27+
import com.aliucord.manager.R
2328
import com.aliucord.manager.ui.components.AnimatedVersionDisplay
2429
import com.aliucord.manager.ui.components.ProjectHeader
2530
import com.aliucord.manager.ui.components.dialogs.NetworkWarningDialog
@@ -70,56 +75,171 @@ class HomeScreen : Screen {
7075

7176
Scaffold(
7277
topBar = { HomeAppBar() },
73-
) { paddingValues ->
74-
LazyColumn(
78+
) { padding ->
79+
when (model.installations) {
80+
is InstallsState.Fetching,
81+
is InstallsState.Fetched,
82+
-> PresentInstallsContent(
83+
model = model,
84+
padding = padding,
85+
onClickInstall = onClickInstall,
86+
)
87+
88+
InstallsState.None -> NoInstallsContent(
89+
supportedVersion = model.supportedVersion,
90+
onClickInstall = onClickInstall,
91+
modifier = Modifier
92+
.padding(padding.exclude(PaddingValuesSides.Bottom)),
93+
)
94+
95+
InstallsState.Error -> {
96+
// This is ugly asf but it should never happen
97+
Box(
98+
contentAlignment = Alignment.Center,
99+
modifier = Modifier.padding(padding),
100+
) {
101+
Text(
102+
text = "Failed to fetch installations",
103+
style = MaterialTheme.typography.labelMedium,
104+
)
105+
}
106+
}
107+
}
108+
}
109+
}
110+
}
111+
112+
@Composable
113+
fun PresentInstallsContent(
114+
model: HomeModel,
115+
padding: PaddingValues,
116+
onClickInstall: () -> Unit,
117+
) {
118+
LazyColumn(
119+
verticalArrangement = Arrangement.spacedBy(6.dp),
120+
horizontalAlignment = Alignment.CenterHorizontally,
121+
contentPadding = padding
122+
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top),
123+
modifier = Modifier
124+
.fillMaxSize()
125+
.padding(padding.exclude(PaddingValuesSides.Bottom))
126+
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
127+
) {
128+
item(key = "PROJECT_HEADER") {
129+
ProjectHeader()
130+
}
131+
132+
item(key = "ADD_INSTALL_BUTTON") {
133+
InstallButton(
134+
onClick = onClickInstall,
135+
modifier = Modifier
136+
.fillMaxWidth()
137+
.padding(top = 10.dp)
138+
)
139+
}
140+
141+
item(key = "SUPPORTED_VERSION") {
142+
AnimatedVersionDisplay(
143+
version = model.supportedVersion,
144+
modifier = Modifier.padding(bottom = 22.dp),
145+
)
146+
}
147+
148+
val installations = (model.installations as? InstallsState.Fetched)?.data
149+
?: return@LazyColumn
150+
151+
items(installations, key = { it.packageName }) {
152+
AnimatedVisibility(
153+
enter = fadeIn() + slideInHorizontally { it * -2 },
154+
exit = fadeOut() + slideOutHorizontally { it * 2 },
155+
visible = model.supportedVersion !is DiscordVersion.None,
156+
) {
157+
val navigator = LocalNavigator.currentOrThrow
158+
159+
InstalledItemCard(
160+
data = it,
161+
onUpdate = ::TODO, // TODO: prefilled install options screen
162+
onOpenApp = { model.launchApp(it.packageName) },
163+
onOpenInfo = { model.openAppInfo(it.packageName) },
164+
onOpenPlugins = { navigator.push(PluginsScreen()) }, // TODO: install-specific plugins
165+
modifier = Modifier.fillMaxWidth()
166+
)
167+
}
168+
}
169+
}
170+
}
171+
172+
@Composable
173+
fun NoInstallsContent(
174+
supportedVersion: DiscordVersion,
175+
onClickInstall: () -> Unit,
176+
modifier: Modifier = Modifier,
177+
) {
178+
Column(
179+
verticalArrangement = Arrangement.spacedBy(6.dp),
180+
horizontalAlignment = Alignment.CenterHorizontally,
181+
modifier = modifier
182+
.fillMaxSize()
183+
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
184+
) {
185+
ProjectHeader()
186+
187+
InstallButton(
188+
onClick = onClickInstall,
189+
modifier = Modifier
190+
.fillMaxWidth()
191+
.padding(top = 10.dp)
192+
)
193+
194+
AnimatedVersionDisplay(
195+
version = supportedVersion,
196+
modifier = Modifier.padding(bottom = 22.dp),
197+
)
198+
199+
Box(
200+
modifier = Modifier.fillMaxSize(),
201+
) {
202+
Column(
75203
verticalArrangement = Arrangement.spacedBy(6.dp),
76-
horizontalAlignment = Alignment.CenterHorizontally,
77-
contentPadding = paddingValues
78-
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top),
79204
modifier = Modifier
205+
.alpha(.1f)
80206
.fillMaxSize()
81-
.padding(paddingValues.exclude(PaddingValuesSides.Bottom))
82-
.padding(top = 16.dp, start = 16.dp, end = 16.dp),
83207
) {
84-
item(key = "PROJECT_HEADER") {
85-
ProjectHeader()
86-
}
87-
88-
item(key = "ADD_INSTALL_BUTTON") {
89-
InstallButton(
90-
onClick = onClickInstall,
208+
for (i in 0..<3) key(i) {
209+
Surface(
210+
content = {},
211+
shape = MaterialTheme.shapes.medium,
212+
tonalElevation = 2.dp,
91213
modifier = Modifier
92214
.fillMaxWidth()
93-
.padding(top = 10.dp)
94-
)
95-
}
96-
97-
item(key = "SUPPORTED_VERSION") {
98-
AnimatedVersionDisplay(
99-
version = model.supportedVersion,
100-
modifier = Modifier.padding(bottom = 22.dp),
215+
.height(195.dp)
216+
.shadow(
217+
clip = false,
218+
elevation = 2.dp,
219+
shape = MaterialTheme.shapes.medium,
220+
),
101221
)
102222
}
223+
}
103224

104-
val installations = (model.installations as? InstallsState.Fetched)?.data
105-
?: return@LazyColumn
225+
Column(
226+
verticalArrangement = Arrangement.spacedBy(14.dp),
227+
horizontalAlignment = Alignment.CenterHorizontally,
228+
modifier = Modifier
229+
.alpha(.8f)
230+
.align(Alignment.Center)
231+
.padding(bottom = 80.dp),
232+
) {
233+
Text(
234+
text = """ /ᐠﹷ ‸ ﹷ ᐟ\ノ""",
235+
style = MaterialTheme.typography.labelLarge
236+
.copy(fontSize = 38.sp),
237+
)
106238

107-
items(installations, key = { it.packageName }) {
108-
AnimatedVisibility(
109-
enter = fadeIn() + slideInHorizontally { it * -2 },
110-
exit = fadeOut() + slideOutHorizontally { it * 2 },
111-
visible = model.supportedVersion !is DiscordVersion.None,
112-
) {
113-
InstalledItemCard(
114-
data = it,
115-
onUpdate = ::TODO, // TODO: prefilled install options screen
116-
onOpenApp = { model.launchApp(it.packageName) },
117-
onOpenInfo = { model.openAppInfo(it.packageName) },
118-
onOpenPlugins = { navigator.push(PluginsScreen()) }, // TODO: install-specific plugins
119-
modifier = Modifier.fillMaxWidth()
120-
)
121-
}
122-
}
239+
Text(
240+
text = stringResource(R.string.installs_no_installs),
241+
style = MaterialTheme.typography.labelMedium,
242+
)
123243
}
124244
}
125245
}

app/src/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<string name="permissions_grant_title">Grant Permissions</string>
3535
<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>
3636

37+
<string name="installs_no_installs">No installations founds!</string>
3738
<string name="launch_aliucord_fail">Failed to launch Aliucord</string>
3839

3940
<string name="settings_theme">Theme</string>

0 commit comments

Comments
 (0)