mirror of
https://github.com/geode-sdk/android-launcher.git
synced 2026-10-21 08:19:33 +00:00
error view
This commit is contained in:
4 files changed
+89
-21
No files matched your search
@@ -1,5 +1,6 @@
|
|||||||
package com.geode.launcher
|
package com.geode.launcher
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
@@ -26,6 +27,7 @@ import androidx.compose.material.icons.filled.Warning
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.FilledTonalButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
@@ -44,7 +46,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -63,7 +64,7 @@ class AltMainActivity : ComponentActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
// requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
|
||||||
val gdInstalled = GamePackageUtils.isGameInstalled(packageManager)
|
val gdInstalled = GamePackageUtils.isGameInstalled(packageManager)
|
||||||
@@ -98,12 +99,9 @@ class AltMainActivity : ComponentActivity() {
|
|||||||
CompositionLocalProvider(LocalTheme provides theme) {
|
CompositionLocalProvider(LocalTheme provides theme) {
|
||||||
GeodeLauncherTheme(theme = theme, blackBackground = backgroundOption) {
|
GeodeLauncherTheme(theme = theme, blackBackground = backgroundOption) {
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize()
|
||||||
color = Color.Transparent
|
|
||||||
) {
|
) {
|
||||||
WithWave {
|
AltMainScreen(launchViewModel)
|
||||||
AltMainScreen(launchViewModel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,11 +232,15 @@ fun LaunchProgressBody(statusInfo: LaunchStatusInfo, modifier: Modifier = Modifi
|
|||||||
if (statusInfo.progress != null) {
|
if (statusInfo.progress != null) {
|
||||||
LinearProgressIndicator(
|
LinearProgressIndicator(
|
||||||
statusInfo.progress,
|
statusInfo.progress,
|
||||||
modifier = Modifier.width(300.dp).align(Alignment.CenterHorizontally)
|
modifier = Modifier
|
||||||
|
.width(300.dp)
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
LinearProgressIndicator(
|
LinearProgressIndicator(
|
||||||
modifier = Modifier.width(300.dp).align(Alignment.CenterHorizontally)
|
modifier = Modifier
|
||||||
|
.width(300.dp)
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +251,14 @@ fun LaunchProgressBody(statusInfo: LaunchStatusInfo, modifier: Modifier = Modifi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LaunchProgressCard(uiState: LaunchViewModel.LaunchUIState, onCancel: () -> Unit, onResume: () -> Unit, modifier: Modifier = Modifier) {
|
fun LaunchProgressCard(
|
||||||
|
uiState: LaunchViewModel.LaunchUIState,
|
||||||
|
crashInfo: LoadFailureInfo?,
|
||||||
|
onCancel: () -> Unit,
|
||||||
|
onResume: () -> Unit,
|
||||||
|
onMore: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
val status = mapLaunchStatusToInfo(uiState)
|
val status = mapLaunchStatusToInfo(uiState)
|
||||||
Card(modifier = modifier) {
|
Card(modifier = modifier) {
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.padding(16.dp)) {
|
Column(verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.padding(16.dp)) {
|
||||||
@@ -260,14 +269,27 @@ fun LaunchProgressCard(uiState: LaunchViewModel.LaunchUIState, onCancel: () -> U
|
|||||||
inProgress = uiState.inProgress
|
inProgress = uiState.inProgress
|
||||||
)
|
)
|
||||||
|
|
||||||
if (uiState.reason.allowsRetry()) {
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
Button(onClick = onResume) {
|
if (uiState.reason.allowsRetry()) {
|
||||||
Icon(
|
Button(onClick = onResume) {
|
||||||
Icons.Filled.Refresh,
|
Icon(
|
||||||
contentDescription = null
|
Icons.Filled.Refresh,
|
||||||
)
|
contentDescription = null
|
||||||
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
|
)
|
||||||
Text(stringResource(R.string.launcher_cancelled_restart))
|
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
|
||||||
|
Text(stringResource(R.string.launcher_cancelled_restart))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crashInfo != null) {
|
||||||
|
FilledTonalButton(onClick = onMore) {
|
||||||
|
Icon(
|
||||||
|
painterResource(R.drawable.icon_question_mark),
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
|
||||||
|
Text(stringResource(R.string.launcher_error_more))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -314,6 +336,7 @@ fun AltMainScreen(
|
|||||||
val launchUIState by launchViewModel.uiState.collectAsState()
|
val launchUIState by launchViewModel.uiState.collectAsState()
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
var launchInSafeMode by remember { mutableStateOf(false) }
|
var launchInSafeMode by remember { mutableStateOf(false) }
|
||||||
|
var showErrorInfo by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -325,6 +348,7 @@ fun AltMainScreen(
|
|||||||
|
|
||||||
LaunchProgressCard(
|
LaunchProgressCard(
|
||||||
launchUIState,
|
launchUIState,
|
||||||
|
crashInfo = launchViewModel.currentCrashInfo(),
|
||||||
onCancel = {
|
onCancel = {
|
||||||
launchInSafeMode = false
|
launchInSafeMode = false
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
@@ -332,12 +356,17 @@ fun AltMainScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onResume = {
|
onResume = {
|
||||||
launchViewModel.loadFailure = null
|
launchViewModel.clearCrashInfo()
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
launchViewModel.beginLaunchFlow()
|
launchViewModel.beginLaunchFlow()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.padding(16.dp).offset(y = 90.dp)
|
onMore = {
|
||||||
|
showErrorInfo = true
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.offset(y = 90.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
@@ -374,4 +403,9 @@ fun AltMainScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val loadFailure = launchViewModel.currentCrashInfo()
|
||||||
|
if (showErrorInfo && loadFailure != null) {
|
||||||
|
ErrorInfoSheet(loadFailure, onDismiss = { showErrorInfo = false })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
val redirectToAlt = PreferenceUtils.get(this).getBoolean(PreferenceUtils.Key.ENABLE_REDESIGN)
|
val redirectToAlt = PreferenceUtils.get(this).getBoolean(PreferenceUtils.Key.ENABLE_REDESIGN)
|
||||||
if (redirectToAlt) {
|
if (redirectToAlt) {
|
||||||
val launchIntent = Intent(this, AltMainActivity::class.java)
|
val launchIntent = Intent(this, AltMainActivity::class.java)
|
||||||
|
launchIntent.putExtras(intent)
|
||||||
startActivity(launchIntent)
|
startActivity(launchIntent)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.takeWhile
|
import kotlinx.coroutines.flow.takeWhile
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
private const val COOLDOWN_LENGTH_MS = 1000L
|
||||||
|
|
||||||
class LaunchViewModel(private val application: Application): ViewModel() {
|
class LaunchViewModel(private val application: Application): ViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
@@ -35,7 +37,7 @@ class LaunchViewModel(private val application: Application): ViewModel() {
|
|||||||
private var readyTimer: CountDownTimer? = null
|
private var readyTimer: CountDownTimer? = null
|
||||||
|
|
||||||
private fun initReadyTimer() {
|
private fun initReadyTimer() {
|
||||||
readyTimer = object : CountDownTimer(1000, 1000) {
|
readyTimer = object : CountDownTimer(COOLDOWN_LENGTH_MS, 1000) {
|
||||||
override fun onTick(millisUntilFinished: Long) {
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
// no tick necessary
|
// no tick necessary
|
||||||
}
|
}
|
||||||
@@ -97,6 +99,22 @@ class LaunchViewModel(private val application: Application): ViewModel() {
|
|||||||
preReadyCheck()
|
preReadyCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun currentCrashInfo(): LoadFailureInfo? {
|
||||||
|
val currentState = _uiState.value
|
||||||
|
if (currentState is LaunchUIState.Cancelled && currentState.reason == LaunchCancelReason.LAST_LAUNCH_CRASHED) {
|
||||||
|
return loadFailure
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCrashInfo() {
|
||||||
|
val currentState = _uiState.value
|
||||||
|
if (currentState is LaunchUIState.Cancelled && currentState.reason == LaunchCancelReason.LAST_LAUNCH_CRASHED) {
|
||||||
|
loadFailure = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun preReadyCheck() {
|
private suspend fun preReadyCheck() {
|
||||||
if (isCancelling) {
|
if (isCancelling) {
|
||||||
// don't let the game start if cancelled
|
// don't let the game start if cancelled
|
||||||
@@ -161,6 +179,11 @@ class LaunchViewModel(private val application: Application): ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun cancelLaunch() {
|
suspend fun cancelLaunch() {
|
||||||
|
// no need to double cancel
|
||||||
|
if (_uiState.value is LaunchUIState.Cancelled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isCancelling = true
|
isCancelling = true
|
||||||
_uiState.emit(LaunchUIState.Cancelled(LaunchCancelReason.MANUAL, true))
|
_uiState.emit(LaunchUIState.Cancelled(LaunchCancelReason.MANUAL, true))
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M424,640Q424,559 438.5,523.5Q453,488 500,446Q541,410 562.5,383.5Q584,357 584,323Q584,282 556.5,255Q529,228 480,228Q429,228 402.5,259Q376,290 365,322L262,278Q283,214 339,167Q395,120 480,120Q585,120 641.5,178.5Q698,237 698,319Q698,369 676.5,404.5Q655,440 609,485Q560,532 549.5,556.5Q539,581 539,640L424,640ZM480,880Q447,880 423.5,856.5Q400,833 400,800Q400,767 423.5,743.5Q447,720 480,720Q513,720 536.5,743.5Q560,767 560,800Q560,833 536.5,856.5Q513,880 480,880Z"/>
|
||||||
|
</vector>
|
||||||
Reference in new issue
Block a user