Skip to content

Commit

Permalink
refactor network layer (simplify)
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Mar 30, 2024
1 parent 5ea0b53 commit 0b55995
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package st.slex.csplashscreen.core.network.client

import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get

interface NetworkClient {

suspend fun <T> request(request: suspend HttpClient.() -> T): T
}

internal suspend inline fun <reified T> NetworkClient.get(
crossinline builder: suspend HttpRequestBuilder.() -> Unit
): T = request {
get {
builder()
}.body()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package st.slex.csplashscreen.core.network.client

import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.android.Android
import io.ktor.client.engine.android.AndroidEngineConfig
import io.ktor.client.plugins.cache.HttpCache
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.defaultRequest
import io.ktor.client.plugins.logging.ANDROID
import io.ktor.client.plugins.logging.EMPTY
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.headers
import io.ktor.http.URLProtocol
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import st.slex.csplashscreen.core.core.coroutine.AppDispatcher
import st.slex.csplashscreen.core.network.client.NetworkClientBuilder.setupDefaultRequest
import st.slex.csplashscreen.core.network.client.NetworkClientBuilder.setupLogging
import st.slex.csplashscreen.core.network.client.NetworkClientBuilder.setupNegotiation
import st.slex.csplashscreen.core.network.BuildConfig
import javax.inject.Inject
import javax.inject.Singleton

Expand All @@ -29,4 +41,52 @@ class NetworkClientImpl @Inject constructor(
expectSuccess = true
setupDefaultRequest()
}

@OptIn(ExperimentalSerializationApi::class)
fun HttpClientConfig<AndroidEngineConfig>.setupNegotiation() {
install(ContentNegotiation) {
json(
Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
explicitNulls = false
}
)
}
}

fun HttpClientConfig<AndroidEngineConfig>.setupDefaultRequest() {
defaultRequest {
url {
host = HOST_URL
protocol = URLProtocol.HTTPS
}
headers {
append(
HEADER_AUTH,
"$HEADER_AUTH_FIELD ${BuildConfig.API_KEY}"
)
}
}
}

fun HttpClientConfig<AndroidEngineConfig>.setupLogging() {
install(Logging) {
logger = when (st.slex.csplashscreen.core.core.BuildConfig.DEBUG) {
true -> Logger.ANDROID
false -> Logger.EMPTY
}
level = when (st.slex.csplashscreen.core.core.BuildConfig.DEBUG) {
true -> LogLevel.ALL
false -> LogLevel.NONE
}
}
}

companion object {
private const val HOST_URL = "api.unsplash.com"
private const val HEADER_AUTH = "Authorization"
private const val HEADER_AUTH_FIELD = "Client-ID"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package st.slex.csplashscreen.core.network.source.impl

import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.http.appendPathSegments
import st.slex.csplashscreen.core.network.client.NetworkClient
import st.slex.csplashscreen.core.network.client.get
import st.slex.csplashscreen.core.network.model.remote.collection.RemoteCollectionModel
import st.slex.csplashscreen.core.network.source.interf.CollectionNetworkClient
import st.slex.csplashscreen.core.network.utils.ServiceConstants.PARAMETER_PAGE
Expand All @@ -22,24 +21,19 @@ class CollectionNetworkClientImpl @Inject constructor(
override suspend fun getCollections(
page: Int,
pageSize: Int
): List<RemoteCollectionModel> = client.request {
get {
url.appendPathSegments(PATH_COLLECTIONS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body()
): List<RemoteCollectionModel> = client.get {
url.appendPathSegments(PATH_COLLECTIONS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}


override suspend fun getUserCollections(
username: String,
page: Int,
pageSize: Int
): List<RemoteCollectionModel> = client.request {
get {
url.appendPathSegments(PATH_USERS, username, PATH_COLLECTIONS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body()
): List<RemoteCollectionModel> = client.get {
url.appendPathSegments(PATH_USERS, username, PATH_COLLECTIONS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package st.slex.csplashscreen.core.network.source.impl

import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.http.appendPathSegments
import st.slex.csplashscreen.core.network.client.NetworkClient
import st.slex.csplashscreen.core.network.client.get
import st.slex.csplashscreen.core.network.model.remote.download.RemoteDownloadModel
import st.slex.csplashscreen.core.network.model.remote.image.RemoteImageModel
import st.slex.csplashscreen.core.network.source.interf.PhotosNetworkClient
Expand All @@ -18,6 +17,9 @@ import st.slex.csplashscreen.core.network.utils.ServiceConstants.PATH_TOPICS
import st.slex.csplashscreen.core.network.utils.ServiceConstants.PATH_USERS
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.collections.List
import kotlin.collections.mutableMapOf
import kotlin.collections.set

@Singleton
class PhotosNetworkClientImpl @Inject constructor(
Expand All @@ -34,81 +36,68 @@ class PhotosNetworkClientImpl @Inject constructor(

override suspend fun getCollectionPhotos(
query: String, page: Int, pageSize: Int
): List<RemoteImageModel> = collectionPhotos[page] ?: client.request {
get {
url.appendPathSegments(PATH_COLLECTIONS, query, PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body<List<RemoteImageModel>>().also { result ->
collectionPhotos[page] = result
}
): List<RemoteImageModel> = collectionPhotos[page] ?: client.get<List<RemoteImageModel>> {
url.appendPathSegments(PATH_COLLECTIONS, query, PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.also { result ->
collectionPhotos[page] = result
}

override suspend fun getPhotos(
page: Int, pageSize: Int
): List<RemoteImageModel> = photos[page] ?: client.request {
get {
url.appendPathSegments(PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body<List<RemoteImageModel>>().also { result ->
photos[page] = result
}
): List<RemoteImageModel> = photos[page] ?: client.get<List<RemoteImageModel>> {
url.appendPathSegments(PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.also { result ->
photos[page] = result
}

override suspend fun getUserPhotos(
username: String, page: Int, pageSize: Int
): List<RemoteImageModel> = userPhotos[page] ?: client.request {
get {
url.appendPathSegments(PATH_USERS, username, PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body<List<RemoteImageModel>>().also { result ->
userPhotos[page] = result
}
): List<RemoteImageModel> = userPhotos[page] ?: client.get<List<RemoteImageModel>> {
url.appendPathSegments(PATH_USERS, username, PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.also { result ->
userPhotos[page] = result
}

override suspend fun getUserLikePhotos(
username: String, page: Int, pageSize: Int
): List<RemoteImageModel> = userLikePhotos[page] ?: client.request {
get {
url.appendPathSegments(PATH_USERS, username, PATH_LIKES)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body<List<RemoteImageModel>>().also { result ->
userLikePhotos[page] = result
}
): List<RemoteImageModel> = userLikePhotos[page] ?: client.get<List<RemoteImageModel>> {
url.appendPathSegments(PATH_USERS, username, PATH_LIKES)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.also { result ->
userLikePhotos[page] = result
}

override suspend fun getTopicPhotos(
topicId: String, page: Int, pageSize: Int
): List<RemoteImageModel> = userTopicPhotos[page] ?: client.request {
get {
url.appendPathSegments(PATH_TOPICS, topicId, PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body<List<RemoteImageModel>>().also { result ->
userTopicPhotos[page] = result
}
): List<RemoteImageModel> = userTopicPhotos[page] ?: client.get<List<RemoteImageModel>> {
url.appendPathSegments(PATH_TOPICS, topicId, PATH_PHOTOS)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.also { result ->
userTopicPhotos[page] = result
}

override suspend fun getSinglePhoto(
id: String
): RemoteImageModel = singlePhoto[id] ?: client.request {
get {
url.appendPathSegments(PATH_PHOTOS, id)
}.body<RemoteImageModel>().also { result ->
singlePhoto[id] = result
}
): RemoteImageModel = singlePhoto[id] ?: client.get<RemoteImageModel> {
url.appendPathSegments(PATH_PHOTOS, id)
}.also { result ->
singlePhoto[id] = result
}

override suspend fun getDownloadLink(
id: String
): RemoteDownloadModel = downloadLink[id] ?: client.request {
get {
): RemoteDownloadModel = downloadLink[id]
?: client.get<RemoteDownloadModel> {
url.appendPathSegments(PATH_PHOTOS, id, PATH_DOWNLOAD)
}.body<RemoteDownloadModel>().also { result ->
}.also { result ->
downloadLink[id] = result
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package st.slex.csplashscreen.core.network.source.impl

import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.http.appendPathSegments
import st.slex.csplashscreen.core.network.client.NetworkClient
import st.slex.csplashscreen.core.network.client.get
import st.slex.csplashscreen.core.network.model.remote.image.RemoteImageSearchModel
import st.slex.csplashscreen.core.network.source.interf.SearchPhotosNetworkSource
import st.slex.csplashscreen.core.network.utils.ServiceConstants.PARAMETER_PAGE
Expand All @@ -24,12 +23,10 @@ class SearchPhotosNetworkSourceImpl @Inject constructor(
query: String,
page: Int,
pageSize: Int
): RemoteImageSearchModel = client.request {
get {
url.appendPathSegments(PATH_SEARCH, PATH_PHOTOS)
parameter(PARAMETER_QUERY, query)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}.body()
): RemoteImageSearchModel = client.get {
url.appendPathSegments(PATH_SEARCH, PATH_PHOTOS)
parameter(PARAMETER_QUERY, query)
parameter(PARAMETER_PAGE, page)
parameter(PARAMETER_PAGE_SIZE, pageSize)
}
}
Loading

0 comments on commit 0b55995

Please sign in to comment.