Skip to content

Commit a72fe41

Browse files
committed
wip reorganize ui
1 parent c2f151a commit a72fe41

15 files changed

+252
-324
lines changed

app/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ android {
9595
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
9696
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
9797
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
98-
// "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${reportsDir}",
98+
"-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${reportsDir}",
9999
)
100100
}
101101

app/src/main/kotlin/com/aliucord/manager/ui/components/ProjectHeader.kt

+10-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import androidx.compose.ui.res.painterResource
1111
import androidx.compose.ui.res.stringResource
1212
import androidx.compose.ui.unit.dp
1313
import androidx.compose.ui.unit.sp
14+
import com.aliucord.manager.BuildConfig
1415
import com.aliucord.manager.R
1516

1617
@Composable
@@ -48,19 +49,21 @@ fun ProjectHeader(modifier: Modifier = Modifier) {
4849
TextButton(onClick = { uriHandler.openUri("https://github.com/Aliucord") }) {
4950
Icon(
5051
painter = painterResource(R.drawable.ic_account_github_white_24dp),
51-
contentDescription = stringResource(R.string.github)
52+
contentDescription = null,
53+
modifier = Modifier.padding(end = ButtonDefaults.IconSpacing),
5254
)
53-
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
5455
Text(text = stringResource(R.string.github))
5556
}
5657

57-
TextButton(onClick = { uriHandler.openUri("https://aliucord.com") }) {
58+
TextButton(onClick = { uriHandler.openUri("https://discord.gg/${BuildConfig.SUPPORT_SERVER}") }) {
5859
Icon(
59-
painter = painterResource(R.drawable.ic_link),
60-
contentDescription = stringResource(R.string.website)
60+
painter = painterResource(R.drawable.ic_discord),
61+
contentDescription = stringResource(R.string.support_server),
62+
modifier = Modifier
63+
.padding(end = ButtonDefaults.IconSpacing)
64+
.size(22.dp),
6165
)
62-
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
63-
Text(text = stringResource(R.string.website))
66+
Text(text = stringResource(R.string.discord))
6467
}
6568
}
6669
}

app/src/main/kotlin/com/aliucord/manager/ui/components/SegmentedButton.kt

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ import androidx.compose.material3.*
66
import androidx.compose.runtime.Composable
77
import androidx.compose.ui.Alignment
88
import androidx.compose.ui.Modifier
9+
import androidx.compose.ui.graphics.Color
910
import androidx.compose.ui.graphics.painter.Painter
1011
import androidx.compose.ui.unit.dp
1112

1213
@Composable
1314
fun RowScope.SegmentedButton(
1415
icon: Painter,
16+
iconColor: Color = MaterialTheme.colorScheme.primary,
1517
iconDescription: String? = null,
1618
text: String,
19+
textColor: Color = MaterialTheme.colorScheme.primary,
1720
onClick: () -> Unit,
1821
) {
1922
Column(
@@ -28,15 +31,15 @@ fun RowScope.SegmentedButton(
2831
Icon(
2932
painter = icon,
3033
contentDescription = iconDescription,
31-
tint = MaterialTheme.colorScheme.primary
34+
tint = iconColor,
3235
)
3336

3437
Text(
3538
text = text,
3639
style = MaterialTheme.typography.labelLarge,
37-
color = MaterialTheme.colorScheme.primary,
40+
color = textColor,
3841
maxLines = 1,
39-
modifier = Modifier.basicMarquee()
42+
modifier = Modifier.basicMarquee(),
4043
)
4144
}
4245
}

app/src/main/kotlin/com/aliucord/manager/ui/screens/about/AboutScreen.kt

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class AboutScreen : Screen {
4646
}
4747
) { paddingValues ->
4848
LazyColumn(
49+
horizontalAlignment = Alignment.CenterHorizontally,
4950
contentPadding = paddingValues
5051
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top),
5152
modifier = Modifier

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

+15-17
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
package com.aliucord.manager.ui.screens.home
22

33
import android.app.Application
4+
import android.content.Intent
45
import android.content.pm.PackageManager
6+
import android.provider.Settings
57
import android.util.Log
68
import androidx.compose.runtime.*
79
import androidx.compose.ui.graphics.asImageBitmap
810
import androidx.compose.ui.graphics.painter.BitmapPainter
911
import androidx.core.graphics.drawable.toBitmap
12+
import androidx.core.net.toUri
1013
import cafe.adriel.voyager.core.model.ScreenModel
1114
import cafe.adriel.voyager.core.model.screenModelScope
1215
import com.aliucord.manager.BuildConfig
1316
import com.aliucord.manager.R
1417
import com.aliucord.manager.domain.repository.GithubRepository
1518
import com.aliucord.manager.installer.util.uninstallApk
16-
import com.aliucord.manager.manager.PreferencesManager
1719
import com.aliucord.manager.network.utils.fold
1820
import com.aliucord.manager.ui.util.DiscordVersion
1921
import com.aliucord.manager.util.launchBlock
@@ -23,26 +25,21 @@ import kotlinx.collections.immutable.toImmutableList
2325
class HomeModel(
2426
private val application: Application,
2527
private val github: GithubRepository,
26-
private val preferences: PreferencesManager,
2728
) : ScreenModel {
2829
var supportedVersion by mutableStateOf<DiscordVersion>(DiscordVersion.None)
2930
private set
3031

31-
var installations by mutableStateOf<InstallsFetchState>(InstallsFetchState.Fetching)
32+
var installations by mutableStateOf<InstallsState>(InstallsState.Fetching)
3233
private set
3334

3435
init {
35-
refresh()
36-
}
37-
38-
fun refresh() {
3936
fetchInstallations()
4037
fetchSupportedVersion()
4138
}
4239

43-
fun launchAliucord() {
40+
fun launchApp(packageName: String) {
4441
val launchIntent = application.packageManager
45-
.getLaunchIntentForPackage(preferences.packageName)
42+
.getLaunchIntentForPackage(packageName)
4643

4744
if (launchIntent != null) {
4845
application.startActivity(launchIntent)
@@ -51,8 +48,12 @@ class HomeModel(
5148
}
5249
}
5350

54-
fun uninstallAliucord() {
55-
application.uninstallApk(preferences.packageName)
51+
fun openAppInfo(packageName: String) {
52+
val launchIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
53+
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
54+
.setData("package:$packageName".toUri())
55+
56+
application.startActivity(launchIntent)
5657
}
5758

5859
private fun fetchInstallations() = screenModelScope.launchBlock {
@@ -64,8 +65,6 @@ class HomeModel(
6465
.takeIf { it.isNotEmpty() }
6566
?: throw IllegalStateException("Failed to fetch installed packages (returned none)")
6667

67-
println(installedPackages)
68-
6968
val aliucordPackages = installedPackages
7069
.asSequence()
7170
.filter {
@@ -74,7 +73,6 @@ class HomeModel(
7473
isAliucordPkg || hasAliucordMeta
7574
}
7675

77-
println(aliucordPackages)
7876
val aliucordInstallations = aliucordPackages
7977
.map {
8078
// `longVersionCode` is unnecessary since Discord doesn't use `versionCodeMajor`
@@ -84,7 +82,7 @@ class HomeModel(
8482
val baseVersion = it.applicationInfo.metaData?.getInt("aliucordBaseVersion")
8583
val isBaseUpdated = /* TODO: remote data json instead */ baseVersion == 0
8684

87-
InstallsFetchState.Data(
85+
InstallData(
8886
name = packageManager.getApplicationLabel(it.applicationInfo).toString(),
8987
packageName = it.packageName,
9088
baseUpdated = isBaseUpdated,
@@ -101,10 +99,10 @@ class HomeModel(
10199
)
102100
}
103101

104-
installations = InstallsFetchState.Fetched(data = aliucordInstallations.toImmutableList())
102+
installations = InstallsState.Fetched(data = aliucordInstallations.toImmutableList())
105103
} catch (t: Throwable) {
106104
Log.e(BuildConfig.TAG, "Failed to query Aliucord installations", t)
107-
installations = InstallsFetchState.Error
105+
installations = InstallsState.Error
108106
}
109107
}
110108

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

+30-36
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
package com.aliucord.manager.ui.screens.home
88

99
import androidx.compose.animation.*
10-
import androidx.compose.animation.core.tween
1110
import androidx.compose.foundation.layout.*
1211
import androidx.compose.foundation.lazy.LazyColumn
1312
import androidx.compose.foundation.lazy.items
@@ -17,6 +16,9 @@ import androidx.compose.ui.Alignment
1716
import androidx.compose.ui.Modifier
1817
import androidx.compose.ui.draw.alpha
1918
import androidx.compose.ui.res.stringResource
19+
import androidx.compose.ui.text.SpanStyle
20+
import androidx.compose.ui.text.font.FontWeight
21+
import androidx.compose.ui.text.withStyle
2022
import androidx.compose.ui.unit.dp
2123
import cafe.adriel.voyager.core.screen.Screen
2224
import cafe.adriel.voyager.koin.getScreenModel
@@ -27,6 +29,7 @@ import com.aliucord.manager.ui.components.ProjectHeader
2729
import com.aliucord.manager.ui.components.dialogs.InstallerDialog
2830
import com.aliucord.manager.ui.screens.home.components.*
2931
import com.aliucord.manager.ui.screens.install.InstallScreen
32+
import com.aliucord.manager.ui.screens.plugins.PluginsScreen
3033
import com.aliucord.manager.ui.util.DiscordVersion
3134
import com.aliucord.manager.ui.util.paddings.PaddingValuesSides
3235
import com.aliucord.manager.ui.util.paddings.exclude
@@ -40,7 +43,6 @@ class HomeScreen : Screen {
4043
val model = getScreenModel<HomeModel>()
4144

4245
var showInstallerDialog by remember { mutableStateOf(false) }
43-
4446
if (showInstallerDialog) {
4547
InstallerDialog(
4648
onDismiss = { showInstallerDialog = false },
@@ -55,7 +57,7 @@ class HomeScreen : Screen {
5557
topBar = { HomeAppBar() },
5658
) { paddingValues ->
5759
LazyColumn(
58-
verticalArrangement = Arrangement.spacedBy(4.dp),
60+
verticalArrangement = Arrangement.spacedBy(6.dp),
5961
horizontalAlignment = Alignment.CenterHorizontally,
6062
contentPadding = paddingValues
6163
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top),
@@ -68,6 +70,17 @@ class HomeScreen : Screen {
6870
ProjectHeader()
6971
}
7072

73+
item(key = "ADD_INSTALL_BUTTON") {
74+
InstallButton(
75+
// TODO: install options screen to configure pkg name
76+
enabled = (model.installations as? InstallsState.Fetched)?.data?.isEmpty() ?: false,
77+
onClick = { showInstallerDialog = true },
78+
modifier = Modifier
79+
.fillMaxWidth()
80+
.padding(top = 10.dp)
81+
)
82+
}
83+
7184
item(key = "SUPPORTED_VERSION") {
7285
AnimatedVisibility(
7386
enter = fadeIn() + slideInVertically { it * -2 },
@@ -77,37 +90,19 @@ class HomeScreen : Screen {
7790
VersionDisplay(
7891
version = model.supportedVersion,
7992
prefix = {
80-
append(stringResource(R.string.version_supported))
81-
append(" ")
93+
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
94+
append(stringResource(R.string.version_supported))
95+
append(" ")
96+
}
8297
},
83-
modifier = Modifier.alpha(.5f),
98+
modifier = Modifier
99+
.alpha(.5f)
100+
.padding(bottom = 22.dp),
84101
)
85102
}
86-
87-
Spacer(Modifier.height(12.dp))
88-
}
89-
90-
item(key = "INSTALL_BUTTON") {
91-
AnimatedVisibility(
92-
visible = model.installations !is InstallsFetchState.Fetching,
93-
enter = fadeIn(
94-
animationSpec = tween(delayMillis = 700)
95-
) + slideInVertically(
96-
animationSpec = tween(delayMillis = 700),
97-
initialOffsetY = { it * 3 },
98-
),
99-
exit = ExitTransition.None,
100-
) {
101-
InstallButton(
102-
onClick = { showInstallerDialog = true },
103-
modifier = Modifier.fillMaxWidth(),
104-
)
105-
106-
Spacer(Modifier.height(4.dp))
107-
}
108103
}
109104

110-
val installations = (model.installations as? InstallsFetchState.Fetched)?.data
105+
val installations = (model.installations as? InstallsState.Fetched)?.data
111106
?: return@LazyColumn
112107

113108
items(installations, key = { it.packageName }) {
@@ -117,13 +112,12 @@ class HomeScreen : Screen {
117112
visible = model.supportedVersion !is DiscordVersion.None,
118113
) {
119114
InstalledItemCard(
120-
appIcon = it.icon,
121-
appName = it.name,
122-
packageName = it.packageName,
123-
discordVersion = it.version,
124-
onOpenApp = { }, // TODO: multi-install open app handler
125-
onOpenInfo = {}, // TODO: multi-install open info handler
126-
onUninstall = {}, // TODO: multi-install uninstall handler
115+
data = it,
116+
onUpdate = { showInstallerDialog = true }, // TODO: prefilled install options screen
117+
onOpenApp = { model.launchApp(it.packageName) },
118+
onOpenInfo = { model.openAppInfo(it.packageName) },
119+
onOpenPlugins = { navigator.push(PluginsScreen()) }, // TODO: install-specific plugins
120+
modifier = Modifier.fillMaxWidth()
127121
)
128122
}
129123
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.aliucord.manager.ui.screens.home
2+
3+
import androidx.compose.runtime.Immutable
4+
import androidx.compose.ui.graphics.painter.BitmapPainter
5+
import com.aliucord.manager.ui.util.DiscordVersion
6+
7+
@Immutable
8+
data class InstallData(
9+
val name: String,
10+
val packageName: String,
11+
val version: DiscordVersion,
12+
val icon: BitmapPainter,
13+
val baseUpdated: Boolean,
14+
)

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

-23
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.aliucord.manager.ui.screens.home
2+
3+
import androidx.compose.runtime.Immutable
4+
import kotlinx.collections.immutable.ImmutableList
5+
6+
@Immutable
7+
sealed interface InstallsState {
8+
data object None : InstallsState
9+
data object Error : InstallsState
10+
data object Fetching : InstallsState
11+
data class Fetched(val data: ImmutableList<InstallData>) : InstallsState
12+
}

0 commit comments

Comments
 (0)