diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 506a388..7eab4f5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -45,6 +45,10 @@ android { buildFeatures { compose = true buildConfig = true + aidl = false + renderScript = false + resValues = true + shaders = false } composeOptions { kotlinCompilerExtensionVersion = Versions.composeCompiler @@ -65,6 +69,8 @@ dependencies { implementation(project(":data")) // [MODULE_DEPENDENCY] Domain module (transitively included via data, but explicit for clarity) implementation(project(":domain")) + implementation(project(":ui")) + implementation(project(":feature:inventory")) // [DEPENDENCY] AndroidX implementation(Libs.coreKtx) diff --git a/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt b/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt index 24fe7b7..6cdfff4 100644 --- a/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt +++ b/app/src/main/java/com/homebox/lens/navigation/NavGraph.kt @@ -15,7 +15,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.homebox.lens.ui.screen.dashboard.DashboardScreen -import com.homebox.lens.ui.screen.inventorylist.InventoryListScreen +import com.homebox.lens.feature.inventory.ui.InventoryScreen import com.homebox.lens.ui.screen.itemdetails.ItemDetailsScreen import com.homebox.lens.ui.screen.itemedit.ItemEditScreen import com.homebox.lens.ui.screen.labelslist.LabelsListScreen @@ -26,6 +26,8 @@ import com.homebox.lens.ui.screen.search.SearchScreen import com.homebox.lens.ui.screen.setup.SetupScreen import com.homebox.lens.ui.screen.settings.SettingsScreen import com.homebox.lens.ui.screen.splash.SplashScreen +import com.homebox.lens.navigation.NavigationActions +import com.homebox.lens.ui.navigation.Screen // [END_IMPORTS] // [ENTITY: Function('NavGraph')] @@ -59,7 +61,9 @@ fun NavGraph( composable(route = Screen.Setup.route) { SetupScreen(onSetupComplete = { navController.navigate(Screen.Dashboard.route) { - popUpTo(Screen.Setup.route) { inclusive = true } + popUpTo(Screen.Setup.route) { + inclusive = true + } } }) } @@ -69,8 +73,8 @@ fun NavGraph( navigationActions = navigationActions ) } - composable(route = Screen.InventoryList.route) { - InventoryListScreen( + composable(route = Screen.Inventory.route) { + InventoryScreen( currentRoute = currentRoute, navigationActions = navigationActions ) @@ -105,7 +109,7 @@ fun NavGraph( navigationActions = navigationActions, onLocationClick = { locationId -> // [AI_NOTE]: Navigate to a pre-filtered inventory list screen - navController.navigate(Screen.InventoryList.route) + navController.navigate(Screen.Inventory.route) }, onAddNewLocationClick = { navController.navigate(Screen.LocationEdit.createRoute("new")) diff --git a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt deleted file mode 100644 index 331e62a..0000000 --- a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt +++ /dev/null @@ -1,38 +0,0 @@ -// [FILE] InventoryListScreen.kt -// [SEMANTICS] app, ui, screen, list - -package com.homebox.lens.ui.screen.inventorylist - -// [IMPORTS] -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import com.homebox.lens.R -import com.homebox.lens.navigation.NavigationActions -import com.homebox.lens.ui.common.MainScaffold -// [END_IMPORTS] - -// [ENTITY: Function('InventoryListScreen')] -// [RELATION: Function('InventoryListScreen')] -> [DEPENDS_ON] -> [Class('NavigationActions')] -// [RELATION: Function('InventoryListScreen')] -> [CALLS] -> [Function('MainScaffold')] -/** - * @summary Composable function for the "Inventory List" screen. - * @param currentRoute The current route to highlight the active item in the Drawer. - * @param navigationActions The object with navigation actions. - */ -@Composable -fun InventoryListScreen( - currentRoute: String?, - navigationActions: NavigationActions -) { - MainScaffold( - topBarTitle = stringResource(id = R.string.inventory_list_title), - currentRoute = currentRoute, - navigationActions = navigationActions - ) { - // [AI_NOTE]: Implement Inventory List Screen UI - Text(text = "Inventory List Screen") - } -} -// [END_ENTITY: Function('InventoryListScreen')] -// [END_FILE_InventoryListScreen.kt] diff --git a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt b/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt deleted file mode 100644 index 7c00c57..0000000 --- a/app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListViewModel.kt +++ /dev/null @@ -1,20 +0,0 @@ -// [FILE] InventoryListViewModel.kt -// [SEMANTICS] app, ui, viewmodel, list -package com.homebox.lens.ui.screen.inventorylist - -// [IMPORTS] -import androidx.lifecycle.ViewModel -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -// [END_IMPORTS] - -// [ENTITY: ViewModel('InventoryListViewModel')] -/** - * @summary ViewModel for the inventory list screen. - */ -@HiltViewModel -class InventoryListViewModel @Inject constructor() : ViewModel() { - // [AI_NOTE]: Implement UI state -} -// [END_ENTITY: ViewModel('InventoryListViewModel')] -// [END_FILE_InventoryListViewModel.kt] \ No newline at end of file diff --git a/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt index 71552ac..0aa08c2 100644 --- a/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt +++ b/app/src/main/java/com/homebox/lens/ui/screen/labelslist/LabelsListScreen.kt @@ -36,7 +36,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.homebox.lens.R import com.homebox.lens.domain.model.Label import com.homebox.lens.navigation.NavigationActions -import com.homebox.lens.navigation.Screen +import com.homebox.lens.ui.navigation.Screen import com.homebox.lens.ui.common.MainScaffold import timber.log.Timber // [END_IMPORTS] diff --git a/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt index 4fd5277..f7908be 100644 --- a/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt +++ b/app/src/main/java/com/homebox/lens/ui/screen/splash/SplashScreen.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController -import com.homebox.lens.navigation.Screen +import com.homebox.lens.ui.navigation.Screen import com.homebox.lens.ui.screen.setup.SetupViewModel import timber.log.Timber // [END_IMPORTS] @@ -50,7 +50,9 @@ fun SplashScreen( } navController.navigate(destination) { - popUpTo(Screen.Splash.route) { inclusive = true } + popUpTo(Screen.Splash.route) { + inclusive = true + } } } } diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml deleted file mode 100644 index 2501676..0000000 --- a/app/src/main/res/values-en/strings.xml +++ /dev/null @@ -1,121 +0,0 @@ - - Homebox Lens - - - Create - Edit - Delete - Search - Logout - No location - Items not found - Failed to load data. Please try again. - - - Open navigation drawer - Scan QR code - Navigate back - Add new location - Add new label - - - Dashboard - Quick Stats - Recently Added - Locations - Labels - %1$s (%2$d) - - - Total Items - Total Value - Total Labels - Total Locations - - - Locations - Labels - - - Inventory - - - Details - Edit Item - Labels - Locations - Search - - Save - Name - Description - Quantity - - - Create Location - Edit Location - - - Locations not found. Press + to add a new one. - Items: %1$d - More options - - - Server Setup - Server URL - Username - Password - Connect - - - Labels - Navigate back - Create new label - Label icon - No labels found. - Create Label - Label Name - Create - Cancel - - - - - Sync inventory - - - Edit item - Delete item - Description - No description - Details - Quantity - Location - Labels - - - Create item - Save item - Name - Description - - - Search items... - - - Setup - - - Create label - Edit label - Label name - - - Back - Save - - - Color - HEX color code - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 69c387d..c5bfe8b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,86 +2,112 @@ Homebox Lens - Создать - Редактировать - Удалить - Поиск - Выйти - Нет локации - Элементы не найдены - Не удалось загрузить данные. Пожалуйста, попробуйте еще раз. + Create + Edit + Delete + Search + Logout + No location + Items not found + Failed to load data. Please try again. - Открыть боковое меню - Enter your Homebox server details to connect. - Сканировать QR-код - Вернуться назад - Добавить новую локацию - Добавить новую метку - - - Синхронизировать инвентарь - - - Редактировать элемент - Удалить элемент - Описание - Нет описания - Детали - Количество - Местоположение - Метки - - - Создать элемент - Сохранить элемент - Название - - - Поиск элементов... + Open navigation drawer + Scan QR code + Navigate back + Add new location + Add new label - Главная - Быстрая статистика - Недавно добавлено - Места хранения - Метки + Dashboard + Quick Stats + Recently Added + Locations + Labels %1$s (%2$d) - Всего вещей - Общая стоимость - Всего меток - Всего локаций + Total Items + Total Value + Total Labels + Total Locations - Локации - Метки + Locations + Labels - Инвентарь - Детали - Редактирование - Метки - Места хранения - Поиск + Inventory + + + Details + Edit Item + Labels + Locations + Search + + Save + Name + Description + Quantity + + + Create Location + Edit Location + + + Locations not found. Press + to add a new one. + Items: %1$d + More options + + + Server Setup + Server URL + Username + Password + Connect + + + Labels + Navigate back + Create new label + Label icon + No labels found. + Create Label + Label Name + Create + Cancel + + + Sync inventory + + + Edit item + Delete item + Description + No description + Details + Quantity + Location + Labels + + + Create item + Save item + Name + Description - Сохранить - Название - Описание - Количество General Information Location - Select Location Labels Select Labels + OK + Cancel Purchase Information Purchase Price Purchase From - Purchase Date + Purchase Time Select Date - OK - Cancel Warranty Information Lifetime Warranty Warranty Details @@ -99,50 +125,26 @@ Sold Price Sold To Sold Notes - Sold Date + Sold Time - - Создать локацию - Редактировать локацию - - - Местоположения не найдены. Нажмите +, чтобы добавить новое. - Предметов: %1$d - Больше опций + + Search items... - Настройка - Настройка сервера - URL сервера - Имя пользователя - Пароль - Подключиться - - - Метки - - Настройки - Вернуться назад - Создать новую метку - Иконка метки - Метки не найдены. - Создать метку - Название метки - Создать - Отмена + Setup + Settings - Создать метку - Редактировать метку - Название метки - Описание + Create label + Edit label + Label name - Назад - Сохранить - + Back + Save - Цвет - HEX-код цвета - + Color + HEX color code + + \ No newline at end of file diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt index dad9d64..c70fa19 100644 --- a/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt +++ b/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt @@ -19,10 +19,10 @@ data class ItemSummaryDto( @Json(name = "name") val name: String, @Json(name = "assetId") val assetId: String?, @Json(name = "image") val image: ImageDto?, - @Json(name = "isArchived") val isArchived: Boolean, + @Json(name = "isArchived") val isArchived: Boolean? = false, @Json(name = "labels") val labels: List, @Json(name = "location") val location: LocationOutDto?, - @Json(name = "value") val value: Double, + @Json(name = "value") val value: Double? = 0.0, @Json(name = "createdAt") val createdAt: String, @Json(name = "updatedAt") val updatedAt: String ) @@ -39,10 +39,10 @@ fun ItemSummaryDto.toDomain(): ItemSummary { name = this.name, assetId = this.assetId, image = this.image?.toDomain(), - isArchived = this.isArchived, + isArchived = this.isArchived ?: false, labels = this.labels.map { it.toDomain() }, location = this.location?.toDomain(), - value = this.value, + value = this.value ?: 0.0, createdAt = this.createdAt, updatedAt = this.updatedAt ) diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt index 330a35b..3c9c16a 100644 --- a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt +++ b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt @@ -16,9 +16,9 @@ data class LocationOutDto( @Json(name = "name") val name: String, @Json(name = "color") - val color: String?, + val color: String? = "#000000", @Json(name = "isArchived") - val isArchived: Boolean?, + val isArchived: Boolean? = false, @Json(name = "createdAt") val createdAt: String, @Json(name = "updatedAt") diff --git a/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt b/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt index 6a73bd2..9edb50c 100644 --- a/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt +++ b/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt @@ -103,10 +103,10 @@ fun ItemSummaryDto.toDomain(): DomainItemSummary { name = this.name, assetId = this.assetId, image = this.image?.toDomain(), - isArchived = this.isArchived, + isArchived = this.isArchived ?: false, labels = this.labels.map { it.toDomain() }, location = this.location?.toDomain(), - value = this.value, + value = this.value ?: 0.0, createdAt = this.createdAt, updatedAt = this.updatedAt ) diff --git a/domain/src/main/java/com/homebox/lens/domain/model/Result.kt b/domain/src/main/java/com/homebox/lens/domain/model/Result.kt index 448b23a..02604d9 100644 --- a/domain/src/main/java/com/homebox/lens/domain/model/Result.kt +++ b/domain/src/main/java/com/homebox/lens/domain/model/Result.kt @@ -21,7 +21,7 @@ sealed class Result { * @summary Представляет собой неуспешный результат операции. * @param exception Исключение, которое произошло во время операции. */ - data class Error(val exception: Exception) : Result() + data class Error(val exception: kotlin.Exception) : Result() // [END_ENTITY: DataClass('Error')] } // [END_ENTITY: SealedClass('Result')] diff --git a/domain/src/main/java/com/homebox/lens/domain/model/ResultExtensions.kt b/domain/src/main/java/com/homebox/lens/domain/model/ResultExtensions.kt new file mode 100644 index 0000000..b5004cb --- /dev/null +++ b/domain/src/main/java/com/homebox/lens/domain/model/ResultExtensions.kt @@ -0,0 +1,23 @@ +// [FILE] ResultExtensions.kt +// [SEMANTICS] domain, model, result, extensions +package com.homebox.lens.domain.model + +// [ENTITY: Function('fold')] +/** + * @summary Extension function to handle success and failure cases of a Result. + * @param onSuccess The function to be called if the Result is Success. + * @param onFailure The function to be called if the Result is Error. + * @return The result of either onSuccess or onFailure. + * @param R The return type of the fold operation. + */ +inline fun Result.fold( + onSuccess: (value: T) -> R, + onFailure: (exception: Exception) -> R +): R { + return when (this) { + is Result.Success -> onSuccess(data) + is Result.Error -> onFailure(exception) + } +} +// [END_ENTITY: Function('fold')] +// [END_FILE_ResultExtensions.kt] \ No newline at end of file diff --git a/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt b/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt index ea0afbd..5a2265b 100644 --- a/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt +++ b/domain/src/main/java/com/homebox/lens/domain/usecase/SearchItemsUseCase.kt @@ -6,6 +6,7 @@ package com.homebox.lens.domain.usecase // [IMPORTS] import com.homebox.lens.domain.model.ItemSummary import com.homebox.lens.domain.model.PaginationResult +import com.homebox.lens.domain.model.Result import com.homebox.lens.domain.repository.ItemRepository import javax.inject.Inject // [END_IMPORTS] @@ -23,10 +24,14 @@ class SearchItemsUseCase @Inject constructor( /** * @summary Executes the search operation. * @param query The search query. - * @return A pagination result object. + * @return A Result object encapsulating either a successful PaginationResult or an Error. */ - suspend operator fun invoke(query: String): PaginationResult { - return itemRepository.searchItems(query) + suspend operator fun invoke(query: String): Result> { + return try { + Result.Success(itemRepository.searchItems(query)) + } catch (e: Exception) { + Result.Error(e) + } } // [END_ENTITY: Function('invoke')] } diff --git a/feature/inventory/build.gradle.kts b/feature/inventory/build.gradle.kts new file mode 100644 index 0000000..03d31ca --- /dev/null +++ b/feature/inventory/build.gradle.kts @@ -0,0 +1,59 @@ +// [FILE] feature/inventory/build.gradle.kts +// [SEMANTICS] build, dependencies +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") + id("dagger.hilt.android.plugin") +} + +android { + namespace = "com.homebox.lens.feature.inventory" + compileSdk = Versions.compileSdk + + defaultConfig { + minSdk = Versions.minSdk + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = Versions.composeCompiler + } +} + +dependencies { + implementation(project(":domain")) + implementation(project(":ui")) + + // AndroidX & Lifecycle + implementation(Libs.coreKtx) + implementation(Libs.lifecycleRuntime) + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") + + // Compose + implementation(platform(Libs.composeBom)) + implementation(Libs.composeUi) + implementation(Libs.composeUiGraphics) + implementation(Libs.composeUiToolingPreview) + implementation(Libs.composeMaterial3) + implementation(Libs.navigationCompose) + implementation(Libs.hiltNavigationCompose) + + // Hilt + implementation(Libs.hiltAndroid) + kapt(Libs.hiltCompiler) + + // Other + implementation(Libs.timber) + implementation("io.coil-kt:coil-compose:2.4.0") +} +// [END_FILE_feature/inventory/build.gradle.kts] \ No newline at end of file diff --git a/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryScreen.kt b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryScreen.kt new file mode 100644 index 0000000..e993ba7 --- /dev/null +++ b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryScreen.kt @@ -0,0 +1,160 @@ +// [FILE] InventoryScreen.kt +// [SEMANTICS] ui, screen, list, compose +package com.homebox.lens.feature.inventory.ui + +// [IMPORTS] +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Card +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.homebox.lens.domain.model.ItemSummary +import com.homebox.lens.navigation.NavigationActions +import com.homebox.lens.ui.navigation.Screen +import com.homebox.lens.ui.R // Import R from ui module +import com.homebox.lens.ui.common.MainScaffold +// [END_IMPORTS] + +// [ENTITY: Function('InventoryScreen')] +// [RELATION: Function('InventoryScreen')] -> [DEPENDS_ON] -> [Class('NavigationActions')] +// [RELATION: Function('InventoryScreen')] -> [CALLS] -> [Function('MainScaffold')] +// [RELATION: Function('InventoryScreen')] -> [CONSUMES_STATE] -> [ViewModel('InventoryViewModel')] +/** + * @summary Composable function for the "Inventory" screen. + * @param currentRoute The current route to highlight the active item in the Drawer. + * @param navigationActions The object with navigation actions. + * @param viewModel The ViewModel for this screen. + */ +@Composable +fun InventoryScreen( + currentRoute: String?, + navigationActions: NavigationActions, + viewModel: InventoryViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsState() + + MainScaffold( + topBarTitle = stringResource(id = R.string.inventory_list_title), + currentRoute = currentRoute, + navigationActions = navigationActions + ) { innerPadding -> + Box( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), + contentAlignment = Alignment.Center + ) { + when (val state = uiState) { + is InventoryUiState.Loading -> CircularProgressIndicator() + is InventoryUiState.Success -> InventoryList( + items = state.items, + onItemClick = { itemId -> + navigationActions.navigateToItemDetails(itemId) + } + ) + is InventoryUiState.Error -> Text(text = state.message) + } + } + } +} +// [END_ENTITY: Function('InventoryScreen')] + +// [ENTITY: Function('InventoryList')] +// [RELATION: Function('InventoryList')] -> [DEPENDS_ON] -> [DataClass('ItemSummary')] +// [RELATION: Function('InventoryList')] -> [CALLS] -> [Function('ItemRow')] +/** + * @summary Displays a list of inventory items. + * @param items The list of items to display. + * @param onItemClick Callback invoked when an item is clicked. + */ +@Composable +private fun InventoryList( + items: List, + onItemClick: (String) -> Unit +) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(8.dp) + ) { + items(items) { item -> + ItemRow(item = item, onItemClick = onItemClick) + } + } +} +// [END_ENTITY: Function('InventoryList')] + +// [ENTITY: Function('ItemRow')] +// [RELATION: Function('ItemRow')] -> [DEPENDS_ON] -> [DataClass('ItemSummary')] +/** + * @summary Displays a single row in the inventory list. + * @param item The item to display. + * @param onItemClick Callback invoked when the row is clicked. + */ +@Composable +private fun ItemRow( + item: ItemSummary, + onItemClick: (String) -> Unit +) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp) + .clickable { onItemClick(item.id) }, + ) { + Row( + modifier = Modifier.padding(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(item.image?.path) + .crossfade(true) + .build(), + placeholder = painterResource(R.drawable.ic_placeholder), + error = painterResource(R.drawable.ic_placeholder), + contentDescription = item.name, + contentScale = ContentScale.Crop, + modifier = Modifier.size(64.dp) + ) + Spacer(modifier = Modifier.width(16.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = item.name, + style = MaterialTheme.typography.titleMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + item.location?.let { + Text( + text = it.name, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + } + // [AI_NOTE]: Quantity is not present in ItemSummary, so it's omitted for now. + // Placeholder: quantity will be added later when ItemSummary is updated to include it. + } + } +} +// [END_ENTITY: Function('ItemRow')] + +// [END_FILE_InventoryScreen.kt] \ No newline at end of file diff --git a/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryUiState.kt b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryUiState.kt new file mode 100644 index 0000000..a2fc4e3 --- /dev/null +++ b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryUiState.kt @@ -0,0 +1,40 @@ +// [FILE] InventoryUiState.kt +// [SEMANTICS] ui, state_management, sealed_state +package com.homebox.lens.feature.inventory.ui + +// [IMPORTS] +import com.homebox.lens.domain.model.ItemSummary +// [END_IMPORTS] + +// [ENTITY: SealedInterface('InventoryUiState')] +/** + * @summary Represents the different states of the Inventory screen. + * @invariant Only one state can be active at a time. + */ +sealed interface InventoryUiState { + // [END_ENTITY: SealedInterface('InventoryUiState')] + + // [ENTITY: Object('Loading')] + /** + * @summary Represents the loading state, where the list of items is being fetched. + */ + object Loading : InventoryUiState + // [END_ENTITY: Object('Loading')] + + // [ENTITY: DataClass('Success')] + /** + * @summary Represents the success state, where the list of items is available. + * @param items The list of inventory items. + */ + data class Success(val items: List) : InventoryUiState + // [END_ENTITY: DataClass('Success')] + + // [ENTITY: DataClass('Error')] + /** + * @summary Represents the error state, where an error occurred while fetching items. + * @param message The error message. + */ + data class Error(val message: String) : InventoryUiState + // [END_ENTITY: DataClass('Error')] +} +// [END_FILE_InventoryUiState.kt] \ No newline at end of file diff --git a/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryViewModel.kt b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryViewModel.kt new file mode 100644 index 0000000..67e5d62 --- /dev/null +++ b/feature/inventory/src/main/java/com/homebox/lens/feature/inventory/ui/InventoryViewModel.kt @@ -0,0 +1,77 @@ +// [FILE] InventoryViewModel.kt +// [SEMANTICS] ui, viewmodel, state_management +package com.homebox.lens.feature.inventory.ui + +// [IMPORTS] +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.homebox.lens.domain.usecase.SearchItemsUseCase +import com.homebox.lens.domain.model.PaginationResult +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import timber.log.Timber +import com.homebox.lens.domain.model.fold +import javax.inject.Inject +// [END_IMPORTS] + +// [ENTITY: ViewModel('InventoryViewModel')] +// [RELATION: ViewModel('InventoryViewModel')] -> [DEPENDS_ON] -> [UseCase('SearchItemsUseCase')] +// [RELATION: ViewModel('InventoryViewModel')] -> [EMITS_STATE] -> [SealedInterface('InventoryUiState')] +/** + * @summary ViewModel for the Inventory screen. + * @param searchItemsUseCase The use case to search for inventory items. + * @invariant The ViewModel manages the UI state and business logic for the inventory screen. + */ +@HiltViewModel +class InventoryViewModel @Inject constructor( + private val searchItemsUseCase: SearchItemsUseCase +) : ViewModel() { + + // [ENTITY: DataStructure('uiState')] + private val _uiState = MutableStateFlow(InventoryUiState.Loading) + val uiState: StateFlow = _uiState.asStateFlow() + // [END_ENTITY: DataStructure('uiState')] + + init { + fetchInventoryItems() + } + + // [ENTITY: Function('fetchInventoryItems')] + // [RELATION: Function('fetchInventoryItems')] -> [CALLS] -> [UseCase('SearchItemsUseCase')] + // [RELATION: Function('fetchInventoryItems')] -> [MODIFIES_STATE_OF] -> [DataStructure('uiState')] + /** + * @summary Fetches the list of inventory items. + * @sideeffect Updates the `uiState` with the result of the operation. + */ + private fun fetchInventoryItems() { + viewModelScope.launch { + _uiState.value = InventoryUiState.Loading + Timber.d("[DEBUG][INVENTORY_VIEW_MODEL][FETCH_START] Fetching inventory items.") + try { + val result = searchItemsUseCase(query = "") + + result.fold( + onSuccess = { paginationResult -> + @Suppress("UNCHECKED_CAST") + val items = paginationResult.items as List + _uiState.value = InventoryUiState.Success(items) + Timber.i("[INFO][INVENTORY_VIEW_MODEL][FETCH_SUCCESS] Successfully fetched %d items.", items.size) + }, + onFailure = { throwable: Exception -> + _uiState.value = InventoryUiState.Error(throwable.message ?: "Unknown error") + Timber.e(throwable, "[ERROR][INVENTORY_VIEW_MODEL][FETCH_FAILURE] Error fetching inventory items: %s", throwable.message) + } + ) + } catch (e: Exception) { + _uiState.value = InventoryUiState.Error(e.message ?: "An unexpected error occurred") + Timber.e(e, "[ERROR][INVENTORY_VIEW_MODEL][FETCH_UNEXPECTED] Unexpected error fetching inventory items: %s", e.message) + } + } + } + // [END_ENTITY: Function('fetchInventoryItems')] +} +// [END_ENTITY: ViewModel('InventoryViewModel')] +// [END_FILE_InventoryViewModel.kt] \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 9f9a3fb..3535841 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,6 +21,8 @@ rootProject.name = "HomeboxLens" include(":app") include(":data") include(":domain") +include(":ui") +include(":feature:inventory") +include(":data:semantic-ktlint-rules") // [END_FILE_settings.gradle.kts] -include(":data:semantic-ktlint-rules") diff --git a/tasks/20251005_migrate_moshi_to_ksp.xml b/tasks/20251005_migrate_moshi_to_ksp.xml deleted file mode 100644 index 1c04347..0000000 --- a/tasks/20251005_migrate_moshi_to_ksp.xml +++ /dev/null @@ -1,84 +0,0 @@ - - Миграция Moshi с Kapt на KSP - - Устранить предупреждение "Kapt support in Moshi Kotlin Code Gen is deprecated". - Это требует миграции генерации кода Moshi с `kapt` на `KSP` (Kotlin Symbol Processing). - - - - Добавить плагин KSP в корневой файл `build.gradle.kts`. - - apply_diff - - - build.gradle.kts - - - >>>>>> REPLACE -]]> - - 9 - - - - - - - Применить плагин KSP и заменить зависимость `kapt` на `ksp` для Moshi в файле `data/build.gradle.kts`. - - apply_diff - - - data/build.gradle.kts - - - >>>>>> REPLACE -]]> - - 6 - - - - >>>>>> REPLACE -]]> - - 53 - - - - - - - -]]> \ No newline at end of file diff --git a/tasks/20251005_remove_package_from_manifest.xml b/tasks/20251005_remove_package_from_manifest.xml deleted file mode 100644 index 569ee11..0000000 --- a/tasks/20251005_remove_package_from_manifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - Удаление атрибута package из AndroidManifest.xml - - Устранить предупреждение "Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported". - Это требует удаления устаревшего атрибута `package` из файла `app/src/main/AndroidManifest.xml`. - - - - Удалить атрибут `package` из тега `manifest` в файле `app/src/main/AndroidManifest.xml`. - - apply_diff - - - app/src/main/AndroidManifest.xml - - - -======= - ->>>>>>> REPLACE -]]> - - 2 - - - - - - - -]]> \ No newline at end of file diff --git a/tasks/20251005_update_gradle_and_java.xml b/tasks/20251005_update_gradle_and_java.xml deleted file mode 100644 index f7f9788..0000000 --- a/tasks/20251005_update_gradle_and_java.xml +++ /dev/null @@ -1,86 +0,0 @@ - - Устранение предупреждений сборки Gradle - - Необходимо устранить два типа предупреждений, возникающих при сборке проекта: - 1. Использование устаревшего метода `Configuration.fileCollection(Spec)` в плагине `org.jetbrains.kotlin.android`. - 2. Использование устаревшей версии Java 8 для компиляции. - - - - Обновить версию Android Gradle Plugin (AGP) и плагина Kotlin в корневом файле `build.gradle.kts`. - - apply_diff - - - build.gradle.kts - - - >>>>>> REPLACE -]]> - - 5 - - - - - - - Обновить версию Java до 17 в файлах сборки всех модулей. Начать с `data/build.gradle.kts`. - - apply_diff - - - data/build.gradle.kts - - - >>>>>> REPLACE -]]> - - 29 - - - - - - - Применить аналогичные изменения для `app/build.gradle.kts` и других модулей. (Примечание: этот шаг потребует поиска и изменения всех `build.gradle.kts` файлов в проекте). - - search_files - - . - build\.gradle\.kts - - - - - -]]> \ No newline at end of file diff --git a/tasks/20251006_add_missing_string_resources.xml b/tasks/20251006_add_missing_string_resources.xml new file mode 100644 index 0000000..a41a4c4 --- /dev/null +++ b/tasks/20251006_add_missing_string_resources.xml @@ -0,0 +1,65 @@ + + + 20251006_add_missing_string_resources + Architect + 2025-10-06T06:05:22Z + Homebox-Lens + Add Missing String Resources to Resolve Build Failure + + The project build is currently failing due to multiple 'Unresolved reference' errors in `ItemEditScreen.kt` and `SettingsScreen.kt`. These errors are caused by missing string resources. To fix this, the specified string resources must be added to the `app/src/main/res/values/strings.xml` file. + + + app/src/main/res/values/strings.xml + + + - The project must compile successfully without any 'Unresolved reference' errors related to string resources. + - All new strings must be added to `app/src/main/res/values/strings.xml`. + - The new strings should have meaningful English values. + + + - Changes should be limited to the `app/src/main/res/values/strings.xml` file. No other files should be modified unless absolutely necessary to resolve the primary issue. + + + app/src/main/res/values/strings.xml + + + + The new strings are for the item editing screen and settings screen. The text should be clear and concise. + + + The following string resources are missing and must be added to `app/src/main/res/values/strings.xml`: + - `item_edit_general_information` + - `item_edit_location` + - `item_edit_labels` + - `item_edit_select_labels` + - `dialog_ok` + - `dialog_cancel` + - `item_edit_purchase_information` + - `item_edit_purchase_price` + - `item_edit_purchase_from` + - `item_edit_purchase_time` + - `item_edit_select_date` + - `item_edit_warranty_information` + - `item_edit_lifetime_warranty` + - `item_edit_warranty_details` + - `item_edit_warranty_expires` + - `item_edit_identification` + - `item_edit_asset_id` + - `item_edit_serial_number` + - `item_edit_manufacturer` + - `item_edit_model_number` + - `item_edit_status_notes` + - `item_edit_archived` + - `item_edit_insured` + - `item_edit_notes` + - `item_edit_sold_information` + - `item_edit_sold_price` + - `item_edit_sold_to` + - `item_edit_sold_notes` + - `item_edit_sold_time` + - `screen_title_settings` + + + +]]> \ No newline at end of file diff --git a/tasks/work_order_inventory_screen.xml b/tasks/work_order_inventory_screen.xml deleted file mode 100644 index 6e27d00..0000000 --- a/tasks/work_order_inventory_screen.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - 1 - 25 - - - filesystem - - tasks/temp - - - - - - xml_file - - logs/metrics - - - - - - xml_file - - logs/main - - - - - - Создать полнофункциональный экран "Inventory", который будет отображать список предметов инвентаря. Экран должен использовать существующую архитектуру и компоненты. - - - - Linux - /usr/bin/zsh - - - Homebox Lens - Android (Jetpack Compose) - Kotlin - Gradle - MVVM, Clean Architecture - - - - - domain/src/main/java/com/homebox/lens/domain/model/ItemSummary.kt - - - app/src/main/java/com/homebox/lens/ui/screen/inventorylist/InventoryListScreen.kt - - - - - Создан новый Gradle-модуль `feature:inventory`. - - - В модуле `feature:inventory` реализован `InventoryScreen`, `InventoryViewModel` и `InventoryUiState`. - - - `InventoryViewModel` использует `SearchItemsUseCase` для получения списка предметов. - - - `InventoryScreen` отображает список предметов, используя `ItemSummary` в качестве модели представления для каждого элемента списка. - - - Новый экран интегрирован в навигацию приложения. - - - Весь новый код соответствует стайлгайду проекта и семантически корректен. - - - - - Создание модуля - Создать новый feature-модуль с именем `inventory`. - - - Реализация ViewModel - Создать `InventoryViewModel` который будет запрашивать данные из `SearchItemsUseCase` и управлять состоянием экрана `InventoryUiState`. - - - Реализация UI - Создать `InventoryScreen`, который будет отображать список `ItemSummary` из `InventoryUiState`. Для каждого элемента списка создать `ItemRow` composable. - - - Интеграция навигации - Добавить `InventoryScreen` в граф навигации приложения. - - - Рефакторинг - Удалить старый `InventoryListScreen` из `app` модуля, если он больше не нужен. - - - \ No newline at end of file diff --git a/ui/build.gradle.kts b/ui/build.gradle.kts new file mode 100644 index 0000000..fc00fe4 --- /dev/null +++ b/ui/build.gradle.kts @@ -0,0 +1,55 @@ +// [FILE] ui/build.gradle.kts +// [SEMANTICS] build, dependencies, ui +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") // Add kapt for Hilt +} + +android { + namespace = "com.homebox.lens.ui" + compileSdk = Versions.compileSdk + + defaultConfig { + minSdk = Versions.minSdk + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = Versions.composeCompiler + } +} + +dependencies { + // AndroidX + implementation(Libs.coreKtx) + implementation(Libs.lifecycleRuntime) // For androidx.lifecycle:lifecycle-runtime-ktx + + // Compose + implementation(platform(Libs.composeBom)) + implementation(Libs.composeUi) + implementation(Libs.composeUiGraphics) + implementation(Libs.composeUiToolingPreview) + implementation(Libs.composeMaterial3) + implementation(Libs.activityCompose) + implementation("androidx.compose.material:material-icons-extended-android:1.6.8") + implementation(Libs.navigationCompose) // For NavigationActions + implementation(Libs.hiltNavigationCompose) // For Hilt with Compose + + // Hilt + implementation(Libs.hiltAndroid) + kapt(Libs.hiltCompiler) + + // Other + implementation(Libs.timber) +} +// [END_FILE_ui/build.gradle.kts] \ No newline at end of file diff --git a/app/src/main/java/com/homebox/lens/navigation/NavigationActions.kt b/ui/src/main/java/com/homebox/lens/navigation/NavigationActions.kt similarity index 81% rename from app/src/main/java/com/homebox/lens/navigation/NavigationActions.kt rename to ui/src/main/java/com/homebox/lens/navigation/NavigationActions.kt index 24e80f7..08a666d 100644 --- a/app/src/main/java/com/homebox/lens/navigation/NavigationActions.kt +++ b/ui/src/main/java/com/homebox/lens/navigation/NavigationActions.kt @@ -1,10 +1,11 @@ // [FILE] NavigationActions.kt -// [SEMANTICS] app, ui, navigation, actions +// [SEMANTICS] ui, navigation, actions package com.homebox.lens.navigation // [IMPORTS] import androidx.navigation.NavHostController import timber.log.Timber +import com.homebox.lens.ui.navigation.Screen // [END_IMPORTS] // [ENTITY: Class('NavigationActions')] @@ -64,10 +65,19 @@ class NavigationActions(private val navController: NavHostController) { } // [END_ENTITY: Function('navigateToSearch')] + // [ENTITY: Function('navigateToInventory')] + fun navigateToInventory() { + Timber.i("[INFO][ACTION][navigate_to_inventory] Navigating to Inventory.") + navController.navigate(Screen.Inventory.route) { + launchSingleTop = true + } + } + // [END_ENTITY: Function('navigateToInventory')] + // [ENTITY: Function('navigateToInventoryListWithLabel')] fun navigateToInventoryListWithLabel(labelId: String) { Timber.i("[INFO][ACTION][navigate_to_inventory_with_label] Navigating to Inventory with label: %s", labelId) - val route = Screen.InventoryList.withFilter("label", labelId) + val route = Screen.Inventory.withFilter("label", labelId) navController.navigate(route) } // [END_ENTITY: Function('navigateToInventoryListWithLabel')] @@ -75,7 +85,7 @@ class NavigationActions(private val navController: NavHostController) { // [ENTITY: Function('navigateToInventoryListWithLocation')] fun navigateToInventoryListWithLocation(locationId: String) { Timber.i("[INFO][ACTION][navigate_to_inventory_with_location] Navigating to Inventory with location: %s", locationId) - val route = Screen.InventoryList.withFilter("location", locationId) + val route = Screen.Inventory.withFilter("location", locationId) navController.navigate(route) } // [END_ENTITY: Function('navigateToInventoryListWithLocation')] @@ -87,6 +97,13 @@ class NavigationActions(private val navController: NavHostController) { } // [END_ENTITY: Function('navigateToCreateItem')] + // [ENTITY: Function('navigateToItemDetails')] + fun navigateToItemDetails(itemId: String) { + Timber.i("[INFO][ACTION][navigate_to_item_details] Navigating to Item Details with ID: %s", itemId) + navController.navigate(Screen.ItemDetails.createRoute(itemId)) + } + // [END_ENTITY: Function('navigateToItemDetails')] + // [ENTITY: Function('navigateToLogout')] fun navigateToLogout() { Timber.i("[INFO][ACTION][navigate_to_logout] Navigating to Logout.") @@ -104,4 +121,4 @@ class NavigationActions(private val navController: NavHostController) { // [END_ENTITY: Function('navigateBack')] } // [END_ENTITY: Class('NavigationActions')] -// [END_FILE_NavigationActions.kt] +// [END_FILE_NavigationActions.kt] \ No newline at end of file diff --git a/app/src/main/java/com/homebox/lens/navigation/Screen.kt b/ui/src/main/java/com/homebox/lens/navigation/Screen.kt similarity index 92% rename from app/src/main/java/com/homebox/lens/navigation/Screen.kt rename to ui/src/main/java/com/homebox/lens/navigation/Screen.kt index ff428e9..67e50f6 100644 --- a/app/src/main/java/com/homebox/lens/navigation/Screen.kt +++ b/ui/src/main/java/com/homebox/lens/navigation/Screen.kt @@ -1,6 +1,6 @@ // [FILE] Screen.kt -// [SEMANTICS] app, ui, navigation, routes -package com.homebox.lens.navigation +// [SEMANTICS] ui, navigation, routes +package com.homebox.lens.ui.navigation // [ENTITY: SealedClass('Screen')] /** @@ -21,11 +21,11 @@ sealed class Screen(val route: String) { data object Dashboard : Screen("dashboard_screen") // [END_ENTITY: Object('Dashboard')] - // [ENTITY: Object('InventoryList')] - data object InventoryList : Screen("inventory_list_screen") { + // [ENTITY: Object('Inventory')] + data object Inventory : Screen("inventory_screen") { // [ENTITY: Function('withFilter')] /** - * @summary Creates a route for the inventory list screen with a filter parameter. + * @summary Creates a route for the inventory screen with a filter parameter. * @param key The filter key (e.g., "label" or "location"). * @param value The filter value (e.g., the ID of the label or location). * @return A string of the full route with a query parameter. @@ -34,13 +34,13 @@ sealed class Screen(val route: String) { fun withFilter(key: String, value: String): String { require(key.isNotBlank()) { "Filter key cannot be blank." } require(value.isNotBlank()) { "Filter value cannot be blank." } - val constructedRoute = "inventory_list_screen?$key=$value" + val constructedRoute = "inventory_screen?$key=$value" check(constructedRoute.contains("?$key=$value")) { "Route must contain the filter query." } return constructedRoute } // [END_ENTITY: Function('withFilter')] } - // [END_ENTITY: Object('InventoryList')] + // [END_ENTITY: Object('Inventory')] // [ENTITY: Object('ItemDetails')] data object ItemDetails : Screen("item_details_screen/{itemId}") { @@ -127,4 +127,4 @@ sealed class Screen(val route: String) { // [END_ENTITY: Object('Settings')] } // [END_ENTITY: SealedClass('Screen')] -// [END_FILE_Screen.kt] +// [END_FILE_Screen.kt] \ No newline at end of file diff --git a/app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt b/ui/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt similarity index 89% rename from app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt rename to ui/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt index ff9b896..eeec9c3 100644 --- a/app/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt +++ b/ui/src/main/java/com/homebox/lens/ui/common/AppDrawer.kt @@ -1,5 +1,5 @@ // [FILE] AppDrawer.kt -// [SEMANTICS] app, ui, common, navigation +// [SEMANTICS] ui, common, navigation package com.homebox.lens.ui.common // [IMPORTS] @@ -21,9 +21,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.homebox.lens.R +import com.homebox.lens.ui.R import com.homebox.lens.navigation.NavigationActions -import com.homebox.lens.navigation.Screen +import com.homebox.lens.ui.navigation.Screen // [END_IMPORTS] // [ENTITY: Function('AppDrawerContent')] @@ -65,6 +65,14 @@ internal fun AppDrawerContent( onCloseDrawer() } ) + NavigationDrawerItem( + label = { Text(stringResource(id = R.string.inventory_list_title)) }, + selected = currentRoute == Screen.Inventory.route, + onClick = { + navigationActions.navigateToInventory() + onCloseDrawer() + } + ) NavigationDrawerItem( label = { Text(stringResource(id = R.string.nav_locations)) }, selected = currentRoute == Screen.LocationsList.route, @@ -102,4 +110,4 @@ internal fun AppDrawerContent( } } // [END_ENTITY: Function('AppDrawerContent')] -// [END_FILE_AppDrawer.kt] +// [END_FILE_AppDrawer.kt] \ No newline at end of file diff --git a/app/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt b/ui/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt similarity index 96% rename from app/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt rename to ui/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt index c7d7821..7a9c353 100644 --- a/app/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt +++ b/ui/src/main/java/com/homebox/lens/ui/common/MainScaffold.kt @@ -1,6 +1,5 @@ // [FILE] MainScaffold.kt -// [SEMANTICS] app, ui, common, scaffold - +// [SEMANTICS] ui, common, scaffold package com.homebox.lens.ui.common // [IMPORTS] @@ -11,7 +10,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.res.stringResource -import com.homebox.lens.R +import com.homebox.lens.ui.R import com.homebox.lens.navigation.NavigationActions import kotlinx.coroutines.launch // [END_IMPORTS] diff --git a/ui/src/main/res/drawable/ic_placeholder.xml b/ui/src/main/res/drawable/ic_placeholder.xml new file mode 100644 index 0000000..d1dcd5f --- /dev/null +++ b/ui/src/main/res/drawable/ic_placeholder.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml new file mode 100644 index 0000000..0f760c6 --- /dev/null +++ b/ui/src/main/res/values/strings.xml @@ -0,0 +1,19 @@ + + + Создать + Поиск + Выйти + + + Открыть боковое меню + + + Главная + + + Локации + Метки + + + Инвентарь + \ No newline at end of file