make crashviewmodel abstract

This commit is contained in:
Chloe committed 2026-02-24 15:27:05 -07:00
1 parent c404f977e5
commit 6d5de931fc
4 files changed
+108 -72

No files matched your search

@@ -0,0 +1,68 @@
package com.geode.launcher.log
import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.io.File
abstract class BaseDirectoryViewModel<T>(protected val baseDirectory: File) : ViewModel() {
private val _lineState = mutableStateListOf<T>()
val lineState = _lineState
private val _isLoading = MutableStateFlow(false)
val isLoading = _isLoading.asStateFlow()
private var logJob: Job? = null
abstract fun getFileList(): List<T>
open fun clearAllFiles() {
logJob?.cancel()
viewModelScope.launch(Dispatchers.IO) {
if (baseDirectory.exists()) {
val files = baseDirectory.listFiles()
files?.forEach {
it.delete()
}
}
}
_lineState.clear()
}
private fun loadLogs() {
_isLoading.value = true
logJob?.cancel()
logJob = viewModelScope.launch(Dispatchers.IO) {
val lines = getFileList()
_lineState.clear()
_lineState.addAll(lines)
_isLoading.value = false
logJob = null
}
}
fun removeFile(filename: String) {
logJob?.cancel()
val crashPath = File(baseDirectory, filename)
if (crashPath.exists()) {
crashPath.delete()
loadLogs()
}
}
init {
loadLogs()
}
}
@@ -1,17 +1,12 @@
package com.geode.launcher.log
import android.app.Application
import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.geode.launcher.utils.LaunchUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.io.File
import kotlin.time.ExperimentalTime
@@ -22,33 +17,23 @@ data class CrashDump @OptIn(ExperimentalTime::class) constructor(
val lastModified: Instant
)
class CrashViewModel(private val application: Application) : ViewModel() {
class CrashViewModel(crashDirectory: File) : BaseDirectoryViewModel<CrashDump>(crashDirectory) {
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
initializer {
val application = this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as Application
val crashDirectory = LaunchUtils.getCrashDirectory(application)
CrashViewModel(
application = application
)
CrashViewModel(crashDirectory)
}
}
}
private val _lineState = mutableStateListOf<CrashDump>()
val lineState = _lineState
private val _isLoading = MutableStateFlow(false)
val isLoading = _isLoading.asStateFlow()
private var failedToLoad = false
private var logJob: Job? = null
var hasIndicator = false
private fun getCrashList(): List<CrashDump> {
val crashDirectory = LaunchUtils.getCrashDirectory(application)
override fun getFileList(): List<CrashDump> {
val crashDirectory = baseDirectory
if (!crashDirectory.exists()) {
return emptyList()
}
@@ -72,8 +57,7 @@ class CrashViewModel(private val application: Application) : ViewModel() {
fun clearIndicator() {
viewModelScope.launch(Dispatchers.IO) {
val crashDirectory = LaunchUtils.getCrashDirectory(application)
File(crashDirectory, LaunchUtils.CRASH_INDICATOR_NAME).delete()
File(baseDirectory, LaunchUtils.CRASH_INDICATOR_NAME).delete()
hasIndicator = false
}
@@ -81,56 +65,14 @@ class CrashViewModel(private val application: Application) : ViewModel() {
fun createIndicator() {
viewModelScope.launch(Dispatchers.IO) {
val crashDirectory = LaunchUtils.getCrashDirectory(application)
File(crashDirectory, LaunchUtils.CRASH_INDICATOR_NAME).createNewFile()
File(baseDirectory, LaunchUtils.CRASH_INDICATOR_NAME).createNewFile()
hasIndicator = true
}
}
fun clearCrashes() {
logJob?.cancel()
viewModelScope.launch(Dispatchers.IO) {
val crashDirectory = LaunchUtils.getCrashDirectory(application)
if (crashDirectory.exists()) {
val files = crashDirectory.listFiles()
files?.forEach {
it.delete()
}
}
}
_lineState.clear()
}
private fun loadLogs() {
_isLoading.value = true
logJob?.cancel()
logJob = viewModelScope.launch(Dispatchers.IO) {
val lines = getCrashList()
_lineState.clear()
_lineState.addAll(lines)
_isLoading.value = false
logJob = null
}
}
fun removeCrash(filename: String) {
logJob?.cancel()
val crashPath = File(LaunchUtils.getCrashDirectory(application), filename)
if (crashPath.exists()) {
crashPath.delete()
loadLogs()
}
}
init {
loadLogs()
override fun clearAllFiles() {
super.clearAllFiles()
hasIndicator = false
}
}
@@ -169,7 +169,7 @@ fun CrashCard(crashDump: CrashDump, crashViewModel: CrashViewModel, modifier: Mo
}
IconButton(onClick = {
crashViewModel.removeCrash(crashDump.filename)
crashViewModel.removeFile(crashDump.filename)
}) {
Icon(
painterResource(R.drawable.icon_delete),
@@ -228,14 +228,13 @@ fun CrashLogsScreen(
text = {
Text(stringResource(R.string.application_logs_delete))
}, onClick = {
crashViewModel.clearCrashes()
crashViewModel.clearAllFiles()
showMoreOptions = false
}
)
val developerMode by PreferenceUtils.useBooleanPreference(PreferenceUtils.Key.DEVELOPER_MODE)
if (developerMode) {
if (crashViewModel.hasIndicator) {
DropdownMenuItem(
leadingIcon = {
@@ -463,6 +463,33 @@ fun GameplaySettingsGroup() {
preferenceKey = PreferenceUtils.Key.LIMIT_FRAME_RATE,
maxFrameRate = maxFrameRate
)
var showSafeModeDialog by remember { mutableStateOf(false) }
OptionsButton(
title = stringResource(R.string.preference_launch_safe_mode),
icon = {
Icon(
painterResource(R.drawable.icon_shield),
contentDescription = null
)
}
) {
showSafeModeDialog = true
}
if (showSafeModeDialog) {
SafeModeDialog(onDismiss = {
showSafeModeDialog = false
}) {
val launchIntent = Intent(context, MainActivity::class.java).apply {
// hardcode it, why not
action = Intent.ACTION_VIEW
data = "geode-launcher://main/launch?safe-mode=true".toUri()
}
context.startActivity(launchIntent)
}
}
}
}