diff --git a/app/build.gradle b/app/build.gradle index 3d6fd45..03caef2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,6 +48,7 @@ android { } dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' def composeBom = platform('androidx.compose:compose-bom:2025.07.00') implementation composeBom androidTestImplementation composeBom diff --git a/app/src/main/java/ru/yandex/practicum/contacts/data/models/Contact.kt b/app/src/main/java/ru/yandex/practicum/contacts/data/models/Contact.kt index ff16899..1ab703b 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/data/models/Contact.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/data/models/Contact.kt @@ -1,13 +1,5 @@ package ru.yandex.practicum.contacts.data.models -data class Contact( - val id: Long, - val firstName: String, - val lastName: String, - val phoneNumber: String, - val messagingApps: List = emptyList() -) - enum class MessagingApp { TELEGRAM, WHATS_APP, @@ -16,4 +8,6 @@ enum class MessagingApp { THREEMA, PHONE, EMAIL -} \ No newline at end of file +} + +annotation class Contact diff --git a/app/src/main/java/ru/yandex/practicum/contacts/data/models/CountryCode.kt b/app/src/main/java/ru/yandex/practicum/contacts/data/models/CountryCode.kt index 9a7c251..5d1efe8 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/data/models/CountryCode.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/data/models/CountryCode.kt @@ -1,8 +1,8 @@ package ru.yandex.practicum.contacts.data.models -data class CountryCode( - val code: String, - val country: String + data class CountryCode( + val code: String, + val country: String ) { companion object { val COMMON_CODES = listOf( @@ -18,4 +18,6 @@ data class CountryCode( CountryCode("+55", "Brazil") ) } -} \ No newline at end of file +} + +annotation class CountryCode diff --git a/app/src/main/java/ru/yandex/practicum/contacts/data/models/MessagingApp.kt b/app/src/main/java/ru/yandex/practicum/contacts/data/models/MessagingApp.kt new file mode 100644 index 0000000..2cc7eb3 --- /dev/null +++ b/app/src/main/java/ru/yandex/practicum/contacts/data/models/MessagingApp.kt @@ -0,0 +1,10 @@ +package ru.yandex.practicum.contacts.data.models + +annotation class MessagingApp { + companion object { + val entries: List + get() { + TODO() + } + } +} diff --git a/app/src/main/java/ru/yandex/practicum/contacts/data/models/SortOrder.kt b/app/src/main/java/ru/yandex/practicum/contacts/data/models/SortOrder.kt deleted file mode 100644 index 7e78358..0000000 --- a/app/src/main/java/ru/yandex/practicum/contacts/data/models/SortOrder.kt +++ /dev/null @@ -1,8 +0,0 @@ -package ru.yandex.practicum.contacts.data.models - -enum class SortOrder(val displayName: String) { - NAME_ASC("имени (А-Я / A-Z)"), - NAME_DESC("имени (Я-А / Z-A)"), - LAST_NAME_ASC("фамилии (А-Я / A-Z)"), - LAST_NAME_DESC("фамилии (Я-А / Z-A)") -} \ No newline at end of file diff --git a/app/src/main/java/ru/yandex/practicum/contacts/data/repository/ContactsRepository.kt b/app/src/main/java/ru/yandex/practicum/contacts/data/repository/ContactsRepository.kt index ee331b7..ad33f7c 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/data/repository/ContactsRepository.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/data/repository/ContactsRepository.kt @@ -11,9 +11,9 @@ import ru.yandex.practicum.contacts.data.models.MessagingApp import ru.yandex.practicum.contacts.domain.repository.ContactsRepository class ContactsRepositoryImpl(private val context: Context) : ContactsRepository { - override fun getContacts(): Flow> = flow { + fun getContacts(): Flow> = flow { val contacts = mutableListOf() - + context.contentResolver.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, arrayOf( @@ -28,18 +28,18 @@ class ContactsRepositoryImpl(private val context: Context) : ContactsRepository val idIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID) val nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME) val numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER) - + while (cursor.moveToNext()) { val id = cursor.getLong(idIndex) val fullName = cursor.getString(nameIndex) val phoneNumber = cursor.getString(numberIndex) - + val nameParts = fullName.split(" ", limit = 2) val firstName = nameParts.firstOrNull() ?: "" val lastName = nameParts.getOrNull(1) ?: "" - + val messagingApps = MessagingApp.entries.filter { (0..1).random() == 1 } - + contacts.add( Contact( id = id, @@ -51,7 +51,7 @@ class ContactsRepositoryImpl(private val context: Context) : ContactsRepository ) } } - + emit(contacts) }.flowOn(Dispatchers.IO) -} \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/ru/yandex/practicum/contacts/domain/repository/ContactsRepository.kt b/app/src/main/java/ru/yandex/practicum/contacts/domain/repository/ContactsRepository.kt index eb7a793..7a99eb3 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/domain/repository/ContactsRepository.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/domain/repository/ContactsRepository.kt @@ -1,8 +1,3 @@ package ru.yandex.practicum.contacts.domain.repository -import kotlinx.coroutines.flow.Flow -import ru.yandex.practicum.contacts.data.models.Contact - -interface ContactsRepository { - fun getContacts(): Flow> -} \ No newline at end of file +open annotation class ContactsRepository diff --git a/app/src/main/java/ru/yandex/practicum/contacts/presentation/country/CountryCodeBottomSheet.kt b/app/src/main/java/ru/yandex/practicum/contacts/presentation/country/CountryCodeBottomSheet.kt index e74ab23..6c4c93a 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/presentation/country/CountryCodeBottomSheet.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/presentation/country/CountryCodeBottomSheet.kt @@ -1,24 +1,14 @@ package ru.yandex.practicum.contacts.presentation.country -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close -import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.Checkbox import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -27,6 +17,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ru.yandex.practicum.contacts.R import ru.yandex.practicum.contacts.data.models.CountryCode +import ru.yandex.practicum.contacts.presentation.ui.components.CommonBottomSheet @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -35,73 +26,23 @@ fun CountryCodeBottomSheet( onCodesSelected: (Set) -> Unit, onDismiss: () -> Unit ) { - ModalBottomSheet( - onDismissRequest = onDismiss, - dragHandle = { BottomSheetDefaults.DragHandle() } - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(R.string.filter_by_country_code), - style = MaterialTheme.typography.titleLarge - ) - IconButton(onClick = onDismiss) { - Icon( - imageVector = Icons.Default.Close, - contentDescription = stringResource(R.string.close) - ) - } - } - - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp) - ) { - items(CountryCode.COMMON_CODES) { countryCode -> - val isSelected = selectedCodes.contains(countryCode) - Surface( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp), - onClick = { - val newSelection = selectedCodes.toMutableSet() - if (isSelected) { - newSelection.remove(countryCode) - } else { - newSelection.add(countryCode) - } - onCodesSelected(newSelection) - }, - color = if (isSelected) { - MaterialTheme.colorScheme.primaryContainer - } else { - MaterialTheme.colorScheme.surface - } - ) { - CountryCodeOption( - isSelected = isSelected, - countryCode = countryCode, - selectedCodes = selectedCodes, - onCodesSelected = onCodesSelected - ) - } - } - } - } + CommonBottomSheet( + title = stringResource(R.string.filter_by_country_code), + items = CountryCode.COMMON_CODES, + selectedCodes, + onItemsSelected = onCodesSelected, + onDismiss=onDismiss + ) { countryCode, isSelected -> + CountryCodeOption( + isSelected = isSelected, + countryCode = countryCode, + selectedCodes = selectedCodes, + onCodesSelected = onCodesSelected + ) } } + @Composable private fun CountryCodeOption( isSelected: Boolean, diff --git a/app/src/main/java/ru/yandex/practicum/contacts/presentation/messengers/MessengersBottomSheet.kt b/app/src/main/java/ru/yandex/practicum/contacts/presentation/messengers/MessengersBottomSheet.kt index dcddf8d..b15c28c 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/presentation/messengers/MessengersBottomSheet.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/presentation/messengers/MessengersBottomSheet.kt @@ -1,24 +1,12 @@ package ru.yandex.practicum.contacts.presentation.messengers -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close -import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.Checkbox import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -27,6 +15,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ru.yandex.practicum.contacts.R import ru.yandex.practicum.contacts.data.models.MessagingApp +import ru.yandex.practicum.contacts.presentation.ui.components.CommonBottomSheet @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -35,70 +24,19 @@ fun MessengersBottomSheet( onAppsSelected: (Set) -> Unit, onDismiss: () -> Unit ) { - ModalBottomSheet( - onDismissRequest = onDismiss, - dragHandle = { BottomSheetDefaults.DragHandle() } - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(R.string.filter_by_messaging_app), - style = MaterialTheme.typography.titleLarge - ) - IconButton(onClick = onDismiss) { - Icon( - imageVector = Icons.Default.Close, - contentDescription = stringResource(R.string.close) - ) - } - } - - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp) - ) { - items(MessagingApp.entries) { app -> - val isSelected = selectedApps.contains(app) - Surface( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp), - onClick = { - val newSelection = selectedApps.toMutableSet() - if (isSelected) { - newSelection.remove(app) - } else { - newSelection.add(app) - } - onAppsSelected(newSelection) - }, - color = if (isSelected) { - MaterialTheme.colorScheme.primaryContainer - } else { - MaterialTheme.colorScheme.surface - } - ) { - MessengerOption( - isSelected = isSelected, - app = app, - selectedApps = selectedApps, - onAppsSelected = onAppsSelected - ) - } - } - } - } + CommonBottomSheet( + title = stringResource(R.string.filter_by_messaging_app), + items= MessagingApp.entries, + selectedItems = selectedApps, + onItemsSelected = onAppsSelected, + onDismiss=onDismiss + ) {app,isSelected-> + MessengerOption( + isSelected=isSelected, + app=app, + selectedApps=selectedApps, + onAppsSelected=onAppsSelected + ) } } diff --git a/app/src/main/java/ru/yandex/practicum/contacts/presentation/ui/components/CommonBottomSheet.kt b/app/src/main/java/ru/yandex/practicum/contacts/presentation/ui/components/CommonBottomSheet.kt index fbf8d02..0b36944 100644 --- a/app/src/main/java/ru/yandex/practicum/contacts/presentation/ui/components/CommonBottomSheet.kt +++ b/app/src/main/java/ru/yandex/practicum/contacts/presentation/ui/components/CommonBottomSheet.kt @@ -83,4 +83,4 @@ fun CommonBottomSheet( } } } -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index dab7c28..b79bf1a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,5 @@ android.useAndroidX=true # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +android.overridePathCheck=true \ No newline at end of file