From 265902a0119060a0e73d5d5dbf3ea47f748c0814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 27 Dec 2025 13:00:49 +0800 Subject: [PATCH] Fix sing-box:// URL scheme import in ComposeActivity The deep link handling was missing after migrating to Compose UI. --- .../sfa/compose/ComposeActivity.kt | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/app/src/main/java/io/nekohasekai/sfa/compose/ComposeActivity.kt b/app/src/main/java/io/nekohasekai/sfa/compose/ComposeActivity.kt index f760ac5..3d3e29b 100644 --- a/app/src/main/java/io/nekohasekai/sfa/compose/ComposeActivity.kt +++ b/app/src/main/java/io/nekohasekai/sfa/compose/ComposeActivity.kt @@ -117,6 +117,8 @@ class ComposeActivity : ComponentActivity(), ServiceConnection.Callback { private var currentAlert by mutableStateOf?>(null) private var showLocationPermissionDialog by mutableStateOf(false) private var showBackgroundLocationDialog by mutableStateOf(false) + private var showImportProfileDialog by mutableStateOf(false) + private var pendingImportProfile by mutableStateOf?>(null) private val notificationPermissionLauncher = registerForActivityResult( @@ -175,6 +177,8 @@ class ComposeActivity : ComponentActivity(), ServiceConnection.Callback { } } + handleIntent(intent) + setContent { SFATheme { SFAApp() @@ -182,6 +186,26 @@ class ComposeActivity : ComponentActivity(), ServiceConnection.Callback { } } + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + handleIntent(intent) + } + + private fun handleIntent(intent: Intent?) { + val uri = intent?.data ?: return + if (uri.scheme == "sing-box" && uri.host == "import-remote-profile") { + try { + val profile = Libbox.parseRemoteProfileImportLink(uri.toString()) + pendingImportProfile = Triple(profile.name, profile.host, profile.url) + showImportProfileDialog = true + } catch (e: Exception) { + lifecycleScope.launch { + GlobalEventBus.emit(UiEvent.ErrorMessage(e.message ?: "Failed to parse profile link")) + } + } + } + } + @SuppressLint("NewApi") fun startService() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !ServiceNotification.checkPermission()) { @@ -285,6 +309,41 @@ class ComposeActivity : ComponentActivity(), ServiceConnection.Callback { }, onDismiss = { showBackgroundLocationDialog = false }) } + // Handle import remote profile dialog + if (showImportProfileDialog && pendingImportProfile != null) { + val (name, host, url) = pendingImportProfile!! + AlertDialog( + onDismissRequest = { + showImportProfileDialog = false + pendingImportProfile = null + }, + title = { Text(stringResource(R.string.import_remote_profile)) }, + text = { Text(stringResource(R.string.import_remote_profile_message, name, host)) }, + confirmButton = { + TextButton(onClick = { + startActivity( + Intent(this@ComposeActivity, NewProfileComposeActivity::class.java).apply { + putExtra(NewProfileComposeActivity.EXTRA_IMPORT_NAME, name) + putExtra(NewProfileComposeActivity.EXTRA_IMPORT_URL, url) + }, + ) + showImportProfileDialog = false + pendingImportProfile = null + }) { + Text(stringResource(R.string.ok)) + } + }, + dismissButton = { + TextButton(onClick = { + showImportProfileDialog = false + pendingImportProfile = null + }) { + Text(stringResource(android.R.string.cancel)) + } + }, + ) + } + // Handle update check prompt dialog (shown only once on first launch) var showUpdateCheckPrompt by remember { mutableStateOf(!Settings.updateCheckPrompted) } if (showUpdateCheckPrompt) {