@@ -63,13 +63,9 @@ fun ConfigSharingBar(
6363 val clipboard = LocalClipboardManager .current
6464 val scope = rememberCoroutineScope()
6565
66- val clipText = clipboard.getText()?.text.orEmpty()
67- val hasConfigInClipboard = clipText.isNotEmpty() && ConfigStore .looksLikeConfig(clipText)
68-
6966 var showExportDialog by remember { mutableStateOf(false ) }
7067 var showImportConfirm by remember { mutableStateOf(false ) }
7168 var pendingImport by remember { mutableStateOf<MhrvConfig ?>(null ) }
72- var showQrDialog by remember { mutableStateOf(false ) }
7369
7470 // QR scanner launcher — fires the ZXing embedded scanner activity.
7571 val scanLauncher = rememberLauncherForActivityResult(ScanContract ()) { result ->
@@ -83,58 +79,32 @@ fun ConfigSharingBar(
8379 }
8480 }
8581
86- // --- Paste from clipboard banner ---
87- if (hasConfigInClipboard) {
88- Card (
89- modifier = Modifier .fillMaxWidth(),
90- colors = CardDefaults .cardColors(
91- containerColor = MaterialTheme .colorScheme.primaryContainer,
92- ),
93- ) {
94- Row (
95- modifier = Modifier
96- .fillMaxWidth()
97- .padding(horizontal = 12 .dp, vertical = 8 .dp),
98- verticalAlignment = Alignment .CenterVertically ,
99- horizontalArrangement = Arrangement .SpaceBetween ,
100- ) {
101- Text (
102- " Config detected in clipboard" ,
103- style = MaterialTheme .typography.labelMedium,
104- color = MaterialTheme .colorScheme.onPrimaryContainer,
105- modifier = Modifier .weight(1f ),
106- )
107- FilledTonalButton (
108- onClick = {
109- val decoded = ConfigStore .decode(clipText)
110- if (decoded != null ) {
111- pendingImport = decoded
112- showImportConfirm = true
113- } else {
114- scope.launch { onSnackbar(ctx.getString(R .string.snack_invalid_config)) }
115- }
116- },
117- ) {
118- Icon (Icons .Default .ContentPaste , null , modifier = Modifier .size(18 .dp))
119- Spacer (Modifier .width(4 .dp))
120- Text (stringResource(R .string.btn_import_clipboard))
121- }
122- }
123- }
124- }
125-
126- // --- Export + Scan row ---
82+ // --- Export + Paste + Scan row ---
12783 Row (
12884 modifier = Modifier .fillMaxWidth(),
12985 horizontalArrangement = Arrangement .spacedBy(8 .dp),
13086 ) {
87+ IconButton (onClick = { showExportDialog = true }) {
88+ Icon (Icons .Default .Share , contentDescription = stringResource(R .string.btn_export_config))
89+ }
90+ // Manual paste — reads clipboard on tap. Android 13+ restricts
91+ // background clipboard access, so auto-detect doesn't work.
92+ // User interaction (tap) grants clipboard permission.
13193 OutlinedButton (
132- onClick = { showExportDialog = true },
133- modifier = Modifier .weight(1f ),
94+ onClick = {
95+ val text = clipboard.getText()?.text.orEmpty()
96+ val decoded = ConfigStore .decode(text)
97+ if (decoded != null ) {
98+ pendingImport = decoded
99+ showImportConfirm = true
100+ } else {
101+ scope.launch { onSnackbar(ctx.getString(R .string.snack_invalid_config)) }
102+ }
103+ },
134104 ) {
135- Icon (Icons .Default .Share , null , modifier = Modifier .size(18 .dp))
105+ Icon (Icons .Default .ContentPaste , null , modifier = Modifier .size(18 .dp))
136106 Spacer (Modifier .width(4 .dp))
137- Text (stringResource( R .string.btn_export_config) )
107+ Text (" Paste " )
138108 }
139109 OutlinedButton (
140110 onClick = {
0 commit comments