manager: Fix save log (#2170)

https://github.com/user-attachments/assets/69467e00-0af9-4d46-add8-e24e767462bd

Use `ContextCompat` in `DownloadListener`
Bump ksp to `2.0.21-1.0.26`
Misc changes (See the
[commit](1fb49d918a)
directly)
This commit is contained in:
Light_summer
2024-10-31 18:06:11 +08:00
committed by GitHub
parent f8310c4d3d
commit b7b704ede7
9 changed files with 53 additions and 68 deletions

View File

@@ -326,7 +326,8 @@ private fun AppMenuBox(packageName: String, content: @Composable () -> Unit) {
touchPoint = it touchPoint = it
expanded = true expanded = true
} }
}) { }
) {
content() content()

View File

@@ -356,6 +356,6 @@ private fun TopBar(
@Composable @Composable
@Preview @Preview
fun SelectInstall_Preview() { fun SelectInstallPreview() {
InstallScreen(EmptyDestinationsNavigator) InstallScreen(EmptyDestinationsNavigator)
} }

View File

@@ -131,9 +131,7 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
) )
}, },
floatingActionButton = { floatingActionButton = {
if (hideInstallButton) { if (!hideInstallButton) {
/* Empty */
} else {
val moduleInstall = stringResource(id = R.string.module_install) val moduleInstall = stringResource(id = R.string.module_install)
val selectZipLauncher = rememberLauncherForActivityResult( val selectZipLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult() contract = ActivityResultContracts.StartActivityForResult()
@@ -162,7 +160,6 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
icon = { Icon(Icons.Filled.Add, moduleInstall) }, icon = { Icon(Icons.Filled.Add, moduleInstall) },
text = { Text(text = moduleInstall) }, text = { Text(text = moduleInstall) },
) )
} }
}, },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal), contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),

View File

@@ -4,6 +4,8 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.widget.Toast import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -35,6 +37,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
@@ -83,9 +86,11 @@ import me.weishu.kernelsu.ui.component.SwitchItem
import me.weishu.kernelsu.ui.component.rememberConfirmDialog import me.weishu.kernelsu.ui.component.rememberConfirmDialog
import me.weishu.kernelsu.ui.component.rememberCustomDialog import me.weishu.kernelsu.ui.component.rememberCustomDialog
import me.weishu.kernelsu.ui.component.rememberLoadingDialog import me.weishu.kernelsu.ui.component.rememberLoadingDialog
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
import me.weishu.kernelsu.ui.util.getBugreportFile import me.weishu.kernelsu.ui.util.getBugreportFile
import me.weishu.kernelsu.ui.util.getFileNameFromUri
import me.weishu.kernelsu.ui.util.shrinkModules import me.weishu.kernelsu.ui.util.shrinkModules
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
/** /**
* @author weishu * @author weishu
@@ -96,6 +101,7 @@ import me.weishu.kernelsu.ui.util.shrinkModules
@Composable @Composable
fun SettingScreen(navigator: DestinationsNavigator) { fun SettingScreen(navigator: DestinationsNavigator) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val snackBarHost = LocalSnackbarHost.current
Scaffold( Scaffold(
topBar = { topBar = {
@@ -106,6 +112,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
scrollBehavior = scrollBehavior scrollBehavior = scrollBehavior
) )
}, },
snackbarHost = { SnackbarHost(snackBarHost) },
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal) contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
) { paddingValues -> ) { paddingValues ->
val aboutDialog = rememberCustomDialog { val aboutDialog = rememberCustomDialog {
@@ -124,6 +131,22 @@ fun SettingScreen(navigator: DestinationsNavigator) {
val context = LocalContext.current val context = LocalContext.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val exportBugreportLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.CreateDocument("application/gzip")
) { uri: Uri? ->
if (uri == null) return@rememberLauncherForActivityResult
scope.launch(Dispatchers.IO) {
loadingDialog.show()
context.contentResolver.openOutputStream(uri)?.use { output ->
getBugreportFile(context).inputStream().use {
it.copyTo(output)
}
}
loadingDialog.hide()
snackBarHost.showSnackbar(context.getString(R.string.log_saved))
}
}
val profileTemplate = stringResource(id = R.string.settings_profile_template) val profileTemplate = stringResource(id = R.string.settings_profile_template)
ListItem( ListItem(
leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) }, leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) },
@@ -208,35 +231,10 @@ fun SettingScreen(navigator: DestinationsNavigator) {
modifier = Modifier modifier = Modifier
.padding(16.dp) .padding(16.dp)
.clickable { .clickable {
scope.launch { val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH_mm")
val bugreport = loadingDialog.withLoading { val current = LocalDateTime.now().format(formatter)
withContext(Dispatchers.IO) { exportBugreportLauncher.launch("KernelSU_bugreport_${current}.tar.gz")
getBugreportFile(context) showBottomsheet = false
}
}
val uri: Uri =
FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
bugreport
)
val filename = getFileNameFromUri(context, uri)
val savefile =
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/zip"
putExtra(Intent.EXTRA_STREAM, uri)
putExtra(Intent.EXTRA_TITLE, filename)
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
}
context.startActivity(
Intent.createChooser(
savefile,
context.getString(R.string.save_log)
)
)
}
} }
) { ) {
Icon( Icon(
@@ -256,7 +254,6 @@ fun SettingScreen(navigator: DestinationsNavigator) {
) )
} }
} }
Box { Box {
Column( Column(
@@ -277,10 +274,11 @@ fun SettingScreen(navigator: DestinationsNavigator) {
bugreport bugreport
) )
val shareIntent = Intent(Intent.ACTION_SEND) val shareIntent = Intent(Intent.ACTION_SEND).apply {
shareIntent.putExtra(Intent.EXTRA_STREAM, uri) putExtra(Intent.EXTRA_STREAM, uri)
shareIntent.setDataAndType(uri, "application/zip") setDataAndType(uri, "application/gzip")
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity( context.startActivity(
Intent.createChooser( Intent.createChooser(
@@ -305,16 +303,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
trim = LineHeightStyle.Trim.None trim = LineHeightStyle.Trim.None
) )
} }
) )
} }
} }
} }
} }
) )
} }
val shrink = stringResource(id = R.string.shrink_sparse_image) val shrink = stringResource(id = R.string.shrink_sparse_image)
@@ -329,8 +323,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
headlineContent = { Text(shrink) }, headlineContent = { Text(shrink) },
modifier = Modifier.clickable { modifier = Modifier.clickable {
scope.launch { scope.launch {
val result = val result = shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
if (result == ConfirmResult.Confirmed) { if (result == ConfirmResult.Confirmed) {
loadingDialog.withLoading { loadingDialog.withLoading {
shrinkModules() shrinkModules()
@@ -340,8 +333,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
) )
val lkmMode = val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
if (lkmMode) { if (lkmMode) {
UninstallItem(navigator) { UninstallItem(navigator) {
loadingDialog.withLoading(it) loadingDialog.withLoading(it)
@@ -353,7 +345,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
leadingContent = { leadingContent = {
Icon( Icon(
Icons.Filled.ContactPage, Icons.Filled.ContactPage,
stringResource(id = R.string.about) about
) )
}, },
headlineContent = { Text(about) }, headlineContent = { Text(about) },

View File

@@ -7,10 +7,10 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Environment import android.os.Environment
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.core.content.ContextCompat
import me.weishu.kernelsu.ui.util.module.LatestVersionInfo import me.weishu.kernelsu.ui.util.module.LatestVersionInfo
/** /**
@@ -26,8 +26,7 @@ fun download(
onDownloaded: (Uri) -> Unit = {}, onDownloaded: (Uri) -> Unit = {},
onDownloading: () -> Unit = {} onDownloading: () -> Unit = {}
) { ) {
val downloadManager = val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val query = DownloadManager.Query() val query = DownloadManager.Query()
query.setFilterByStatus(DownloadManager.STATUS_RUNNING or DownloadManager.STATUS_PAUSED or DownloadManager.STATUS_PENDING) query.setFilterByStatus(DownloadManager.STATUS_RUNNING or DownloadManager.STATUS_PAUSED or DownloadManager.STATUS_PENDING)
@@ -130,18 +129,12 @@ fun DownloadListener(context: Context, onDownloaded: (Uri) -> Unit) {
} }
} }
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { ContextCompat.registerReceiver(
context.registerReceiver( context,
receiver, receiver,
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE),
Context.RECEIVER_EXPORTED ContextCompat.RECEIVER_EXPORTED
) )
} else {
context.registerReceiver(
receiver,
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
)
}
onDispose { onDispose {
context.unregisterReceiver(receiver) context.unregisterReceiver(receiver)
} }

View File

@@ -51,10 +51,10 @@ inline fun <T> withNewRootShell(
return createRootShell(globalMnt).use(block) return createRootShell(globalMnt).use(block)
} }
fun getFileNameFromUri(context: Context, uri: Uri): String? { fun Uri.getFileName(context: Context): String? {
var fileName: String? = null var fileName: String? = null
val contentResolver: ContentResolver = context.contentResolver val contentResolver: ContentResolver = context.contentResolver
val cursor: Cursor? = contentResolver.query(uri, null, null, null, null) val cursor: Cursor? = contentResolver.query(this, null, null, null, null)
cursor?.use { cursor?.use {
if (it.moveToFirst()) { if (it.moveToFirst()) {
fileName = it.getString(it.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)) fileName = it.getString(it.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))

View File

@@ -130,4 +130,5 @@
<string name="flash_failed">刷写失败</string> <string name="flash_failed">刷写失败</string>
<string name="selected_lkm">选择的 LKM %s</string> <string name="selected_lkm">选择的 LKM %s</string>
<string name="save_log">保存日志</string> <string name="save_log">保存日志</string>
<string name="log_saved">日志已保存</string>
</resources> </resources>

View File

@@ -132,4 +132,5 @@
<string name="flash_failed">Flash failed</string> <string name="flash_failed">Flash failed</string>
<string name="selected_lkm">Selected LKM: %s</string> <string name="selected_lkm">Selected LKM: %s</string>
<string name="save_log">Save logs</string> <string name="save_log">Save logs</string>
<string name="log_saved">Logs saved</string>
</resources> </resources>

View File

@@ -1,7 +1,7 @@
[versions] [versions]
agp = "8.7.1" agp = "8.7.1"
kotlin = "2.0.21" kotlin = "2.0.21"
ksp = "2.0.21-1.0.25" ksp = "2.0.21-1.0.26"
compose-bom = "2024.10.00" compose-bom = "2024.10.00"
lifecycle = "2.8.6" lifecycle = "2.8.6"
navigation = "2.8.3" navigation = "2.8.3"