diff --git a/LICENSE b/LICENSE
index 48fbc0f..613662e 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,6 +2,8 @@ MIT License
Copyright (c) 2022 premex-byggappen
+Copyright (c) 2023 developers at @usefulness
+
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
@@ -18,4 +20,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
+SOFTWARE.
diff --git a/README.md b/README.md
index 98e2aa4..2917611 100644
--- a/README.md
+++ b/README.md
@@ -1,56 +1,47 @@
-# Gross
+# lincesee-for-android
+___
-Gradle Open Source Software
+Turn raw [cashapp/licensee](https://github.com/cashapp/licensee) report into assets/Kotlin code that can be easily consumed from an Android app
-## Plugin can be found at:
-https://plugins.gradle.org/plugin/se.premex.gross
+### Installation
-### Getting started
-Gross uses the output of another plugin which figures out all your dependencies: https://github.com/cashapp/licensee
+Available on:
-Add licensee and gross to your root project / module. We need both mavenCentral and gradle plugin portal for plugin resolution:
+- [Gradle Plugin Portal](https://plugins.gradle.org/plugin/io.github.usefulness.licensee-for-android)
+- [Maven Central](https://mvnrepository.com/artifact/io.github.usefulness/licensee-for-android)
-settings.gradle.kts
-```kotlin
-pluginManagement {
- repositories {
- gradlePluginPortal()
- }
-}
+#### Apply the plugin
-dependencyResolutionManagement {
- repositories {
- mavenCentral()
- }
+```groovy
+plugins {
+ id("app.cash.licensee") version "x.y.z"
+ id("io.github.usefulness.licensee-for-android") version "{{version}}"
}
```
-build.gradle.kts
-```kotlin
-buildscript {
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath("app.cash.licensee:licensee-gradle-plugin:1.7.0")
- }
-}
-plugins {
- id("app.cash.licensee")
- id("se.premex.gross") version "0.1.0"
+### Features
+- Access licenses report directly by a generated Kotlin code (accessible via static `io.github.usefulness.licensee.Licensee` object)
+- Read _licensee_ report copied to projects assets directory in runtime (via `assetManager.open("licensee_artifacts.json")`)
+
+### Configuration
+
+Options can be configured in the `licenseeForAndroid` extension:
+
+```groovy
+licenseeForAndroid {
+ enableKotlinCodeGeneration = false
+ enableAndroidAssetGeneration = true
+ androidAssetFileName = "licensee_artifacts.json"
+ singularVariantName = null
}
```
-### Gradle dsl:
-gross {
- enableKotlinCodeGeneration.set(true)
- enableAndroidAssetGeneration.set(true)
-}
+- `enableKotlinCodeGeneration` - Generates a static list of open source assets
+- `enableAndroidAssetGeneration` - Enable asset generation. Will copy licensee report to android asset directory making it available as `androidAssetFileName`
+- `androidAssetFileName` - The name of the asset file the licensee report gets copied to.
+- `singularVariantName` - The name of the build variant that all variants will use to have always the same licensed, regardless of app variant. (i.e. "productionRelease")
-## enableKotlinCodeGeneration
-Generates a static list of open source assets in Gross.artifacts.
-## enableAndroidAssetGeneration
-Saves licensee report as an android asset. Default name is 'artifacts.json' but can be configured
-using androidAssetFileName. Check out AssetLicenseParser for an example of how to consume the file.
+### Credits
+Huge thanks to [premex-ab/gross](https://github.com/premex-ab/gross) which this plugin forked from.
diff --git a/app/.gitignore b/app/.gitignore
deleted file mode 100644
index 42afabf..0000000
--- a/app/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
deleted file mode 100644
index 46e0eb8..0000000
--- a/app/build.gradle.kts
+++ /dev/null
@@ -1,93 +0,0 @@
-plugins {
- alias(libs.plugins.com.android.application)
- alias(libs.plugins.org.jetbrains.kotlin.android)
- alias(libs.plugins.app.cash.licensee)
- id("se.premex.gross")
-}
-
-licensee {
- allow("Apache-2.0")
-}
-
-gross {
- enableKotlinCodeGeneration.set(true)
- enableAndroidAssetGeneration.set(true)
-}
-android {
- namespace = "se.premex.gross"
- compileSdk = 33
-
- defaultConfig {
- applicationId = "se.premex.gross"
- minSdk = 24
- targetSdk = 33
- versionCode = 1
- versionName = "1.0"
-
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
- vectorDrawables {
- useSupportLibrary = true
- }
- }
-
- 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"
- }
- buildFeatures {
- compose = true
- }
- composeOptions {
- kotlinCompilerExtensionVersion = libs.versions.androidx.compose.compiler.get()
- }
- packagingOptions {
- resources {
- excludes += "/META-INF/{AL2.0,LGPL2.1}"
- }
- }
-}
-
-java {
- toolchain {
- languageVersion.set(JavaLanguageVersion.of(17))
- vendor.set(JvmVendorSpec.AZUL)
- }
-}
-
-dependencies {
-
- implementation(libs.core.ktx)
- implementation(libs.lifecycle.runtime.ktx)
- implementation(libs.activity.compose)
- implementation(platform(libs.androidx.compose.bom))
- implementation(libs.ui)
- implementation(libs.ui.graphics)
- implementation(libs.ui.tooling.preview)
- implementation(libs.material3)
-
- // In theory we should be able to refer to "se.premex.gross:ui-oss" here and set a mapping up
- // in the includeBuild like this
- // dependencySubstitution { substitute(module("se.premex.gross:ui-oss")).using(project(":oss")) }
- // Unfortunately this does not work - maybe same issue as https://youtrack.jetbrains.com/issue/KTIJ-13435
- implementation("se.premex.gross:ui:1.0")
-
- testImplementation(libs.junit)
- androidTestImplementation(libs.androidx.test.ext.junit)
- androidTestImplementation(libs.espresso.core)
- androidTestImplementation(platform(libs.androidx.compose.bom))
- androidTestImplementation(libs.ui.test.junit4)
- debugImplementation(libs.ui.tooling)
- debugImplementation(libs.ui.test.manifest)
-}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
deleted file mode 100644
index 481bb43..0000000
--- a/app/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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
diff --git a/app/src/androidTest/java/se/premex/gross/ExampleInstrumentedTest.kt b/app/src/androidTest/java/se/premex/gross/ExampleInstrumentedTest.kt
deleted file mode 100644
index 32c4448..0000000
--- a/app/src/androidTest/java/se/premex/gross/ExampleInstrumentedTest.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package se.premex.gross
-
-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("se.premex.gross", appContext.packageName)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
deleted file mode 100644
index c2a6060..0000000
--- a/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/se/premex/gross/MainActivity.kt b/app/src/main/java/se/premex/gross/MainActivity.kt
deleted file mode 100644
index 5e1f438..0000000
--- a/app/src/main/java/se/premex/gross/MainActivity.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package se.premex.gross
-
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.rounded.AddCircle
-import androidx.compose.material.icons.rounded.Create
-import androidx.compose.material3.BottomAppBar
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.NavigationBarItem
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Surface
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import se.premex.gross.ui.theme.GrossTheme
-
-enum class Views {
- Programmatic, AssetBased
-}
-
-class MainActivity : ComponentActivity() {
- @OptIn(ExperimentalMaterial3Api::class)
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- val selectedView = remember { mutableStateOf(Views.Programmatic) }
- GrossTheme {
- Scaffold(
- bottomBar = {
- BottomAppBar {
- NavigationBarItem(
- selected = false,
- onClick = {
- selectedView.value = Views.Programmatic
- },
- icon = {
- Icon(
- imageVector = Icons.Rounded.Create,
- contentDescription = stringResource(id = R.string.programmatic)
- )
- })
- NavigationBarItem(
- selected = false,
- onClick = {
- selectedView.value = Views.AssetBased
- },
- icon = {
- Icon(
- imageVector = Icons.Rounded.AddCircle,
- contentDescription = stringResource(id = R.string.assetBased)
- )
- })
- }
- }
- ) { paddingValues ->
- Surface(
- modifier = Modifier
- .fillMaxSize()
- .padding(paddingValues),
- color = MaterialTheme.colorScheme.background
- ) {
- when (selectedView.value) {
- Views.Programmatic -> ProgrammaticOssView()
- Views.AssetBased -> AssetsOssView()
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/se/premex/gross/OssArtifactView.kt b/app/src/main/java/se/premex/gross/OssArtifactView.kt
deleted file mode 100644
index b20f015..0000000
--- a/app/src/main/java/se/premex/gross/OssArtifactView.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package se.premex.gross
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
-import se.premex.gross.oss.R
-import se.premex.gross.ui.AssetLicenseParser
-import se.premex.gross.ui.ErrorView
-import se.premex.gross.ui.LoadingView
-import se.premex.gross.ui.OssView
-import se.premex.gross.ui.OssViewState
-import se.premex.gross.ui.State
-import java.io.IOException
-
-@Composable
-fun AssetsOssView() {
- val assetManager = LocalContext.current.assets
-
- val licenseParser = remember { AssetLicenseParser(assetManager) }
-
- val uiState = remember { mutableStateOf(OssViewState()) }
-
- LaunchedEffect(key1 = assetManager) {
- try {
- uiState.value =
- OssViewState(viewState = State.Success(data = licenseParser.readFromAssets()))
- } catch (ioException: IOException) {
- uiState.value =
- OssViewState(
- viewState = State.Failed(
- errorMessage = ioException.localizedMessage ?: ""
- )
- )
- }
- }
-
- when (val state = uiState.value.viewState) {
- is State.Failed -> ErrorView(stringResource(id = R.string.error), state.errorMessage)
- is State.Loading -> LoadingView(stringResource(id = R.string.loading))
- is State.Success -> {
- Column {
- Text(text = stringResource(id = se.premex.gross.R.string.assetBased))
-
- OssView(state.data)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/se/premex/gross/OssKotlinCodeView.kt b/app/src/main/java/se/premex/gross/OssKotlinCodeView.kt
deleted file mode 100644
index d800ee4..0000000
--- a/app/src/main/java/se/premex/gross/OssKotlinCodeView.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package se.premex.gross
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.res.stringResource
-import se.premex.gross.core.Artifact
-import se.premex.gross.core.Scm
-import se.premex.gross.core.SpdxLicenses
-import se.premex.gross.core.UnknownLicenses
-import se.premex.gross.ui.OssView
-
-@Composable
-fun ProgrammaticOssView() {
- Column {
- Text(text = stringResource(id = R.string.programmatic))
- OssView(Gross.artifacts.map { artifact ->
- Artifact(
- name = artifact.name,
- groupId = artifact.groupId,
- artifactId = artifact.artifactId,
- version = artifact.version,
- scm = if (artifact.scm?.url != null) {
- Scm(artifact.scm.url)
- } else {
- null
- },
- spdxLicenses = artifact.spdxLicenses.map {
- SpdxLicenses(
- identifier = it.identifier,
- name = it.name,
- url = it.url
- )
- }, unknownLicenses = artifact.unknownLicenses.map {
- UnknownLicenses(name = it.name, url = it.url)
- })
- })
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/se/premex/gross/ui/theme/Color.kt b/app/src/main/java/se/premex/gross/ui/theme/Color.kt
deleted file mode 100644
index d1dda7a..0000000
--- a/app/src/main/java/se/premex/gross/ui/theme/Color.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package se.premex.gross.ui.theme
-
-import androidx.compose.ui.graphics.Color
-
-val Purple80 = Color(0xFFD0BCFF)
-val PurpleGrey80 = Color(0xFFCCC2DC)
-val Pink80 = Color(0xFFEFB8C8)
-
-val Purple40 = Color(0xFF6650a4)
-val PurpleGrey40 = Color(0xFF625b71)
-val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/app/src/main/java/se/premex/gross/ui/theme/Theme.kt b/app/src/main/java/se/premex/gross/ui/theme/Theme.kt
deleted file mode 100644
index 9266d67..0000000
--- a/app/src/main/java/se/premex/gross/ui/theme/Theme.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package se.premex.gross.ui.theme
-
-import android.app.Activity
-import android.os.Build
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.darkColorScheme
-import androidx.compose.material3.dynamicDarkColorScheme
-import androidx.compose.material3.dynamicLightColorScheme
-import androidx.compose.material3.lightColorScheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.SideEffect
-import androidx.compose.ui.graphics.toArgb
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalView
-import androidx.core.view.WindowCompat
-
-private val DarkColorScheme = darkColorScheme(
- primary = Purple80,
- secondary = PurpleGrey80,
- tertiary = Pink80
-)
-
-private val LightColorScheme = lightColorScheme(
- primary = Purple40,
- secondary = PurpleGrey40,
- tertiary = Pink40
-
- /* Other default colors to override
- background = Color(0xFFFFFBFE),
- surface = Color(0xFFFFFBFE),
- onPrimary = Color.White,
- onSecondary = Color.White,
- onTertiary = Color.White,
- onBackground = Color(0xFF1C1B1F),
- onSurface = Color(0xFF1C1B1F),
- */
-)
-
-@Composable
-fun GrossTheme(
- darkTheme: Boolean = isSystemInDarkTheme(),
- // Dynamic color is available on Android 12+
- dynamicColor: Boolean = true,
- content: @Composable () -> Unit
-) {
- val colorScheme = when {
- dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
- val context = LocalContext.current
- if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
- }
-
- darkTheme -> DarkColorScheme
- else -> LightColorScheme
- }
- val view = LocalView.current
- if (!view.isInEditMode) {
- SideEffect {
- val window = (view.context as Activity).window
- window.statusBarColor = colorScheme.primary.toArgb()
- WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
- }
- }
-
- MaterialTheme(
- colorScheme = colorScheme,
- typography = Typography,
- content = content
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/se/premex/gross/ui/theme/Type.kt b/app/src/main/java/se/premex/gross/ui/theme/Type.kt
deleted file mode 100644
index c78bce2..0000000
--- a/app/src/main/java/se/premex/gross/ui/theme/Type.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package se.premex.gross.ui.theme
-
-import androidx.compose.material3.Typography
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.sp
-
-// Set of Material typography styles to start with
-val Typography = Typography(
- bodyLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- lineHeight = 24.sp,
- letterSpacing = 0.5.sp
- )
- /* Other default text styles to override
- titleLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 22.sp,
- lineHeight = 28.sp,
- letterSpacing = 0.sp
- ),
- labelSmall = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Medium,
- fontSize = 11.sp,
- lineHeight = 16.sp,
- letterSpacing = 0.5.sp
- )
- */
-)
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 07d5da9..0000000
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
deleted file mode 100644
index 2b068d1..0000000
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index 6f3b755..0000000
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index 6f3b755..0000000
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
deleted file mode 100644
index c209e78..0000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
deleted file mode 100644
index b2dfe3d..0000000
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
deleted file mode 100644
index 4f0f1d6..0000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
deleted file mode 100644
index 62b611d..0000000
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
deleted file mode 100644
index 948a307..0000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
deleted file mode 100644
index 1b9a695..0000000
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
deleted file mode 100644
index 28d4b77..0000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9287f50..0000000
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
deleted file mode 100644
index aa7d642..0000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9126ae3..0000000
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
deleted file mode 100644
index f8c6127..0000000
--- a/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
deleted file mode 100644
index ed25f78..0000000
--- a/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
- Gross
- Programmatic oss view
- Asset baset oss view
- Error
- Loading
-
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
deleted file mode 100644
index b8582c9..0000000
--- a/app/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
deleted file mode 100644
index fa0f996..0000000
--- a/app/src/main/res/xml/backup_rules.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
deleted file mode 100644
index 9ee9997..0000000
--- a/app/src/main/res/xml/data_extraction_rules.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/test/java/se/premex/gross/ExampleUnitTest.kt b/app/src/test/java/se/premex/gross/ExampleUnitTest.kt
deleted file mode 100644
index 8c9c6c9..0000000
--- a/app/src/test/java/se/premex/gross/ExampleUnitTest.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package se.premex.gross
-
-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
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e68aa22..d43e5e4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -7,6 +7,7 @@ maven-kotlin-serialization = "1.6.0"
maven-kotlin = "1.9.20"
maven-junit = "5.10.1"
maven-assertj = "3.24.2"
+maven-binarycompatiblity = "0.13.2"
[libraries]
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "maven-junit" }
@@ -26,4 +27,5 @@ starter-library-kotlin = { id = "com.starter.library.kotlin", version.ref = "gra
starter-library-android = { id = "com.starter.library.android", version.ref = "gradle-starter" }
gradle-pluginpublish = { id = "com.gradle.plugin-publish", version.ref = "gradle-pluginpublish" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "maven-kotlin" }
+kotlinx-binarycompatibility = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "maven-binarycompatiblity" }
osacky-doctor = { id = "com.osacky.doctor", version.ref = "gradle-doctor" }
diff --git a/licensee-for-android/api/licensee-for-android.api b/licensee-for-android/api/licensee-for-android.api
new file mode 100644
index 0000000..d110e99
--- /dev/null
+++ b/licensee-for-android/api/licensee-for-android.api
@@ -0,0 +1,28 @@
+public abstract class se/premex/gross/AssetCopyTask : org/gradle/api/DefaultTask {
+ public fun ()V
+ public final fun action ()V
+ public abstract fun getInputFile ()Lorg/gradle/api/file/RegularFileProperty;
+ public abstract fun getOutputDirectory ()Lorg/gradle/api/file/DirectoryProperty;
+ public abstract fun getTargetFileName ()Lorg/gradle/api/provider/Property;
+}
+
+public abstract class se/premex/gross/CodeGenerationTask : org/gradle/api/DefaultTask {
+ public fun ()V
+ public final fun action ()V
+ public abstract fun getInputFile ()Lorg/gradle/api/file/RegularFileProperty;
+ public abstract fun getOutputDirectory ()Lorg/gradle/api/file/DirectoryProperty;
+}
+
+public abstract interface class se/premex/gross/GrossExtension {
+ public abstract fun getAndroidAssetFileName ()Lorg/gradle/api/provider/Property;
+ public abstract fun getEnableAndroidAssetGeneration ()Lorg/gradle/api/provider/Property;
+ public abstract fun getEnableKotlinCodeGeneration ()Lorg/gradle/api/provider/Property;
+ public abstract fun getSingularVariantName ()Lorg/gradle/api/provider/Property;
+}
+
+public final class se/premex/gross/GrossPlugin : org/gradle/api/Plugin {
+ public fun ()V
+ public synthetic fun apply (Ljava/lang/Object;)V
+ public fun apply (Lorg/gradle/api/Project;)V
+}
+
diff --git a/licensee-for-android/build.gradle b/licensee-for-android/build.gradle
index 7cf201e..3eeadfa 100644
--- a/licensee-for-android/build.gradle
+++ b/licensee-for-android/build.gradle
@@ -1,4 +1,3 @@
-import org.gradle.kotlin.dsl.ProjectExtensionsKt
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -6,6 +5,7 @@ plugins {
alias(libs.plugins.gradle.pluginpublish)
alias(libs.plugins.starter.library.kotlin)
alias(libs.plugins.kotlin.serialization)
+ alias(libs.plugins.kotlinx.binarycompatibility)
}
dependencies {
@@ -24,6 +24,12 @@ dependencies {
testImplementation(libs.assertj.core)
}
+
+kotlin {
+ explicitApi()
+}
+
+
tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
apiVersion = "1.8"
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/ArtifactCodeGenerator.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/ArtifactCodeGenerator.kt
index ebd02ac..79175e6 100644
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/ArtifactCodeGenerator.kt
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/ArtifactCodeGenerator.kt
@@ -6,7 +6,7 @@ import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.TypeSpec
import se.premex.gross.core.Artifact
-class ArtifactCodeGenerator(
+internal class ArtifactCodeGenerator(
private val packageName: String,
private val spdxLicensesTypeSpec: TypeSpec,
private val scmTypeSpec: TypeSpec,
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/AssetCopyTask.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/AssetCopyTask.kt
index 868eebc..7a8e55b 100644
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/AssetCopyTask.kt
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/AssetCopyTask.kt
@@ -11,27 +11,23 @@ import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
-import java.io.File
@CacheableTask
-abstract class AssetCopyTask : DefaultTask() {
+public abstract class AssetCopyTask : DefaultTask() {
@get:OutputDirectory
- abstract val outputDirectory: DirectoryProperty
+ public abstract val outputDirectory: DirectoryProperty
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:InputFile
- abstract val inputFile: RegularFileProperty
+ public abstract val inputFile: RegularFileProperty
@get:Input
- abstract val targetFileName: Property
+ public abstract val targetFileName: Property
@TaskAction
- fun action() {
+ public fun action() {
inputFile.get().asFile.copyTo(
- target = File(
- outputDirectory.get().asFile,
- targetFileName.get(),
- ),
+ target = outputDirectory.get().asFile.resolve(targetFileName.get()),
overwrite = true,
)
}
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/CodeGenerationTask.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/CodeGenerationTask.kt
index 1f30a6f..d3a135e 100644
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/CodeGenerationTask.kt
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/CodeGenerationTask.kt
@@ -22,19 +22,19 @@ import org.gradle.api.tasks.TaskAction
import se.premex.gross.core.Artifact
@CacheableTask
-abstract class CodeGenerationTask : DefaultTask() {
- private val packageName = "se.premex.gross"
+public abstract class CodeGenerationTask : DefaultTask() {
+ private val packageName = "io.github.usefulness.licensee"
@get:OutputDirectory
- abstract val outputDirectory: DirectoryProperty
+ public abstract val outputDirectory: DirectoryProperty
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:InputFile
- abstract val inputFile: RegularFileProperty
+ public abstract val inputFile: RegularFileProperty
@TaskAction
@ExperimentalSerializationApi
- fun action() {
+ public fun action() {
val licenseeTypesGenerator = LicenseeTypesGenerator(packageName)
FileSpec.builder(packageName, "Artifact")
@@ -62,14 +62,14 @@ abstract class CodeGenerationTask : DefaultTask() {
addStatement(")")
}.build()
- val grossType = TypeSpec.objectBuilder("Gross")
+ val grossType = TypeSpec.objectBuilder("Licensee")
.addProperty(
PropertySpec.builder("artifacts", licenseeTypesGenerator.artifactListType)
.initializer(artifactList).build(),
)
.build()
- FileSpec.builder(packageName, "Gross")
+ FileSpec.builder(packageName, "Licensee")
.addType(grossType)
.build().writeTo(outputDirectory.asFile.get())
}
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/GrossExtension.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/GrossExtension.kt
deleted file mode 100644
index 77655eb..0000000
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/GrossExtension.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package se.premex.gross
-
-import org.gradle.api.provider.Property
-
-interface GrossExtension {
- /**
- *
- */
- val enableKotlinCodeGeneration: Property
-
- /**
- * Enable asset generation. Will copy licensee report to
- * android asset directory making it available as 'androidAssetFileName'
- */
- val enableAndroidAssetGeneration: Property
-
- /**
- * The name of the asset file the licensee report gets copied to.
- * Default: "artifacts.json"
- */
- val androidAssetFileName: Property
-}
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/GrossPlugin.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/GrossPlugin.kt
index f9f0341..5e9ef98 100644
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/GrossPlugin.kt
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/GrossPlugin.kt
@@ -6,62 +6,64 @@ import org.gradle.api.Project
import org.gradle.api.reporting.ReportingExtension
public class GrossPlugin : Plugin {
- override fun apply(project: Project) {
- val extension = project.extensions.create("gross", GrossExtension::class.java)
- extension.enableKotlinCodeGeneration.convention(true)
- extension.enableAndroidAssetGeneration.convention(false)
- extension.androidAssetFileName.convention("artifacts.json")
- val reportingExtension: ReportingExtension =
- project.extensions.getByType(ReportingExtension::class.java)
+ override fun apply(project: Project): Unit = with(project) {
+ val extension = extensions.create("licenseeForAndroid", LicenseeForAndroidExtension::class.java)
- project.pluginManager.withPlugin("app.cash.licensee") {
+ pluginManager.withPlugin("app.cash.licensee") {
listOf(
"com.android.application",
"com.android.library",
"com.android.dynamic-feature",
)
.forEach { pluginId ->
- project.pluginManager.withPlugin(pluginId) {
- configureAndroidPlugin(project, extension, reportingExtension)
+ pluginManager.withPlugin(pluginId) {
+ configureAndroidPlugin(extension)
}
}
}
}
- private fun configureAndroidPlugin(project: Project, extension: GrossExtension, reportingExtension: ReportingExtension) {
- val androidComponentsExtension =
- project.extensions.getByName("androidComponents") as AndroidComponentsExtension<*, *, *>
+ private fun Project.configureAndroidPlugin(extension: LicenseeForAndroidExtension) {
+ val androidComponents = extensions.getByName("androidComponents") as AndroidComponentsExtension<*, *, *>
+ val reportingExtension = extensions.getByType(ReportingExtension::class.java)
+
+ androidComponents.onVariants { variant ->
+ val source = extension.singularVariantName.getOrElse(variant.name)
+ val sourceCapitalized = source.replaceFirstChar(Char::titlecase)
- androidComponentsExtension.onVariants { variant ->
val target = variant.name
val targetCapitalized = target.replaceFirstChar(Char::titlecase)
- val licenseeTaskName = "licenseeAndroid$targetCapitalized"
+ val licenseeTaskName = "licenseeAndroid$sourceCapitalized"
- val artifactsFile = reportingExtension.file("licensee/android$targetCapitalized/artifacts.json")
+ val artifactsFile = reportingExtension.file("licensee/android$sourceCapitalized/artifacts.json")
if (extension.enableAndroidAssetGeneration.get()) {
- val copyArtifactsTask =
- project.tasks.register("copy${targetCapitalized}LicenseeReportToAssets", AssetCopyTask::class.java) {
- it.inputFile.set(artifactsFile)
- it.targetFileName.set(extension.androidAssetFileName.get())
- }
+ val copyArtifactsTask = tasks.register(
+ "generate${sourceCapitalized}LicenseeAssetsFor$targetCapitalized",
+ AssetCopyTask::class.java,
+ ) {
+ it.inputFile.set(artifactsFile)
+ it.targetFileName.set(extension.androidAssetFileName)
+ }
variant.sources.assets!!.addGeneratedSourceDirectory(
- copyArtifactsTask,
- AssetCopyTask::outputDirectory,
+ taskProvider = copyArtifactsTask,
+ wiredWith = AssetCopyTask::outputDirectory,
)
copyArtifactsTask.configure { it.dependsOn(licenseeTaskName) }
}
if (extension.enableKotlinCodeGeneration.get()) {
- val codeGenerationTask =
- project.tasks.register("${target}LicenseeReportToKotlin", CodeGenerationTask::class.java) {
- it.inputFile.set(artifactsFile)
- }
+ val codeGenerationTask = tasks.register(
+ "generate${sourceCapitalized}LicenseeKotlinCodeFor$targetCapitalized",
+ CodeGenerationTask::class.java,
+ ) {
+ it.inputFile.set(artifactsFile)
+ }
// Do NOT use `.kotlin` here: https://issuetracker.google.com/issues/268248348
variant.sources.java!!.addGeneratedSourceDirectory(
- codeGenerationTask,
- CodeGenerationTask::outputDirectory,
+ taskProvider = codeGenerationTask,
+ wiredWith = CodeGenerationTask::outputDirectory,
)
codeGenerationTask.configure { it.dependsOn(licenseeTaskName) }
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeForAndroidExtension.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeForAndroidExtension.kt
new file mode 100644
index 0000000..1d675e8
--- /dev/null
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeForAndroidExtension.kt
@@ -0,0 +1,35 @@
+package se.premex.gross
+
+import org.gradle.api.Incubating
+import org.gradle.api.model.ObjectFactory
+import org.gradle.api.provider.Property
+
+public open class LicenseeForAndroidExtension(objectFactory: ObjectFactory) {
+
+ /**
+ * Generates a static list of open source assets
+ */
+ public val enableKotlinCodeGeneration: Property = objectFactory.property(default = false)
+
+ /**
+ * Enable asset generation. Will copy licensee report to
+ * android asset directory making it available as 'androidAssetFileName'
+ */
+ public val enableAndroidAssetGeneration: Property = objectFactory.property(default = true)
+
+ /**
+ * The name of the asset file the licensee report gets copied to.
+ */
+ public val androidAssetFileName: Property = objectFactory.property(default = "licensee_artifacts.json")
+
+ /**
+ * The name of the build variant that all variants will use to have always the same licensed, regardless of app variant.
+ * Default: null - each build variant will get its unique report
+ */
+ @Incubating
+ public val singularVariantName: Property = objectFactory.property(default = null)
+}
+
+internal inline fun ObjectFactory.property(default: T? = null): Property = property(T::class.java).apply {
+ convention(default)
+}
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeTypesGenerator.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeTypesGenerator.kt
index 74de23a..0f74603 100644
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeTypesGenerator.kt
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/LicenseeTypesGenerator.kt
@@ -9,7 +9,7 @@ import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.asTypeName
-class LicenseeTypesGenerator(private val packageName: String) {
+internal class LicenseeTypesGenerator(packageName: String) {
val spdxLicensesTypeSpec: TypeSpec =
TypeSpec.classBuilder("SpdxLicenses")
diff --git a/licensee-for-android/src/main/kotlin/se/premex/gross/core/Artifact.kt b/licensee-for-android/src/main/kotlin/se/premex/gross/core/Artifact.kt
index e88404c..dbec3fa 100644
--- a/licensee-for-android/src/main/kotlin/se/premex/gross/core/Artifact.kt
+++ b/licensee-for-android/src/main/kotlin/se/premex/gross/core/Artifact.kt
@@ -3,23 +3,23 @@ package se.premex.gross.core
import kotlinx.serialization.Serializable
@Serializable
-data class SpdxLicenses(
+internal data class SpdxLicenses(
val identifier: String,
val name: String,
val url: String,
)
@Serializable
-data class Scm(val url: String)
+internal data class Scm(val url: String)
@Serializable
-data class UnknownLicenses(
+internal data class UnknownLicenses(
val name: String,
val url: String,
)
@Serializable
-data class Artifact(
+internal data class Artifact(
val groupId: String,
val artifactId: String,
val version: String,
diff --git a/sample/app/build.gradle b/sample/app/build.gradle
index 82071f9..59b69e0 100644
--- a/sample/app/build.gradle
+++ b/sample/app/build.gradle
@@ -8,9 +8,9 @@ licensee {
allow("Apache-2.0")
}
-gross {
- enableKotlinCodeGeneration.set(true)
- enableAndroidAssetGeneration.set(true)
+licenseeForAndroid {
+ enableKotlinCodeGeneration = true
+ enableAndroidAssetGeneration = true
}
android {
namespace "io.githhub.usefulness.licensee.android.app"
diff --git a/sample/app/config/baseline.xml b/sample/app/config/baseline.xml
index 4f3fad9..2253a08 100644
--- a/sample/app/config/baseline.xml
+++ b/sample/app/config/baseline.xml
@@ -2,9 +2,9 @@
- FunctionNaming:OssArtifactView.kt$@Composable fun AssetsOssView()
+ FunctionNaming:OssArtifactView.kt$@OptIn(ExperimentalSerializationApi::class) @Composable fun AssetsOssView()
FunctionNaming:OssKotlinCodeView.kt$@Composable fun ProgrammaticOssView()
FunctionNaming:Theme.kt$@Composable fun GrossTheme( darkTheme: Boolean = isSystemInDarkTheme(), // Dynamic color is available on Android 12+ dynamicColor: Boolean = true, content: @Composable () -> Unit, )
- WildcardImport:ExampleUnitTest.kt$import org.junit.Assert.*
+ InvalidPackageDeclaration:MainActivity.kt$package io.githhub.usefulness.licensee.android.app
diff --git a/sample/app/src/main/kotlin/se/premex/gross/OssKotlinCodeView.kt b/sample/app/src/main/kotlin/se/premex/gross/OssKotlinCodeView.kt
index 46c3880..d9d779d 100644
--- a/sample/app/src/main/kotlin/se/premex/gross/OssKotlinCodeView.kt
+++ b/sample/app/src/main/kotlin/se/premex/gross/OssKotlinCodeView.kt
@@ -10,13 +10,14 @@ import se.premex.gross.core.Scm
import se.premex.gross.core.SpdxLicenses
import se.premex.gross.core.UnknownLicenses
import se.premex.gross.ui.OssView
+import io.github.usefulness.licensee.Licensee
@Composable
fun ProgrammaticOssView() {
Column {
Text(text = stringResource(id = R.string.programmatic))
OssView(
- Gross.artifacts.map { artifact ->
+ Licensee.artifacts.map { artifact ->
Artifact(
name = artifact.name,
groupId = artifact.groupId,
diff --git a/sample/ui/src/main/kotlin/se/premex/gross/ui/AssetLicenseParser.kt b/sample/ui/src/main/kotlin/se/premex/gross/ui/AssetLicenseParser.kt
index 4dc375a..83a05dc 100644
--- a/sample/ui/src/main/kotlin/se/premex/gross/ui/AssetLicenseParser.kt
+++ b/sample/ui/src/main/kotlin/se/premex/gross/ui/AssetLicenseParser.kt
@@ -14,7 +14,7 @@ import se.premex.gross.core.UnknownLicenses
class AssetLicenseParser(private val assetManager: AssetManager) : LicenseParser {
@ExperimentalSerializationApi
suspend fun readFromAssets(): List = withContext(Dispatchers.IO) {
- val source = assetManager.open("artifacts.json").source().buffer()
+ val source = assetManager.open("licensee_artifacts.json").source().buffer()
decode(source)
}
}
diff --git a/sample/ui/src/main/kotlin/se/premex/gross/ui/OssView.kt b/sample/ui/src/main/kotlin/se/premex/gross/ui/OssView.kt
index 8b34297..4e8a2a4 100644
--- a/sample/ui/src/main/kotlin/se/premex/gross/ui/OssView.kt
+++ b/sample/ui/src/main/kotlin/se/premex/gross/ui/OssView.kt
@@ -40,8 +40,7 @@ fun OssView(artifacts: List, modifier: Modifier = Modifier) {
val licenses =
artifact.spdxLicenses.spdxToLicenses() + artifact.unknownLicenses.unknownToLicenses()
- val nameOrPackage =
- artifact.name ?: ("${artifact.groupId}:${artifact.artifactId}:${artifact.version}")
+ val nameOrPackage = ("${artifact.name}\n(${artifact.groupId}:${artifact.artifactId}:${artifact.version})".trim())
ViewArtifact(nameOrPackage, licenses)
}.sortedBy { it.title }
diff --git a/ui/.gitignore b/ui/.gitignore
deleted file mode 100644
index 42afabf..0000000
--- a/ui/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts
deleted file mode 100644
index 569a392..0000000
--- a/ui/build.gradle.kts
+++ /dev/null
@@ -1,101 +0,0 @@
-import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
-
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-plugins {
- alias(libs.plugins.com.android.library)
- alias(libs.plugins.org.jetbrains.kotlin.android)
- alias(libs.plugins.com.github.ben.manes.versions)
- alias(libs.plugins.nl.littlerobots.version.catalog.update)
- kotlin("plugin.serialization") version "1.8.21"
- id("io.gitlab.arturbosch.detekt") version "1.23.0"
-}
-
-detekt {
- autoCorrect = true
- buildUponDefaultConfig = true
-}
-
-fun isNonStable(version: String): Boolean {
- val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) }
- val regex = "^[0-9,.v-]+(-r)?$".toRegex()
- val isStable = stableKeyword || regex.matches(version)
- return isStable.not()
-}
-
-// https://github.com/ben-manes/gradle-versions-plugin
-tasks.withType {
- resolutionStrategy {
- componentSelection {
- all {
- if (isNonStable(candidate.version) && !isNonStable(currentVersion)) {
- reject("Release candidate")
- }
- }
- }
- }
-}
-
-android {
- namespace = "se.premex.gross.oss"
-
- compileSdk = 33
- defaultConfig {
- minSdk = 24
- }
- buildFeatures {
- compose = true
- }
- composeOptions {
- kotlinCompilerExtensionVersion = libs.versions.androidx.compose.compiler.get()
- }
-
- publishing {
- singleVariant("release") {
- withSourcesJar()
- }
- }
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = "1.8"
- }
-}
-
-group = "se.premex.gross"
-version = "1.0"
-
-java {
- toolchain {
- languageVersion.set(JavaLanguageVersion.of(17))
- vendor.set(JvmVendorSpec.AZUL)
- }
-}
-
-dependencies {
- api("se.premex.gross:core:1.0")
- implementation(libs.com.squareup.okio)
- implementation(platform(libs.androidx.compose.bom))
- implementation(libs.androidx.compose.runtime)
- implementation(libs.androidx.compose.ui)
- implementation(libs.androidx.compose.foundation.foundation.layout)
- implementation(libs.androidx.compose.material3)
- implementation(libs.androidx.compose.foundation)
-
- implementation(libs.org.jetbrains.kotlinx.kotlinx.serialization.json)
-
- implementation(libs.androidx.compose.material.material.icons.extended)
-
- implementation(libs.androidx.compose.animation)
-
- implementation(libs.androidx.compose.ui.ui.tooling)
- implementation(libs.androidx.compose.runtime.runtime.livedata)
- implementation(libs.androidx.compose.ui.ui.text)
-
- implementation(libs.androidx.core.core.ktx)
- testImplementation(libs.org.jetbrains.kotlin.kotlin.test.junit)
- testImplementation(libs.org.jetbrains.kotlinx.kotlinx.coroutines.test)
-
- detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1")
-}
diff --git a/ui/src/main/AndroidManifest.xml b/ui/src/main/AndroidManifest.xml
deleted file mode 100644
index 8072ee0..0000000
--- a/ui/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/ui/src/main/java/se/premex/gross/ui/AssetLicenseParser.kt b/ui/src/main/java/se/premex/gross/ui/AssetLicenseParser.kt
deleted file mode 100644
index 063d3cb..0000000
--- a/ui/src/main/java/se/premex/gross/ui/AssetLicenseParser.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package se.premex.gross.ui
-
-import android.content.res.AssetManager
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import kotlinx.serialization.ExperimentalSerializationApi
-import okio.buffer
-import okio.source
-import se.premex.gross.core.Artifact
-import se.premex.gross.core.LicenseParser
-import se.premex.gross.core.SpdxLicenses
-import se.premex.gross.core.UnknownLicenses
-
-class AssetLicenseParser(private val assetManager: AssetManager) : LicenseParser {
- @ExperimentalSerializationApi
- suspend fun readFromAssets(): List =
- withContext(Dispatchers.IO) {
- val source = assetManager.open("artifacts.json").source().buffer()
- decode(source)
- }
-}
-
-internal fun List?.unknownToLicenses(): List =
- orEmpty().map { unknown -> unknown.asLicense() }
-
-internal fun UnknownLicenses.asLicense(): License = License(name, url)
-
-internal fun List?.spdxToLicenses(): List =
- orEmpty().map { spdx -> spdx.asLicense() }
-
-internal fun SpdxLicenses.asLicense() = License(title = name, url = url)
diff --git a/ui/src/main/java/se/premex/gross/ui/ErrorView.kt b/ui/src/main/java/se/premex/gross/ui/ErrorView.kt
deleted file mode 100644
index d1739c6..0000000
--- a/ui/src/main/java/se/premex/gross/ui/ErrorView.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package se.premex.gross.ui
-
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Error
-import androidx.compose.material3.Icon
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import se.premex.gross.oss.R
-
-@Composable
-@Suppress("FunctionNaming")
-fun ErrorView(errorString: String, errorMessage: String, modifier: Modifier = Modifier) =
- ErrorView(modifier = modifier) {
- Text(text = errorString)
- Text(text = errorMessage)
- }
-
-@Composable
-@Suppress("FunctionNaming")
-fun ErrorView(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
- Column(
- modifier = modifier.fillMaxSize(),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center
- ) {
- Icon(
- imageVector = Icons.Filled.Error,
- contentDescription = stringResource(
- id = R.string.error
- )
- )
- Spacer(Modifier.height(16.dp))
- content()
- }
-}
-
-@Preview
-@Composable
-@Suppress("FunctionNaming")
-fun ErrorViewPreview() {
- ErrorView("ErrorString", "ErrorMessage")
-}
diff --git a/ui/src/main/java/se/premex/gross/ui/LoadingView.kt b/ui/src/main/java/se/premex/gross/ui/LoadingView.kt
deleted file mode 100644
index fa3adce..0000000
--- a/ui/src/main/java/se/premex/gross/ui/LoadingView.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package se.premex.gross.ui
-
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.material3.CircularProgressIndicator
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-
-@Composable
-@Suppress("FunctionNaming")
-fun LoadingView(loadingTitle: String, modifier: Modifier = Modifier) =
- LoadingView(modifier) {
- Text(text = loadingTitle)
- }
-
-@Composable
-@Suppress("FunctionNaming")
-fun LoadingView(modifier: Modifier = Modifier, content: @Composable () -> Unit = {}) {
- Column(
- modifier = modifier.fillMaxSize(),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center
- ) {
- CircularProgressIndicator()
- Spacer(Modifier.height(32.dp))
- content()
- }
-}
-
-@Preview
-@Composable
-@Suppress("FunctionNaming")
-fun PreviewLoadingView() {
- LoadingView("LoadingTitle")
-}
diff --git a/ui/src/main/java/se/premex/gross/ui/OssView.kt b/ui/src/main/java/se/premex/gross/ui/OssView.kt
deleted file mode 100644
index 759a8e7..0000000
--- a/ui/src/main/java/se/premex/gross/ui/OssView.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-@file:OptIn(ExperimentalFoundationApi::class)
-
-package se.premex.gross.ui
-
-import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Link
-import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.ListItem
-import androidx.compose.material3.Text
-import androidx.compose.material3.TextButton
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateListOf
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.runtime.snapshots.SnapshotStateList
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalUriHandler
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import se.premex.gross.core.Artifact
-import se.premex.gross.oss.R
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-@Suppress("FunctionNaming")
-fun OssView(artifacts: List, modifier: Modifier = Modifier) {
- val viewData = artifacts.map { artifact ->
- val licenses =
- artifact.spdxLicenses.spdxToLicenses() + artifact.unknownLicenses.unknownToLicenses()
-
- val nameOrPackage =
- artifact.name ?: ("${artifact.groupId}:${artifact.artifactId}:${artifact.version}")
-
- ViewArtifact(nameOrPackage, licenses)
- }.sortedBy { it.title }
-
- val licenses: SnapshotStateList = remember { mutableStateListOf() }
- var alertTitle by remember { mutableStateOf("") }
- LicenseSelector(alertTitle, licenses) {
- licenses.clear()
- }
-
- LazyColumn(
- modifier = modifier.fillMaxSize(),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center
- ) {
- item {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(16.dp),
- verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally
- ) {
- Text(
- textAlign = TextAlign.Center,
- modifier = Modifier.padding(horizontal = 40.dp),
- text = stringResource(id = R.string.oss_description)
- )
- }
- }
-
- val grouped: Map> =
- viewData.groupBy { it.title[0].uppercaseChar().toString() }
- grouped.forEach { (title, list) ->
- stickyHeader {
- CharacterHeader(title)
- }
- items(list) { artifact ->
- ListItem(
- headlineText = {
- Text(text = artifact.title)
- },
- modifier = Modifier.clickable {
- alertTitle = artifact.title
- licenses.addAll(artifact.licenses)
- }
- )
- }
- }
- }
-}
-
-@Composable
-@Suppress("FunctionNaming")
-fun CharacterHeader(initial: String) {
- Text(
- modifier = Modifier.padding(
- start = 16.dp,
- top = 16.dp,
- end = 16.dp,
- bottom = 4.dp
- ),
- text = initial
- )
-}
-
-@Preview(showSystemUi = true)
-@Composable
-@Suppress("FunctionNaming")
-fun LicenseSelectorPreview() {
- Column(Modifier.fillMaxSize()) {
- LicenseSelector("Licenses", listOf(License("aaa", "http://google.se"))) {
- }
- }
-}
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-@Suppress("FunctionNaming")
-fun LicenseSelector(title: String, licenses: List, close: () -> Unit) {
- val uriHandler = LocalUriHandler.current
-
- if (licenses.isNotEmpty()) {
- AlertDialog(
- onDismissRequest = {
- close()
- },
- title = {
- Text(text = title)
- },
- text = {
- Column {
- licenses.forEach { license ->
- ListItem(
- headlineText = {
- Text(text = license.title)
- },
- leadingContent = {
- Icon(
- imageVector = Icons.Filled.Link,
- contentDescription = null
- )
- },
- modifier = Modifier.clickable {
- uriHandler.openUri(license.url)
- }
- )
- }
- }
- },
- confirmButton = {
- TextButton(
- onClick = close
- ) {
- Text(stringResource(id = R.string.close))
- }
- },
- )
- }
-}
diff --git a/ui/src/main/java/se/premex/gross/ui/OssViewModel.kt b/ui/src/main/java/se/premex/gross/ui/OssViewModel.kt
deleted file mode 100644
index 39c3a88..0000000
--- a/ui/src/main/java/se/premex/gross/ui/OssViewModel.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package se.premex.gross.ui
-
-import se.premex.gross.core.Artifact
-
-sealed class State {
- class Loading : State()
- data class Success(val data: T) : State()
- data class Failed(val errorMessage: String) : State()
-}
-
-data class OssViewState(
- val viewState: State> = State.Loading(),
-)
-
-data class ViewArtifact(
- val title: String,
- val licenses: List,
-)
-
-data class License(
- val title: String,
- val url: String,
-)
diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml
deleted file mode 100644
index 4751e70..0000000
--- a/ui/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
- Open source licenses
- Error
- Loading
- This application is built with the following open source projects.
- Close
-
\ No newline at end of file
diff --git a/ui/src/test/java/se/premex/gross/oss/LicenseParserTest.kt b/ui/src/test/java/se/premex/gross/oss/LicenseParserTest.kt
deleted file mode 100644
index decc1ec..0000000
--- a/ui/src/test/java/se/premex/gross/oss/LicenseParserTest.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-package se.premex.gross.oss
-
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runTest
-import kotlinx.serialization.ExperimentalSerializationApi
-import okio.buffer
-import okio.source
-import se.premex.gross.core.LicenseParser
-import kotlin.test.Test
-
-private const val ARTIFACTS_SMALL = """[
- {
- "groupId": "androidx.activity",
- "artifactId": "activity",
- "version": "1.7.0",
- "name": "Activity",
- "spdxLicenses": [
- {
- "identifier": "Apache-2.0",
- "name": "Apache License 2.0",
- "url": "https://www.apache.org/licenses/LICENSE-2.0"
- }
- ],
- "scm": {
- "url": "https://cs.android.com/androidx/platform/frameworks/support"
- }
- }
-]"""
-
-private const val ARTIFACTS_MEDIUM = """[
- {
- "groupId": "androidx.activity",
- "artifactId": "activity",
- "version": "1.7.0",
- "name": "Activity",
- "spdxLicenses": [
- {
- "identifier": "Apache-2.0",
- "name": "Apache License 2.0",
- "url": "https://www.apache.org/licenses/LICENSE-2.0"
- }
- ],
- "scm": {
- "url": "https://cs.android.com/androidx/platform/frameworks/support"
- }
- },
- {
- "groupId": "androidx.activity",
- "artifactId": "activity-compose",
- "version": "1.7.0",
- "name": "Activity Compose",
- "spdxLicenses": [
- {
- "identifier": "Apache-2.0",
- "name": "Apache License 2.0",
- "url": "https://www.apache.org/licenses/LICENSE-2.0"
- }
- ],
- "scm": {
- "url": "https://cs.android.com/androidx/platform/frameworks/support"
- }
- },
- {
- "groupId": "androidx.activity",
- "artifactId": "activity-ktx",
- "version": "1.7.0",
- "name": "Activity Kotlin Extensions",
- "spdxLicenses": [
- {
- "identifier": "Apache-2.0",
- "name": "Apache License 2.0",
- "url": "https://www.apache.org/licenses/LICENSE-2.0"
- }
- ],
- "scm": {
- "url": "https://cs.android.com/androidx/platform/frameworks/support"
- }
- }
-]"""
-
-class LicenseParserTest {
- @Test
- @ExperimentalCoroutinesApi
- @ExperimentalSerializationApi
- fun testSmall() = runTest {
- val licenseParser = object : LicenseParser {}
- licenseParser.decode(ARTIFACTS_SMALL.byteInputStream().source().buffer())
- }
-
- @Test
- @ExperimentalCoroutinesApi
- @ExperimentalSerializationApi
- fun testMedium() = runTest {
- val licenseParser = object : LicenseParser {}
- licenseParser.decode(ARTIFACTS_MEDIUM.byteInputStream().source().buffer())
- }
-}