From 44b6f1b52f9bf62eea0270c3c742779672c4f215 Mon Sep 17 00:00:00 2001 From: Zakhar Timoshenko Date: Wed, 10 Apr 2024 00:14:58 +0300 Subject: [PATCH] Crash screen tweak --- app/src/main/java/org/xtimms/shirizu/App.kt | 51 ++++---- .../xtimms/shirizu/core/screens/InfoScreen.kt | 120 +++++++++++++++--- .../org/xtimms/shirizu/crash/CrashActivity.kt | 3 +- .../org/xtimms/shirizu/crash/CrashScreen.kt | 19 +-- 4 files changed, 138 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/org/xtimms/shirizu/App.kt b/app/src/main/java/org/xtimms/shirizu/App.kt index b8d6e67..580ba02 100644 --- a/app/src/main/java/org/xtimms/shirizu/App.kt +++ b/app/src/main/java/org/xtimms/shirizu/App.kt @@ -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,30 +74,29 @@ class App : Application(), Configuration.Provider { } } - // GlobalExceptionHandler.initialize(applicationContext, CrashActivity::class.java) - if (AppSettings.isACRAEnabled()) { - initAcra { - buildConfigClass = BuildConfig::class.java - reportFormat = StringFormat.JSON - httpSender { - uri = BuildConfig.ACRA_URI - basicAuthLogin = BuildConfig.ACRA_AUTH_LOGIN - basicAuthPassword = BuildConfig.ACRA_AUTH_PASSWORD - httpMethod = HttpSender.Method.POST - } - reportContent = listOf( - ReportField.PACKAGE_NAME, - ReportField.INSTALLATION_ID, - ReportField.APP_VERSION_CODE, - ReportField.APP_VERSION_NAME, - ReportField.ANDROID_VERSION, - ReportField.PHONE_MODEL, - ReportField.STACK_TRACE, - ReportField.CRASH_CONFIGURATION, - ReportField.CUSTOM_DATA, - ) + initAcra { + buildConfigClass = BuildConfig::class.java + reportFormat = StringFormat.JSON + httpSender { + uri = BuildConfig.ACRA_URI + basicAuthLogin = BuildConfig.ACRA_AUTH_LOGIN + basicAuthPassword = BuildConfig.ACRA_AUTH_PASSWORD + httpMethod = HttpSender.Method.POST } + reportContent = listOf( + ReportField.PACKAGE_NAME, + ReportField.INSTALLATION_ID, + ReportField.APP_VERSION_CODE, + ReportField.APP_VERSION_NAME, + ReportField.ANDROID_VERSION, + ReportField.PHONE_MODEL, + ReportField.STACK_TRACE, + ReportField.CRASH_CONFIGURATION, + 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) { diff --git a/app/src/main/java/org/xtimms/shirizu/core/screens/InfoScreen.kt b/app/src/main/java/org/xtimms/shirizu/core/screens/InfoScreen.kt index 9663e50..91d9603 100644 --- a/app/src/main/java/org/xtimms/shirizu/core/screens/InfoScreen.kt +++ b/app/src/main/java/org/xtimms/shirizu/core/screens/InfoScreen.kt @@ -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, ) - Text( - text = headingText, - style = MaterialTheme.typography.headlineLarge, + 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 = it, + style = MaterialTheme.typography.headlineLarge, + ) + } Text( text = subtitleText, modifier = Modifier @@ -128,15 +203,18 @@ fun InfoScreen( @PreviewLightDark @Composable private fun InfoScaffoldPreview() { - InfoScreen( - icon = Icons.Outlined.Newspaper, - headingText = "Heading", - subtitleText = "Subtitle", - acceptText = "Accept", - onAcceptClick = {}, - rejectText = "Reject", - onRejectClick = {}, - ) { - Text("Hello world") + ShirizuTheme { + InfoScreen( + icon = Icons.Outlined.Newspaper, + headingText1 = "Heading 1", + headingText2 = "Heading 2", + subtitleText = "Subtitle", + acceptText = "Accept", + onAcceptClick = {}, + rejectText = "Reject", + onRejectClick = {}, + ) { + Text("Hello world") + } } } \ No newline at end of file diff --git a/app/src/main/java/org/xtimms/shirizu/crash/CrashActivity.kt b/app/src/main/java/org/xtimms/shirizu/crash/CrashActivity.kt index c132ba8..df951d9 100644 --- a/app/src/main/java/org/xtimms/shirizu/crash/CrashActivity.kt +++ b/app/src/main/java/org/xtimms/shirizu/crash/CrashActivity.kt @@ -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, diff --git a/app/src/main/java/org/xtimms/shirizu/crash/CrashScreen.kt b/app/src/main/java/org/xtimms/shirizu/crash/CrashScreen.kt index 01f651b..92213aa 100644 --- a/app/src/main/java/org/xtimms/shirizu/crash/CrashScreen.kt +++ b/app/src/main/java/org/xtimms/shirizu/crash/CrashScreen.kt @@ -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,