diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 97d469162..677a36879 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -222,6 +222,11 @@
android:name=".ui.about.AboutActivity"
android:enableOnBackInvokedCallback="true"
android:launchMode="singleTask" />
+
file.isFile }
+ ?.maxByOrNull { it.name }
+ file?.readText()
+ }.getOrNull()
}
/**
diff --git a/app/src/main/java/io/legado/app/ui/about/CrashReportActivity.kt b/app/src/main/java/io/legado/app/ui/about/CrashReportActivity.kt
new file mode 100644
index 000000000..b00ea97d5
--- /dev/null
+++ b/app/src/main/java/io/legado/app/ui/about/CrashReportActivity.kt
@@ -0,0 +1,35 @@
+package io.legado.app.ui.about
+
+import android.content.Intent
+import androidx.compose.runtime.Composable
+import io.legado.app.base.BaseComposeActivity
+import io.legado.app.help.CrashHandler
+import io.legado.app.ui.main.MainActivity
+import io.legado.app.utils.sendToClip
+
+class CrashReportActivity : BaseComposeActivity() {
+
+ private val crashText: String by lazy {
+ CrashHandler.readCrashLog(
+ intent.getStringExtra(CrashHandler.EXTRA_CRASH_FILE_NAME)
+ ).orEmpty()
+ }
+
+ @Composable
+ override fun Content() {
+ CrashReportScreen(
+ errorText = crashText,
+ onCopy = { sendToClip(crashText) },
+ onRestart = { restartApp() },
+ onClose = { finish() }
+ )
+ }
+
+ private fun restartApp() {
+ startActivity(
+ Intent(this, MainActivity::class.java)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ )
+ finish()
+ }
+}
diff --git a/app/src/main/java/io/legado/app/ui/about/CrashReportScreen.kt b/app/src/main/java/io/legado/app/ui/about/CrashReportScreen.kt
new file mode 100644
index 000000000..b532985d4
--- /dev/null
+++ b/app/src/main/java/io/legado/app/ui/about/CrashReportScreen.kt
@@ -0,0 +1,105 @@
+package io.legado.app.ui.about
+
+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.foundation.rememberScrollState
+import androidx.compose.foundation.text.selection.SelectionContainer
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Button
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.unit.dp
+import io.legado.app.R
+import io.legado.app.ui.theme.LegadoTheme
+import io.legado.app.ui.widget.components.AppScaffold
+import io.legado.app.ui.widget.components.icon.AppIcons
+import io.legado.app.ui.widget.components.text.AppText
+import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
+import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
+import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
+
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
+@Composable
+fun CrashReportScreen(
+ errorText: String,
+ onCopy: () -> Unit,
+ onRestart: () -> Unit,
+ onClose: () -> Unit
+) {
+ val scrollBehavior = GlassTopAppBarDefaults.defaultScrollBehavior()
+ val displayText = errorText.ifBlank {
+ stringResource(R.string.crash_report_empty)
+ }
+
+ AppScaffold(
+ modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
+ topBar = {
+ GlassMediumFlexibleTopAppBar(
+ title = stringResource(R.string.crash_report),
+ navigationIcon = {
+ TopBarNavigationButton(
+ onClick = onClose,
+ imageVector = AppIcons.Close
+ )
+ },
+ scrollBehavior = scrollBehavior
+ )
+ }
+ ) { padding ->
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(padding)
+ .padding(horizontal = 16.dp, vertical = 12.dp),
+ verticalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ AppText(
+ text = stringResource(R.string.crash_report_message),
+ style = LegadoTheme.typography.bodyMedium
+ )
+
+ SelectionContainer(
+ modifier = Modifier
+ .weight(1f)
+ .fillMaxWidth()
+ .verticalScroll(rememberScrollState())
+ ) {
+ Text(
+ text = displayText,
+ style = LegadoTheme.typography.bodySmall,
+ fontFamily = FontFamily.Monospace
+ )
+ }
+
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(12.dp)
+ ) {
+ OutlinedButton(
+ onClick = onRestart,
+ modifier = Modifier.weight(1f)
+ ) {
+ Text(text = stringResource(R.string.restart_app))
+ }
+ Button(
+ onClick = onCopy,
+ enabled = errorText.isNotBlank(),
+ modifier = Modifier.weight(1f)
+ ) {
+ Text(text = stringResource(R.string.copy_text))
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index fe10a4ab5..3726544d5 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -1209,6 +1209,10 @@
按键长按翻页
保存日志
创建堆转储
+ 崩溃报告
+ 应用发生崩溃。报告问题时,请复制以下错误信息。
+ 未找到崩溃信息。
+ 重启应用
当应用发生OOM崩溃时保存堆转储
记录堆转储
字重
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 6f42b0a29..bd067e4b3 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -1178,6 +1178,10 @@
按键长按翻页
保存日志
创建堆转储
+ 崩潰報告
+ 應用程式發生崩潰。回報問題時,請複製以下錯誤資訊。
+ 找不到崩潰資訊。
+ 重新啟動應用程式
当应用发生OOM崩溃时保存堆转储
记录堆转储
字重
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index f5fced0c9..f99edc6a2 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -1181,6 +1181,10 @@
按键长按翻页
保存日志
创建堆转储
+ 崩潰報告
+ 應用程式發生崩潰。回報問題時,請複製以下錯誤資訊。
+ 找不到崩潰資訊。
+ 重新啟動應用程式
当应用发生OOM崩溃时保存堆转储
记录堆转储
字重
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4651f6df6..1aaa51039 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1212,6 +1212,10 @@
Press and Hold the Key to Turn Page
Save logs
Create Heap Dump
+ Crash report
+ The app crashed. Copy the error information below when reporting the issue.
+ No crash information found.
+ Restart app
Saving a heap dump when the application crashes by OOM
Capture heap dump
N/B/L