compose: onboarding: Add back microG page for required flavors

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2025-12-09 13:37:53 +08:00
parent 08b2f0421e
commit e988a9af2f
7 changed files with 228 additions and 65 deletions

View File

@@ -0,0 +1,136 @@
/*
* SPDX-FileCopyrightText: 2025 The Calyx Institute
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.aurora.store.compose.composable
import androidx.compose.foundation.layout.Arrangement
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.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.util.fastForEach
import com.aurora.extensions.browse
import com.aurora.store.R
import com.aurora.store.compose.preview.PreviewTemplate
import com.aurora.store.data.model.Link
/**
* Composable to display suggestion to install microG
* @param modifier Modifier for the composable
* @param isTOSChecked Whether the TOS checkbox is checked
* @param onInstall Callback when user requests installing microG bundle
*/
@Composable
fun MicroG(
modifier: Modifier = Modifier,
isTOSChecked: Boolean = false,
onInstall: () -> Unit = {}
) {
val context = LocalContext.current
var isChecked by rememberSaveable { mutableStateOf(isTOSChecked) }
val links = listOf(
Link(
id = 2,
title = stringResource(R.string.details_dev_website),
subtitle = stringResource(R.string.microg_website),
icon = R.drawable.ic_network,
url = "https://microG.org"
),
Link(
id = 4,
title = stringResource(R.string.privacy_policy_title),
subtitle = stringResource(R.string.microg_privacy_policy),
icon = R.drawable.ic_privacy,
url = "https://microg.org/privacy.html"
),
Link(
id = 5,
title = stringResource(R.string.menu_disclaimer),
subtitle = stringResource(R.string.microg_license_agreement),
icon = R.drawable.ic_disclaimer,
url = "https://raw.githubusercontent.com/microg/GmsCore/refs/heads/master/LICENSE"
)
)
Column(
modifier = modifier
.fillMaxSize()
.padding(
horizontal = dimensionResource(R.dimen.padding_small),
vertical = dimensionResource(R.dimen.padding_xxsmall)
),
verticalArrangement = Arrangement.SpaceBetween
) {
Column(
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_xxsmall))
) {
Text(
text = stringResource(R.string.onboarding_gms_microg),
style = MaterialTheme.typography.bodyMedium,
)
links.fastForEach { link ->
LinkListItem(
link = link,
onClick = { context.browse(link.url) },
iconTint = MaterialTheme.colorScheme.primary
)
}
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = dimensionResource(R.dimen.padding_xlarge)),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_small))
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(
dimensionResource(R.dimen.padding_small)
)
) {
Checkbox(checked = isChecked, onCheckedChange = { isChecked = !isChecked })
Text(
text = stringResource(R.string.onboarding_gms_agreement),
style = MaterialTheme.typography.bodyMedium,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
Button(onClick = onInstall, enabled = isChecked) {
Text(
text = stringResource(R.string.action_install_microG)
)
}
}
}
}
@Preview(showBackground = true)
@Composable
private fun MicroGPreview() {
PreviewTemplate {
MicroG(isTOSChecked = true)
}
}

View File

@@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2025 The Calyx Institute
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.aurora.store.compose.ui.onboarding
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.aurora.store.R
import com.aurora.store.compose.composable.MicroG
import com.aurora.store.compose.preview.PreviewTemplate
import com.aurora.store.viewmodel.onboarding.MicroGViewModel
@Composable
fun MicroGPage(viewModel: MicroGViewModel = hiltViewModel()) {
ScreenContent(
onInstall = { viewModel.downloadMicroG() }
)
}
@Composable
private fun ScreenContent(onInstall: () -> Unit = {}) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = dimensionResource(R.dimen.padding_medium))
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_medium))
) {
Column(
modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))
) {
Text(
text = stringResource(R.string.onboarding_title_gsf),
style = MaterialTheme.typography.headlineLargeEmphasized,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = stringResource(R.string.onboarding_title_gsf_desc),
style = MaterialTheme.typography.titleLarge,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
MicroG(onInstall = onInstall)
}
}
@Preview(showBackground = true)
@Composable
private fun MicroGPagePreview() {
PreviewTemplate {
ScreenContent()
}
}

View File

@@ -25,6 +25,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
@@ -36,14 +37,17 @@ import com.aurora.store.compose.composable.Logo
import com.aurora.store.compose.composable.PageIndicator
import com.aurora.store.compose.preview.PreviewTemplate
import com.aurora.store.compose.ui.onboarding.navigation.OnboardingPage
import com.aurora.store.util.FlavouredUtil
import com.aurora.store.viewmodel.onboarding.OnboardingViewModel
import kotlinx.coroutines.launch
@Composable
fun OnboardingScreen(viewModel: OnboardingViewModel = hiltViewModel()) {
val context = LocalContext.current
val pages = listOfNotNull(
OnboardingPage.WELCOME,
OnboardingPage.PERMISSIONS
OnboardingPage.PERMISSIONS,
if (FlavouredUtil.promptMicroGInstall(context)) OnboardingPage.MICRO_G else null
)
ScreenContent(
@@ -171,6 +175,7 @@ private fun ScreenContent(
when (pages[page]) {
OnboardingPage.WELCOME -> WelcomePage()
OnboardingPage.PERMISSIONS -> PermissionsPage()
OnboardingPage.MICRO_G -> MicroGPage()
}
}
}

View File

@@ -51,7 +51,7 @@ private fun PageContent(
header = {
Surface(modifier = Modifier.fillMaxWidth()) {
Column(
modifier = Modifier.padding(dimensionResource(R.dimen.padding_normal))
modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))
) {
Text(
text = stringResource(R.string.onboarding_title_permissions),

View File

@@ -102,7 +102,7 @@ private fun PageContent(onAboutAurora: () -> Unit = {}) {
stickyHeader {
Surface(modifier = Modifier.fillMaxWidth()) {
Column(
modifier = Modifier.padding(dimensionResource(R.dimen.padding_normal))
modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))
) {
Text(
text = stringResource(R.string.onboarding_title_welcome),

View File

@@ -11,4 +11,5 @@ package com.aurora.store.compose.ui.onboarding.navigation
enum class OnboardingPage {
WELCOME,
PERMISSIONS,
MICRO_G
}

View File

@@ -5,52 +5,32 @@
package com.aurora.store.viewmodel.onboarding
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.aurora.Constants.PACKAGE_NAME_GMS
import com.aurora.Constants.PACKAGE_NAME_PLAY_STORE
import com.aurora.gplayapi.data.models.PlayFile
import com.aurora.store.AuroraApp
import com.aurora.store.data.event.InstallerEvent
import com.aurora.store.data.helper.DownloadHelper
import com.aurora.store.data.room.suite.ExternalApk
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class MicroGViewModel @Inject constructor(
@ApplicationContext private val context: Context,
private val downloadHelper: DownloadHelper
) : ViewModel() {
companion object {
const val MICROG_DOWNLOAD_URL = "https://github.com/microg/GmsCore/releases/download"
const val MICROG_VERSION = "v0.3.6.244735"
const val GMS_VERSION_CODE = 244735012
const val COMPANION_VERSION_CODE = 84022612
private const val MICROG_DOWNLOAD_URL =
"https://github.com/microg/GmsCore/releases/download"
private const val MICROG_VERSION = "v0.3.6.244735"
private const val GMS_VERSION_CODE = 244735012
private const val COMPANION_VERSION_CODE = 84022612
}
private val _packageNames = MutableSharedFlow<List<String>>()
val packageNames = _packageNames.asSharedFlow()
private val _checked = MutableStateFlow(false)
val checked: StateFlow<Boolean> = _checked
val download = combine(packageNames, downloadHelper.downloadsList) { apps, list ->
list.find { d -> apps.any { it == d.packageName } }
}.stateIn(viewModelScope, SharingStarted.Eagerly, null)
val microGServiceApk = ExternalApk(
private val microGServiceApk = ExternalApk(
packageName = PACKAGE_NAME_GMS,
versionCode = GMS_VERSION_CODE.toLong(),
versionName = MICROG_VERSION,
@@ -67,7 +47,7 @@ class MicroGViewModel @Inject constructor(
)
)
val microGCompanionApk = ExternalApk(
private val microGCompanionApk = ExternalApk(
packageName = PACKAGE_NAME_PLAY_STORE,
versionCode = COMPANION_VERSION_CODE.toLong(),
versionName = MICROG_VERSION,
@@ -84,41 +64,10 @@ class MicroGViewModel @Inject constructor(
)
)
fun markAgreement(checked: Boolean) {
viewModelScope.launch {
_checked.emit(checked)
}
}
fun downloadMicroG() {
viewModelScope.launch {
try {
_packageNames.emit(listOf(PACKAGE_NAME_GMS))
if (microGServiceApk.isInstalled(context)) {
AuroraApp.events.send(InstallerEvent.Installed(PACKAGE_NAME_GMS))
} else {
downloadHelper.enqueueStandalone(microGServiceApk)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun downloadCompanion() {
viewModelScope.launch {
try {
_packageNames.emit(listOf(PACKAGE_NAME_PLAY_STORE))
if (microGCompanionApk.isInstalled(context)) {
AuroraApp.events.send(InstallerEvent.Installed(PACKAGE_NAME_PLAY_STORE))
} else {
downloadHelper.enqueueStandalone(microGCompanionApk)
}
} catch (e: Exception) {
e.printStackTrace()
}
viewModelScope.launch(Dispatchers.IO) {
downloadHelper.enqueueStandalone(microGServiceApk)
downloadHelper.enqueueStandalone(microGCompanionApk)
}
}
}