Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev #20

Merged
merged 4 commits into from
Dec 2, 2023
Merged

dev #20

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
10 changes: 10 additions & 0 deletions .github/workflows/build_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: set up LOCAL_PROPERTIES
env:
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
run: echo "$LOCAL_PROPERTIES" > ./local.properties

- name: Build with Gradle
run: ./gradlew assembleAndroidTest

Expand All @@ -49,5 +54,10 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: set up LOCAL_PROPERTIES
env:
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
run: echo "$LOCAL_PROPERTIES" > ./local.properties

- name: Build with Gradle
run: ./gradlew desktopMainClasses desktopSourcesJar desktopTestClasses
5 changes: 5 additions & 0 deletions .github/workflows/build_mac_os.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,10 @@ jobs:
with:
xcode-version: latest-stable

- name: set up LOCAL_PROPERTIES
env:
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
run: echo "$LOCAL_PROPERTIES" > ./local.properties

- name: Build with Gradle
run: ./gradlew iosArm64Binaries
24 changes: 12 additions & 12 deletions composeApp/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import androidx.compose.runtime.Composable
import com.stslex.core.core.coreModule
import com.stslex.core.database.di.databaseModule
import com.stslex.core.network.di.networkModule
import com.stslex.core.database.di.coreDatabaseModule
import com.stslex.core.network.di.coreNetworkModule
import com.stslex.core.ui.theme.AppTheme
import com.stslex.feature.film.di.filmModule
import com.stslex.feature.film_feed.di.feedModule
import com.stslex.feature.match_feed.di.matchFeedModule
import com.stslex.feature.profile.di.profileModule
import com.stslex.feature.film.di.featureFilmModule
import com.stslex.feature.film_feed.di.featureFeedModule
import com.stslex.feature.match_feed.di.featureMatchFeedModule
import com.stslex.feature.profile.di.featureProfileModule
import di.appModule
import org.koin.compose.KoinApplication
import org.koin.dsl.KoinAppDeclaration
Expand Down Expand Up @@ -35,12 +35,12 @@ private fun setupModules(): KoinAppDeclaration = {
listOf(
appModule,
coreModule,
networkModule,
databaseModule,
feedModule,
filmModule,
profileModule,
matchFeedModule
coreNetworkModule,
coreDatabaseModule,
featureFeedModule,
featureFilmModule,
featureProfileModule,
featureMatchFeedModule
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import com.stslex.core.database.sources.source.FavouriteFilmDataSource
import com.stslex.core.database.sources.source.FavouriteFilmDataSourceImpl
import org.koin.dsl.module

val databaseModule = module {
val coreDatabaseModule = module {
single<FavouriteFilmDataSource> { FavouriteFilmDataSourceImpl() }
}
15 changes: 15 additions & 0 deletions core/network/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.github.gmazzo.gradle.plugins.BuildConfigExtension

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.kotlinCocoapods)
kotlin("plugin.serialization") version "1.9.20"
id("com.github.gmazzo.buildconfig").version("4.2.0")
}

kotlin {
Expand Down Expand Up @@ -43,6 +47,9 @@ kotlin {
commonTest.dependencies {
implementation(libs.kotlin.test)
}
buildConfig {
setLocalProperty(project.rootProject)
}
}
}

Expand All @@ -53,3 +60,11 @@ android {
minSdk = libs.versions.android.minSdk.get().toInt()
}
}


fun BuildConfigExtension.setLocalProperty(dir: Project) {
val key = gradleLocalProperties(dir.projectDir)["KINOPOISK_API_KEY"]
?.toString()
?: throw IllegalStateException("KINOPOISK_API_KEY should be initialised")
buildConfigField("String", "KINOPOISK_API_KEY", key)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.stslex.core.network.api.base

import com.stslex.core.core.AppDispatcher
import com.stslex.core.network.api.model.DefaultRequest
import com.stslex.core.network.api.base.NetworkClientBuilder.setupDefaultRequest
import com.stslex.core.network.api.base.NetworkClientBuilder.setupLogging
import com.stslex.core.network.api.base.NetworkClientBuilder.setupNegotiation
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.cache.HttpCache
import kotlinx.coroutines.withContext

abstract class BaseNetworkClient(
private val appDispatcher: AppDispatcher,
defaultRequest: DefaultRequest = DefaultRequest.EMPTY
) : NetworkClient {

override suspend fun <T> request(
request: suspend HttpClient.() -> T
): T = withContext(appDispatcher.io) {
request(client)
}

private val client: HttpClient = HttpClient(CIO) {
setupNegotiation()
install(HttpCache)
setupLogging()
expectSuccess = true
setupDefaultRequest(defaultRequest)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.stslex.core.network.api.base

import com.stslex.core.core.AppDispatcher

class DefaultNetworkClientImpl(
dispatcher: AppDispatcher
) : BaseNetworkClient(dispatcher)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stslex.core.network.client
package com.stslex.core.network.api.base

import io.ktor.client.HttpClient

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.stslex.core.network.client
package com.stslex.core.network.api.base

import com.stslex.core.network.api.model.DefaultRequest
import com.stslex.core.network.utils.KtorLogger
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.cio.CIOEngineConfig
Expand All @@ -15,8 +16,6 @@ import kotlinx.serialization.json.Json

internal object NetworkClientBuilder {

private const val HOST_URL = "smth_host_url"

@OptIn(ExperimentalSerializationApi::class)
fun HttpClientConfig<CIOEngineConfig>.setupNegotiation() {
install(ContentNegotiation) {
Expand All @@ -31,14 +30,18 @@ internal object NetworkClientBuilder {
}
}

fun HttpClientConfig<CIOEngineConfig>.setupDefaultRequest() {
fun HttpClientConfig<CIOEngineConfig>.setupDefaultRequest(
defaultRequest: DefaultRequest
) {
defaultRequest {
url {
host = HOST_URL
host = defaultRequest.hostUrl
protocol = URLProtocol.HTTPS
}
headers {
// TODO add auth headers
defaultRequest.headers.forEach { (key, value) ->
append(key, value)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.stslex.core.network.api.kinopoisk

interface KinopoiskApiClient
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.stslex.core.network.api.kinopoisk

import Wizard.core.network.BuildConfig
import com.stslex.core.core.AppDispatcher
import com.stslex.core.network.api.base.BaseNetworkClient
import com.stslex.core.network.api.model.DefaultRequest

class KinopoiskApiClientImpl(
appDispatcher: AppDispatcher
) : KinopoiskApiClient, BaseNetworkClient(
appDispatcher = appDispatcher,
defaultRequest = DEFAULT_REQUEST
) {

companion object {
private const val KINOPOISK_HOST_URL = "https://kinopoiskapiunofficial.tech/api/v2.2/"
private const val API_KEY = BuildConfig.KINOPOISK_API_KEY
private const val API_HEADER = "X-API-KEY"
private const val CONTENT_TYPE = "Content-Type"
private const val CONTENT_TYPE_VALUE = "application/json"

private val DEFAULT_REQUEST = DefaultRequest(
hostUrl = KINOPOISK_HOST_URL,
headers = mapOf(
API_HEADER to API_KEY,
CONTENT_TYPE to CONTENT_TYPE_VALUE
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.stslex.core.network.api.kinopoisk.model

import com.stslex.core.network.api.kinopoisk.model.network.FilmItemNetwork
import com.stslex.core.network.api.kinopoisk.model.network.FilmListNetwork
import com.stslex.core.network.api.kinopoisk.model.network.FilmProductionStatusNetwork
import com.stslex.core.network.api.kinopoisk.model.network.FilmTypeNetwork
import com.stslex.core.network.api.kinopoisk.model.network.MovieNetwork
import com.stslex.core.network.api.kinopoisk.model.network.TrailerItemNetwork
import com.stslex.core.network.api.kinopoisk.model.network.TrailerNetwork
import com.stslex.core.network.api.kinopoisk.model.response.FilmItemResponse
import com.stslex.core.network.api.kinopoisk.model.response.FilmListResponse
import com.stslex.core.network.api.kinopoisk.model.response.MovieResponse
import com.stslex.core.network.api.kinopoisk.model.response.TrailerItemResponse
import com.stslex.core.network.api.kinopoisk.model.response.TrailerResponse

fun FilmListResponse.toNetwork(): FilmListNetwork = FilmListNetwork(
total = total ?: 0,
totalPages = totalPages ?: 0,
items = items?.map { it.toNetwork() }.orEmpty()
)

fun FilmItemResponse.toNetwork(): FilmItemNetwork = FilmItemNetwork(
kinopoiskId = kinopoiskId,
imdbId = imdbId.orEmpty(),
nameRu = nameRu.orEmpty(),
nameEn = nameEn.orEmpty(),
nameOriginal = nameOriginal.orEmpty(),
countries = countries?.map { it.country }.orEmpty(),
genres = genres?.map { it.genre }.orEmpty(),
ratingKinopoisk = ratingKinopoisk,
ratingImdb = ratingImdb,
year = year,
posterUrl = posterUrl.orEmpty(),
posterUrlPreview = posterUrlPreview.orEmpty(),
type = FilmTypeNetwork.valueOf(type.orEmpty())
)

fun TrailerResponse.toNetwork(): TrailerNetwork = TrailerNetwork(
total = total ?: 0,
items = items?.map { it.toNetwork() }.orEmpty()
)

fun TrailerItemResponse.toNetwork(): TrailerItemNetwork = TrailerItemNetwork(
url = url.orEmpty(),
name = name.orEmpty(),
site = site.orEmpty(),
)

fun MovieResponse.toNetwork(): MovieNetwork = MovieNetwork(
kinopoiskId = kinopoiskId,
kinopoiskHDId = kinopoiskHDId.orEmpty(),
imdbId = imdbId.orEmpty(),
nameRu = nameRu.orEmpty(),
nameEn = nameEn.orEmpty(),
nameOriginal = nameOriginal.orEmpty(),
posterUrl = posterUrl.orEmpty(),
posterUrlPreview = posterUrlPreview.orEmpty(),
coverUrl = coverUrl.orEmpty(),
logoUrl = logoUrl.orEmpty(),
reviewsCount = reviewsCount,
ratingGoodReview = ratingGoodReview,
ratingGoodReviewVoteCount = ratingGoodReviewVoteCount,
ratingKinopoisk = ratingKinopoisk,
ratingKinopoiskVoteCount = ratingKinopoiskVoteCount,
ratingImdb = ratingImdb,
ratingImdbVoteCount = ratingImdbVoteCount,
ratingFilmCritics = ratingFilmCritics,
ratingFilmCriticsVoteCount = ratingFilmCriticsVoteCount,
ratingAwait = ratingAwait,
ratingAwaitCount = ratingAwaitCount,
ratingRfCritics = ratingRfCritics,
ratingRfCriticsVoteCount = ratingRfCriticsVoteCount,
webUrl = webUrl.orEmpty(),
year = year,
filmLength = filmLength,
slogan = slogan.orEmpty(),
description = description,
shortDescription = shortDescription.orEmpty(),
editorAnnotation = editorAnnotation.orEmpty(),
isTicketsAvailable = isTicketsAvailable ?: false,
productionStatus = FilmProductionStatusNetwork.fromValue(productionStatus.orEmpty()),
type = type,
ratingMpaa = ratingMpaa,
ratingAgeLimits = ratingAgeLimits,
hasImax = hasImax ?: false,
has3D = has3D ?: false,
lastSync = lastSync,
countries = countries?.map { it.country }.orEmpty(),
genres = genres?.map { it.genre }.orEmpty(),
startYear = startYear,
endYear = endYear,
isSerial = serial ?: false,
isShortFilm = shortFilm ?: false,
isCompleted = completed ?: false
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.stslex.core.network.api.kinopoisk.model.network

data class FilmItemNetwork(
val kinopoiskId: Int,
val imdbId: String,
val nameRu: String,
val nameEn: String,
val nameOriginal: String,
val countries: List<String>,
val genres: List<String>,
val ratingKinopoisk: Double?,
val ratingImdb: Double?,
val year: Int?,
val type: FilmTypeNetwork,
val posterUrl: String,
val posterUrlPreview: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.stslex.core.network.api.kinopoisk.model.network

data class FilmListNetwork(
val total: Int,
val totalPages: Int,
val items: List<FilmItemNetwork>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.stslex.core.network.api.kinopoisk.model.network

enum class FilmProductionStatusNetwork(val value: String) {
FILMING("FILMING"),
PRE_PRODUCTION("PRE_PRODUCTION"),
COMPLETED("COMPLETED"),
ANNOUNCED("ANNOUNCED"),
UNKNOWN("UNKNOWN"),
POST_PRODUCTION("POST_PRODUCTION");

companion object {
fun fromValue(value: String) = FilmProductionStatusNetwork
.entries
.firstOrNull { it.value == value }
?: UNKNOWN
}
}
Loading
Loading