From 47ec25d81387cb87f1039ad60a31916a9b0609fb Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Tue, 29 Aug 2023 23:30:39 +0900 Subject: [PATCH 01/41] Add feature/licenses module --- feature/licenses/.gitignore | 1 + feature/licenses/build.gradle.kts | 15 +++++++++++++ feature/licenses/proguard-rules.pro | 21 +++++++++++++++++++ .../src/test/resources/robolectric.properties | 3 +++ settings.gradle.kts | 1 + 5 files changed, 41 insertions(+) create mode 100644 feature/licenses/.gitignore create mode 100644 feature/licenses/build.gradle.kts create mode 100644 feature/licenses/proguard-rules.pro create mode 100644 feature/licenses/src/test/resources/robolectric.properties diff --git a/feature/licenses/.gitignore b/feature/licenses/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/feature/licenses/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/licenses/build.gradle.kts b/feature/licenses/build.gradle.kts new file mode 100644 index 000000000..7cdf7bbba --- /dev/null +++ b/feature/licenses/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("droidkaigi.convention.androidfeature") +} + +android.namespace = "io.github.droidkaigi.confsched2023.feature.licenses" + +dependencies { + implementation(projects.core.designsystem) + implementation(projects.core.ui) + implementation(projects.core.model) + testImplementation(projects.core.testing) + + implementation(libs.composeHiltNavigtation) + implementation(libs.composeMaterialIcon) +} diff --git a/feature/licenses/proguard-rules.pro b/feature/licenses/proguard-rules.pro new file mode 100644 index 000000000..ff59496d8 --- /dev/null +++ b/feature/licenses/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle.kts. +# +# 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/feature/licenses/src/test/resources/robolectric.properties b/feature/licenses/src/test/resources/robolectric.properties new file mode 100644 index 000000000..82b64083b --- /dev/null +++ b/feature/licenses/src/test/resources/robolectric.properties @@ -0,0 +1,3 @@ +application=dagger.hilt.android.testing.HiltTestApplication +# https://github.com/robolectric/robolectric/issues/6593 +instrumentedPackages=androidx.loader.content \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index cfb3ff2d0..791776d8e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,6 +26,7 @@ include( ":feature:contributors", ":feature:stamps", ":feature:staff", + ":feature:licenses", ":core:designsystem", ":core:data", ":core:model", From aa0e41975ff5e80f8ea8eed55f12b22c2a0f2b35 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 11:30:23 +0900 Subject: [PATCH 02/41] Add empty oss license screen --- .../io/github/droidkaigi/confsched2023/OssLicenseScreen.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt new file mode 100644 index 000000000..04ebf1e64 --- /dev/null +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt @@ -0,0 +1,7 @@ +package io.github.droidkaigi.confsched2023 + +import androidx.compose.runtime.Composable + +@Composable +fun OssLicenseScreen (){ +} From f537b83f0a1a88ac50011b4771b57a138b6c5f8d Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 11:31:08 +0900 Subject: [PATCH 03/41] Add empty oss license ViewModel --- .../droidkaigi/confsched2023/OssLicenseViewModel.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt new file mode 100644 index 000000000..2920e2483 --- /dev/null +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt @@ -0,0 +1,11 @@ +package io.github.droidkaigi.confsched2023 + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class OssLicenseViewModel @Inject constructor( + +) : ViewModel() { +} From fde39dc2aea2586e69fba960718b4f25d3aff3c4 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 11:32:03 +0900 Subject: [PATCH 04/41] Combine screen and ViewModel --- .../io/github/droidkaigi/confsched2023/OssLicenseScreen.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt index 04ebf1e64..d4b354721 100644 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt @@ -1,7 +1,10 @@ package io.github.droidkaigi.confsched2023 import androidx.compose.runtime.Composable +import androidx.hilt.navigation.compose.hiltViewModel @Composable -fun OssLicenseScreen (){ +fun OssLicenseScreen ( + viewModel: OssLicenseViewModel = hiltViewModel(), +){ } From 15c6b3bd03ea5bfda463f40c8b64a641cefa9342 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 11:55:31 +0900 Subject: [PATCH 05/41] Setup basis of license screen --- app-android/build.gradle.kts | 1 + .../droidkaigi/confsched2023/KaigiApp.kt | 3 +- .../droidkaigi/confsched2023/OssLicense.kt | 5 ++ .../confsched2023/OssLicenseRepository.kt | 25 +++++++++ .../OssLicenseRepositoryModule.kt | 17 ++++++ .../confsched2023/OssLicenseScreen.kt | 53 ++++++++++++++++++- .../confsched2023/OssLicenseViewModel.kt | 26 ++++++++- 7 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt create mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt create mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt diff --git a/app-android/build.gradle.kts b/app-android/build.gradle.kts index 8ab192f01..c673fbd05 100644 --- a/app-android/build.gradle.kts +++ b/app-android/build.gradle.kts @@ -102,6 +102,7 @@ dependencies { implementation(projects.feature.floorMap) implementation(projects.feature.stamps) implementation(projects.feature.staff) + implementation(projects.feature.licenses) implementation(projects.core.model) implementation(projects.core.data) implementation(projects.core.designsystem) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt index 3baace71f..3d86310eb 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt @@ -127,6 +127,7 @@ private fun KaigiNavHost( onBackClick = navController::popBackStack, onStaffClick = externalNavController::navigate, ) + ossLicenseScreen() } } @@ -159,7 +160,7 @@ private fun NavGraphBuilder.mainScreen( Sponsors -> navController.navigateSponsorsScreen() CodeOfConduct -> { externalNavController.navigate(url = "$portalBaseUrl/about/code-of-conduct") } Contributors -> mainNestedNavController.navigate(contributorsScreenRoute) - License -> externalNavController.navigateToLicenseScreen() + License -> navController.navigateOssLicenseScreen() Medium -> externalNavController.navigate(url = "https://medium.com/droidkaigi") PrivacyPolicy -> { externalNavController.navigate(url = "$portalBaseUrl/about/privacy") } Staff -> navController.navigateStaffScreen() diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt new file mode 100644 index 000000000..2a39d3208 --- /dev/null +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt @@ -0,0 +1,5 @@ +package io.github.droidkaigi.confsched2023 + +data class OssLicense( + val name: String, +) diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt new file mode 100644 index 000000000..627406ec1 --- /dev/null +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt @@ -0,0 +1,25 @@ +package io.github.droidkaigi.confsched2023 + +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import javax.inject.Inject + +public interface OssLicenseRepository { + public fun sponsors(): Flow> + + public fun refresh(): Unit +} + +internal class OssLicenseRepositoryImpl @Inject constructor() : OssLicenseRepository { + + private val ossLicenseStateFlow = MutableStateFlow>(persistentListOf()) + override fun sponsors(): Flow> { + return ossLicenseStateFlow + } + + override fun refresh() { + // TODO implement later + } +} diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt new file mode 100644 index 000000000..a7a871add --- /dev/null +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt @@ -0,0 +1,17 @@ +package io.github.droidkaigi.confsched2023 + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class OssLicenseRepositoryModule { + @Provides + @Singleton + fun provideSponsorsRepository(): OssLicenseRepository { + return OssLicenseRepositoryImpl() + } +} diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt index d4b354721..86b84374a 100644 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt @@ -1,10 +1,59 @@ package io.github.droidkaigi.confsched2023 +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable + +const val ossLicenseScreenRoute = "osslicense" +fun NavGraphBuilder.ossLicenseScreen() { + composable(ossLicenseScreenRoute) { + OssLicenseScreen() + } +} + +fun NavController.navigateOssLicenseScreen() { + navigate(ossLicenseScreenRoute) +} + +data class OssLicenseScreenUiState( + val licenseList: MutableList = mutableListOf(), +) @Composable -fun OssLicenseScreen ( +fun OssLicenseScreen( viewModel: OssLicenseViewModel = hiltViewModel(), -){ +) { + val uiState by viewModel.uiState.collectAsState() + + LaunchedEffect(Unit) { + viewModel.loadLicenseList() + } + + OssLicenseScreen( + uiState = uiState, + onLibraryClick = {}, + ) +} + +@Composable +private fun OssLicenseScreen( + uiState: OssLicenseScreenUiState, + onLibraryClick: (OssLicense) -> Unit, +) { + LazyColumn { + items(items = uiState.licenseList) { item -> + TextButton(onClick = { onLibraryClick(item) }) { + Text(text = item.name) + } + } + } } diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt index 2920e2483..c597cd6f4 100644 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt +++ b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt @@ -1,11 +1,35 @@ package io.github.droidkaigi.confsched2023 import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.droidkaigi.confsched2023.ui.buildUiState +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.stateIn import javax.inject.Inject @HiltViewModel class OssLicenseViewModel @Inject constructor( - + ossLicenseRepository: OssLicenseRepository, ) : ViewModel() { + + private val ossLicenseStateFlow: StateFlow> = + ossLicenseRepository.sponsors() + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5_000), + initialValue = persistentListOf(), + ) + + internal val uiState: StateFlow = + buildUiState(ossLicenseStateFlow) { staffs -> + OssLicenseScreenUiState() + } + + fun loadLicenseList() { + // TODO implement load logic + } } From 810acb48cdfa20acc962253b2733b4e58fbe69a6 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 15:04:38 +0900 Subject: [PATCH 06/41] Remove feature/lincenses --- app-android/build.gradle.kts | 1 - settings.gradle.kts | 1 - 2 files changed, 2 deletions(-) diff --git a/app-android/build.gradle.kts b/app-android/build.gradle.kts index c673fbd05..8ab192f01 100644 --- a/app-android/build.gradle.kts +++ b/app-android/build.gradle.kts @@ -102,7 +102,6 @@ dependencies { implementation(projects.feature.floorMap) implementation(projects.feature.stamps) implementation(projects.feature.staff) - implementation(projects.feature.licenses) implementation(projects.core.model) implementation(projects.core.data) implementation(projects.core.designsystem) diff --git a/settings.gradle.kts b/settings.gradle.kts index 791776d8e..cfb3ff2d0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,7 +26,6 @@ include( ":feature:contributors", ":feature:stamps", ":feature:staff", - ":feature:licenses", ":core:designsystem", ":core:data", ":core:model", From 2a326c1cb83ca8bb01e8087e3e9e0dac7a8a8b0f Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 15:05:44 +0900 Subject: [PATCH 07/41] Remove feature/licenses relational file --- feature/licenses/.gitignore | 1 - feature/licenses/build.gradle.kts | 15 ------------- feature/licenses/proguard-rules.pro | 21 ------------------- .../src/test/resources/robolectric.properties | 3 --- 4 files changed, 40 deletions(-) delete mode 100644 feature/licenses/.gitignore delete mode 100644 feature/licenses/build.gradle.kts delete mode 100644 feature/licenses/proguard-rules.pro delete mode 100644 feature/licenses/src/test/resources/robolectric.properties diff --git a/feature/licenses/.gitignore b/feature/licenses/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/feature/licenses/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/feature/licenses/build.gradle.kts b/feature/licenses/build.gradle.kts deleted file mode 100644 index 7cdf7bbba..000000000 --- a/feature/licenses/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -plugins { - id("droidkaigi.convention.androidfeature") -} - -android.namespace = "io.github.droidkaigi.confsched2023.feature.licenses" - -dependencies { - implementation(projects.core.designsystem) - implementation(projects.core.ui) - implementation(projects.core.model) - testImplementation(projects.core.testing) - - implementation(libs.composeHiltNavigtation) - implementation(libs.composeMaterialIcon) -} diff --git a/feature/licenses/proguard-rules.pro b/feature/licenses/proguard-rules.pro deleted file mode 100644 index ff59496d8..000000000 --- a/feature/licenses/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.kts. -# -# 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/feature/licenses/src/test/resources/robolectric.properties b/feature/licenses/src/test/resources/robolectric.properties deleted file mode 100644 index 82b64083b..000000000 --- a/feature/licenses/src/test/resources/robolectric.properties +++ /dev/null @@ -1,3 +0,0 @@ -application=dagger.hilt.android.testing.HiltTestApplication -# https://github.com/robolectric/robolectric/issues/6593 -instrumentedPackages=androidx.loader.content \ No newline at end of file From b717b7d76b222fbcbb0f3265593f2f4aa88ab541 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 15:05:58 +0900 Subject: [PATCH 08/41] Move classes --- .../confsched2023/license/OssLicense.kt | 7 +++ .../license/OssLicenseRepository.kt | 45 +++++++++++++++++++ .../license/OssLicenseRepositoryModule.kt | 21 +++++++++ .../license}/OssLicenseScreen.kt | 2 +- .../license}/OssLicenseViewModel.kt | 2 +- .../droidkaigi/confsched2023/OssLicense.kt | 5 --- .../confsched2023/OssLicenseRepository.kt | 25 ----------- .../OssLicenseRepositoryModule.kt | 17 ------- 8 files changed, 75 insertions(+), 49 deletions(-) create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt rename {feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023 => app-android/src/main/java/io/github/droidkaigi/confsched2023/license}/OssLicenseScreen.kt (96%) rename {feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023 => app-android/src/main/java/io/github/droidkaigi/confsched2023/license}/OssLicenseViewModel.kt (95%) delete mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt delete mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt delete mode 100644 feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt new file mode 100644 index 000000000..c6818e4a6 --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt @@ -0,0 +1,7 @@ +package io.github.droidkaigi.confsched2023.license + +data class OssLicense( + val name: String, + val ossSet: Int, + val length: Int, +) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt new file mode 100644 index 000000000..53487570c --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt @@ -0,0 +1,45 @@ +package io.github.droidkaigi.confsched2023.license + +import android.content.Context +import com.google.android.gms.oss.licenses.R +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import okio.buffer +import okio.source +import javax.inject.Inject + +public interface OssLicenseRepository { + public fun sponsors(): Flow> + + public fun refresh(): Unit +} + +internal class OssLicenseRepositoryImpl @Inject constructor( + private val context:Context +) : OssLicenseRepository { + + private val ossLicenseStateFlow = MutableStateFlow>(persistentListOf()) + override fun sponsors(): Flow> { + refresh() + return ossLicenseStateFlow + } + + override fun refresh() { + ossLicenseStateFlow.value = context.resources.openRawResource(R.raw.keep_third_party_licenses) + .source() + .buffer() + .use { + val libraries = mutableListOf() + while (true) { + val line = it.readUtf8Line() ?: break + val (position, name) = line.split(' ', limit = 2) + val (offset, length) = position.split(':').map { it.toInt() } + libraries.add(OssLicense(name, offset, length)) + } + libraries.toList() + }.toPersistentList() + } +} diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt new file mode 100644 index 000000000..44502ee38 --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt @@ -0,0 +1,21 @@ +package io.github.droidkaigi.confsched2023.license + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class OssLicenseRepositoryModule { + @Provides + @Singleton + fun provideSponsorsRepository( + @ApplicationContext context: Context, + ): OssLicenseRepository { + return OssLicenseRepositoryImpl(context = context) + } +} diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt similarity index 96% rename from feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt rename to app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt index 86b84374a..38641f552 100644 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt @@ -1,4 +1,4 @@ -package io.github.droidkaigi.confsched2023 +package io.github.droidkaigi.confsched2023.license import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt similarity index 95% rename from feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt rename to app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index c597cd6f4..15a4483d5 100644 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -1,4 +1,4 @@ -package io.github.droidkaigi.confsched2023 +package io.github.droidkaigi.confsched2023.license import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt deleted file mode 100644 index 2a39d3208..000000000 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicense.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.github.droidkaigi.confsched2023 - -data class OssLicense( - val name: String, -) diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt deleted file mode 100644 index 627406ec1..000000000 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepository.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.droidkaigi.confsched2023 - -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import javax.inject.Inject - -public interface OssLicenseRepository { - public fun sponsors(): Flow> - - public fun refresh(): Unit -} - -internal class OssLicenseRepositoryImpl @Inject constructor() : OssLicenseRepository { - - private val ossLicenseStateFlow = MutableStateFlow>(persistentListOf()) - override fun sponsors(): Flow> { - return ossLicenseStateFlow - } - - override fun refresh() { - // TODO implement later - } -} diff --git a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt b/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt deleted file mode 100644 index a7a871add..000000000 --- a/feature/licenses/src/main/kotlin/io/github/droidkaigi/confsched2023/OssLicenseRepositoryModule.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.droidkaigi.confsched2023 - -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -class OssLicenseRepositoryModule { - @Provides - @Singleton - fun provideSponsorsRepository(): OssLicenseRepository { - return OssLicenseRepositoryImpl() - } -} From 6ddec12f0e95c835be67ea92b39adebfd6c8c72e Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 15:26:40 +0900 Subject: [PATCH 09/41] Add logic to load the licenses data --- .../droidkaigi/confsched2023/KaigiApp.kt | 2 + .../license/OssLicenseRepository.kt | 45 +++++++++++++------ .../license/OssLicenseViewModel.kt | 8 ++-- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt index 3d86310eb..0389239b6 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt @@ -39,6 +39,8 @@ import io.github.droidkaigi.confsched2023.designsystem.theme.KaigiTheme import io.github.droidkaigi.confsched2023.floormap.floorMapScreenRoute import io.github.droidkaigi.confsched2023.floormap.navigateFloorMapScreen import io.github.droidkaigi.confsched2023.floormap.nestedFloorMapScreen +import io.github.droidkaigi.confsched2023.license.navigateOssLicenseScreen +import io.github.droidkaigi.confsched2023.license.ossLicenseScreen import io.github.droidkaigi.confsched2023.main.MainNestedGraphStateHolder import io.github.droidkaigi.confsched2023.main.MainScreenTab import io.github.droidkaigi.confsched2023.main.MainScreenTab.About diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt index 53487570c..2682c2caa 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt @@ -1,12 +1,13 @@ package io.github.droidkaigi.confsched2023.license import android.content.Context -import com.google.android.gms.oss.licenses.R +import io.github.droidkaigi.confsched2023.R import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import okio.BufferedSource import okio.buffer import okio.source import javax.inject.Inject @@ -18,28 +19,44 @@ public interface OssLicenseRepository { } internal class OssLicenseRepositoryImpl @Inject constructor( - private val context:Context + private val context: Context, ) : OssLicenseRepository { - private val ossLicenseStateFlow = MutableStateFlow>(persistentListOf()) + private val ossLicenseStateFlow = + MutableStateFlow>(persistentListOf()) + override fun sponsors(): Flow> { refresh() return ossLicenseStateFlow } override fun refresh() { - ossLicenseStateFlow.value = context.resources.openRawResource(R.raw.keep_third_party_licenses) + ossLicenseStateFlow.value = readLicensesMetaFile() + .toRowList() + .parseToLibraryItem() + .toPersistentList() + } + + private fun readLicensesMetaFile(): BufferedSource { + return context.resources.openRawResource(R.raw.third_party_license_metadata) .source() .buffer() - .use { - val libraries = mutableListOf() - while (true) { - val line = it.readUtf8Line() ?: break - val (position, name) = line.split(' ', limit = 2) - val (offset, length) = position.split(':').map { it.toInt() } - libraries.add(OssLicense(name, offset, length)) - } - libraries.toList() - }.toPersistentList() + } + + private fun List.parseToLibraryItem(): List { + return map { + val (position, name) = it.split(' ', limit = 2) + val (offset, length) = position.split(':').map { it.toInt() } + OssLicense(name, offset, length) + } + } + + private fun BufferedSource.toRowList(): List { + val list: MutableList = mutableListOf() + while (true) { + val line = readUtf8Line() ?: break + list.add(line) + } + return list } } diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index 15a4483d5..46c3c7c81 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -13,7 +13,7 @@ import javax.inject.Inject @HiltViewModel class OssLicenseViewModel @Inject constructor( - ossLicenseRepository: OssLicenseRepository, + private val ossLicenseRepository: OssLicenseRepository, ) : ViewModel() { private val ossLicenseStateFlow: StateFlow> = @@ -25,11 +25,11 @@ class OssLicenseViewModel @Inject constructor( ) internal val uiState: StateFlow = - buildUiState(ossLicenseStateFlow) { staffs -> - OssLicenseScreenUiState() + buildUiState(ossLicenseStateFlow) { licenses -> + OssLicenseScreenUiState(licenseList = licenses.toMutableList()) } fun loadLicenseList() { - // TODO implement load logic + ossLicenseRepository.refresh() } } From e4e55ffb0b2462acd5330f3c9dbb8fec9be48933 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 15:34:28 +0900 Subject: [PATCH 10/41] Add Scaffold for OSS licenses screen --- .../confsched2023/license/OssLicenseScreen.kt | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt index 38641f552..4a6139efb 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt @@ -1,13 +1,23 @@ package io.github.droidkaigi.confsched2023.license +import androidx.compose.foundation.layout.Box +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.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder @@ -28,8 +38,10 @@ data class OssLicenseScreenUiState( val licenseList: MutableList = mutableListOf(), ) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun OssLicenseScreen( + modifier: Modifier = Modifier, viewModel: OssLicenseViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsState() @@ -38,10 +50,31 @@ fun OssLicenseScreen( viewModel.loadLicenseList() } - OssLicenseScreen( - uiState = uiState, - onLibraryClick = {}, - ) + Scaffold( + modifier = Modifier, + topBar = { + TopAppBar( + title = { + Text(text = "OSS ライセンス") + }, + navigationIcon = { + IconButton(onClick = { /*TODO*/ }) { + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = "back button" + ) + } + } + ) + } + ) { paddingValues -> + Box(modifier = Modifier.padding(paddingValues)) { + OssLicenseScreen( + uiState = uiState, + onLibraryClick = {}, + ) + } + } } @Composable From 71db5156ac49fbc09c3586579cf8b2b69f839dbc Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 16:24:27 +0900 Subject: [PATCH 11/41] Add UI implementation --- .../confsched2023/license/License.kt | 20 +++++++ .../confsched2023/license/OssLicense.kt | 7 --- .../license/OssLicenseRepository.kt | 16 +++--- .../confsched2023/license/OssLicenseScreen.kt | 52 ++++++++++++++++--- .../license/OssLicenseViewModel.kt | 41 +++++++++++++-- 5 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt delete mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt new file mode 100644 index 000000000..1d00483f8 --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt @@ -0,0 +1,20 @@ +package io.github.droidkaigi.confsched2023.license + +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf + +data class License( + val name: String, + val ossSet: Int, + val length: Int, +) + +data class OssLicenseGroup( + val title: String, + val licenses:List, + val expand:Boolean = false, +) + +data class OssLicense( + val groupList:PersistentList = persistentListOf() +) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt deleted file mode 100644 index c6818e4a6..000000000 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicense.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.droidkaigi.confsched2023.license - -data class OssLicense( - val name: String, - val ossSet: Int, - val length: Int, -) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt index 2682c2caa..af530ffaf 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt @@ -13,7 +13,7 @@ import okio.source import javax.inject.Inject public interface OssLicenseRepository { - public fun sponsors(): Flow> + public fun sponsors(): Flow> public fun refresh(): Unit } @@ -22,16 +22,16 @@ internal class OssLicenseRepositoryImpl @Inject constructor( private val context: Context, ) : OssLicenseRepository { - private val ossLicenseStateFlow = - MutableStateFlow>(persistentListOf()) + private val licenseStateFlow = + MutableStateFlow>(persistentListOf()) - override fun sponsors(): Flow> { + override fun sponsors(): Flow> { refresh() - return ossLicenseStateFlow + return licenseStateFlow } override fun refresh() { - ossLicenseStateFlow.value = readLicensesMetaFile() + licenseStateFlow.value = readLicensesMetaFile() .toRowList() .parseToLibraryItem() .toPersistentList() @@ -43,11 +43,11 @@ internal class OssLicenseRepositoryImpl @Inject constructor( .buffer() } - private fun List.parseToLibraryItem(): List { + private fun List.parseToLibraryItem(): List { return map { val (position, name) = it.split(' ', limit = 2) val (offset, length) = position.split(':').map { it.toInt() } - OssLicense(name, offset, length) + License(name, offset, length) } } diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt index 4a6139efb..367ef98b8 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt @@ -1,14 +1,21 @@ package io.github.droidkaigi.confsched2023.license +import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height 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.ArrowBack +import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -17,7 +24,12 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder @@ -35,7 +47,7 @@ fun NavController.navigateOssLicenseScreen() { } data class OssLicenseScreenUiState( - val licenseList: MutableList = mutableListOf(), + val ossLicense: OssLicense = OssLicense(), ) @OptIn(ExperimentalMaterial3Api::class) @@ -72,21 +84,49 @@ fun OssLicenseScreen( OssLicenseScreen( uiState = uiState, onLibraryClick = {}, + onLibraryGroupClick = {} ) } } } +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun OssLicenseScreen( uiState: OssLicenseScreenUiState, - onLibraryClick: (OssLicense) -> Unit, + onLibraryClick: (License) -> Unit, + onLibraryGroupClick: (OssLicenseGroup) -> Unit, ) { - LazyColumn { - items(items = uiState.licenseList) { item -> - TextButton(onClick = { onLibraryClick(item) }) { - Text(text = item.name) + LazyColumn(modifier = Modifier.padding(horizontal = 8.dp)) { + items(items = uiState.ossLicense.groupList) { group -> + var expand by remember { + mutableStateOf(false) + } + ElevatedCard(modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + onClick = { expand = !expand } + ) { + Column { + Spacer(modifier = Modifier.height(8.dp)) + Text(modifier = Modifier.padding(start = 8.dp),text = group.title, style = MaterialTheme.typography.headlineMedium) + AnimatedContent(targetState = expand, label = "") { targetState -> + if (targetState) { + Column { + group.licenses.forEach { license -> + key(license.name) { + TextButton(onClick = { onLibraryClick(license) }) { + Text(text = license.name) + } + } + } + } + } + } + Spacer(modifier = Modifier.height(8.dp)) + } } + Spacer(modifier = Modifier.height(8.dp)) } } } diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index 46c3c7c81..af8091fbd 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -6,6 +6,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import io.github.droidkaigi.confsched2023.ui.buildUiState import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn @@ -16,7 +17,7 @@ class OssLicenseViewModel @Inject constructor( private val ossLicenseRepository: OssLicenseRepository, ) : ViewModel() { - private val ossLicenseStateFlow: StateFlow> = + private val licenseStateFlow: StateFlow> = ossLicenseRepository.sponsors() .stateIn( scope = viewModelScope, @@ -25,11 +26,45 @@ class OssLicenseViewModel @Inject constructor( ) internal val uiState: StateFlow = - buildUiState(ossLicenseStateFlow) { licenses -> - OssLicenseScreenUiState(licenseList = licenses.toMutableList()) + buildUiState(licenseStateFlow) { licenses -> + val groupList = licenses.distinctBy { it.name }.groupByCategory() + .map { + OssLicenseGroup( + title = it.key, + licenses = it.value + ) + }.toPersistentList() + OssLicenseScreenUiState(ossLicense = OssLicense(groupList)) } + private fun List.groupByCategory(): Map> { + val categoryList = listOf( + "Android Support", + "Android Datastore", + "Android ", + "Compose UI", + "Compose Material3", + "Compose ", + "ktor", + "AndroidX lifecycle", + "AndroidX " + ) + val map = mutableMapOf>() + forEach {license -> + val group = categoryList.firstOrNull() { + license.name.startsWith(it) + } ?: "etc" + map[group] = map.getOrDefault(group, emptyList()).toMutableList().apply { + add(license) + } + } + return map + } + fun loadLicenseList() { ossLicenseRepository.refresh() } + + fun onLibraryGroupClick(ossLicenseGroup: OssLicenseGroup) { + } } From d2794b98e7ac8e093413a4b41aba2c63c31639e9 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 16:32:58 +0900 Subject: [PATCH 12/41] Add license detail implementation --- .../confsched2023/license/License.kt | 1 + .../license/OssLicenseRepository.kt | 29 +++++++++++++++---- .../license/OssLicenseViewModel.kt | 27 ++++++++++++----- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt index 1d00483f8..865bbf90f 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt @@ -7,6 +7,7 @@ data class License( val name: String, val ossSet: Int, val length: Int, + val detail:String = "", ) data class OssLicenseGroup( diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt index af530ffaf..4d4988a50 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt @@ -13,7 +13,9 @@ import okio.source import javax.inject.Inject public interface OssLicenseRepository { - public fun sponsors(): Flow> + public fun licenseMetaData(): Flow> + + public fun licenseDetailData(): Flow> public fun refresh(): Unit } @@ -22,19 +24,30 @@ internal class OssLicenseRepositoryImpl @Inject constructor( private val context: Context, ) : OssLicenseRepository { - private val licenseStateFlow = + private val licenseMetaStateFlow = MutableStateFlow>(persistentListOf()) - override fun sponsors(): Flow> { + private val licenseDetailStateFlow = MutableStateFlow>(emptyList()) + + override fun licenseMetaData(): Flow> { + refresh() + return licenseMetaStateFlow + } + + override fun licenseDetailData(): Flow> { refresh() - return licenseStateFlow + return licenseDetailStateFlow } + override fun refresh() { - licenseStateFlow.value = readLicensesMetaFile() + licenseMetaStateFlow.value = readLicensesMetaFile() .toRowList() .parseToLibraryItem() .toPersistentList() + + licenseDetailStateFlow.value = readLicensesFile() + .toRowList() } private fun readLicensesMetaFile(): BufferedSource { @@ -43,6 +56,12 @@ internal class OssLicenseRepositoryImpl @Inject constructor( .buffer() } + private fun readLicensesFile(): BufferedSource { + return context.resources.openRawResource(R.raw.third_party_licenses) + .source() + .buffer() + } + private fun List.parseToLibraryItem(): List { return map { val (position, name) = it.split(' ', limit = 2) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index af8091fbd..42efb8fdd 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -18,16 +18,24 @@ class OssLicenseViewModel @Inject constructor( ) : ViewModel() { private val licenseStateFlow: StateFlow> = - ossLicenseRepository.sponsors() + ossLicenseRepository.licenseMetaData() .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = persistentListOf(), ) + private val licenseDetailStateFlow: StateFlow> = + ossLicenseRepository.licenseDetailData() + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5_000), + initialValue = emptyList(), + ) + internal val uiState: StateFlow = - buildUiState(licenseStateFlow) { licenses -> - val groupList = licenses.distinctBy { it.name }.groupByCategory() + buildUiState(licenseStateFlow, licenseDetailStateFlow) { metadata, detail -> + val groupList = metadata.distinctBy { it.name }.groupByCategory(detail) .map { OssLicenseGroup( title = it.key, @@ -37,7 +45,7 @@ class OssLicenseViewModel @Inject constructor( OssLicenseScreenUiState(ossLicense = OssLicense(groupList)) } - private fun List.groupByCategory(): Map> { + private fun List.groupByCategory(detail: List): Map> { val categoryList = listOf( "Android Support", "Android Datastore", @@ -50,12 +58,17 @@ class OssLicenseViewModel @Inject constructor( "AndroidX " ) val map = mutableMapOf>() - forEach {license -> + forEach { license -> val group = categoryList.firstOrNull() { - license.name.startsWith(it) + license.name.startsWith(it) } ?: "etc" map[group] = map.getOrDefault(group, emptyList()).toMutableList().apply { - add(license) + add(license.copy( + detail = detail.subList(license.ossSet, license.length + license.ossSet) + .fold("") { i, i2 -> + i + i2 + } + )) } } return map From 54e83029b5ff3fd640e946883d71122ccd52cb56 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sun, 3 Sep 2023 16:37:13 +0900 Subject: [PATCH 13/41] Fix code format --- .../confsched2023/license/License.kt | 8 +++--- .../license/OssLicenseRepository.kt | 1 - .../confsched2023/license/OssLicenseScreen.kt | 25 +++++++++---------- .../license/OssLicenseViewModel.kt | 23 ++++++++--------- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt index 865bbf90f..d179aceb9 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt @@ -7,15 +7,15 @@ data class License( val name: String, val ossSet: Int, val length: Int, - val detail:String = "", + val detail: String = "", ) data class OssLicenseGroup( val title: String, - val licenses:List, - val expand:Boolean = false, + val licenses: List, + val expand: Boolean = false, ) data class OssLicense( - val groupList:PersistentList = persistentListOf() + val groupList: PersistentList = persistentListOf(), ) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt index 4d4988a50..43b91e5ab 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt @@ -39,7 +39,6 @@ internal class OssLicenseRepositoryImpl @Inject constructor( return licenseDetailStateFlow } - override fun refresh() { licenseMetaStateFlow.value = readLicensesMetaFile() .toRowList() diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt index 367ef98b8..e39820ab2 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt @@ -1,5 +1,6 @@ package io.github.droidkaigi.confsched2023.license +import android.annotation.SuppressLint import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -50,10 +51,10 @@ data class OssLicenseScreenUiState( val ossLicense: OssLicense = OssLicense(), ) +@SuppressLint("ComposeModifierMissing") @OptIn(ExperimentalMaterial3Api::class) @Composable fun OssLicenseScreen( - modifier: Modifier = Modifier, viewModel: OssLicenseViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsState() @@ -73,19 +74,17 @@ fun OssLicenseScreen( IconButton(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Default.ArrowBack, - contentDescription = "back button" + contentDescription = "back button", ) } - } + }, ) - } + }, ) { paddingValues -> Box(modifier = Modifier.padding(paddingValues)) { OssLicenseScreen( uiState = uiState, - onLibraryClick = {}, - onLibraryGroupClick = {} - ) + ) {} } } } @@ -95,21 +94,21 @@ fun OssLicenseScreen( private fun OssLicenseScreen( uiState: OssLicenseScreenUiState, onLibraryClick: (License) -> Unit, - onLibraryGroupClick: (OssLicenseGroup) -> Unit, ) { LazyColumn(modifier = Modifier.padding(horizontal = 8.dp)) { items(items = uiState.ossLicense.groupList) { group -> var expand by remember { mutableStateOf(false) } - ElevatedCard(modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - onClick = { expand = !expand } + ElevatedCard( + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + onClick = { expand = !expand }, ) { Column { Spacer(modifier = Modifier.height(8.dp)) - Text(modifier = Modifier.padding(start = 8.dp),text = group.title, style = MaterialTheme.typography.headlineMedium) + Text(modifier = Modifier.padding(start = 8.dp), text = group.title, style = MaterialTheme.typography.headlineMedium) AnimatedContent(targetState = expand, label = "") { targetState -> if (targetState) { Column { diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index 42efb8fdd..b334f1fda 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -39,7 +39,7 @@ class OssLicenseViewModel @Inject constructor( .map { OssLicenseGroup( title = it.key, - licenses = it.value + licenses = it.value, ) }.toPersistentList() OssLicenseScreenUiState(ossLicense = OssLicense(groupList)) @@ -55,20 +55,22 @@ class OssLicenseViewModel @Inject constructor( "Compose ", "ktor", "AndroidX lifecycle", - "AndroidX " + "AndroidX ", ) val map = mutableMapOf>() forEach { license -> - val group = categoryList.firstOrNull() { + val group = categoryList.firstOrNull { license.name.startsWith(it) } ?: "etc" map[group] = map.getOrDefault(group, emptyList()).toMutableList().apply { - add(license.copy( - detail = detail.subList(license.ossSet, license.length + license.ossSet) - .fold("") { i, i2 -> - i + i2 - } - )) + add( + license.copy( + detail = detail.subList(license.ossSet, license.length + license.ossSet) + .fold("") { i, i2 -> + i + i2 + }, + ), + ) } } return map @@ -77,7 +79,4 @@ class OssLicenseViewModel @Inject constructor( fun loadLicenseList() { ossLicenseRepository.refresh() } - - fun onLibraryGroupClick(ossLicenseGroup: OssLicenseGroup) { - } } From 8cea72a0b94e2b4ff53a70388a348b83179a87cc Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Tue, 12 Sep 2023 21:39:49 +0900 Subject: [PATCH 14/41] Add OssLicense screen --- .../droidkaigi/confsched2023/KaigiApp.kt | 18 +++++++++-- .../confsched2023/license/License.kt | 2 +- .../confsched2023/license/OssLicenseScreen.kt | 29 +++++++++++------ .../license/OssLicenseViewModel.kt | 32 ++++--------------- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt index 0389239b6..acbe68d96 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt @@ -39,8 +39,10 @@ import io.github.droidkaigi.confsched2023.designsystem.theme.KaigiTheme import io.github.droidkaigi.confsched2023.floormap.floorMapScreenRoute import io.github.droidkaigi.confsched2023.floormap.navigateFloorMapScreen import io.github.droidkaigi.confsched2023.floormap.nestedFloorMapScreen +import io.github.droidkaigi.confsched2023.license.navigateOssLicenseDetailScreen import io.github.droidkaigi.confsched2023.license.navigateOssLicenseScreen -import io.github.droidkaigi.confsched2023.license.ossLicenseScreen +import io.github.droidkaigi.confsched2023.license.nestedOssLicenseDetailScreen +import io.github.droidkaigi.confsched2023.license.nestedOssLicenseScreen import io.github.droidkaigi.confsched2023.main.MainNestedGraphStateHolder import io.github.droidkaigi.confsched2023.main.MainScreenTab import io.github.droidkaigi.confsched2023.main.MainScreenTab.About @@ -129,7 +131,19 @@ private fun KaigiNavHost( onBackClick = navController::popBackStack, onStaffClick = externalNavController::navigate, ) - ossLicenseScreen() + nestedOssLicenseScreen( + onLicenseClick = { license -> + navController.navigateOssLicenseDetailScreen(license) + }, + onUpClick = { + navController.navigateUp() + }, + ) + nestedOssLicenseDetailScreen( + onUpClick = { + navController.navigateUp() + }, + ) } } diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt index d179aceb9..29fdf7ec1 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt @@ -5,7 +5,7 @@ import kotlinx.collections.immutable.persistentListOf data class License( val name: String, - val ossSet: Int, + val offset: Int, val length: Int, val detail: String = "", ) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt index e39820ab2..227b0cac5 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt @@ -1,6 +1,5 @@ package io.github.droidkaigi.confsched2023.license -import android.annotation.SuppressLint import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -37,9 +36,12 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable const val ossLicenseScreenRoute = "osslicense" -fun NavGraphBuilder.ossLicenseScreen() { +fun NavGraphBuilder.nestedOssLicenseScreen( + onLicenseClick: (License) -> Unit, + onUpClick: () -> Unit, +) { composable(ossLicenseScreenRoute) { - OssLicenseScreen() + OssLicenseScreen(onLicenseClick = onLicenseClick, onUpClick = onUpClick) } } @@ -51,10 +53,12 @@ data class OssLicenseScreenUiState( val ossLicense: OssLicense = OssLicense(), ) -@SuppressLint("ComposeModifierMissing") @OptIn(ExperimentalMaterial3Api::class) @Composable fun OssLicenseScreen( + onLicenseClick: (License) -> Unit, + onUpClick: () -> Unit, + modifier: Modifier = Modifier, viewModel: OssLicenseViewModel = hiltViewModel(), ) { val uiState by viewModel.uiState.collectAsState() @@ -64,14 +68,14 @@ fun OssLicenseScreen( } Scaffold( - modifier = Modifier, + modifier = modifier, topBar = { TopAppBar( title = { Text(text = "OSS ライセンス") }, navigationIcon = { - IconButton(onClick = { /*TODO*/ }) { + IconButton(onClick = { onUpClick() }) { Icon( imageVector = Icons.Default.ArrowBack, contentDescription = "back button", @@ -84,7 +88,8 @@ fun OssLicenseScreen( Box(modifier = Modifier.padding(paddingValues)) { OssLicenseScreen( uiState = uiState, - ) {} + onLicenseClick = onLicenseClick, + ) } } } @@ -93,7 +98,7 @@ fun OssLicenseScreen( @Composable private fun OssLicenseScreen( uiState: OssLicenseScreenUiState, - onLibraryClick: (License) -> Unit, + onLicenseClick: (License) -> Unit, ) { LazyColumn(modifier = Modifier.padding(horizontal = 8.dp)) { items(items = uiState.ossLicense.groupList) { group -> @@ -108,13 +113,17 @@ private fun OssLicenseScreen( ) { Column { Spacer(modifier = Modifier.height(8.dp)) - Text(modifier = Modifier.padding(start = 8.dp), text = group.title, style = MaterialTheme.typography.headlineMedium) + Text( + modifier = Modifier.padding(start = 8.dp), + text = group.title, + style = MaterialTheme.typography.headlineMedium, + ) AnimatedContent(targetState = expand, label = "") { targetState -> if (targetState) { Column { group.licenses.forEach { license -> key(license.name) { - TextButton(onClick = { onLibraryClick(license) }) { + TextButton(onClick = { onLicenseClick(license) }) { Text(text = license.name) } } diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index b334f1fda..c4de8936a 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -25,17 +25,9 @@ class OssLicenseViewModel @Inject constructor( initialValue = persistentListOf(), ) - private val licenseDetailStateFlow: StateFlow> = - ossLicenseRepository.licenseDetailData() - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5_000), - initialValue = emptyList(), - ) - internal val uiState: StateFlow = - buildUiState(licenseStateFlow, licenseDetailStateFlow) { metadata, detail -> - val groupList = metadata.distinctBy { it.name }.groupByCategory(detail) + buildUiState(licenseStateFlow) { metadata -> + val groupList = metadata.distinctBy { it.name }.groupByCategory() .map { OssLicenseGroup( title = it.key, @@ -45,7 +37,7 @@ class OssLicenseViewModel @Inject constructor( OssLicenseScreenUiState(ossLicense = OssLicense(groupList)) } - private fun List.groupByCategory(detail: List): Map> { + private fun List.groupByCategory(): Map> { val categoryList = listOf( "Android Support", "Android Datastore", @@ -53,27 +45,17 @@ class OssLicenseViewModel @Inject constructor( "Compose UI", "Compose Material3", "Compose ", + "kotlinx", + "Kotlin", "ktor", "AndroidX lifecycle", "AndroidX ", ) - val map = mutableMapOf>() - forEach { license -> - val group = categoryList.firstOrNull { + return groupBy { license -> + categoryList.firstOrNull { license.name.startsWith(it) } ?: "etc" - map[group] = map.getOrDefault(group, emptyList()).toMutableList().apply { - add( - license.copy( - detail = detail.subList(license.ossSet, license.length + license.ossSet) - .fold("") { i, i2 -> - i + i2 - }, - ), - ) - } } - return map } fun loadLicenseList() { From 0294a8891f8876acefdf14136c9d43e7ed36e5eb Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Tue, 12 Sep 2023 21:39:59 +0900 Subject: [PATCH 15/41] Add OssDetailLicense screen --- .../license/OssLicenseDetailScreen.kt | 90 +++++++++++++++++++ .../license/OssLicenseDetailViewModel.kt | 59 ++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt new file mode 100644 index 000000000..c23781d3b --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt @@ -0,0 +1,90 @@ +package io.github.droidkaigi.confsched2023.license + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable + +const val ossLicenseDetailScreenRouteNameArgument = "name" +const val ossLicenseDetailScreenRoute = "osslicense" +fun NavGraphBuilder.nestedOssLicenseDetailScreen(onUpClick: () -> Unit) { + composable("$ossLicenseDetailScreenRoute/{$ossLicenseDetailScreenRouteNameArgument}") { + OssLicenseDetailScreen( + onUpClick = onUpClick, + ) + } +} + +fun NavController.navigateOssLicenseDetailScreen( + license: License, +) { + val licenseName = license.name.replace(' ', '-') + navigate("$ossLicenseDetailScreenRoute/$licenseName") +} + +data class OssLicenseDetailScreenUiState( + val ossLicense: License? = null, +) + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OssLicenseDetailScreen( + modifier: Modifier = Modifier, + viewModel: OssLicenseDetailViewModel = hiltViewModel(), + onUpClick: () -> Unit, +) { + val uiState by viewModel.uiState.collectAsState() + + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = { + Text(text = "OSS ライセンス") + }, + navigationIcon = { + IconButton(onClick = { onUpClick() }) { + Icon( + imageVector = Icons.Default.ArrowBack, + contentDescription = "back button", + ) + } + }, + ) + }, + ) { paddingValues -> + Box(modifier = Modifier.padding(paddingValues)) { + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(horizontal = 8.dp), + ) { + uiState.ossLicense?.run { + Text( + text = this.detail, + style = MaterialTheme.typography.bodyMedium, + ) + } + } + } + } +} diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt new file mode 100644 index 000000000..dd04a58e8 --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt @@ -0,0 +1,59 @@ +package io.github.droidkaigi.confsched2023.license + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.droidkaigi.confsched2023.ui.buildUiState +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.stateIn +import javax.inject.Inject + +@HiltViewModel +class OssLicenseDetailViewModel @Inject constructor( + private val ossLicenseRepository: OssLicenseRepository, + savedStateHandle: SavedStateHandle, +) : ViewModel() { + + private val licenseName = savedStateHandle.getStateFlow( + ossLicenseDetailScreenRouteNameArgument, + "", + ) + + private val licenseStateFlow: StateFlow> = + ossLicenseRepository.licenseMetaData() + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5_000), + initialValue = persistentListOf(), + ) + + private val licenseDetailStateFlow: StateFlow> = + ossLicenseRepository.licenseDetailData() + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5_000), + initialValue = emptyList(), + ) + + internal val uiState: StateFlow = + buildUiState(licenseStateFlow, licenseDetailStateFlow) { metadata, detail -> + val license = metadata.firstOrNull { it.name.replace(' ', '-') == licenseName.value } + ?.let { license -> + val detail = kotlin.runCatching { + val start = license.offset + val end = license.offset + license.length + detail.subList( + fromIndex = start, + toIndex = end, + ).joinToString("\n") + }.getOrElse { "" } + license.copy(detail = detail) + } + + OssLicenseDetailScreenUiState(license) + } +} From dc641f34bd23ecc1fb5c1f2bf2e974834be18875 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Tue, 12 Sep 2023 22:45:13 +0900 Subject: [PATCH 16/41] Move License to core/model module --- .../droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt | 1 + .../confsched2023/license/OssLicenseDetailViewModel.kt | 1 + .../droidkaigi/confsched2023/license/OssLicenseRepository.kt | 1 + .../droidkaigi/confsched2023/license/OssLicenseScreen.kt | 2 ++ .../droidkaigi/confsched2023/license/OssLicenseViewModel.kt | 3 +++ .../io/github/droidkaigi/confsched2023/model}/License.kt | 2 +- 6 files changed, 9 insertions(+), 1 deletion(-) rename {app-android/src/main/java/io/github/droidkaigi/confsched2023/license => core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model}/License.kt (89%) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt index c23781d3b..481ee5bf9 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt @@ -23,6 +23,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import io.github.droidkaigi.confsched2023.model.License const val ossLicenseDetailScreenRouteNameArgument = "name" const val ossLicenseDetailScreenRoute = "osslicense" diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt index dd04a58e8..95a9f989e 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.droidkaigi.confsched2023.model.License import io.github.droidkaigi.confsched2023.ui.buildUiState import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt index 43b91e5ab..8035b2450 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt @@ -2,6 +2,7 @@ package io.github.droidkaigi.confsched2023.license import android.content.Context import io.github.droidkaigi.confsched2023.R +import io.github.droidkaigi.confsched2023.model.License import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt index 227b0cac5..80ca0f3a3 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt @@ -34,6 +34,8 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicense const val ossLicenseScreenRoute = "osslicense" fun NavGraphBuilder.nestedOssLicenseScreen( diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt index c4de8936a..97b98e5ed 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt @@ -3,6 +3,9 @@ package io.github.droidkaigi.confsched2023.license import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicense +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import io.github.droidkaigi.confsched2023.ui.buildUiState import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt similarity index 89% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt rename to core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt index 29fdf7ec1..969595f94 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/License.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt @@ -1,4 +1,4 @@ -package io.github.droidkaigi.confsched2023.license +package io.github.droidkaigi.confsched2023.model import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf From c18fb1df6d812b1ddc84d199b76bb9c4ad2486ff Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Tue, 12 Sep 2023 23:03:37 +0900 Subject: [PATCH 17/41] Oss screen move to feature / about --- .../github/droidkaigi/confsched2023/KaigiApp.kt | 8 ++++---- ...epository.kt => OssLicenseRepositoryImpl.kt} | 17 +++++------------ .../license/OssLicenseRepositoryModule.kt | 1 + .../confsched2023/model/OssLicenseRepository.kt | 14 ++++++++++++++ .../about}/OssLicenseDetailScreen.kt | 2 +- .../about}/OssLicenseDetailViewModel.kt | 3 ++- .../confsched2023/about}/OssLicenseScreen.kt | 2 +- .../confsched2023/about}/OssLicenseViewModel.kt | 3 ++- 8 files changed, 30 insertions(+), 20 deletions(-) rename app-android/src/main/java/io/github/droidkaigi/confsched2023/license/{OssLicenseRepository.kt => OssLicenseRepositoryImpl.kt} (81%) create mode 100644 core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt rename {app-android/src/main/java/io/github/droidkaigi/confsched2023/license => feature/about/src/main/java/io/github/droidkaigi/confsched2023/about}/OssLicenseDetailScreen.kt (98%) rename {app-android/src/main/java/io/github/droidkaigi/confsched2023/license => feature/about/src/main/java/io/github/droidkaigi/confsched2023/about}/OssLicenseDetailViewModel.kt (95%) rename {app-android/src/main/java/io/github/droidkaigi/confsched2023/license => feature/about/src/main/java/io/github/droidkaigi/confsched2023/about}/OssLicenseScreen.kt (98%) rename {app-android/src/main/java/io/github/droidkaigi/confsched2023/license => feature/about/src/main/java/io/github/droidkaigi/confsched2023/about}/OssLicenseViewModel.kt (95%) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt index 95f5412c3..0299f4e79 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt @@ -31,7 +31,11 @@ import co.touchlab.kermit.Logger import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import io.github.droidkaigi.confsched2023.about.aboutScreenRoute import io.github.droidkaigi.confsched2023.about.navigateAboutScreen +import io.github.droidkaigi.confsched2023.about.navigateOssLicenseDetailScreen +import io.github.droidkaigi.confsched2023.about.navigateOssLicenseScreen import io.github.droidkaigi.confsched2023.about.nestedAboutScreen +import io.github.droidkaigi.confsched2023.about.nestedOssLicenseDetailScreen +import io.github.droidkaigi.confsched2023.about.nestedOssLicenseScreen import io.github.droidkaigi.confsched2023.achievements.achievementsScreenRoute import io.github.droidkaigi.confsched2023.achievements.navigateAchievementsScreen import io.github.droidkaigi.confsched2023.achievements.nestedAchievementsScreen @@ -41,10 +45,6 @@ import io.github.droidkaigi.confsched2023.designsystem.theme.KaigiTheme import io.github.droidkaigi.confsched2023.floormap.floorMapScreenRoute import io.github.droidkaigi.confsched2023.floormap.navigateFloorMapScreen import io.github.droidkaigi.confsched2023.floormap.nestedFloorMapScreen -import io.github.droidkaigi.confsched2023.license.navigateOssLicenseDetailScreen -import io.github.droidkaigi.confsched2023.license.navigateOssLicenseScreen -import io.github.droidkaigi.confsched2023.license.nestedOssLicenseDetailScreen -import io.github.droidkaigi.confsched2023.license.nestedOssLicenseScreen import io.github.droidkaigi.confsched2023.main.MainNestedGraphStateHolder import io.github.droidkaigi.confsched2023.main.MainScreenTab import io.github.droidkaigi.confsched2023.main.MainScreenTab.About diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt similarity index 81% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt rename to app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt index 8035b2450..a0c8aa9e5 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepository.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt @@ -1,8 +1,9 @@ package io.github.droidkaigi.confsched2023.license import android.content.Context -import io.github.droidkaigi.confsched2023.R +import io.github.droidkaigi.confsched2023.R.raw import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList @@ -13,15 +14,7 @@ import okio.buffer import okio.source import javax.inject.Inject -public interface OssLicenseRepository { - public fun licenseMetaData(): Flow> - - public fun licenseDetailData(): Flow> - - public fun refresh(): Unit -} - -internal class OssLicenseRepositoryImpl @Inject constructor( +class OssLicenseRepositoryImpl @Inject constructor( private val context: Context, ) : OssLicenseRepository { @@ -51,13 +44,13 @@ internal class OssLicenseRepositoryImpl @Inject constructor( } private fun readLicensesMetaFile(): BufferedSource { - return context.resources.openRawResource(R.raw.third_party_license_metadata) + return context.resources.openRawResource(raw.third_party_license_metadata) .source() .buffer() } private fun readLicensesFile(): BufferedSource { - return context.resources.openRawResource(R.raw.third_party_licenses) + return context.resources.openRawResource(raw.third_party_licenses) .source() .buffer() } diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt index 44502ee38..893096ca7 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt @@ -6,6 +6,7 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import javax.inject.Singleton @Module diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt new file mode 100644 index 000000000..8be766241 --- /dev/null +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt @@ -0,0 +1,14 @@ +package io.github.droidkaigi.confsched2023.model + +import io.github.droidkaigi.confsched2023.model.License +import kotlinx.collections.immutable.PersistentList +import kotlinx.coroutines.flow.Flow + +public interface OssLicenseRepository { + public fun licenseMetaData(): Flow> + + public fun licenseDetailData(): Flow> + + public fun refresh(): Unit +} + diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt similarity index 98% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt rename to feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt index 481ee5bf9..3c16e9e40 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt @@ -1,4 +1,4 @@ -package io.github.droidkaigi.confsched2023.license +package io.github.droidkaigi.confsched2023.about import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt similarity index 95% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt rename to feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt index 95a9f989e..f82f143b0 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseDetailViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt @@ -1,10 +1,11 @@ -package io.github.droidkaigi.confsched2023.license +package io.github.droidkaigi.confsched2023.about import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.buildUiState import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt similarity index 98% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt rename to feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt index 80ca0f3a3..9fc996efc 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt @@ -1,4 +1,4 @@ -package io.github.droidkaigi.confsched2023.license +package io.github.droidkaigi.confsched2023.about import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.layout.Box diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt similarity index 95% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt rename to feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index 97b98e5ed..a92c688ec 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -1,4 +1,4 @@ -package io.github.droidkaigi.confsched2023.license +package io.github.droidkaigi.confsched2023.about import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -6,6 +6,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import io.github.droidkaigi.confsched2023.model.License import io.github.droidkaigi.confsched2023.model.OssLicense import io.github.droidkaigi.confsched2023.model.OssLicenseGroup +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.buildUiState import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf From 1ae517488f8909840b539746d9c0cd46f3304239 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Tue, 12 Sep 2023 23:03:58 +0900 Subject: [PATCH 18/41] Fix code format --- .../droidkaigi/confsched2023/model/OssLicenseRepository.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt index 8be766241..9d853e21b 100644 --- a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt @@ -1,6 +1,5 @@ package io.github.droidkaigi.confsched2023.model -import io.github.droidkaigi.confsched2023.model.License import kotlinx.collections.immutable.PersistentList import kotlinx.coroutines.flow.Flow @@ -11,4 +10,3 @@ public interface OssLicenseRepository { public fun refresh(): Unit } - From 753f9a7d8b0722e4738b42fc6308a043e2b10b30 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 11:54:55 +0900 Subject: [PATCH 19/41] Update DI config with using the optional binding --- .../droidkaigi/confsched2023/AppModule.kt | 12 ++++++ .../license/OssLicenseRepositoryModule.kt | 31 ++++++--------- .../data/di/BuildConfigProviderModule.kt | 39 +++++++++++++++++++ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt index 4cef11e65..8edadb4cc 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt @@ -1,11 +1,16 @@ package io.github.droidkaigi.confsched2023 +import android.content.Context import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import io.github.droidkaigi.confsched2023.data.di.AppAndroidBuildConfig +import io.github.droidkaigi.confsched2023.data.di.AppAndroidOssLicenseConfig +import io.github.droidkaigi.confsched2023.license.OssLicenseRepositoryImpl import io.github.droidkaigi.confsched2023.model.BuildConfigProvider +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import javax.inject.Singleton @InstallIn(SingletonComponent::class) @@ -15,6 +20,13 @@ class AppModule { @Singleton @AppAndroidBuildConfig fun provideBuildConfigProvider(): BuildConfigProvider = AppBuildConfigProvider() + + @Provides + @Singleton + @AppAndroidOssLicenseConfig + fun provideOssLicenseRepositoryProvider( + @ApplicationContext context: Context, + ): OssLicenseRepository = OssLicenseRepositoryImpl(context) } class AppBuildConfigProvider( diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt index 893096ca7..b726eb9b0 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt @@ -1,22 +1,13 @@ package io.github.droidkaigi.confsched2023.license -import android.content.Context -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import io.github.droidkaigi.confsched2023.model.OssLicenseRepository -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -class OssLicenseRepositoryModule { - @Provides - @Singleton - fun provideSponsorsRepository( - @ApplicationContext context: Context, - ): OssLicenseRepository { - return OssLicenseRepositoryImpl(context = context) - } -} +// @Module +// @InstallIn(SingletonComponent::class) +// class OssLicenseRepositoryModule { +// @Provides +// @Singleton +// fun provideSponsorsRepository( +// @ApplicationContext context: Context, +// ): OssLicenseRepository { +// return OssLicenseRepositoryImpl(context = context) +// } +// } diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index e2e243734..0f0745750 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -6,6 +6,10 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import io.github.droidkaigi.confsched2023.model.BuildConfigProvider +import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository +import kotlinx.collections.immutable.PersistentList +import kotlinx.coroutines.flow.Flow import java.util.Optional import javax.inject.Qualifier import javax.inject.Singleton @@ -13,6 +17,9 @@ import javax.inject.Singleton @Qualifier annotation class AppAndroidBuildConfig +@Qualifier +annotation class AppAndroidOssLicenseConfig + @Module @InstallIn(SingletonComponent::class) class BuildConfigProviderModule { @@ -25,6 +32,16 @@ class BuildConfigProviderModule { } else { EmptyBuildConfigProvider } + + @Provides + @Singleton + fun provideOssLicenseRepositoryProvider( + @AppAndroidOssLicenseConfig ossLicenseRepository: Optional, + ): OssLicenseRepository = if (ossLicenseRepository.isPresent) { + ossLicenseRepository.get() + } else { + EmptyOssLicenseRepository + } } @InstallIn(SingletonComponent::class) @@ -35,6 +52,28 @@ abstract class AppAndroidBuildConfigModule { abstract fun bindBuildConfigProvider(): BuildConfigProvider } +@InstallIn(SingletonComponent::class) +@Module +abstract class AppAndroidOssLicenseModule { + @BindsOptionalOf + @AppAndroidOssLicenseConfig + abstract fun bindOssLicenseProvider(): OssLicenseRepository +} + private object EmptyBuildConfigProvider : BuildConfigProvider { override val versionName: String = "" } + +private object EmptyOssLicenseRepository : OssLicenseRepository { + override fun licenseMetaData(): Flow> { + TODO("Not yet implemented") + } + + override fun licenseDetailData(): Flow> { + TODO("Not yet implemented") + } + + override fun refresh() { + TODO("Not yet implemented") + } +} From c605ed344e7fec98cb8b35c1cfbd660f7a22f0a6 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 11:59:38 +0900 Subject: [PATCH 20/41] Delete unnecessary Dagger module --- .../license/OssLicenseRepositoryModule.kt | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt deleted file mode 100644 index b726eb9b0..000000000 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryModule.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.droidkaigi.confsched2023.license - -// @Module -// @InstallIn(SingletonComponent::class) -// class OssLicenseRepositoryModule { -// @Provides -// @Singleton -// fun provideSponsorsRepository( -// @ApplicationContext context: Context, -// ): OssLicenseRepository { -// return OssLicenseRepositoryImpl(context = context) -// } -// } From 35316a8652d7febdea2535ebacba1ce9d01b8168 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:18:31 +0900 Subject: [PATCH 21/41] Rename unintentional method name for the navigation --- .../java/io/github/droidkaigi/confsched2023/KaigiApp.kt | 8 ++++---- .../confsched2023/about/OssLicenseDetailScreen.kt | 2 +- .../droidkaigi/confsched2023/about/OssLicenseScreen.kt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt index 0299f4e79..75282bbc2 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/KaigiApp.kt @@ -34,8 +34,8 @@ import io.github.droidkaigi.confsched2023.about.navigateAboutScreen import io.github.droidkaigi.confsched2023.about.navigateOssLicenseDetailScreen import io.github.droidkaigi.confsched2023.about.navigateOssLicenseScreen import io.github.droidkaigi.confsched2023.about.nestedAboutScreen -import io.github.droidkaigi.confsched2023.about.nestedOssLicenseDetailScreen -import io.github.droidkaigi.confsched2023.about.nestedOssLicenseScreen +import io.github.droidkaigi.confsched2023.about.ossLicenseDetailScreen +import io.github.droidkaigi.confsched2023.about.ossLicenseScreen import io.github.droidkaigi.confsched2023.achievements.achievementsScreenRoute import io.github.droidkaigi.confsched2023.achievements.navigateAchievementsScreen import io.github.droidkaigi.confsched2023.achievements.nestedAchievementsScreen @@ -129,7 +129,7 @@ private fun KaigiNavHost( onBackClick = navController::popBackStack, onStaffClick = externalNavController::navigate, ) - nestedOssLicenseScreen( + ossLicenseScreen( onLicenseClick = { license -> navController.navigateOssLicenseDetailScreen(license) }, @@ -137,7 +137,7 @@ private fun KaigiNavHost( navController.navigateUp() }, ) - nestedOssLicenseDetailScreen( + ossLicenseDetailScreen( onUpClick = { navController.navigateUp() }, diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt index 3c16e9e40..6ed628124 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt @@ -27,7 +27,7 @@ import io.github.droidkaigi.confsched2023.model.License const val ossLicenseDetailScreenRouteNameArgument = "name" const val ossLicenseDetailScreenRoute = "osslicense" -fun NavGraphBuilder.nestedOssLicenseDetailScreen(onUpClick: () -> Unit) { +fun NavGraphBuilder.ossLicenseDetailScreen(onUpClick: () -> Unit) { composable("$ossLicenseDetailScreenRoute/{$ossLicenseDetailScreenRouteNameArgument}") { OssLicenseDetailScreen( onUpClick = onUpClick, diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt index 9fc996efc..3fabd3fa6 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt @@ -38,7 +38,7 @@ import io.github.droidkaigi.confsched2023.model.License import io.github.droidkaigi.confsched2023.model.OssLicense const val ossLicenseScreenRoute = "osslicense" -fun NavGraphBuilder.nestedOssLicenseScreen( +fun NavGraphBuilder.ossLicenseScreen( onLicenseClick: (License) -> Unit, onUpClick: () -> Unit, ) { From c7a3413dc5d07ecc61f03ede90ac823edfcbdff2 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:23:45 +0900 Subject: [PATCH 22/41] Remove un-necessary method --- .../license/OssLicenseRepositoryImpl.kt | 14 ++++---------- .../data/di/BuildConfigProviderModule.kt | 4 ---- .../confsched2023/model/OssLicenseRepository.kt | 2 -- .../confsched2023/about/OssLicenseScreen.kt | 5 ----- .../confsched2023/about/OssLicenseViewModel.kt | 4 ---- 5 files changed, 4 insertions(+), 25 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt index a0c8aa9e5..64d60db48 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt @@ -24,23 +24,17 @@ class OssLicenseRepositoryImpl @Inject constructor( private val licenseDetailStateFlow = MutableStateFlow>(emptyList()) override fun licenseMetaData(): Flow> { - refresh() - return licenseMetaStateFlow - } - - override fun licenseDetailData(): Flow> { - refresh() - return licenseDetailStateFlow - } - - override fun refresh() { licenseMetaStateFlow.value = readLicensesMetaFile() .toRowList() .parseToLibraryItem() .toPersistentList() + return licenseMetaStateFlow + } + override fun licenseDetailData(): Flow> { licenseDetailStateFlow.value = readLicensesFile() .toRowList() + return licenseDetailStateFlow } private fun readLicensesMetaFile(): BufferedSource { diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index 0f0745750..a47b32150 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -72,8 +72,4 @@ private object EmptyOssLicenseRepository : OssLicenseRepository { override fun licenseDetailData(): Flow> { TODO("Not yet implemented") } - - override fun refresh() { - TODO("Not yet implemented") - } } diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt index 9d853e21b..054c64b0b 100644 --- a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt @@ -7,6 +7,4 @@ public interface OssLicenseRepository { public fun licenseMetaData(): Flow> public fun licenseDetailData(): Flow> - - public fun refresh(): Unit } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt index 3fabd3fa6..d77c34dee 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.key @@ -65,10 +64,6 @@ fun OssLicenseScreen( ) { val uiState by viewModel.uiState.collectAsState() - LaunchedEffect(Unit) { - viewModel.loadLicenseList() - } - Scaffold( modifier = modifier, topBar = { diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index a92c688ec..81f862f77 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -61,8 +61,4 @@ class OssLicenseViewModel @Inject constructor( } ?: "etc" } } - - fun loadLicenseList() { - ossLicenseRepository.refresh() - } } From be4982d7a0306d24d38706ad5b127d03953b415f Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:28:06 +0900 Subject: [PATCH 23/41] Cleanup fake class --- .../data/di/BuildConfigProviderModule.kt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index a47b32150..c2e4a6725 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -9,7 +9,9 @@ import io.github.droidkaigi.confsched2023.model.BuildConfigProvider import io.github.droidkaigi.confsched2023.model.License import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf import java.util.Optional import javax.inject.Qualifier import javax.inject.Singleton @@ -65,11 +67,6 @@ private object EmptyBuildConfigProvider : BuildConfigProvider { } private object EmptyOssLicenseRepository : OssLicenseRepository { - override fun licenseMetaData(): Flow> { - TODO("Not yet implemented") - } - - override fun licenseDetailData(): Flow> { - TODO("Not yet implemented") - } + override fun licenseMetaData(): Flow> = flowOf(persistentListOf()) + override fun licenseDetailData(): Flow> = flowOf(emptyList()) } From a7c4a4c51f74798cadd093339d4086e7d8dfa10d Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:35:36 +0900 Subject: [PATCH 24/41] Cleanup duplicate logic for id of license --- .../confsched2023/license/OssLicenseRepositoryImpl.kt | 3 ++- .../kotlin/io/github/droidkaigi/confsched2023/model/License.kt | 1 + .../droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt | 3 +-- .../confsched2023/about/OssLicenseDetailViewModel.kt | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt index 64d60db48..8b6cfb450 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt @@ -53,7 +53,8 @@ class OssLicenseRepositoryImpl @Inject constructor( return map { val (position, name) = it.split(' ', limit = 2) val (offset, length) = position.split(':').map { it.toInt() } - License(name, offset, length) + val id = name.replace(' ', '-') + License(id = id, name = name, offset = offset, length = length) } } diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt index 969595f94..08130bc44 100644 --- a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt @@ -4,6 +4,7 @@ import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf data class License( + val id: String, val name: String, val offset: Int, val length: Int, diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt index 6ed628124..0b16b77d9 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt @@ -38,8 +38,7 @@ fun NavGraphBuilder.ossLicenseDetailScreen(onUpClick: () -> Unit) { fun NavController.navigateOssLicenseDetailScreen( license: License, ) { - val licenseName = license.name.replace(' ', '-') - navigate("$ossLicenseDetailScreenRoute/$licenseName") + navigate("$ossLicenseDetailScreenRoute/${license.id}") } data class OssLicenseDetailScreenUiState( diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt index f82f143b0..b50ff9cfe 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt @@ -43,7 +43,7 @@ class OssLicenseDetailViewModel @Inject constructor( internal val uiState: StateFlow = buildUiState(licenseStateFlow, licenseDetailStateFlow) { metadata, detail -> - val license = metadata.firstOrNull { it.name.replace(' ', '-') == licenseName.value } + val license = metadata.firstOrNull { it.id == licenseName.value } ?.let { license -> val detail = kotlin.runCatching { val start = license.offset From 6afe1e6389d6c10d68ef5a0212a414f9878bb356 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:42:44 +0900 Subject: [PATCH 25/41] Using multi language support feature for the screen title --- .../io/github/droidkaigi/confsched2023/about/AboutStrings.kt | 3 +++ .../github/droidkaigi/confsched2023/about/OssLicenseScreen.kt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/AboutStrings.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/AboutStrings.kt index f1e01528b..2e174bdc8 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/AboutStrings.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/AboutStrings.kt @@ -21,6 +21,7 @@ sealed class AboutStrings : Strings(Bindings) { data object OthersTitle : AboutStrings() data object CodeOfConduct : AboutStrings() data object License : AboutStrings() + data object LicenseScreenTitle : AboutStrings() data object PrivacyPolicy : AboutStrings() data object AppVersion : AboutStrings() data object LicenceDescription : AboutStrings() @@ -42,6 +43,7 @@ sealed class AboutStrings : Strings(Bindings) { OthersTitle -> "Others" CodeOfConduct -> "行動規範" License -> "ライセンス" + LicenseScreenTitle -> "ライセンス" PrivacyPolicy -> "プライバシーポリシー" AppVersion -> "アプリバージョン" LicenceDescription -> "The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License." @@ -63,6 +65,7 @@ sealed class AboutStrings : Strings(Bindings) { OthersTitle -> bindings.defaultBinding(item, bindings) CodeOfConduct -> "Code Of Conduct" License -> "License" + LicenseScreenTitle -> "License" PrivacyPolicy -> "Privacy Policy" AppVersion -> "App Version" LicenceDescription -> bindings.defaultBinding(item, bindings) diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt index d77c34dee..47937697f 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt @@ -69,7 +69,7 @@ fun OssLicenseScreen( topBar = { TopAppBar( title = { - Text(text = "OSS ライセンス") + Text(text = AboutStrings.LicenseScreenTitle.asString()) }, navigationIcon = { IconButton(onClick = { onUpClick() }) { From 1d0da32283354a0faa2848946727b1eb40ecaad9 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:49:30 +0900 Subject: [PATCH 26/41] Update library grouping logic --- .../confsched2023/about/OssLicenseViewModel.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index 81f862f77..9bc448dc6 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -49,15 +49,21 @@ class OssLicenseViewModel @Inject constructor( "Compose UI", "Compose Material3", "Compose ", - "kotlinx", - "Kotlin", - "ktor", "AndroidX lifecycle", "AndroidX ", + "Kotlin", + "Dagger", + "Firebase", + "Ktorfit", + "okhttp", + "ktor", ) return groupBy { license -> categoryList.firstOrNull { - license.name.startsWith(it) + license.name.startsWith( + prefix = it, + ignoreCase = true + ) } ?: "etc" } } From 620740403098b14e3854cd432ae871e5547cfaea Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Thu, 14 Sep 2023 15:50:15 +0900 Subject: [PATCH 27/41] Fix code format --- .../droidkaigi/confsched2023/about/OssLicenseViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index 9bc448dc6..cd1313623 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -62,7 +62,7 @@ class OssLicenseViewModel @Inject constructor( categoryList.firstOrNull { license.name.startsWith( prefix = it, - ignoreCase = true + ignoreCase = true, ) } ?: "etc" } From 2c4d86f063df6736d74ad4d4588b4777d8e923e0 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 12:17:54 +0900 Subject: [PATCH 28/41] Rename default implementation for Repository --- .../main/java/io/github/droidkaigi/confsched2023/AppModule.kt | 4 ++-- ...seRepositoryImpl.kt => DefaultOssLicenseRepositoryImpl.kt} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename app-android/src/main/java/io/github/droidkaigi/confsched2023/license/{OssLicenseRepositoryImpl.kt => DefaultOssLicenseRepositoryImpl.kt} (97%) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt index 8edadb4cc..2ff6acb36 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt @@ -8,7 +8,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import io.github.droidkaigi.confsched2023.data.di.AppAndroidBuildConfig import io.github.droidkaigi.confsched2023.data.di.AppAndroidOssLicenseConfig -import io.github.droidkaigi.confsched2023.license.OssLicenseRepositoryImpl +import io.github.droidkaigi.confsched2023.license.DefaultOssLicenseRepositoryImpl import io.github.droidkaigi.confsched2023.model.BuildConfigProvider import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import javax.inject.Singleton @@ -26,7 +26,7 @@ class AppModule { @AppAndroidOssLicenseConfig fun provideOssLicenseRepositoryProvider( @ApplicationContext context: Context, - ): OssLicenseRepository = OssLicenseRepositoryImpl(context) + ): OssLicenseRepository = DefaultOssLicenseRepositoryImpl(context) } class AppBuildConfigProvider( diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt similarity index 97% rename from app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt rename to app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt index 8b6cfb450..1e005a0e5 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/OssLicenseRepositoryImpl.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt @@ -14,7 +14,7 @@ import okio.buffer import okio.source import javax.inject.Inject -class OssLicenseRepositoryImpl @Inject constructor( +class DefaultOssLicenseRepositoryImpl @Inject constructor( private val context: Context, ) : OssLicenseRepository { From b172de998babbcc0bb04b23cdb7c2c1708f9e470 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 12:59:24 +0900 Subject: [PATCH 29/41] Update DI config for OssLicenseDataSource --- .../droidkaigi/confsched2023/AppModule.kt | 8 +- .../license/DefaultOssLicenseDataSource.kt | 100 ++++++++++++++++++ .../DefaultOssLicenseRepositoryImpl.kt | 69 ------------ .../data/di/BuildConfigProviderModule.kt | 25 ++--- .../osslicense/OssLicenseRepositoryModule.kt | 22 ++++ .../osslicense/DefaultOssLicenseRepository.kt | 26 +++++ .../data/osslicense/OssLicenseDataSource.kt | 7 ++ .../model/OssLicenseRepository.kt | 4 +- .../about/OssLicenseDetailViewModel.kt | 26 +---- .../about/OssLicenseViewModel.kt | 2 +- 10 files changed, 175 insertions(+), 114 deletions(-) create mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt delete mode 100644 app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt create mode 100644 core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt create mode 100644 core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt create mode 100644 core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt index 2ff6acb36..e3c12c29f 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/AppModule.kt @@ -8,9 +8,9 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import io.github.droidkaigi.confsched2023.data.di.AppAndroidBuildConfig import io.github.droidkaigi.confsched2023.data.di.AppAndroidOssLicenseConfig -import io.github.droidkaigi.confsched2023.license.DefaultOssLicenseRepositoryImpl +import io.github.droidkaigi.confsched2023.data.osslicense.OssLicenseDataSource +import io.github.droidkaigi.confsched2023.license.DefaultOssLicenseDataSource import io.github.droidkaigi.confsched2023.model.BuildConfigProvider -import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import javax.inject.Singleton @InstallIn(SingletonComponent::class) @@ -24,9 +24,9 @@ class AppModule { @Provides @Singleton @AppAndroidOssLicenseConfig - fun provideOssLicenseRepositoryProvider( + fun provideOssLicenseDataSourceProvider( @ApplicationContext context: Context, - ): OssLicenseRepository = DefaultOssLicenseRepositoryImpl(context) + ): OssLicenseDataSource = DefaultOssLicenseDataSource(context) } class AppBuildConfigProvider( diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt new file mode 100644 index 000000000..bcc49d2b4 --- /dev/null +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt @@ -0,0 +1,100 @@ +package io.github.droidkaigi.confsched2023.license + +import android.content.Context +import io.github.droidkaigi.confsched2023.R +import io.github.droidkaigi.confsched2023.data.osslicense.OssLicenseDataSource +import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicense +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup +import io.github.droidkaigi.confsched2023.ui.Inject +import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import okio.BufferedSource +import okio.buffer +import okio.source + +class DefaultOssLicenseDataSource @Inject constructor( + private val context: Context, +) : OssLicenseDataSource { + + override suspend fun licenseFlow(): OssLicense { + return withContext(context = Dispatchers.IO) { + val details = readLicensesFile().toRowList() + val metadata = readLicensesMetaFile().toRowList().parseToLibraryItem( + details = details, + ) + val groupList = metadata.distinctBy { it.name }.groupByCategory() + .map { + OssLicenseGroup( + title = it.key, + licenses = it.value, + ) + }.toPersistentList() + OssLicense(groupList) + } + } + + private fun List.groupByCategory(): Map> { + val categoryList = listOf( + "Android Support", + "Android Datastore", + "Android ", + "Compose UI", + "Compose Material3", + "Compose ", + "AndroidX lifecycle", + "AndroidX ", + "Kotlin", + "Dagger", + "Firebase", + "Ktorfit", + "okhttp", + "ktor", + ) + return groupBy { license -> + categoryList.firstOrNull { + license.name.startsWith( + prefix = it, + ignoreCase = true, + ) + } ?: "etc" + } + } + + private fun readLicensesMetaFile(): BufferedSource { + return context.resources.openRawResource(R.raw.third_party_license_metadata) + .source() + .buffer() + } + + private fun readLicensesFile(): BufferedSource { + return context.resources.openRawResource(R.raw.third_party_licenses) + .source() + .buffer() + } + + private fun List.parseToLibraryItem(details: List): List { + return mapIndexed { index, value -> + val (position, name) = value.split(' ', limit = 2) + val (offset, length) = position.split(':').map { it.toInt() } + val id = name.replace(' ', '-') + License( + name = name, + id = id, + offset = offset, + length = length, + detail = details[index], + ) + } + } + + private fun BufferedSource.toRowList(): List { + val list: MutableList = mutableListOf() + while (true) { + val line = readUtf8Line() ?: break + list.add(line) + } + return list + } +} diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt deleted file mode 100644 index 1e005a0e5..000000000 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseRepositoryImpl.kt +++ /dev/null @@ -1,69 +0,0 @@ -package io.github.droidkaigi.confsched2023.license - -import android.content.Context -import io.github.droidkaigi.confsched2023.R.raw -import io.github.droidkaigi.confsched2023.model.License -import io.github.droidkaigi.confsched2023.model.OssLicenseRepository -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import okio.BufferedSource -import okio.buffer -import okio.source -import javax.inject.Inject - -class DefaultOssLicenseRepositoryImpl @Inject constructor( - private val context: Context, -) : OssLicenseRepository { - - private val licenseMetaStateFlow = - MutableStateFlow>(persistentListOf()) - - private val licenseDetailStateFlow = MutableStateFlow>(emptyList()) - - override fun licenseMetaData(): Flow> { - licenseMetaStateFlow.value = readLicensesMetaFile() - .toRowList() - .parseToLibraryItem() - .toPersistentList() - return licenseMetaStateFlow - } - - override fun licenseDetailData(): Flow> { - licenseDetailStateFlow.value = readLicensesFile() - .toRowList() - return licenseDetailStateFlow - } - - private fun readLicensesMetaFile(): BufferedSource { - return context.resources.openRawResource(raw.third_party_license_metadata) - .source() - .buffer() - } - - private fun readLicensesFile(): BufferedSource { - return context.resources.openRawResource(raw.third_party_licenses) - .source() - .buffer() - } - - private fun List.parseToLibraryItem(): List { - return map { - val (position, name) = it.split(' ', limit = 2) - val (offset, length) = position.split(':').map { it.toInt() } - val id = name.replace(' ', '-') - License(id = id, name = name, offset = offset, length = length) - } - } - - private fun BufferedSource.toRowList(): List { - val list: MutableList = mutableListOf() - while (true) { - val line = readUtf8Line() ?: break - list.add(line) - } - return list - } -} diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index c2e4a6725..45b6f6464 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -5,13 +5,9 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import io.github.droidkaigi.confsched2023.data.osslicense.OssLicenseDataSource import io.github.droidkaigi.confsched2023.model.BuildConfigProvider -import io.github.droidkaigi.confsched2023.model.License -import io.github.droidkaigi.confsched2023.model.OssLicenseRepository -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf +import io.github.droidkaigi.confsched2023.model.OssLicense import java.util.Optional import javax.inject.Qualifier import javax.inject.Singleton @@ -38,11 +34,11 @@ class BuildConfigProviderModule { @Provides @Singleton fun provideOssLicenseRepositoryProvider( - @AppAndroidOssLicenseConfig ossLicenseRepository: Optional, - ): OssLicenseRepository = if (ossLicenseRepository.isPresent) { - ossLicenseRepository.get() + @AppAndroidOssLicenseConfig ossLicenseDataSourceOptional: Optional, + ): OssLicenseDataSource = if (ossLicenseDataSourceOptional.isPresent) { + ossLicenseDataSourceOptional.get() } else { - EmptyOssLicenseRepository + EmptyOssLicenseDataSource } } @@ -59,14 +55,15 @@ abstract class AppAndroidBuildConfigModule { abstract class AppAndroidOssLicenseModule { @BindsOptionalOf @AppAndroidOssLicenseConfig - abstract fun bindOssLicenseProvider(): OssLicenseRepository + abstract fun bindOssLicenseDataStoreProvider(): OssLicenseDataSource } private object EmptyBuildConfigProvider : BuildConfigProvider { override val versionName: String = "" } -private object EmptyOssLicenseRepository : OssLicenseRepository { - override fun licenseMetaData(): Flow> = flowOf(persistentListOf()) - override fun licenseDetailData(): Flow> = flowOf(emptyList()) +private object EmptyOssLicenseDataSource : OssLicenseDataSource { + override suspend fun licenseFlow(): OssLicense { + return OssLicense() + } } diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt new file mode 100644 index 000000000..b2388cda3 --- /dev/null +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt @@ -0,0 +1,22 @@ +package io.github.droidkaigi.confsched2023.data.osslicense + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class OssLicenseRepositoryModule { + @Provides + @Singleton + fun provideOssLicenseRepository( + ossLicenseDataSource: OssLicenseDataSource, + ): OssLicenseRepository { + return DefaultOssLicenseRepository( + ossLicenseDataSource, + ) + } +} diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt new file mode 100644 index 000000000..de6988ccb --- /dev/null +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt @@ -0,0 +1,26 @@ +package io.github.droidkaigi.confsched2023.data.osslicense + +import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicenseRepository +import io.github.droidkaigi.confsched2023.ui.Inject +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.onStart + +class DefaultOssLicenseRepository @Inject constructor( + private val ossLicenseDataSource: OssLicenseDataSource, +) : OssLicenseRepository { + + private val contributorsStateFlow = + MutableStateFlow>(persistentListOf()) + + override fun licenseData(): Flow> { + return contributorsStateFlow.onStart { + if (contributorsStateFlow.value.isEmpty()) { + ossLicenseDataSource.licenseFlow() + } + } + } +} diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt new file mode 100644 index 000000000..8e597d5d2 --- /dev/null +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt @@ -0,0 +1,7 @@ +package io.github.droidkaigi.confsched2023.data.osslicense + +import io.github.droidkaigi.confsched2023.model.OssLicense + +interface OssLicenseDataSource { + suspend fun licenseFlow(): OssLicense +} diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt index 054c64b0b..760216ee8 100644 --- a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt @@ -4,7 +4,5 @@ import kotlinx.collections.immutable.PersistentList import kotlinx.coroutines.flow.Flow public interface OssLicenseRepository { - public fun licenseMetaData(): Flow> - - public fun licenseDetailData(): Flow> + public fun licenseData(): Flow> } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt index b50ff9cfe..74da36b55 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt @@ -26,36 +26,16 @@ class OssLicenseDetailViewModel @Inject constructor( ) private val licenseStateFlow: StateFlow> = - ossLicenseRepository.licenseMetaData() + ossLicenseRepository.licenseData() .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = persistentListOf(), ) - private val licenseDetailStateFlow: StateFlow> = - ossLicenseRepository.licenseDetailData() - .stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5_000), - initialValue = emptyList(), - ) - internal val uiState: StateFlow = - buildUiState(licenseStateFlow, licenseDetailStateFlow) { metadata, detail -> - val license = metadata.firstOrNull { it.id == licenseName.value } - ?.let { license -> - val detail = kotlin.runCatching { - val start = license.offset - val end = license.offset + license.length - detail.subList( - fromIndex = start, - toIndex = end, - ).joinToString("\n") - }.getOrElse { "" } - license.copy(detail = detail) - } - + buildUiState(licenseStateFlow) { licenses -> + val license = licenses.firstOrNull { it.id == licenseName.value } OssLicenseDetailScreenUiState(license) } } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index cd1313623..747b58187 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -22,7 +22,7 @@ class OssLicenseViewModel @Inject constructor( ) : ViewModel() { private val licenseStateFlow: StateFlow> = - ossLicenseRepository.licenseMetaData() + ossLicenseRepository.licenseData() .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000), From 5e5c12ed7eed9840f59dcc4919fdacfc1700c8e1 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 13:36:25 +0900 Subject: [PATCH 30/41] Refactoring DataFlow --- .../license/DefaultOssLicenseDataSource.kt | 46 +++++++++---------- .../data/di/BuildConfigProviderModule.kt | 8 ++-- .../osslicense/DefaultOssLicenseRepository.kt | 14 +++--- .../data/osslicense/OssLicenseDataSource.kt | 4 +- .../droidkaigi/confsched2023/model/License.kt | 12 +---- .../model/OssLicenseRepository.kt | 2 +- .../about/OssLicenseDetailScreen.kt | 2 +- .../about/OssLicenseDetailViewModel.kt | 8 ++-- .../confsched2023/about/OssLicenseScreen.kt | 8 ++-- .../about/OssLicenseViewModel.kt | 45 ++---------------- 10 files changed, 52 insertions(+), 97 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt index bcc49d2b4..03aa1acc3 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt @@ -4,7 +4,6 @@ import android.content.Context import io.github.droidkaigi.confsched2023.R import io.github.droidkaigi.confsched2023.data.osslicense.OssLicenseDataSource import io.github.droidkaigi.confsched2023.model.License -import io.github.droidkaigi.confsched2023.model.OssLicense import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import io.github.droidkaigi.confsched2023.ui.Inject import kotlinx.collections.immutable.toPersistentList @@ -18,23 +17,37 @@ class DefaultOssLicenseDataSource @Inject constructor( private val context: Context, ) : OssLicenseDataSource { - override suspend fun licenseFlow(): OssLicense { + override suspend fun license(): List { return withContext(context = Dispatchers.IO) { - val details = readLicensesFile().toRowList() - val metadata = readLicensesMetaFile().toRowList().parseToLibraryItem( - details = details, - ) - val groupList = metadata.distinctBy { it.name }.groupByCategory() + readLicenses() + .groupByCategory() .map { OssLicenseGroup( title = it.key, licenses = it.value, ) - }.toPersistentList() - OssLicense(groupList) + } + .toPersistentList() } } + private fun readLicenses(): List { + val licenseData = readLicensesFile().toRowList() + return readLicensesMetaFile().toRowList() + .map { + val (position, name) = it.split(' ', limit = 2) + val (offset, length) = position.split(':').map { it.toInt() } + val licensesText = kotlin.runCatching { + licenseData.subList(offset, offset + length).joinToString() + }.getOrNull() ?: "" + License( + id = name.replace(' ', '-'), + name = name, + licensesText = licensesText, + ) + } + } + private fun List.groupByCategory(): Map> { val categoryList = listOf( "Android Support", @@ -74,21 +87,6 @@ class DefaultOssLicenseDataSource @Inject constructor( .buffer() } - private fun List.parseToLibraryItem(details: List): List { - return mapIndexed { index, value -> - val (position, name) = value.split(' ', limit = 2) - val (offset, length) = position.split(':').map { it.toInt() } - val id = name.replace(' ', '-') - License( - name = name, - id = id, - offset = offset, - length = length, - detail = details[index], - ) - } - } - private fun BufferedSource.toRowList(): List { val list: MutableList = mutableListOf() while (true) { diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index 45b6f6464..3a304569b 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -7,7 +7,9 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import io.github.droidkaigi.confsched2023.data.osslicense.OssLicenseDataSource import io.github.droidkaigi.confsched2023.model.BuildConfigProvider -import io.github.droidkaigi.confsched2023.model.OssLicense +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf import java.util.Optional import javax.inject.Qualifier import javax.inject.Singleton @@ -63,7 +65,7 @@ private object EmptyBuildConfigProvider : BuildConfigProvider { } private object EmptyOssLicenseDataSource : OssLicenseDataSource { - override suspend fun licenseFlow(): OssLicense { - return OssLicense() + override suspend fun license(): PersistentList { + return persistentListOf() } } diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt index de6988ccb..0ec3e6ba9 100644 --- a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt @@ -1,6 +1,6 @@ package io.github.droidkaigi.confsched2023.data.osslicense -import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.Inject import kotlinx.collections.immutable.PersistentList @@ -13,14 +13,12 @@ class DefaultOssLicenseRepository @Inject constructor( private val ossLicenseDataSource: OssLicenseDataSource, ) : OssLicenseRepository { - private val contributorsStateFlow = - MutableStateFlow>(persistentListOf()) + private val ossLicenseStateFlow = + MutableStateFlow>(persistentListOf()) - override fun licenseData(): Flow> { - return contributorsStateFlow.onStart { - if (contributorsStateFlow.value.isEmpty()) { - ossLicenseDataSource.licenseFlow() - } + override fun licenseData(): Flow> { + return ossLicenseStateFlow.onStart { + ossLicenseDataSource.license() } } } diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt index 8e597d5d2..a3772f79a 100644 --- a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt @@ -1,7 +1,7 @@ package io.github.droidkaigi.confsched2023.data.osslicense -import io.github.droidkaigi.confsched2023.model.OssLicense +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup interface OssLicenseDataSource { - suspend fun licenseFlow(): OssLicense + suspend fun license(): List } diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt index 08130bc44..bc0ee8a90 100644 --- a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/License.kt @@ -1,22 +1,12 @@ package io.github.droidkaigi.confsched2023.model -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf - data class License( val id: String, val name: String, - val offset: Int, - val length: Int, - val detail: String = "", + val licensesText: String, ) data class OssLicenseGroup( val title: String, val licenses: List, - val expand: Boolean = false, -) - -data class OssLicense( - val groupList: PersistentList = persistentListOf(), ) diff --git a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt index 760216ee8..1d4b7e748 100644 --- a/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt +++ b/core/model/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/model/OssLicenseRepository.kt @@ -4,5 +4,5 @@ import kotlinx.collections.immutable.PersistentList import kotlinx.coroutines.flow.Flow public interface OssLicenseRepository { - public fun licenseData(): Flow> + public fun licenseData(): Flow> } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt index 0b16b77d9..f870cdfcc 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailScreen.kt @@ -80,7 +80,7 @@ fun OssLicenseDetailScreen( ) { uiState.ossLicense?.run { Text( - text = this.detail, + text = this.licensesText, style = MaterialTheme.typography.bodyMedium, ) } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt index 74da36b55..7d49e90eb 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt @@ -4,7 +4,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import io.github.droidkaigi.confsched2023.model.License +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.buildUiState import kotlinx.collections.immutable.PersistentList @@ -25,7 +25,7 @@ class OssLicenseDetailViewModel @Inject constructor( "", ) - private val licenseStateFlow: StateFlow> = + private val licenseStateFlow: StateFlow> = ossLicenseRepository.licenseData() .stateIn( scope = viewModelScope, @@ -35,7 +35,9 @@ class OssLicenseDetailViewModel @Inject constructor( internal val uiState: StateFlow = buildUiState(licenseStateFlow) { licenses -> - val license = licenses.firstOrNull { it.id == licenseName.value } + val license = licenses + .flatMap { it.licenses } + .firstOrNull { it.id == licenseName.value } OssLicenseDetailScreenUiState(license) } } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt index 47937697f..91c6d54ae 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseScreen.kt @@ -34,7 +34,9 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import io.github.droidkaigi.confsched2023.model.License -import io.github.droidkaigi.confsched2023.model.OssLicense +import io.github.droidkaigi.confsched2023.model.OssLicenseGroup +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf const val ossLicenseScreenRoute = "osslicense" fun NavGraphBuilder.ossLicenseScreen( @@ -51,7 +53,7 @@ fun NavController.navigateOssLicenseScreen() { } data class OssLicenseScreenUiState( - val ossLicense: OssLicense = OssLicense(), + val ossLicense: PersistentList = persistentListOf(), ) @OptIn(ExperimentalMaterial3Api::class) @@ -98,7 +100,7 @@ private fun OssLicenseScreen( onLicenseClick: (License) -> Unit, ) { LazyColumn(modifier = Modifier.padding(horizontal = 8.dp)) { - items(items = uiState.ossLicense.groupList) { group -> + items(items = uiState.ossLicense) { group -> var expand by remember { mutableStateOf(false) } diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index 747b58187..38831be81 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -3,12 +3,9 @@ package io.github.droidkaigi.confsched2023.about import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import io.github.droidkaigi.confsched2023.model.License -import io.github.droidkaigi.confsched2023.model.OssLicense import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.buildUiState -import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.SharingStarted @@ -18,10 +15,10 @@ import javax.inject.Inject @HiltViewModel class OssLicenseViewModel @Inject constructor( - private val ossLicenseRepository: OssLicenseRepository, + ossLicenseRepository: OssLicenseRepository, ) : ViewModel() { - private val licenseStateFlow: StateFlow> = + private val licenseStateFlow: StateFlow> = ossLicenseRepository.licenseData() .stateIn( scope = viewModelScope, @@ -30,41 +27,7 @@ class OssLicenseViewModel @Inject constructor( ) internal val uiState: StateFlow = - buildUiState(licenseStateFlow) { metadata -> - val groupList = metadata.distinctBy { it.name }.groupByCategory() - .map { - OssLicenseGroup( - title = it.key, - licenses = it.value, - ) - }.toPersistentList() - OssLicenseScreenUiState(ossLicense = OssLicense(groupList)) + buildUiState(licenseStateFlow) { licenses -> + OssLicenseScreenUiState(ossLicense = licenses.toPersistentList()) } - - private fun List.groupByCategory(): Map> { - val categoryList = listOf( - "Android Support", - "Android Datastore", - "Android ", - "Compose UI", - "Compose Material3", - "Compose ", - "AndroidX lifecycle", - "AndroidX ", - "Kotlin", - "Dagger", - "Firebase", - "Ktorfit", - "okhttp", - "ktor", - ) - return groupBy { license -> - categoryList.firstOrNull { - license.name.startsWith( - prefix = it, - ignoreCase = true, - ) - } ?: "etc" - } - } } From 65ffeeb4375fd91204e50dc2616fce483514dbc6 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 13:42:59 +0900 Subject: [PATCH 31/41] Fix logic --- .../data/osslicense/DefaultOssLicenseRepository.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt index 0ec3e6ba9..c77a65443 100644 --- a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt @@ -5,6 +5,7 @@ import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.Inject import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.onStart @@ -18,7 +19,8 @@ class DefaultOssLicenseRepository @Inject constructor( override fun licenseData(): Flow> { return ossLicenseStateFlow.onStart { - ossLicenseDataSource.license() + val ossLicenseData = ossLicenseDataSource.license().toPersistentList() + ossLicenseStateFlow.emit(ossLicenseData) } } } From 6e246d2f5736f82ecb95fe980815d3afcd0f0ac6 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 13:48:22 +0900 Subject: [PATCH 32/41] Remove duplicated libraries --- .../confsched2023/license/DefaultOssLicenseDataSource.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt index 03aa1acc3..17a4a7750 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt @@ -46,6 +46,7 @@ class DefaultOssLicenseDataSource @Inject constructor( licensesText = licensesText, ) } + .distinctBy { it.id } } private fun List.groupByCategory(): Map> { From 723baf910912257dd716c9ba42acfda4be85b401 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 14:34:32 +0900 Subject: [PATCH 33/41] Refactoring --- .../confsched2023/license/DefaultOssLicenseDataSource.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt index 17a4a7750..b9729d9ac 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt @@ -37,11 +37,14 @@ class DefaultOssLicenseDataSource @Inject constructor( .map { val (position, name) = it.split(' ', limit = 2) val (offset, length) = position.split(':').map { it.toInt() } + + val id = name.replace(' ', '-') val licensesText = kotlin.runCatching { licenseData.subList(offset, offset + length).joinToString() }.getOrNull() ?: "" + License( - id = name.replace(' ', '-'), + id = id, name = name, licensesText = licensesText, ) From aaad120b56df3cf5168e22c246f6df5755424e6b Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 14:35:49 +0900 Subject: [PATCH 34/41] Remove unnecessary code --- .../confsched2023/about/OssLicenseDetailViewModel.kt | 2 +- .../droidkaigi/confsched2023/about/OssLicenseViewModel.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt index 7d49e90eb..e2c768712 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseDetailViewModel.kt @@ -20,7 +20,7 @@ class OssLicenseDetailViewModel @Inject constructor( savedStateHandle: SavedStateHandle, ) : ViewModel() { - private val licenseName = savedStateHandle.getStateFlow( + private val licenseName = savedStateHandle.getStateFlow( ossLicenseDetailScreenRouteNameArgument, "", ) diff --git a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt index 38831be81..59fd8f154 100644 --- a/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt +++ b/feature/about/src/main/java/io/github/droidkaigi/confsched2023/about/OssLicenseViewModel.kt @@ -6,8 +6,8 @@ import dagger.hilt.android.lifecycle.HiltViewModel import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import io.github.droidkaigi.confsched2023.model.OssLicenseRepository import io.github.droidkaigi.confsched2023.ui.buildUiState +import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.stateIn @@ -18,7 +18,7 @@ class OssLicenseViewModel @Inject constructor( ossLicenseRepository: OssLicenseRepository, ) : ViewModel() { - private val licenseStateFlow: StateFlow> = + private val licenseStateFlow: StateFlow> = ossLicenseRepository.licenseData() .stateIn( scope = viewModelScope, @@ -28,6 +28,6 @@ class OssLicenseViewModel @Inject constructor( internal val uiState: StateFlow = buildUiState(licenseStateFlow) { licenses -> - OssLicenseScreenUiState(ossLicense = licenses.toPersistentList()) + OssLicenseScreenUiState(ossLicense = licenses) } } From c0c4f4d611fb04d339d12a30d99ff67201517c0f Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 16:31:40 +0900 Subject: [PATCH 35/41] Fix visibility --- .../confsched2023/license/DefaultOssLicenseDataSource.kt | 2 +- .../data/osslicense/DefaultOssLicenseRepository.kt | 2 +- .../confsched2023/data/osslicense/OssLicenseDataSource.kt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt index b9729d9ac..189f18a4f 100644 --- a/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt +++ b/app-android/src/main/java/io/github/droidkaigi/confsched2023/license/DefaultOssLicenseDataSource.kt @@ -13,7 +13,7 @@ import okio.BufferedSource import okio.buffer import okio.source -class DefaultOssLicenseDataSource @Inject constructor( +public class DefaultOssLicenseDataSource @Inject constructor( private val context: Context, ) : OssLicenseDataSource { diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt index c77a65443..03103a290 100644 --- a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/DefaultOssLicenseRepository.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.onStart -class DefaultOssLicenseRepository @Inject constructor( +public class DefaultOssLicenseRepository @Inject constructor( private val ossLicenseDataSource: OssLicenseDataSource, ) : OssLicenseRepository { diff --git a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt index a3772f79a..d6db168fd 100644 --- a/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt +++ b/core/data/src/commonMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseDataSource.kt @@ -2,6 +2,6 @@ package io.github.droidkaigi.confsched2023.data.osslicense import io.github.droidkaigi.confsched2023.model.OssLicenseGroup -interface OssLicenseDataSource { - suspend fun license(): List +public interface OssLicenseDataSource { + public suspend fun license(): List } From 18191133138f9d3c46a334e55961378bb545a904 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 16 Sep 2023 16:33:26 +0900 Subject: [PATCH 36/41] Fix visibility --- .../confsched2023/data/di/BuildConfigProviderModule.kt | 8 ++++---- .../data/osslicense/OssLicenseRepositoryModule.kt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index 10089da21..74289dd32 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -18,7 +18,7 @@ import javax.inject.Singleton public annotation class AppAndroidBuildConfig @Qualifier -annotation class AppAndroidOssLicenseConfig +public annotation class AppAndroidOssLicenseConfig @Module @InstallIn(SingletonComponent::class) @@ -35,7 +35,7 @@ public class BuildConfigProviderModule { @Provides @Singleton - fun provideOssLicenseRepositoryProvider( + public fun provideOssLicenseRepositoryProvider( @AppAndroidOssLicenseConfig ossLicenseDataSourceOptional: Optional, ): OssLicenseDataSource = if (ossLicenseDataSourceOptional.isPresent) { ossLicenseDataSourceOptional.get() @@ -54,10 +54,10 @@ public abstract class AppAndroidBuildConfigModule { @InstallIn(SingletonComponent::class) @Module -abstract class AppAndroidOssLicenseModule { +public abstract class AppAndroidOssLicenseModule { @BindsOptionalOf @AppAndroidOssLicenseConfig - abstract fun bindOssLicenseDataStoreProvider(): OssLicenseDataSource + public abstract fun bindOssLicenseDataStoreProvider(): OssLicenseDataSource } private object EmptyBuildConfigProvider : BuildConfigProvider { diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt index b2388cda3..e6656bf89 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/osslicense/OssLicenseRepositoryModule.kt @@ -9,10 +9,10 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -class OssLicenseRepositoryModule { +public class OssLicenseRepositoryModule { @Provides @Singleton - fun provideOssLicenseRepository( + public fun provideOssLicenseRepository( ossLicenseDataSource: OssLicenseDataSource, ): OssLicenseRepository { return DefaultOssLicenseRepository( From 4183d9663a6bea368a00b2d62d5aabaa29715d00 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 23 Sep 2023 18:18:14 +0900 Subject: [PATCH 37/41] Add screenshot testing for oss license screen --- app-android/build.gradle.kts | 2 +- .../testing/robot/OssLicenseScreenRobot.kt | 50 +++++++++++++++++++ .../confsched2023/OssLicenseScreenTest.kt | 41 +++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseScreenRobot.kt create mode 100644 feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseScreenTest.kt diff --git a/app-android/build.gradle.kts b/app-android/build.gradle.kts index ebd609627..c1249bad0 100644 --- a/app-android/build.gradle.kts +++ b/app-android/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("droidkaigi.primitive.android.crashlytics") id("droidkaigi.primitive.detekt") id("droidkaigi.primitive.android.roborazzi") - id("droidkaigi.primitive.kover.entrypoint") +// id("droidkaigi.primitive.kover.entrypoint") id("droidkaigi.primitive.android.osslicenses") } diff --git a/core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseScreenRobot.kt b/core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseScreenRobot.kt new file mode 100644 index 000000000..344693721 --- /dev/null +++ b/core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseScreenRobot.kt @@ -0,0 +1,50 @@ +package io.github.droidkaigi.confsched2023.testing.robot + +import androidx.compose.ui.test.isRoot +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import com.github.takahirom.roborazzi.captureRoboImage +import io.github.droidkaigi.confsched2023.about.OssLicenseScreen +import io.github.droidkaigi.confsched2023.designsystem.theme.KaigiTheme +import io.github.droidkaigi.confsched2023.testing.RobotTestRule +import io.github.droidkaigi.confsched2023.testing.coroutines.runTestWithLogging +import kotlinx.coroutines.test.TestDispatcher +import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds + +class OssLicenseScreenRobot @Inject constructor( + private val testDispatcher: TestDispatcher, +) { + @Inject lateinit var robotTestRule: RobotTestRule + private lateinit var composeTestRule: AndroidComposeTestRule<*, *> + operator fun invoke( + block: OssLicenseScreenRobot.() -> Unit, + ) { + runTestWithLogging(timeout = 30.seconds) { + this@OssLicenseScreenRobot.composeTestRule = robotTestRule.composeTestRule + block() + } + } + + fun setupOssLicenseScreenContent() { + composeTestRule.setContent { + KaigiTheme { + OssLicenseScreen( + onLicenseClick = {}, + onUpClick = {}, + ) + } + } + waitUntilIdle() + } + + fun checkScreenCapture() { + composeTestRule + .onNode(isRoot()) + .captureRoboImage() + } + + fun waitUntilIdle() { + composeTestRule.waitForIdle() + testDispatcher.scheduler.advanceUntilIdle() + } +} diff --git a/feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseScreenTest.kt b/feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseScreenTest.kt new file mode 100644 index 000000000..f9e6eab3f --- /dev/null +++ b/feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseScreenTest.kt @@ -0,0 +1,41 @@ +package io.github.droidkaigi.confsched2023 + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers +import dagger.hilt.android.testing.BindValue +import dagger.hilt.android.testing.HiltAndroidTest +import io.github.droidkaigi.confsched2023.testing.HiltTestActivity +import io.github.droidkaigi.confsched2023.testing.RobotTestRule +import io.github.droidkaigi.confsched2023.testing.category.ScreenshotTests +import io.github.droidkaigi.confsched2023.testing.robot.OssLicenseScreenRobot +import org.junit.Rule +import org.junit.Test +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import javax.inject.Inject + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@HiltAndroidTest +@Config( + qualifiers = RobolectricDeviceQualifiers.NexusOne, +) +class OssLicenseScreenTest { + + @get:Rule + @BindValue val robotTestRule: RobotTestRule = RobotTestRule(this) + + @Inject + lateinit var ossLicenseScreenRobot: OssLicenseScreenRobot + + @Test + @Category(ScreenshotTests::class) + fun checkLaunchShot() { + ossLicenseScreenRobot { + setupOssLicenseScreenContent() + checkScreenCapture() + } + } +} From d94c87ea29339fd44a62fb7ad338c47f4ec21579 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 23 Sep 2023 18:19:20 +0900 Subject: [PATCH 38/41] Add screenshot testing for oss license detail screen --- .../robot/OssLicenseDetailScreenRobot.kt | 49 +++++++++++++++++++ .../OssLicenseDetailScreenTest.kt | 41 ++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseDetailScreenRobot.kt create mode 100644 feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseDetailScreenTest.kt diff --git a/core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseDetailScreenRobot.kt b/core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseDetailScreenRobot.kt new file mode 100644 index 000000000..84f11f1cd --- /dev/null +++ b/core/testing/src/main/java/io/github/droidkaigi/confsched2023/testing/robot/OssLicenseDetailScreenRobot.kt @@ -0,0 +1,49 @@ +package io.github.droidkaigi.confsched2023.testing.robot + +import androidx.compose.ui.test.isRoot +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import com.github.takahirom.roborazzi.captureRoboImage +import io.github.droidkaigi.confsched2023.about.OssLicenseDetailScreen +import io.github.droidkaigi.confsched2023.designsystem.theme.KaigiTheme +import io.github.droidkaigi.confsched2023.testing.RobotTestRule +import io.github.droidkaigi.confsched2023.testing.coroutines.runTestWithLogging +import kotlinx.coroutines.test.TestDispatcher +import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds + +class OssLicenseDetailScreenRobot @Inject constructor( + private val testDispatcher: TestDispatcher, +) { + @Inject lateinit var robotTestRule: RobotTestRule + private lateinit var composeTestRule: AndroidComposeTestRule<*, *> + operator fun invoke( + block: OssLicenseDetailScreenRobot.() -> Unit, + ) { + runTestWithLogging(timeout = 30.seconds) { + this@OssLicenseDetailScreenRobot.composeTestRule = robotTestRule.composeTestRule + block() + } + } + + fun setupOssLicenseDetailScreenContent() { + composeTestRule.setContent { + KaigiTheme { + OssLicenseDetailScreen( + onUpClick = {}, + ) + } + } + waitUntilIdle() + } + + fun checkScreenCapture() { + composeTestRule + .onNode(isRoot()) + .captureRoboImage() + } + + fun waitUntilIdle() { + composeTestRule.waitForIdle() + testDispatcher.scheduler.advanceUntilIdle() + } +} diff --git a/feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseDetailScreenTest.kt b/feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseDetailScreenTest.kt new file mode 100644 index 000000000..f071ea926 --- /dev/null +++ b/feature/about/src/test/java/io/github/droidkaigi/confsched2023/OssLicenseDetailScreenTest.kt @@ -0,0 +1,41 @@ +package io.github.droidkaigi.confsched2023 + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers +import dagger.hilt.android.testing.BindValue +import dagger.hilt.android.testing.HiltAndroidTest +import io.github.droidkaigi.confsched2023.testing.HiltTestActivity +import io.github.droidkaigi.confsched2023.testing.RobotTestRule +import io.github.droidkaigi.confsched2023.testing.category.ScreenshotTests +import io.github.droidkaigi.confsched2023.testing.robot.OssLicenseDetailScreenRobot +import org.junit.Rule +import org.junit.Test +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode +import javax.inject.Inject + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@HiltAndroidTest +@Config( + qualifiers = RobolectricDeviceQualifiers.NexusOne, +) +class OssLicenseDetailScreenTest { + + @get:Rule + @BindValue val robotTestRule: RobotTestRule = RobotTestRule(this) + + @Inject + lateinit var ossLicenseDetailScreenRobot: OssLicenseDetailScreenRobot + + @Test + @Category(ScreenshotTests::class) + fun checkLaunchShot() { + ossLicenseDetailScreenRobot { + setupOssLicenseDetailScreenContent() + checkScreenCapture() + } + } +} From a26cc925f7b0d961b84f3655bd26266a2bc9731b Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 23 Sep 2023 18:36:36 +0900 Subject: [PATCH 39/41] revert comment out --- app-android/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-android/build.gradle.kts b/app-android/build.gradle.kts index c1249bad0..ebd609627 100644 --- a/app-android/build.gradle.kts +++ b/app-android/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("droidkaigi.primitive.android.crashlytics") id("droidkaigi.primitive.detekt") id("droidkaigi.primitive.android.roborazzi") -// id("droidkaigi.primitive.kover.entrypoint") + id("droidkaigi.primitive.kover.entrypoint") id("droidkaigi.primitive.android.osslicenses") } From 1255554399dbf2e53d930cbd29a1f8eac7a3b9d5 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 23 Sep 2023 18:38:26 +0900 Subject: [PATCH 40/41] Try to update the build variant when CI --- .github/workflows/CompareScreenshot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CompareScreenshot.yml b/.github/workflows/CompareScreenshot.yml index 8b8a4c363..7bfe68dad 100644 --- a/.github/workflows/CompareScreenshot.yml +++ b/.github/workflows/CompareScreenshot.yml @@ -33,7 +33,7 @@ jobs: workflow: UnitTest.yml branch: main - - run: ./gradlew compareRoborazziDebug compareRoborazziDevDebug --stacktrace -Pscreenshot + - run: ./gradlew compareRoborazziDebug compareRoborazziDevRelease --stacktrace -Pscreenshot - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 if: ${{ always() }} From ecd9b9f8afc52f78548d102ab646cb2d51cf33e1 Mon Sep 17 00:00:00 2001 From: fumiya-kume Date: Sat, 23 Sep 2023 19:06:00 +0900 Subject: [PATCH 41/41] Revert variant change --- .../data/di/BuildConfigProviderModule.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt index 74289dd32..4ab45e157 100644 --- a/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt +++ b/core/data/src/androidMain/kotlin/io/github/droidkaigi/confsched2023/data/di/BuildConfigProviderModule.kt @@ -7,6 +7,7 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import io.github.droidkaigi.confsched2023.data.osslicense.OssLicenseDataSource import io.github.droidkaigi.confsched2023.model.BuildConfigProvider +import io.github.droidkaigi.confsched2023.model.License import io.github.droidkaigi.confsched2023.model.OssLicenseGroup import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf @@ -67,6 +68,17 @@ private object EmptyBuildConfigProvider : BuildConfigProvider { private object EmptyOssLicenseDataSource : OssLicenseDataSource { override suspend fun license(): PersistentList { - return persistentListOf() + return persistentListOf( + OssLicenseGroup( + "dummy", + listOf( + License( + "id", + "name", + "license text", + ), + ), + ), + ) } }