@@ -4,6 +4,8 @@ import android.content.Context
44import android.content.Intent
55import android.net.Uri
66import android.widget.Toast
7+ import androidx.activity.compose.rememberLauncherForActivityResult
8+ import androidx.activity.result.contract.ActivityResultContracts
79import androidx.compose.foundation.clickable
810import androidx.compose.foundation.layout.Box
911import androidx.compose.foundation.layout.Column
@@ -35,6 +37,7 @@ import androidx.compose.material3.IconButton
3537import androidx.compose.material3.ListItem
3638import androidx.compose.material3.ModalBottomSheet
3739import androidx.compose.material3.Scaffold
40+ import androidx.compose.material3.SnackbarHost
3841import androidx.compose.material3.Text
3942import androidx.compose.material3.TopAppBar
4043import androidx.compose.material3.TopAppBarDefaults
@@ -83,9 +86,11 @@ import me.weishu.kernelsu.ui.component.SwitchItem
8386import me.weishu.kernelsu.ui.component.rememberConfirmDialog
8487import me.weishu.kernelsu.ui.component.rememberCustomDialog
8588import me.weishu.kernelsu.ui.component.rememberLoadingDialog
89+ import me.weishu.kernelsu.ui.util.LocalSnackbarHost
8690import me.weishu.kernelsu.ui.util.getBugreportFile
87- import me.weishu.kernelsu.ui.util.getFileNameFromUri
8891import me.weishu.kernelsu.ui.util.shrinkModules
92+ import java.time.LocalDateTime
93+ import java.time.format.DateTimeFormatter
8994
9095/* *
9196 * @author weishu
@@ -96,6 +101,7 @@ import me.weishu.kernelsu.ui.util.shrinkModules
96101@Composable
97102fun SettingScreen (navigator : DestinationsNavigator ) {
98103 val scrollBehavior = TopAppBarDefaults .pinnedScrollBehavior(rememberTopAppBarState())
104+ val snackBarHost = LocalSnackbarHost .current
99105
100106 Scaffold (
101107 topBar = {
@@ -106,6 +112,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
106112 scrollBehavior = scrollBehavior
107113 )
108114 },
115+ snackbarHost = { SnackbarHost (snackBarHost) },
109116 contentWindowInsets = WindowInsets .safeDrawing.only(WindowInsetsSides .Top + WindowInsetsSides .Horizontal )
110117 ) { paddingValues ->
111118 val aboutDialog = rememberCustomDialog {
@@ -124,6 +131,22 @@ fun SettingScreen(navigator: DestinationsNavigator) {
124131 val context = LocalContext .current
125132 val scope = rememberCoroutineScope()
126133
134+ val exportBugreportLauncher = rememberLauncherForActivityResult(
135+ ActivityResultContracts .CreateDocument (" application/gzip" )
136+ ) { uri: Uri ? ->
137+ if (uri == null ) return @rememberLauncherForActivityResult
138+ scope.launch(Dispatchers .IO ) {
139+ loadingDialog.show()
140+ context.contentResolver.openOutputStream(uri)?.use { output ->
141+ getBugreportFile(context).inputStream().use {
142+ it.copyTo(output)
143+ }
144+ }
145+ loadingDialog.hide()
146+ snackBarHost.showSnackbar(context.getString(R .string.log_saved))
147+ }
148+ }
149+
127150 val profileTemplate = stringResource(id = R .string.settings_profile_template)
128151 ListItem (
129152 leadingContent = { Icon (Icons .Filled .Fence , profileTemplate) },
@@ -208,35 +231,10 @@ fun SettingScreen(navigator: DestinationsNavigator) {
208231 modifier = Modifier
209232 .padding(16 .dp)
210233 .clickable {
211- scope.launch {
212- val bugreport = loadingDialog.withLoading {
213- withContext(Dispatchers .IO ) {
214- getBugreportFile(context)
215- }
216- }
217-
218- val uri: Uri =
219- FileProvider .getUriForFile(
220- context,
221- " ${BuildConfig .APPLICATION_ID } .fileprovider" ,
222- bugreport
223- )
224- val filename = getFileNameFromUri(context, uri)
225- val savefile =
226- Intent (Intent .ACTION_CREATE_DOCUMENT ).apply {
227- addCategory(Intent .CATEGORY_OPENABLE )
228- type = " application/zip"
229- putExtra(Intent .EXTRA_STREAM , uri)
230- putExtra(Intent .EXTRA_TITLE , filename)
231- flags = Intent .FLAG_GRANT_READ_URI_PERMISSION
232- }
233- context.startActivity(
234- Intent .createChooser(
235- savefile,
236- context.getString(R .string.save_log)
237- )
238- )
239- }
234+ val formatter = DateTimeFormatter .ofPattern(" yyyy-MM-dd_HH_mm" )
235+ val current = LocalDateTime .now().format(formatter)
236+ exportBugreportLauncher.launch(" KernelSU_bugreport_${current} .tar.gz" )
237+ showBottomsheet = false
240238 }
241239 ) {
242240 Icon (
@@ -256,7 +254,6 @@ fun SettingScreen(navigator: DestinationsNavigator) {
256254
257255 )
258256 }
259-
260257 }
261258 Box {
262259 Column (
@@ -277,10 +274,11 @@ fun SettingScreen(navigator: DestinationsNavigator) {
277274 bugreport
278275 )
279276
280- val shareIntent = Intent (Intent .ACTION_SEND )
281- shareIntent.putExtra(Intent .EXTRA_STREAM , uri)
282- shareIntent.setDataAndType(uri, " application/zip" )
283- shareIntent.addFlags(Intent .FLAG_GRANT_READ_URI_PERMISSION )
277+ val shareIntent = Intent (Intent .ACTION_SEND ).apply {
278+ putExtra(Intent .EXTRA_STREAM , uri)
279+ setDataAndType(uri, " application/gzip" )
280+ addFlags(Intent .FLAG_GRANT_READ_URI_PERMISSION )
281+ }
284282
285283 context.startActivity(
286284 Intent .createChooser(
@@ -305,16 +303,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
305303 trim = LineHeightStyle .Trim .None
306304 )
307305 }
308-
309306 )
310307 }
311-
312308 }
313309 }
314310 }
315311 )
316-
317-
318312 }
319313
320314 val shrink = stringResource(id = R .string.shrink_sparse_image)
@@ -329,8 +323,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
329323 headlineContent = { Text (shrink) },
330324 modifier = Modifier .clickable {
331325 scope.launch {
332- val result =
333- shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
326+ val result = shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
334327 if (result == ConfirmResult .Confirmed ) {
335328 loadingDialog.withLoading {
336329 shrinkModules()
@@ -340,8 +333,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
340333 }
341334 )
342335
343- val lkmMode =
344- Natives .version >= Natives .MINIMAL_SUPPORTED_KERNEL_LKM && Natives .isLkmMode
336+ val lkmMode = Natives .version >= Natives .MINIMAL_SUPPORTED_KERNEL_LKM && Natives .isLkmMode
345337 if (lkmMode) {
346338 UninstallItem (navigator) {
347339 loadingDialog.withLoading(it)
@@ -353,7 +345,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
353345 leadingContent = {
354346 Icon (
355347 Icons .Filled .ContactPage ,
356- stringResource(id = R .string. about)
348+ about
357349 )
358350 },
359351 headlineContent = { Text (about) },
0 commit comments