Skip to content

Commit f9952f2

Browse files
author
pav
committed
— Изменён размер рамки при сканировании маркировки.
— При использовании полноэкранного уведомления о приёме лекарства теперь вместо фона будут отображаться текущие обои устройства.
1 parent 99fe202 commit f9952f2

24 files changed

+340
-271
lines changed

app/build.gradle.kts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
plugins {
2-
alias(libs.plugins.androidApplication)
3-
alias(libs.plugins.composeCompiler)
4-
alias(libs.plugins.jetbrainsKotlin)
5-
alias(libs.plugins.googleKsp)
6-
alias(libs.plugins.roomPlugin)
2+
alias(libs.plugins.android)
3+
alias(libs.plugins.compose)
4+
alias(libs.plugins.kotlin)
5+
alias(libs.plugins.kotlin.serialization)
6+
alias(libs.plugins.ksp)
7+
alias(libs.plugins.room)
78
}
89

910
android {
@@ -14,8 +15,8 @@ android {
1415
applicationId = "ru.application.homemedkit"
1516
minSdk = 26
1617
targetSdk = 35
17-
versionCode = 40
18-
versionName = "1.5.5"
18+
versionCode = 41
19+
versionName = "1.5.6"
1920
}
2021

2122
dependenciesInfo {
@@ -72,8 +73,8 @@ dependencies {
7273
implementation(libs.converter.moshi)
7374

7475
// ==================== Navigation ====================
75-
ksp(libs.compose.destinations.ksp)
76-
implementation(libs.compose.destinations)
76+
implementation(libs.androidx.navigation.compose)
77+
implementation(libs.kotlinx.serialization.json)
7778

7879
// ==================== Scanner ====================
7980
implementation(libs.androidx.camera.camera2)

app/src/main/java/ru/application/homemedkit/IntakeDialogActivity.kt

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package ru.application.homemedkit
22

33
import android.os.Bundle
44
import android.view.Window
5+
import android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
6+
import android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
57
import androidx.activity.ComponentActivity
68
import androidx.activity.compose.setContent
79
import androidx.compose.material3.AlertDialog
@@ -26,8 +28,11 @@ import ru.application.homemedkit.ui.theme.AppTheme
2628
class IntakeDialogActivity : ComponentActivity() {
2729
override fun onCreate(savedInstanceState: Bundle?) {
2830
requestWindowFeature(Window.FEATURE_NO_TITLE)
31+
theme.applyStyle(android.R.style.Theme_Wallpaper, true)
2932
super.onCreate(savedInstanceState)
3033

34+
window.addFlags(FLAG_KEEP_SCREEN_ON or FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)
35+
3136
val database = MedicineDatabase.getInstance(this)
3237
val takenDAO = database.takenDAO()
3338

app/src/main/java/ru/application/homemedkit/MainActivity.kt

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import androidx.activity.ComponentActivity
66
import androidx.activity.compose.setContent
77
import androidx.compose.runtime.getValue
88
import androidx.lifecycle.compose.collectAsStateWithLifecycle
9-
import androidx.navigation.compose.rememberNavController
109
import ru.application.homemedkit.helpers.KEY_EXP_IMP
1110
import ru.application.homemedkit.helpers.Preferences
1211
import ru.application.homemedkit.helpers.showToast
1312
import ru.application.homemedkit.receivers.AlarmSetter
14-
import ru.application.homemedkit.ui.screens.RootScreen
13+
import ru.application.homemedkit.ui.screens.Navigation
1514
import ru.application.homemedkit.ui.theme.AppTheme
1615

1716
class MainActivity : ComponentActivity() {
@@ -26,11 +25,10 @@ class MainActivity : ComponentActivity() {
2625
}
2726

2827
setContent {
29-
val navController = rememberNavController()
3028
val theme by Preferences.theme.collectAsStateWithLifecycle()
3129
val dynamicColors by Preferences.dynamicColors.collectAsStateWithLifecycle()
3230

33-
AppTheme(theme, dynamicColors) { RootScreen(navController) }
31+
AppTheme(theme, dynamicColors) { Navigation() }
3432
}
3533
}
3634
}

app/src/main/java/ru/application/homemedkit/data/dao/MedicineDAO.kt

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.room.Delete
55
import androidx.room.Insert
66
import androidx.room.Query
77
import androidx.room.Update
8+
import kotlinx.coroutines.flow.Flow
89
import ru.application.homemedkit.data.dto.Medicine
910

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

17+
@Query("SELECT * FROM medicines")
18+
fun getFlow(): Flow<List<Medicine>>
19+
1620
@Query("SELECT productName FROM medicines WHERE id = :medicineId")
1721
fun getProductName(medicineId: Long): String
1822

app/src/main/java/ru/application/homemedkit/helpers/AppUtils.kt

+34
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,20 @@ import androidx.core.app.NotificationChannelCompat
1212
import androidx.core.app.NotificationManagerCompat
1313
import androidx.core.os.ConfigurationCompat
1414
import androidx.core.os.LocaleListCompat
15+
import androidx.navigation.NavBackStackEntry
16+
import androidx.navigation.NavDestination.Companion.hasRoute
17+
import androidx.navigation.NavDestination.Companion.hierarchy
18+
import ru.application.homemedkit.HomeMeds.Companion.database
1519
import ru.application.homemedkit.R
1620
import ru.application.homemedkit.R.string.text_error
1721
import ru.application.homemedkit.R.string.text_success
1822
import ru.application.homemedkit.data.dto.Intake
1923
import ru.application.homemedkit.data.dto.Medicine
2024
import ru.application.homemedkit.data.dto.Technical
25+
import ru.application.homemedkit.models.events.Response
2126
import ru.application.homemedkit.models.states.IntakeState
2227
import ru.application.homemedkit.models.states.MedicineState
28+
import ru.application.homemedkit.models.states.TechnicalState
2329
import java.time.Instant
2430
import java.time.LocalDate
2531
import java.time.LocalDateTime
@@ -28,6 +34,7 @@ import java.time.YearMonth
2834
import java.time.ZoneId
2935
import java.time.format.DateTimeFormatter
3036
import java.time.format.FormatStyle
37+
import kotlin.reflect.KClass
3138

3239
val LOCALE
3340
@Composable get() = ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
@@ -119,6 +126,33 @@ fun createNotificationChannel(
119126
)
120127
}
121128

129+
fun <T: Any> NavBackStackEntry?.isCurrentRoute(route: KClass<T>) =
130+
this?.destination?.hierarchy?.any { it.hasRoute(route) } == true
131+
132+
fun Medicine.toState() = MedicineState(
133+
adding = false,
134+
editing = false,
135+
default = true,
136+
fetch = Response.Default,
137+
id = id,
138+
kitId = kitId,
139+
kitTitle = database.medicineDAO().getKitTitle(kitId) ?: BLANK,
140+
cis = cis,
141+
productName = productName,
142+
expDate = expDate,
143+
prodFormNormName = prodFormNormName,
144+
prodDNormName = prodDNormName,
145+
prodAmount = prodAmount.toString(),
146+
doseType = doseType,
147+
phKinetics = phKinetics,
148+
comment = comment,
149+
image = image,
150+
technical = TechnicalState(
151+
scanned = technical.scanned,
152+
verified = technical.verified
153+
)
154+
)
155+
122156
fun MedicineState.toMedicine() = Medicine(
123157
id = id,
124158
kitId = kitId,

app/src/main/java/ru/application/homemedkit/helpers/Constants.kt

+33-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ package ru.application.homemedkit.helpers
22

33
import androidx.annotation.DrawableRes
44
import androidx.annotation.StringRes
5-
import com.ramcosta.composedestinations.generated.destinations.IntakesScreenDestination
6-
import com.ramcosta.composedestinations.generated.destinations.MedicinesScreenDestination
7-
import com.ramcosta.composedestinations.generated.destinations.SettingsScreenDestination
8-
import com.ramcosta.composedestinations.spec.Direction
5+
import kotlinx.serialization.Serializable
96
import ru.application.homemedkit.R.drawable.vector_after_food
107
import ru.application.homemedkit.R.drawable.vector_before_food
118
import ru.application.homemedkit.R.drawable.vector_in_food
@@ -196,10 +193,10 @@ enum class Languages(val value: String, @StringRes val title: Int) {
196193
CHINESE_TW("zh-TW", lang_zh_TW),
197194
}
198195

199-
enum class Menu(val route: Direction, @StringRes val title: Int, @DrawableRes val icon: Int) {
200-
MEDICINES(MedicinesScreenDestination, bottom_bar_medicines, vector_medicine),
201-
INTAKES(IntakesScreenDestination, bottom_bar_intakes, vector_time),
202-
SETTINGS(SettingsScreenDestination, bottom_bar_settings, vector_settings)
196+
enum class Menu(val route: Any, @StringRes val title: Int, @DrawableRes val icon: Int) {
197+
MEDICINES(Medicines, bottom_bar_medicines, vector_medicine),
198+
INTAKES(Intakes, bottom_bar_intakes, vector_time),
199+
SETTINGS(Settings, bottom_bar_settings, vector_settings)
203200
}
204201

205202
enum class Periods(val days: Int, @StringRes val title: Int) {
@@ -248,4 +245,31 @@ enum class Types(val value: String, @StringRes val title: Int, @DrawableRes val
248245
AEROSOL("vector_type_aerosol", type_aerosol, vector_type_aerosol),
249246
SPRAY("vector_type_nasal_spray", type_spray, vector_type_nasal_spray),
250247
DROPS("vector_type_drops", type_drops, vector_type_drops)
251-
}
248+
}
249+
250+
// ============================================ Screens ============================================
251+
252+
@Serializable
253+
object Medicines
254+
255+
@Serializable
256+
object Intakes
257+
258+
@Serializable
259+
object Settings
260+
261+
@Serializable
262+
object Scanner
263+
264+
@Serializable
265+
data class Medicine(
266+
val id: Long = 0L,
267+
val cis: String = BLANK,
268+
val duplicate: Boolean = false
269+
)
270+
271+
@Serializable
272+
data class Intake(
273+
val intakeId: Long = 0L,
274+
val medicineId: Long = 0L
275+
)

app/src/main/java/ru/application/homemedkit/helpers/DataMatrixAnalyzer.kt

+13-11
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,35 @@ import android.graphics.ImageFormat.YUV_422_888
55
import android.graphics.ImageFormat.YUV_444_888
66
import androidx.camera.core.ImageAnalysis
77
import androidx.camera.core.ImageProxy
8-
import com.google.zxing.BarcodeFormat
8+
import com.google.zxing.BarcodeFormat.DATA_MATRIX
99
import com.google.zxing.BinaryBitmap
10-
import com.google.zxing.DecodeHintType
10+
import com.google.zxing.DecodeHintType.POSSIBLE_FORMATS
11+
import com.google.zxing.DecodeHintType.TRY_HARDER
1112
import com.google.zxing.MultiFormatReader
1213
import com.google.zxing.PlanarYUVLuminanceSource
1314
import com.google.zxing.common.HybridBinarizer
1415
import java.nio.ByteBuffer
16+
import kotlin.math.roundToInt
1517

1618
class DataMatrixAnalyzer(private val onResult: (String) -> Unit) : ImageAnalysis.Analyzer {
1719
override fun analyze(image: ImageProxy) {
1820
if (image.format in listOf(YUV_420_888, YUV_422_888, YUV_444_888)) {
21+
val length = if (image.width > image.height) image.height * 0.5f else image.width * 0.7f
22+
1923
val source = PlanarYUVLuminanceSource(
2024
image.planes.first().buffer.toByteArray(),
21-
image.width, image.height,
22-
0, 0,
23-
image.width, image.height,
25+
image.width,
26+
image.height,
27+
((image.width - length) / 2).roundToInt(),
28+
((image.height - length) / 2).roundToInt(),
29+
length.roundToInt(),
30+
length.roundToInt(),
2431
false
2532
)
2633

2734
try {
2835
val result = MultiFormatReader().apply {
29-
setHints(
30-
mapOf(
31-
DecodeHintType.POSSIBLE_FORMATS to setOf(BarcodeFormat.DATA_MATRIX),
32-
DecodeHintType.TRY_HARDER to true
33-
)
34-
)
36+
setHints(mapOf(POSSIBLE_FORMATS to setOf(DATA_MATRIX), TRY_HARDER to true))
3537
}.decodeWithState(BinaryBitmap(HybridBinarizer(source)))
3638

3739
onResult(result.text)

app/src/main/java/ru/application/homemedkit/models/viewModels/MedicineViewModel.kt

+5-33
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@ import ru.application.homemedkit.helpers.BLANK
1818
import ru.application.homemedkit.helpers.CATEGORY
1919
import ru.application.homemedkit.helpers.DoseTypes
2020
import ru.application.homemedkit.helpers.toMedicine
21+
import ru.application.homemedkit.helpers.toState
2122
import ru.application.homemedkit.helpers.toTimestamp
2223
import ru.application.homemedkit.models.events.Response
2324
import ru.application.homemedkit.models.events.Response.Default
2425
import ru.application.homemedkit.models.events.Response.Error
2526
import ru.application.homemedkit.models.events.Response.Loading
2627
import ru.application.homemedkit.models.events.Response.NoNetwork
27-
import ru.application.homemedkit.models.events.Response.Success
2828
import ru.application.homemedkit.models.states.MedicineState
29-
import ru.application.homemedkit.models.states.TechnicalState
3029
import ru.application.homemedkit.network.Network
3130
import java.io.File
3231

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

3938
private val _state = MutableStateFlow(MedicineState())
4039
val state = _state.asStateFlow()
41-
.onStart {
42-
dao.getById(medicineId)?.let { medicine ->
43-
_state.update {
44-
it.copy(
45-
adding = false,
46-
editing = false,
47-
default = true,
48-
fetch = Default,
49-
id = medicine.id,
50-
kitId = medicine.kitId,
51-
kitTitle = dao.getKitTitle(medicine.kitId) ?: BLANK,
52-
cis = medicine.cis,
53-
productName = medicine.productName,
54-
expDate = medicine.expDate,
55-
prodFormNormName = medicine.prodFormNormName,
56-
prodDNormName = medicine.prodDNormName,
57-
prodAmount = medicine.prodAmount.toString(),
58-
doseType = medicine.doseType,
59-
phKinetics = medicine.phKinetics,
60-
comment = medicine.comment,
61-
image = medicine.image,
62-
technical = TechnicalState(
63-
scanned = medicine.technical.scanned,
64-
verified = medicine.technical.verified
65-
)
66-
)
67-
}
68-
}
69-
}
40+
.onStart { dao.getById(medicineId)?.let { _state.value = it.toState() } }
7041
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), MedicineState())
7142

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

10071
dao.update(medicine)
101-
_response.emit(Success(medicineId))
72+
_state.value = medicine.toState()
73+
_response.emit(Default)
10274
} else {
10375
_response.emit(Error)
10476
delay(2000)
@@ -113,7 +85,7 @@ class MedicineViewModel(private val medicineId: Long) : ViewModel() {
11385
}
11486
}
11587

116-
fun update() = viewModelScope.launch {
88+
fun update() = viewModelScope.launch(Dispatchers.IO) {
11789
dao.update(_state.value.toMedicine())
11890
_state.update { it.copy(adding = false, editing = false, default = true) }
11991
}

app/src/main/java/ru/application/homemedkit/models/viewModels/MedicinesViewModel.kt

+12-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
77
import kotlinx.coroutines.flow.SharingStarted
88
import kotlinx.coroutines.flow.asStateFlow
99
import kotlinx.coroutines.flow.flatMapLatest
10-
import kotlinx.coroutines.flow.flow
10+
import kotlinx.coroutines.flow.mapLatest
1111
import kotlinx.coroutines.flow.stateIn
1212
import kotlinx.coroutines.flow.update
1313
import ru.application.homemedkit.HomeMeds.Companion.database
@@ -23,15 +23,18 @@ class MedicinesViewModel : ViewModel() {
2323

2424
@OptIn(ExperimentalCoroutinesApi::class)
2525
val medicines = _state.flatMapLatest { (search, sorting, kitId) ->
26-
flow {
27-
emit(
28-
database.medicineDAO().getAll().filter { (_, dKitId, _, productName) ->
29-
productName.lowercase(ROOT).contains(search.lowercase(ROOT)) &&
30-
if (kitId != 0L) dKitId == kitId else true
31-
}.sortedWith(sorting)
32-
)
26+
database.medicineDAO().getFlow().mapLatest { list ->
27+
list.filter { (_, dKitId, _, productName) ->
28+
productName.lowercase(ROOT).contains(search.lowercase(ROOT)) &&
29+
if (kitId != 0L) dKitId == kitId else true
30+
}.sortedWith(sorting)
3331
}
34-
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), database.medicineDAO().getAll())
32+
}.stateIn(
33+
scope = viewModelScope,
34+
started = SharingStarted.WhileSubscribed(),
35+
initialValue = database.medicineDAO().getAll()
36+
)
37+
3538

3639
fun setSearch(text: String) = _state.update { it.copy(search = text) }
3740
fun clearSearch() = _state.update { it.copy(search = BLANK) }

0 commit comments

Comments
 (0)