Browse Source
This should fix both configuration cache and reproducible F-droid builds. Cleanup and remove gplay/fdroid diff on open source licenses. Co-authored by @jmartinesppull/3381/head
Benoit Marty
2 weeks ago
committed by
Benoit Marty
38 changed files with 983 additions and 309 deletions
@ -1,12 +0,0 @@ |
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> |
|
||||||
|
|
||||||
<application> |
|
||||||
<activity |
|
||||||
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity" |
|
||||||
android:theme="@style/Theme.OssLicenses" /> |
|
||||||
<activity |
|
||||||
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity" |
|
||||||
android:theme="@style/Theme.OssLicenses" /> |
|
||||||
</application> |
|
||||||
|
|
||||||
</manifest> |
|
@ -1,37 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2024 New Vector Ltd |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package io.element.android.x.licenses |
|
||||||
|
|
||||||
import android.app.Activity |
|
||||||
import android.content.Intent |
|
||||||
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity |
|
||||||
import com.squareup.anvil.annotations.ContributesBinding |
|
||||||
import io.element.android.features.preferences.api.OpenSourceLicensesProvider |
|
||||||
import io.element.android.libraries.di.AppScope |
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings |
|
||||||
import javax.inject.Inject |
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class) |
|
||||||
class OssOpenSourcesLicensesProvider @Inject constructor() : OpenSourceLicensesProvider { |
|
||||||
override val hasOpenSourceLicenses: Boolean = true |
|
||||||
|
|
||||||
override fun navigateToOpenSourceLicenses(activity: Activity) { |
|
||||||
val title = activity.getString(CommonStrings.common_open_source_licenses) |
|
||||||
OssLicensesMenuActivity.setActivityTitle(title) |
|
||||||
activity.startActivity(Intent(activity, OssLicensesMenuActivity::class.java)) |
|
||||||
} |
|
||||||
} |
|
@ -1,32 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- |
|
||||||
~ Copyright (c) 2024 New Vector Ltd |
|
||||||
~ |
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
~ you may not use this file except in compliance with the License. |
|
||||||
~ You may obtain a copy of the License at |
|
||||||
~ |
|
||||||
~ https://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
~ |
|
||||||
~ Unless required by applicable law or agreed to in writing, software |
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
~ See the License for the specific language governing permissions and |
|
||||||
~ limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<resources> |
|
||||||
|
|
||||||
<!-- Use a few colors from compoundColorsDark --> |
|
||||||
<!-- DarkColorTokens.colorThemeBg --> |
|
||||||
<color name="colorThemeBg">#FF101317</color> |
|
||||||
<!-- DarkColorTokens.colorGray1400 --> |
|
||||||
<color name="textPrimary">#FFEBEEF2</color> |
|
||||||
<!-- DarkColorTokens.colorGray900 --> |
|
||||||
<color name="textSecondary">#ff808994</color> |
|
||||||
<!-- DarkColorTokens.colorBlue900 --> |
|
||||||
<color name="textLinkExternal">#FF4187EB</color> |
|
||||||
|
|
||||||
<bool name="windowLightStatusBar">false</bool> |
|
||||||
<bool name="windowLightNavigationBar">false</bool> |
|
||||||
|
|
||||||
</resources> |
|
@ -1,25 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- |
|
||||||
~ Copyright (c) 2024 New Vector Ltd |
|
||||||
~ |
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
~ you may not use this file except in compliance with the License. |
|
||||||
~ You may obtain a copy of the License at |
|
||||||
~ |
|
||||||
~ https://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
~ |
|
||||||
~ Unless required by applicable law or agreed to in writing, software |
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
~ See the License for the specific language governing permissions and |
|
||||||
~ limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<resources> |
|
||||||
|
|
||||||
<style name="Theme.OssLicenses.Light.v27" parent="Base.Theme.OssLicenses"> |
|
||||||
<item name="android:windowLightNavigationBar">@bool/windowLightNavigationBar</item> |
|
||||||
</style> |
|
||||||
|
|
||||||
<style name="Theme.OssLicenses" parent="Theme.OssLicenses.Light.v27"/> |
|
||||||
|
|
||||||
</resources> |
|
@ -1,32 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- |
|
||||||
~ Copyright (c) 2024 New Vector Ltd |
|
||||||
~ |
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
~ you may not use this file except in compliance with the License. |
|
||||||
~ You may obtain a copy of the License at |
|
||||||
~ |
|
||||||
~ https://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
~ |
|
||||||
~ Unless required by applicable law or agreed to in writing, software |
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
~ See the License for the specific language governing permissions and |
|
||||||
~ limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<resources> |
|
||||||
|
|
||||||
<!-- Use a few colors from compoundColorsLight --> |
|
||||||
<!-- LightColorTokens.colorThemeBg --> |
|
||||||
<color name="colorThemeBg">#FFFFFFFF</color> |
|
||||||
<!-- LightColorTokens.colorGray1400 --> |
|
||||||
<color name="textPrimary">#FF1B1D22</color> |
|
||||||
<!-- LightColorTokens.colorGray900 --> |
|
||||||
<color name="textSecondary">#FF656D77</color> |
|
||||||
<!-- LightColorTokens.colorBlue900 --> |
|
||||||
<color name="textLinkExternal">#FF0467DD</color> |
|
||||||
|
|
||||||
<bool name="windowLightStatusBar">true</bool> |
|
||||||
<bool name="windowLightNavigationBar">true</bool> |
|
||||||
|
|
||||||
</resources> |
|
@ -1,23 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- |
|
||||||
~ Copyright (c) 2024 New Vector Ltd |
|
||||||
~ |
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
~ you may not use this file except in compliance with the License. |
|
||||||
~ You may obtain a copy of the License at |
|
||||||
~ |
|
||||||
~ https://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
~ |
|
||||||
~ Unless required by applicable law or agreed to in writing, software |
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
~ See the License for the specific language governing permissions and |
|
||||||
~ limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<resources> |
|
||||||
|
|
||||||
<style name="NoElevationToolbar" parent="Widget.MaterialComponents.Toolbar"> |
|
||||||
<item name="android:elevation">0dp</item> |
|
||||||
</style> |
|
||||||
|
|
||||||
</resources> |
|
@ -1,41 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- |
|
||||||
~ Copyright (c) 2024 New Vector Ltd |
|
||||||
~ |
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
~ you may not use this file except in compliance with the License. |
|
||||||
~ You may obtain a copy of the License at |
|
||||||
~ |
|
||||||
~ https://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
~ |
|
||||||
~ Unless required by applicable law or agreed to in writing, software |
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
~ See the License for the specific language governing permissions and |
|
||||||
~ limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<resources> |
|
||||||
|
|
||||||
<style name="Base.Theme.OssLicenses" parent="Theme.MaterialComponents.DayNight"> |
|
||||||
<!-- Background of title bar --> |
|
||||||
<item name="colorPrimary">@color/colorThemeBg</item> |
|
||||||
<!-- Background of the screen --> |
|
||||||
<item name="android:colorBackground">@color/colorThemeBg</item> |
|
||||||
<!-- Text of the licenses --> |
|
||||||
<item name="android:textColor">@color/textSecondary</item> |
|
||||||
<!-- Link text color --> |
|
||||||
<item name="android:textColorLink">@color/textLinkExternal</item> |
|
||||||
<!-- Title, back button and license item text color --> |
|
||||||
<item name="android:textColorPrimary">@color/textPrimary</item> |
|
||||||
<!-- Background of status bar --> |
|
||||||
<item name="android:statusBarColor">@color/colorThemeBg</item> |
|
||||||
<item name="android:windowLightStatusBar">@bool/windowLightStatusBar</item> |
|
||||||
<!-- Background of navigation bar --> |
|
||||||
<item name="android:navigationBarColor">@color/colorThemeBg</item> |
|
||||||
<!-- Try to remove Toolbar elevation, but it does not work :/ --> |
|
||||||
<item name="toolbarStyle">@style/NoElevationToolbar</item> |
|
||||||
</style> |
|
||||||
|
|
||||||
<style name="Theme.OssLicenses" parent="Base.Theme.OssLicenses" /> |
|
||||||
|
|
||||||
</resources> |
|
@ -0,0 +1,28 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
plugins { |
||||||
|
id("io.element.android-compose-library") |
||||||
|
} |
||||||
|
|
||||||
|
android { |
||||||
|
namespace = "io.element.android.features.licenses.api" |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
implementation(projects.libraries.architecture) |
||||||
|
implementation(projects.libraries.designsystem) |
||||||
|
implementation(projects.libraries.uiStrings) |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2022 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
plugins { |
||||||
|
id("io.element.android-compose-library") |
||||||
|
id("kotlin-parcelize") |
||||||
|
alias(libs.plugins.anvil) |
||||||
|
alias(libs.plugins.kotlin.serialization) |
||||||
|
} |
||||||
|
|
||||||
|
android { |
||||||
|
namespace = "io.element.android.features.licenses.impl" |
||||||
|
} |
||||||
|
|
||||||
|
anvil { |
||||||
|
generateDaggerFactories.set(true) |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
implementation(projects.anvilannotations) |
||||||
|
anvil(projects.anvilcodegen) |
||||||
|
implementation(libs.serialization.json) |
||||||
|
implementation(projects.libraries.architecture) |
||||||
|
implementation(projects.libraries.designsystem) |
||||||
|
implementation(projects.libraries.core) |
||||||
|
implementation(projects.libraries.uiStrings) |
||||||
|
api(projects.features.licenses.api) |
||||||
|
testImplementation(libs.test.junit) |
||||||
|
testImplementation(libs.coroutines.test) |
||||||
|
testImplementation(libs.coroutines.core) |
||||||
|
testImplementation(libs.molecule.runtime) |
||||||
|
testImplementation(libs.test.truth) |
||||||
|
testImplementation(libs.test.turbine) |
||||||
|
testImplementation(projects.libraries.matrix.test) |
||||||
|
testImplementation(projects.tests.testutils) |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl |
||||||
|
|
||||||
|
import android.os.Parcelable |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import com.bumble.appyx.core.modality.BuildContext |
||||||
|
import com.bumble.appyx.core.node.Node |
||||||
|
import com.bumble.appyx.core.plugin.Plugin |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack |
||||||
|
import com.bumble.appyx.navmodel.backstack.operation.push |
||||||
|
import dagger.assisted.Assisted |
||||||
|
import dagger.assisted.AssistedInject |
||||||
|
import io.element.android.anvilannotations.ContributesNode |
||||||
|
import io.element.android.features.licenses.impl.details.DependenciesDetailsNode |
||||||
|
import io.element.android.features.licenses.impl.list.DependencyLicensesListNode |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.architecture.BackstackView |
||||||
|
import io.element.android.libraries.architecture.BaseFlowNode |
||||||
|
import io.element.android.libraries.architecture.createNode |
||||||
|
import io.element.android.libraries.di.AppScope |
||||||
|
import kotlinx.parcelize.Parcelize |
||||||
|
|
||||||
|
@ContributesNode(AppScope::class) |
||||||
|
class DependenciesFlowNode @AssistedInject constructor( |
||||||
|
@Assisted buildContext: BuildContext, |
||||||
|
@Assisted plugins: List<Plugin>, |
||||||
|
) : BaseFlowNode<DependenciesFlowNode.NavTarget>( |
||||||
|
backstack = BackStack( |
||||||
|
initialElement = NavTarget.LicensesList, |
||||||
|
savedStateMap = buildContext.savedStateMap, |
||||||
|
), |
||||||
|
buildContext = buildContext, |
||||||
|
plugins = plugins, |
||||||
|
) { |
||||||
|
sealed interface NavTarget : Parcelable { |
||||||
|
@Parcelize |
||||||
|
data object LicensesList : NavTarget |
||||||
|
|
||||||
|
@Parcelize |
||||||
|
data class LicenseDetails(val license: DependencyLicenseItem) : NavTarget |
||||||
|
} |
||||||
|
|
||||||
|
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { |
||||||
|
return when (navTarget) { |
||||||
|
is NavTarget.LicensesList -> { |
||||||
|
val callback = object : DependencyLicensesListNode.Callback { |
||||||
|
override fun onOpenLicense(license: DependencyLicenseItem) { |
||||||
|
backstack.push(NavTarget.LicenseDetails(license)) |
||||||
|
} |
||||||
|
} |
||||||
|
createNode<DependencyLicensesListNode>(buildContext, listOf(callback)) |
||||||
|
} |
||||||
|
is NavTarget.LicenseDetails -> { |
||||||
|
createNode<DependenciesDetailsNode>(buildContext, listOf(DependenciesDetailsNode.Inputs(navTarget.license))) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
override fun View(modifier: Modifier) { |
||||||
|
BackstackView(modifier) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import com.squareup.anvil.annotations.ContributesBinding |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers |
||||||
|
import io.element.android.libraries.di.AppScope |
||||||
|
import io.element.android.libraries.di.ApplicationContext |
||||||
|
import kotlinx.coroutines.withContext |
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi |
||||||
|
import kotlinx.serialization.json.Json |
||||||
|
import kotlinx.serialization.json.decodeFromStream |
||||||
|
import javax.inject.Inject |
||||||
|
|
||||||
|
interface LicensesProvider { |
||||||
|
suspend fun provides(): List<DependencyLicenseItem> |
||||||
|
} |
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class) |
||||||
|
class AssetLicensesProvider @Inject constructor( |
||||||
|
@ApplicationContext private val context: Context, |
||||||
|
private val dispatchers: CoroutineDispatchers, |
||||||
|
) : LicensesProvider { |
||||||
|
@OptIn(ExperimentalSerializationApi::class) |
||||||
|
override suspend fun provides(): List<DependencyLicenseItem> { |
||||||
|
return withContext(dispatchers.io) { |
||||||
|
context.assets.open("licensee-artifacts.json").use { inputStream -> |
||||||
|
val json = Json { |
||||||
|
ignoreUnknownKeys = true |
||||||
|
explicitNulls = false |
||||||
|
} |
||||||
|
json.decodeFromStream<List<DependencyLicenseItem>>(inputStream) |
||||||
|
.sortedBy { it.safeName.lowercase() } |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.details |
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import com.bumble.appyx.core.modality.BuildContext |
||||||
|
import com.bumble.appyx.core.node.Node |
||||||
|
import com.bumble.appyx.core.plugin.Plugin |
||||||
|
import dagger.assisted.Assisted |
||||||
|
import dagger.assisted.AssistedInject |
||||||
|
import io.element.android.anvilannotations.ContributesNode |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.architecture.NodeInputs |
||||||
|
import io.element.android.libraries.architecture.inputs |
||||||
|
import io.element.android.libraries.di.AppScope |
||||||
|
|
||||||
|
@ContributesNode(AppScope::class) |
||||||
|
class DependenciesDetailsNode @AssistedInject constructor( |
||||||
|
@Assisted buildContext: BuildContext, |
||||||
|
@Assisted plugins: List<Plugin>, |
||||||
|
) : Node( |
||||||
|
buildContext = buildContext, |
||||||
|
plugins = plugins |
||||||
|
) { |
||||||
|
data class Inputs( |
||||||
|
val licenseItem: DependencyLicenseItem, |
||||||
|
) : NodeInputs |
||||||
|
|
||||||
|
private val licenseItem = inputs<Inputs>().licenseItem |
||||||
|
|
||||||
|
@Composable |
||||||
|
override fun View(modifier: Modifier) { |
||||||
|
DependenciesDetailsView( |
||||||
|
modifier = modifier, |
||||||
|
licenseItem = licenseItem, |
||||||
|
onBack = ::navigateUp |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,90 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.details |
||||||
|
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.foundation.lazy.LazyColumn |
||||||
|
import androidx.compose.foundation.lazy.items |
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import io.element.android.features.licenses.impl.list.aDependencyLicenseItem |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.designsystem.components.ClickableLinkText |
||||||
|
import io.element.android.libraries.designsystem.components.button.BackButton |
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreview |
||||||
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight |
||||||
|
import io.element.android.libraries.designsystem.theme.components.ListItem |
||||||
|
import io.element.android.libraries.designsystem.theme.components.Scaffold |
||||||
|
import io.element.android.libraries.designsystem.theme.components.Text |
||||||
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar |
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class) |
||||||
|
@Composable |
||||||
|
fun DependenciesDetailsView( |
||||||
|
licenseItem: DependencyLicenseItem, |
||||||
|
onBack: () -> Unit, |
||||||
|
modifier: Modifier = Modifier, |
||||||
|
) { |
||||||
|
Scaffold( |
||||||
|
modifier = modifier, |
||||||
|
topBar = { |
||||||
|
TopAppBar( |
||||||
|
title = { Text(text = licenseItem.safeName) }, |
||||||
|
navigationIcon = { BackButton(onClick = onBack) }, |
||||||
|
) |
||||||
|
}, |
||||||
|
) { contentPadding -> |
||||||
|
LazyColumn( |
||||||
|
modifier = Modifier.padding(contentPadding), |
||||||
|
) { |
||||||
|
val licenses = licenseItem.licenses.orEmpty() + |
||||||
|
licenseItem.unknownLicenses.orEmpty() |
||||||
|
items(licenses) { license -> |
||||||
|
val text = buildString { |
||||||
|
if (license.name != null) { |
||||||
|
append(license.name) |
||||||
|
append("\n") |
||||||
|
append("\n") |
||||||
|
} |
||||||
|
if (license.url != null) { |
||||||
|
append(license.url) |
||||||
|
} |
||||||
|
} |
||||||
|
ListItem( |
||||||
|
headlineContent = { |
||||||
|
ClickableLinkText( |
||||||
|
text = text, |
||||||
|
interactionSource = remember { MutableInteractionSource() }, |
||||||
|
) |
||||||
|
} |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@PreviewsDayNight |
||||||
|
@Composable |
||||||
|
internal fun DependenciesDetailsViewPreview() = ElementPreview { |
||||||
|
DependenciesDetailsView( |
||||||
|
licenseItem = aDependencyLicenseItem(), |
||||||
|
onBack = {} |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.list |
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import com.bumble.appyx.core.modality.BuildContext |
||||||
|
import com.bumble.appyx.core.node.Node |
||||||
|
import com.bumble.appyx.core.plugin.Plugin |
||||||
|
import com.bumble.appyx.core.plugin.plugins |
||||||
|
import dagger.assisted.Assisted |
||||||
|
import dagger.assisted.AssistedInject |
||||||
|
import io.element.android.anvilannotations.ContributesNode |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.di.AppScope |
||||||
|
|
||||||
|
@ContributesNode(AppScope::class) |
||||||
|
class DependencyLicensesListNode @AssistedInject constructor( |
||||||
|
@Assisted buildContext: BuildContext, |
||||||
|
@Assisted plugins: List<Plugin>, |
||||||
|
private val presenter: DependencyLicensesListPresenter, |
||||||
|
) : Node( |
||||||
|
buildContext = buildContext, |
||||||
|
plugins = plugins |
||||||
|
) { |
||||||
|
interface Callback : Plugin { |
||||||
|
fun onOpenLicense(license: DependencyLicenseItem) |
||||||
|
} |
||||||
|
|
||||||
|
private fun onOpenLicense(license: DependencyLicenseItem) { |
||||||
|
plugins<Callback>() |
||||||
|
.forEach { it.onOpenLicense(license) } |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
override fun View(modifier: Modifier) { |
||||||
|
val state = presenter.present() |
||||||
|
DependencyLicensesListView( |
||||||
|
state = state, |
||||||
|
onBackClick = ::navigateUp, |
||||||
|
onOpenLicense = ::onOpenLicense, |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.list |
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.LaunchedEffect |
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import io.element.android.features.licenses.impl.LicensesProvider |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.architecture.AsyncData |
||||||
|
import io.element.android.libraries.architecture.Presenter |
||||||
|
import kotlinx.collections.immutable.ImmutableList |
||||||
|
import kotlinx.collections.immutable.toPersistentList |
||||||
|
import javax.inject.Inject |
||||||
|
|
||||||
|
class DependencyLicensesListPresenter @Inject constructor( |
||||||
|
private val licensesProvider: LicensesProvider, |
||||||
|
) : Presenter<DependencyLicensesListState> { |
||||||
|
@Composable |
||||||
|
override fun present(): DependencyLicensesListState { |
||||||
|
var licenses by remember { |
||||||
|
mutableStateOf<AsyncData<ImmutableList<DependencyLicenseItem>>>(AsyncData.Loading()) |
||||||
|
} |
||||||
|
LaunchedEffect(Unit) { |
||||||
|
runCatching { |
||||||
|
licenses = AsyncData.Success(licensesProvider.provides().toPersistentList()) |
||||||
|
}.onFailure { |
||||||
|
licenses = AsyncData.Failure(it) |
||||||
|
} |
||||||
|
} |
||||||
|
return DependencyLicensesListState(licenses = licenses) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.list |
||||||
|
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.features.licenses.impl.model.License |
||||||
|
import io.element.android.libraries.architecture.AsyncData |
||||||
|
import kotlinx.collections.immutable.persistentListOf |
||||||
|
|
||||||
|
open class DependencyLicensesListStateProvider : PreviewParameterProvider<DependencyLicensesListState> { |
||||||
|
override val values: Sequence<DependencyLicensesListState> |
||||||
|
get() = sequenceOf( |
||||||
|
DependencyLicensesListState( |
||||||
|
licenses = AsyncData.Loading() |
||||||
|
), |
||||||
|
DependencyLicensesListState( |
||||||
|
licenses = AsyncData.Failure(Exception("Failed to load licenses")) |
||||||
|
), |
||||||
|
DependencyLicensesListState( |
||||||
|
licenses = AsyncData.Success( |
||||||
|
persistentListOf( |
||||||
|
aDependencyLicenseItem(), |
||||||
|
aDependencyLicenseItem(name = null), |
||||||
|
) |
||||||
|
) |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
internal fun aDependencyLicenseItem( |
||||||
|
name: String? = "A dependency", |
||||||
|
) = DependencyLicenseItem( |
||||||
|
groupId = "org.some.group", |
||||||
|
artifactId = "a-dependency", |
||||||
|
version = "1.0.0", |
||||||
|
name = name, |
||||||
|
licenses = listOf( |
||||||
|
License( |
||||||
|
identifier = "Apache 2.0", |
||||||
|
name = "Apache 2.0", |
||||||
|
url = "https://www.apache.org/licenses/LICENSE-2.0" |
||||||
|
) |
||||||
|
), |
||||||
|
unknownLicenses = listOf(), |
||||||
|
scm = null, |
||||||
|
) |
@ -0,0 +1,118 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.list |
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box |
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.foundation.lazy.LazyColumn |
||||||
|
import androidx.compose.foundation.lazy.items |
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api |
||||||
|
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.PreviewParameter |
||||||
|
import androidx.compose.ui.unit.dp |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.architecture.AsyncData |
||||||
|
import io.element.android.libraries.designsystem.components.button.BackButton |
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreview |
||||||
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight |
||||||
|
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator |
||||||
|
import io.element.android.libraries.designsystem.theme.components.ListItem |
||||||
|
import io.element.android.libraries.designsystem.theme.components.Scaffold |
||||||
|
import io.element.android.libraries.designsystem.theme.components.Text |
||||||
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar |
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings |
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class) |
||||||
|
@Composable |
||||||
|
fun DependencyLicensesListView( |
||||||
|
state: DependencyLicensesListState, |
||||||
|
onBackClick: () -> Unit, |
||||||
|
onOpenLicense: (DependencyLicenseItem) -> Unit, |
||||||
|
modifier: Modifier = Modifier, |
||||||
|
) { |
||||||
|
Scaffold( |
||||||
|
modifier = modifier, |
||||||
|
topBar = { |
||||||
|
TopAppBar( |
||||||
|
title = { Text(text = stringResource(CommonStrings.common_open_source_licenses)) }, |
||||||
|
navigationIcon = { BackButton(onClick = onBackClick) }, |
||||||
|
) |
||||||
|
}, |
||||||
|
) { contentPadding -> |
||||||
|
LazyColumn( |
||||||
|
modifier = Modifier |
||||||
|
.padding(contentPadding) |
||||||
|
.padding(horizontal = 16.dp) |
||||||
|
) { |
||||||
|
when (state.licenses) { |
||||||
|
is AsyncData.Failure -> item { |
||||||
|
Text( |
||||||
|
text = stringResource(CommonStrings.common_error), |
||||||
|
modifier = Modifier.padding(16.dp) |
||||||
|
) |
||||||
|
} |
||||||
|
AsyncData.Uninitialized, |
||||||
|
is AsyncData.Loading -> item { |
||||||
|
Box( |
||||||
|
modifier = Modifier |
||||||
|
.fillMaxWidth() |
||||||
|
.padding(top = 64.dp) |
||||||
|
) { |
||||||
|
CircularProgressIndicator( |
||||||
|
modifier = Modifier.align(Alignment.Center) |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
is AsyncData.Success -> items(state.licenses.data) { license -> |
||||||
|
ListItem( |
||||||
|
headlineContent = { Text(license.safeName) }, |
||||||
|
supportingContent = { |
||||||
|
Text( |
||||||
|
buildString { |
||||||
|
append(license.groupId) |
||||||
|
append(":") |
||||||
|
append(license.artifactId) |
||||||
|
append(":") |
||||||
|
append(license.version) |
||||||
|
} |
||||||
|
) |
||||||
|
}, |
||||||
|
onClick = { |
||||||
|
onOpenLicense(license) |
||||||
|
} |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@PreviewsDayNight |
||||||
|
@Composable |
||||||
|
internal fun DependencyLicensesListViewPreview( |
||||||
|
@PreviewParameter(DependencyLicensesListStateProvider::class) state: DependencyLicensesListState |
||||||
|
) = ElementPreview { |
||||||
|
DependencyLicensesListView( |
||||||
|
state = state, |
||||||
|
onBackClick = {}, |
||||||
|
onOpenLicense = {}, |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.model |
||||||
|
|
||||||
|
import android.os.Parcelable |
||||||
|
import kotlinx.parcelize.IgnoredOnParcel |
||||||
|
import kotlinx.parcelize.Parcelize |
||||||
|
import kotlinx.serialization.SerialName |
||||||
|
import kotlinx.serialization.Serializable |
||||||
|
|
||||||
|
@Serializable |
||||||
|
@Parcelize |
||||||
|
data class DependencyLicenseItem( |
||||||
|
val groupId: String, |
||||||
|
val artifactId: String, |
||||||
|
val version: String, |
||||||
|
@SerialName("spdxLicenses") |
||||||
|
val licenses: List<License>?, |
||||||
|
val unknownLicenses: List<License>?, |
||||||
|
val name: String?, |
||||||
|
val scm: Scm?, |
||||||
|
) : Parcelable { |
||||||
|
@IgnoredOnParcel |
||||||
|
val safeName = name?.takeIf { name -> name != "null" } ?: "$groupId:$artifactId" |
||||||
|
} |
||||||
|
|
||||||
|
@Serializable |
||||||
|
@Parcelize |
||||||
|
data class License( |
||||||
|
val identifier: String?, |
||||||
|
val name: String?, |
||||||
|
val url: String?, |
||||||
|
) : Parcelable |
||||||
|
|
||||||
|
@Serializable |
||||||
|
@Parcelize |
||||||
|
data class Scm( |
||||||
|
val url: String, |
||||||
|
) : Parcelable |
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.list |
||||||
|
|
||||||
|
import app.cash.molecule.RecompositionMode |
||||||
|
import app.cash.molecule.moleculeFlow |
||||||
|
import app.cash.turbine.test |
||||||
|
import com.google.common.truth.Truth.assertThat |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.libraries.architecture.AsyncData |
||||||
|
import io.element.android.tests.testutils.WarmUpRule |
||||||
|
import kotlinx.coroutines.test.runTest |
||||||
|
import org.junit.Rule |
||||||
|
import org.junit.Test |
||||||
|
|
||||||
|
class DependencyLicensesListPresenterTest { |
||||||
|
@get:Rule |
||||||
|
val warmUpRule = WarmUpRule() |
||||||
|
|
||||||
|
@Test |
||||||
|
fun `present - initial state, no licenses`() = runTest { |
||||||
|
val presenter = createPresenter { emptyList() } |
||||||
|
moleculeFlow(RecompositionMode.Immediate) { |
||||||
|
presenter.present() |
||||||
|
}.test { |
||||||
|
val initialState = awaitItem() |
||||||
|
assertThat(initialState.licenses).isInstanceOf(AsyncData.Loading::class.java) |
||||||
|
val finalState = awaitItem() |
||||||
|
assertThat(finalState.licenses.isSuccess()).isTrue() |
||||||
|
assertThat(finalState.licenses.dataOrNull()).isEmpty() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun `present - initial state, one license`() = runTest { |
||||||
|
val anItem = aDependencyLicenseItem() |
||||||
|
val presenter = createPresenter { |
||||||
|
listOf(anItem) |
||||||
|
} |
||||||
|
moleculeFlow(RecompositionMode.Immediate) { |
||||||
|
presenter.present() |
||||||
|
}.test { |
||||||
|
val initialState = awaitItem() |
||||||
|
assertThat(initialState.licenses).isInstanceOf(AsyncData.Loading::class.java) |
||||||
|
val finalState = awaitItem() |
||||||
|
assertThat(finalState.licenses.isSuccess()).isTrue() |
||||||
|
assertThat(finalState.licenses.dataOrNull()!!.size).isEqualTo(1) |
||||||
|
assertThat(finalState.licenses.dataOrNull()!!.get(0)).isEqualTo(anItem) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun createPresenter( |
||||||
|
provideResult: () -> List<DependencyLicenseItem> |
||||||
|
) = DependencyLicensesListPresenter( |
||||||
|
licensesProvider = FakeLicensesProvider(provideResult), |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package io.element.android.features.licenses.impl.list |
||||||
|
|
||||||
|
import io.element.android.features.licenses.impl.LicensesProvider |
||||||
|
import io.element.android.features.licenses.impl.model.DependencyLicenseItem |
||||||
|
import io.element.android.tests.testutils.lambda.lambdaError |
||||||
|
|
||||||
|
class FakeLicensesProvider( |
||||||
|
private val provideResult: () -> List<DependencyLicenseItem> = { lambdaError() } |
||||||
|
) : LicensesProvider { |
||||||
|
override suspend fun provides(): List<DependencyLicenseItem> { |
||||||
|
return provideResult() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2024 New Vector Ltd |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package extension |
||||||
|
|
||||||
|
import java.io.File |
||||||
|
import org.gradle.api.DefaultTask |
||||||
|
import org.gradle.api.file.DirectoryProperty |
||||||
|
import org.gradle.api.file.RegularFileProperty |
||||||
|
import org.gradle.api.provider.Property |
||||||
|
import org.gradle.api.tasks.CacheableTask |
||||||
|
import org.gradle.api.tasks.Input |
||||||
|
import org.gradle.api.tasks.InputFile |
||||||
|
import org.gradle.api.tasks.OutputDirectory |
||||||
|
import org.gradle.api.tasks.PathSensitive |
||||||
|
import org.gradle.api.tasks.PathSensitivity |
||||||
|
import org.gradle.api.tasks.TaskAction |
||||||
|
|
||||||
|
@CacheableTask |
||||||
|
abstract class AssetCopyTask : DefaultTask() { |
||||||
|
@get:OutputDirectory |
||||||
|
abstract val outputDirectory: DirectoryProperty |
||||||
|
|
||||||
|
@get:PathSensitive(PathSensitivity.RELATIVE) |
||||||
|
@get:InputFile |
||||||
|
abstract val inputFile: RegularFileProperty |
||||||
|
|
||||||
|
@get:Input |
||||||
|
abstract val targetFileName: Property<String> |
||||||
|
|
||||||
|
@TaskAction |
||||||
|
fun action() { |
||||||
|
println("Copying ${inputFile.get()} to ${outputDirectory.get().asFile}/${targetFileName.get()}") |
||||||
|
inputFile.get().asFile.copyTo( |
||||||
|
target = File( |
||||||
|
outputDirectory.get().asFile, |
||||||
|
targetFileName.get(), |
||||||
|
), |
||||||
|
overwrite = true, |
||||||
|
) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue