From 4e6a6c3d1e7eaff50869117d067f60fa4e4d39a9 Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 8 Jun 2026 17:14:25 +0000 Subject: [PATCH] fix(outbound): URL-encode token in glucodroid.cloud URL; show subdomain before token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Uri.encode() the ingest token so characters like +, &, =, # in base64-style tokens don't produce malformed query strings. - Move the subdomain field above the token field in the UI so the order matches the URL shape (subdomain → token) and users fill in the account identifier first. Co-Authored-By: Claude Sonnet 4.6 --- .../java/tk/glucodata/OutboundApiSettings.kt | 3 +- .../glucodata/ui/OutboundApiSettingsScreen.kt | 29 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Common/src/main/java/tk/glucodata/OutboundApiSettings.kt b/Common/src/main/java/tk/glucodata/OutboundApiSettings.kt index c82ec5f8b..fc5082bfb 100644 --- a/Common/src/main/java/tk/glucodata/OutboundApiSettings.kt +++ b/Common/src/main/java/tk/glucodata/OutboundApiSettings.kt @@ -1,6 +1,7 @@ package tk.glucodata import android.content.Context +import android.net.Uri import androidx.annotation.Keep import org.json.JSONArray import org.json.JSONObject @@ -124,7 +125,7 @@ object OutboundApiSettings { if (normalizedPreset() == PRESET_GLUCODROID_CLOUD) { val subdomain = url.trim() if (subdomain.isBlank()) return "" - return "https://$subdomain.glucodroid.cloud/api/v1/ingest?token=${token.trim()}" + return "https://$subdomain.glucodroid.cloud/api/v1/ingest?token=${Uri.encode(token.trim())}" } val trimmed = url.trim() val replacementToken = if (normalizedPreset() == PRESET_TELEGRAM_BOT) { diff --git a/Common/src/mobile/java/tk/glucodata/ui/OutboundApiSettingsScreen.kt b/Common/src/mobile/java/tk/glucodata/ui/OutboundApiSettingsScreen.kt index 6912c9ea3..e6f972750 100644 --- a/Common/src/mobile/java/tk/glucodata/ui/OutboundApiSettingsScreen.kt +++ b/Common/src/mobile/java/tk/glucodata/ui/OutboundApiSettingsScreen.kt @@ -446,6 +446,20 @@ private fun DestinationEditor( onChangePreset = { showPresetSheet = true } ) + if (isGlucodroid) { + OutlinedTextField( + value = destination.url, + onValueChange = { onChange(destination.copy(url = it.trim())) }, + modifier = Modifier.fillMaxWidth(), + singleLine = true, + label = { Text(stringResource(R.string.outbound_api_glucodroid_subdomain)) }, + suffix = { Text(".glucodroid.cloud", color = MaterialTheme.colorScheme.onSurfaceVariant) }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Next + ) + ) + } if (isTelegram || isVk || isGlucodroid) { OutlinedTextField( value = destination.token, @@ -504,20 +518,7 @@ private fun DestinationEditor( ) } - if (isGlucodroid) { - OutlinedTextField( - value = destination.url, - onValueChange = { onChange(destination.copy(url = it.trim())) }, - modifier = Modifier.fillMaxWidth(), - singleLine = true, - label = { Text(stringResource(R.string.outbound_api_glucodroid_subdomain)) }, - suffix = { Text(".glucodroid.cloud", color = MaterialTheme.colorScheme.onSurfaceVariant) }, - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Next - ) - ) - } else { + if (!isGlucodroid) { OutlinedTextField( value = destination.url.ifBlank { OutboundApiSettings.defaultUrl(preset) }, onValueChange = { onChange(destination.copy(url = it)) },