Skip to content

Commit

Permalink
Implement donate screen (#331)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandregpereira authored Aug 20, 2024
1 parent 21ece79 commit 9c3a16f
Show file tree
Hide file tree
Showing 26 changed files with 242 additions and 63 deletions.
1 change: 1 addition & 0 deletions .github/workflows/Main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
paths-ignore:
- '**.md'
- 'media/**'
- 'content/**'

jobs:
multiplatform-build:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
paths-ignore:
- '**.md'
- 'media/**'
- 'content/**'

jobs:
multiplatform-build:
Expand Down
Binary file added content/media/buy-me-coffee-cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package br.alexandregpereira.hunter.strings

fun String.format(vararg args: Any): String {
return args.foldIndexed(this) { index, string, arg ->
string.replace("{$index}", arg.toString())
}
}

fun String.formatWithPlural(arg: Int, plural: String): String {
val string = if (arg != 1 && plural.isNotBlank()) plural else this
return string.format(arg)
}
1 change: 1 addition & 0 deletions feature/monster-content-manager/compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ multiplatform {
androidMain()
commonMain {
implementation(project(":core:ui:state-recovery"))
implementation(project(":core:uuid"))
implementation(project(":feature:monster-content-manager:state-holder"))
implementation(project(":ui:core"))
implementation(project(":ui:monster-compendium"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import br.alexandregpereira.hunter.monster.content.MonsterContentManagerEmptyStrings
import br.alexandregpereira.hunter.monster.content.MonsterContentManagerStrings
import br.alexandregpereira.hunter.strings.format
import br.alexandregpereira.hunter.ui.compose.AppButton
import br.alexandregpereira.hunter.ui.compose.AppButtonSize
import br.alexandregpereira.hunter.ui.compose.AppCard
Expand Down Expand Up @@ -55,7 +56,7 @@ internal fun MonsterContentCard(
Cover(
coverImageUrl = coverImageUrl,
name = name,
totalMonsters = strings.totalMonsters(totalMonsters),
totalMonsters = strings.totalMonsters.format(totalMonsters),
modifier = Modifier.fillMaxWidth()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@ interface MonsterContentManagerStrings {
val title: String
val add: String
val remove: String
val totalMonsters: (Int) -> String
val totalMonsters: String
val preview: String
}

internal data class MonsterContentManagerEnStrings(
override val title: String = "Manage Content",
override val add: String = "Add",
override val remove: String = "Remove",
override val totalMonsters: (Int) -> String = { total -> "$total monsters" },
override val totalMonsters: String = "{0} monsters",
override val preview: String = "Preview",
) : MonsterContentManagerStrings

internal data class MonsterContentManagerPtStrings(
override val title: String = "Gerenciar Conteúdo",
override val add: String = "Adicionar",
override val remove: String = "Remover",
override val totalMonsters: (Int) -> String = { total -> "$total monstros" },
override val totalMonsters: String = "{0} monstros",
override val preview: String = "Prévia",
) : MonsterContentManagerStrings

data class MonsterContentManagerEmptyStrings(
override val title: String = "",
override val add: String = "",
override val remove: String = "",
override val totalMonsters: (Int) -> String = { _ -> "" },
override val totalMonsters: String = "",
override val preview: String = "",
) : MonsterContentManagerStrings

Expand Down
1 change: 1 addition & 0 deletions feature/monster-registration/compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ multiplatform {
androidMain()
commonMain {
implementation(project(":core:state-holder"))
implementation(project(":core:uuid"))
implementation(project(":domain:monster:core"))
implementation(project(":domain:monster-lore:core"))
implementation(project(":domain:spell:core"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.ui.unit.sp
import br.alexandregpereira.hunter.domain.model.MonsterImageContentScale
import br.alexandregpereira.hunter.monster.registration.MonsterInfoState
import br.alexandregpereira.hunter.monster.registration.ui.strings
import br.alexandregpereira.hunter.strings.format
import br.alexandregpereira.hunter.ui.compose.AppImageContentScale
import br.alexandregpereira.hunter.ui.compose.AppSwitch
import br.alexandregpereira.hunter.ui.compose.AppTextField
Expand Down Expand Up @@ -80,7 +81,7 @@ internal fun LazyListScope.MonsterImageForm(
Spacer(modifier = Modifier.padding(4.dp))
val aspectRatio = getMonsterImageAspectRatio(infoState.isImageHorizontal)
Text(
text = strings.imageProportion(aspectRatio.toString()),
text = strings.imageProportion.format(aspectRatio),
fontWeight = FontWeight.Light,
fontSize = 14.sp,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ interface MonsterRegistrationStrings {
val imageFormTitle: String
val imageHorizontalSwitchLabel: String
val darkThemeSwitchLabel: String
val imageProportion: (String) -> String
val imageProportion: String
val challengeRating: String
}

Expand Down Expand Up @@ -227,7 +227,7 @@ internal data class MonsterRegistrationEnStrings(
override val imageFormTitle: String = "Image",
override val imageHorizontalSwitchLabel: String = "Landscape Image",
override val darkThemeSwitchLabel: String = "Preview Dark Theme",
override val imageProportion: (String) -> String = { "Proportion - $it" },
override val imageProportion: String = "Proportion - {0}",
override val challengeRating: String = "Challenge Rating",
) : MonsterRegistrationStrings

Expand Down Expand Up @@ -341,7 +341,7 @@ internal data class MonsterRegistrationPtStrings(
override val imageFormTitle: String = "Imagem",
override val imageHorizontalSwitchLabel: String = "Imagem Landscape",
override val darkThemeSwitchLabel: String = "Pré visualizar em Tema Escuro",
override val imageProportion: (String) -> String = { "Proporção - $it" },
override val imageProportion: String = "Proporção - {0}",
override val challengeRating: String = "Nível de Desafio",
) : MonsterRegistrationStrings

Expand Down
1 change: 1 addition & 0 deletions feature/search/compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ multiplatform {
implementation(project(":core:localization"))
implementation(project(":core:state-holder"))
implementation(project(":core:search"))
implementation(project(":core:uuid"))
implementation(project(":domain:monster:core"))
implementation(project(":domain:monster-lore:core"))
implementation(project(":domain:spell:core"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import br.alexandregpereira.hunter.search.domain.SearchKeySymbolAnd
import br.alexandregpereira.hunter.search.domain.SearchMonstersByUseCase
import br.alexandregpereira.hunter.search.ui.SearchViewState
import br.alexandregpereira.hunter.state.UiModel
import br.alexandregpereira.hunter.strings.formatWithPlural
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.Job
Expand Down Expand Up @@ -87,7 +88,12 @@ internal class SearchStateHolder(
copy(
monsterRows = monsterRows,
totalResults = totalResults,
searchResults = appLocalization.getStrings().searchResults(totalResults)
searchResults = appLocalization.getStrings().run {
searchResultsSingular.formatWithPlural(
totalResults,
searchResultsPlural
)
}
)
}
}
Expand All @@ -111,7 +117,10 @@ internal class SearchStateHolder(
setState {
copy(
searchLabel = strings.search,
searchResults = strings.searchResults(state.value.totalResults)
searchResults = strings.searchResultsSingular.formatWithPlural(
state.value.totalResults,
strings.searchResultsPlural
)
)
}
}.launchIn(scope)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,20 @@ import br.alexandregpereira.hunter.localization.Language

internal interface SearchStrings {
val search: String
val searchResults: (Int) -> String
val searchResultsPlural: String
val searchResultsSingular: String
}

internal data class SearchEnStrings(
override val search: String = "Search",
override val searchResults: (Int) -> String = { results ->
if (results == 1) {
"1 result"
} else {
"$results results"
}
}
override val searchResultsPlural: String = "{0} results",
override val searchResultsSingular: String = "{0} result"
) : SearchStrings

internal data class SearchPtStrings(
override val search: String = "Buscar",
override val searchResults: (Int) -> String = { results ->
if (results == 1) {
"1 resultado"
} else {
"$results resultados"
}
}
override val searchResultsPlural: String = "{0} resultados",
override val searchResultsSingular: String = "{0} resultado"
) : SearchStrings

internal fun AppLocalization.getStrings(): SearchStrings {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,16 @@ internal class SettingsAnalytics(
eventName = "Settings - appearance settings click",
)
}

fun trackDonateClick() {
analytics.track(
eventName = "Settings - donate click",
)
}

fun trackPixCodeCopyClick() {
analytics.track(
eventName = "Donate - pix code copy click",
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import br.alexandregpereira.hunter.settings.ui.AdvancedSettings
import br.alexandregpereira.hunter.settings.ui.AppearanceSettingsBottomSheet
import br.alexandregpereira.hunter.settings.ui.DonateScreen
import br.alexandregpereira.hunter.settings.ui.SettingsBottomSheet
import br.alexandregpereira.hunter.ui.compose.BottomSheet
import org.koin.compose.koinInject
Expand Down Expand Up @@ -44,5 +45,12 @@ fun SettingsBottomSheets() {
onStateChange = stateHolder::onAppearanceChange,
onSaveButtonClick = stateHolder::onAppearanceSettingsSaveClick,
onClose = stateHolder::onAppearanceSettingsCloseClick
)
)

DonateScreen(
isOpen = state.donateIsOpen,
state = state.donateState,
onClose = stateHolder::onDonateCloseClick,
onPixCodeCopy = stateHolder::onPixCodeCopyClick
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ internal class SettingsStateHolder(
).also { sendAction(it) }
}

override fun onDonateClick() {
analytics.trackDonateClick()
setState { copy(donateIsOpen = true) }
}

fun onDonateCloseClick() {
setState { copy(donateIsOpen = false) }
}

fun onPixCodeCopyClick() {
analytics.trackPixCodeCopyClick()
}

private fun load() {
getMonsterImageJsonUrl()
.zip(getAlternativeSourceJsonUrl()) { imageBaseUrl, alternativeSourceBaseUrl ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ interface SettingsStrings {
val imageContentScaleFit: String
val imageContentScaleCrop: String
val openGitHubProject: String
val donateStrings: DonateStrings
}

interface DonateStrings {
val buyMeACoffee: String
val donateDescription: String
val fromBrazil: String
val pixCopyAndPaste: String
val copyPixCode: String
val fromOtherCountries: String
val fromOtherCountriesDescription: String
}

internal data class SettingsEnStrings(
Expand All @@ -42,6 +53,15 @@ internal data class SettingsEnStrings(
override val imageContentScaleFit: String = "Show entire image",
override val imageContentScaleCrop: String = "Expand the image",
override val openGitHubProject: String = "Open GitHub Project",
override val donateStrings: DonateStrings = object : DonateStrings {
override val buyMeACoffee: String = "Buy me a Coffee"
override val donateDescription: String = "If you are enjoying this app and want to help me maintain it, please consider buying me a coffee."
override val fromBrazil: String = "From Brazil"
override val pixCopyAndPaste: String = "Pix Copia e Cola"
override val copyPixCode: String = "Copy Pix Code"
override val fromOtherCountries: String = "From Other Countries"
override val fromOtherCountriesDescription: String = "Soon"
}
) : SettingsStrings

internal data class SettingsPtStrings(
Expand All @@ -63,27 +83,15 @@ internal data class SettingsPtStrings(
override val imageContentScaleFit: String = "Mostrar imagem inteira",
override val imageContentScaleCrop: String = "Expandir a imagem",
override val openGitHubProject: String = "Abrir Projeto no GitHub",
) : SettingsStrings

internal data class SettingsEmptyStrings(
override val additionalContent: String = "",
override val monsterImagesJson: String = "",
override val alternativeSourcesJson: String = "",
override val manageMonsterContent: String = "",
override val sync: String = "",
override val manageAdvancedSettings: String = "",
override val settingsTitle: String = "",
override val languageLabel: String = "",
override val save: String = "",
override val appearanceSettingsTitle: String = "",
override val forceLightImageBackground: String = "",
override val defaultLightBackground: String = "",
override val defaultDarkBackground: String = "",
override val importContent: String = "",
override val monsterImageContentScale: String = "",
override val imageContentScaleFit: String = "",
override val imageContentScaleCrop: String = "",
override val openGitHubProject: String = "",
override val donateStrings: DonateStrings = object : DonateStrings {
override val buyMeACoffee: String = "Compre-me um Café"
override val donateDescription: String = "Se você está gostando deste aplicativo e quer me ajudar a mantê-lo, considere me comprar um café."
override val fromBrazil: String = "Do Brasil"
override val pixCopyAndPaste: String = "Pix Copia e Cola"
override val copyPixCode: String = "Copiar código Pix"
override val fromOtherCountries: String = "De Outros Países"
override val fromOtherCountriesDescription: String = "Em breve"
}
) : SettingsStrings

internal fun getSettingsStrings(lang: Language): SettingsStrings {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ internal interface SettingsViewIntent {
fun onImport()

fun onOpenGitHubProjectClick()

fun onDonateClick()
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@ internal data class SettingsViewState(
val appearanceSettingsOpened: Boolean = false,
val settingsState: SettingsState = SettingsState(),
val appearanceState: AppearanceSettingsState = AppearanceSettingsState(),
val strings: SettingsStrings = SettingsEmptyStrings(),
val strings: SettingsStrings = SettingsEnStrings(),
val donateIsOpen: Boolean = false,
val donateState: DonateState = DonateState(strings = strings.donateStrings),
)

internal data class DonateState(
val coverImageUrl: String = "https://raw.githubusercontent.com/alexandregpereira/Monster-Compendium/main/content/media/buy-me-coffee-cover.png",
val pixCode: String = "00020126580014BR.GOV.BCB.PIX01365bc29fc7-557c-4935-bdad-1d1f53dd29e65204000053039865802BR5923Alexandre Gomes Pereira6009SAO PAULO62140510FdKlqycExz6304BCEF",
val strings: DonateStrings,
)

internal data class SettingsState(
Expand Down
Loading

0 comments on commit 9c3a16f

Please sign in to comment.