Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.jetbrains.kotlin.serialization)
}

android {
Expand Down Expand Up @@ -68,4 +69,12 @@ dependencies {

// DI
implementation(libs.bundles.koin)

// network
implementation(libs.retrofit)
implementation(libs.retrofit.serialization)
implementation(libs.kotlinx.serialization.json)
debugImplementation("com.github.chuckerteam.chucker:library:4.0.0")
releaseImplementation("com.github.chuckerteam.chucker:library-no-op:4.0.0")

}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/Theme.Practice3">
<activity
android:name=".MainActivity"
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/com/example/practice3/Application.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.example.practice3

import android.app.Application
import com.example.practice3.di.filmsFeatureModule
import com.example.practice3.di.mainModule
import com.example.practice3.di.networkModule
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.GlobalContext.startKoin
Expand All @@ -12,7 +14,7 @@ class Application: Application(){
startKoin{
androidLogger()
androidContext(this@Application)
modules(mainModule)
modules(mainModule, filmsFeatureModule, networkModule)
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/java/com/example/practice3/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ fun MainScreen() {
ContentGray("test")
}
entry<Films> {
FilmsListScreen(topLevelBackStack)
FilmsListScreen()
}
entry<FilmsDetails>(
metadata = DialogSceneStrategy.dialog(DialogProperties())
Expand Down
44 changes: 44 additions & 0 deletions app/src/main/java/com/example/practice3/core/CoroutineUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.example.practice3.core

import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext

fun CoroutineScope.launchLoadingAndError(
handleError: (Throwable) -> Unit = {},
updateLoading: (Boolean) -> Unit = {},
block: suspend CoroutineScope.() -> Unit,
): Job {
val context =
CoroutineExceptionHandler { _, throwable -> handleError.invoke(throwable) } +
LoadingContextHandler(updateLoading)

return launch(context) {
handleLoading(this, block)
}
}

class LoadingContextHandler(
private val updateLoading: (Boolean) -> Unit
): CoroutineContext.Element {
override val key: CoroutineContext.Key<*> = Key

companion object Key: CoroutineContext.Key<LoadingContextHandler>

fun showProgress() = updateLoading.invoke(true)
fun hideProgress() = updateLoading.invoke(false)
}

private suspend fun <T> handleLoading(
coroutineScope: CoroutineScope,
block: suspend CoroutineScope.() -> T
): T {
return coroutineScope.runCatching {
coroutineScope.coroutineContext[LoadingContextHandler]?.showProgress()
block()
}. also {
coroutineScope.coroutineContext[LoadingContextHandler]?.hideProgress()
}.getOrThrow()
}
26 changes: 26 additions & 0 deletions app/src/main/java/com/example/practice3/di/FilmsFeatureModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.practice3.di

import com.example.practice3.Films
import com.example.practice3.navigation.Route
import com.example.practice3.navigation.TopLevelBackStack
import com.example.practice3.news.data.mapper.FilmsResponseToEntityMapper
import com.example.practice3.news.data.model.FilmsApi
import com.example.practice3.news.data.repository.FilmsRepository
import com.example.practice3.news.domain.interactor.FilmsInteractor
import com.example.practice3.news.presentation.viewModel.FilmsDetailsViewModel
import com.example.practice3.news.presentation.viewModel.FilmsListViewModel
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
import retrofit2.Retrofit

val filmsFeatureModule = module {
viewModel { FilmsDetailsViewModel(get(), get()) }
viewModel { FilmsListViewModel(get(), get()) }

single { get<Retrofit>().create(FilmsApi::class.java) }

factory { FilmsResponseToEntityMapper() }
single { FilmsRepository(get(), get()) }

single { FilmsInteractor(get()) }
}
2 changes: 0 additions & 2 deletions app/src/main/java/com/example/practice3/di/MainModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ import org.koin.core.module.dsl.viewModelOf

val mainModule = module {
single { TopLevelBackStack<Route>(Films) }
//viewModelOf(::FilmsDetailsViewModel)
viewModel { FilmsDetailsViewModel(get(), get()) }
}
34 changes: 34 additions & 0 deletions app/src/main/java/com/example/practice3/di/NetworkModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.practice3.di

import com.chuckerteam.chucker.api.ChuckerInterceptor
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory

val networkModule = module {
single {
OkHttpClient.Builder()
.addInterceptor(ChuckerInterceptor(androidContext()))
.build()
}

single {
val json = Json {
explicitNulls = false
ignoreUnknownKeys = true
}
Retrofit.Builder()
.baseUrl("http://26.15.99.17:8001/")
.addConverterFactory(
json.asConverterFactory(
"application/json; charset=UTF8".toMediaType()
)
)
.client(get())
.build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.practice3.news.data.mapper

import com.example.practice3.news.data.model.FilmsListResponse
import com.example.practice3.news.domain.model.FilmsEntity

class FilmsResponseToEntityMapper {
fun mapResponse(response: FilmsListResponse): List<FilmsEntity> {
return response.documents?.map { doc ->
FilmsEntity(
id = doc.id.orEmpty(),
title = doc.title.orEmpty(),
descr = doc.descr,
year = doc.year.orEmpty(),
imageUrl = doc.imageUrl,
)
}.orEmpty()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.practice3.news.data.model

import retrofit2.http.GET
import retrofit2.http.Query

interface FilmsApi {
@GET("/")
suspend fun getFilms(
// @Query("orderBy") orderBy: String = CREATE_TIME_KEY,
): FilmsListResponse

// companion object {
// private const val CREATE_TIME_KEY = "createTime desc"
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.practice3.news.data.model

import androidx.annotation.Keep
import kotlinx.serialization.Serializable

@Keep
@Serializable
class FilmsListResponse(
val documents: List<FilmsListDocument>?,
)

@Keep
@Serializable
class FilmsListDocument(
val id: String?,
val title: String?,
val descr: String?,
val year: String?,
val imageUrl: String?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.practice3.news.data.model

import androidx.annotation.Keep
import kotlinx.serialization.Serializable

@Keep
@Serializable
class StringFireStoreModel(val stringValue: String?)

@Keep
@Serializable
class BooleanFireStoreModel(val booleanValue: Boolean?)

@Keep
@Serializable
class NumberFireStoreModel(val integerValue: Int?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.practice3.news.data.repository

import com.example.practice3.news.data.mapper.FilmsResponseToEntityMapper
import com.example.practice3.news.data.model.FilmsApi
import com.example.practice3.news.domain.model.FilmsEntity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class FilmsRepository(
private val api: FilmsApi,
private val mapper: FilmsResponseToEntityMapper,
) {
suspend fun getFilms(): List<FilmsEntity> = withContext(Dispatchers.IO) {
val response = api.getFilms()
mapper.mapResponse(response)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.practice3.news.domain.interactor

import com.example.practice3.news.data.repository.FilmsRepository

class FilmsInteractor (
private val filmsRepository: FilmsRepository,
) {
suspend fun getFilms() = filmsRepository.getFilms()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.practice3.news.domain.model

class FilmsEntity (
val id: String,
val title: String,
val descr: String?,
val year: String,
val imageUrl: String?,
)
Loading