diff --git a/app/build.gradle b/app/build.gradle index c3051a005..1758e3e60 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -187,7 +187,7 @@ dependencies { // https://developer.android.com/jetpack/androidx/releases/compose-material implementation "androidx.compose.material:material" implementation "androidx.compose.material:material-icons-extended" - debugImplementation "androidx.compose.ui:ui-tooling" + implementation "androidx.compose.ui:ui-tooling" implementation "androidx.compose.ui:ui-tooling-preview" androidTestImplementation "androidx.compose.ui:ui-test-junit4" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5ddc99ab..5d6ebf6d1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> - + @@ -34,6 +34,11 @@ + + + v.setPadding(0, 0, 0, 0) + insets + } + val errorMessage: String = intent.getStringExtra(ERROR_REPORT_KEY).toString() + + setContent { + SettingsProvider { + AppTheme(useDarkTheme = LocalDarkTheme.current.isDarkTheme()) { + val clipboardManager = LocalClipboardManager.current + val appVersion = getCurrentVersion().toString() + val deviceModel = "${Build.MANUFACTURER} ${Build.MODEL}" + val androidVersion = + "Android ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})" + + val errorReport = + "Version: $appVersion\nDevice: $deviceModel\nSystem: $androidVersion\n\nStack trace: \n\n$errorMessage" + + CrashReportPage(text = errorReport) { + clipboardManager.setText(AnnotatedString(errorReport)) + } + } + } + } + } + + override fun onDestroy() { + super.onDestroy() + if (isFinishing) finishAffinity() + } + + companion object { + const val ERROR_REPORT_KEY = "error_stack_trace" + } + +} + + +@OptIn(ExperimentalTextApi::class) +@Composable +@Preview(apiLevel = 33) +fun CrashReportPage( + text: String = "Version: 0.9.11\n" + + "Model: Google Pixel 6 Pro\n" + "System: Android 13 (API 33)\n\n" + + "Stack trace: \n" + + "\nFATAL EXCEPTION: main\n" + + "Process: me.ash.reader, PID: 29184\n" + + "java.lang.IllegalArgumentException: performMeasureAndLayout called during measure layout\n" + + "\tat androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:133)\n" + + "\tat androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:34)\n" + + "\tat androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:15)\n" + + "\tat android.view.View.draw(View.java:24193)\n" + + "\tat android.view.View.updateDisplayListIfDirty(View.java:23056)\n" + + "\tat android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4550)\n", + onClick: () -> Unit = {} +) { + val context = LocalContext.current + val openLinkPreference = LocalOpenLink.current + val openLinkSpecificBrowserPreference = LocalOpenLinkSpecificBrowser.current + + Scaffold( + modifier = Modifier.fillMaxSize(), + containerColor = MaterialTheme.colorScheme.surfaceContainer, + bottomBar = {}) { + Column( + modifier = Modifier + .padding(it) + .verticalScroll(rememberScrollState()) + ) { + Icon( + imageVector = Icons.Outlined.BugReport, + contentDescription = null, + modifier = Modifier + .padding(top = 24.dp) + .padding(horizontal = 16.dp) + .size(64.dp), + tint = MaterialTheme.colorScheme.surfaceTint + ) + + Text( + text = stringResource(R.string.unexpected_error_title), + style = MaterialTheme.typography.headlineLarge, + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, top = 12.dp) + ) + Spacer(modifier = Modifier.height(24.dp)) + + + val hyperLinkText = stringResource(R.string.submit_bug_report) + val msg = stringResource(R.string.unexpected_error_msg).format(hyperLinkText) + + val annotatedString = buildAnnotatedString { + append(msg.format(hyperLinkText)) + val startIndex = msg.indexOf(hyperLinkText) + val endIndex = startIndex + hyperLinkText.length + addUrlAnnotation( + UrlAnnotation("https://github.com/Ashinch/ReadYou/issues/new?assignees=&labels=bug&projects=&template=bug_report.md&title="), + start = startIndex, + end = endIndex + ) + addStyle( + SpanStyle( + color = MaterialTheme.colorScheme.primary, + textDecoration = TextDecoration.Underline, + ), start = startIndex, + end = endIndex + ) + } + + ClickableText( + text = annotatedString, + style = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onSurface), + modifier = Modifier.padding(horizontal = 16.dp), + onClick = { index -> + annotatedString.getUrlAnnotations(index, index).firstOrNull()?.let { range -> + context.openURL( + url = range.item.url, + openLink = openLinkPreference, + specificBrowser = openLinkSpecificBrowserPreference + ) + } + } + ) + + Row( + modifier = Modifier + .padding(vertical = 16.dp, horizontal = 16.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + Spacer(modifier = Modifier.width(12.dp)) + Button( + onClick = onClick, + modifier = Modifier + .padding(), + contentPadding = ButtonDefaults.ButtonWithIconContentPadding + ) { + Icon( + imageVector = Icons.Rounded.ContentCopy, + contentDescription = null, + modifier = Modifier.size(ButtonDefaults.IconSize) + ) + Spacer(modifier = Modifier.width(8.dp)) + Text(text = stringResource(R.string.copy_error_report)) + } + } + + + Surface( + shape = MaterialTheme.shapes.large, + color = MaterialTheme.colorScheme.surface, + modifier = Modifier.padding(12.dp) + ) { + Column { + Text( + text = text, + style = MaterialTheme.typography.bodyMedium.copy( + fontFamily = FontFamily.Monospace + ), + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier + .padding(16.dp) + .fillMaxWidth() + ) + } + + } + + } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 472c9b750..84a71d19c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -408,4 +408,8 @@ Grey out articles All read Read, excluding starred + Oops! Something went wrong… + Copy error report + submit a bug report on GitHub + The app encountered an unexpected error and had to close.\n\nTo help us identify and fix this issue quickly, you can %1$s with the error stack trace below.