From cb8c694b77734177738a48a392d1289fd6f76878 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Thu, 7 Mar 2024 13:52:19 +0300 Subject: [PATCH 1/9] update libs, fix ratings images --- gradle.properties | 3 -- gradle/libs.versions.toml | 11 +++-- modules/features/root/root.podspec | 13 ++++- modules/features/ui/build.gradle.kts | 2 + .../user/components/RatingUserWidget.kt | 27 +++++++++-- .../users/components/RatingUserWidget.kt | 47 +++++++++++++++++-- 6 files changed, 89 insertions(+), 14 deletions(-) diff --git a/gradle.properties b/gradle.properties index 89eee20b..41995c1e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,9 +31,6 @@ org.gradle.parallel=true kotlin.mpp.enableCInteropCommonization=true org.jetbrains.compose.experimental.uikit.enabled=true kotlin.native.binary.memoryModel=experimental -kotlin.native.enableDependencyPropagation=false -#kotlinOptions.useIR = true -kotlin.mpp.enableGranularSourceSetsMetadata=true android.suppressUnsupportedCompileSdk=32 kotlin.mpp.androidSourceSetLayoutVersion=2 # Java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a4e76884..19c9f365 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,16 +1,16 @@ [versions] # Kotlin -kotlin-version = "1.9.10" +kotlin-version = "1.9.22" kotlin-dokka = "1.8.10" kotlin-coroutines = "1.7.2" -kotlin-compilerExtensionVersion = "1.5.3" +kotlin-compilerExtensionVersion = "1.5.10" kotlin-android-application = "8.0.1" kotlin-serialization-json = "1.5.1" # Androidx androidx-lifecycle = "2.6.1" androidx-lifecycle-ext = "2.2.0" -androidx-compose-bom = "2023.10.00" +androidx-compose-bom = "2024.02.02" androidx-fragment = "1.6.1" androidx-core = "1.10.1" androidx-appcompat = "1.6.1" @@ -55,7 +55,7 @@ klibs-kstorage = "1.0.0" klibs-kdi = "1.1.0" # Compose -kotlin-compose = "1.5.3" +kotlin-compose = "1.6.0" # Moko moko-mvvm = "0.16.1" @@ -205,6 +205,9 @@ moko-resources-compose = { module = "dev.icerock.moko:resources-compose", versio # Other coil = { module = "io.coil-kt:coil-compose", version.ref = "coil" } +# Compose ext +composeext-shimmer = { module = "com.valentinilk.shimmer:compose-shimmer", version.strictly = "1.2.0" } + # Okio okio = { module = "com.squareup.okio:okio", version.strictly = "3.3.0" } diff --git a/modules/features/root/root.podspec b/modules/features/root/root.podspec index 1bc1c277..c7794c9f 100644 --- a/modules/features/root/root.podspec +++ b/modules/features/root/root.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'root' - spec.version = '0.2.2' + spec.version = '0.2.4' spec.homepage = 'https://empireprojekt.ru' spec.source = { :http=> ''} spec.authors = '' @@ -11,6 +11,17 @@ Pod::Spec.new do |spec| spec.ios.deployment_target = '16.0' + if !Dir.exist?('build/cocoapods/framework/Root.framework') || Dir.empty?('build/cocoapods/framework/Root.framework') + raise " + + Kotlin framework 'Root' doesn't exist yet, so a proper Xcode project can't be generated. + 'pod install' should be executed after running ':generateDummyFramework' Gradle task: + + ./gradlew :modules:features:root:generateDummyFramework + + Alternatively, proper pod installation is performed during Gradle sync in the IDE (if Podfile location is set)" + end + spec.pod_target_xcconfig = { 'KOTLIN_PROJECT_PATH' => ':modules:features:root', 'PRODUCT_MODULE_NAME' => 'Root', diff --git a/modules/features/ui/build.gradle.kts b/modules/features/ui/build.gradle.kts index b395a468..7e62195f 100644 --- a/modules/features/ui/build.gradle.kts +++ b/modules/features/ui/build.gradle.kts @@ -24,6 +24,8 @@ kotlin { implementation(compose.material) implementation(compose.material3) implementation(compose.materialIconsExtended) + // Compose extensions + implementation(libs.composeext.shimmer) // klibs implementation(libs.klibs.mikro.core) implementation(libs.klibs.mikro.platform) diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt index 6417013d..cb08caf3 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -15,6 +16,7 @@ import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Cookie import androidx.compose.material.icons.filled.ThumbDown import androidx.compose.material.icons.filled.ThumbUp import androidx.compose.runtime.Composable @@ -23,10 +25,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage +import coil.compose.SubcomposeAsyncImage import com.makeevrserg.empireprojekt.mobile.core.ui.asComposableString import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme import com.makeevrserg.empireprojekt.mobile.resources.MR +import com.valentinilk.shimmer.shimmer import ru.astrainteractive.empireapi.models.rating.RatingModel @Composable @@ -44,10 +47,28 @@ fun RatingUserWidget(ratingModel: RatingModel) { horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.S), modifier = Modifier.padding(horizontal = AppTheme.dimens.S) ) { - AsyncImage( + SubcomposeAsyncImage( model = "https://mc-heads.net/avatar/${ratingModel.userCreatedReport?.minecraftUUID}", contentDescription = null, - modifier = Modifier.size(32.dp) + modifier = Modifier + .size(32.dp) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)), + loading = { + Box( + modifier = Modifier + .fillMaxSize() + .shimmer() + .background(MaterialTheme.colors.primaryVariant) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)) + ) + }, + error = { + Icon( + imageVector = Icons.Filled.Cookie, + contentDescription = null, + tint = MaterialTheme.colors.onPrimary + ) + } ) Text( text = ratingModel.userCreatedReport?.minecraftName ?: "-", diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt index ff899ee3..f0533b89 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -16,6 +17,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChevronRight +import androidx.compose.material.icons.filled.Cookie import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -23,11 +25,15 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage +import coil.compose.SubcomposeAsyncImage import com.makeevrserg.empireprojekt.mobile.core.ui.asComposableString +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AdaptThemeFade import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.ComposeTheme import com.makeevrserg.empireprojekt.mobile.resources.MR +import com.valentinilk.shimmer.shimmer import ru.astrainteractive.empireapi.models.rating.RatingUserModel @Composable @@ -48,10 +54,28 @@ fun RatingUserWidget( modifier = Modifier.padding(vertical = AppTheme.dimens.XS, horizontal = AppTheme.dimens.S), horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS) ) { - AsyncImage( + SubcomposeAsyncImage( model = "https://mc-heads.net/avatar/${model.minecraftUUID}", contentDescription = null, - modifier = Modifier.size(32.dp) + modifier = Modifier + .size(32.dp) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)), + loading = { + Box( + modifier = Modifier + .fillMaxSize() + .shimmer() + .background(MaterialTheme.colors.primaryVariant) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)) + ) + }, + error = { + Icon( + imageVector = Icons.Filled.Cookie, + contentDescription = null, + tint = MaterialTheme.colors.onPrimary + ) + } ) Column { Text( @@ -110,3 +134,20 @@ fun RatingUserWidget( } } } + +@Composable +@Preview +private fun RatingUserWidgetPreview() { + AdaptThemeFade(composeTheme = ComposeTheme.DARK) { + RatingUserWidget( + model = RatingUserModel( + id = 1, + minecraftUUID = "uuid", + minecraftName = "name", + lastUpdated = 0, + total = 10 + ), + onClick = {} + ) + } +} From 4f7a30a0b2ec9116a9563cde3a2a59ab31f0a7f9 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 13:35:15 +0300 Subject: [PATCH 2/9] feature: towns, pager --- .gitignore | 3 +- gradle/libs.versions.toml | 4 +- modules/features/rating/build.gradle.kts | 2 +- .../rating/user/DefaultRatingUserComponent.kt | 15 +-- .../rating/user/data/RatingUserRepository.kt | 5 +- .../user/data/RatingUserRepositoryImpl.kt | 11 +- .../users/data/RatingUsersRepository.kt | 4 +- .../users/data/RatingUsersRepositoryImpl.kt | 9 +- .../users/store/RatingUsersBootstrapper.kt | 10 +- .../rating/users/store/RatingUsersStore.kt | 5 +- modules/features/root/build.gradle.kts | 1 + .../mobile/features/root/di/RootModule.kt | 5 +- .../features/root/di/impl/RootModuleImpl.kt | 24 +++- .../root/pager/DefaultPagerComponent.kt | 105 ++++++++++++++++++ .../features/root/pager/PagerComponent.kt | 37 ++++++ .../features/root/pager/di/PagerModule.kt | 25 +++++ .../root/screen/DefaultRootScreenComponent.kt | 17 +-- .../root/screen/RootScreenComponent.kt | 5 +- .../RootScreenComponentChildFactory.kt | 38 ++----- modules/features/towns/build.gradle.kts | 49 ++++++++ .../towny/towns/data/TownsRepository.kt | 8 ++ .../towny/towns/data/TownsRepositoryImpl.kt | 32 ++++++ .../towny/towns/di/TownsDependencies.kt | 22 ++++ .../features/towny/towns/di/TownsModule.kt | 26 +++++ .../presentation/DefaultTownsComponent.kt | 25 +++++ .../towns/presentation/TownsComponent.kt | 19 ++++ .../towny/towns/presentation/TownsFeature.kt | 29 +++++ modules/features/ui/build.gradle.kts | 1 + .../features/ui/pager/PagerScreenComponent.kt | 66 +++++++++++ .../ui/pager/components/PagerBottomBar.kt | 75 +++++++++++++ .../components/model/PagerBottomBarItem.kt | 13 +++ .../user/components/RatingUserWidget.kt | 26 +---- .../users/RatingUsersScreenComponent.kt | 3 +- .../rating/users/components/PlayerHeadBox.kt | 41 +++++++ .../users/components/RatingUserWidget.kt | 25 +---- .../features/ui/root/ApplicationContent.kt | 20 ++-- .../mobile/features/ui/splash/SplashScreen.kt | 2 +- .../mobile/features/ui/status/StatusScreen.kt | 22 +--- .../ui/towny/towns/TownsScreenComponent.kt | 73 ++++++++++++ .../ui/towny/towns/components/TownCard.kt | 101 +++++++++++++++++ .../mobile/api/empireapi/TownyApi.kt | 11 ++ .../api/empireapi/di/EmpireApiModule.kt | 6 + .../api/empireapi/impl/RatingApiImpl.kt | 2 +- .../mobile/api/empireapi/impl/TownyApiImpl.kt | 30 +++++ .../empireapi/models/towny/NationModel.kt | 16 +++ .../empireapi/models/towny/TownModel.kt | 19 ++++ .../core/ui/components/RowSettingItem.kt | 28 +++++ .../mobile/core/ui/theme/ThemeAdapt.kt | 2 +- .../commonMain/resources/MR/base/strings.xml | 1 + settings.gradle.kts | 2 +- 50 files changed, 946 insertions(+), 174 deletions(-) create mode 100644 modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt create mode 100644 modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt create mode 100644 modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/di/PagerModule.kt create mode 100644 modules/features/towns/build.gradle.kts create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsDependencies.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsModule.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/PlayerHeadBox.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/NationModel.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt diff --git a/.gitignore b/.gitignore index dc823c67..e0b319f9 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,5 @@ modules/features/onboard/build modules/features/ui/onboard/build modules/features/ui/splash/build modules/features/common/build -modules/features/ui/common/build \ No newline at end of file +modules/features/ui/common/build +modules/features/towns/build \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 19c9f365..73e68e3d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ ktor = "2.3.2-eap-692" coil = "2.2.2" # klibs -klibs-mikro = "1.0.0" +klibs-mikro = "1.5.0" klibs-kstorage = "1.0.0" klibs-kdi = "1.1.0" @@ -90,8 +90,10 @@ dokka = "1.8.10" # klibs klibs-mikro-core = { module = "ru.astrainteractive.klibs:mikro-core", version.ref = "klibs-mikro" } klibs-mikro-platform = { module = "ru.astrainteractive.klibs:mikro-platform", version.ref = "klibs-mikro" } +klibs-mikro-extensions = { module = "ru.astrainteractive.klibs:mikro-extensions", version.ref = "klibs-mikro" } klibs-kstorage = { module = "ru.astrainteractive.klibs:kstorage", version.ref = "klibs-kstorage" } klibs-kdi = { module = "ru.astrainteractive.klibs:kdi", version.ref = "klibs-kdi" } +klibs-paging = { module = "ru.astrainteractive.klibs:paging", version.strictly = "2.0.0" } # dokka dokka-android = { module = "org.jetbrains.dokka:android-documentation-plugin", version.ref = "dokka" } dokka-gradle-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" } diff --git a/modules/features/rating/build.gradle.kts b/modules/features/rating/build.gradle.kts index 613be7d8..490c0ca0 100644 --- a/modules/features/rating/build.gradle.kts +++ b/modules/features/rating/build.gradle.kts @@ -28,7 +28,7 @@ kotlin { // Moko implementation(libs.moko.resources.core) // Paging - implementation("ru.astrainteractive.klibs:paging:1.0.0") + implementation(libs.klibs.paging) // Coroutines implementation(libs.kotlin.coroutines.core) // MVIKotlin diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/DefaultRatingUserComponent.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/DefaultRatingUserComponent.kt index 18105bde..c852e550 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/DefaultRatingUserComponent.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/DefaultRatingUserComponent.kt @@ -29,25 +29,18 @@ class DefaultRatingUserComponent( ) private fun collectPagingState() = coroutineFeature.launch { - repository.pagingStateFlow.collectLatest { + repository.state.collectLatest { model.update { model -> model.copy( isLastPage = it.isLastPage, isLoading = it.isLoading, - isFailure = it.isFailure + isFailure = it.isFailure, + items = it.items ) } } } - private fun collectListStateFlow() = coroutineFeature.launch { - repository.listStateFlow.collectLatest { - model.update { model -> - model.copy(items = it) - } - } - } - override fun reset() { coroutineFeature.launch { repository.reset() @@ -56,7 +49,6 @@ class DefaultRatingUserComponent( } override fun loadNextPage() { - println("LoadingNextPage") coroutineFeature.launch { repository.loadNextPage() } @@ -65,6 +57,5 @@ class DefaultRatingUserComponent( init { repository.updateRequest(model.value.request) collectPagingState() - collectListStateFlow() } } diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepository.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepository.kt index 4ef360e2..41143d80 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepository.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepository.kt @@ -3,13 +3,12 @@ package com.makeevrserg.empireprojekt.mobile.features.rating.user.data import kotlinx.coroutines.flow.StateFlow import ru.astrainteractive.empireapi.models.rating.RatingModel import ru.astrainteractive.empireapi.models.rating.UserRatingsRequest +import ru.astrainteractive.klibs.paging.context.IntPageContext import ru.astrainteractive.klibs.paging.state.PagingState interface RatingUserRepository { - val pagingStateFlow: StateFlow> - - val listStateFlow: StateFlow> + val state: StateFlow> suspend fun reset() diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepositoryImpl.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepositoryImpl.kt index 8cf33095..52d8dffd 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepositoryImpl.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/user/data/RatingUserRepositoryImpl.kt @@ -2,13 +2,16 @@ package com.makeevrserg.empireprojekt.mobile.features.rating.user.data import com.makeevrserg.empireprojekt.mobile.api.empireapi.RatingApi import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext import ru.astrainteractive.empireapi.models.rating.RatingModel import ru.astrainteractive.empireapi.models.rating.UserRatingsRequest import ru.astrainteractive.klibs.mikro.core.dispatchers.KotlinDispatchers import ru.astrainteractive.klibs.paging.IntPagerCollector +import ru.astrainteractive.klibs.paging.context.IntPageContext import ru.astrainteractive.klibs.paging.data.LambdaPagedListDataSource +import ru.astrainteractive.klibs.paging.state.PagingState class RatingUserRepositoryImpl( private val ratingApi: RatingApi, @@ -19,13 +22,11 @@ class RatingUserRepositoryImpl( private val pagingCollector = IntPagerCollector( initialPage = 0, pager = LambdaPagedListDataSource { - loadPage(it.pageDescriptor) + loadPage(it.pageContext.page) } ) - override val pagingStateFlow = pagingCollector.pagingStateFlow - - override val listStateFlow = pagingCollector.listStateFlow + override val state: StateFlow> = pagingCollector.state private suspend fun loadPage(page: Int): Result> { return runCatching { @@ -44,8 +45,6 @@ class RatingUserRepositoryImpl( } override suspend fun loadNextPage() { - println("LoadingNextPage in repository") - println(pagingCollector.pagingStateFlow.value) pagingCollector.loadNextPage() } diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepository.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepository.kt index 01d28de1..77be2527 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepository.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepository.kt @@ -3,12 +3,12 @@ package com.makeevrserg.empireprojekt.mobile.features.rating.users.data import kotlinx.coroutines.flow.StateFlow import ru.astrainteractive.empireapi.models.rating.RatingListRequest import ru.astrainteractive.empireapi.models.rating.RatingUserModel +import ru.astrainteractive.klibs.paging.context.IntPageContext import ru.astrainteractive.klibs.paging.state.PagingState interface RatingUsersRepository { fun updateRequest(request: RatingListRequest) suspend fun loadNextPage() suspend fun reset() - val pagingStateFlow: StateFlow> - val listStateFlow: StateFlow> + val state: StateFlow> } diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepositoryImpl.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepositoryImpl.kt index a4766f9f..5b6a8d09 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepositoryImpl.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/data/RatingUsersRepositoryImpl.kt @@ -2,13 +2,16 @@ package com.makeevrserg.empireprojekt.mobile.features.rating.users.data import com.makeevrserg.empireprojekt.mobile.api.empireapi.RatingApi import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext import ru.astrainteractive.empireapi.models.rating.RatingListRequest import ru.astrainteractive.empireapi.models.rating.RatingUserModel import ru.astrainteractive.klibs.mikro.core.dispatchers.KotlinDispatchers import ru.astrainteractive.klibs.paging.IntPagerCollector +import ru.astrainteractive.klibs.paging.context.IntPageContext import ru.astrainteractive.klibs.paging.data.LambdaPagedListDataSource +import ru.astrainteractive.klibs.paging.state.PagingState class RatingUsersRepositoryImpl( private val ratingApi: RatingApi, @@ -19,13 +22,11 @@ class RatingUsersRepositoryImpl( private val pagingCollector = IntPagerCollector( initialPage = 0, pager = LambdaPagedListDataSource { - loadPage(it.pageDescriptor) + loadPage(it.pageContext.page) } ) - override val pagingStateFlow = pagingCollector.pagingStateFlow - - override val listStateFlow = pagingCollector.listStateFlow + override val state: StateFlow> = pagingCollector.state private suspend fun loadPage(page: Int): Result> { return runCatching { diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersBootstrapper.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersBootstrapper.kt index 111c34a4..871caf24 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersBootstrapper.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersBootstrapper.kt @@ -13,7 +13,6 @@ internal class RatingUsersBootstrapper( override fun invoke() { collectPagingState() - collectListStateFlow() updateRequestModel() } @@ -22,14 +21,9 @@ internal class RatingUsersBootstrapper( } private fun collectPagingState() = scope.launch { - ratingUsersRepository.pagingStateFlow.collectLatest { + ratingUsersRepository.state.collectLatest { Action.PagingStateChanged(it).run(::dispatch) - } - } - - private fun collectListStateFlow() = scope.launch { - ratingUsersRepository.listStateFlow.collectLatest { - Action.ListChanged(it).run(::dispatch) + Action.ListChanged(it.items).run(::dispatch) } } } diff --git a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersStore.kt b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersStore.kt index ba9e6a44..4e40f827 100644 --- a/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersStore.kt +++ b/modules/features/rating/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/rating/users/store/RatingUsersStore.kt @@ -6,6 +6,7 @@ import com.makeevrserg.empireprojekt.mobile.features.rating.users.store.RatingUs import com.makeevrserg.empireprojekt.mobile.features.rating.users.store.RatingUsersStore.State import ru.astrainteractive.empireapi.models.rating.RatingListRequest import ru.astrainteractive.empireapi.models.rating.RatingUserModel +import ru.astrainteractive.klibs.paging.context.IntPageContext import ru.astrainteractive.klibs.paging.state.PagingState interface RatingUsersStore : Store { @@ -24,14 +25,14 @@ interface RatingUsersStore : Store { sealed interface Message { class ListChanged(val list: List) : Message - class PagingStateChanged(val pagingState: PagingState) : Message + class PagingStateChanged(val pagingState: PagingState) : Message } object Label sealed interface Action { class ListChanged(val list: List) : Action - class PagingStateChanged(val pagingState: PagingState) : Action + class PagingStateChanged(val pagingState: PagingState) : Action data object UpdateRequestModel : Action } } diff --git a/modules/features/root/build.gradle.kts b/modules/features/root/build.gradle.kts index d62da324..6acff948 100644 --- a/modules/features/root/build.gradle.kts +++ b/modules/features/root/build.gradle.kts @@ -74,6 +74,7 @@ kotlin { api(projects.modules.features.rating) api(projects.modules.features.theme) api(projects.modules.features.status) + api(projects.modules.features.towns) } } val androidMain by getting { diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/RootModule.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/RootModule.kt index de5efa6d..9e3d2370 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/RootModule.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/RootModule.kt @@ -2,7 +2,9 @@ package com.makeevrserg.empireprojekt.mobile.features.root.di import com.makeevrserg.empireprojekt.mobile.api.empireapi.di.EmpireApiModule import com.makeevrserg.empireprojekt.mobile.features.logic.splash.di.SplashComponentModule +import com.makeevrserg.empireprojekt.mobile.features.root.pager.di.PagerModule import com.makeevrserg.empireprojekt.mobile.features.status.di.StatusModule +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.di.TownsModule import ru.astrainteractive.klibs.kdi.Module interface RootModule : Module { @@ -10,7 +12,8 @@ interface RootModule : Module { val servicesModule: ServicesModule val statusModule: StatusModule val splashModule: SplashComponentModule + val townsModule: TownsModule val componentsModule: ComponentsModule - + val pagerModule: PagerModule val empireApiModule: EmpireApiModule } diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/impl/RootModuleImpl.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/impl/RootModuleImpl.kt index 53c9b641..79df14ff 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/impl/RootModuleImpl.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/di/impl/RootModuleImpl.kt @@ -5,7 +5,9 @@ import com.makeevrserg.empireprojekt.mobile.features.logic.splash.di.SplashCompo import com.makeevrserg.empireprojekt.mobile.features.root.di.ComponentsModule import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule import com.makeevrserg.empireprojekt.mobile.features.root.di.ServicesModule +import com.makeevrserg.empireprojekt.mobile.features.root.pager.di.PagerModule import com.makeevrserg.empireprojekt.mobile.features.status.di.StatusModule +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.di.TownsModule import ru.astrainteractive.klibs.kdi.Provider import ru.astrainteractive.klibs.kdi.Single import ru.astrainteractive.klibs.kdi.getValue @@ -16,6 +18,12 @@ class RootModuleImpl : RootModule { ServicesModuleImpl() } + override val empireApiModule: EmpireApiModule by Provider { + EmpireApiModule.Default( + httpClient = servicesModule.httpClient.value + ) + } + override val statusModule: StatusModule by Provider { StatusModule.Default( dispatchers = servicesModule.dispatchers.value, @@ -30,13 +38,17 @@ class RootModuleImpl : RootModule { ) } - override val componentsModule: ComponentsModule by Single { - ComponentsModuleImpl(this) + override val townsModule: TownsModule by Provider { + TownsModule.Default( + empireApiModule = empireApiModule, + dispatchers = servicesModule.dispatchers.value + ) + } + override val pagerModule: PagerModule by Provider { + PagerModule.Default(this) } - override val empireApiModule: EmpireApiModule by Provider { - EmpireApiModule.Default( - httpClient = servicesModule.httpClient.value - ) + override val componentsModule: ComponentsModule by Single { + ComponentsModuleImpl(this) } } diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt new file mode 100644 index 00000000..de16bac2 --- /dev/null +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt @@ -0,0 +1,105 @@ +package com.makeevrserg.empireprojekt.mobile.features.root.pager + +import com.arkivanov.decompose.ComponentContext +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.childStack +import com.arkivanov.decompose.router.stack.replaceAll +import com.arkivanov.decompose.value.Value +import com.arkivanov.decompose.value.operator.map +import com.arkivanov.essenty.parcelable.Parcelable +import com.arkivanov.essenty.parcelable.Parcelize +import com.makeevrserg.empireprojekt.mobile.features.rating.users.DefaultRatingUsersComponent +import com.makeevrserg.empireprojekt.mobile.features.rating.users.di.RatingUsersModule +import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule +import com.makeevrserg.empireprojekt.mobile.features.root.screen.RootScreenComponent + +internal class DefaultPagerComponent( + componentContext: ComponentContext, + rootModule: RootModule, + onRootNavigation: (RootScreenComponent.Child) -> Unit +) : PagerComponent, ComponentContext by componentContext { + private val navigation = StackNavigation() + + override val childStack: Value> = childStack( + source = navigation, + initialConfiguration = Configuration.Status, + handleBackButton = false, + childFactory = { config, context -> + when (config) { + Configuration.RatingUsers -> { + PagerComponent.Child.RatingUsers( + ratingUsersComponent = DefaultRatingUsersComponent( + componentContext = context, + moduleFactory = { + RatingUsersModule.Default( + empireApiModule = rootModule.empireApiModule, + dispatchers = rootModule.servicesModule.dispatchers.value + ) + }, + onShowUserRatingsClicked = { id, userName -> + val configuration = RootScreenComponent.Child.RatingUser(id, userName) + onRootNavigation.invoke(configuration) + } + ) + ) + } + + Configuration.Status -> { + PagerComponent.Child.Status( + themeSwitcherComponent = rootModule.componentsModule.themeSwitcherComponent.value, + rootStatusComponent = rootModule.componentsModule.rootStatusComponent.value + ) + } + + Configuration.Towns -> { + PagerComponent.Child.Towns( + townsComponent = rootModule.townsModule.createTownsComponent( + componentContext = context + ) + ) + } + } + } + ) + + override val selectedIndex: Value = childStack.map { + when (it.active.instance) { + is PagerComponent.Child.RatingUsers -> 2 + is PagerComponent.Child.Status -> 1 + is PagerComponent.Child.Towns -> 0 + } + } + + override fun selectStatus() { + navigation.replaceAll(Configuration.Status) + } + + override fun selectRatings() { + navigation.replaceAll(Configuration.RatingUsers) + } + + override fun selectTowns() { + navigation.replaceAll(Configuration.Towns) + } + + override fun select(index: Int) { + when (index) { + 0 -> selectTowns() + 1 -> selectStatus() + 2 -> selectRatings() + else -> error("Index out of bounds") + } + } + + private sealed interface Configuration : Parcelable { + @Parcelize + data object Status : Configuration + + @Parcelize + data object RatingUsers : Configuration + + @Parcelize + data object Towns : Configuration + } +} diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt new file mode 100644 index 00000000..1509f869 --- /dev/null +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt @@ -0,0 +1,37 @@ +package com.makeevrserg.empireprojekt.mobile.features.root.pager + +import com.arkivanov.decompose.router.stack.ChildStack +import com.arkivanov.decompose.value.Value +import com.makeevrserg.empireprojekt.mobile.features.rating.users.RatingUsersComponent +import com.makeevrserg.empireprojekt.mobile.features.status.root.RootStatusComponent +import com.makeevrserg.empireprojekt.mobile.features.theme.ThemeSwitcherComponent +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation.TownsComponent + +interface PagerComponent { + val childStack: Value> + val selectedIndex: Value + + fun selectStatus() + + fun selectRatings() + + fun selectTowns() + + fun select(index: Int) + + sealed interface Child { + + class Status( + val rootStatusComponent: RootStatusComponent, + val themeSwitcherComponent: ThemeSwitcherComponent + ) : Child + + class RatingUsers( + val ratingUsersComponent: RatingUsersComponent + ) : Child + + class Towns( + val townsComponent: TownsComponent + ) : Child + } +} diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/di/PagerModule.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/di/PagerModule.kt new file mode 100644 index 00000000..51ffb348 --- /dev/null +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/di/PagerModule.kt @@ -0,0 +1,25 @@ +package com.makeevrserg.empireprojekt.mobile.features.root.pager.di + +import com.arkivanov.decompose.ComponentContext +import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule +import com.makeevrserg.empireprojekt.mobile.features.root.pager.DefaultPagerComponent +import com.makeevrserg.empireprojekt.mobile.features.root.pager.PagerComponent +import com.makeevrserg.empireprojekt.mobile.features.root.screen.RootScreenComponent + +interface PagerModule { + fun createPagerComponent( + componentContext: ComponentContext, + onRootNavigation: (RootScreenComponent.Child) -> Unit + ): PagerComponent + + class Default(private val rootModule: RootModule) : PagerModule { + override fun createPagerComponent( + componentContext: ComponentContext, + onRootNavigation: (RootScreenComponent.Child) -> Unit + ): PagerComponent = DefaultPagerComponent( + componentContext = componentContext, + rootModule = rootModule, + onRootNavigation = onRootNavigation + ) + } +} diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/DefaultRootScreenComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/DefaultRootScreenComponent.kt index d7e3fdab..97b74a4d 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/DefaultRootScreenComponent.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/DefaultRootScreenComponent.kt @@ -12,11 +12,9 @@ import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.operator.map import com.makeevrserg.empireprojekt.mobile.features.logic.splash.SplashComponent import com.makeevrserg.empireprojekt.mobile.features.rating.user.RatingUserComponent -import com.makeevrserg.empireprojekt.mobile.features.rating.users.RatingUsersComponent import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule +import com.makeevrserg.empireprojekt.mobile.features.root.pager.PagerComponent import com.makeevrserg.empireprojekt.mobile.features.root.screen.di.factory.RootScreenComponentChildFactory -import com.makeevrserg.empireprojekt.mobile.features.status.root.RootStatusComponent -import com.makeevrserg.empireprojekt.mobile.features.theme.ThemeSwitcherComponent import com.makeevrserg.empireprojekt.mobile.services.core.PopComponent class DefaultRootScreenComponent( @@ -69,17 +67,12 @@ class DefaultRootScreenComponent( val splashComponent: SplashComponent ) : Configuration - class Status( - val rootStatusComponent: RootStatusComponent, - val themeSwitcherComponent: ThemeSwitcherComponent - ) : Configuration - - class RatingUsers( - val ratingUsersComponent: RatingUsersComponent - ) : Configuration - class RatingUser( val ratingUserComponent: RatingUserComponent ) : Configuration + + class Pager( + val pagerComponent: PagerComponent + ) : Configuration } } diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/RootScreenComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/RootScreenComponent.kt index f4445b10..950a84c3 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/RootScreenComponent.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/RootScreenComponent.kt @@ -19,10 +19,7 @@ interface RootScreenComponent : BackHandlerOwner, PopComponent { data object Splash : Child @Parcelize - data object Status : Child - - @Parcelize - data object RatingUsers : Child + data object Pager : Child @Parcelize class RatingUser(val userId: Long, val userName: String) : Child diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/di/factory/RootScreenComponentChildFactory.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/di/factory/RootScreenComponentChildFactory.kt index 545c6b84..88b2c4b1 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/di/factory/RootScreenComponentChildFactory.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/screen/di/factory/RootScreenComponentChildFactory.kt @@ -4,8 +4,6 @@ import com.arkivanov.decompose.ComponentContext import com.makeevrserg.empireprojekt.mobile.features.logic.splash.DefaultSplashComponent import com.makeevrserg.empireprojekt.mobile.features.rating.user.DefaultRatingUserComponent import com.makeevrserg.empireprojekt.mobile.features.rating.user.di.RatingUserModule -import com.makeevrserg.empireprojekt.mobile.features.rating.users.DefaultRatingUsersComponent -import com.makeevrserg.empireprojekt.mobile.features.rating.users.di.RatingUsersModule import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule import com.makeevrserg.empireprojekt.mobile.features.root.screen.DefaultRootScreenComponent import com.makeevrserg.empireprojekt.mobile.features.root.screen.RootScreenComponent @@ -26,31 +24,6 @@ class RootScreenComponentChildFactory( ) ) - RootScreenComponent.Child.Status -> { - DefaultRootScreenComponent.Configuration.Status( - themeSwitcherComponent = rootModule.componentsModule.themeSwitcherComponent.value, - rootStatusComponent = rootModule.componentsModule.rootStatusComponent.value - ) - } - - RootScreenComponent.Child.RatingUsers -> { - DefaultRootScreenComponent.Configuration.RatingUsers( - ratingUsersComponent = DefaultRatingUsersComponent( - componentContext = context, - moduleFactory = { - RatingUsersModule.Default( - empireApiModule = rootModule.empireApiModule, - dispatchers = rootModule.servicesModule.dispatchers.value - ) - }, - onShowUserRatingsClicked = { id, userName -> - val configuration = RootScreenComponent.Child.RatingUser(id, userName) - instance.push(configuration) - } - ) - ) - } - is RootScreenComponent.Child.RatingUser -> { val module = RatingUserModule.Default( empireApiModule = rootModule.empireApiModule, @@ -65,6 +38,17 @@ class RootScreenComponentChildFactory( ) ) } + + RootScreenComponent.Child.Pager -> { + DefaultRootScreenComponent.Configuration.Pager( + pagerComponent = rootModule.pagerModule.createPagerComponent( + componentContext = context, + onRootNavigation = { configuration -> + instance.push(configuration) + } + ) + ) + } } } } diff --git a/modules/features/towns/build.gradle.kts b/modules/features/towns/build.gradle.kts new file mode 100644 index 00000000..b119dc83 --- /dev/null +++ b/modules/features/towns/build.gradle.kts @@ -0,0 +1,49 @@ +@file:Suppress("UnusedPrivateMember") + +import ru.astrainteractive.gradleplugin.util.ProjectProperties.projectInfo + +plugins { + id("com.android.library") + kotlin("multiplatform") + id("ru.astrainteractive.gradleplugin.java.core") + id("ru.astrainteractive.gradleplugin.android.core") + alias(libs.plugins.kotlin.serialization) +} + +kotlin { + android() + ios() + iosSimulatorArm64() + sourceSets { + val commonMain by getting { + dependencies { + // klibs + implementation(libs.klibs.mikro.core) + implementation(libs.klibs.mikro.extensions) + api(libs.klibs.mikro.platform) + implementation(libs.klibs.kstorage) + implementation(libs.klibs.kdi) + // Decompose + api(libs.decompose.core) + api(libs.essenty) + // Moko + implementation(libs.moko.resources.core) + // Paging + implementation(libs.klibs.paging) + // Coroutines + implementation(libs.kotlin.coroutines.core) + // MVIKotlin + implementation(libs.mvikotlin) + implementation(libs.mvikotlin.main) + implementation(libs.mvikotlin.coroutines) + // Local + api(projects.modules.services.resources) + api(projects.modules.services.core) + api(projects.modules.services.apiEmpireapi) + } + } + } +} +android { + namespace = "${projectInfo.group}.feature.towns" +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt new file mode 100644 index 00000000..c9b350b2 --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt @@ -0,0 +1,8 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.data + +import ru.astrainteractive.empireapi.models.towny.TownModel +import ru.astrainteractive.klibs.paging.IntPagerCollector + +internal interface TownsRepository { + val pagingCollector: IntPagerCollector +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt new file mode 100644 index 00000000..744b150e --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt @@ -0,0 +1,32 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.data + +import com.makeevrserg.empireprojekt.mobile.api.empireapi.TownyApi +import kotlinx.coroutines.withContext +import ru.astrainteractive.empireapi.models.towny.TownModel +import ru.astrainteractive.klibs.mikro.core.dispatchers.KotlinDispatchers +import ru.astrainteractive.klibs.paging.IntPagerCollector +import ru.astrainteractive.klibs.paging.data.LambdaPagedListDataSource + +internal class TownsRepositoryImpl( + private val townyApi: TownyApi, + private val dispatchers: KotlinDispatchers +) : TownsRepository { + + private suspend fun loadPage(page: Int): Result> { + return runCatching { + withContext(dispatchers.IO) { + townyApi.towns( + page = page, + size = 10, + ).data + } + }.onFailure(Throwable::printStackTrace) + } + + override val pagingCollector = IntPagerCollector( + initialPage = 0, + pager = LambdaPagedListDataSource { + loadPage(it.pageContext.page) + } + ) +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsDependencies.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsDependencies.kt new file mode 100644 index 00000000..69dca0dd --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsDependencies.kt @@ -0,0 +1,22 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.di + +import com.makeevrserg.empireprojekt.mobile.api.empireapi.di.EmpireApiModule +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.data.TownsRepository +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.data.TownsRepositoryImpl +import ru.astrainteractive.klibs.mikro.core.dispatchers.KotlinDispatchers + +internal interface TownsDependencies { + val townsRepository: TownsRepository + + class Default( + empireApiModule: EmpireApiModule, + dispatchers: KotlinDispatchers + ) : TownsDependencies { + override val townsRepository: TownsRepository by lazy { + TownsRepositoryImpl( + townyApi = empireApiModule.townyApi, + dispatchers = dispatchers + ) + } + } +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsModule.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsModule.kt new file mode 100644 index 00000000..410e4bc4 --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/di/TownsModule.kt @@ -0,0 +1,26 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.di + +import com.arkivanov.decompose.ComponentContext +import com.makeevrserg.empireprojekt.mobile.api.empireapi.di.EmpireApiModule +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation.DefaultTownsComponent +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation.TownsComponent +import ru.astrainteractive.klibs.mikro.core.dispatchers.KotlinDispatchers + +interface TownsModule { + fun createTownsComponent(componentContext: ComponentContext): TownsComponent + class Default( + private val empireApiModule: EmpireApiModule, + private val dispatchers: KotlinDispatchers + ) : TownsModule { + override fun createTownsComponent(componentContext: ComponentContext): TownsComponent { + val dependencies = TownsDependencies.Default( + empireApiModule = empireApiModule, + dispatchers = dispatchers + ) + return DefaultTownsComponent( + componentContext = componentContext, + dependencies = dependencies + ) + } + } +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt new file mode 100644 index 00000000..03876c2c --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt @@ -0,0 +1,25 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation + +import com.arkivanov.decompose.ComponentContext +import com.arkivanov.essenty.instancekeeper.getOrCreate +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.di.TownsDependencies +import kotlinx.coroutines.flow.StateFlow + +internal class DefaultTownsComponent( + componentContext: ComponentContext, + dependencies: TownsDependencies +) : TownsComponent, ComponentContext by componentContext { + private val townsFeature = instanceKeeper.getOrCreate { + TownsFeature(dependencies) + } + override val model: StateFlow + get() = townsFeature.model + + override fun reset() { + townsFeature.reset() + } + + override fun loadNextPage() { + townsFeature.loadNextPage() + } +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt new file mode 100644 index 00000000..d631500d --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt @@ -0,0 +1,19 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation + +import kotlinx.coroutines.flow.StateFlow +import ru.astrainteractive.empireapi.models.towny.TownModel + +interface TownsComponent { + val model: StateFlow + + fun reset() + + fun loadNextPage() + + data class Model( + val items: List = emptyList(), + val isLoading: Boolean = false, + val isFailure: Boolean = false, + val isLastPage: Boolean = false + ) +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt new file mode 100644 index 00000000..5ebaf7d6 --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt @@ -0,0 +1,29 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation + +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.di.TownsDependencies +import kotlinx.coroutines.launch +import ru.astrainteractive.klibs.mikro.core.util.mapStateFlow +import ru.astrainteractive.klibs.mikro.extensions.arkivanov.CoroutineFeature + +internal class TownsFeature( + dependencies: TownsDependencies +) : CoroutineFeature by CoroutineFeature.Main(), + TownsDependencies by dependencies { + + fun loadNextPage() { + launch { townsRepository.pagingCollector.loadNextPage() } + } + + fun reset() { + townsRepository.pagingCollector.reset() + } + + val model = townsRepository.pagingCollector.state.mapStateFlow { + TownsComponent.Model( + items = it.items, + isLoading = it.isLoading, + isFailure = it.isFailure, + isLastPage = it.isLastPage + ) + } +} diff --git a/modules/features/ui/build.gradle.kts b/modules/features/ui/build.gradle.kts index 7e62195f..d6bf57fa 100644 --- a/modules/features/ui/build.gradle.kts +++ b/modules/features/ui/build.gradle.kts @@ -44,6 +44,7 @@ kotlin { implementation(projects.modules.features.root) implementation(projects.modules.features.theme) implementation(projects.modules.features.status) + implementation(projects.modules.features.towns) } } val androidMain by getting { diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt new file mode 100644 index 00000000..00fec0bb --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt @@ -0,0 +1,66 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.pager + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.arkivanov.decompose.extensions.compose.jetbrains.stack.Children +import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.fade +import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.stackAnimation +import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState +import com.makeevrserg.empireprojekt.mobile.features.root.modal.RootBottomSheetComponent +import com.makeevrserg.empireprojekt.mobile.features.root.pager.PagerComponent +import com.makeevrserg.empireprojekt.mobile.features.root.screen.RootScreenComponent +import com.makeevrserg.empireprojekt.mobile.features.ui.pager.components.PagerBottomBar +import com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.RatingUsersScreenComponent +import com.makeevrserg.empireprojekt.mobile.features.ui.status.StatusScreen +import com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns.TownsScreenComponent + +@Composable +fun PagerScreenComponent( + pagerComponent: PagerComponent, + rootScreenComponent: RootScreenComponent, + rootBottomSheetComponent: RootBottomSheetComponent, + modifier: Modifier = Modifier +) { + val childStack by pagerComponent.childStack.subscribeAsState() + val selectedIndex by pagerComponent.selectedIndex.subscribeAsState() + Scaffold( + modifier = Modifier.navigationBarsPadding(), + bottomBar = { + PagerBottomBar( + selectedIndex = selectedIndex, + onClicked = pagerComponent::select + ) + } + ) { paddingValues -> + Children( + stack = childStack, + modifier = modifier + .fillMaxSize() + .padding(paddingValues), + animation = stackAnimation(fade()) + ) { child -> + when (val instance = child.instance) { + is PagerComponent.Child.RatingUsers -> RatingUsersScreenComponent( + ratingUsersComponent = instance.ratingUsersComponent, + popComponent = rootScreenComponent + ) + + is PagerComponent.Child.Status -> StatusScreen( + themeSwitcherComponent = instance.themeSwitcherComponent, + rootStatusComponent = instance.rootStatusComponent, + rootBottomSheetComponent = rootBottomSheetComponent + ) + + is PagerComponent.Child.Towns -> TownsScreenComponent( + popComponent = rootScreenComponent, + townsComponent = instance.townsComponent + ) + } + } + } +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt new file mode 100644 index 00000000..8a8b9253 --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt @@ -0,0 +1,75 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.pager.components + +import android.annotation.SuppressLint +import androidx.compose.animation.animateColorAsState +import androidx.compose.material.BottomNavigation +import androidx.compose.material.BottomNavigationItem +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AdaptThemeFade +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.makeevrserg.empireprojekt.mobile.features.ui.pager.components.model.PagerBottomBarItem + +@Composable +internal fun PagerBottomBar(selectedIndex: Int, onClicked: (Int) -> Unit, modifier: Modifier = Modifier) { + val items = remember { + listOf( + PagerBottomBarItem.Towns, + PagerBottomBarItem.Status, + PagerBottomBarItem.Ratings + ) + } + BottomNavigation( + modifier = modifier, + backgroundColor = MaterialTheme.colors.primary, + contentColor = MaterialTheme.colors.onPrimary + ) { + items.forEachIndexed { index, item -> + val isSelected = selectedIndex == index + BottomNavigationItem( + selected = isSelected, + onClick = { + onClicked.invoke(index) + }, + icon = { + val tint by animateColorAsState( + targetValue = when { + isSelected -> AppTheme.customColors.astraYellow + else -> MaterialTheme.colors.onPrimary + }, + label = "selected tint color" + ) + Icon( + imageVector = item.icon, + contentDescription = null, + tint = tint + ) + } + ) + } + } +} + +@SuppressLint("UnusedMaterialScaffoldPaddingParameter") +@Preview +@Composable +private fun PagerBottomBarPreview() { + AdaptThemeFade { + Scaffold( + bottomBar = { + PagerBottomBar( + selectedIndex = 1, + onClicked = { + } + ) + } + ) { + } + } +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt new file mode 100644 index 00000000..9eb59967 --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt @@ -0,0 +1,13 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.pager.components.model + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Apartment +import androidx.compose.material.icons.filled.NetworkWifi +import androidx.compose.material.icons.filled.People +import androidx.compose.ui.graphics.vector.ImageVector + +internal sealed class PagerBottomBarItem(val icon: ImageVector) { + data object Towns : PagerBottomBarItem(icon = Icons.Filled.Apartment) + data object Status : PagerBottomBarItem(icon = Icons.Filled.NetworkWifi) + data object Ratings : PagerBottomBarItem(icon = Icons.Filled.People) +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt index cb08caf3..cc10a8df 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/user/components/RatingUserWidget.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -16,7 +15,6 @@ import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Cookie import androidx.compose.material.icons.filled.ThumbDown import androidx.compose.material.icons.filled.ThumbUp import androidx.compose.runtime.Composable @@ -25,11 +23,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import coil.compose.SubcomposeAsyncImage import com.makeevrserg.empireprojekt.mobile.core.ui.asComposableString import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.components.PlayerHeadBox import com.makeevrserg.empireprojekt.mobile.resources.MR -import com.valentinilk.shimmer.shimmer import ru.astrainteractive.empireapi.models.rating.RatingModel @Composable @@ -47,28 +44,11 @@ fun RatingUserWidget(ratingModel: RatingModel) { horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.S), modifier = Modifier.padding(horizontal = AppTheme.dimens.S) ) { - SubcomposeAsyncImage( - model = "https://mc-heads.net/avatar/${ratingModel.userCreatedReport?.minecraftUUID}", - contentDescription = null, + PlayerHeadBox( + uuid = ratingModel.userCreatedReport?.minecraftUUID.orEmpty(), modifier = Modifier .size(32.dp) .clip(RoundedCornerShape(AppTheme.dimens.XXS)), - loading = { - Box( - modifier = Modifier - .fillMaxSize() - .shimmer() - .background(MaterialTheme.colors.primaryVariant) - .clip(RoundedCornerShape(AppTheme.dimens.XXS)) - ) - }, - error = { - Icon( - imageVector = Icons.Filled.Cookie, - contentDescription = null, - tint = MaterialTheme.colors.onPrimary - ) - } ) Text( text = ratingModel.userCreatedReport?.minecraftName ?: "-", diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/RatingUsersScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/RatingUsersScreenComponent.kt index aab95cc7..2a6cb6f3 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/RatingUsersScreenComponent.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/RatingUsersScreenComponent.kt @@ -1,7 +1,6 @@ package com.makeevrserg.empireprojekt.mobile.features.ui.rating.users import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -42,7 +41,7 @@ fun RatingUsersScreenComponent( } ) { LazyColumn( - modifier = Modifier.padding(horizontal = AppTheme.dimens.XS).navigationBarsPadding(), + modifier = Modifier.padding(horizontal = AppTheme.dimens.XS), verticalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS), contentPadding = it, state = lazyListState diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/PlayerHeadBox.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/PlayerHeadBox.kt new file mode 100644 index 00000000..7079a68e --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/PlayerHeadBox.kt @@ -0,0 +1,41 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Cookie +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import coil.compose.SubcomposeAsyncImage +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.valentinilk.shimmer.shimmer + +@Composable +fun PlayerHeadBox(uuid: String, modifier: Modifier = Modifier) { + SubcomposeAsyncImage( + model = "https://mc-heads.net/avatar/$uuid", + contentDescription = null, + modifier = modifier, + loading = { + Box( + modifier = Modifier + .fillMaxSize() + .shimmer() + .background(MaterialTheme.colors.primaryVariant) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)) + ) + }, + error = { + Icon( + imageVector = Icons.Filled.Cookie, + contentDescription = null, + tint = MaterialTheme.colors.onPrimary + ) + } + ) +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt index f0533b89..7f08313e 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/rating/users/components/RatingUserWidget.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -17,7 +16,6 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChevronRight -import androidx.compose.material.icons.filled.Cookie import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -27,13 +25,11 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import coil.compose.SubcomposeAsyncImage import com.makeevrserg.empireprojekt.mobile.core.ui.asComposableString import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AdaptThemeFade import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme import com.makeevrserg.empireprojekt.mobile.core.ui.theme.ComposeTheme import com.makeevrserg.empireprojekt.mobile.resources.MR -import com.valentinilk.shimmer.shimmer import ru.astrainteractive.empireapi.models.rating.RatingUserModel @Composable @@ -54,28 +50,11 @@ fun RatingUserWidget( modifier = Modifier.padding(vertical = AppTheme.dimens.XS, horizontal = AppTheme.dimens.S), horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS) ) { - SubcomposeAsyncImage( - model = "https://mc-heads.net/avatar/${model.minecraftUUID}", - contentDescription = null, + PlayerHeadBox( + uuid = model.minecraftUUID, modifier = Modifier .size(32.dp) .clip(RoundedCornerShape(AppTheme.dimens.XXS)), - loading = { - Box( - modifier = Modifier - .fillMaxSize() - .shimmer() - .background(MaterialTheme.colors.primaryVariant) - .clip(RoundedCornerShape(AppTheme.dimens.XXS)) - ) - }, - error = { - Icon( - imageVector = Icons.Filled.Cookie, - contentDescription = null, - tint = MaterialTheme.colors.onPrimary - ) - } ) Column { Text( diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/root/ApplicationContent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/root/ApplicationContent.kt index dc6a3b5e..ad3ddb6a 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/root/ApplicationContent.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/root/ApplicationContent.kt @@ -10,10 +10,9 @@ import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.stac import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState import com.makeevrserg.empireprojekt.mobile.features.root.RootComponent import com.makeevrserg.empireprojekt.mobile.features.root.screen.DefaultRootScreenComponent +import com.makeevrserg.empireprojekt.mobile.features.ui.pager.PagerScreenComponent import com.makeevrserg.empireprojekt.mobile.features.ui.rating.user.RatingUserScreenComponent -import com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.RatingUsersScreenComponent import com.makeevrserg.empireprojekt.mobile.features.ui.splash.SplashScreenComponent -import com.makeevrserg.empireprojekt.mobile.features.ui.status.StatusScreen @Composable fun ApplicationContent( @@ -33,21 +32,16 @@ fun ApplicationContent( splashComponent = screen.splashComponent ) - is DefaultRootScreenComponent.Configuration.Status -> StatusScreen( - rootComponent = rootComponent, - themeSwitcherComponent = screen.themeSwitcherComponent, - rootStatusComponent = screen.rootStatusComponent - ) - - is DefaultRootScreenComponent.Configuration.RatingUsers -> RatingUsersScreenComponent( - ratingUsersComponent = screen.ratingUsersComponent, - popComponent = rootComponent.rootScreenComponent - ) - is DefaultRootScreenComponent.Configuration.RatingUser -> RatingUserScreenComponent( ratingUserComponent = screen.ratingUserComponent, popComponent = rootComponent.rootScreenComponent ) + + is DefaultRootScreenComponent.Configuration.Pager -> PagerScreenComponent( + pagerComponent = screen.pagerComponent, + rootBottomSheetComponent = rootComponent.rootBottomSheetComponent, + rootScreenComponent = rootComponent.rootScreenComponent + ) } } } diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/splash/SplashScreen.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/splash/SplashScreen.kt index 24f90f1f..4e55fdfe 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/splash/SplashScreen.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/splash/SplashScreen.kt @@ -31,7 +31,7 @@ fun SplashScreenComponent( splashComponent.screenChannelFlow.collectLatest { when (it) { is SplashComponent.Label.InitialLaunch -> { - rootComponent.rootScreenComponent.replaceCurrent(RootScreenComponent.Child.Status) + rootComponent.rootScreenComponent.replaceCurrent(RootScreenComponent.Child.Pager) } } } diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/status/StatusScreen.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/status/StatusScreen.kt index 93241e6b..afd1225e 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/status/StatusScreen.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/status/StatusScreen.kt @@ -18,14 +18,10 @@ import androidx.compose.material.icons.filled.WbSunny import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import com.makeevrserg.empireprojekt.mobile.core.ui.asComposableString -import com.makeevrserg.empireprojekt.mobile.core.ui.components.RowSettingChevronItem -import com.makeevrserg.empireprojekt.mobile.core.ui.components.navBarsPadding import com.makeevrserg.empireprojekt.mobile.core.ui.components.topbar.AstraCenterAlignedTopAppBar import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme -import com.makeevrserg.empireprojekt.mobile.features.root.RootComponent -import com.makeevrserg.empireprojekt.mobile.features.root.screen.RootScreenComponent +import com.makeevrserg.empireprojekt.mobile.features.root.modal.RootBottomSheetComponent import com.makeevrserg.empireprojekt.mobile.features.status.root.RootStatusComponent import com.makeevrserg.empireprojekt.mobile.features.theme.ThemeSwitcherComponent import com.makeevrserg.empireprojekt.mobile.features.theme.data.model.Theme @@ -36,7 +32,7 @@ import ru.astrainteractive.klibs.mikro.core.util.next @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable fun StatusScreen( - rootComponent: RootComponent, + rootBottomSheetComponent: RootBottomSheetComponent, themeSwitcherComponent: ThemeSwitcherComponent, rootStatusComponent: RootStatusComponent, ) { @@ -61,10 +57,9 @@ fun StatusScreen( }, floatingActionButton = { FloatingActionButton( - modifier = Modifier.navBarsPadding(), backgroundColor = MaterialTheme.colors.secondaryVariant, onClick = { - rootComponent.rootBottomSheetComponent.showInfoSheet() + rootBottomSheetComponent.showInfoSheet() }, ) { Icon( @@ -86,17 +81,6 @@ fun StatusScreen( color = MaterialTheme.colors.onPrimary.copy(alpha = .5f) ) } - item { - RowSettingChevronItem( - icon = MR.images.ic_splash, - text = MR.strings.statuses_ratings.asComposableString(), - tint = Color.Unspecified, - onClick = { - val configuration = RootScreenComponent.Child.RatingUsers - rootComponent.rootScreenComponent.push(configuration) - } - ) - } items(rootStatusComponent.statusComponents) { StatusWidget(it) } diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt new file mode 100644 index 00000000..4d249aa5 --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt @@ -0,0 +1,73 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import com.makeevrserg.empireprojekt.mobile.core.ui.components.OnEndReached +import com.makeevrserg.empireprojekt.mobile.core.ui.components.PagingWidget +import com.makeevrserg.empireprojekt.mobile.core.ui.components.topbar.AstraCenterAlignedTopAppBar +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation.TownsComponent +import com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns.components.TownCard +import com.makeevrserg.empireprojekt.mobile.services.core.PopComponent + +@Composable +fun TownsScreenComponent( + popComponent: PopComponent, + townsComponent: TownsComponent +) { + val model by townsComponent.model.collectAsState() + val lazyListState = rememberLazyListState() + lazyListState.OnEndReached { + townsComponent.loadNextPage() + } + + Scaffold( + modifier = Modifier, + topBar = { + AstraCenterAlignedTopAppBar( + title = "Towns", + popComponent = popComponent + ) + } + ) { + LazyColumn( + modifier = Modifier + .padding(horizontal = AppTheme.dimens.XS) + .navigationBarsPadding(), + verticalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS), + contentPadding = it, + state = lazyListState + ) { + items(model.items) { townModel -> + TownCard( + mayor = townModel.mayor, + townName = townModel.name, + board = townModel.townBoard, + founder = townModel.founder, + nation = townModel.nation + ) + } + + item { + PagingWidget.Auto( + list = model.items, + isLastPage = model.isLastPage, + isLoading = model.isLoading, + isFailure = model.isFailure, + onReload = { + townsComponent.reset() + } + ) + } + } + } +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt new file mode 100644 index 00000000..2661fddc --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt @@ -0,0 +1,101 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.makeevrserg.empireprojekt.mobile.core.ui.components.RowText +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AdaptThemeFade +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.ComposeTheme +import com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.components.PlayerHeadBox + +@Composable +fun TownCard( + mayor: String, + townName: String, + board: String, + founder: String, + nation: String +) { + Column( + modifier = Modifier + .clip(RoundedCornerShape(AppTheme.dimens.XS)) + .background(MaterialTheme.colors.primary) + .padding( + vertical = AppTheme.dimens.XS, + horizontal = AppTheme.dimens.S + ), + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS) + ) { + PlayerHeadBox( + uuid = mayor, + modifier = Modifier + .size(32.dp) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)), + ) + Text( + text = mayor, + style = MaterialTheme.typography.h6, + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.Center + ) + } + Text( + text = townName, + style = MaterialTheme.typography.h5, + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.Center + ) + if (board.isNotBlank()) { + Text( + text = board, + style = MaterialTheme.typography.subtitle1, + color = MaterialTheme.colors.onPrimary, + ) + } + RowText( + title = "Founder:", + desc = founder, + modifier = Modifier.fillMaxWidth() + ) + RowText( + title = "Nation:", + desc = nation, + modifier = Modifier.fillMaxWidth() + ) + } +} + +@Preview +@Composable +private fun TownCardPreview() { + AdaptThemeFade(composeTheme = ComposeTheme.DARK) { + Box(modifier = Modifier.background(MaterialTheme.colors.primaryVariant)) { + TownCard( + mayor = "RomaRoman", + townName = "Rostov", + board = "Международный контролирующий орган по борьбе с пивом", + founder = "cinnamonrein", + nation = "NCR" + ) + } + } +} diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt new file mode 100644 index 00000000..50a419b5 --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt @@ -0,0 +1,11 @@ +package com.makeevrserg.empireprojekt.mobile.api.empireapi + +import ru.astrainteractive.empireapi.models.response.GenericPagedModel +import ru.astrainteractive.empireapi.models.towny.TownModel + +interface TownyApi { + /** + * Fetch all towns + */ + suspend fun towns(page: Int, size: Int): GenericPagedModel +} diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/di/EmpireApiModule.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/di/EmpireApiModule.kt index 8f42dd70..14b8d18b 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/di/EmpireApiModule.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/di/EmpireApiModule.kt @@ -1,17 +1,23 @@ package com.makeevrserg.empireprojekt.mobile.api.empireapi.di import com.makeevrserg.empireprojekt.mobile.api.empireapi.RatingApi +import com.makeevrserg.empireprojekt.mobile.api.empireapi.TownyApi import com.makeevrserg.empireprojekt.mobile.api.empireapi.impl.RatingApiImpl +import com.makeevrserg.empireprojekt.mobile.api.empireapi.impl.TownyApiImpl import io.ktor.client.HttpClient import ru.astrainteractive.klibs.kdi.Provider import ru.astrainteractive.klibs.kdi.getValue interface EmpireApiModule { val ratingApi: RatingApi + val townyApi: TownyApi class Default(httpClient: HttpClient) : EmpireApiModule { override val ratingApi: RatingApi by Provider { RatingApiImpl(httpClient = httpClient) } + override val townyApi: TownyApi by Provider { + TownyApiImpl(httpClient = httpClient) + } } } diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt index 112bd53c..497c1884 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt @@ -18,7 +18,7 @@ import ru.astrainteractive.empireapi.models.response.GenericPagedModel class RatingApiImpl( private val httpClient: HttpClient, - private val baseUrl: String = "http://astralearner.empireprojekt.ru:8086" + private val baseUrl: String = "http://192.168.1.2:8080" ) : RatingApi { override suspend fun users(page: Int, size: Int, body: RatingListRequest): GenericPagedModel { diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt new file mode 100644 index 00000000..cc6a5659 --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt @@ -0,0 +1,30 @@ +package com.makeevrserg.empireprojekt.mobile.api.empireapi.impl + +import com.makeevrserg.empireprojekt.mobile.api.empireapi.TownyApi +import io.ktor.client.HttpClient +import io.ktor.client.call.body +import io.ktor.client.request.get +import io.ktor.client.request.parameter +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.client.request.url +import io.ktor.http.ContentType +import io.ktor.http.contentType +import ru.astrainteractive.empireapi.models.response.GenericPagedModel +import ru.astrainteractive.empireapi.models.towny.TownModel + +class TownyApiImpl( + private val httpClient: HttpClient, + private val baseUrl: String = "http://192.168.1.2:8080" +) : TownyApi { + + override suspend fun towns(page: Int, size: Int): GenericPagedModel { + return httpClient.post { + url("$baseUrl/towny/towns") + parameter("page", page) + parameter("size", size) + contentType(ContentType.Application.Json) + setBody(body) + }.body() + } +} diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/NationModel.kt b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/NationModel.kt new file mode 100644 index 00000000..8cdc16ad --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/NationModel.kt @@ -0,0 +1,16 @@ +package ru.astrainteractive.empireapi.models.towny + +import kotlinx.serialization.Serializable + +@Serializable +data class NationModel( + val name: String, + val capital: String, + val tag: String, + val allies: List, + val enemies: List, + val registered: Long, + val nationBoard: String, + val isOpen: Boolean, + val isPublic: Boolean +) diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt new file mode 100644 index 00000000..37efd9f5 --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt @@ -0,0 +1,19 @@ +package ru.astrainteractive.empireapi.models.towny + +import kotlinx.serialization.Serializable + +@Serializable +class TownModel( + val name: String, + val mayor: String, + val nation: String, + val townBoard: String, + val tag: String, + val founder: String, + val hasUpkeep: Boolean, + val open: Boolean, + val public: Boolean, + val outlaws: List, + val registered: Long, + val ruined: Boolean, +) diff --git a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt index 8e4c11ca..2cc1d976 100644 --- a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt +++ b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt @@ -65,3 +65,31 @@ fun RowSettingItem( postfix?.invoke(this) } } + +@Composable +fun RowText( + title: String, + desc: String, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = title, + color = MaterialTheme.colors.onPrimary.copy(0.5f), + textAlign = TextAlign.Start, + modifier = Modifier, + style = MaterialTheme.typography.subtitle1, + ) + Text( + text = desc, + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.End, + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.subtitle1 + ) + } +} diff --git a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/theme/ThemeAdapt.kt b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/theme/ThemeAdapt.kt index a088bc6d..5187dda7 100644 --- a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/theme/ThemeAdapt.kt +++ b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/theme/ThemeAdapt.kt @@ -29,7 +29,7 @@ private fun Material2ThemeAdapt(theme: Material2Theme, content: @Composable () - @Composable fun AdaptThemeFade( - composeTheme: ComposeTheme, + composeTheme: ComposeTheme = ComposeTheme.DARK, content: @Composable () -> Unit ) { val appTheme = when (composeTheme) { diff --git a/modules/services/resources/src/commonMain/resources/MR/base/strings.xml b/modules/services/resources/src/commonMain/resources/MR/base/strings.xml index 1431e209..fbb6e492 100644 --- a/modules/services/resources/src/commonMain/resources/MR/base/strings.xml +++ b/modules/services/resources/src/commonMain/resources/MR/base/strings.xml @@ -8,6 +8,7 @@ Рейтинги + Города Ничего больше нет Тут ничего нет diff --git a/settings.gradle.kts b/settings.gradle.kts index 05cdfae3..d3b04efd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,5 +37,5 @@ include(":modules:features:splash") include(":modules:features:ui") include(":modules:features:theme") include(":modules:features:status") - include(":modules:features:rating") +include(":modules:features:towns") From 58fc5381f5cc24c8f8affdfc56d00fab33684e50 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 14:31:21 +0300 Subject: [PATCH 3/9] feature: more town info --- gradle/libs.versions.toml | 1 + modules/features/ui/build.gradle.kts | 3 + .../ui/towny/towns/TownsScreenComponent.kt | 7 +- .../ui/towny/towns/components/TownCard.kt | 101 +++++++++++++++--- .../empireapi/models/towny/TownModel.kt | 1 + .../core/ui/components/RowSettingItem.kt | 9 +- 6 files changed, 103 insertions(+), 19 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 73e68e3d..ea3231ca 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -131,6 +131,7 @@ decompose-android = { module = "com.arkivanov.decompose:extensions-android", ver essenty = { module = "com.arkivanov.essenty:lifecycle", version.ref = "essenty" } # Kotlin kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin-version" } +kotlin-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.strictly = "0.4.0" } kotlin-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" } kotlin-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlin-coroutines" } kotlin-coroutines-javafx = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-javafx", version.ref = "kotlin-coroutines" } diff --git a/modules/features/ui/build.gradle.kts b/modules/features/ui/build.gradle.kts index d6bf57fa..d215c293 100644 --- a/modules/features/ui/build.gradle.kts +++ b/modules/features/ui/build.gradle.kts @@ -29,8 +29,11 @@ kotlin { // klibs implementation(libs.klibs.mikro.core) implementation(libs.klibs.mikro.platform) + implementation(libs.klibs.mikro.extensions) implementation(libs.klibs.kstorage) implementation(libs.klibs.kdi) + // Kotlin + implementation(libs.kotlin.datetime) // Moko implementation(libs.moko.resources.core) // Decompose diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt index 4d249aa5..8d09a876 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt @@ -53,7 +53,12 @@ fun TownsScreenComponent( townName = townModel.name, board = townModel.townBoard, founder = townModel.founder, - nation = townModel.nation + nation = townModel.nation, + outlawsAmount = townModel.outlaws.size, + tag = townModel.tag, + registered = townModel.registered, + residentsCount = townModel.residentsCount, + isOpen = townModel.open ) } diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt index 2661fddc..f90afd96 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownCard.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -23,6 +24,9 @@ import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AdaptThemeFade import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme import com.makeevrserg.empireprojekt.mobile.core.ui.theme.ComposeTheme import com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.components.PlayerHeadBox +import kotlinx.datetime.Instant +import ru.astrainteractive.klibs.mikro.extensions.JvmTimeFormatter +import ru.astrainteractive.klibs.mikro.extensions.TimeFormatter @Composable fun TownCard( @@ -30,8 +34,14 @@ fun TownCard( townName: String, board: String, founder: String, - nation: String + nation: String, + outlawsAmount: Int, + tag: String, + registered: Long, + residentsCount: Long, + isOpen: Boolean ) { + val timeFormatter: TimeFormatter = JvmTimeFormatter() Column( modifier = Modifier .clip(RoundedCornerShape(AppTheme.dimens.XS)) @@ -43,19 +53,36 @@ fun TownCard( ) { Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS) + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() ) { - PlayerHeadBox( - uuid = mayor, - modifier = Modifier - .size(32.dp) - .clip(RoundedCornerShape(AppTheme.dimens.XXS)), - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS) + ) { + PlayerHeadBox( + uuid = mayor, + modifier = Modifier + .size(32.dp) + .clip(RoundedCornerShape(AppTheme.dimens.XXS)), + ) + Text( + text = mayor, + style = MaterialTheme.typography.h6, + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.Center + ) + } Text( - text = mayor, - style = MaterialTheme.typography.h6, - color = MaterialTheme.colors.onPrimary, - textAlign = TextAlign.Center + text = residentsCount.toString(), + style = MaterialTheme.typography.subtitle2, + color = MaterialTheme.colors.primary, + textAlign = TextAlign.Center, + modifier = Modifier + .clip(RoundedCornerShape(AppTheme.dimens.XS)) + .background(AppTheme.customColors.astraYellow) + .padding(horizontal = AppTheme.dimens.XS) + .padding(vertical = AppTheme.dimens.XXS) ) } Text( @@ -71,14 +98,53 @@ fun TownCard( color = MaterialTheme.colors.onPrimary, ) } + RowText( + title = "Tag:", + desc = tag, + modifier = Modifier.fillMaxWidth() + ) RowText( title = "Founder:", desc = founder, modifier = Modifier.fillMaxWidth() ) + if (nation.isNotBlank()) { + RowText( + title = "Nation:", + desc = nation, + modifier = Modifier.fillMaxWidth() + ) + } + if (outlawsAmount > 0) { + RowText( + title = "Outlaws count:", + desc = outlawsAmount.toString(), + modifier = Modifier.fillMaxWidth() + ) + } + + RowText( + title = "Registered:", + desc = remember { + timeFormatter.format( + instant = Instant.fromEpochMilliseconds(registered), + format = "dd.MM.yyyy" + ) + }, + modifier = Modifier.fillMaxWidth() + ) RowText( - title = "Nation:", - desc = nation, + title = "Enterance:", + desc = remember { + when (isOpen) { + true -> "Public" + false -> "Private" + } + }, + descColor = when (isOpen) { + true -> AppTheme.customColors.colorPositive + false -> AppTheme.customColors.colorNegative + }, modifier = Modifier.fillMaxWidth() ) } @@ -94,7 +160,12 @@ private fun TownCardPreview() { townName = "Rostov", board = "Международный контролирующий орган по борьбе с пивом", founder = "cinnamonrein", - nation = "NCR" + nation = "NCR", + outlawsAmount = 1, + tag = "NCR", + registered = 1706549308031, + residentsCount = 10, + isOpen = true ) } } diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt index 37efd9f5..6018c2e7 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownModel.kt @@ -16,4 +16,5 @@ class TownModel( val outlaws: List, val registered: Long, val ruined: Boolean, + val residentsCount: Long ) diff --git a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt index 2cc1d976..319a4a8b 100644 --- a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt +++ b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt @@ -10,6 +10,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme @@ -70,7 +71,9 @@ fun RowSettingItem( fun RowText( title: String, desc: String, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + titleColor: Color = MaterialTheme.colors.onPrimary.copy(0.5f), + descColor: Color = MaterialTheme.colors.onPrimary ) { Row( modifier = modifier, @@ -79,14 +82,14 @@ fun RowText( ) { Text( text = title, - color = MaterialTheme.colors.onPrimary.copy(0.5f), + color = titleColor, textAlign = TextAlign.Start, modifier = Modifier, style = MaterialTheme.typography.subtitle1, ) Text( text = desc, - color = MaterialTheme.colors.onPrimary, + color = descColor, textAlign = TextAlign.End, modifier = Modifier.weight(1f), style = MaterialTheme.typography.subtitle1 From efd2cba9c849d53a8b15ed1ebcda56a3f8c25792 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 16:37:38 +0300 Subject: [PATCH 4/9] feat: town filtering --- .../towny/towns/data/TownsRepository.kt | 4 +- .../towny/towns/data/TownsRepositoryImpl.kt | 10 +- .../towns/data/paging/TownyPageContext.kt | 15 ++ .../towns/data/paging/TownyPagingCollector.kt | 25 ++++ .../presentation/DefaultTownsComponent.kt | 14 ++ .../towns/presentation/TownsComponent.kt | 10 ++ .../towny/towns/presentation/TownsFeature.kt | 42 +++++- .../towny/towns/util/TownPublicTypeExt.kt | 13 ++ .../towny/towns/util/TownSortByExt.kt | 23 +++ .../ui/towny/towns/TownsScreenComponent.kt | 8 ++ .../towny/towns/components/TownFilterCard.kt | 88 ++++++++++++ .../mobile/api/empireapi/TownyApi.kt | 3 +- .../mobile/api/empireapi/impl/TownyApiImpl.kt | 5 +- .../empireapi/models/towny/TownPublicType.kt | 5 + .../empireapi/models/towny/TownSortBy.kt | 17 +++ .../empireapi/models/towny/TownsFilter.kt | 10 ++ .../core/ui/components/RowSettingItem.kt | 131 ++++++++++++++++++ 17 files changed, 413 insertions(+), 10 deletions(-) create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPageContext.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPagingCollector.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownPublicTypeExt.kt create mode 100644 modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownSortByExt.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownFilterCard.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownPublicType.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownSortBy.kt create mode 100644 modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownsFilter.kt diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt index c9b350b2..93cb97a0 100644 --- a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepository.kt @@ -1,8 +1,8 @@ package com.makeevrserg.empireprojekt.mobile.features.towny.towns.data +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.data.paging.TownyPagingCollector import ru.astrainteractive.empireapi.models.towny.TownModel -import ru.astrainteractive.klibs.paging.IntPagerCollector internal interface TownsRepository { - val pagingCollector: IntPagerCollector + val pagingCollector: TownyPagingCollector } diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt index 744b150e..9f1bd881 100644 --- a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/TownsRepositoryImpl.kt @@ -1,10 +1,11 @@ package com.makeevrserg.empireprojekt.mobile.features.towny.towns.data import com.makeevrserg.empireprojekt.mobile.api.empireapi.TownyApi +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.data.paging.TownyPagingCollector import kotlinx.coroutines.withContext import ru.astrainteractive.empireapi.models.towny.TownModel +import ru.astrainteractive.empireapi.models.towny.TownsFilter import ru.astrainteractive.klibs.mikro.core.dispatchers.KotlinDispatchers -import ru.astrainteractive.klibs.paging.IntPagerCollector import ru.astrainteractive.klibs.paging.data.LambdaPagedListDataSource internal class TownsRepositoryImpl( @@ -12,21 +13,22 @@ internal class TownsRepositoryImpl( private val dispatchers: KotlinDispatchers ) : TownsRepository { - private suspend fun loadPage(page: Int): Result> { + private suspend fun loadPage(page: Int, filter: TownsFilter): Result> { return runCatching { withContext(dispatchers.IO) { townyApi.towns( page = page, size = 10, + filter = filter ).data } }.onFailure(Throwable::printStackTrace) } - override val pagingCollector = IntPagerCollector( + override val pagingCollector = TownyPagingCollector( initialPage = 0, pager = LambdaPagedListDataSource { - loadPage(it.pageContext.page) + loadPage(it.pageContext.page, it.pageContext.filter) } ) } diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPageContext.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPageContext.kt new file mode 100644 index 00000000..e408842f --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPageContext.kt @@ -0,0 +1,15 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.data.paging + +import ru.astrainteractive.empireapi.models.towny.TownsFilter +import ru.astrainteractive.klibs.paging.context.PageContext + +internal data class TownyPageContext( + val page: Int = 0, + val filter: TownsFilter = TownsFilter() +) : PageContext { + object Factory : PageContext.Factory { + override fun next(pageContext: TownyPageContext): TownyPageContext { + return pageContext.copy(page = pageContext.page + 1) + } + } +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPagingCollector.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPagingCollector.kt new file mode 100644 index 00000000..2e5c20e4 --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/data/paging/TownyPagingCollector.kt @@ -0,0 +1,25 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.data.paging + +import ru.astrainteractive.empireapi.models.towny.TownsFilter +import ru.astrainteractive.klibs.paging.DefaultPagingCollector +import ru.astrainteractive.klibs.paging.PagingCollector +import ru.astrainteractive.klibs.paging.data.PagedListDataSource +import ru.astrainteractive.klibs.paging.state.PagingState + +internal class TownyPagingCollector( + private val initialPage: Int = 0, + private val pageSize: Int = 10, + private val pager: PagedListDataSource, + private val initialFilter: TownsFilter = TownsFilter() +) : PagingCollector by DefaultPagingCollector( + initialPagingState = PagingState( + pageContext = TownyPageContext(page = initialPage, filter = initialFilter), + pageSizeAtLeast = pageSize, + isLastPage = false, + isLoading = false, + isFailure = false, + items = emptyList() + ), + pager = pager, + pageContextFactory = TownyPageContext.Factory +) diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt index 03876c2c..d8b6416f 100644 --- a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/DefaultTownsComponent.kt @@ -4,6 +4,8 @@ import com.arkivanov.decompose.ComponentContext import com.arkivanov.essenty.instancekeeper.getOrCreate import com.makeevrserg.empireprojekt.mobile.features.towny.towns.di.TownsDependencies import kotlinx.coroutines.flow.StateFlow +import ru.astrainteractive.empireapi.models.towny.TownPublicType +import ru.astrainteractive.empireapi.models.towny.TownSortBy internal class DefaultTownsComponent( componentContext: ComponentContext, @@ -22,4 +24,16 @@ internal class DefaultTownsComponent( override fun loadNextPage() { townsFeature.loadNextPage() } + + override fun updateQuery(query: String) { + townsFeature.updateQuery(query) + } + + override fun selectPublicType(townPublicType: TownPublicType) { + townsFeature.selectPublicType(townPublicType) + } + + override fun selectSortType(townSortBy: TownSortBy) { + townsFeature.selectSortType(townSortBy) + } } diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt index d631500d..4f9514eb 100644 --- a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsComponent.kt @@ -2,6 +2,9 @@ package com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation import kotlinx.coroutines.flow.StateFlow import ru.astrainteractive.empireapi.models.towny.TownModel +import ru.astrainteractive.empireapi.models.towny.TownPublicType +import ru.astrainteractive.empireapi.models.towny.TownSortBy +import ru.astrainteractive.empireapi.models.towny.TownsFilter interface TownsComponent { val model: StateFlow @@ -10,8 +13,15 @@ interface TownsComponent { fun loadNextPage() + fun updateQuery(query: String) + + fun selectPublicType(townPublicType: TownPublicType) + + fun selectSortType(townSortBy: TownSortBy) + data class Model( val items: List = emptyList(), + val filter: TownsFilter, val isLoading: Boolean = false, val isFailure: Boolean = false, val isLastPage: Boolean = false diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt index 5ebaf7d6..e9f07e2c 100644 --- a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/presentation/TownsFeature.kt @@ -2,8 +2,12 @@ package com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation import com.makeevrserg.empireprojekt.mobile.features.towny.towns.di.TownsDependencies import kotlinx.coroutines.launch +import ru.astrainteractive.empireapi.models.towny.TownPublicType +import ru.astrainteractive.empireapi.models.towny.TownSortBy +import ru.astrainteractive.empireapi.models.towny.TownsFilter import ru.astrainteractive.klibs.mikro.core.util.mapStateFlow import ru.astrainteractive.klibs.mikro.extensions.arkivanov.CoroutineFeature +import ru.astrainteractive.klibs.paging.PagingCollectorExt.submitList internal class TownsFeature( dependencies: TownsDependencies @@ -18,12 +22,48 @@ internal class TownsFeature( townsRepository.pagingCollector.reset() } + private fun updateFilter(buildFilter: (TownsFilter) -> TownsFilter) { + townsRepository.pagingCollector.submitList(emptyList()) + townsRepository.pagingCollector.update { state -> + state.copy( + pageContext = state.pageContext.copy( + page = 0, + filter = buildFilter.invoke(state.pageContext.filter) + ), + items = emptyList(), + isLoading = false, + isFailure = false, + isLastPage = false + ) + } + loadNextPage() + } + + fun updateQuery(query: String) { + updateFilter { filter -> + filter.copy(query = query) + } + } + + fun selectPublicType(townPublicType: TownPublicType) { + updateFilter { filter -> + filter.copy(publicType = townPublicType) + } + } + + fun selectSortType(townSortBy: TownSortBy) { + updateFilter { filter -> + filter.copy(sortBy = townSortBy) + } + } + val model = townsRepository.pagingCollector.state.mapStateFlow { TownsComponent.Model( items = it.items, isLoading = it.isLoading, isFailure = it.isFailure, - isLastPage = it.isLastPage + isLastPage = it.isLastPage, + filter = it.pageContext.filter ) } } diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownPublicTypeExt.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownPublicTypeExt.kt new file mode 100644 index 00000000..a03c5c7a --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownPublicTypeExt.kt @@ -0,0 +1,13 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.util + +import dev.icerock.moko.resources.desc.Raw +import dev.icerock.moko.resources.desc.StringDesc +import ru.astrainteractive.empireapi.models.towny.TownPublicType + +object TownPublicTypeExt { + fun TownPublicType.toStringDesc() = when (this) { + TownPublicType.NONE -> StringDesc.Raw("None") + TownPublicType.PUBLIC -> StringDesc.Raw("Public") + TownPublicType.PRIVATE -> StringDesc.Raw("Private") + } +} diff --git a/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownSortByExt.kt b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownSortByExt.kt new file mode 100644 index 00000000..ac29b694 --- /dev/null +++ b/modules/features/towns/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/towny/towns/util/TownSortByExt.kt @@ -0,0 +1,23 @@ +package com.makeevrserg.empireprojekt.mobile.features.towny.towns.util + +import dev.icerock.moko.resources.desc.Raw +import dev.icerock.moko.resources.desc.StringDesc +import ru.astrainteractive.empireapi.models.towny.TownSortBy + +object TownSortByExt { + fun TownSortBy.toStringDesc() = when (this) { + TownSortBy.NONE -> StringDesc.Raw("None") + TownSortBy.NAME_ASC -> StringDesc.Raw("Name (asc)") + TownSortBy.NAME_DESC -> StringDesc.Raw("Name (desc)") + TownSortBy.TAG_ASC -> StringDesc.Raw("Tag (asc)") + TownSortBy.TAG_DESC -> StringDesc.Raw("Tag (desc)") + TownSortBy.FOUNDER_ASC -> StringDesc.Raw("Founder (asc)") + TownSortBy.FOUNDER_DESC -> StringDesc.Raw("Founder (desc)") + TownSortBy.NATION_ASC -> StringDesc.Raw("Nation (asc)") + TownSortBy.NATION_DESC -> StringDesc.Raw("Nation (desc)") + TownSortBy.DATE_ASC -> StringDesc.Raw("Date (asc)") + TownSortBy.DATE_DESC -> StringDesc.Raw("Date (desc)") + TownSortBy.RESIDENTS_ASC -> StringDesc.Raw("Residents (asc)") + TownSortBy.RESIDENTS_DESC -> StringDesc.Raw("Residents (desc)") + } +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt index 8d09a876..8865f9f1 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/TownsScreenComponent.kt @@ -17,6 +17,7 @@ import com.makeevrserg.empireprojekt.mobile.core.ui.components.topbar.AstraCente import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme import com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation.TownsComponent import com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns.components.TownCard +import com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns.components.TownFilterCard import com.makeevrserg.empireprojekt.mobile.services.core.PopComponent @Composable @@ -47,6 +48,13 @@ fun TownsScreenComponent( contentPadding = it, state = lazyListState ) { + item { + TownFilterCard( + townsFilter = model.filter, + onSortSelected = townsComponent::selectSortType, + onPublicSelected = townsComponent::selectPublicType + ) + } items(model.items) { townModel -> TownCard( mayor = townModel.mayor, diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownFilterCard.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownFilterCard.kt new file mode 100644 index 00000000..1a50bbda --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/towny/towns/components/TownFilterCard.kt @@ -0,0 +1,88 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.towny.towns.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +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.shape.RoundedCornerShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import com.makeevrserg.empireprojekt.mobile.core.ui.asComposableString +import com.makeevrserg.empireprojekt.mobile.core.ui.components.RowDropdownText +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AdaptThemeFade +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.ComposeTheme +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.util.TownPublicTypeExt.toStringDesc +import com.makeevrserg.empireprojekt.mobile.features.towny.towns.util.TownSortByExt.toStringDesc +import ru.astrainteractive.empireapi.models.towny.TownPublicType +import ru.astrainteractive.empireapi.models.towny.TownSortBy +import ru.astrainteractive.empireapi.models.towny.TownsFilter + +@Composable +fun TownFilterCard( + townsFilter: TownsFilter, + onSortSelected: (TownSortBy) -> Unit, + onPublicSelected: (TownPublicType) -> Unit +) { + Column( + modifier = Modifier + .clip(RoundedCornerShape(AppTheme.dimens.XS)) + .background(MaterialTheme.colors.primary) + .padding( + vertical = AppTheme.dimens.XS, + horizontal = AppTheme.dimens.S + ), + verticalArrangement = Arrangement.spacedBy(AppTheme.dimens.XS) + ) { + Text( + text = "Filter", + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.Start, + style = MaterialTheme.typography.h5, + ) + Spacer(modifier = Modifier.height(AppTheme.dimens.XS)) + + RowDropdownText( + title = "Public:", + items = TownPublicType.entries, + modifier = Modifier.fillMaxWidth(), + toString = { it.toStringDesc().asComposableString() }, + selectedItem = townsFilter.publicType, + onItemClicked = onPublicSelected + ) + + RowDropdownText( + title = "Sort by:", + items = TownSortBy.entries, + modifier = Modifier.fillMaxWidth(), + toString = { it.toStringDesc().asComposableString() }, + selectedItem = townsFilter.sortBy, + onItemClicked = onSortSelected + ) + } +} + +@Preview +@Composable +private fun TownFilterCardPreview() { + AdaptThemeFade(composeTheme = ComposeTheme.DARK) { + Box(modifier = Modifier.background(MaterialTheme.colors.primaryVariant)) { + TownFilterCard( + townsFilter = TownsFilter(), + onSortSelected = { + }, + onPublicSelected = { + } + ) + } + } +} diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt index 50a419b5..e48029a7 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/TownyApi.kt @@ -2,10 +2,11 @@ package com.makeevrserg.empireprojekt.mobile.api.empireapi import ru.astrainteractive.empireapi.models.response.GenericPagedModel import ru.astrainteractive.empireapi.models.towny.TownModel +import ru.astrainteractive.empireapi.models.towny.TownsFilter interface TownyApi { /** * Fetch all towns */ - suspend fun towns(page: Int, size: Int): GenericPagedModel + suspend fun towns(page: Int, size: Int, filter: TownsFilter): GenericPagedModel } diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt index cc6a5659..08fda2bc 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt @@ -12,19 +12,20 @@ import io.ktor.http.ContentType import io.ktor.http.contentType import ru.astrainteractive.empireapi.models.response.GenericPagedModel import ru.astrainteractive.empireapi.models.towny.TownModel +import ru.astrainteractive.empireapi.models.towny.TownsFilter class TownyApiImpl( private val httpClient: HttpClient, private val baseUrl: String = "http://192.168.1.2:8080" ) : TownyApi { - override suspend fun towns(page: Int, size: Int): GenericPagedModel { + override suspend fun towns(page: Int, size: Int, filter: TownsFilter): GenericPagedModel { return httpClient.post { url("$baseUrl/towny/towns") parameter("page", page) parameter("size", size) contentType(ContentType.Application.Json) - setBody(body) + setBody(filter) }.body() } } diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownPublicType.kt b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownPublicType.kt new file mode 100644 index 00000000..c9892deb --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownPublicType.kt @@ -0,0 +1,5 @@ +package ru.astrainteractive.empireapi.models.towny + +enum class TownPublicType { + NONE, PUBLIC, PRIVATE +} diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownSortBy.kt b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownSortBy.kt new file mode 100644 index 00000000..2c9689ba --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownSortBy.kt @@ -0,0 +1,17 @@ +package ru.astrainteractive.empireapi.models.towny + +enum class TownSortBy { + NONE, + NAME_ASC, + NAME_DESC, + TAG_ASC, + TAG_DESC, + FOUNDER_ASC, + FOUNDER_DESC, + NATION_ASC, + NATION_DESC, + DATE_ASC, + DATE_DESC, + RESIDENTS_ASC, + RESIDENTS_DESC +} diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownsFilter.kt b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownsFilter.kt new file mode 100644 index 00000000..7f18cfcb --- /dev/null +++ b/modules/services/api-empireapi/src/commonMain/kotlin/ru/astrainteractive/empireapi/models/towny/TownsFilter.kt @@ -0,0 +1,10 @@ +package ru.astrainteractive.empireapi.models.towny + +import kotlinx.serialization.Serializable + +@Serializable +data class TownsFilter( + val query: String = "", + val publicType: TownPublicType = TownPublicType.NONE, + val sortBy: TownSortBy = TownSortBy.NONE +) diff --git a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt index 319a4a8b..8974a01b 100644 --- a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt +++ b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/RowSettingItem.kt @@ -1,15 +1,28 @@ package com.makeevrserg.empireprojekt.mobile.core.ui.components +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.DropdownMenu import androidx.compose.material.MaterialTheme import androidx.compose.material.Text +import androidx.compose.material3.DropdownMenuItem import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp @@ -96,3 +109,121 @@ fun RowText( ) } } + +@Composable +fun RowText( + title: String, + desc: String, + onDescClicked: () -> Unit, + modifier: Modifier = Modifier, + titleColor: Color = MaterialTheme.colors.onPrimary, + descColor: Color = AppTheme.customColors.astraYellow +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = title, + color = titleColor, + textAlign = TextAlign.Start, + modifier = Modifier, + style = MaterialTheme.typography.subtitle1, + ) + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterEnd + ) { + Text( + text = desc, + color = descColor, + textAlign = TextAlign.End, + modifier = Modifier + .clip(RoundedCornerShape(AppTheme.dimens.XS)) + .background(MaterialTheme.colors.primaryVariant) + .clickable { onDescClicked.invoke() } + .padding(horizontal = AppTheme.dimens.XS) + .padding(vertical = AppTheme.dimens.XXS), + style = MaterialTheme.typography.subtitle1 + ) + } + } +} + +@Composable +fun RowDropdownText( + title: String, + items: List, + selectedItem: T, + toString: @Composable (T) -> String, + onItemClicked: (T) -> Unit, + modifier: Modifier = Modifier, + titleColor: Color = MaterialTheme.colors.onPrimary, + itemColor: Color = AppTheme.customColors.astraYellow +) { + var expanded by remember { mutableStateOf(false) } + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = title, + color = titleColor, + textAlign = TextAlign.Start, + modifier = Modifier, + style = MaterialTheme.typography.subtitle1, + ) + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterEnd + ) { + Text( + text = toString.invoke(selectedItem), + color = itemColor, + textAlign = TextAlign.End, + modifier = Modifier + .clip(RoundedCornerShape(AppTheme.dimens.XS)) + .background(MaterialTheme.colors.primaryVariant) + .clickable { expanded = !expanded } + .padding(horizontal = AppTheme.dimens.XS) + .padding(vertical = AppTheme.dimens.XXS), + style = MaterialTheme.typography.subtitle1 + ) + + Box(modifier = Modifier.align(Alignment.CenterEnd)) { + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = !expanded }, + modifier = Modifier + .align(Alignment.CenterEnd) + .wrapContentWidth() + .background(MaterialTheme.colors.primaryVariant) + .clickable { expanded = !expanded } + ) { + items.forEachIndexed { index, item -> + DropdownMenuItem( + onClick = { + onItemClicked.invoke(item) + expanded = !expanded + }, + text = { + Text( + text = toString.invoke(item), + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.End, + modifier = Modifier + .clip(RoundedCornerShape(AppTheme.dimens.XS)) + .padding(horizontal = AppTheme.dimens.XS) + .padding(vertical = AppTheme.dimens.XXS), + style = MaterialTheme.typography.subtitle1 + ) + } + ) + } + } + } + } + } +} From d11b19afb3722037bdad66384ce95d19b2d502cb Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 18:05:32 +0300 Subject: [PATCH 5/9] feat: add map view --- .../root/pager/DefaultPagerComponent.kt | 11 +++ .../features/root/pager/PagerComponent.kt | 4 + .../mobile/features/ui/map/AndroidMapView.kt | 78 +++++++++++++++++++ .../features/ui/map/LoadingWebViewClient.kt | 23 ++++++ .../features/ui/pager/PagerScreenComponent.kt | 3 + .../ui/pager/components/PagerBottomBar.kt | 3 +- .../components/model/PagerBottomBarItem.kt | 2 + .../mobile/core/ui/components/PagingWidget.kt | 29 +++---- 8 files changed, 139 insertions(+), 14 deletions(-) create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/AndroidMapView.kt create mode 100644 modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/LoadingWebViewClient.kt diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt index de16bac2..83a97f3f 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt @@ -59,12 +59,15 @@ internal class DefaultPagerComponent( ) ) } + + Configuration.Map -> PagerComponent.Child.Map } } ) override val selectedIndex: Value = childStack.map { when (it.active.instance) { + PagerComponent.Child.Map -> 3 is PagerComponent.Child.RatingUsers -> 2 is PagerComponent.Child.Status -> 1 is PagerComponent.Child.Towns -> 0 @@ -83,11 +86,16 @@ internal class DefaultPagerComponent( navigation.replaceAll(Configuration.Towns) } + override fun selectMap() { + navigation.replaceAll(Configuration.Map) + } + override fun select(index: Int) { when (index) { 0 -> selectTowns() 1 -> selectStatus() 2 -> selectRatings() + 3 -> selectMap() else -> error("Index out of bounds") } } @@ -101,5 +109,8 @@ internal class DefaultPagerComponent( @Parcelize data object Towns : Configuration + + @Parcelize + data object Map : Configuration } } diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt index 1509f869..4b07c578 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt @@ -17,6 +17,8 @@ interface PagerComponent { fun selectTowns() + fun selectMap() + fun select(index: Int) sealed interface Child { @@ -33,5 +35,7 @@ interface PagerComponent { class Towns( val townsComponent: TownsComponent ) : Child + + data object Map : Child } } diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/AndroidMapView.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/AndroidMapView.kt new file mode 100644 index 00000000..8ab011e8 --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/AndroidMapView.kt @@ -0,0 +1,78 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.map + +import android.view.ViewGroup +import android.webkit.WebSettings +import android.webkit.WebView +import androidx.compose.animation.Crossfade +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.viewinterop.AndroidView +import com.makeevrserg.empireprojekt.mobile.core.ui.components.AstraLoading +import com.makeevrserg.empireprojekt.mobile.core.ui.theme.AppTheme + +@Composable +internal fun AndroidMapView() { + var webView: WebView? = remember { + null + } + var isLoading by remember { + mutableStateOf(true) + } + AndroidView( + modifier = Modifier + .fillMaxSize() + .statusBarsPadding() + .background(Color.Red), + factory = { context -> + webView ?: WebView(context).apply { + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + loadUrl("https://map.astrainteractive.ru") + settings.javaScriptEnabled = true + settings.useWideViewPort = true + settings.allowFileAccess = true + settings.allowContentAccess = true + settings.builtInZoomControls = true + settings.displayZoomControls = false + settings.useWideViewPort = true + settings.loadWithOverviewMode = true + settings.domStorageEnabled = true + settings.blockNetworkLoads = false + settings.blockNetworkImage = false + settings.databaseEnabled = true + settings.cacheMode = WebSettings.LOAD_NO_CACHE + settings.setSupportZoom(true) + scrollBarStyle = WebView.SCROLLBARS_OUTSIDE_OVERLAY + isScrollbarFadingEnabled = false + webViewClient = LoadingWebViewClient { + isLoading = it + } + }.also { webView = it } + }, + update = { + webView = it + } + ) + Crossfade( + targetState = isLoading, + label = "loading indicator crossfade" + ) { isLoading -> + if (isLoading) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + AstraLoading(AppTheme.dimens.M) + } + } + } +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/LoadingWebViewClient.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/LoadingWebViewClient.kt new file mode 100644 index 00000000..e0417c22 --- /dev/null +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/map/LoadingWebViewClient.kt @@ -0,0 +1,23 @@ +package com.makeevrserg.empireprojekt.mobile.features.ui.map + +import android.webkit.WebView +import android.webkit.WebViewClient + +internal class LoadingWebViewClient( + private val onLoading: (Boolean) -> Unit +) : WebViewClient() { + + init { + onLoading.invoke(true) + } + + override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { + onLoading.invoke(true) + return super.shouldOverrideUrlLoading(view, url) + } + + override fun onPageFinished(view: WebView, url: String) { + onLoading.invoke(false) + return super.onPageFinished(view, url) + } +} diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt index 00fec0bb..8f9331b2 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt @@ -14,6 +14,7 @@ import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState import com.makeevrserg.empireprojekt.mobile.features.root.modal.RootBottomSheetComponent import com.makeevrserg.empireprojekt.mobile.features.root.pager.PagerComponent import com.makeevrserg.empireprojekt.mobile.features.root.screen.RootScreenComponent +import com.makeevrserg.empireprojekt.mobile.features.ui.map.AndroidMapView import com.makeevrserg.empireprojekt.mobile.features.ui.pager.components.PagerBottomBar import com.makeevrserg.empireprojekt.mobile.features.ui.rating.users.RatingUsersScreenComponent import com.makeevrserg.empireprojekt.mobile.features.ui.status.StatusScreen @@ -60,6 +61,8 @@ fun PagerScreenComponent( popComponent = rootScreenComponent, townsComponent = instance.townsComponent ) + + PagerComponent.Child.Map -> AndroidMapView() } } } diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt index 8a8b9253..27f30ff4 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/PagerBottomBar.kt @@ -22,7 +22,8 @@ internal fun PagerBottomBar(selectedIndex: Int, onClicked: (Int) -> Unit, modifi listOf( PagerBottomBarItem.Towns, PagerBottomBarItem.Status, - PagerBottomBarItem.Ratings + PagerBottomBarItem.Ratings, + PagerBottomBarItem.Map ) } BottomNavigation( diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt index 9eb59967..d6df5416 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/components/model/PagerBottomBarItem.kt @@ -2,6 +2,7 @@ package com.makeevrserg.empireprojekt.mobile.features.ui.pager.components.model import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Apartment +import androidx.compose.material.icons.filled.Map import androidx.compose.material.icons.filled.NetworkWifi import androidx.compose.material.icons.filled.People import androidx.compose.ui.graphics.vector.ImageVector @@ -10,4 +11,5 @@ internal sealed class PagerBottomBarItem(val icon: ImageVector) { data object Towns : PagerBottomBarItem(icon = Icons.Filled.Apartment) data object Status : PagerBottomBarItem(icon = Icons.Filled.NetworkWifi) data object Ratings : PagerBottomBarItem(icon = Icons.Filled.People) + data object Map : PagerBottomBarItem(icon = Icons.Filled.Map) } diff --git a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/PagingWidget.kt b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/PagingWidget.kt index 2ff369b5..f28d1127 100644 --- a/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/PagingWidget.kt +++ b/modules/services/core-ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/core/ui/components/PagingWidget.kt @@ -1,5 +1,6 @@ package com.makeevrserg.empireprojekt.mobile.core.ui.components +import androidx.compose.animation.Crossfade import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -7,7 +8,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.material.Button -import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -72,15 +72,19 @@ object PagingWidget { @Suppress("ModifierMissing") @Composable - fun Loading() { - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator( - modifier = Modifier.size(AppTheme.dimens.M), - color = AppTheme.customColors.astraOrange - ) + fun Loading(isLoading: Boolean) { + Crossfade( + targetState = isLoading, + label = "crossfade loading indicator" + ) { localIsLoading -> + if (localIsLoading) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + AstraLoading(AppTheme.dimens.M) + } + } } } @@ -92,9 +96,8 @@ object PagingWidget { isFailure: Boolean, onReload: () -> Unit ) { - if (isLoading) { - Loading() - } else if (isLastPage && list.isNotEmpty()) { + Loading(isLoading = isLoading) + if (isLastPage && list.isNotEmpty()) { LastPage() } else if (isLastPage && list.isEmpty()) { NoPages() From 05c7167d6a0ff0498cc00784d53a5635805acc44 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 18:17:46 +0300 Subject: [PATCH 6/9] feat: retained pager components --- .../root/pager/DefaultPagerComponent.kt | 122 ++++++------------ .../features/root/pager/PagerComponent.kt | 11 +- .../features/ui/pager/PagerScreenComponent.kt | 47 +++++-- 3 files changed, 79 insertions(+), 101 deletions(-) diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt index 83a97f3f..622af732 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/DefaultPagerComponent.kt @@ -1,14 +1,10 @@ package com.makeevrserg.empireprojekt.mobile.features.root.pager import com.arkivanov.decompose.ComponentContext -import com.arkivanov.decompose.router.stack.ChildStack -import com.arkivanov.decompose.router.stack.StackNavigation -import com.arkivanov.decompose.router.stack.childStack -import com.arkivanov.decompose.router.stack.replaceAll +import com.arkivanov.decompose.childContext +import com.arkivanov.decompose.value.MutableValue import com.arkivanov.decompose.value.Value import com.arkivanov.decompose.value.operator.map -import com.arkivanov.essenty.parcelable.Parcelable -import com.arkivanov.essenty.parcelable.Parcelize import com.makeevrserg.empireprojekt.mobile.features.rating.users.DefaultRatingUsersComponent import com.makeevrserg.empireprojekt.mobile.features.rating.users.di.RatingUsersModule import com.makeevrserg.empireprojekt.mobile.features.root.di.RootModule @@ -19,98 +15,56 @@ internal class DefaultPagerComponent( rootModule: RootModule, onRootNavigation: (RootScreenComponent.Child) -> Unit ) : PagerComponent, ComponentContext by componentContext { - private val navigation = StackNavigation() - - override val childStack: Value> = childStack( - source = navigation, - initialConfiguration = Configuration.Status, - handleBackButton = false, - childFactory = { config, context -> - when (config) { - Configuration.RatingUsers -> { - PagerComponent.Child.RatingUsers( - ratingUsersComponent = DefaultRatingUsersComponent( - componentContext = context, - moduleFactory = { - RatingUsersModule.Default( - empireApiModule = rootModule.empireApiModule, - dispatchers = rootModule.servicesModule.dispatchers.value - ) - }, - onShowUserRatingsClicked = { id, userName -> - val configuration = RootScreenComponent.Child.RatingUser(id, userName) - onRootNavigation.invoke(configuration) - } - ) + private val ratingUsersChild by lazy { + PagerComponent.Child.RatingUsers( + ratingUsersComponent = DefaultRatingUsersComponent( + componentContext = componentContext.childContext("RatingUsers"), + moduleFactory = { + RatingUsersModule.Default( + empireApiModule = rootModule.empireApiModule, + dispatchers = rootModule.servicesModule.dispatchers.value ) + }, + onShowUserRatingsClicked = { id, userName -> + val configuration = RootScreenComponent.Child.RatingUser(id, userName) + onRootNavigation.invoke(configuration) } - - Configuration.Status -> { - PagerComponent.Child.Status( - themeSwitcherComponent = rootModule.componentsModule.themeSwitcherComponent.value, - rootStatusComponent = rootModule.componentsModule.rootStatusComponent.value - ) - } - - Configuration.Towns -> { - PagerComponent.Child.Towns( - townsComponent = rootModule.townsModule.createTownsComponent( - componentContext = context - ) - ) - } - - Configuration.Map -> PagerComponent.Child.Map - } - } - ) - - override val selectedIndex: Value = childStack.map { - when (it.active.instance) { - PagerComponent.Child.Map -> 3 - is PagerComponent.Child.RatingUsers -> 2 - is PagerComponent.Child.Status -> 1 - is PagerComponent.Child.Towns -> 0 - } + ) + ) } - override fun selectStatus() { - navigation.replaceAll(Configuration.Status) + private val statusChild by lazy { + PagerComponent.Child.Status( + themeSwitcherComponent = rootModule.componentsModule.themeSwitcherComponent.value, + rootStatusComponent = rootModule.componentsModule.rootStatusComponent.value + ) } - override fun selectRatings() { - navigation.replaceAll(Configuration.RatingUsers) + private val townsChild by lazy { + PagerComponent.Child.Towns( + townsComponent = rootModule.townsModule.createTownsComponent( + componentContext = componentContext.childContext("Towns") + ) + ) } - override fun selectTowns() { - navigation.replaceAll(Configuration.Towns) + private val mapChild by lazy { + PagerComponent.Child.Map } - override fun selectMap() { - navigation.replaceAll(Configuration.Map) - } + override val selectedIndex: MutableValue = MutableValue(1) - override fun select(index: Int) { - when (index) { - 0 -> selectTowns() - 1 -> selectStatus() - 2 -> selectRatings() - 3 -> selectMap() + override val selectedChild: Value = selectedIndex.map { + when (it) { + 0 -> townsChild + 1 -> statusChild + 2 -> ratingUsersChild + 3 -> mapChild else -> error("Index out of bounds") } } - private sealed interface Configuration : Parcelable { - @Parcelize - data object Status : Configuration - - @Parcelize - data object RatingUsers : Configuration - - @Parcelize - data object Towns : Configuration - - @Parcelize - data object Map : Configuration + override fun select(index: Int) { + selectedIndex.value = index } } diff --git a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt index 4b07c578..e928a747 100644 --- a/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt +++ b/modules/features/root/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/root/pager/PagerComponent.kt @@ -1,6 +1,5 @@ package com.makeevrserg.empireprojekt.mobile.features.root.pager -import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.value.Value import com.makeevrserg.empireprojekt.mobile.features.rating.users.RatingUsersComponent import com.makeevrserg.empireprojekt.mobile.features.status.root.RootStatusComponent @@ -8,16 +7,16 @@ import com.makeevrserg.empireprojekt.mobile.features.theme.ThemeSwitcherComponen import com.makeevrserg.empireprojekt.mobile.features.towny.towns.presentation.TownsComponent interface PagerComponent { - val childStack: Value> val selectedIndex: Value + val selectedChild: Value - fun selectStatus() +// fun selectStatus() - fun selectRatings() +// fun selectRatings() - fun selectTowns() +// fun selectTowns() - fun selectMap() +// fun selectMap() fun select(index: Int) diff --git a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt index 8f9331b2..dde17151 100644 --- a/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt +++ b/modules/features/ui/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/features/ui/pager/PagerScreenComponent.kt @@ -1,15 +1,13 @@ package com.makeevrserg.empireprojekt.mobile.features.ui.pager -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.animation.Crossfade +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.material.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import com.arkivanov.decompose.extensions.compose.jetbrains.stack.Children -import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.fade -import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.stackAnimation import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState import com.makeevrserg.empireprojekt.mobile.features.root.modal.RootBottomSheetComponent import com.makeevrserg.empireprojekt.mobile.features.root.pager.PagerComponent @@ -27,7 +25,7 @@ fun PagerScreenComponent( rootBottomSheetComponent: RootBottomSheetComponent, modifier: Modifier = Modifier ) { - val childStack by pagerComponent.childStack.subscribeAsState() + val selectedChild by pagerComponent.selectedChild.subscribeAsState() val selectedIndex by pagerComponent.selectedIndex.subscribeAsState() Scaffold( modifier = Modifier.navigationBarsPadding(), @@ -38,14 +36,14 @@ fun PagerScreenComponent( ) } ) { paddingValues -> - Children( - stack = childStack, + Crossfade( modifier = modifier - .fillMaxSize() + .fillMaxWidth() .padding(paddingValues), - animation = stackAnimation(fade()) - ) { child -> - when (val instance = child.instance) { + targetState = selectedChild, + label = "Crossfade instance composable" + ) { instance -> + when (instance) { is PagerComponent.Child.RatingUsers -> RatingUsersScreenComponent( ratingUsersComponent = instance.ratingUsersComponent, popComponent = rootScreenComponent @@ -65,5 +63,32 @@ fun PagerScreenComponent( PagerComponent.Child.Map -> AndroidMapView() } } +// Children( +// stack = childStack, +// modifier = modifier +// .fillMaxSize() +// .padding(paddingValues), +// animation = stackAnimation(fade()) +// ) { child -> +// when (val instance = child.instance) { +// is PagerComponent.Child.RatingUsers -> RatingUsersScreenComponent( +// ratingUsersComponent = instance.ratingUsersComponent, +// popComponent = rootScreenComponent +// ) +// +// is PagerComponent.Child.Status -> StatusScreen( +// themeSwitcherComponent = instance.themeSwitcherComponent, +// rootStatusComponent = instance.rootStatusComponent, +// rootBottomSheetComponent = rootBottomSheetComponent +// ) +// +// is PagerComponent.Child.Towns -> TownsScreenComponent( +// popComponent = rootScreenComponent, +// townsComponent = instance.townsComponent +// ) +// +// PagerComponent.Child.Map -> AndroidMapView() +// } +// } } } From f83590d72202ce094c9684be28ae5679485c04a7 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 18:20:16 +0300 Subject: [PATCH 7/9] reset to UNLICENSE --- LICENSE.md | 53 ----------------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 43e8b279..00000000 --- a/LICENSE.md +++ /dev/null @@ -1,53 +0,0 @@ -# EMPIREPROJEKT-MOBILE LICENSE - - -## Version 1.1, June 2023 - - -## Definitions - -"Package" refers to the collection of files (unless something else is indicated inside the file) distributed -by the Copyright Holder, and derivatives of that collection of files created through textual modification. - -"Copyright Holder" is whoever is named in the copyright or copyrights for the package. - -"You" is you, if you're thinking about copying or distributing this Package. - - -## Copyright (C) 2021 Makeev Roman - -You are not allowed to redistribute full, partial or modified versions of the package to which the license -is associated. This license does not apply to modules or extensions that use but do not contain full, -partial or modified code from this package. - -You cannot use this code for anything that might be considered commercial use. - -## EMPIREPROJEKT-MOBILE LICENSE -This source code is provided as reference to licensed individuals that have downloaded or bought official release of EmpireProjekt-Mobile once from any of the official sources it is provided. The availability of this code does not grant you the rights to modify, re-distribute, compile or redistribute this source code or "application" outside this intended purpose. This license does not cover libraries developed by thirdparties that are utilised in the application. - -### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -1. Do whatever you like with the original work, as long as you keep it for yourself or have the Copyright -Holder's permission. - -2. You are not allowed to redistribute full, partial or modified versions of the package - -3. Code is provided with no warranty. You have the right to propose improvements -to the package as long as you don't use it as a way to circumvent the restrictions of the license. - -4. By proposing a modification you agree to assign all your rights on your code to the Copyright Holder. -You must therefore own the modifications you propose or have the permission to assign their rights. - -5. You cannot use this source or edited versions in commercial projects - -6. You cannot use this code in projects that earn using advertisements or that take donations - -7. You cannot state that this is your code - -8. You must share the edited source code - -9. You cannot use this code in projects that earn using advertisements or that take donations - -10. You cannot resell this code - -11. You cannot use this code for anything that might be considered commercial use. From 6ecb8bdbb9342621fe2cf3262f04bc4d8c4628d9 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 18:21:29 +0300 Subject: [PATCH 8/9] up version 0.3.0 12 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 41995c1e..a16365b8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -44,8 +44,8 @@ makeevrserg.android.sdk.target=34 # Project makeevrserg.project.name=EmpireProjektMobile makeevrserg.project.group=com.makeevrserg.empireprojekt.mobile -makeevrserg.project.version.string=0.2.4 -makeevrserg.project.version.code=11 +makeevrserg.project.version.string=0.3.0 +makeevrserg.project.version.code=12 makeevrserg.project.description=EmpireProjekt mobile application makeevrserg.project.developers=makeevrserg|Makeev Roman|makeevrserg@gmail.com makeevrserg.project.url=https://empireprojekt.ru From c6b5024c1d1b6cbd2519be16638f38048366ddc9 Mon Sep 17 00:00:00 2001 From: Roman Makeev Date: Sat, 9 Mar 2024 18:29:16 +0300 Subject: [PATCH 9/9] update api path --- modules/features/root/root.podspec | 2 +- .../empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt | 2 +- .../empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/features/root/root.podspec b/modules/features/root/root.podspec index c7794c9f..965d8b91 100644 --- a/modules/features/root/root.podspec +++ b/modules/features/root/root.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'root' - spec.version = '0.2.4' + spec.version = '0.3.0' spec.homepage = 'https://empireprojekt.ru' spec.source = { :http=> ''} spec.authors = '' diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt index 497c1884..7ea80d5a 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/RatingApiImpl.kt @@ -18,7 +18,7 @@ import ru.astrainteractive.empireapi.models.response.GenericPagedModel class RatingApiImpl( private val httpClient: HttpClient, - private val baseUrl: String = "http://192.168.1.2:8080" + private val baseUrl: String = "https://empireapi.astrainteractive.ru" ) : RatingApi { override suspend fun users(page: Int, size: Int, body: RatingListRequest): GenericPagedModel { diff --git a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt index 08fda2bc..4e9007c3 100644 --- a/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt +++ b/modules/services/api-empireapi/src/commonMain/kotlin/com/makeevrserg/empireprojekt/mobile/api/empireapi/impl/TownyApiImpl.kt @@ -16,7 +16,7 @@ import ru.astrainteractive.empireapi.models.towny.TownsFilter class TownyApiImpl( private val httpClient: HttpClient, - private val baseUrl: String = "http://192.168.1.2:8080" + private val baseUrl: String = "https://empireapi.astrainteractive.ru" ) : TownyApi { override suspend fun towns(page: Int, size: Int, filter: TownsFilter): GenericPagedModel {