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

Account #117

Merged
merged 1 commit into from
Mar 13, 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
13 changes: 4 additions & 9 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,9 @@ android {
}

buildFeatures {
viewBinding = true
compose = true
}

kotlinOptions {
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
"-opt-in=androidx.lifecycle.compose.ExperimentalLifecycleComposeApi",
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi"
)
}

composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}
Expand All @@ -159,6 +150,10 @@ dependencies {
implementation(project(":core:common"))
implementation(project(":core:domain"))
implementation(project(":core:navigation"))
implementation(project(":core:ui"))

implementation(project(":feature:auth"))
implementation(project(":feature:account"))
implementation(project(":feature:details"))
implementation(project(":feature:feed"))
implementation(project(":feature:settings"))
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/kotlin/org/michaelbel/movies/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import dagger.hilt.android.AndroidEntryPoint
import org.michaelbel.movies.common.shortcuts.installShortcuts
import org.michaelbel.movies.common.theme.AppTheme
import org.michaelbel.movies.domain.workers.MoviesDatabaseWorker
import org.michaelbel.movies.ui.shortcuts.installShortcuts
import org.michaelbel.movies.ui.theme.MoviesTheme
import org.michaelbel.movies.ui.theme.model.AppTheme

/**
* Per-App Language depends on AppCompatActivity (not ComponentActivity).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import org.michaelbel.movies.auth.AccountDestination
import org.michaelbel.movies.auth.AuthDestination
import org.michaelbel.movies.auth.accountGraph
import org.michaelbel.movies.auth.authGraph
import org.michaelbel.movies.details.DetailsDestination
import org.michaelbel.movies.details.detailsGraph
import org.michaelbel.movies.feed.FeedDestination
Expand All @@ -20,7 +24,19 @@ internal fun MainActivityContent(
navController = navHostController,
startDestination = startDestination
) {
authGraph(
onBackClick = navHostController::popBackStack
)
accountGraph(
onBackClick = navHostController::popBackStack
)
feedGraph(
navigateToAuth = {
navHostController.navigate(AuthDestination.route)
},
navigateToAccount = {
navHostController.navigate(AccountDestination.route)
},
navigateToSettings = {
navHostController.navigate(SettingsDestination.route)
},
Expand Down
23 changes: 12 additions & 11 deletions app/src/main/kotlin/org/michaelbel/movies/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,54 @@ package org.michaelbel.movies

import android.os.Bundle
import androidx.compose.ui.unit.LayoutDirection
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavDestination
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.michaelbel.movies.analytics.MoviesAnalytics
import org.michaelbel.movies.common.theme.AppTheme
import org.michaelbel.movies.common.viewmodel.BaseViewModel
import org.michaelbel.movies.domain.interactor.settings.SettingsInteractor
import org.michaelbel.movies.ui.theme.model.AppTheme
import javax.inject.Inject

@HiltViewModel
internal class MainViewModel @Inject constructor(
private val settingsInteractor: SettingsInteractor,
private val analytics: MoviesAnalytics
): ViewModel() {
): BaseViewModel() {

val currentTheme: StateFlow<AppTheme> = settingsInteractor.currentTheme
.stateIn(
scope = viewModelScope,
scope = this,
started = SharingStarted.Lazily,
initialValue = AppTheme.FollowSystem
)

val dynamicColors: StateFlow<Boolean> = settingsInteractor.dynamicColors
.stateIn(
scope = viewModelScope,
scope = this,
started = SharingStarted.Lazily,
initialValue = false
)

val layoutDirection: StateFlow<LayoutDirection> = settingsInteractor.layoutDirection
.stateIn(
scope = viewModelScope,
scope = this,
started = SharingStarted.Lazily,
initialValue = LayoutDirection.Ltr
)

init {
viewModelScope.launch {
settingsInteractor.fetchRemoteConfig()
}
fetchRemoteConfig()
}

fun analyticsTrackDestination(destination: NavDestination, arguments: Bundle?) {
analytics.trackDestination(destination.route, arguments)
}

private fun fetchRemoteConfig() = launch {
settingsInteractor.fetchRemoteConfig()
}
}
2 changes: 1 addition & 1 deletion core/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ android {
dependencies {
implementation(project(":core:analytics"))
api(project(":core:entities"))
api(project(":core:ui"))
api(libs.bundles.kotlin.coroutines)
api(libs.firebase.config)
api(libs.play.services.base)
Expand All @@ -60,4 +59,5 @@ dependencies {
implementation(libs.bundles.appcompat)
implementation(libs.firebase.crashlytics)
implementation(libs.androidx.startup.runtime)
implementation(libs.androidx.browser)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.michaelbel.movies.common.browser

import android.content.Intent
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.net.toUri

fun openUrl(
resultContract: ManagedActivityResultLauncher<Intent, ActivityResult>,
toolbarColor: Int,
url: String
) {
val colorSchemeParams: CustomTabColorSchemeParams = CustomTabColorSchemeParams.Builder()
.setToolbarColor(toolbarColor)
.build()
val customTabsIntentBuilder: CustomTabsIntent.Builder = CustomTabsIntent.Builder().apply {
setDefaultColorSchemeParams(colorSchemeParams)
}
val customTabsIntent: CustomTabsIntent = customTabsIntentBuilder.build().apply {
intent.data = url.toUri()
}
resultContract.launch(customTabsIntent.intent)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.michaelbel.movies.settings.ktx
package org.michaelbel.movies.common.ktx

import android.app.NotificationManager
import android.content.Context
import androidx.core.content.ContextCompat

internal val Context.notificationManager: NotificationManager
val Context.notificationManager: NotificationManager
get() = ContextCompat.getSystemService(this, NotificationManager::class.java) as NotificationManager
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.michaelbel.movies.details.ktx
package org.michaelbel.movies.common.ktx

import androidx.lifecycle.SavedStateHandle

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.michaelbel.movies.common.localization

import kotlinx.coroutines.flow.Flow
import org.michaelbel.movies.ui.language.model.AppLanguage
import org.michaelbel.movies.common.localization.model.AppLanguage

interface LocaleController {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package org.michaelbel.movies.ui.language.exceptions
package org.michaelbel.movies.common.localization.exceptions

internal object InvalidLocaleException: Exception("Invalid locale")
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.michaelbel.movies.common.localization.impl

import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
Expand All @@ -12,7 +11,8 @@ import org.michaelbel.movies.analytics.event.SelectLanguageEvent
import org.michaelbel.movies.common.coroutines.Dispatcher
import org.michaelbel.movies.common.coroutines.MoviesDispatchers
import org.michaelbel.movies.common.localization.LocaleController
import org.michaelbel.movies.ui.language.model.AppLanguage
import org.michaelbel.movies.common.localization.model.AppLanguage
import javax.inject.Inject

internal class LocaleControllerImpl @Inject constructor(
@Dispatcher(MoviesDispatchers.Main) private val dispatcher: CoroutineDispatcher,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.michaelbel.movies.ui.language.model
package org.michaelbel.movies.common.localization.model

import org.michaelbel.movies.ui.language.exceptions.InvalidLocaleException
import org.michaelbel.movies.common.localization.exceptions.InvalidLocaleException

sealed class AppLanguage(val code: String) {
sealed class AppLanguage(
val code: String
) {
object English: AppLanguage("en") {
override fun toString(): String = "English"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.michaelbel.movies.ui.theme.model
package org.michaelbel.movies.common.theme

import androidx.appcompat.app.AppCompatDelegate
import org.michaelbel.movies.ui.theme.exceptions.InvalidThemeException
import org.michaelbel.movies.common.theme.exceptions.InvalidThemeException

sealed class AppTheme(val theme: Int) {
sealed class AppTheme(
val theme: Int
) {
object NightNo: AppTheme(AppCompatDelegate.MODE_NIGHT_NO) {
override fun toString(): String = "NightNo"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package org.michaelbel.movies.ui.theme.exceptions
package org.michaelbel.movies.common.theme.exceptions

internal object InvalidThemeException: Exception("Invalid theme")
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.michaelbel.movies.ui.version
package org.michaelbel.movies.common.version

data class AppVersionData(
val version: String,
Expand Down
3 changes: 2 additions & 1 deletion core/domain/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ android {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=androidx.paging.ExperimentalPagingApi",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import org.michaelbel.movies.domain.data.converter.CalendarConverter
import org.michaelbel.movies.domain.data.dao.AccountDao
import org.michaelbel.movies.domain.data.dao.MovieDao
import org.michaelbel.movies.domain.data.dao.PagingKeyDao
import org.michaelbel.movies.domain.data.entity.AccountDb
import org.michaelbel.movies.domain.data.entity.MovieDb
import org.michaelbel.movies.domain.data.entity.PagingKeyDb

Expand All @@ -17,6 +19,7 @@ import org.michaelbel.movies.domain.data.entity.PagingKeyDb
@Database(
entities = [
MovieDb::class,
AccountDb::class,
PagingKeyDb::class
],
version = AppDatabase.DATABASE_VERSION,
Expand All @@ -26,11 +29,12 @@ import org.michaelbel.movies.domain.data.entity.PagingKeyDb
abstract class AppDatabase: RoomDatabase() {

abstract fun movieDao(): MovieDao
abstract fun accountDao(): AccountDao
abstract fun pagingKeyDao(): PagingKeyDao

companion object {
private const val DATABASE_NAME = "movies-db"
const val DATABASE_VERSION = 13
const val DATABASE_VERSION = 14

@Volatile
private var instance: AppDatabase? = null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.michaelbel.movies.domain.data.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow
import org.michaelbel.movies.domain.data.entity.AccountDb

/**
* The Data Access Object for the [AccountDb] class.
*/
@Dao
interface AccountDao {

@Query("SELECT * FROM accounts WHERE id = :accountId")
fun accountById(accountId: Int): Flow<AccountDb?>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(account: AccountDb)

@Query("DELETE FROM accounts WHERE id = :accountId")
suspend fun removeById(accountId: Int)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import org.michaelbel.movies.domain.data.AppDatabase
import org.michaelbel.movies.domain.data.dao.AccountDao
import org.michaelbel.movies.domain.data.dao.MovieDao
import org.michaelbel.movies.domain.data.dao.PagingKeyDao
import javax.inject.Singleton
Expand All @@ -24,6 +25,9 @@ internal object DatabaseModule {
@Provides
fun provideMovieDao(appDatabase: AppDatabase): MovieDao = appDatabase.movieDao()

@Provides
fun provideAccountDao(appDatabase: AppDatabase): AccountDao = appDatabase.accountDao()

@Provides
fun providePagingKeyDao(appDatabase: AppDatabase): PagingKeyDao = appDatabase.pagingKeyDao()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.michaelbel.movies.domain.data.entity

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import org.jetbrains.annotations.NotNull

@Entity(tableName = "accounts")
data class AccountDb(
@NotNull @PrimaryKey @ColumnInfo(name = "id") val accountId: Int,
@NotNull val avatarUrl: String,
@NotNull val language: String,
@NotNull val country: String,
@NotNull val name: String,
@NotNull val adult: Boolean,
@NotNull val username: String
) {
companion object {
val Empty: AccountDb = AccountDb(
accountId = 0,
avatarUrl = "",
language = "",
country = "",
name = "",
adult = false,
username = ""
)
}
}
Loading