Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/MainApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package com.paulcoding.hviewer

import android.app.Application
import android.content.Context
import com.paulcoding.hviewer.helper.CrashHandler
import com.paulcoding.hviewer.helper.setupPaths
import com.tencent.mmkv.MMKV

class MainApp : Application() {
override fun onCreate() {
CrashHandler.install()
super.onCreate()
appContext = this
MMKV.initialize(this)
Expand Down
42 changes: 42 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/helper/CrashHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.paulcoding.hviewer.helper

import com.paulcoding.hviewer.MainApp.Companion.appContext
import java.io.File
import java.io.PrintWriter

// Reference: https://github.com/FooIbar/EhViewer/blob/main/app/src/main/kotlin/com/hippo/ehviewer/util/CrashHandler.kt
object CrashHandler {
fun install() {
val handler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { t, e ->
runCatching { saveCrashLog(e) }
handler?.uncaughtException(t, e)
}
}

private fun getThrowableInfo(t: Throwable, writer: PrintWriter) {
t.printStackTrace(writer)
var cause = t.cause
while (cause != null) {
cause.printStackTrace(writer)
cause = cause.cause
}
}

private fun saveCrashLog(e: Throwable) {
val nowString = System.currentTimeMillis()
val fileName = "crash-$nowString.log"
val file = File(appContext.crashLogDir, fileName)

runCatching {
file.printWriter().use { writer ->
writer.write("======== CrashInfo ========\n")
getThrowableInfo(e, writer)
writer.write("\n")
}
}.onFailure {
log(it)
file.delete()
}
}
}
13 changes: 9 additions & 4 deletions app/src/main/java/com/paulcoding/hviewer/helper/File.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,33 @@ import java.io.File
import java.io.FileOutputStream

const val SCRIPTS_DIR = "scripts"
const val CRASH_LOG_DIR = "crash_logs"
const val CONFIG_FILE = "config.json"

val Context.scriptsDir
get() = File(filesDir, SCRIPTS_DIR)

val Context.crashLogDir
get() = File(filesDir, CRASH_LOG_DIR)

val Context.configFile
get() = File(scriptsDir, CONFIG_FILE)

fun Context.setupPaths() {
scriptsDir.mkdir()
crashLogDir.mkdir()
}

fun Context.writeFile(data: String, fileName: String): File {
val file = File(scriptsDir, fileName)
fun Context.writeFile(data: String, fileName: String, fileDir: File = scriptsDir): File {
val file = File(fileDir, fileName)
FileOutputStream(file).use { fos ->
fos.write(data.toByteArray())
}
return file
}

fun Context.readFile(fileName: String): String {
val file = File(scriptsDir, fileName)
fun Context.readFile(fileName: String, fileDir: File = scriptsDir): String {
val file = File(fileDir, fileName)

file.bufferedReader().use { reader ->
return reader.readText()
Expand Down
104 changes: 104 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/ui/icon/BugReport.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.paulcoding.hviewer.ui.icon

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.unit.dp

public val BugReport: ImageVector
get() {
if (_Bug_report != null) {
return _Bug_report!!
}
_Bug_report = ImageVector.Builder(
name = "Bug_report",
defaultWidth = 24.dp,
defaultHeight = 24.dp,
viewportWidth = 960f,
viewportHeight = 960f
).apply {
path(
fill = SolidColor(Color.Black),
fillAlpha = 1.0f,
stroke = null,
strokeAlpha = 1.0f,
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt,
strokeLineJoin = StrokeJoin.Miter,
strokeLineMiter = 1.0f,
pathFillType = PathFillType.NonZero
) {
moveTo(480f, 760f)
quadToRelative(66f, 0f, 113f, -47f)
reflectiveQuadToRelative(47f, -113f)
verticalLineToRelative(-160f)
quadToRelative(0f, -66f, -47f, -113f)
reflectiveQuadToRelative(-113f, -47f)
reflectiveQuadToRelative(-113f, 47f)
reflectiveQuadToRelative(-47f, 113f)
verticalLineToRelative(160f)
quadToRelative(0f, 66f, 47f, 113f)
reflectiveQuadToRelative(113f, 47f)
moveToRelative(-80f, -120f)
horizontalLineToRelative(160f)
verticalLineToRelative(-80f)
horizontalLineTo(400f)
close()
moveToRelative(0f, -160f)
horizontalLineToRelative(160f)
verticalLineToRelative(-80f)
horizontalLineTo(400f)
close()
moveToRelative(80f, 360f)
quadToRelative(-65f, 0f, -120.5f, -32f)
reflectiveQuadTo(272f, 720f)
horizontalLineTo(160f)
verticalLineToRelative(-80f)
horizontalLineToRelative(84f)
quadToRelative(-3f, -20f, -3.5f, -40f)
reflectiveQuadToRelative(-0.5f, -40f)
horizontalLineToRelative(-80f)
verticalLineToRelative(-80f)
horizontalLineToRelative(80f)
quadToRelative(0f, -20f, 0.5f, -40f)
reflectiveQuadToRelative(3.5f, -40f)
horizontalLineToRelative(-84f)
verticalLineToRelative(-80f)
horizontalLineToRelative(112f)
quadToRelative(14f, -23f, 31.5f, -43f)
reflectiveQuadToRelative(40.5f, -35f)
lineToRelative(-64f, -66f)
lineToRelative(56f, -56f)
lineToRelative(86f, 86f)
quadToRelative(28f, -9f, 57f, -9f)
reflectiveQuadToRelative(57f, 9f)
lineToRelative(88f, -86f)
lineToRelative(56f, 56f)
lineToRelative(-66f, 66f)
quadToRelative(23f, 15f, 41.5f, 34.5f)
reflectiveQuadTo(688f, 320f)
horizontalLineToRelative(112f)
verticalLineToRelative(80f)
horizontalLineToRelative(-84f)
quadToRelative(3f, 20f, 3.5f, 40f)
reflectiveQuadToRelative(0.5f, 40f)
horizontalLineToRelative(80f)
verticalLineToRelative(80f)
horizontalLineToRelative(-80f)
quadToRelative(0f, 20f, -0.5f, 40f)
reflectiveQuadToRelative(-3.5f, 40f)
horizontalLineToRelative(84f)
verticalLineToRelative(80f)
horizontalLineTo(688f)
quadToRelative(-32f, 56f, -87.5f, 88f)
reflectiveQuadTo(480f, 840f)
}
}.build()
return _Bug_report!!
}

private var _Bug_report: ImageVector? = null
17 changes: 13 additions & 4 deletions app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ fun AppEntry() {
navController.navigate(Route.FAVORITE)
},
navToListScript = {
navController.navigate(Route.LIST_SCRIPT)
navController.navigate(Route.LIST_SCRIPT + "/script")
},
navToListCrashLog = {
navController.navigate(Route.LIST_SCRIPT + "/crash_log")
},
goBack = { navController.popBackStack() })
}
Expand Down Expand Up @@ -114,18 +117,24 @@ fun AppEntry() {
goBack = { navController.popBackStack() }
)
}
animatedComposable(Route.LIST_SCRIPT) {
animatedComposable(Route.LIST_SCRIPT + "/{type}") { backStackEntry ->
val type = backStackEntry.arguments?.getString("type")!!

ListScriptPage(
appViewModel = appViewModel,
type = type,
goBack = { navController.popBackStack() },
navToEditor = {
navController.navigate(Route.EDITOR + "/$it")
navController.navigate(Route.EDITOR + "/$type" + "/$it")
})
}
animatedComposable(Route.EDITOR + "/{scriptFile}") { backStackEntry ->
animatedComposable(Route.EDITOR + "/{type}" + "/{scriptFile}") { backStackEntry ->
val type = backStackEntry.arguments?.getString("type")!!
val scriptFile = backStackEntry.arguments?.getString("scriptFile")!!

EditorPage(
appViewModel = appViewModel,
type = type,
scriptFile = scriptFile,
goBack = { navController.popBackStack() })
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.paulcoding.hviewer.MainApp.Companion.appContext
import com.paulcoding.hviewer.database.DatabaseProvider
import com.paulcoding.hviewer.helper.crashLogDir
import com.paulcoding.hviewer.helper.scriptsDir
import com.paulcoding.hviewer.model.PostItem
import com.paulcoding.hviewer.model.SiteConfig
Expand All @@ -14,9 +15,11 @@ import kotlinx.coroutines.launch
import java.io.File

class AppViewModel : ViewModel() {
private val scriptsDir = appContext.scriptsDir
val listScriptFiles: List<File>
get() = scriptsDir.listFiles()?.toList() ?: listOf()
get() = appContext.scriptsDir.listFiles()?.toList() ?: listOf()

val listCrashLogFiles: List<File>
get() = appContext.crashLogDir.listFiles()?.toList() ?: listOf()

private var _stateFlow = MutableStateFlow(UiState())
val stateFlow = _stateFlow.asStateFlow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import io.github.rosemoe.sora.widget.CodeEditor

data class CodeEditorState(
var editor: CodeEditor? = null,
val initialContent: Content = Content()
val initialContent: Content = Content(),
val isEditable: Boolean = true,
) {
var content by mutableStateOf(initialContent)
var editable by mutableStateOf(isEditable)
}

private fun setCodeEditorFactory(
Expand All @@ -26,6 +28,7 @@ private fun setCodeEditorFactory(
val editor = CodeEditor(context)
editor.apply {
setText(state.content)
editor.editable = state.editable
}
state.editor = editor
return editor
Expand Down Expand Up @@ -54,9 +57,11 @@ fun CodeEditor(

@Composable
fun rememberCodeEditorState(
initialContent: Content = Content()
initialContent: Content = Content(),
editable: Boolean = true,
) = remember {
CodeEditorState(
initialContent = initialContent
initialContent = initialContent,
isEditable = editable,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import com.paulcoding.hviewer.helper.crashLogDir
import com.paulcoding.hviewer.helper.makeToast
import com.paulcoding.hviewer.helper.readFile
import com.paulcoding.hviewer.helper.scriptsDir
import com.paulcoding.hviewer.helper.writeFile
import com.paulcoding.hviewer.network.Github
import com.paulcoding.hviewer.ui.component.HBackIcon
Expand All @@ -22,10 +24,21 @@ import io.github.rosemoe.sora.text.Content

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditorPage(appViewModel: AppViewModel, goBack: () -> Boolean, scriptFile: String) {
fun EditorPage(
appViewModel: AppViewModel,
type: String,
goBack: () -> Boolean,
scriptFile: String
) {
val context = LocalContext.current
val script = context.readFile(scriptFile)
val state = rememberCodeEditorState(initialContent = Content(script))
val dir = when (type) {
"script" -> context.scriptsDir
"crash_log" -> context.crashLogDir
else -> return makeToast("Unknown type $type")
}
val editable = type == "script"
val script = context.readFile(scriptFile, dir)
val state = rememberCodeEditorState(initialContent = Content(script), editable = editable)
val localSoftwareKeyboardController = LocalSoftwareKeyboardController.current

Scaffold(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,43 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.paulcoding.hviewer.helper.makeToast
import com.paulcoding.hviewer.ui.component.HBackIcon
import com.paulcoding.hviewer.ui.icon.BugReport
import com.paulcoding.hviewer.ui.icon.Javascript
import com.paulcoding.hviewer.ui.page.AppViewModel

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ListScriptPage(
appViewModel: AppViewModel,
type: String,
goBack: () -> Unit,
navToEditor: (String) -> Unit
navToEditor: (String) -> Unit,
) {

val listFiles = when (type) {
"script" -> appViewModel.listScriptFiles
"crash_log" -> appViewModel.listCrashLogFiles
else -> emptyList()
}

val title = when (type) {
"script" -> "List Script"
"crash_log" -> "List Crash Log"
else -> ""
}

val fileIcon = when (type) {
"script" -> Javascript
"crash_log" -> BugReport
else -> return makeToast("Unknown type $type")
}

Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(title = { Text(text = "List Script") },
TopAppBar(title = { Text(text = title) },
navigationIcon = {
HBackIcon {
goBack()
Expand All @@ -45,7 +66,7 @@ fun ListScriptPage(
.padding(paddings)
.fillMaxSize()
) {
items(appViewModel.listScriptFiles, key = { it.name }) {
items(listFiles, key = { it.name }) {
Row(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -56,7 +77,7 @@ fun ListScriptPage(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
Javascript,
fileIcon,
contentDescription = "Javascript",
modifier = Modifier.size(32.dp),
)
Expand Down
Loading
Loading