--- a/ui/common/build.gradle.kts	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/build.gradle.kts	Thu Apr 24 18:10:07 2025 -0400
@@ -63,6 +63,7 @@
 
         androidMain.dependencies {
             api(libs.androidx.activity)
+            implementation(libs.androidx.activity.compose)
             api(libs.geekdroid)
         }
     }
--- a/ui/common/src/androidMain/kotlin/com/geekorum/aboutoss/ui/common/AndroidBrowserLauncher.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/androidMain/kotlin/com/geekorum/aboutoss/ui/common/AndroidBrowserLauncher.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -21,20 +21,25 @@
  */
 package com.geekorum.aboutoss.ui.common
 
+import android.app.Activity
 import android.content.Context
+import androidx.activity.compose.LocalActivity
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.remember
 import androidx.core.net.toUri
 import com.geekorum.geekdroid.network.BrowserLauncher as GeekdroidBrowserLauncher
 
 class AndroidBrowserLauncher(
-    private val context: Context,
+    private val activity: Activity,
     private val delegate: GeekdroidBrowserLauncher
 ) : BrowserLauncher {
-    override fun warmUp() {
+    fun warmUp() {
         delegate.warmUp(null)
     }
 
     override fun launchUrl(link: String) {
-        delegate.launchUrl(context, link.toUri(), null as GeekdroidBrowserLauncher.LaunchCustomizer?)
+        delegate.launchUrl(activity, link.toUri(), null as GeekdroidBrowserLauncher.LaunchCustomizer?)
     }
 
     override fun mayLaunchUrl(vararg uris: String) {
@@ -42,7 +47,25 @@
         delegate.mayLaunchUrl(*asUris)
     }
 
-    override fun shutdown() {
+    fun shutdown() {
         delegate.shutdown()
     }
+}
+
+@Composable
+actual fun rememberBrowserLauncher(): BrowserLauncher {
+    val activity = checkNotNull(LocalActivity.current)
+    val result = remember(activity) {
+        val application = activity.application
+        val delegate =
+            GeekdroidBrowserLauncher(application, application.packageManager)
+        AndroidBrowserLauncher(activity, delegate)
+    }
+    DisposableEffect(result) {
+        result.warmUp()
+        onDispose {
+            result.shutdown()
+        }
+    }
+    return result
 }
\ No newline at end of file
--- a/ui/common/src/androidMain/kotlin/com/geekorum/aboutoss/ui/common/OpenSourceLicensesViewModel.android.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/androidMain/kotlin/com/geekorum/aboutoss/ui/common/OpenSourceLicensesViewModel.android.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -25,17 +25,12 @@
 import androidx.lifecycle.viewmodel.initializer
 import androidx.lifecycle.viewmodel.viewModelFactory
 import com.geekorum.aboutoss.core.LicenseInfoRepository
-import com.geekorum.geekdroid.network.BrowserLauncher as GeekdroidBrowserLauncher
 
 
 fun OpenSourceLicensesViewModel.Companion.Factory(licenseInfoRepository: LicenseInfoRepository) = viewModelFactory {
     initializer {
-        val application = this[APPLICATION_KEY]!!
-        val geekdroidBrowserLauncher = GeekdroidBrowserLauncher(application, application.packageManager)
-        val browserLauncher = AndroidBrowserLauncher(application, geekdroidBrowserLauncher)
         OpenSourceLicensesViewModel(
             licenseInfoRepository,
-            browserLauncher
         )
     }
 }
\ No newline at end of file
--- a/ui/common/src/commonMain/kotlin/BrowserLauncher.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/commonMain/kotlin/BrowserLauncher.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -21,16 +21,19 @@
  */
 package com.geekorum.aboutoss.ui.common
 
+import androidx.compose.runtime.Composable
+
 
 /**
  * Interface to be able to launch a browser to display a link
  */
 interface BrowserLauncher {
-    fun warmUp()
 
     fun launchUrl(link: String)
 
     fun mayLaunchUrl(vararg uris: String)
 
-    fun shutdown()
-}
\ No newline at end of file
+}
+
+@Composable
+expect fun rememberBrowserLauncher(): BrowserLauncher
\ No newline at end of file
--- a/ui/common/src/commonMain/kotlin/OpenSourceLicensesViewModel.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/commonMain/kotlin/OpenSourceLicensesViewModel.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -34,11 +34,7 @@
  */
 class OpenSourceLicensesViewModel(
     private val licenseInfoRepository: LicenseInfoRepository,
-    private val browserLauncher: BrowserLauncher,
 ) : ViewModel() {
-    init {
-        browserLauncher.warmUp()
-    }
 
     private val licensesInfo = flow {
         emit(licenseInfoRepository.getLicensesInfo())
@@ -52,15 +48,5 @@
         emit(licenseInfoRepository.getLicenseFor(dependency))
     }
 
-    fun openLinkInBrowser(link: String) {
-        browserLauncher.launchUrl(link)
-    }
-
-    fun mayLaunchUrl(vararg uris: String) = browserLauncher.mayLaunchUrl(*uris)
-
-    override fun onCleared() {
-        browserLauncher.shutdown()
-    }
-
     companion object
 }
\ No newline at end of file
--- a/ui/common/src/desktopMain/kotlin/DesktopBrowserLauncher.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/desktopMain/kotlin/DesktopBrowserLauncher.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -21,6 +21,8 @@
  */
 package com.geekorum.aboutoss.ui.common
 
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import java.awt.Desktop
 import java.net.URI
 import java.util.Locale
@@ -39,9 +41,6 @@
 
     private val openCommandLauncher = OpenCommandLauncher()
 
-    override fun warmUp() {
-    }
-
     override fun launchUrl(link: String) {
         try {
             desktopLauncher?.launchUrl(link)
@@ -63,8 +62,11 @@
     override fun mayLaunchUrl(vararg uris: String) {
     }
 
-    override fun shutdown() {
-    }
+}
+
+@Composable
+actual fun rememberBrowserLauncher(): BrowserLauncher {
+    return remember { DesktopBrowserLauncher() }
 }
 
 private interface Launcher {
--- a/ui/common/src/desktopMain/kotlin/OpenSourceLicensesViewModel.desktop.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/desktopMain/kotlin/OpenSourceLicensesViewModel.desktop.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -28,10 +28,6 @@
 
 fun OpenSourceLicensesViewModel.Companion.Factory(licenseInfoRepository: LicenseInfoRepository) = viewModelFactory {
     initializer {
-        val browserLauncher = DesktopBrowserLauncher()
-        OpenSourceLicensesViewModel(
-            licenseInfoRepository,
-            browserLauncher
-        )
+        OpenSourceLicensesViewModel(licenseInfoRepository)
     }
 }
\ No newline at end of file
--- a/ui/common/src/iosMain/kotlin/IosBrowserLauncher.kt	Wed Apr 23 14:43:46 2025 -0400
+++ b/ui/common/src/iosMain/kotlin/IosBrowserLauncher.kt	Thu Apr 24 18:10:07 2025 -0400
@@ -21,12 +21,13 @@
  */
 package com.geekorum.aboutoss.ui.common
 
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
 import platform.Foundation.NSURL.Companion.URLWithString
 import platform.UIKit.UIApplication
 
 
 class IosBrowserLauncher : BrowserLauncher {
-    override fun warmUp() {}
 
     override fun launchUrl(link: String) {
         UIApplication.sharedApplication.openURL(
@@ -37,6 +38,9 @@
     }
 
     override fun mayLaunchUrl(vararg uris: String) {}
+}
 
-    override fun shutdown() {}
+@Composable
+actual fun rememberBrowserLauncher(): BrowserLauncher {
+    return remember { IosBrowserLauncher() }
 }
\ No newline at end of file