From b91c12d3a2f763aab453df02fd4c7e5417afaab4 Mon Sep 17 00:00:00 2001 From: charlie Date: Mon, 18 May 2026 12:56:27 +0800 Subject: [PATCH] enhance(android): add logs for the navigation stack --- .../main/java/com/logseq/app/ComposeHost.kt | 30 +++++++++++++++++-- .../java/com/logseq/app/MainActivity.java | 19 ++++++++++++ .../com/logseq/app/NavigationCoordinator.kt | 27 ++++++++++++++++- .../src/main/java/com/logseq/app/UILocal.kt | 7 +++++ 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/logseq/app/ComposeHost.kt b/android/app/src/main/java/com/logseq/app/ComposeHost.kt index 04e816a91f..d9e81fef3e 100644 --- a/android/app/src/main/java/com/logseq/app/ComposeHost.kt +++ b/android/app/src/main/java/com/logseq/app/ComposeHost.kt @@ -39,6 +39,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch private const val ROOT_ROUTE = "web/{encodedPath}" +private const val DEBUG_NAV_STACK_PREFIX = "[DEBUG-navstack]" data class NavigationEvent( val navigationType: String, @@ -55,6 +56,7 @@ object ComposeHost { fun applyNavigation(navigationType: String?, path: String?) { val type = (navigationType ?: "push").lowercase() val safePath = path?.takeIf { it.isNotBlank() } ?: "/" + Log.d("NavStack", "$DEBUG_NAV_STACK_PREFIX compose.applyNavigation type=$type path=$safePath") if (!navEvents.tryEmit(NavigationEvent(type, safePath))) { Log.w("ComposeHost", "Dropped navigation event: type=$type path=$safePath") } @@ -99,8 +101,9 @@ private fun encodePath(path: String): String = private fun routeFor(path: String): String = "web/${encodePath(path)}" +@Suppress("UNUSED_PARAMETER") private fun shouldAnimateNavigation(navigationType: String): Boolean = - navigationType == "push" || navigationType == "pop" + false @OptIn(ExperimentalAnimationApi::class) @Composable @@ -273,13 +276,20 @@ private fun HandleNavigationEvents( snapshotVersion += 1 val currentSnapshotVersion = snapshotVersion val animateNavigation = shouldAnimateNavigation(event.navigationType) + val route = routeFor(event.path) + Log.d( + "NavStack", + "$DEBUG_NAV_STACK_PREFIX compose.event.before type=${event.navigationType} path=${event.path} targetRoute=$route " + + "currentRoute=${navController.currentBackStackEntry?.destination?.route} " + + "currentArgs=${navController.currentBackStackEntry?.arguments} " + + "previousRoute=${navController.previousBackStackEntry?.destination?.route}" + ) if (animateNavigation) { WebViewSnapshotManager.showSnapshot("navigation", webView) } else { WebViewSnapshotManager.clearSnapshot("navigation") } onNavType(event.navigationType) - val route = routeFor(event.path) when (event.navigationType) { "push" -> navController.navigate(route) @@ -291,7 +301,14 @@ private fun HandleNavigationEvents( } "pop" -> { - navController.popBackStack() + if (!navController.popBackStack(route, inclusive = false)) { + navController.navigate(route) { + popUpTo(ROOT_ROUTE) { + inclusive = true + } + launchSingleTop = true + } + } } "reset" -> { @@ -306,6 +323,13 @@ private fun HandleNavigationEvents( else -> navController.navigate(route) } + Log.d( + "NavStack", + "$DEBUG_NAV_STACK_PREFIX compose.event.after type=${event.navigationType} path=${event.path} targetRoute=$route " + + "currentRoute=${navController.currentBackStackEntry?.destination?.route} " + + "currentArgs=${navController.currentBackStackEntry?.arguments} " + + "previousRoute=${navController.previousBackStackEntry?.destination?.route}" + ) if (animateNavigation) { launch { diff --git a/android/app/src/main/java/com/logseq/app/MainActivity.java b/android/app/src/main/java/com/logseq/app/MainActivity.java index 55d9be6734..a911a134e1 100644 --- a/android/app/src/main/java/com/logseq/app/MainActivity.java +++ b/android/app/src/main/java/com/logseq/app/MainActivity.java @@ -19,6 +19,7 @@ import java.util.Timer; import java.util.TimerTask; public class MainActivity extends BridgeActivity { + private static final String NAV_STACK_DEBUG_PREFIX = "[DEBUG-navstack]"; private final NavigationCoordinator navigationCoordinator = new NavigationCoordinator(); private BroadcastReceiver routeChangeReceiver; @@ -60,7 +61,19 @@ public class MainActivity extends BridgeActivity { String stack = intent.getStringExtra("stack"); String navigationType = intent.getStringExtra("navigationType"); String path = intent.getStringExtra("path"); + Log.d( + "NavStack", + NAV_STACK_DEBUG_PREFIX + " activity.routeChange.received stack=" + stack + + " type=" + navigationType + + " path=" + path + + " before=" + navigationCoordinator.debugState() + ); navigationCoordinator.onRouteChange(stack, navigationType, path); + Log.d( + "NavStack", + NAV_STACK_DEBUG_PREFIX + " activity.routeChange.applied after=" + + navigationCoordinator.debugState() + ); } }; IntentFilter filter = new IntentFilter(UILocal.ACTION_ROUTE_CHANGED); @@ -133,6 +146,11 @@ public class MainActivity extends BridgeActivity { private void handleNativeBack() { Log.d("onBackPressed", "Debug"); + Log.d( + "NavStack", + NAV_STACK_DEBUG_PREFIX + " activity.nativeBack source=system-or-edge before=" + + navigationCoordinator.debugState() + ); WebView webView = getBridge().getWebView(); if (webView != null) { @@ -167,6 +185,7 @@ public class MainActivity extends BridgeActivity { private void sendJsBack(WebView webView) { if (webView == null) return; + Log.d("NavStack", NAV_STACK_DEBUG_PREFIX + " activity.sendJsBack dispatching onNativePop"); webView.post(() -> webView.evaluateJavascript( "window.LogseqNative && window.LogseqNative.onNativePop && window.LogseqNative.onNativePop();", null diff --git a/android/app/src/main/java/com/logseq/app/NavigationCoordinator.kt b/android/app/src/main/java/com/logseq/app/NavigationCoordinator.kt index c49faaab07..a4a2190621 100644 --- a/android/app/src/main/java/com/logseq/app/NavigationCoordinator.kt +++ b/android/app/src/main/java/com/logseq/app/NavigationCoordinator.kt @@ -1,6 +1,13 @@ package com.logseq.app +import android.util.Log + class NavigationCoordinator { + companion object { + private const val TAG = "NavStack" + private const val DEBUG_PREFIX = "[DEBUG-navstack]" + } + private val primaryStack = "home" private val stackPaths: MutableMap> = mutableMapOf( primaryStack to mutableListOf("/") @@ -14,11 +21,22 @@ class NavigationCoordinator { private fun normalizedPath(raw: String?): String = raw?.takeIf { it.isNotBlank() } ?: "/" + fun debugState(): String = + "active=$activeStackId stacks=" + stackPaths.entries.joinToString( + prefix = "{", + postfix = "}" + ) { (stack, paths) -> "$stack=${paths.joinToString(prefix = "[", postfix = "]")}" } + fun onRouteChange(stack: String?, navigationType: String?, path: String?) { val stackId = stack?.takeIf { it.isNotBlank() } ?: primaryStack val navType = navigationType?.lowercase() ?: "push" val resolvedPath = normalizedPath(path) + Log.d( + TAG, + "$DEBUG_PREFIX coordinator.onRouteChange.before stack=$stackId type=$navType path=$resolvedPath ${debugState()}" + ) + val paths = stackPaths.getOrPut(stackId) { mutableListOf(defaultPath(stackId)) } when (navType) { @@ -58,6 +76,11 @@ class NavigationCoordinator { activeStackId = stackId stackPaths[stackId] = paths + + Log.d( + TAG, + "$DEBUG_PREFIX coordinator.onRouteChange.after stack=$stackId type=$navType path=$resolvedPath ${debugState()} canPop=${canPop()}" + ) } fun canPop(): Boolean { @@ -69,6 +92,8 @@ class NavigationCoordinator { val paths = stackPaths[activeStackId] ?: return null if (paths.size <= 1) return null paths.removeAt(paths.lastIndex) - return paths.lastOrNull() + return paths.lastOrNull().also { target -> + Log.d(TAG, "$DEBUG_PREFIX coordinator.pop target=$target ${debugState()} canPop=${canPop()}") + } } } diff --git a/android/app/src/main/java/com/logseq/app/UILocal.kt b/android/app/src/main/java/com/logseq/app/UILocal.kt index 37923da853..4d2ccdda1e 100644 --- a/android/app/src/main/java/com/logseq/app/UILocal.kt +++ b/android/app/src/main/java/com/logseq/app/UILocal.kt @@ -2,6 +2,7 @@ package com.logseq.app import android.app.DatePickerDialog import android.content.Intent +import android.util.Log import android.view.View import android.view.ViewGroup import android.widget.DatePicker @@ -21,6 +22,7 @@ class UILocal : Plugin() { private var toast: Toast? = null companion object { const val ACTION_ROUTE_CHANGED = "com.logseq.app.ROUTE_DID_CHANGE" + private const val DEBUG_PREFIX = "[DEBUG-navstack]" } @PluginMethod @@ -119,6 +121,11 @@ class UILocal : Plugin() { val path = call.getString("path") ?: "/" val stack = call.getString("stack") ?: "home" + Log.d( + "NavStack", + "$DEBUG_PREFIX uiLocal.routeDidChange stack=$stack type=$navigationType push=$push path=$path" + ) + // Drive Compose Nav for native animations/back handling. ComposeHost.applyNavigation(navigationType, path)