--- a/build.gradle.kts	Thu Apr 13 17:11:33 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-plugins {
-//alias(libs.plugins.com.android.library810.alpha11) apply false
-//    alias(libs.plugins.org.jetbrains.kotlin.android) apply false
-    //    alias(libs.plugins.com.android.application) apply false
-//    alias(libs.plugins.org.jetbrains.kotlin.android) apply false
-}
\ No newline at end of file
--- a/settings.gradle.kts	Thu Apr 13 17:11:33 2023 -0400
+++ b/settings.gradle.kts	Thu Apr 13 17:28:56 2023 -0400
@@ -20,3 +20,4 @@
 rootProject.name = "AboutOss"
 include(":core")
 include(":ui")
+include(":ui:common")
--- a/ui/build.gradle.kts	Thu Apr 13 17:11:33 2023 -0400
+++ b/ui/build.gradle.kts	Thu Apr 13 17:28:56 2023 -0400
@@ -42,7 +42,7 @@
 }
 
 dependencies {
-    implementation(project(":core"))
+    implementation(project(":ui:common"))
     implementation(platform(libs.androidx.compose.bom))
     implementation(libs.androidx.compose.material)
     implementation(libs.androidx.lifecycle.viewmodel)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/.gitignore	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,1 @@
+/build
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/build.gradle.kts	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,50 @@
+plugins {
+    id("com.android.library")
+    kotlin("android")
+    id("com.geekorum.build.source-license-checker")
+}
+
+android {
+    namespace = "com.geekorum.aboutoss.ui.common"
+    compileSdk = 33
+
+    defaultConfig {
+        minSdk = 28
+
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+        consumerProguardFiles("consumer-rules.pro")
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(
+                getDefaultProguardFile("proguard-android-optimize.txt"),
+                "proguard-rules.pro"
+            )
+        }
+    }
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+dependencies {
+    implementation(project(":core"))
+    implementation(libs.appcompat)
+    implementation(libs.androidx.lifecycle.viewmodel)
+    implementation(libs.androidx.activity)
+    implementation(libs.geekdroid) {
+        //TODO get rid of dagger platform in geekdroid
+        exclude("com.google.dagger", "dagger-platform")
+    }
+
+
+    testImplementation(libs.junit)
+    androidTestImplementation(libs.androidx.test.ext.junit)
+    androidTestImplementation(libs.espresso.core)
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/proguard-rules.pro	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/src/androidTest/java/com/geekorum/aboutoss/ui/common/ExampleInstrumentedTest.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,45 @@
+/*
+ * AboutOss is a utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.ui.common
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+    @Test
+    fun useAppContext() {
+        // Context of the app under test.
+        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+        assertEquals("com.geekorum.aboutoss.ui.common.test", appContext.packageName)
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/src/main/java/com/geekorum/aboutoss/ui/common/BaseOpensourceLicenseActivity.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,33 @@
+/*
+ * AboutOss is a utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.ui.common
+
+import androidx.activity.viewModels
+import androidx.appcompat.app.AppCompatActivity
+
+abstract class BaseOpensourceLicenseActivity : AppCompatActivity() {
+    protected val viewModel: OpenSourceLicensesViewModel by viewModels(
+        factoryProducer = {
+            OpenSourceLicensesViewModel.Factory
+        }
+    )
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/src/main/java/com/geekorum/aboutoss/ui/common/OpenSourceLicensesViewModel.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,87 @@
+/*
+ * AboutOss is a utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.ui.common
+
+import android.content.Context
+import android.net.Uri
+import androidx.core.net.toUri
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.initializer
+import androidx.lifecycle.viewmodel.viewModelFactory
+import com.geekorum.aboutoss.core.LicenseInfoRepository
+import com.geekorum.geekdroid.network.BrowserLauncher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+class OpenSourceLicensesViewModel constructor(
+    private val licenseInfoRepository: LicenseInfoRepository,
+    private val browserLauncher: BrowserLauncher,
+) : ViewModel() {
+    init {
+        browserLauncher.warmUp(null)
+    }
+
+    private val licensesInfo = flow {
+        emit(licenseInfoRepository.getLicensesInfo())
+    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyMap())
+
+    val dependenciesList = licensesInfo.map { licensesInfo ->
+        licensesInfo.keys.sortedBy { it.lowercase() }
+    }
+
+    fun getLicenseDependency(dependency: String) = flow {
+        emit(licenseInfoRepository.getLicenseFor(dependency))
+    }
+
+    fun openLinkInBrowser(context: Context, link: String) {
+        browserLauncher.launchUrl(context, link.toUri(),  null as BrowserLauncher.LaunchCustomizer?)
+    }
+
+    fun mayLaunchUrl(vararg uris: Uri) = browserLauncher.mayLaunchUrl(*uris)
+
+    override fun onCleared() {
+        browserLauncher.shutdown()
+    }
+
+    companion object {
+        val Factory = viewModelFactory {
+            initializer {
+                val application = this[APPLICATION_KEY]!!
+                val licenseInfoRepository = LicenseInfoRepository(
+                    appContext = application,
+                    mainCoroutineDispatcher = Dispatchers.Main,
+                    ioCoroutineDispatcher = Dispatchers.IO
+                )
+                val browserLauncher = BrowserLauncher(application, application.packageManager)
+                OpenSourceLicensesViewModel(
+                    licenseInfoRepository,
+                    browserLauncher
+                )
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/src/main/res/values/strings.xml	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+    AboutOss is a utility library to retrieve and display
+    opensource licenses in Android applications.
+
+    Copyright (C) 2023 by Frederic-Charles Barthelery.
+
+    This file is part of AboutOss.
+
+    AboutOss is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    AboutOss is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<resources>
+    <string name="title_oss_licenses">Opensource Licenses</string>
+</resources>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/common/src/test/java/com/geekorum/aboutoss/ui/common/ExampleUnitTest.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -0,0 +1,38 @@
+/*
+ * AboutOss is a utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.ui.common
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+    @Test
+    fun addition_isCorrect() {
+        assertEquals(4, 2 + 2)
+    }
+}
\ No newline at end of file
--- a/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceDependenciesListScreen.kt	Thu Apr 13 17:11:33 2023 -0400
+++ b/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceDependenciesListScreen.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -49,6 +49,8 @@
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
+import com.geekorum.aboutoss.ui.common.OpenSourceLicensesViewModel
+import com.geekorum.aboutoss.ui.common.R as commonR
 
 @Composable
 fun OpenSourceDependenciesListScreen(
@@ -81,7 +83,7 @@
         if (hasScrolled) 4.dp else 0.dp
     )
     Scaffold(topBar = {
-        TopAppBar(title = { Text(stringResource(R.string.title_oss_licenses)) },
+        TopAppBar(title = { Text(stringResource(commonR.string.title_oss_licenses)) },
             navigationIcon = {
                 IconButton(onClick = onUpClick) {
                     Icon(
--- a/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceLicenseScreen.kt	Thu Apr 13 17:11:33 2023 -0400
+++ b/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceLicenseScreen.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -56,6 +56,7 @@
 import androidx.compose.ui.text.withStyle
 import androidx.compose.ui.unit.dp
 import androidx.core.net.toUri
+import com.geekorum.aboutoss.ui.common.OpenSourceLicensesViewModel
 
 @Composable
 fun OpenSourceLicenseScreen(
--- a/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceLicensesActivity.kt	Thu Apr 13 17:11:33 2023 -0400
+++ b/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceLicensesActivity.kt	Thu Apr 13 17:28:56 2023 -0400
@@ -24,21 +24,15 @@
 import android.net.Uri
 import android.os.Bundle
 import androidx.activity.compose.setContent
-import androidx.activity.viewModels
-import androidx.appcompat.app.AppCompatActivity
 import androidx.compose.material.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.navigation.compose.NavHost
 import androidx.navigation.compose.composable
 import androidx.navigation.compose.rememberNavController
-
-class OpenSourceLicensesActivity : AppCompatActivity() {
+import com.geekorum.aboutoss.ui.common.BaseOpensourceLicenseActivity
+import com.geekorum.aboutoss.ui.common.OpenSourceLicensesViewModel
 
-    private val viewModel: OpenSourceLicensesViewModel by viewModels(
-        factoryProducer = {
-            OpenSourceLicensesViewModel.Factory
-        }
-    )
+class OpenSourceLicensesActivity : BaseOpensourceLicenseActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
--- a/ui/src/main/java/com/geekorum/aboutoss/ui/OpenSourceLicensesViewModel.kt	Thu Apr 13 17:11:33 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * AboutOss is a utility library to retrieve and display
- * opensource licenses in Android applications.
- *
- * Copyright (C) 2023 by Frederic-Charles Barthelery.
- *
- * This file is part of AboutOss.
- *
- * AboutOss is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AboutOss is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
- */
-package com.geekorum.aboutoss.ui
-
-import android.content.Context
-import android.net.Uri
-import androidx.core.net.toUri
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
-import androidx.lifecycle.viewModelScope
-import androidx.lifecycle.viewmodel.initializer
-import androidx.lifecycle.viewmodel.viewModelFactory
-import com.geekorum.aboutoss.core.LicenseInfoRepository
-import com.geekorum.geekdroid.network.BrowserLauncher
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.flow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
-
-class OpenSourceLicensesViewModel constructor(
-    private val licenseInfoRepository: LicenseInfoRepository,
-    private val browserLauncher: BrowserLauncher,
-) : ViewModel() {
-    init {
-        browserLauncher.warmUp(null)
-    }
-
-    private val licensesInfo = flow {
-        emit(licenseInfoRepository.getLicensesInfo())
-    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyMap())
-
-    val dependenciesList = licensesInfo.map { licensesInfo ->
-        licensesInfo.keys.sortedBy { it.lowercase() }
-    }
-
-    fun getLicenseDependency(dependency: String) = flow {
-        emit(licenseInfoRepository.getLicenseFor(dependency))
-    }
-
-    fun openLinkInBrowser(context: Context, link: String) {
-        browserLauncher.launchUrl(context, link.toUri(),  null as BrowserLauncher.LaunchCustomizer?)
-    }
-
-    fun mayLaunchUrl(vararg uris: Uri) = browserLauncher.mayLaunchUrl(*uris)
-
-    override fun onCleared() {
-        browserLauncher.shutdown()
-    }
-
-    companion object {
-        val Factory = viewModelFactory {
-            initializer {
-                val application = this[APPLICATION_KEY]!!
-                val licenseInfoRepository = LicenseInfoRepository(
-                    appContext = application,
-                    mainCoroutineDispatcher = Dispatchers.Main,
-                    ioCoroutineDispatcher = Dispatchers.IO
-                )
-                val browserLauncher = BrowserLauncher(application, application.packageManager)
-                OpenSourceLicensesViewModel(
-                    licenseInfoRepository,
-                    browserLauncher
-                )
-            }
-        }
-    }
-}
--- a/ui/src/main/res/values/strings.xml	Thu Apr 13 17:11:33 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-
-    AboutOss is a utility library to retrieve and display
-    opensource licenses in Android applications.
-
-    Copyright (C) 2023 by Frederic-Charles Barthelery.
-
-    This file is part of AboutOss.
-
-    AboutOss is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    AboutOss is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with AboutOss.  If not, see <http://www.gnu.org/licenses/>.
-
--->
-<resources>
-    <string name="title_oss_licenses">Opensource Licenses</string>
-</resources>
\ No newline at end of file