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

Initial photolibray module #8

Merged
merged 2 commits into from
Dec 2, 2023
Merged
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
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ android {

dependencies {
implementation(project(":feature:home"))
implementation(project(":feature:photolibrary"))

// TODO Wei
// implementation(project(":feature:login"))
// implementation(project(":feature:contactme"))

implementation(project(":core:designsystem"))
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.window.layout.DisplayFeature
import com.wei.picquest.core.designsystem.ui.DeviceOrientation
import com.wei.picquest.feature.home.home.navigation.homeGraph
import com.wei.picquest.feature.home.home.navigation.homeRoute
import com.wei.picquest.feature.photolibrary.photolibrary.navigation.photoLibraryGraph
import com.wei.picquest.ui.PqAppState

/**
Expand Down Expand Up @@ -36,5 +37,8 @@ fun PqNavHost(
homeGraph(
navController = navController,
)
photoLibraryGraph(
navController = navController,
)
}
}
11 changes: 7 additions & 4 deletions app/src/main/java/com/wei/picquest/ui/PqAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import com.wei.picquest.core.designsystem.ui.isBookPosture
import com.wei.picquest.core.designsystem.ui.isSeparating
import com.wei.picquest.feature.home.home.navigation.homeRoute
import com.wei.picquest.feature.home.home.navigation.navigateToHome
import com.wei.picquest.feature.photolibrary.photolibrary.navigation.navigateToPhotoLibrary
import com.wei.picquest.feature.photolibrary.photolibrary.navigation.photoLibraryRoute
import com.wei.picquest.navigation.TopLevelDestination
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
Expand Down Expand Up @@ -149,6 +151,7 @@ class PqAppState(
val currentTopLevelDestination: TopLevelDestination?
@Composable get() = when (currentDestination?.route) {
homeRoute -> TopLevelDestination.HOME
photoLibraryRoute -> TopLevelDestination.PHOTO_LIBRARY
else -> null
}

Expand Down Expand Up @@ -196,10 +199,10 @@ class PqAppState(
topLevelNavOptions,
)

// TopLevelDestination.PHOTO_LIBRARY -> navController.navigateToPhotoLibrary(
// topLevelNavOptions,
// )
//
TopLevelDestination.PHOTO_LIBRARY -> navController.navigateToPhotoLibrary(
topLevelNavOptions,
)

// TopLevelDestination.CONTACT_ME -> navController.navigateToContactMe(
// topLevelNavOptions,
// )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
add("androidTestImplementation", kotlin("test"))
add("androidTestImplementation", project(":core:testing"))

// Paging 3
add("implementation", libs.findLibrary("paging-runtime").get())
add("implementation", libs.findLibrary("paging-compose").get())
add("testImplementation", libs.findLibrary("paging-common").get())

// Timber
add("implementation", libs.findLibrary("timber").get())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.wei.picquest.core.data.model

import com.wei.picquest.core.network.model.NetworkImageDetail

data class ImageDetail(
val id: Int,
val pageURL: String,
val type: String,
val tags: String,
val previewURL: String,
val previewWidth: Int,
val previewHeight: Int,
val webformatURL: String,
val webformatWidth: Int,
val webformatHeight: Int,
val largeImageURL: String,
val imageWidth: Int,
val imageHeight: Int,
val imageSize: Long,
val views: Int,
val downloads: Int,
val likes: Int,
val comments: Int,
val userId: Int,
val user: String,
val userImageURL: String,
) {
val aspectRatio get() = imageWidth.toFloat() / imageHeight.toFloat()
}

fun NetworkImageDetail.asExternalModel() = ImageDetail(
id = this.id,
pageURL = this.pageURL,
type = this.type,
tags = this.tags,
previewURL = this.previewURL,
previewWidth = this.previewWidth,
previewHeight = this.previewHeight,
webformatURL = this.webformatURL,
webformatWidth = this.webformatWidth,
webformatHeight = this.webformatHeight,
largeImageURL = this.largeImageURL,
imageWidth = this.imageWidth,
imageHeight = this.imageHeight,
imageSize = this.imageSize,
views = this.views,
downloads = this.downloads,
likes = this.likes,
comments = this.comments,
userId = this.userId,
user = this.user,
userImageURL = this.userImageURL,
)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
package com.wei.picquest.core.data.repository

import com.wei.picquest.core.network.Dispatcher
import com.wei.picquest.core.network.PqDispatchers
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.map
import com.wei.picquest.core.data.model.ImageDetail
import com.wei.picquest.core.data.model.asExternalModel
import com.wei.picquest.core.network.PqNetworkDataSource
import com.wei.picquest.core.network.model.NetworkSearchImages
import kotlinx.coroutines.CoroutineDispatcher
import com.wei.picquest.core.network.pagingsource.PixabayPagingSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withContext
import kotlinx.coroutines.flow.map
import javax.inject.Inject

/**
* Implementation of the [SearchImagesRepository].
* @param ioDispatcher 用於執行 IO 相關操作的 CoroutineDispatcher。
* @param network 數據源的網路接口。
*/
class DefaultSearchImagesRepository @Inject constructor(
@Dispatcher(PqDispatchers.IO) private val ioDispatcher: CoroutineDispatcher,
private val network: PqNetworkDataSource,
private val pqNetworkDataSource: PqNetworkDataSource,
) : SearchImagesRepository {

/**
* @param query。A URL encoded search term. If omitted, all images are returned. This value may not exceed 100 characters.
* Example: "yellow+flower"
* @return 一個 Flow,內容為 Search Images 的數據。
*/
override suspend fun getSearchImages(
query: String,
): Flow<NetworkSearchImages> = withContext(ioDispatcher) {
flow {
emit(network.searchImages(query))
override suspend fun getSearchImages(query: String): Flow<PagingData<ImageDetail>> {
return Pager(
config = PagingConfig(
pageSize = 20,
prefetchDistance = 5,
enablePlaceholders = false,
),
pagingSourceFactory = { PixabayPagingSource(pqNetworkDataSource, query) },
).flow.map { pagingData ->
pagingData.map { it.asExternalModel() }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.wei.picquest.core.data.repository

import com.wei.picquest.core.network.model.NetworkSearchImages
import androidx.paging.PagingData
import com.wei.picquest.core.data.model.ImageDetail
import kotlinx.coroutines.flow.Flow

interface SearchImagesRepository {

suspend fun getSearchImages(query: String): Flow<NetworkSearchImages>
suspend fun getSearchImages(query: String): Flow<PagingData<ImageDetail>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import androidx.compose.material.icons.rounded.ArrowForward
import androidx.compose.material.icons.rounded.ArrowForwardIos
import androidx.compose.material.icons.rounded.CalendarMonth
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.GridView
import androidx.compose.material.icons.rounded.Home
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.List
import androidx.compose.material.icons.rounded.Menu
import androidx.compose.material.icons.rounded.Person
import androidx.compose.material.icons.rounded.Phone
Expand Down Expand Up @@ -55,4 +57,6 @@ object PqIcons {
val Person = Icons.Rounded.Person
val Menu = Icons.Rounded.Menu
val Add = Icons.Rounded.Add
val ListView = Icons.Rounded.List
val GridView = Icons.Rounded.GridView
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import com.wei.picquest.core.network.model.NetworkSearchImages
*/
interface PqNetworkDataSource {

suspend fun searchImages(query: String): NetworkSearchImages
suspend fun searchImages(query: String, page: Int, perPage: Int): NetworkSearchImages
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.wei.picquest.core.network.pagingsource

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.wei.picquest.core.network.PqNetworkDataSource
import com.wei.picquest.core.network.model.NetworkImageDetail

class PixabayPagingSource(
private val pqNetworkDataSource: PqNetworkDataSource,
private val query: String,
) : PagingSource<Int, NetworkImageDetail>() {

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, NetworkImageDetail> {
try {
val currentPage = params.key ?: 1
val response = pqNetworkDataSource.searchImages(
query = query,
page = currentPage,
perPage = 20,
)

val endOfPaginationReached = response.hits.isEmpty()

return LoadResult.Page(
data = response.hits,
prevKey = if (currentPage == 1) null else currentPage - 1,
nextKey = if (endOfPaginationReached) null else currentPage + 1,
)
} catch (exception: Exception) {
return LoadResult.Error(exception)
}
}

override fun getRefreshKey(state: PagingState<Int, NetworkImageDetail>): Int? {
return state.anchorPosition
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ interface RetrofitPixabayApi {
@Query("key") apiKey: String = API_KEY,
@Query("q") query: String,
@Query("image_type") imageType: String = "photo",
@Query("page") page: Int,
@Query("perPage") perPage: Int,
// Add more parameters as needed
): NetworkSearchImages
}
Expand All @@ -50,7 +52,7 @@ class RetrofitPqNetwork @Inject constructor(
.build()
.create(RetrofitPixabayApi::class.java)

override suspend fun searchImages(query: String): NetworkSearchImages {
return pixabayApi.searchImages(query = query)
override suspend fun searchImages(query: String, page: Int, perPage: Int): NetworkSearchImages {
return pixabayApi.searchImages(query = query, page = page, perPage = perPage)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ internal fun HomeRoute(
internal fun HomeScreen(
withTopSpacer: Boolean = true,
withBottomSpacer: Boolean = true,
isPreview: Boolean = false,
) {
val showPopup = remember { mutableStateOf(false) }

Expand Down Expand Up @@ -108,8 +107,6 @@ internal fun HomeScreen(
@Composable
fun HomeScreenPreview() {
PqTheme {
HomeScreen(
isPreview = true,
)
HomeScreen()
}
}
1 change: 1 addition & 0 deletions feature/photolibrary/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
12 changes: 12 additions & 0 deletions feature/photolibrary/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
alias(libs.plugins.pq.android.feature)
alias(libs.plugins.pq.android.library.compose)
alias(libs.plugins.pq.android.hilt)
}

android {
namespace = "com.wei.picquest.feature.photolibrary"
}

dependencies {
}
4 changes: 4 additions & 0 deletions feature/photolibrary/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Loading