Skip to content

Commit

Permalink
Initial videolibray module
Browse files Browse the repository at this point in the history
- feat:  Implement search videos Pixabay API of the videolibray module
  • Loading branch information
azrael8576 committed Dec 5, 2023
1 parent 0765fbf commit 42f57ac
Show file tree
Hide file tree
Showing 24 changed files with 430 additions and 4 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ android {
dependencies {
implementation(project(":feature:home"))
implementation(project(":feature:photo"))
implementation(project(":feature:video"))
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 @@ -10,6 +10,7 @@ import com.wei.picquest.feature.home.home.navigation.homeGraph
import com.wei.picquest.feature.home.home.navigation.homeRoute
import com.wei.picquest.feature.photo.photolibrary.navigation.photoLibraryGraph
import com.wei.picquest.feature.photo.photosearch.navigation.photoSearchGraph
import com.wei.picquest.feature.video.videolibrary.navigation.videoLibraryGraph
import com.wei.picquest.ui.PqAppState

/**
Expand Down Expand Up @@ -45,6 +46,9 @@ fun PqNavHost(
photoLibraryGraph(navController = navController)
},
)
videoLibraryGraph(
navController = navController,
)
contactMeGraph(
navController = navController,
contentType = contentType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ enum class TopLevelDestination(
iconTextId = R.string.photo,
titleTextId = R.string.photo,
),
VIDEO(
selectedIcon = PqIcons.VideoLibrary,
unselectedIcon = PqIcons.VideoLibraryBorder,
iconTextId = R.string.video,
titleTextId = R.string.video,
),
CONTACT_ME(
selectedIcon = PqIcons.ContactMe,
unselectedIcon = PqIcons.ContactMeBorder,
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/wei/picquest/ui/PqAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import com.wei.picquest.feature.home.home.navigation.homeRoute
import com.wei.picquest.feature.home.home.navigation.navigateToHome
import com.wei.picquest.feature.photo.photosearch.navigation.navigateToPhotoSearch
import com.wei.picquest.feature.photo.photosearch.navigation.photoSearchRoute
import com.wei.picquest.feature.video.videolibrary.navigation.navigateToVideoLibrary
import com.wei.picquest.feature.video.videolibrary.navigation.videoLibraryRoute
import com.wei.picquest.navigation.TopLevelDestination
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
Expand Down Expand Up @@ -154,6 +156,7 @@ class PqAppState(
@Composable get() = when (currentDestination?.route) {
homeRoute -> TopLevelDestination.HOME
photoSearchRoute -> TopLevelDestination.PHOTO
videoLibraryRoute -> TopLevelDestination.VIDEO
contactMeRoute -> TopLevelDestination.CONTACT_ME
else -> null
}
Expand Down Expand Up @@ -206,6 +209,10 @@ class PqAppState(
topLevelNavOptions,
)

TopLevelDestination.VIDEO -> navController.navigateToVideoLibrary(
topLevelNavOptions,
)

TopLevelDestination.CONTACT_ME -> navController.navigateToContactMe(
topLevelNavOptions,
)
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
<string name="photo">照片</string>
<string name="home">首頁</string>
<string name="contact_me">聯絡我</string>
<string name="video">影片</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<string name="photo">Photo</string>
<string name="home">Home</string>
<string name="contact_me">Contact Me</string>
<string name="video">Video</string>

<!-- Test tag -->
<string name="tag_pq_bottom_bar" translatable="false">PqBottomBar</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.wei.picquest.core.data.model

import com.wei.picquest.core.network.model.NetworkVideoDetail
import com.wei.picquest.core.network.model.NetworkVideoDetailSize
import com.wei.picquest.core.network.model.NetworkVideoStreams

data class VideoDetail(
val id: Int,
val pageURL: String,
val type: String,
val tags: String,
val duration: Int,
val pictureId: String,
val videos: VideoStreams,
val views: Int,
val downloads: Int,
val likes: Int,
val comments: Int,
val userId: Int,
val user: String,
val userImageURL: String,
)

data class VideoStreams(
val large: VideoDetailSize,
val medium: VideoDetailSize,
val small: VideoDetailSize,
val tiny: VideoDetailSize,
)

data class VideoDetailSize(
val url: String,
val width: Int,
val height: Int,
val size: Long,
)

fun NetworkVideoDetail.asExternalModel() = VideoDetail(
id = this.id,
pageURL = this.pageURL,
type = this.type,
tags = this.tags,
duration = this.duration,
pictureId = this.pictureId,
videos = this.videos.asExternalModel(),
views = this.views,
downloads = this.downloads,
likes = this.likes,
comments = this.comments,
userId = this.userId,
user = this.user,
userImageURL = this.userImageURL,
)

fun NetworkVideoStreams.asExternalModel() = VideoStreams(
large = this.large.asExternalModel(),
medium = this.medium.asExternalModel(),
small = this.small.asExternalModel(),
tiny = this.tiny.asExternalModel(),
)

fun NetworkVideoDetailSize.asExternalModel() = VideoDetailSize(
url = this.url,
width = this.width,
height = this.height,
size = this.size,
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ 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.pagingsource.PixabayPagingSource
import com.wei.picquest.core.network.pagingsource.PixabayImagePagingSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
Expand All @@ -23,7 +23,7 @@ class DefaultSearchImagesRepository @Inject constructor(
prefetchDistance = 5,
enablePlaceholders = false,
),
pagingSourceFactory = { PixabayPagingSource(pqNetworkDataSource, query) },
pagingSourceFactory = { PixabayImagePagingSource(pqNetworkDataSource, query) },
).flow.map { pagingData ->
pagingData.map { it.asExternalModel() }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.wei.picquest.core.data.repository

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.map
import com.wei.picquest.core.data.model.VideoDetail
import com.wei.picquest.core.data.model.asExternalModel
import com.wei.picquest.core.network.PqNetworkDataSource
import com.wei.picquest.core.network.pagingsource.PixabayVideoPagingSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class DefaultSearchVideoRepository @Inject constructor(
private val pqNetworkDataSource: PqNetworkDataSource,
) : SearchVideoRepository {

override suspend fun getSearchVideo(query: String): Flow<PagingData<VideoDetail>> {
return Pager(
config = PagingConfig(
pageSize = 20,
prefetchDistance = 5,
enablePlaceholders = false,
),
pagingSourceFactory = { PixabayVideoPagingSource(pqNetworkDataSource, query) },
).flow.map { pagingData ->
pagingData.map { it.asExternalModel() }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.wei.picquest.core.data.repository

import androidx.paging.PagingData
import com.wei.picquest.core.data.model.VideoDetail
import kotlinx.coroutines.flow.Flow

interface SearchVideoRepository {

suspend fun getSearchVideo(query: String): Flow<PagingData<VideoDetail>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.PhotoLibrary
import androidx.compose.material.icons.outlined.SupportAgent
import androidx.compose.material.icons.outlined.Upcoming
import androidx.compose.material.icons.outlined.VideoLibrary
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.ArrowBackIosNew
Expand All @@ -25,6 +26,7 @@ import androidx.compose.material.icons.rounded.Settings
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.SupportAgent
import androidx.compose.material.icons.rounded.Upcoming
import androidx.compose.material.icons.rounded.VideoLibrary
import androidx.compose.ui.graphics.vector.ImageVector

/**
Expand All @@ -46,6 +48,8 @@ object PqIcons {
val ContactMeBorder = Icons.Outlined.SupportAgent
val PhotoLibrary = Icons.Rounded.PhotoLibrary
val PhotoLibraryBorder = Icons.Outlined.PhotoLibrary
val VideoLibrary = Icons.Rounded.VideoLibrary
val VideoLibraryBorder = Icons.Outlined.VideoLibrary
val Phone = Icons.Rounded.Phone
val Upcoming = Icons.Rounded.Upcoming
val UpcomingBorder = Icons.Outlined.Upcoming
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.wei.picquest.core.network

import com.wei.picquest.core.network.model.NetworkSearchImages
import com.wei.picquest.core.network.model.NetworkSearchVideos

/**
* Interface representing network calls to the PicQuest backend
*/
interface PqNetworkDataSource {

suspend fun searchImages(query: String, page: Int, perPage: Int): NetworkSearchImages

suspend fun searchVideos(query: String, page: Int, perPage: Int): NetworkSearchVideos
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Network representation of [SearchImages] when fetched from /
* Network representation of [NetworkSearchImages] when fetched from /
*/
@Serializable
data class NetworkSearchImages(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.wei.picquest.core.network.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Network representation of [NetworkSearchVideos] when fetched from /videos/
*/
@Serializable
data class NetworkSearchVideos(
@SerialName("total")
val total: Int,
@SerialName("totalHits")
val totalHits: Int,
@SerialName("hits")
val hits: List<NetworkVideoDetail>,
)

@Serializable
data class NetworkVideoDetail(
@SerialName("id")
val id: Int,
@SerialName("pageURL")
val pageURL: String,
@SerialName("type")
val type: String,
@SerialName("tags")
val tags: String,
@SerialName("duration")
val duration: Int,
@SerialName("picture_id")
val pictureId: String,
@SerialName("videos")
val videos: NetworkVideoStreams,
@SerialName("views")
val views: Int,
@SerialName("downloads")
val downloads: Int,
@SerialName("likes")
val likes: Int,
@SerialName("comments")
val comments: Int,
@SerialName("user_id")
val userId: Int,
@SerialName("user")
val user: String,
@SerialName("userImageURL")
val userImageURL: String,
)

@Serializable
data class NetworkVideoStreams(
@SerialName("large")
val large: NetworkVideoDetailSize,
@SerialName("medium")
val medium: NetworkVideoDetailSize,
@SerialName("small")
val small: NetworkVideoDetailSize,
@SerialName("tiny")
val tiny: NetworkVideoDetailSize,
)

@Serializable
data class NetworkVideoDetailSize(
@SerialName("url")
val url: String,
@SerialName("width")
val width: Int,
@SerialName("height")
val height: Int,
@SerialName("size")
val size: Long,
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.paging.PagingState
import com.wei.picquest.core.network.PqNetworkDataSource
import com.wei.picquest.core.network.model.NetworkImageDetail

class PixabayPagingSource(
class PixabayImagePagingSource(
private val pqNetworkDataSource: PqNetworkDataSource,
private val query: String,
) : PagingSource<Int, NetworkImageDetail>() {
Expand Down
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.NetworkVideoDetail

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

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, NetworkVideoDetail> {
try {
val currentPage = params.key ?: 1
val response = pqNetworkDataSource.searchVideos(
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, NetworkVideoDetail>): Int? {
return state.anchorPosition
}
}
Loading

0 comments on commit 42f57ac

Please sign in to comment.