Skip to content

Commit

Permalink
— Изменён размер рамки при сканировании маркировки.
Browse files Browse the repository at this point in the history
— При использовании полноэкранного уведомления о приёме лекарства теперь вместо фона будут отображаться текущие обои устройства.
  • Loading branch information
pav committed Nov 16, 2024
1 parent 99fe202 commit f9952f2
Show file tree
Hide file tree
Showing 24 changed files with 340 additions and 271 deletions.
19 changes: 10 additions & 9 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.composeCompiler)
alias(libs.plugins.jetbrainsKotlin)
alias(libs.plugins.googleKsp)
alias(libs.plugins.roomPlugin)
alias(libs.plugins.android)
alias(libs.plugins.compose)
alias(libs.plugins.kotlin)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.ksp)
alias(libs.plugins.room)
}

android {
Expand All @@ -14,8 +15,8 @@ android {
applicationId = "ru.application.homemedkit"
minSdk = 26
targetSdk = 35
versionCode = 40
versionName = "1.5.5"
versionCode = 41
versionName = "1.5.6"
}

dependenciesInfo {
Expand Down Expand Up @@ -72,8 +73,8 @@ dependencies {
implementation(libs.converter.moshi)

// ==================== Navigation ====================
ksp(libs.compose.destinations.ksp)
implementation(libs.compose.destinations)
implementation(libs.androidx.navigation.compose)
implementation(libs.kotlinx.serialization.json)

// ==================== Scanner ====================
implementation(libs.androidx.camera.camera2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package ru.application.homemedkit

import android.os.Bundle
import android.view.Window
import android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
import android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.AlertDialog
Expand All @@ -26,8 +28,11 @@ import ru.application.homemedkit.ui.theme.AppTheme
class IntakeDialogActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
requestWindowFeature(Window.FEATURE_NO_TITLE)
theme.applyStyle(android.R.style.Theme_Wallpaper, true)
super.onCreate(savedInstanceState)

window.addFlags(FLAG_KEEP_SCREEN_ON or FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)

val database = MedicineDatabase.getInstance(this)
val takenDAO = database.takenDAO()

Expand Down
6 changes: 2 additions & 4 deletions app/src/main/java/ru/application/homemedkit/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.compose.rememberNavController
import ru.application.homemedkit.helpers.KEY_EXP_IMP
import ru.application.homemedkit.helpers.Preferences
import ru.application.homemedkit.helpers.showToast
import ru.application.homemedkit.receivers.AlarmSetter
import ru.application.homemedkit.ui.screens.RootScreen
import ru.application.homemedkit.ui.screens.Navigation
import ru.application.homemedkit.ui.theme.AppTheme

class MainActivity : ComponentActivity() {
Expand All @@ -26,11 +25,10 @@ class MainActivity : ComponentActivity() {
}

setContent {
val navController = rememberNavController()
val theme by Preferences.theme.collectAsStateWithLifecycle()
val dynamicColors by Preferences.dynamicColors.collectAsStateWithLifecycle()

AppTheme(theme, dynamicColors) { RootScreen(navController) }
AppTheme(theme, dynamicColors) { Navigation() }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import kotlinx.coroutines.flow.Flow
import ru.application.homemedkit.data.dto.Medicine

@Dao
Expand All @@ -13,6 +14,9 @@ interface MedicineDAO {
@Query("SELECT * FROM medicines")
fun getAll(): List<Medicine>

@Query("SELECT * FROM medicines")
fun getFlow(): Flow<List<Medicine>>

@Query("SELECT productName FROM medicines WHERE id = :medicineId")
fun getProductName(medicineId: Long): String

Expand Down
34 changes: 34 additions & 0 deletions app/src/main/java/ru/application/homemedkit/helpers/AppUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.os.ConfigurationCompat
import androidx.core.os.LocaleListCompat
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavDestination.Companion.hierarchy
import ru.application.homemedkit.HomeMeds.Companion.database
import ru.application.homemedkit.R
import ru.application.homemedkit.R.string.text_error
import ru.application.homemedkit.R.string.text_success
import ru.application.homemedkit.data.dto.Intake
import ru.application.homemedkit.data.dto.Medicine
import ru.application.homemedkit.data.dto.Technical
import ru.application.homemedkit.models.events.Response
import ru.application.homemedkit.models.states.IntakeState
import ru.application.homemedkit.models.states.MedicineState
import ru.application.homemedkit.models.states.TechnicalState
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
Expand All @@ -28,6 +34,7 @@ import java.time.YearMonth
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import kotlin.reflect.KClass

val LOCALE
@Composable get() = ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
Expand Down Expand Up @@ -119,6 +126,33 @@ fun createNotificationChannel(
)
}

fun <T: Any> NavBackStackEntry?.isCurrentRoute(route: KClass<T>) =
this?.destination?.hierarchy?.any { it.hasRoute(route) } == true

fun Medicine.toState() = MedicineState(
adding = false,
editing = false,
default = true,
fetch = Response.Default,
id = id,
kitId = kitId,
kitTitle = database.medicineDAO().getKitTitle(kitId) ?: BLANK,
cis = cis,
productName = productName,
expDate = expDate,
prodFormNormName = prodFormNormName,
prodDNormName = prodDNormName,
prodAmount = prodAmount.toString(),
doseType = doseType,
phKinetics = phKinetics,
comment = comment,
image = image,
technical = TechnicalState(
scanned = technical.scanned,
verified = technical.verified
)
)

fun MedicineState.toMedicine() = Medicine(
id = id,
kitId = kitId,
Expand Down
42 changes: 33 additions & 9 deletions app/src/main/java/ru/application/homemedkit/helpers/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package ru.application.homemedkit.helpers

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import com.ramcosta.composedestinations.generated.destinations.IntakesScreenDestination
import com.ramcosta.composedestinations.generated.destinations.MedicinesScreenDestination
import com.ramcosta.composedestinations.generated.destinations.SettingsScreenDestination
import com.ramcosta.composedestinations.spec.Direction
import kotlinx.serialization.Serializable
import ru.application.homemedkit.R.drawable.vector_after_food
import ru.application.homemedkit.R.drawable.vector_before_food
import ru.application.homemedkit.R.drawable.vector_in_food
Expand Down Expand Up @@ -196,10 +193,10 @@ enum class Languages(val value: String, @StringRes val title: Int) {
CHINESE_TW("zh-TW", lang_zh_TW),
}

enum class Menu(val route: Direction, @StringRes val title: Int, @DrawableRes val icon: Int) {
MEDICINES(MedicinesScreenDestination, bottom_bar_medicines, vector_medicine),
INTAKES(IntakesScreenDestination, bottom_bar_intakes, vector_time),
SETTINGS(SettingsScreenDestination, bottom_bar_settings, vector_settings)
enum class Menu(val route: Any, @StringRes val title: Int, @DrawableRes val icon: Int) {
MEDICINES(Medicines, bottom_bar_medicines, vector_medicine),
INTAKES(Intakes, bottom_bar_intakes, vector_time),
SETTINGS(Settings, bottom_bar_settings, vector_settings)
}

enum class Periods(val days: Int, @StringRes val title: Int) {
Expand Down Expand Up @@ -248,4 +245,31 @@ enum class Types(val value: String, @StringRes val title: Int, @DrawableRes val
AEROSOL("vector_type_aerosol", type_aerosol, vector_type_aerosol),
SPRAY("vector_type_nasal_spray", type_spray, vector_type_nasal_spray),
DROPS("vector_type_drops", type_drops, vector_type_drops)
}
}

// ============================================ Screens ============================================

@Serializable
object Medicines

@Serializable
object Intakes

@Serializable
object Settings

@Serializable
object Scanner

@Serializable
data class Medicine(
val id: Long = 0L,
val cis: String = BLANK,
val duplicate: Boolean = false
)

@Serializable
data class Intake(
val intakeId: Long = 0L,
val medicineId: Long = 0L
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,35 @@ import android.graphics.ImageFormat.YUV_422_888
import android.graphics.ImageFormat.YUV_444_888
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.zxing.BarcodeFormat
import com.google.zxing.BarcodeFormat.DATA_MATRIX
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.DecodeHintType.POSSIBLE_FORMATS
import com.google.zxing.DecodeHintType.TRY_HARDER
import com.google.zxing.MultiFormatReader
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.common.HybridBinarizer
import java.nio.ByteBuffer
import kotlin.math.roundToInt

class DataMatrixAnalyzer(private val onResult: (String) -> Unit) : ImageAnalysis.Analyzer {
override fun analyze(image: ImageProxy) {
if (image.format in listOf(YUV_420_888, YUV_422_888, YUV_444_888)) {
val length = if (image.width > image.height) image.height * 0.5f else image.width * 0.7f

val source = PlanarYUVLuminanceSource(
image.planes.first().buffer.toByteArray(),
image.width, image.height,
0, 0,
image.width, image.height,
image.width,
image.height,
((image.width - length) / 2).roundToInt(),
((image.height - length) / 2).roundToInt(),
length.roundToInt(),
length.roundToInt(),
false
)

try {
val result = MultiFormatReader().apply {
setHints(
mapOf(
DecodeHintType.POSSIBLE_FORMATS to setOf(BarcodeFormat.DATA_MATRIX),
DecodeHintType.TRY_HARDER to true
)
)
setHints(mapOf(POSSIBLE_FORMATS to setOf(DATA_MATRIX), TRY_HARDER to true))
}.decodeWithState(BinaryBitmap(HybridBinarizer(source)))

onResult(result.text)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ import ru.application.homemedkit.helpers.BLANK
import ru.application.homemedkit.helpers.CATEGORY
import ru.application.homemedkit.helpers.DoseTypes
import ru.application.homemedkit.helpers.toMedicine
import ru.application.homemedkit.helpers.toState
import ru.application.homemedkit.helpers.toTimestamp
import ru.application.homemedkit.models.events.Response
import ru.application.homemedkit.models.events.Response.Default
import ru.application.homemedkit.models.events.Response.Error
import ru.application.homemedkit.models.events.Response.Loading
import ru.application.homemedkit.models.events.Response.NoNetwork
import ru.application.homemedkit.models.events.Response.Success
import ru.application.homemedkit.models.states.MedicineState
import ru.application.homemedkit.models.states.TechnicalState
import ru.application.homemedkit.network.Network
import java.io.File

Expand All @@ -38,35 +37,7 @@ class MedicineViewModel(private val medicineId: Long) : ViewModel() {

private val _state = MutableStateFlow(MedicineState())
val state = _state.asStateFlow()
.onStart {
dao.getById(medicineId)?.let { medicine ->
_state.update {
it.copy(
adding = false,
editing = false,
default = true,
fetch = Default,
id = medicine.id,
kitId = medicine.kitId,
kitTitle = dao.getKitTitle(medicine.kitId) ?: BLANK,
cis = medicine.cis,
productName = medicine.productName,
expDate = medicine.expDate,
prodFormNormName = medicine.prodFormNormName,
prodDNormName = medicine.prodDNormName,
prodAmount = medicine.prodAmount.toString(),
doseType = medicine.doseType,
phKinetics = medicine.phKinetics,
comment = medicine.comment,
image = medicine.image,
technical = TechnicalState(
scanned = medicine.technical.scanned,
verified = medicine.technical.verified
)
)
}
}
}
.onStart { dao.getById(medicineId)?.let { _state.value = it.toState() } }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), MedicineState())

fun add() = viewModelScope.launch(Dispatchers.IO) {
Expand Down Expand Up @@ -98,7 +69,8 @@ class MedicineViewModel(private val medicineId: Long) : ViewModel() {
)

dao.update(medicine)
_response.emit(Success(medicineId))
_state.value = medicine.toState()
_response.emit(Default)
} else {
_response.emit(Error)
delay(2000)
Expand All @@ -113,7 +85,7 @@ class MedicineViewModel(private val medicineId: Long) : ViewModel() {
}
}

fun update() = viewModelScope.launch {
fun update() = viewModelScope.launch(Dispatchers.IO) {
dao.update(_state.value.toMedicine())
_state.update { it.copy(adding = false, editing = false, default = true) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import ru.application.homemedkit.HomeMeds.Companion.database
Expand All @@ -23,15 +23,18 @@ class MedicinesViewModel : ViewModel() {

@OptIn(ExperimentalCoroutinesApi::class)
val medicines = _state.flatMapLatest { (search, sorting, kitId) ->
flow {
emit(
database.medicineDAO().getAll().filter { (_, dKitId, _, productName) ->
productName.lowercase(ROOT).contains(search.lowercase(ROOT)) &&
if (kitId != 0L) dKitId == kitId else true
}.sortedWith(sorting)
)
database.medicineDAO().getFlow().mapLatest { list ->
list.filter { (_, dKitId, _, productName) ->
productName.lowercase(ROOT).contains(search.lowercase(ROOT)) &&
if (kitId != 0L) dKitId == kitId else true
}.sortedWith(sorting)
}
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), database.medicineDAO().getAll())
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(),
initialValue = database.medicineDAO().getAll()
)


fun setSearch(text: String) = _state.update { it.copy(search = text) }
fun clearSearch() = _state.update { it.copy(search = BLANK) }
Expand Down
Loading

0 comments on commit f9952f2

Please sign in to comment.