Skip to content

Commit

Permalink
Add close screen button (#304)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandregpereira authored Jul 21, 2024
1 parent 3f758bd commit cdd2cb4
Show file tree
Hide file tree
Showing 27 changed files with 353 additions and 176 deletions.
5 changes: 4 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ kotlin {
dependencies {
implementation(libs.bundles.instrumentedtest)
implementation(libs.compose.ui.test)
implementation(libs.sqldelight.android)
implementation(libs.multiplatform.settings)
implementation(libs.multiplatform.settings.test)
debugImplementation(libs.compose.ui.test.manifest)
}
}
Expand Down Expand Up @@ -173,7 +176,7 @@ android {
setProperty("archivesBaseName", "app-dev")
}

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner = "br.alexandregpereira.hunter.app.KoinTestRunner"
}

signingConfigs {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package br.alexandregpereira.hunter.app

import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import br.alexandregpereira.hunter.data.Database
import br.alexandregpereira.hunter.localization.Language
import com.russhwolf.settings.MapSettings
import com.russhwolf.settings.Settings
import com.squareup.sqldelight.android.AndroidSqliteDriver
import com.squareup.sqldelight.db.SqlDriver
import org.koin.core.context.startKoin
import org.koin.dsl.module

internal class KoinTestRunner : AndroidJUnitRunner() {

override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application {
return super.newApplication(cl, KoinTestApplication::class.qualifiedName, context)
}
}

internal class KoinTestApplication : Application() {

override fun onCreate() {
super.onCreate()
startKoin {
initAndroidModules(this@KoinTestApplication)
allowOverride(true)
module {
factory<SqlDriver> {
AndroidSqliteDriver(
schema = Database.Schema,
context = get<Application>(),
name = null
)
}
single<Settings> { MapSettings() }
factory<Language> { Language.ENGLISH }
}.also {
modules(it)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import androidx.compose.ui.test.performTouchInput
import androidx.test.espresso.Espresso
import br.alexandregpereira.hunter.app.HunterApp
import org.junit.Rule
import org.junit.Test
Expand All @@ -36,8 +35,7 @@ class FolderListTest {
composeTestRule.onNodeWithText("Add to Folder").performClick()
composeTestRule.onNodeWithText("Folder name").performTextInput("Folder Test")
composeTestRule.onNodeWithText("Save").performClick()
Espresso.closeSoftKeyboard()
Espresso.pressBack()
composeTestRule.onNodeWithContentDescription("Close").performClick()
composeTestRule.waitUntil(timeoutMillis = 5000) {
composeTestRule.onNodeWithText("Folders").isDisplayed()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import org.koin.android.ext.koin.androidContext
import org.koin.core.KoinApplication
import org.koin.core.context.startKoin
import org.koin.dsl.module

Expand All @@ -34,14 +35,18 @@ class HunterApplication : Application() {

private fun initKoin() {
startKoin {
androidContext(this@HunterApplication)
modules(
module {
factory { Firebase.analytics }
factory { Firebase.crashlytics }
}
)
initKoinModules()
initAndroidModules(this@HunterApplication)
}
}
}

internal fun KoinApplication.initAndroidModules(app: Application) {
androidContext(app)
modules(
module {
factory { Firebase.analytics }
factory { Firebase.crashlytics }
}
)
initKoinModules()
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.koin.core.qualifier.named
import org.koin.dsl.module

internal fun KoinApplication.initKoinModules() {
allowOverride(false)
modules(domainModules)
modules(dataModules)
modules(
Expand Down
2 changes: 1 addition & 1 deletion app/src/jvmMain/kotlin/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fun main() = application {
onCloseRequest = ::exitApplication,
title = "Monster Compendium",
state = rememberWindowState(
size = DpSize(520.dp, 920.dp)
size = DpSize(600.dp, 800.dp)
),
onKeyEvent = onKeyEvent@ { keyEvent ->
val keyPressedHandled = keyEvent.asKeyPressedHandled() ?: return@onKeyEvent false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ interface MutableAppLocalization : AppLocalization {
fun setLanguage(language: String)
}

internal class AppLocalizationImpl : MutableAppLocalization, AppReactiveLocalization {
internal class AppLocalizationImpl(
private val defaultLanguage: Language,
) : MutableAppLocalization, AppReactiveLocalization {

private var language: Language = getDefaultLanguage()
private var language: Language = defaultLanguage
private val _languageFlow: MutableSharedFlow<Language> = MutableSharedFlow(
extraBufferCapacity = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
Expand All @@ -34,15 +36,9 @@ internal class AppLocalizationImpl : MutableAppLocalization, AppReactiveLocaliza
}

override fun setLanguage(language: String) {
this.language = Language.entries.firstOrNull { it.code == language } ?: getDefaultLanguage()
this.language = Language.entries.firstOrNull { it.code == language } ?: defaultLanguage
_languageFlow.tryEmit(this.language)
}

private fun getDefaultLanguage(): Language {
return Language.entries.firstOrNull {
it.code == getDeviceLangCode()
} ?: Language.ENGLISH
}
}

internal expect fun getDeviceLangCode(): String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ package br.alexandregpereira.hunter.localization.di
import br.alexandregpereira.hunter.localization.AppLocalization
import br.alexandregpereira.hunter.localization.AppLocalizationImpl
import br.alexandregpereira.hunter.localization.AppReactiveLocalization
import br.alexandregpereira.hunter.localization.Language
import br.alexandregpereira.hunter.localization.MutableAppLocalization
import br.alexandregpereira.hunter.localization.getDeviceLangCode
import org.koin.dsl.module

val localizationModule = module {
single { AppLocalizationImpl() }
factory<Language> { getDefaultLanguage() }
single { AppLocalizationImpl(get()) }
single<MutableAppLocalization> { get<AppLocalizationImpl>() }
single<AppLocalization> { get<AppLocalizationImpl>() }
single<AppReactiveLocalization> { get<AppLocalizationImpl>() }
}

private fun getDefaultLanguage(): Language {
return Language.entries.firstOrNull {
it.code == getDeviceLangCode()
} ?: Language.ENGLISH
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ import br.alexandregpereira.hunter.data.monster.local.dao.MonsterDao
import br.alexandregpereira.hunter.data.monster.lore.local.dao.MonsterLoreDao
import br.alexandregpereira.hunter.data.source.local.dao.AlternativeSourceDao
import br.alexandregpereira.hunter.data.spell.local.dao.SpellDao
import com.squareup.sqldelight.db.SqlDriver
import kotlinx.coroutines.CoroutineDispatcher
import org.koin.dsl.module

val databaseModule = module {
factory<SqlDriver> {
createSqlDriver()
}
single {
Database(createSqlDriver())
Database(get())
}
factory<AlternativeSourceDao> {
AlternativeSourceDaoImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.koin.dsl.module

val settingsDataModule = module {
factory { AlternativeSourceUrlBuilder(get()) }
single { get<Settings.Factory>().create("preferences") }
single<Settings> { get<Settings.Factory>().create("preferences") }
factory<SettingsRepository> { DefaultSettingsRepository(get()) }
getAdditionalSettingsModule()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package br.alexandregpereira.hunter.domain.sync

import br.alexandregpereira.hunter.domain.settings.SettingsRepository
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.single

fun interface IsFirstTime {
suspend operator fun invoke(): Boolean
}

fun interface ResetFirstTime {
suspend operator fun invoke()
}

private const val IsFirstTimeKey = "isFirstTimeKey"


internal fun IsFirstTime(
repository: SettingsRepository,
): IsFirstTime = IsFirstTime {
repository.getInt(key = IsFirstTimeKey).map { it ?: 1 }.map { it == 1 }.single()
}

internal fun ResetFirstTime(
repository: SettingsRepository,
): ResetFirstTime = ResetFirstTime {
repository.saveInt(key = IsFirstTimeKey, value = 0).single()
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package br.alexandregpereira.hunter.domain.sync
import br.alexandregpereira.hunter.domain.monster.lore.SyncMonstersLoreUseCase
import br.alexandregpereira.hunter.domain.settings.GetContentVersionUseCase
import br.alexandregpereira.hunter.domain.settings.GetLanguageUseCase
import br.alexandregpereira.hunter.domain.settings.IsLanguageSupported
import br.alexandregpereira.hunter.domain.settings.SaveContentVersionUseCase
import br.alexandregpereira.hunter.domain.settings.SaveLanguageUseCase
import br.alexandregpereira.hunter.domain.spell.SyncSpellsUseCase
Expand All @@ -46,6 +45,8 @@ class SyncUseCase internal constructor(
private val saveLanguageUseCase: SaveLanguageUseCase,
private val getContentVersionUseCase: GetContentVersionUseCase,
private val saveContentVersionUseCase: SaveContentVersionUseCase,
private val isFirstTime: IsFirstTime,
private val resetFirstTime: ResetFirstTime,
) {

private val contentVersion = 3
Expand All @@ -67,6 +68,7 @@ class SyncUseCase internal constructor(
runCatching { saveContentVersionUseCase(lastContentVersionRollback).single() }
}
}
resetFirstTime()
emit(SyncStatus.SYNCED)
} else {
emit(SyncStatus.IDLE)
Expand All @@ -77,7 +79,8 @@ class SyncUseCase internal constructor(
private fun isToSync(): Flow<Triple<Boolean, String, Int>> {
return isLangSyncScenario()
.zip(isContentVersionSyncScenario()) { (isLangSyncScenario, lastLanguageRollback), (isContentVersionSyncScenario, lastContentVersionRollback) ->
Triple((isLangSyncScenario || isContentVersionSyncScenario), lastLanguageRollback, lastContentVersionRollback)
val isToSync = isFirstTime() || isLangSyncScenario || isContentVersionSyncScenario
Triple(isToSync, lastLanguageRollback, lastContentVersionRollback)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@

package br.alexandregpereira.hunter.domain.sync.di

import br.alexandregpereira.hunter.domain.sync.IsFirstTime
import br.alexandregpereira.hunter.domain.sync.ResetFirstTime
import br.alexandregpereira.hunter.domain.sync.SyncUseCase
import org.koin.dsl.module

val syncDomainModule = module {
factory { SyncUseCase(get(), get(), get(), get(), get(), get(), get()) }
factory { IsFirstTime(get()) }
factory { ResetFirstTime(get()) }
factory { SyncUseCase(get(), get(), get(), get(), get(), get(), get(), get(), get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@
package br.alexandregpereira.hunter.folder.detail.ui

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import br.alexandregpereira.hunter.domain.folder.model.MonsterPreviewFolder
import br.alexandregpereira.hunter.folder.detail.FolderDetailState
import br.alexandregpereira.hunter.ui.compendium.CompendiumItemState.Item
Expand All @@ -30,9 +28,7 @@ import br.alexandregpereira.hunter.ui.compendium.monster.MonsterCardState
import br.alexandregpereira.hunter.ui.compendium.monster.MonsterCompendium
import br.alexandregpereira.hunter.ui.compendium.monster.MonsterImageState
import br.alexandregpereira.hunter.ui.compendium.monster.MonsterTypeState
import br.alexandregpereira.hunter.ui.compose.BackHandler
import br.alexandregpereira.hunter.ui.compose.SwipeVerticalToDismiss
import br.alexandregpereira.hunter.ui.compose.Window
import br.alexandregpereira.hunter.ui.compose.AppFullScreen

@Composable
internal fun FolderDetailScreen(
Expand All @@ -41,29 +37,23 @@ internal fun FolderDetailScreen(
onItemCLick: (index: String) -> Unit = {},
onItemLongCLick: (index: String) -> Unit = {},
onClose: () -> Unit = {}
) {
BackHandler(enabled = state.isOpen, onBack = onClose)

) = AppFullScreen(isOpen = state.isOpen, contentPadding, onClose = onClose) {
val monsters = remember(state.monsters) { state.monsters.asState() }
SwipeVerticalToDismiss(visible = state.isOpen, onClose = onClose) {
Window(Modifier.fillMaxSize()) {
val items = listOf(
Title(
value = state.folderName,
isHeader = true
),
) + monsters.map {
Item(value = it)
}
MonsterCompendium(
items = items,
animateItems = true,
contentPadding = contentPadding,
onItemCLick = onItemCLick,
onItemLongCLick = onItemLongCLick
)
}
val items = listOf(
Title(
value = state.folderName,
isHeader = true
),
) + monsters.map {
Item(value = it)
}
MonsterCompendium(
items = items,
animateItems = true,
contentPadding = contentPadding,
onItemCLick = onItemCLick,
onItemLongCLick = onItemLongCLick
)
}

private fun List<MonsterPreviewFolder>.asState(): List<MonsterCardState> = map {
Expand Down
Loading

0 comments on commit cdd2cb4

Please sign in to comment.