feat: allow user to save logs

This commit is contained in:
Ax333l 2023-07-06 20:01:44 +02:00
parent 8dd8f88d2b
commit d9d83df9de
5 changed files with 75 additions and 25 deletions

View File

@ -22,10 +22,10 @@ class Session(
cacheDir: String, cacheDir: String,
frameworkDir: String, frameworkDir: String,
aaptPath: String, aaptPath: String,
private val logger: Logger,
private val input: File, private val input: File,
private val onProgress: suspend (Progress) -> Unit = { } private val onProgress: suspend (Progress) -> Unit = { }
) : Closeable { ) : Closeable {
private val logger = LogcatLogger
private val temporary = File(cacheDir).resolve("manager").also { it.mkdirs() } private val temporary = File(cacheDir).resolve("manager").also { it.mkdirs() }
private val patcher = Patcher( private val patcher = Patcher(
PatcherOptions( PatcherOptions(
@ -83,24 +83,4 @@ class Session(
override fun close() { override fun close() {
temporary.delete() temporary.delete()
} }
}
private object LogcatLogger : Logger {
fun String.fmt() = "[Patcher]: $this"
override fun error(msg: String) {
Log.e(tag, msg.fmt())
}
override fun warn(msg: String) {
Log.w(tag, msg.fmt())
}
override fun info(msg: String) {
Log.i(tag, msg.fmt())
}
override fun trace(msg: String) {
Log.v(tag, msg.fmt())
}
} }

View File

@ -24,6 +24,7 @@ import app.revanced.manager.util.PatchesSelection
import app.revanced.manager.util.tag import app.revanced.manager.util.tag
import app.revanced.patcher.extensions.PatchExtensions.options import app.revanced.patcher.extensions.PatchExtensions.options
import app.revanced.patcher.extensions.PatchExtensions.patchName import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.logging.Logger
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -46,7 +47,8 @@ class PatcherWorker(context: Context, parameters: WorkerParameters) :
val options: Options, val options: Options,
val packageName: String, val packageName: String,
val packageVersion: String, val packageVersion: String,
val progress: MutableStateFlow<ImmutableList<Step>> val progress: MutableStateFlow<ImmutableList<Step>>,
val logger: Logger
) )
companion object { companion object {
@ -159,6 +161,7 @@ class PatcherWorker(context: Context, parameters: WorkerParameters) :
applicationContext.cacheDir.absolutePath, applicationContext.cacheDir.absolutePath,
frameworkPath, frameworkPath,
aaptPath, aaptPath,
args.logger,
File(args.input) File(args.input)
) { ) {
updateProgress(it) updateProgress(it)

View File

@ -25,6 +25,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
@ -48,11 +49,13 @@ fun InstallerScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
vm: InstallerViewModel vm: InstallerViewModel
) { ) {
val context = LocalContext.current
val exportApkLauncher = val exportApkLauncher =
rememberLauncherForActivityResult(CreateDocument(APK_MIMETYPE), vm::export) rememberLauncherForActivityResult(CreateDocument(APK_MIMETYPE), vm::export)
val patcherState by vm.patcherState.observeAsState(null) val patcherState by vm.patcherState.observeAsState(null)
val steps by vm.progress.collectAsStateWithLifecycle() val steps by vm.progress.collectAsStateWithLifecycle()
val canInstall by remember { derivedStateOf { patcherState == true && (vm.installedPackageName != null || !vm.isInstalling) } } val canInstall by remember { derivedStateOf { patcherState == true && (vm.installedPackageName != null || !vm.isInstalling) } }
var dropdownActive by rememberSaveable { mutableStateOf(false) }
AppScaffold( AppScaffold(
topBar = { topBar = {
@ -63,9 +66,19 @@ fun InstallerScreen(
IconButton(onClick = {}) { IconButton(onClick = {}) {
Icon(Icons.Outlined.HelpOutline, stringResource(R.string.help)) Icon(Icons.Outlined.HelpOutline, stringResource(R.string.help))
} }
IconButton(onClick = {}) { IconButton(onClick = { dropdownActive = true }) {
Icon(Icons.Outlined.MoreVert, stringResource(R.string.more)) Icon(Icons.Outlined.MoreVert, stringResource(R.string.more))
} }
DropdownMenu(
expanded = dropdownActive,
onDismissRequest = { dropdownActive = false }
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.save_logs)) },
onClick = { vm.exportLogs(context) },
enabled = patcherState != null
)
}
} }
) )
} }

View File

@ -15,7 +15,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.map import androidx.lifecycle.map
import androidx.work.* import androidx.work.WorkInfo
import androidx.work.WorkManager
import app.revanced.manager.domain.manager.KeystoreManager import app.revanced.manager.domain.manager.KeystoreManager
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.domain.worker.WorkerRepository import app.revanced.manager.domain.worker.WorkerRepository
@ -28,6 +29,7 @@ import app.revanced.manager.ui.destination.Destination
import app.revanced.manager.util.PM import app.revanced.manager.util.PM
import app.revanced.manager.util.tag import app.revanced.manager.util.tag
import app.revanced.manager.util.toast import app.revanced.manager.util.toast
import app.revanced.patcher.logging.Logger
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -60,6 +62,7 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
private val _progress: MutableStateFlow<ImmutableList<Step>> private val _progress: MutableStateFlow<ImmutableList<Step>>
private val patcherWorkerId: UUID private val patcherWorkerId: UUID
private val logger = ManagerLogger()
init { init {
val (appInfo, patches, options) = input val (appInfo, patches, options) = input
@ -77,7 +80,8 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
options, options,
packageName, packageName,
appInfo.packageInfo!!.versionName, appInfo.packageInfo!!.versionName,
_progress _progress,
logger
) )
) )
} }
@ -122,6 +126,17 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
}) })
} }
fun exportLogs(context: Context) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, logger.export())
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent)
}
override fun onCleared() { override fun onCleared() {
super.onCleared() super.onCleared()
app.unregisterReceiver(installBroadcastReceiver) app.unregisterReceiver(installBroadcastReceiver)
@ -166,4 +181,42 @@ class InstallerViewModel(input: Destination.Installer) : ViewModel(), KoinCompon
isInstalling = false isInstalling = false
} }
} }
}
private class ManagerLogger : Logger {
private val logs = mutableListOf<Pair<LogLevel, String>>()
private fun log(level: LogLevel, msg: String) {
level.androidLog(msg)
if (level == LogLevel.TRACE) return
logs.add(level to msg)
}
fun export() =
logs.asSequence().map { (level, msg) -> "[${level.name}]: $msg" }.joinToString("\n")
override fun trace(msg: String) = log(LogLevel.TRACE, msg)
override fun info(msg: String) = log(LogLevel.INFO, msg)
override fun warn(msg: String) = log(LogLevel.WARN, msg)
override fun error(msg: String) = log(LogLevel.ERROR, msg)
}
enum class LogLevel {
TRACE {
override fun androidLog(msg: String) = Log.v(androidTag, msg)
},
INFO {
override fun androidLog(msg: String) = Log.i(androidTag, msg)
},
WARN {
override fun androidLog(msg: String) = Log.w(androidTag, msg)
},
ERROR {
override fun androidLog(msg: String) = Log.e(androidTag, msg)
};
abstract fun androidLog(msg: String): Int
private companion object {
const val androidTag = "ReVanced Patcher"
}
} }

View File

@ -97,6 +97,7 @@
<string name="export_app">Export</string> <string name="export_app">Export</string>
<string name="export_app_success">Apk exported</string> <string name="export_app_success">Apk exported</string>
<string name="sign_fail">Failed to sign Apk: %s</string> <string name="sign_fail">Failed to sign Apk: %s</string>
<string name="save_logs">Save logs</string>
<string name="patcher_step_group_prepare">Preparation</string> <string name="patcher_step_group_prepare">Preparation</string>
<string name="patcher_step_load_patches">Load patches</string> <string name="patcher_step_load_patches">Load patches</string>