Skip to content

Commit

Permalink
Android version 2.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-Fabi committed Jun 17, 2024
2 parents a306a6f + b4682a4 commit 77cd26f
Show file tree
Hide file tree
Showing 16 changed files with 70 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package org.datepollsystems.waiterrobot.android.ui.order
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
Expand Down Expand Up @@ -142,7 +144,8 @@ fun OrderScreen(
showProductSheet = false
},
sheetState = productSheetState,
dragHandle = null
dragHandle = null,
contentWindowInsets = { WindowInsets.statusBars }
) {
ProductSearch(
productGroupsResource = state.productGroups,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.datepollsystems.waiterrobot.android.ui.order

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
Expand Down Expand Up @@ -51,7 +50,6 @@ import org.datepollsystems.waiterrobot.shared.generated.localization.noProductFo
import org.datepollsystems.waiterrobot.shared.generated.localization.placeholder
import org.datepollsystems.waiterrobot.shared.generated.localization.title

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ProductSearch(
productGroupsResource: Resource<List<ProductGroup>>,
Expand Down
2 changes: 1 addition & 1 deletion androidApp/version.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
androidVersion=2.2.1
androidVersion=2.2.2
24 changes: 11 additions & 13 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
[versions]
# Shared
kotlin = "1.9.23" # Always check https://developer.android.com/jetpack/androidx/releases/compose-kotlin for compose version compatibility
ksp = "1.9.23-1.0.20" # First part must match the kotlin version
detektFormatting = "1.23.6"
kotlin = "1.9.24" # Always check https://developer.android.com/jetpack/androidx/releases/compose-kotlin for compose version compatibility
ksp = "1.9.24-1.0.20" # First part must match the kotlin version
kermit = "2.0.3"
koin = "3.5.6"
orbitMvi = "7.1.0"
orbitMvi = "8.0.0"
mokoMvvm = "0.16.1"
ktor = "2.3.11"
mokoPermissions = "0.18.0"
settings = "1.1.1"
realm = "1.16.0"
detekt = "1.23.6"
kotlinx-serialization-json = "1.6.3"
kotlinx-datetime = "0.5.0"
kotlinx-datetime = "0.6.0"
buildkonfig = "0.15.1"
skie = "0.7.0"
skie = "0.8.2"
kmmbridge = "0.5.5"
kmmresources = "1.0.0-alpha11"

Expand All @@ -25,12 +24,12 @@ android-targetSdk = "33"
android-compileSdk = "34"
android-buildTools = "34.0.0"
android-gradle = "8.4.0"
android-camera = "1.3.3"
android-camera = "1.3.4"
android-desugar = "2.0.4"
androidx-lifecycle = "2.7.0"
androidx-appcompat = "1.6.1"
androidx-compose = "2024.05.00"
androidx-compose-compiler = "1.5.13"
androidx-compose = "2024.06.00"
androidx-compose-compiler = "1.5.14"
androidx-compose-activity = "1.9.0"
compose-destinations = "1.10.2"
play-publisher = "3.9.1"
Expand All @@ -39,7 +38,7 @@ koinCompose = "3.5.6"
appUpdate = "2.1.0"
barcodeScanning = "17.2.0"
stripe = "3.5.0"
playServicesLocation = "21.2.0"
playServicesLocation = "21.3.0"

[libraries]

Expand All @@ -59,8 +58,7 @@ androidx-compose-ui-core = { module = "androidx.compose.ui:ui" }
androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
androidx-compose-material3-core = { module = "androidx.compose.material3:material3" }
androidx-compose-material-core = { module = "androidx.compose.material:material" }
androidx-compose-material3-core = { module = "androidx.compose.material3:material3", version = "1.3.0-beta03" }
androidx-compose-material-icons = { module = "androidx.compose.material:material-icons-core" }
androidx-compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }

Expand All @@ -77,7 +75,7 @@ koin-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref =
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" }

detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detektFormatting" }
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }

Expand Down
10 changes: 6 additions & 4 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ tasks {
findByName("skiePackageCustomSwift${buildType}FrameworkIos$arch")?.apply {
dependsOn(generateLocalizationsTask)
}
findByName("skieProcessSwiftSourcesIos$arch")?.apply {
dependsOn(generateLocalizationsTask)
}
}
}

Expand All @@ -228,9 +231,8 @@ detekt {
}

skie {
build {
// TODO workaround for "No 'swiftinterface' files found within xxx"
// Should be fixed in 0.7.1 but there is another issue (missing iosArm64)
enableSwiftLibraryEvolution.set(true)
analytics {
disableUpload.set(true)
enabled.set(false)
}
}
7 changes: 7 additions & 0 deletions shared/localization.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ order:
descOrderAdd:
en: \"%1$s\" is sold out. It is not added to the order.
de: \"%1$s\" ist ausverkauft. Es wird der Bestellung nicht hinzugefügt.
stockToLow:
title:
en: Product stock to low
de: Produktbestand zu niedrig
desc:
en: There are only %1$s pieces of \"%2$s\" left. Reduce the quantity or remove it from the order.
de: Es sind nur noch %1$s Stück von \"%2$s\" übrig. Reduziere die Anzahl oder entferne es aus der Bestellung.
addNoteDialog:
title:
de: Notiz für %1$s
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ internal sealed class ApiException : Exception() {
@SerialName("SOLD_OUT")
class ProductSoldOut(val productId: Long) : ApiException()

@Serializable
@SerialName("TOO_SMALL_STOCK")
class ProductStockToLow(val productId: Long, val remaining: Int = 0) : ApiException()

@Serializable
@SerialName("ACCOUNT_NOT_ACTIVATED")
class AccountNotActivated : ApiException()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal fun HttpClientConfig<*>.installApiClientExceptionTransformer(json: Json
expectSuccess = true
HttpResponseValidator {
handleResponseExceptionWithRequest { exception, request ->
// TODO maybe also map ServerExceptions (and also other HttpExceptions) to ApiException
val clientException = exception as? ClientRequestException
?: return@handleResponseExceptionWithRequest

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ internal abstract class CachedRepository<EntityType, ModelType> : AbstractReposi

suspend fun requery() {
_flow.emit(
query().first().let {
_flow.value.map { it }
query().first().let { entity ->
_flow.value.map { mapDbEntity(entity) }
}
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.datepollsystems.waiterrobot.shared.core.viewmodel

import dev.icerock.moko.mvvm.viewmodel.ViewModel
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -44,6 +45,8 @@ abstract class AbstractViewModel<S : ViewModelState, E : ViewModelEffect>(
buildSettings = {
exceptionHandler = CoroutineExceptionHandler { _, exception ->
when (exception) {
is CancellationException -> Unit // Expected, nothing to do here

is ApiException.AppVersionTooOld -> intent {
navigator.replaceRoot(Screen.UpdateApp)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.map
import org.datepollsystems.waiterrobot.shared.core.data.db.AbstractDatabase
import org.datepollsystems.waiterrobot.shared.features.order.db.model.ProductEntry
import org.datepollsystems.waiterrobot.shared.features.order.db.model.ProductGroupEntry
import org.datepollsystems.waiterrobot.shared.features.table.db.model.TableGroupEntry
import org.datepollsystems.waiterrobot.shared.utils.extensions.Now
import kotlin.time.Duration

Expand All @@ -24,7 +23,7 @@ internal class ProductDatabase : AbstractDatabase() {
val idsToKeep = productGroups.mapTo(mutableSetOf(), ProductGroupEntry::id)

realm.write {
delete(query<TableGroupEntry>("id == NONE $0", idsToKeep))
delete(query<ProductGroupEntry>("id == NONE $0", idsToKeep))
productGroups.forEach { copyToRealm(it, UpdatePolicy.ALL) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ class OrderViewModel internal constructor(
} catch (e: ApiException.ProductSoldOut) {
val soldOutProduct = order.first { it.product.id == e.productId }.product
reduce { productSoldOut(soldOutProduct) }
} catch (e: ApiException.ProductStockToLow) {
val stockToLowProduct = order.first { it.product.id == e.productId }.product
if (e.remaining <= 0) {
reduce { productSoldOut(stockToLowProduct) }
} else {
reduce { stockToLow(stockToLowProduct, e.remaining) }
}
}
}

Expand Down Expand Up @@ -165,6 +172,7 @@ class OrderViewModel internal constructor(
}

private fun SimpleContext<OrderState>.productSoldOut(product: Product): OrderState {
refreshProducts()
return state.copy(
_currentOrder = Resource.Error(
L.order.productSoldOut.descOrderSent(product.name),
Expand All @@ -173,6 +181,16 @@ class OrderViewModel internal constructor(
)
}

private fun SimpleContext<OrderState>.stockToLow(product: Product, remaining: Int): OrderState {
refreshProducts()
return state.copy(
_currentOrder = Resource.Error(
L.order.stockToLow.desc(remaining.toString(), product.name),
state._currentOrder.dataOrEmpty
)
)
}

fun filterProducts(filter: String) = intent {
reduce { state.copy(filter = filter) } // TODO can we move the filter to the repository?
productRepository.requery()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package org.datepollsystems.waiterrobot.shared.features.settings.viewmodel

import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.joinAll
import org.datepollsystems.waiterrobot.shared.core.CommonApp
import org.datepollsystems.waiterrobot.shared.core.navigation.NavOrViewModelEffect
import org.datepollsystems.waiterrobot.shared.core.navigation.Screen
import org.datepollsystems.waiterrobot.shared.core.viewmodel.AbstractViewModel
import org.datepollsystems.waiterrobot.shared.features.order.repository.ProductRepository
import org.datepollsystems.waiterrobot.shared.features.settings.models.AppTheme
import org.datepollsystems.waiterrobot.shared.features.table.repository.TableRepository
import org.datepollsystems.waiterrobot.shared.features.table.viewmodel.list.TableListViewModel
import org.datepollsystems.waiterrobot.shared.utils.launchCatching
import org.orbitmvi.orbit.syntax.simple.SimpleSyntax
import org.orbitmvi.orbit.syntax.simple.intent
Expand All @@ -26,12 +24,9 @@ class SettingsViewModel internal constructor(

fun refreshAll() = intent {
coroutineScope {
listOf(
launchCatching(logger) { tableRepo.refresh() },
launchCatching(logger) { productRepo.refresh() }
).joinAll()
launchCatching(logger) { tableRepo.refresh() }
launchCatching(logger) { productRepo.refresh() }
}
updateParent<TableListViewModel>()
}

fun switchEvent() = intent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ internal class TableDatabase : AbstractDatabase() {
.find { it.mapTo(mutableSetOf(), TableGroupEntry::id) }
tableGroups.forEach {
it.hidden = it.id in hiddenGroupIds
it.tables.forEach { table ->
table.hasOrders = table.id in tableIdsWithOrders
}
}

realm.write {
delete(query<TableGroupEntry>("id == NONE $0", idsToKeep))
tableGroups.forEach { copyToRealm(it, UpdatePolicy.ALL) }
}
updateTablesWithOrder(tableIdsWithOrders)
}

suspend fun updateTablesWithOrder(tableIdsWithOrders: Set<Long>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.datepollsystems.waiterrobot.shared.features.table.repository

import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.datetime.Instant
import org.datepollsystems.waiterrobot.shared.core.CommonApp
import org.datepollsystems.waiterrobot.shared.core.data.Resource
Expand Down Expand Up @@ -62,7 +63,11 @@ internal class TableRepository(
}

override fun query(): Flow<List<TableGroupEntry>> =
tableDb.getForEventFlow(CommonApp.settings.selectedEventId)
tableDb.getForEventFlow(CommonApp.settings.selectedEventId).map { groups ->
groups.filter { it.tables.isNotEmpty() } // Do not show groups that do not have tables at all
.sortedBy { it.name.lowercase() } // Sort groups with same position by name
.sortedBy(TableGroupEntry::position)
}

override suspend fun update() {
logger.i { "Loading Tables from api ..." }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ internal fun ApiException.getLocalizedUserMessage(): String = when (this) {
is ApiException.BillAmountTooLow -> L.billing.amountToLow(minAmount.cent.toString())
is ApiException.StripeDisabled -> L.stripeInit.error.disabled()
is ApiException.StripeNotActivated -> L.stripeInit.error.disabledForEvent()
is ApiException.ProductStockToLow -> L.order.stockToLow.title()

// Unknown exceptions or exceptions that should normally not happen
is ApiException.Generic,
Expand Down

0 comments on commit 77cd26f

Please sign in to comment.