Crash screen tweak
This commit is contained in:
@@ -4,8 +4,10 @@ import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.Build
|
||||
import android.os.StrictMode
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.hilt.work.HiltWorkerFactory
|
||||
import androidx.work.Configuration
|
||||
import androidx.work.WorkManager
|
||||
@@ -21,9 +23,10 @@ import org.acra.ktx.initAcra
|
||||
import org.acra.sender.HttpSender
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.xtimms.shirizu.core.database.ShirizuDatabase
|
||||
import org.xtimms.shirizu.core.prefs.AppSettings
|
||||
import org.xtimms.shirizu.core.prefs.KotatsuAppSettings
|
||||
import org.xtimms.shirizu.core.updates.Updater
|
||||
import org.xtimms.shirizu.crash.CrashActivity
|
||||
import org.xtimms.shirizu.crash.GlobalExceptionHandler
|
||||
import org.xtimms.shirizu.utils.lang.processLifecycleScope
|
||||
import org.xtimms.shirizu.work.WorkScheduleManager
|
||||
import javax.inject.Inject
|
||||
@@ -61,6 +64,7 @@ class App : Application(), Configuration.Provider {
|
||||
) else getPackageInfo(packageName, 0)
|
||||
}
|
||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
connectivityManager = getSystemService()!!
|
||||
|
||||
processLifecycleScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
@@ -70,8 +74,6 @@ class App : Application(), Configuration.Provider {
|
||||
}
|
||||
}
|
||||
|
||||
// GlobalExceptionHandler.initialize(applicationContext, CrashActivity::class.java)
|
||||
if (AppSettings.isACRAEnabled()) {
|
||||
initAcra {
|
||||
buildConfigClass = BuildConfig::class.java
|
||||
reportFormat = StringFormat.JSON
|
||||
@@ -93,7 +95,8 @@ class App : Application(), Configuration.Provider {
|
||||
ReportField.CUSTOM_DATA,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
GlobalExceptionHandler.initialize(applicationContext, CrashActivity::class.java)
|
||||
workScheduleManager.init()
|
||||
}
|
||||
|
||||
@@ -123,8 +126,8 @@ class App : Application(), Configuration.Provider {
|
||||
companion object {
|
||||
|
||||
lateinit var packageInfo: PackageInfo
|
||||
lateinit var connectivityManager: ConnectivityManager
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun getVersionReport(): String {
|
||||
val versionName = packageInfo.versionName
|
||||
val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
package org.xtimms.shirizu.core.screens
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.core.RepeatMode
|
||||
import androidx.compose.animation.core.VectorConverter
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
import androidx.compose.animation.core.animateValue
|
||||
import androidx.compose.animation.core.infiniteRepeatable
|
||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.absoluteOffset
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -21,20 +30,34 @@ import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import org.xtimms.shirizu.R
|
||||
import org.xtimms.shirizu.sections.stats.Size
|
||||
import org.xtimms.shirizu.ui.theme.ShirizuTheme
|
||||
import org.xtimms.shirizu.utils.composable.secondaryItemAlpha
|
||||
import org.xtimms.shirizu.utils.material.combineColors
|
||||
|
||||
@Composable
|
||||
fun InfoScreen(
|
||||
icon: ImageVector,
|
||||
headingText: String,
|
||||
headingText1: String,
|
||||
headingText2: String,
|
||||
subtitleText: String,
|
||||
acceptText: String,
|
||||
onAcceptClick: () -> Unit,
|
||||
@@ -43,6 +66,9 @@ fun InfoScreen(
|
||||
onRejectClick: (() -> Unit)? = null,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
|
||||
val localDensity = LocalDensity.current
|
||||
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
val strokeWidth = Dp.Hairline
|
||||
@@ -82,15 +108,50 @@ fun InfoScreen(
|
||||
}
|
||||
},
|
||||
) { paddingValues ->
|
||||
// Status bar scrim
|
||||
|
||||
var headerSize by remember { mutableStateOf(Size(0.dp, 0.dp)) }
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.zIndex(2f)
|
||||
.secondaryItemAlpha()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.fillMaxWidth()
|
||||
.height(paddingValues.calculateTopPadding()),
|
||||
.onGloballyPositioned {
|
||||
headerSize = Size(
|
||||
width = with(localDensity) { it.size.width.toDp() },
|
||||
height = with(localDensity) { it.size.height.toDp() }
|
||||
)
|
||||
},
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
val halfWidth = headerSize.width / 2
|
||||
val halfHeight = headerSize.height / 2
|
||||
|
||||
val starColor1 = combineColors(
|
||||
MaterialTheme.colorScheme.primaryContainer,
|
||||
MaterialTheme.colorScheme.surface,
|
||||
0.5f,
|
||||
)
|
||||
|
||||
val angleStar1 by rememberInfiniteTransition("angleStar1").animateFloat(
|
||||
label = "angleStar1",
|
||||
initialValue = -20f,
|
||||
targetValue = 20f,
|
||||
animationSpec = infiniteRepeatable(tween(5000), RepeatMode.Reverse)
|
||||
)
|
||||
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.requiredSize(256.dp)
|
||||
.absoluteOffset(
|
||||
x = halfWidth * 0.7f,
|
||||
y = -halfHeight * 0.6f
|
||||
)
|
||||
.rotate(angleStar1)
|
||||
.zIndex(-1f),
|
||||
painter = painterResource(R.drawable.shape_soft_star_1),
|
||||
tint = starColor1,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -108,10 +169,24 @@ fun InfoScreen(
|
||||
.size(48.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
val infiniteTransition by rememberInfiniteTransition("infiniteTransition").animateValue(
|
||||
label = "infiniteTransition",
|
||||
initialValue = 0,
|
||||
targetValue = 2,
|
||||
typeConverter = Int.VectorConverter,
|
||||
animationSpec = infiniteRepeatable(tween(15000), RepeatMode.Restart)
|
||||
)
|
||||
val heading = when (infiniteTransition) {
|
||||
0 -> headingText1
|
||||
1 -> headingText2
|
||||
else -> headingText2
|
||||
}
|
||||
AnimatedContent(targetState = heading, label = "heading animation") {
|
||||
Text(
|
||||
text = headingText,
|
||||
text = it,
|
||||
style = MaterialTheme.typography.headlineLarge,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = subtitleText,
|
||||
modifier = Modifier
|
||||
@@ -128,9 +203,11 @@ fun InfoScreen(
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun InfoScaffoldPreview() {
|
||||
ShirizuTheme {
|
||||
InfoScreen(
|
||||
icon = Icons.Outlined.Newspaper,
|
||||
headingText = "Heading",
|
||||
headingText1 = "Heading 1",
|
||||
headingText2 = "Heading 2",
|
||||
subtitleText = "Subtitle",
|
||||
acceptText = "Accept",
|
||||
onAcceptClick = {},
|
||||
@@ -140,3 +217,4 @@ private fun InfoScaffoldPreview() {
|
||||
Text("Hello world")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import androidx.activity.enableEdgeToEdge
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.xtimms.shirizu.LocalDarkTheme
|
||||
import org.xtimms.shirizu.LocalDynamicColorSwitch
|
||||
import org.xtimms.shirizu.LocalWindowWidthState
|
||||
import org.xtimms.shirizu.MainActivity
|
||||
import org.xtimms.shirizu.SettingsProvider
|
||||
import org.xtimms.shirizu.ui.theme.ShirizuTheme
|
||||
@@ -21,7 +22,7 @@ class CrashActivity : ComponentActivity() {
|
||||
|
||||
val exception = GlobalExceptionHandler.getThrowableFromIntent(intent)
|
||||
setContent {
|
||||
SettingsProvider {
|
||||
SettingsProvider(LocalWindowWidthState.current) {
|
||||
ShirizuTheme(
|
||||
darkTheme = LocalDarkTheme.current.isDarkTheme(),
|
||||
isDynamicColorEnabled = LocalDynamicColorSwitch.current,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.xtimms.shirizu.crash
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@@ -9,7 +10,6 @@ import androidx.compose.material.icons.outlined.BugReport
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -17,29 +17,30 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.acra.ktx.sendWithAcra
|
||||
import org.xtimms.shirizu.R
|
||||
import org.xtimms.shirizu.core.screens.InfoScreen
|
||||
import org.xtimms.shirizu.ui.theme.ShirizuTheme
|
||||
import org.xtimms.shirizu.utils.CrashLogUtil
|
||||
import org.xtimms.shirizu.utils.system.toast
|
||||
|
||||
@Composable
|
||||
fun CrashScreen(
|
||||
exception: Throwable?,
|
||||
onRestartClick: () -> Unit,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val activity = (context as? Activity)
|
||||
|
||||
InfoScreen(
|
||||
icon = Icons.Outlined.BugReport,
|
||||
headingText = stringResource(R.string.crash_screen_title),
|
||||
headingText1 = stringResource(R.string.crash_screen_title),
|
||||
headingText2 = stringResource(id = R.string.crash_screen_something_went_wrong),
|
||||
subtitleText = stringResource(R.string.crash_screen_description, stringResource(R.string.app_name)),
|
||||
acceptText = stringResource(R.string.pref_dump_crash_logs),
|
||||
acceptText = stringResource(R.string.pref_send_crash_logs),
|
||||
onAcceptClick = {
|
||||
scope.launch {
|
||||
CrashLogUtil(context).dumpLogs()
|
||||
}
|
||||
exception?.sendWithAcra()
|
||||
context.toast(context.resources.getString(R.string.crash_screen_toast))
|
||||
activity?.finishAndRemoveTask()
|
||||
},
|
||||
rejectText = stringResource(R.string.crash_screen_restart_application),
|
||||
onRejectClick = onRestartClick,
|
||||
|
||||
Reference in New Issue
Block a user