Skip to content

Commit

Permalink
[feature|optimize|doc] Support configure text field style; optimize c…
Browse files Browse the repository at this point in the history
…rash info screen; update README
  • Loading branch information
SkyD666 committed Apr 26, 2024
1 parent b753587 commit bde4beb
Show file tree
Hide file tree
Showing 35 changed files with 332 additions and 92 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
</div>




## 💡 Features

1. **Subscribe to RSS**, Update RSS, **Read** RSS
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.datastore.preferences.core.Preferences
import com.skyd.anivu.model.preference.IgnoreUpdateVersionPreference
import com.skyd.anivu.model.preference.Settings
import com.skyd.anivu.model.preference.appearance.DarkModePreference
import com.skyd.anivu.model.preference.appearance.TextFieldStylePreference
import com.skyd.anivu.model.preference.appearance.ThemePreference
import com.skyd.anivu.model.preference.appearance.feed.FeedGroupExpandPreference
import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPreference
Expand All @@ -16,6 +17,7 @@ fun Preferences.toSettings(): Settings {
theme = ThemePreference.fromPreferences(this),
darkMode = DarkModePreference.fromPreferences(this),
feedGroupExpand = FeedGroupExpandPreference.fromPreferences(this),
textFieldStyle = TextFieldStylePreference.fromPreferences(this),

// Update
ignoreUpdateVersion = IgnoreUpdateVersionPreference.fromPreferences(this),
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/skyd/anivu/model/preference/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.ui.platform.LocalContext
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.toSettings
import com.skyd.anivu.model.preference.appearance.DarkModePreference
import com.skyd.anivu.model.preference.appearance.TextFieldStylePreference
import com.skyd.anivu.model.preference.appearance.ThemePreference
import com.skyd.anivu.model.preference.appearance.feed.FeedGroupExpandPreference
import com.skyd.anivu.model.preference.behavior.article.ArticleSwipeLeftActionPreference
Expand All @@ -20,6 +21,7 @@ import com.skyd.anivu.ui.local.LocalDarkMode
import com.skyd.anivu.ui.local.LocalDeduplicateTitleInDesc
import com.skyd.anivu.ui.local.LocalFeedGroupExpand
import com.skyd.anivu.ui.local.LocalIgnoreUpdateVersion
import com.skyd.anivu.ui.local.LocalTextFieldStyle
import com.skyd.anivu.ui.local.LocalTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.map
Expand All @@ -29,6 +31,7 @@ data class Settings(
val theme: String = ThemePreference.default,
val darkMode: Int = DarkModePreference.default,
val feedGroupExpand: Boolean = FeedGroupExpandPreference.default,
val textFieldStyle: String = TextFieldStylePreference.default,
// Update
val ignoreUpdateVersion: Long = IgnoreUpdateVersionPreference.default,
// Behavior
Expand All @@ -50,6 +53,7 @@ fun SettingsProvider(
LocalTheme provides settings.theme,
LocalDarkMode provides settings.darkMode,
LocalFeedGroupExpand provides settings.feedGroupExpand,
LocalTextFieldStyle provides settings.textFieldStyle,
// Update
LocalIgnoreUpdateVersion provides settings.ignoreUpdateVersion,
// Behavior
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.skyd.anivu.model.preference.appearance

import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.skyd.anivu.R
import com.skyd.anivu.base.BasePreference
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.ext.put
import com.skyd.anivu.ui.component.AniVuTextFieldStyle
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object TextFieldStylePreference : BasePreference<String> {
private const val TEXT_FIELD_STYLE = "textFieldStyle"

val values = AniVuTextFieldStyle.entries.map { it.value }

override val default = AniVuTextFieldStyle.Normal.value

val key = stringPreferencesKey(TEXT_FIELD_STYLE)

fun put(context: Context, scope: CoroutineScope, value: String) {
scope.launch(Dispatchers.IO) {
context.dataStore.put(key, value)
}
}

override fun fromPreferences(preferences: Preferences): String = preferences[key] ?: default

fun toDisplayName(
context: Context,
value: String = context.dataStore.getOrDefault(this),
): String = when (value) {
AniVuTextFieldStyle.Normal.value -> context.getString(R.string.normal_text_field_style)
AniVuTextFieldStyle.Outlined.value -> context.getString(R.string.outlined_text_field_style)
else -> context.getString(R.string.unknown)
}
}
173 changes: 128 additions & 45 deletions app/src/main/java/com/skyd/anivu/ui/activity/CrashActivity.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,63 @@
package com.skyd.anivu.ui.activity

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Process
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.dp
import com.skyd.anivu.R
import com.skyd.anivu.config.Const.GITHUB_NEW_ISSUE_URL
import com.skyd.anivu.ext.getAppVersionCode
import com.skyd.anivu.ext.getAppVersionName
import com.skyd.anivu.ext.openBrowser
import com.skyd.anivu.ext.sp
import com.skyd.anivu.ui.component.showToast
import kotlin.system.exitProcess
import com.skyd.anivu.ext.showSnackbar
import com.skyd.anivu.model.preference.SettingsProvider
import com.skyd.anivu.ui.local.LocalDarkMode
import com.skyd.anivu.ui.local.LocalWindowSizeClass
import com.skyd.anivu.ui.theme.AniVuTheme


/**
* CrashActivity, do not extends BaseActivity
*/
class CrashActivity : AppCompatActivity() {
class CrashActivity : ComponentActivity() {
companion object {
const val CRASH_INFO = "crashInfo"

Expand All @@ -37,23 +69,11 @@ class CrashActivity : AppCompatActivity() {
}
}

private fun copyToClipboard(crashInfo: String?) {
val cm = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
cm.setPrimaryClip(ClipData.newPlainText("Exception trace stack", crashInfo))
}

private fun exitApp() {
finish()
Process.killProcess(Process.myPid())
exitProcess(1)
}

override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)

val crashInfo = intent.getStringExtra(CRASH_INFO)

val message = buildString {
append("VersionName: ").append(getAppVersionName()).append("\n")
append("VersionCode: ").append(getAppVersionCode()).append("\n")
Expand All @@ -64,31 +84,94 @@ class CrashActivity : AppCompatActivity() {
append("Crash Info: \n")
append(crashInfo)
}
MaterialAlertDialogBuilder(this)
.setIcon(R.drawable.ic_error_24)
.setTitle(getString(R.string.crashed))
.setMessage(message)
.setCancelable(false)
.setPositiveButton(getString(R.string.submit_an_issue_on_github)) { _, _ ->
copyToClipboard(message)
Uri.parse(GITHUB_NEW_ISSUE_URL).openBrowser(this)
exitApp()
}
.setNegativeButton(getString(R.string.close)) { _, _ ->
exitApp()
}
.setNeutralButton(getString(android.R.string.copy)) { _, _ ->
copyToClipboard(message)
getString(R.string.copied).showToast()
exitApp()

setContent {
CompositionLocalProvider(
LocalWindowSizeClass provides calculateWindowSizeClass(this)
) {
SettingsProvider {
AniVuTheme(darkTheme = LocalDarkMode.current) {
CrashScreen(
message = message,
onReport = {
Uri.parse(GITHUB_NEW_ISSUE_URL).openBrowser(this)
}
)
}
}
}
.show()
.apply {
window?.decorView?.findViewById<TextView>(android.R.id.message)?.apply {
setTextIsSelectable(true)
textSize = 3.5f.sp
}
}
}

@Composable
private fun CrashScreen(
message: String,
onReport: () -> Unit,
) {
val snackbarHostState = remember { SnackbarHostState() }
val context = LocalContext.current
val scope = rememberCoroutineScope()
val clipboardManager = LocalClipboardManager.current

Scaffold(
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
) {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(it)
.padding(20.dp)
) {
Spacer(modifier = Modifier.height(40.dp))
Icon(
modifier = Modifier.size(40.dp),
imageVector = Icons.Default.BugReport,
contentDescription = null,
)

Spacer(modifier = Modifier.height(30.dp))
Text(
text = stringResource(id = R.string.crashed),
style = MaterialTheme.typography.headlineLarge,
)

Spacer(modifier = Modifier.height(30.dp))
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
TextButton(onClick = {
copyToClipboard(message, clipboardManager)
snackbarHostState.showSnackbar(
scope = scope,
message = context.getString(R.string.copied),
)
}) {
Text(text = stringResource(id = R.string.crash_screen_copy_crash_log))
}

Spacer(modifier = Modifier.width(12.dp))

Button(onClick = {
copyToClipboard(message, clipboardManager)
onReport()
}) {
Text(text = stringResource(id = R.string.submit_an_issue_on_github))
}
}
setFinishOnTouchOutside(false)

Spacer(modifier = Modifier.height(20.dp))
Text(
text = stringResource(R.string.crash_screen_crash_log),
style = MaterialTheme.typography.titleLarge,
)

Spacer(modifier = Modifier.height(10.dp))
SelectionContainer {
Text(text = message, style = MaterialTheme.typography.bodyMedium)
}
}
}
}

private fun copyToClipboard(text: String, clipboardManager: ClipboardManager) {
clipboardManager.setText(AnnotatedString(text))
}
Loading

0 comments on commit bde4beb

Please sign in to comment.