diff --git a/core/src/main/kotlin/dev/hotwire/core/bridge/Bridge.kt b/core/src/main/kotlin/dev/hotwire/core/bridge/Bridge.kt index 0132a5a..9a0fd2d 100644 --- a/core/src/main/kotlin/dev/hotwire/core/bridge/Bridge.kt +++ b/core/src/main/kotlin/dev/hotwire/core/bridge/Bridge.kt @@ -3,7 +3,8 @@ package dev.hotwire.core.bridge import android.webkit.JavascriptInterface import android.webkit.WebView import androidx.annotation.VisibleForTesting -import dev.hotwire.core.logging.logEvent +import dev.hotwire.core.logging.logDebug +import dev.hotwire.core.logging.logVerbose import kotlinx.serialization.json.JsonElement import java.lang.ref.WeakReference @@ -30,37 +31,37 @@ class Bridge internal constructor(webView: WebView) { } internal fun register(component: String) { - logEvent("bridgeWillRegisterComponent", component) + logDebug("bridgeWillRegisterComponent", component) val javascript = generateJavaScript("register", component.toJsonElement()) evaluate(javascript) } internal fun register(components: List) { - logEvent("bridgeWillRegisterComponents", components.joinToString()) + logDebug("bridgeWillRegisterComponents", components.joinToString()) val javascript = generateJavaScript("register", components.toJsonElement()) evaluate(javascript) } internal fun unregister(component: String) { - logEvent("bridgeWillUnregisterComponent", component) + logDebug("bridgeWillUnregisterComponent", component) val javascript = generateJavaScript("unregister", component.toJsonElement()) evaluate(javascript) } internal fun replyWith(message: Message) { - logEvent("bridgeWillReplyWithMessage", message.toString()) + logDebug("bridgeWillReplyWithMessage", message.toString()) val internalMessage = InternalMessage.fromMessage(message) val javascript = generateJavaScript("replyWith", internalMessage.toJson().toJsonElement()) evaluate(javascript) } internal fun load() { - logEvent("bridgeWillLoad") + logDebug("bridgeWillLoad") evaluate(userScript()) } internal fun reset() { - logEvent("bridgeDidReset") + logDebug("bridgeDidReset") componentsAreRegistered = false } @@ -70,7 +71,7 @@ class Bridge internal constructor(webView: WebView) { @JavascriptInterface fun bridgeDidInitialize() { - logEvent("bridgeDidInitialize", "success") + logDebug("bridgeDidInitialize", "success") runOnUiThread { delegate?.bridgeDidInitialize() } @@ -78,7 +79,7 @@ class Bridge internal constructor(webView: WebView) { @JavascriptInterface fun bridgeDidUpdateSupportedComponents() { - logEvent("bridgeDidUpdateSupportedComponents", "success") + logDebug("bridgeDidUpdateSupportedComponents", "success") componentsAreRegistered = true } @@ -99,7 +100,7 @@ class Bridge internal constructor(webView: WebView) { } internal fun evaluate(javascript: String) { - logEvent("evaluatingJavascript", javascript) + logVerbose("evaluatingJavascript", javascript) webView?.evaluateJavascript(javascript) {} } diff --git a/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeComponentJsonConverter.kt b/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeComponentJsonConverter.kt index 4a5763c..be13a71 100644 --- a/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeComponentJsonConverter.kt +++ b/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeComponentJsonConverter.kt @@ -2,7 +2,6 @@ package dev.hotwire.core.bridge import dev.hotwire.core.config.Hotwire import dev.hotwire.core.logging.logError -import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json abstract class BridgeComponentJsonConverter { diff --git a/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeDelegate.kt b/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeDelegate.kt index cf14a4c..100a89f 100644 --- a/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeDelegate.kt +++ b/core/src/main/kotlin/dev/hotwire/core/bridge/BridgeDelegate.kt @@ -3,7 +3,7 @@ package dev.hotwire.core.bridge import android.webkit.WebView import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner -import dev.hotwire.core.logging.logEvent +import dev.hotwire.core.logging.logDebug import dev.hotwire.core.logging.logWarning @Suppress("unused") @@ -63,7 +63,7 @@ class BridgeDelegate( internal fun bridgeDidReceiveMessage(message: Message): Boolean { return if (destinationIsActive && resolvedLocation == message.metadata?.url) { - logEvent("bridgeDidReceiveMessage", message.toString()) + logDebug("bridgeDidReceiveMessage", message.toString()) getOrCreateComponent(message.component)?.didReceive(message) true } else { @@ -79,7 +79,7 @@ class BridgeDelegate( // Lifecycle events override fun onStart(owner: LifecycleOwner) { - logEvent("bridgeDestinationDidStart", resolvedLocation) + logDebug("bridgeDestinationDidStart", resolvedLocation) destinationIsActive = true activeComponents.forEach { it.didStart() } } @@ -87,12 +87,12 @@ class BridgeDelegate( override fun onStop(owner: LifecycleOwner) { activeComponents.forEach { it.didStop() } destinationIsActive = false - logEvent("bridgeDestinationDidStop", resolvedLocation) + logDebug("bridgeDestinationDidStop", resolvedLocation) } override fun onDestroy(owner: LifecycleOwner) { destinationIsActive = false - logEvent("bridgeDestinationDidDestroy", resolvedLocation) + logDebug("bridgeDestinationDidDestroy", resolvedLocation) } // Retrieve component(s) by type diff --git a/core/src/main/kotlin/dev/hotwire/core/bridge/JsonExtensions.kt b/core/src/main/kotlin/dev/hotwire/core/bridge/JsonExtensions.kt index df27132..49b97b1 100644 --- a/core/src/main/kotlin/dev/hotwire/core/bridge/JsonExtensions.kt +++ b/core/src/main/kotlin/dev/hotwire/core/bridge/JsonExtensions.kt @@ -1,7 +1,6 @@ package dev.hotwire.core.bridge import dev.hotwire.core.logging.logError -import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.decodeFromJsonElement diff --git a/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt b/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt index 90f5aee..5705ab0 100644 --- a/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt +++ b/core/src/main/kotlin/dev/hotwire/core/config/HotwireConfig.kt @@ -5,8 +5,9 @@ import android.webkit.WebView import dev.hotwire.core.bridge.BridgeComponent import dev.hotwire.core.bridge.BridgeComponentFactory import dev.hotwire.core.bridge.BridgeComponentJsonConverter +import dev.hotwire.core.logging.DefaultHotwireLogger +import dev.hotwire.core.logging.HotwireLogger import dev.hotwire.core.turbo.config.PathConfiguration -import dev.hotwire.core.turbo.http.HotwireHttpClient import dev.hotwire.core.turbo.offline.OfflineRequestHandler import dev.hotwire.core.turbo.webview.HotwireWebView @@ -32,16 +33,12 @@ class HotwireConfig internal constructor() { var offlineRequestHandler: OfflineRequestHandler? = null /** - * Enables/disables debug logging. This should be disabled in production environments. - * Disabled by default. + * Set a custom logger to handle debug messages. * - * Important: You should not enable debug logging in production release builds. + * The default logger is [DefaultHotwireLogger] which prints logs to Logcat. + * If you'd like to change this behavior, provide your own implementation of [HotwireLogger]. */ - var debugLoggingEnabled = false - set(value) { - field = value - HotwireHttpClient.reset() - } + var logger: HotwireLogger = DefaultHotwireLogger /** * Enables/disables debugging of web contents loaded into WebViews. diff --git a/core/src/main/kotlin/dev/hotwire/core/files/delegates/FileChooserDelegate.kt b/core/src/main/kotlin/dev/hotwire/core/files/delegates/FileChooserDelegate.kt index a03fcb5..59dfd51 100644 --- a/core/src/main/kotlin/dev/hotwire/core/files/delegates/FileChooserDelegate.kt +++ b/core/src/main/kotlin/dev/hotwire/core/files/delegates/FileChooserDelegate.kt @@ -8,10 +8,10 @@ import android.webkit.ValueCallback import android.webkit.WebChromeClient.FileChooserParams import androidx.activity.result.ActivityResult import dev.hotwire.core.R -import dev.hotwire.core.logging.logError -import dev.hotwire.core.turbo.session.Session import dev.hotwire.core.files.util.HOTWIRE_REQUEST_CODE_FILES import dev.hotwire.core.files.util.HotwireFileProvider +import dev.hotwire.core.logging.logError +import dev.hotwire.core.turbo.session.Session import dev.hotwire.core.turbo.util.dispatcherProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job diff --git a/core/src/main/kotlin/dev/hotwire/core/logging/CoreLog.kt b/core/src/main/kotlin/dev/hotwire/core/logging/CoreLog.kt index 3533bfd..4e6657e 100644 --- a/core/src/main/kotlin/dev/hotwire/core/logging/CoreLog.kt +++ b/core/src/main/kotlin/dev/hotwire/core/logging/CoreLog.kt @@ -1,45 +1,47 @@ package dev.hotwire.core.logging -import android.util.Log import dev.hotwire.core.config.Hotwire +import okhttp3.logging.HttpLoggingInterceptor -internal object CoreLog { - private const val DEFAULT_TAG = "Hotwire-Core" - - private val debugEnabled get() = Hotwire.config.debugLoggingEnabled - - internal fun d(msg: String) = log(Log.DEBUG, msg) - - internal fun w(msg: String) = log(Log.WARN, msg) - - internal fun e(msg: String) = log(Log.ERROR, msg) +private const val DEFAULT_TAG = "Hotwire-Core" +private const val PAD_END_LENGTH = 35 - private fun log(logLevel: Int, msg: String) { - when (logLevel) { - Log.DEBUG -> if (debugEnabled) Log.d(DEFAULT_TAG, msg) - Log.WARN -> Log.w(DEFAULT_TAG, msg) - Log.ERROR -> Log.e(DEFAULT_TAG, msg) - } +internal class HotwireHttpLogger : HttpLoggingInterceptor.Logger { + override fun log(message: String) { + Hotwire.config.logger.d(DEFAULT_TAG) { message } } } -private const val PAD_END_LENGTH = 35 +internal fun logVerbose(event: String, details: String = "") { + Hotwire.config.logger.v(DEFAULT_TAG) { + "${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]" + } +} -internal fun logEvent(event: String, details: String = "") { - CoreLog.d("$event ".padEnd(PAD_END_LENGTH, '.') + " [$details]") +internal fun logDebug(event: String, details: String = "") { + Hotwire.config.logger.d(DEFAULT_TAG) { + "${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]" + } } -internal fun logEvent(event: String, attributes: List>) { - val description = attributes.joinToString(prefix = "[", postfix = "]", separator = ", ") { - "${it.first}: ${it.second}" +internal fun logDebug(event: String, attributes: List>) { + Hotwire.config.logger.d(DEFAULT_TAG) { + val description = attributes.joinToString(prefix = "[", postfix = "]", separator = ", ") { + "${it.first}: ${it.second}" + } + + "${"$event ".padEnd(PAD_END_LENGTH, '.')} $description" } - CoreLog.d("$event ".padEnd(PAD_END_LENGTH, '.') + " $description") } internal fun logWarning(event: String, details: String) { - CoreLog.w("$event ".padEnd(PAD_END_LENGTH, '.') + " [$details]") + Hotwire.config.logger.w(DEFAULT_TAG) { + "${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]" + } } -internal fun logError(event: String, error: Exception) { - CoreLog.e("$event: ${error.stackTraceToString()}") -} +internal fun logError(event: String, throwable: Throwable) { + Hotwire.config.logger.e(DEFAULT_TAG, throwable) { + "$event: ${throwable.stackTraceToString()}" + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/hotwire/core/logging/DefaultHotwireLogger.kt b/core/src/main/kotlin/dev/hotwire/core/logging/DefaultHotwireLogger.kt new file mode 100644 index 0000000..8087b5b --- /dev/null +++ b/core/src/main/kotlin/dev/hotwire/core/logging/DefaultHotwireLogger.kt @@ -0,0 +1,37 @@ +package dev.hotwire.core.logging + +import android.util.Log + +internal object DefaultHotwireLogger : HotwireLogger { + override var logLevel = HotwireLogLevel.NONE + + override fun v(tag: String, msg: () -> String) { + if (logLevel.priority <= HotwireLogLevel.VERBOSE.priority) { + Log.v(tag, msg()) + } + } + + override fun d(tag: String, msg: () -> String) { + if (logLevel.priority <= HotwireLogLevel.DEBUG.priority) { + Log.d(tag, msg()) + } + } + + override fun i(tag: String, msg: () -> String) { + if (logLevel.priority <= HotwireLogLevel.INFO.priority) { + Log.i(tag, msg()) + } + } + + override fun w(tag: String, msg: () -> String) { + if (logLevel.priority <= HotwireLogLevel.WARN.priority) { + Log.w(tag, msg()) + } + } + + override fun e(tag: String, throwable: Throwable?, msg: () -> String) { + if (logLevel.priority <= HotwireLogLevel.ERROR.priority) { + Log.e(tag, msg(), throwable) + } + } +} diff --git a/core/src/main/kotlin/dev/hotwire/core/logging/HotwireLogLevel.kt b/core/src/main/kotlin/dev/hotwire/core/logging/HotwireLogLevel.kt new file mode 100644 index 0000000..7fc192b --- /dev/null +++ b/core/src/main/kotlin/dev/hotwire/core/logging/HotwireLogLevel.kt @@ -0,0 +1,10 @@ +package dev.hotwire.core.logging + +enum class HotwireLogLevel(val priority: Int) { + VERBOSE(0), + DEBUG(1), + INFO(2), + WARN(3), + ERROR(4), + NONE(5) +} diff --git a/core/src/main/kotlin/dev/hotwire/core/logging/HotwireLogger.kt b/core/src/main/kotlin/dev/hotwire/core/logging/HotwireLogger.kt new file mode 100644 index 0000000..387cf82 --- /dev/null +++ b/core/src/main/kotlin/dev/hotwire/core/logging/HotwireLogger.kt @@ -0,0 +1,10 @@ +package dev.hotwire.core.logging + +interface HotwireLogger { + var logLevel: HotwireLogLevel + fun v(tag: String, msg: () -> String) + fun d(tag: String, msg: () -> String) + fun i(tag: String, msg: () -> String) + fun w(tag: String, msg: () -> String) + fun e(tag: String, throwable: Throwable?, msg: () -> String) +} \ No newline at end of file diff --git a/core/src/main/kotlin/dev/hotwire/core/turbo/config/PathConfigurationLoader.kt b/core/src/main/kotlin/dev/hotwire/core/turbo/config/PathConfigurationLoader.kt index 296ca73..0b5c297 100644 --- a/core/src/main/kotlin/dev/hotwire/core/turbo/config/PathConfigurationLoader.kt +++ b/core/src/main/kotlin/dev/hotwire/core/turbo/config/PathConfigurationLoader.kt @@ -3,7 +3,7 @@ package dev.hotwire.core.turbo.config import android.content.Context import com.google.gson.reflect.TypeToken import dev.hotwire.core.logging.logError -import dev.hotwire.core.logging.logEvent +import dev.hotwire.core.logging.logDebug import dev.hotwire.core.turbo.util.dispatcherProvider import dev.hotwire.core.turbo.util.toObject import kotlinx.coroutines.CoroutineScope @@ -42,7 +42,7 @@ internal class PathConfigurationLoader(val context: Context) : CoroutineScope { launch { repository.getRemoteConfiguration(url, options)?.let { json -> load(json)?.let { - logEvent("remotePathConfigurationLoaded", url) + logDebug("remotePathConfigurationLoaded", url) onCompletion(it) cacheConfigurationForUrl(url, it) } @@ -56,7 +56,7 @@ internal class PathConfigurationLoader(val context: Context) : CoroutineScope { ) { val json = repository.getBundledConfiguration(context, filePath) load(json)?.let { - logEvent("bundledPathConfigurationLoaded", filePath) + logDebug("bundledPathConfigurationLoaded", filePath) onCompletion(it) } } @@ -67,7 +67,7 @@ internal class PathConfigurationLoader(val context: Context) : CoroutineScope { ) { repository.getCachedConfigurationForUrl(context, url)?.let { json -> load(json)?.let { - logEvent("cachedPathConfigurationLoaded", url) + logDebug("cachedPathConfigurationLoaded", url) onCompletion(it) } } diff --git a/core/src/main/kotlin/dev/hotwire/core/turbo/http/HotwireHttpClient.kt b/core/src/main/kotlin/dev/hotwire/core/turbo/http/HotwireHttpClient.kt index 512c06a..f908a7c 100644 --- a/core/src/main/kotlin/dev/hotwire/core/turbo/http/HotwireHttpClient.kt +++ b/core/src/main/kotlin/dev/hotwire/core/turbo/http/HotwireHttpClient.kt @@ -1,7 +1,7 @@ package dev.hotwire.core.turbo.http import android.content.Context -import dev.hotwire.core.config.Hotwire +import dev.hotwire.core.logging.HotwireHttpLogger import dev.hotwire.core.logging.logError import okhttp3.Cache import okhttp3.OkHttpClient @@ -16,7 +16,7 @@ import java.util.concurrent.TimeUnit object HotwireHttpClient { private var cache: Cache? = null private var httpCacheSize = 100L * 1024L * 1024L // 100 MBs - private val loggingInterceptor = HttpLoggingInterceptor().apply { + private val loggingInterceptor = HttpLoggingInterceptor(logger = HotwireHttpLogger()).apply { level = HttpLoggingInterceptor.Level.BASIC } @@ -55,15 +55,12 @@ object HotwireHttpClient { .connectTimeout(10L, TimeUnit.SECONDS) .readTimeout(30L, TimeUnit.SECONDS) .writeTimeout(30L, TimeUnit.SECONDS) + .addInterceptor(loggingInterceptor) cache?.let { builder.cache(it) } - if (Hotwire.config.debugLoggingEnabled) { - builder.addInterceptor(loggingInterceptor) - } - return builder.build() } } diff --git a/core/src/main/kotlin/dev/hotwire/core/turbo/offline/OfflineWebViewRequestInterceptor.kt b/core/src/main/kotlin/dev/hotwire/core/turbo/offline/OfflineWebViewRequestInterceptor.kt index fb27df9..a70d45d 100644 --- a/core/src/main/kotlin/dev/hotwire/core/turbo/offline/OfflineWebViewRequestInterceptor.kt +++ b/core/src/main/kotlin/dev/hotwire/core/turbo/offline/OfflineWebViewRequestInterceptor.kt @@ -3,7 +3,7 @@ package dev.hotwire.core.turbo.offline import android.webkit.WebResourceRequest import android.webkit.WebResourceResponse import dev.hotwire.core.config.Hotwire -import dev.hotwire.core.logging.logEvent +import dev.hotwire.core.logging.logDebug import dev.hotwire.core.turbo.session.Session import dev.hotwire.core.turbo.util.isHttpGetRequest @@ -56,6 +56,6 @@ internal class OfflineWebViewRequestInterceptor(val session: Session) { val attributes = params.toMutableList().apply { add(0, "session" to session.sessionName) } - logEvent("interceptRequest", attributes) + logDebug("interceptRequest", attributes) } } diff --git a/core/src/main/kotlin/dev/hotwire/core/turbo/session/Session.kt b/core/src/main/kotlin/dev/hotwire/core/turbo/session/Session.kt index 7cb9d91..0fee3ce 100644 --- a/core/src/main/kotlin/dev/hotwire/core/turbo/session/Session.kt +++ b/core/src/main/kotlin/dev/hotwire/core/turbo/session/Session.kt @@ -23,7 +23,7 @@ import androidx.webkit.WebViewFeature.isFeatureSupported import dev.hotwire.core.config.Hotwire import dev.hotwire.core.files.delegates.FileChooserDelegate import dev.hotwire.core.files.delegates.GeolocationPermissionDelegate -import dev.hotwire.core.logging.logEvent +import dev.hotwire.core.logging.logDebug import dev.hotwire.core.logging.logWarning import dev.hotwire.core.turbo.errors.HttpError import dev.hotwire.core.turbo.errors.LoadError @@ -758,7 +758,7 @@ class Session( private fun logEvent(event: String, vararg params: Pair) { val attributes = params.toMutableList().apply { add(0, "session" to sessionName) } - logEvent(event, attributes) + logDebug(event, attributes) } diff --git a/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt b/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt index f9aa834..ef256d2 100644 --- a/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt +++ b/core/src/main/kotlin/dev/hotwire/core/turbo/webview/HotwireWebView.kt @@ -2,7 +2,6 @@ package dev.hotwire.core.turbo.webview import android.annotation.SuppressLint import android.content.Context -import android.content.res.Configuration import android.os.Build import android.util.AttributeSet import android.webkit.WebView diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts index 056d214..5805389 100644 --- a/demo/build.gradle.kts +++ b/demo/build.gradle.kts @@ -32,6 +32,7 @@ android { buildFeatures { viewBinding = true + buildConfig = true } compileOptions { diff --git a/demo/src/main/kotlin/dev/hotwire/demo/DemoApplication.kt b/demo/src/main/kotlin/dev/hotwire/demo/DemoApplication.kt index c759576..46bfe3b 100644 --- a/demo/src/main/kotlin/dev/hotwire/demo/DemoApplication.kt +++ b/demo/src/main/kotlin/dev/hotwire/demo/DemoApplication.kt @@ -1,10 +1,10 @@ package dev.hotwire.demo import android.app.Application -import dev.hotwire.core.BuildConfig import dev.hotwire.core.bridge.BridgeComponentFactory import dev.hotwire.core.bridge.KotlinXJsonConverter import dev.hotwire.core.config.Hotwire +import dev.hotwire.core.logging.HotwireLogLevel import dev.hotwire.core.turbo.config.PathConfiguration import dev.hotwire.demo.bridge.FormComponent import dev.hotwire.demo.bridge.MenuComponent @@ -52,9 +52,13 @@ class DemoApplication : Application() { ) // Set configuration options - Hotwire.config.debugLoggingEnabled = BuildConfig.DEBUG Hotwire.config.webViewDebuggingEnabled = BuildConfig.DEBUG Hotwire.config.jsonConverter = KotlinXJsonConverter() Hotwire.config.applicationUserAgentPrefix = "Hotwire Demo;" + Hotwire.config.logger.logLevel = if (BuildConfig.DEBUG) { + HotwireLogLevel.DEBUG + } else { + HotwireLogLevel.NONE + } } } diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/activities/HotwireActivityDelegate.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/activities/HotwireActivityDelegate.kt index 0bd3710..531a313 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/activities/HotwireActivityDelegate.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/activities/HotwireActivityDelegate.kt @@ -2,7 +2,7 @@ package dev.hotwire.navigation.activities import androidx.activity.OnBackPressedCallback import androidx.annotation.IdRes -import dev.hotwire.navigation.logging.logEvent +import dev.hotwire.navigation.logging.logDebug import dev.hotwire.navigation.navigator.Navigator import dev.hotwire.navigation.navigator.NavigatorConfiguration import dev.hotwire.navigation.navigator.NavigatorHost @@ -61,7 +61,7 @@ class HotwireActivityDelegate(val activity: HotwireActivity) { * you must update this whenever the current navigator changes. */ fun setCurrentNavigator(configuration: NavigatorConfiguration) { - logEvent("navigatorSetAsCurrent", listOf("navigator" to configuration.name)) + logDebug("navigatorSetAsCurrent", listOf("navigator" to configuration.name)) currentNavigatorHostId = configuration.navigatorHostId val navigatorHost = navigatorHosts[currentNavigatorHostId] @@ -71,7 +71,7 @@ class HotwireActivityDelegate(val activity: HotwireActivity) { } internal fun registerNavigatorHost(host: NavigatorHost) { - logEvent("navigatorRegistered", listOf("navigator" to host.navigator.configuration.name)) + logDebug("navigatorRegistered", listOf("navigator" to host.navigator.configuration.name)) if (navigatorHosts[host.id] == null) { navigatorHosts[host.id] = host @@ -84,12 +84,12 @@ class HotwireActivityDelegate(val activity: HotwireActivity) { } internal fun unregisterNavigatorHost(host: NavigatorHost) { - logEvent("navigatorUnregistered", listOf("navigator" to host.navigator.configuration.name)) + logDebug("navigatorUnregistered", listOf("navigator" to host.navigator.configuration.name)) navigatorHosts.remove(host.id) } internal fun onNavigatorHostReady(host: NavigatorHost) { - logEvent("navigatorReady", listOf("navigator" to host.navigator.configuration.name)) + logDebug("navigatorReady", listOf("navigator" to host.navigator.configuration.name)) activity.onNavigatorReady(host.navigator) } diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/config/HotwireNavigation.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/config/HotwireNavigation.kt index 0d692e6..7137fe4 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/config/HotwireNavigation.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/config/HotwireNavigation.kt @@ -9,8 +9,8 @@ import dev.hotwire.navigation.fragments.HotwireWebBottomSheetFragment import dev.hotwire.navigation.fragments.HotwireWebFragment import dev.hotwire.navigation.routing.AppNavigationRouteDecisionHandler import dev.hotwire.navigation.routing.BrowserTabRouteDecisionHandler -import dev.hotwire.navigation.routing.SystemNavigationRouteDecisionHandler import dev.hotwire.navigation.routing.Router +import dev.hotwire.navigation.routing.SystemNavigationRouteDecisionHandler import kotlin.reflect.KClass internal object HotwireNavigation { diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/destinations/HotwireDestination.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/destinations/HotwireDestination.kt index 34dd47a..b448437 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/destinations/HotwireDestination.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/destinations/HotwireDestination.kt @@ -1,23 +1,16 @@ package dev.hotwire.navigation.destinations import android.content.Intent -import android.os.Bundle import androidx.activity.result.ActivityResultLauncher import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import androidx.navigation.NavOptions -import androidx.navigation.navOptions import dev.hotwire.core.bridge.BridgeDestination import dev.hotwire.core.config.Hotwire import dev.hotwire.core.turbo.config.PathConfigurationProperties import dev.hotwire.core.turbo.config.context -import dev.hotwire.core.turbo.config.presentation -import dev.hotwire.core.turbo.nav.Presentation import dev.hotwire.core.turbo.nav.PresentationContext import dev.hotwire.core.turbo.visit.VisitAction -import dev.hotwire.navigation.R -import dev.hotwire.navigation.activities.HotwireActivity -import dev.hotwire.navigation.config.HotwireNavigation import dev.hotwire.navigation.fragments.HotwireFragmentDelegate import dev.hotwire.navigation.fragments.HotwireFragmentViewModel import dev.hotwire.navigation.navigator.Navigator diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireFragmentDelegate.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireFragmentDelegate.kt index 265e0e0..dc5645b 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireFragmentDelegate.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireFragmentDelegate.kt @@ -1,7 +1,7 @@ package dev.hotwire.navigation.fragments -import dev.hotwire.navigation.logging.logEvent import dev.hotwire.navigation.destinations.HotwireDestination +import dev.hotwire.navigation.logging.logDebug import dev.hotwire.navigation.navigator.navigatorName import dev.hotwire.navigation.session.SessionModalResult import dev.hotwire.navigation.session.SessionViewModel @@ -119,6 +119,6 @@ class HotwireFragmentDelegate(private val navDestination: HotwireDestination) { add(0, "navigator" to navigator.configuration.name) add("fragment" to fragment.javaClass.simpleName) } - logEvent(event, attributes) + logDebug(event, attributes) } } diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireWebFragmentCallback.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireWebFragmentCallback.kt index b0c272b..7e84d67 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireWebFragmentCallback.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireWebFragmentCallback.kt @@ -3,9 +3,9 @@ package dev.hotwire.navigation.fragments import android.view.View import android.webkit.HttpAuthHandler import dev.hotwire.core.turbo.errors.VisitError -import dev.hotwire.navigation.views.HotwireView import dev.hotwire.core.turbo.webview.HotwireWebChromeClient import dev.hotwire.core.turbo.webview.HotwireWebView +import dev.hotwire.navigation.views.HotwireView /** * Callback interface to be implemented by a [HotwireWebFragment], diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/logging/NavigationLog.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/logging/NavigationLog.kt index 13a4eb6..e15a6d8 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/logging/NavigationLog.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/logging/NavigationLog.kt @@ -1,45 +1,34 @@ package dev.hotwire.navigation.logging -import android.util.Log import dev.hotwire.core.config.Hotwire -internal object NavigationLog { - private const val DEFAULT_TAG = "Hotwire-Navigation" - - private val debugEnabled get() = Hotwire.config.debugLoggingEnabled - - internal fun d(msg: String) = log(Log.DEBUG, msg) - - internal fun w(msg: String) = log(Log.WARN, msg) - - internal fun e(msg: String) = log(Log.ERROR, msg) +private const val DEFAULT_TAG = "Hotwire-Navigation" +private const val PAD_END_LENGTH = 35 - private fun log(logLevel: Int, msg: String) { - when (logLevel) { - Log.DEBUG -> if (debugEnabled) Log.d(DEFAULT_TAG, msg) - Log.WARN -> Log.w(DEFAULT_TAG, msg) - Log.ERROR -> Log.e(DEFAULT_TAG, msg) - } +internal fun logDebug(event: String, details: String = "") { + Hotwire.config.logger.d(DEFAULT_TAG) { + "${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]" } } -private const val PAD_END_LENGTH = 35 - -internal fun logEvent(event: String, details: String = "") { - NavigationLog.d("$event ".padEnd(PAD_END_LENGTH, '.') + " [$details]") -} +internal fun logDebug(event: String, attributes: List>) { + Hotwire.config.logger.d(DEFAULT_TAG) { + val description = attributes.joinToString(prefix = "[", postfix = "]", separator = ", ") { + "${it.first}: ${it.second}" + } -internal fun logEvent(event: String, attributes: List>) { - val description = attributes.joinToString(prefix = "[", postfix = "]", separator = ", ") { - "${it.first}: ${it.second}" + "${"$event ".padEnd(PAD_END_LENGTH, '.')} $description" } - NavigationLog.d("$event ".padEnd(PAD_END_LENGTH, '.') + " $description") } internal fun logWarning(event: String, details: String) { - NavigationLog.w("$event ".padEnd(PAD_END_LENGTH, '.') + " [$details]") + Hotwire.config.logger.w(DEFAULT_TAG) { + "${"$event ".padEnd(PAD_END_LENGTH, '.')} [$details]" + } } -internal fun logError(event: String, error: Exception) { - NavigationLog.e("$event: ${error.stackTraceToString()}") +internal fun logError(event: String, throwable: Throwable) { + Hotwire.config.logger.e(DEFAULT_TAG, throwable) { + "$event: ${throwable.stackTraceToString()}" + } } diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt index e63b785..b955eb3 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt @@ -18,7 +18,7 @@ import dev.hotwire.navigation.config.HotwireNavigation import dev.hotwire.navigation.destinations.HotwireDestination import dev.hotwire.navigation.destinations.HotwireDestinationAnimations import dev.hotwire.navigation.destinations.HotwireDialogDestination -import dev.hotwire.navigation.logging.logEvent +import dev.hotwire.navigation.logging.logDebug import dev.hotwire.navigation.routing.Router import dev.hotwire.navigation.session.SessionModalResult import dev.hotwire.navigation.session.SessionViewModel @@ -471,6 +471,6 @@ class Navigator( add(0, "navigator" to configuration.name) add("currentFragment" to (destinationName ?: "NONE")) } - logEvent(event, attributes) + logDebug(event, attributes) } } diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/NavigatorArguments.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/NavigatorArguments.kt index 2b3b42b..818da55 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/NavigatorArguments.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/NavigatorArguments.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.os.Bundle import dev.hotwire.core.turbo.nav.PresentationContext import dev.hotwire.navigation.logging.logError -import kotlin.text.uppercase internal const val ARG_LOCATION = "location" internal const val ARG_NAVIGATOR_NAME = "navigator-name" diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/routing/Router.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/routing/Router.kt index c55ecf3..6163668 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/routing/Router.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/routing/Router.kt @@ -1,9 +1,8 @@ package dev.hotwire.navigation.routing import dev.hotwire.navigation.activities.HotwireActivity -import dev.hotwire.navigation.logging.logEvent +import dev.hotwire.navigation.logging.logDebug import dev.hotwire.navigation.navigator.NavigatorConfiguration -import dev.hotwire.navigation.routing.Router.RouteDecisionHandler /** * Routes location urls within in-app navigation or with custom behaviors @@ -62,7 +61,7 @@ class Router(private val decisionHandlers: List) { ): Decision { decisionHandlers.forEach { handler -> if (handler.matches(location, configuration)) { - logEvent("handlerMatch", listOf( + logDebug("handlerMatch", listOf( "handler" to handler.name, "location" to location )) @@ -71,7 +70,7 @@ class Router(private val decisionHandlers: List) { } } - logEvent("noHandlerForLocation", location) + logDebug("noHandlerForLocation", location) return Decision.CANCEL } } diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/util/HotwireViewScreenshotHolder.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/util/HotwireViewScreenshotHolder.kt index 58aa845..8937057 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/util/HotwireViewScreenshotHolder.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/util/HotwireViewScreenshotHolder.kt @@ -10,9 +10,8 @@ import android.os.Looper import android.view.PixelCopy import android.view.View import dev.hotwire.navigation.logging.logError -import dev.hotwire.navigation.logging.logEvent +import dev.hotwire.navigation.logging.logDebug import dev.hotwire.navigation.views.HotwireView -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.resume @@ -66,7 +65,7 @@ internal class HotwireViewScreenshotHolder { window, rect, bitmap, { result -> if (result == PixelCopy.SUCCESS) { - logEvent( + logDebug( "viewScreenshotCreated", listOf( "size" to "${bitmap.width}x${bitmap.height}", "duration" to "${System.currentTimeMillis() - start}ms", diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/views/HotwireView.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/views/HotwireView.kt index f51c0ba..14b83af 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/views/HotwireView.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/views/HotwireView.kt @@ -9,7 +9,10 @@ import android.view.ViewGroup import android.webkit.WebView import android.widget.FrameLayout import android.widget.ImageView -import androidx.core.view.* +import androidx.core.view.ScrollingView +import androidx.core.view.contains +import androidx.core.view.isVisible +import androidx.core.view.updateLayoutParams import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import dev.hotwire.navigation.R diff --git a/navigation-fragments/src/test/kotlin/dev/hotwire/navigation/navigator/NavigatorHostTest.kt b/navigation-fragments/src/test/kotlin/dev/hotwire/navigation/navigator/NavigatorHostTest.kt index d6ddec3..f1ec459 100644 --- a/navigation-fragments/src/test/kotlin/dev/hotwire/navigation/navigator/NavigatorHostTest.kt +++ b/navigation-fragments/src/test/kotlin/dev/hotwire/navigation/navigator/NavigatorHostTest.kt @@ -1,8 +1,6 @@ package dev.hotwire.navigation.navigator -import android.R.attr.host import android.content.Intent -import android.os.Bundle import androidx.core.os.bundleOf import dev.hotwire.navigation.activities.HotwireActivity import org.assertj.core.api.Assertions.assertThat