@@ -4,6 +4,8 @@ import android.content.Context
4
4
import android.content.Intent
5
5
import android.net.Uri
6
6
import android.widget.Toast
7
+ import androidx.activity.compose.rememberLauncherForActivityResult
8
+ import androidx.activity.result.contract.ActivityResultContracts
7
9
import androidx.compose.foundation.clickable
8
10
import androidx.compose.foundation.layout.Box
9
11
import androidx.compose.foundation.layout.Column
@@ -35,6 +37,7 @@ import androidx.compose.material3.IconButton
35
37
import androidx.compose.material3.ListItem
36
38
import androidx.compose.material3.ModalBottomSheet
37
39
import androidx.compose.material3.Scaffold
40
+ import androidx.compose.material3.SnackbarHost
38
41
import androidx.compose.material3.Text
39
42
import androidx.compose.material3.TopAppBar
40
43
import androidx.compose.material3.TopAppBarDefaults
@@ -83,9 +86,11 @@ import me.weishu.kernelsu.ui.component.SwitchItem
83
86
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
84
87
import me.weishu.kernelsu.ui.component.rememberCustomDialog
85
88
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
89
+ import me.weishu.kernelsu.ui.util.LocalSnackbarHost
86
90
import me.weishu.kernelsu.ui.util.getBugreportFile
87
- import me.weishu.kernelsu.ui.util.getFileNameFromUri
88
91
import me.weishu.kernelsu.ui.util.shrinkModules
92
+ import java.time.LocalDateTime
93
+ import java.time.format.DateTimeFormatter
89
94
90
95
/* *
91
96
* @author weishu
@@ -96,6 +101,7 @@ import me.weishu.kernelsu.ui.util.shrinkModules
96
101
@Composable
97
102
fun SettingScreen (navigator : DestinationsNavigator ) {
98
103
val scrollBehavior = TopAppBarDefaults .pinnedScrollBehavior(rememberTopAppBarState())
104
+ val snackBarHost = LocalSnackbarHost .current
99
105
100
106
Scaffold (
101
107
topBar = {
@@ -106,6 +112,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
106
112
scrollBehavior = scrollBehavior
107
113
)
108
114
},
115
+ snackbarHost = { SnackbarHost (snackBarHost) },
109
116
contentWindowInsets = WindowInsets .safeDrawing.only(WindowInsetsSides .Top + WindowInsetsSides .Horizontal )
110
117
) { paddingValues ->
111
118
val aboutDialog = rememberCustomDialog {
@@ -124,6 +131,22 @@ fun SettingScreen(navigator: DestinationsNavigator) {
124
131
val context = LocalContext .current
125
132
val scope = rememberCoroutineScope()
126
133
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
+
127
150
val profileTemplate = stringResource(id = R .string.settings_profile_template)
128
151
ListItem (
129
152
leadingContent = { Icon (Icons .Filled .Fence , profileTemplate) },
@@ -208,35 +231,10 @@ fun SettingScreen(navigator: DestinationsNavigator) {
208
231
modifier = Modifier
209
232
.padding(16 .dp)
210
233
.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
240
238
}
241
239
) {
242
240
Icon (
@@ -256,7 +254,6 @@ fun SettingScreen(navigator: DestinationsNavigator) {
256
254
257
255
)
258
256
}
259
-
260
257
}
261
258
Box {
262
259
Column (
@@ -277,10 +274,11 @@ fun SettingScreen(navigator: DestinationsNavigator) {
277
274
bugreport
278
275
)
279
276
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
+ }
284
282
285
283
context.startActivity(
286
284
Intent .createChooser(
@@ -305,16 +303,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
305
303
trim = LineHeightStyle .Trim .None
306
304
)
307
305
}
308
-
309
306
)
310
307
}
311
-
312
308
}
313
309
}
314
310
}
315
311
)
316
-
317
-
318
312
}
319
313
320
314
val shrink = stringResource(id = R .string.shrink_sparse_image)
@@ -329,8 +323,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
329
323
headlineContent = { Text (shrink) },
330
324
modifier = Modifier .clickable {
331
325
scope.launch {
332
- val result =
333
- shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
326
+ val result = shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
334
327
if (result == ConfirmResult .Confirmed ) {
335
328
loadingDialog.withLoading {
336
329
shrinkModules()
@@ -340,8 +333,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
340
333
}
341
334
)
342
335
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
345
337
if (lkmMode) {
346
338
UninstallItem (navigator) {
347
339
loadingDialog.withLoading(it)
@@ -353,7 +345,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
353
345
leadingContent = {
354
346
Icon (
355
347
Icons .Filled .ContactPage ,
356
- stringResource(id = R .string. about)
348
+ about
357
349
)
358
350
},
359
351
headlineContent = { Text (about) },
0 commit comments