Skip to content

Commit

Permalink
Update project
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbel committed Oct 28, 2023
1 parent a3623d9 commit d6d605f
Show file tree
Hide file tree
Showing 41 changed files with 822 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ internal object MoviesEvents {

const val SETTINGS_SELECT_LANGUAGE = "select_language"
const val SETTINGS_SELECT_THEME = "select_theme"
const val SETTINGS_FEED_VIEW = "select_feed_view"
const val SETTINGS_CHANGE_DYNAMIC_COLORS = "change_dynamic_colors"
const val SETTINGS_CHANGE_RTL_ENABLED = "change_rtl_enabled"
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ internal object MoviesParams {

const val PARAM_SELECTED_LANGUAGE = "selected_language"
const val PARAM_SELECTED_THEME = "selected_theme"
const val PARAM_SELECTED_FEED_VIEW = "selected_feed_view"
const val PARAM_DYNAMIC_COLORS_ENABLED = "dynamic_colors_enabled"
const val PARAM_RTL_ENABLED = "rtl_enabled"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.michaelbel.movies.analytics.event

import org.michaelbel.movies.analytics.constants.MoviesEvents
import org.michaelbel.movies.analytics.constants.MoviesParams
import org.michaelbel.movies.analytics.model.BaseEvent

class SelectFeedViewEvent(
feedView: String
): BaseEvent(MoviesEvents.SETTINGS_FEED_VIEW) {

init {
add(MoviesParams.PARAM_SELECTED_FEED_VIEW, feedView)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.michaelbel.movies.common.appearance

import org.michaelbel.movies.common.appearance.exceptions.InvalidFeedViewException

sealed interface FeedView {

data object List: FeedView

data object Grid: FeedView

companion object {
fun transform(name: String): FeedView {
return when (name) {
List.toString() -> List
Grid.toString() -> Grid
else -> throw InvalidFeedViewException
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.michaelbel.movies.common.appearance.exceptions

internal data object InvalidFeedViewException: Exception("Invalid feed view") {
private fun readResolve(): Any = InvalidFeedViewException
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.michaelbel.movies.domain.ktx

import org.michaelbel.movies.entities.image.formatBackdropImage
import org.michaelbel.movies.entities.image.formatPosterImage
import org.michaelbel.movies.network.model.MovieResponse
import org.michaelbel.movies.persistence.database.entity.MovieDb

Expand All @@ -11,7 +12,7 @@ internal fun MovieResponse.mapToMovieDb(movieList: String, position: Int): Movie
position = position,
movieId = id,
overview = overview.orEmpty(),
posterPath = posterPath.orEmpty(),
posterPath = posterPath.orEmpty().formatPosterImage,
backdropPath = backdropPath.orEmpty().formatBackdropImage,
releaseDate = releaseDate,
title = title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ package org.michaelbel.movies.entities.image
private const val TMDB_IMAGE_BASE_URL = "https://image.tmdb.org/t/p/%s%s"
private const val IMAGE_EMPTY_URL = "https://null"

val String.formatPosterImage: String
get() = String.format(TMDB_IMAGE_BASE_URL, PosterSize.W780.size, this).ifEmpty { IMAGE_EMPTY_URL }

val String.formatBackdropImage: String
get() = String.format(TMDB_IMAGE_BASE_URL, BackdropSize.W1280.size, this).ifEmpty { IMAGE_EMPTY_URL }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import kotlinx.coroutines.withContext
import org.michaelbel.movies.analytics.MoviesAnalytics
import org.michaelbel.movies.analytics.event.ChangeDynamicColorsEvent
import org.michaelbel.movies.analytics.event.ChangeRtlEnabledEvent
import org.michaelbel.movies.analytics.event.SelectFeedViewEvent
import org.michaelbel.movies.analytics.event.SelectThemeEvent
import org.michaelbel.movies.common.appearance.FeedView
import org.michaelbel.movies.common.config.RemoteParams
import org.michaelbel.movies.common.dispatchers.MoviesDispatchers
import org.michaelbel.movies.common.googleapi.GoogleApi
Expand All @@ -30,6 +32,8 @@ internal class SettingsInteractorImpl @Inject constructor(

override val currentTheme: Flow<AppTheme> = settingsRepository.currentTheme

override val currentFeedView: Flow<FeedView> = settingsRepository.currentFeedView

override val dynamicColors: Flow<Boolean> = settingsRepository.dynamicColors

override val layoutDirection: Flow<LayoutDirection> = settingsRepository.layoutDirection
Expand All @@ -49,6 +53,11 @@ internal class SettingsInteractorImpl @Inject constructor(
analytics.logEvent(SelectThemeEvent(appTheme.toString()))
}

override suspend fun selectFeedView(feedView: FeedView) = withContext(dispatchers.main) {
settingsRepository.selectFeedView(feedView)
analytics.logEvent(SelectFeedViewEvent(feedView.toString()))
}

override suspend fun setDynamicColors(value: Boolean) = withContext(dispatchers.main) {
settingsRepository.setDynamicColors(value)
analytics.logEvent(ChangeDynamicColorsEvent(value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package org.michaelbel.movies.interactor

import androidx.compose.ui.unit.LayoutDirection
import kotlinx.coroutines.flow.Flow
import org.michaelbel.movies.common.appearance.FeedView
import org.michaelbel.movies.common.theme.AppTheme
import org.michaelbel.movies.common.version.AppVersionData

interface SettingsInteractor {

val currentTheme: Flow<AppTheme>

val currentFeedView: Flow<FeedView>

val dynamicColors: Flow<Boolean>

val layoutDirection: Flow<LayoutDirection>
Expand All @@ -23,6 +26,8 @@ interface SettingsInteractor {

suspend fun selectTheme(appTheme: AppTheme)

suspend fun selectFeedView(feedView: FeedView)

suspend fun setDynamicColors(value: Boolean)

suspend fun setRtlEnabled(value: Boolean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class DelayUseCase @Inject constructor(
private val preferences: MoviesPreferences
): UseCase<Int, Unit>(dispatchers.io) {

val networkRequestDelay: Flow<Int> = preferences.networkRequestDelay.map { networkRequestDelay ->
val networkRequestDelay: Flow<Int> = preferences.networkRequestDelayFlow.map { networkRequestDelay ->
networkRequestDelay ?: 0
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.michaelbel.movies.interactor.usecase

import org.michaelbel.movies.common.appearance.FeedView
import org.michaelbel.movies.interactor.Interactor
import javax.inject.Inject

class SelectFeedViewCase @Inject constructor(
private val interactor: Interactor
) {
suspend operator fun invoke(feedView: FeedView) {
interactor.selectFeedView(feedView)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,49 @@ import javax.inject.Inject
class MoviesPreferences @Inject constructor(
private val dataStore: DataStore<Preferences>
) {
val theme: Flow<Int?>

val themeFlow: Flow<Int?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_THEME_KEY] }

val feedViewFlow: Flow<String?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_FEED_VIEW_KEY] }

val isDynamicColorsFlow: Flow<Boolean?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_DYNAMIC_COLORS_KEY] }

val isRtlEnabledFlow: Flow<Boolean?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_RTL_ENABLED_KEY] }

val networkRequestDelayFlow: Flow<Int?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_NETWORK_REQUEST_DELAY_KEY] }

val accountIdFlow: Flow<Int?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_ACCOUNT_ID_KEY] }

suspend fun setTheme(theme: Int) {
dataStore.edit { preferences ->
preferences[PREFERENCE_THEME_KEY] = theme
}
}

val isDynamicColors: Flow<Boolean?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_DYNAMIC_COLORS_KEY] }
suspend fun setFeedView(feedView: String) {
dataStore.edit { preferences ->
preferences[PREFERENCE_FEED_VIEW_KEY] = feedView
}
}

suspend fun setDynamicColors(isDynamicColors: Boolean) {
dataStore.edit { preferences ->
preferences[PREFERENCE_DYNAMIC_COLORS_KEY] = isDynamicColors
}
}

val isRtlEnabled: Flow<Boolean?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_RTL_ENABLED_KEY] }

suspend fun setRtlEnabled(isRtlEnabled: Boolean) {
dataStore.edit { preferences ->
preferences[PREFERENCE_RTL_ENABLED_KEY] = isRtlEnabled
}
}

val networkRequestDelay: Flow<Int?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_NETWORK_REQUEST_DELAY_KEY] }

suspend fun getNetworkRequestDelay(): Long? {
return dataStore.data.first()[PREFERENCE_NETWORK_REQUEST_DELAY_KEY]?.toLong()
}
Expand All @@ -71,9 +84,6 @@ class MoviesPreferences @Inject constructor(
}
}

val accountId: Flow<Int?>
get() = dataStore.data.map { preferences -> preferences[PREFERENCE_ACCOUNT_ID_KEY] }

suspend fun getAccountId(): Int? {
return dataStore.data.first()[PREFERENCE_ACCOUNT_ID_KEY]
}
Expand Down Expand Up @@ -112,6 +122,7 @@ class MoviesPreferences @Inject constructor(

private companion object {
private val PREFERENCE_THEME_KEY: Preferences.Key<Int> = intPreferencesKey("theme")
private val PREFERENCE_FEED_VIEW_KEY: Preferences.Key<String> = stringPreferencesKey("feed_view")
private val PREFERENCE_DYNAMIC_COLORS_KEY: Preferences.Key<Boolean> = booleanPreferencesKey("dynamic_colors")
private val PREFERENCE_RTL_ENABLED_KEY: Preferences.Key<Boolean> = booleanPreferencesKey("rtl_enabled")
private val PREFERENCE_NETWORK_REQUEST_DELAY_KEY: Preferences.Key<Int> = intPreferencesKey("network_request_delay")
Expand Down
6 changes: 6 additions & 0 deletions core/repository-impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ android {
}
}*/

kotlinOptions {
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
)
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class AccountRepositoryImpl @Inject constructor(
private val preferences: MoviesPreferences
): AccountRepository {

override val account: Flow<AccountDb?> = preferences.accountId
override val account: Flow<AccountDb?> = preferences.accountIdFlow
.map { accountId -> accountId ?: 0 }
.flatMapLatest(accountDao::accountById)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import org.michaelbel.movies.common.BuildConfig
import org.michaelbel.movies.common.appearance.FeedView
import org.michaelbel.movies.common.theme.AppTheme
import org.michaelbel.movies.common.version.AppVersionData
import org.michaelbel.movies.persistence.datastore.MoviesPreferences
Expand All @@ -22,15 +23,19 @@ internal class SettingsRepositoryImpl @Inject constructor(
private val preferences: MoviesPreferences
): SettingsRepository {

override val currentTheme: Flow<AppTheme> = preferences.theme.map { theme ->
override val currentTheme: Flow<AppTheme> = preferences.themeFlow.map { theme ->
AppTheme.transform(theme ?: AppTheme.FollowSystem.theme)
}

override val dynamicColors: Flow<Boolean> = preferences.isDynamicColors.map { isDynamicColors ->
override val currentFeedView: Flow<FeedView> = preferences.feedViewFlow.map { feedView ->
FeedView.transform(feedView ?: FeedView.List.toString())
}

override val dynamicColors: Flow<Boolean> = preferences.isDynamicColorsFlow.map { isDynamicColors ->
isDynamicColors ?: (Build.VERSION.SDK_INT >= 31)
}

override val layoutDirection: Flow<LayoutDirection> = preferences.isRtlEnabled.map { isRtlEnabled ->
override val layoutDirection: Flow<LayoutDirection> = preferences.isRtlEnabledFlow.map { isRtlEnabled ->
if (isRtlEnabled == true) LayoutDirection.Rtl else LayoutDirection.Ltr
}

Expand All @@ -46,6 +51,10 @@ internal class SettingsRepositoryImpl @Inject constructor(
preferences.setTheme(appTheme.theme)
}

override suspend fun selectFeedView(feedView: FeedView) {
preferences.setFeedView(feedView.toString())
}

override suspend fun setDynamicColors(value: Boolean) {
preferences.setDynamicColors(value)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.michaelbel.movies.repository.ktx

import org.michaelbel.movies.entities.image.formatBackdropImage
import org.michaelbel.movies.entities.image.formatPosterImage
import org.michaelbel.movies.network.model.Movie
import org.michaelbel.movies.persistence.database.entity.MovieDb

Expand All @@ -11,7 +12,7 @@ internal val Movie.mapToMovieDb: MovieDb
position = 0,
movieId = id,
overview = overview.orEmpty(),
posterPath = posterPath.orEmpty(),
posterPath = posterPath.orEmpty().formatPosterImage,
backdropPath = backdropPath.orEmpty().formatBackdropImage,
releaseDate = releaseDate.orEmpty(),
title = title.orEmpty(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.michaelbel.movies.repository.ktx

import org.michaelbel.movies.entities.image.formatBackdropImage
import org.michaelbel.movies.entities.image.formatPosterImage
import org.michaelbel.movies.network.model.MovieResponse
import org.michaelbel.movies.persistence.database.entity.MovieDb

Expand All @@ -11,7 +12,7 @@ internal fun MovieResponse.mapToMovieDb(movieList: String, position: Int): Movie
position = position,
movieId = id,
overview = overview.orEmpty(),
posterPath = posterPath.orEmpty(),
posterPath = posterPath.orEmpty().formatPosterImage,
backdropPath = backdropPath.orEmpty().formatBackdropImage,
releaseDate = releaseDate,
title = title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package org.michaelbel.movies.repository

import androidx.compose.ui.unit.LayoutDirection
import kotlinx.coroutines.flow.Flow
import org.michaelbel.movies.common.appearance.FeedView
import org.michaelbel.movies.common.theme.AppTheme
import org.michaelbel.movies.common.version.AppVersionData

interface SettingsRepository {

val currentTheme: Flow<AppTheme>

val currentFeedView: Flow<FeedView>

val dynamicColors: Flow<Boolean>

val layoutDirection: Flow<LayoutDirection>
Expand All @@ -17,6 +20,8 @@ interface SettingsRepository {

suspend fun selectTheme(appTheme: AppTheme)

suspend fun selectFeedView(feedView: FeedView)

suspend fun setDynamicColors(value: Boolean)

suspend fun setRtlEnabled(value: Boolean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.material.icons.filled.MovieFilter
import androidx.compose.material.icons.outlined.AccountCircle
import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.GridView
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Language
import androidx.compose.material.icons.outlined.LocationOn
Expand All @@ -32,6 +33,7 @@ object MoviesIcons {
val ArrowBack: ImageVector = Icons.Outlined.ArrowBack
val Close: ImageVector = Icons.Outlined.Close
val Info: ImageVector = Icons.Outlined.Info
val GridView: ImageVector = Icons.Outlined.GridView
val Language: ImageVector = Icons.Outlined.Language
val LocationOn: ImageVector = Icons.Outlined.LocationOn
val MovieFilter: ImageVector = Icons.Filled.MovieFilter
Expand Down
Loading

0 comments on commit d6d605f

Please sign in to comment.