feat(app/settings): message logger export & clear

This commit is contained in:
rhunk
2023-11-22 20:41:03 +01:00
parent 780d5b9858
commit 15c56b705f
5 changed files with 159 additions and 31 deletions

View File

@@ -21,8 +21,10 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import me.rhunk.snapenhance.bridge.BridgeService
import me.rhunk.snapenhance.common.BuildConfig
import me.rhunk.snapenhance.common.bridge.types.BridgeFileType
import me.rhunk.snapenhance.common.bridge.wrapper.LocaleWrapper
import me.rhunk.snapenhance.common.bridge.wrapper.MappingsWrapper
import me.rhunk.snapenhance.common.bridge.wrapper.MessageLoggerWrapper
import me.rhunk.snapenhance.common.config.ModConfig
import me.rhunk.snapenhance.e2ee.E2EEImplementation
import me.rhunk.snapenhance.messaging.ModDatabase
@@ -67,6 +69,7 @@ class RemoteSideContext(
val scriptManager = RemoteScriptManager(this)
val settingsOverlay = SettingsOverlay(this)
val e2eeImplementation = E2EEImplementation(this)
val messageLogger by lazy { MessageLoggerWrapper(androidContext.getDatabasePath(BridgeFileType.MESSAGE_LOGGER_DATABASE.fileName)) }
//used to load bitmoji selfies and download previews
val imageLoader by lazy {
@@ -104,6 +107,7 @@ class RemoteSideContext(
modDatabase.init()
streaksReminder.init()
scriptManager.init()
messageLogger.init()
}.onFailure {
log.error("Failed to load RemoteSideContext", it)
}

View File

@@ -20,7 +20,6 @@ import me.rhunk.snapenhance.download.DownloadProcessor
import kotlin.system.measureTimeMillis
class BridgeService : Service() {
private lateinit var messageLoggerWrapper: MessageLoggerWrapper
private lateinit var remoteSideContext: RemoteSideContext
lateinit var syncCallback: SyncCallback
var messagingBridge: MessagingBridge? = null
@@ -38,7 +37,6 @@ class BridgeService : Service() {
remoteSideContext.apply {
bridgeService = this@BridgeService
}
messageLoggerWrapper = MessageLoggerWrapper(getDatabasePath(BridgeFileType.MESSAGE_LOGGER_DATABASE.fileName)).also { it.init() }
return BridgeBinder()
}
@@ -180,7 +178,7 @@ class BridgeService : Service() {
override fun getScriptingInterface() = remoteSideContext.scriptManager
override fun getE2eeInterface() = remoteSideContext.e2eeImplementation
override fun getMessageLogger() = messageLoggerWrapper
override fun getMessageLogger() = remoteSideContext.messageLogger
override fun registerMessagingBridge(bridge: MessagingBridge) {
messagingBridge = bridge
}

View File

@@ -271,7 +271,7 @@ class HomeSection : Section() {
homeSubSection.LogsSection()
}
composable(SETTINGS_SECTION_ROUTE) {
SettingsSection().also { it.context = context }.Content()
SettingsSection(activityLauncherHelper).also { it.context = context }.Content()
}
}
}

View File

@@ -6,27 +6,28 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.core.net.toUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import me.rhunk.snapenhance.common.Constants
import me.rhunk.snapenhance.common.action.EnumAction
import me.rhunk.snapenhance.common.bridge.types.BridgeFileType
import me.rhunk.snapenhance.ui.manager.Section
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
import me.rhunk.snapenhance.ui.util.AlertDialogs
import me.rhunk.snapenhance.ui.util.saveFile
class SettingsSection : Section() {
class SettingsSection(
private val activityLauncherHelper: ActivityLauncherHelper
) : Section() {
private val dialogs by lazy { AlertDialogs(context.translation) }
@Composable
@@ -59,7 +60,7 @@ class SettingsSection : Section() {
}
}
Row(
ShiftedRow(
modifier = Modifier
.fillMaxWidth()
.height(65.dp)
@@ -86,6 +87,22 @@ class SettingsSection : Section() {
context.androidContext.startActivity(intent)
}
@Composable
private fun ShiftedRow(
modifier: Modifier = Modifier,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top,
content: @Composable RowScope.() -> Unit
) {
Row(
modifier = modifier.padding(start = 26.dp),
horizontalArrangement = horizontalArrangement,
verticalAlignment = verticalAlignment
) { content(this) }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
override fun Content() {
Column(
@@ -99,16 +116,106 @@ class SettingsSection : Section() {
launchActionIntent(enumAction)
}
}
RowTitle(title = "Clear Files")
BridgeFileType.entries.forEach { fileType ->
RowAction(title = fileType.displayName, requireConfirmation = true) {
runCatching {
fileType.resolve(context.androidContext).delete()
context.longToast("Deleted ${fileType.displayName}!")
}.onFailure {
context.longToast("Failed to delete ${fileType.displayName}!")
RowTitle(title = "Message Logger")
ShiftedRow {
Column(
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
var storedMessagesCount by remember { mutableIntStateOf(0) }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
storedMessagesCount = context.messageLogger.getStoredMessageCount()
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(5.dp)
) {
Text(text = "$storedMessagesCount messages", modifier = Modifier.weight(1f))
Button(onClick = {
runCatching {
activityLauncherHelper.saveFile("message_logger.db", "application/octet-stream") { uri ->
context.androidContext.contentResolver.openOutputStream(uri.toUri())?.use { outputStream ->
context.messageLogger.databaseFile.inputStream().use { inputStream ->
inputStream.copyTo(outputStream)
}
}
}
}.onFailure {
context.log.error("Failed to export database", it)
context.longToast("Failed to export database! ${it.localizedMessage}")
}
}) {
Text(text = "Export")
}
Button(onClick = {
runCatching {
context.messageLogger.clearMessages()
storedMessagesCount = 0
}.onFailure {
context.log.error("Failed to clear messages", it)
context.longToast("Failed to clear messages! ${it.localizedMessage}")
}.onSuccess {
context.shortToast("Done!")
}
}) {
Text(text = "Clear")
}
}
}
}
RowTitle(title = "Clear App Files")
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
var selectedFileType by remember { mutableStateOf(BridgeFileType.entries.first()) }
Box(
modifier = Modifier
.weight(1f)
.padding(start = 26.dp)
) {
var expanded by remember { mutableStateOf(false) }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = it },
modifier = Modifier.fillMaxWidth(0.8f)
) {
TextField(
value = selectedFileType.displayName,
onValueChange = {},
readOnly = true,
modifier = Modifier.menuAnchor()
)
ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
BridgeFileType.entries.forEach { fileType ->
DropdownMenuItem(onClick = {
expanded = false
selectedFileType = fileType
}, text = {
Text(text = fileType.displayName)
})
}
}
}
}
Button(onClick = {
runCatching {
selectedFileType.resolve(context.androidContext).delete()
}.onFailure {
context.log.error("Failed to clear file", it)
context.longToast("Failed to clear file! ${it.localizedMessage}")
}.onSuccess {
context.shortToast("Done!")
}
}) {
Text(text = "Clear")
}
}
}