diff --git a/agent_promts/roles/architect.xml b/agent_promts/roles/architect.xml index d7de1ea..095f3de 100644 --- a/agent_promts/roles/architect.xml +++ b/agent_promts/roles/architect.xml @@ -18,7 +18,7 @@ - При исполнении этой роли, я, Gemini, действую как стратегический интерфейс между человеком-архитектором и автоматизированной системой разработки. Моя задача — вести итеративный диалог для уточнения целей, анализировать кодовую базу и, после получения одобрения, инициировать производственную цепочку через выбранный канал задач. + При исполнении этой роли, я действую как стратегический интерфейс между человеком-архитектором и автоматизированной системой разработки. Моя задача — вести итеративный диалог для уточнения целей, анализировать кодовую базу и, после получения одобрения, инициировать производственную цепочку через выбранный канал задач. Основная цель этой роли — трансформировать неструктурированный человеческий диалог в структурированный, машиночитаемый и полностью готовый к исполнению `Work Order` для роли 'Агента-Разработчика'. diff --git a/agent_promts/roles/semantic_linter.xml b/agent_promts/roles/semantic_linter.xml index 110f287..2afb586 100644 --- a/agent_promts/roles/semantic_linter.xml +++ b/agent_promts/roles/semantic_linter.xml @@ -30,21 +30,6 @@ - - Задачи для этой роли должны содержать XML-блок, определяющий режим работы. - - - full_project | recent_changes | single_file - - - - - - ]]> - - - diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/TokenResponseDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/TokenResponseDto.kt index 9d860f6..446b133 100644 --- a/data/src/main/java/com/homebox/lens/data/api/dto/TokenResponseDto.kt +++ b/data/src/main/java/com/homebox/lens/data/api/dto/TokenResponseDto.kt @@ -28,7 +28,9 @@ data class TokenResponseDto( */ fun TokenResponseDto.toDomain(): TokenResponse { return TokenResponse( - token = this.token + token = this.token, + attachmentToken = this.attachmentToken, + expiresAt = this.expiresAt ) } // [END_ENTITY: Function('toDomain')] diff --git a/data/src/main/java/com/homebox/lens/data/api/model/LoginRequest.kt b/data/src/main/java/com/homebox/lens/data/api/model/LoginRequest.kt index b71fd40..0b5296c 100644 --- a/data/src/main/java/com/homebox/lens/data/api/model/LoginRequest.kt +++ b/data/src/main/java/com/homebox/lens/data/api/model/LoginRequest.kt @@ -4,9 +4,6 @@ package com.homebox.lens.data.api.model -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - // [IMPORTS] import com.squareup.moshi.Json import com.squareup.moshi.JsonClass 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 e868b79..3e720d9 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 @@ -20,6 +20,7 @@ import com.homebox.lens.domain.model.LocationOut as DomainLocationOut import com.homebox.lens.domain.model.LocationOutCount as DomainLocationOutCount import com.homebox.lens.domain.model.MaintenanceEntry as DomainMaintenanceEntry import com.homebox.lens.domain.model.PaginationResult as DomainPaginationResult +import com.homebox.lens.domain.model.TokenResponse as DomainTokenResponse // [END_IMPORTS] // [ENTITY: Function('ItemOutDto.toDomain')] @@ -265,4 +266,5 @@ fun LabelSummaryDto.toDomain(): DomainLabelSummary { } // [END_ENTITY: Function('LabelSummaryDto.toDomain')] + // [END_FILE_DtoToDomain.kt] \ No newline at end of file diff --git a/data/src/main/java/com/homebox/lens/data/repository/AuthRepositoryImpl.kt b/data/src/main/java/com/homebox/lens/data/repository/AuthRepositoryImpl.kt index d1d16dd..cce0a9d 100644 --- a/data/src/main/java/com/homebox/lens/data/repository/AuthRepositoryImpl.kt +++ b/data/src/main/java/com/homebox/lens/data/repository/AuthRepositoryImpl.kt @@ -8,8 +8,9 @@ package com.homebox.lens.data.repository import android.content.SharedPreferences import com.homebox.lens.data.api.HomeboxApiService import com.homebox.lens.data.api.dto.LoginFormDto -import com.homebox.lens.data.api.mapper.toDomain +import com.homebox.lens.data.api.dto.toDomain import com.homebox.lens.domain.model.Credentials +import com.homebox.lens.domain.model.Result import com.homebox.lens.domain.model.TokenResponse import com.homebox.lens.domain.repository.AuthRepository import kotlinx.coroutines.Dispatchers @@ -56,7 +57,7 @@ class AuthRepositoryImpl @Inject constructor( require(credentials.serverUrl.isNotBlank()) { "Server URL cannot be blank." } return withContext(Dispatchers.IO) { - runCatching { + try { Timber.d("[DEBUG][ACTION][creating_retrofit_client] Creating temporary Retrofit client for URL: ${credentials.serverUrl}") val tempApiService = Retrofit.Builder() .baseUrl(credentials.serverUrl) @@ -70,7 +71,10 @@ class AuthRepositoryImpl @Inject constructor( val tokenResponseDto = tempApiService.login(loginForm) Timber.d("[DEBUG][ACTION][mapping_to_domain] Mapping token response to domain model.") - tokenResponseDto.toDomain() + Result.Success(tokenResponseDto.toDomain()) + } catch (e: Exception) { + Timber.e(e, "[ERROR][FAILURE][login_failed] Login failed.") + Result.Error(e) } } } diff --git a/domain/src/main/java/com/homebox/lens/domain/model/TokenResponse.kt b/domain/src/main/java/com/homebox/lens/domain/model/TokenResponse.kt index 170c1a8..9e40f62 100644 --- a/domain/src/main/java/com/homebox/lens/domain/model/TokenResponse.kt +++ b/domain/src/main/java/com/homebox/lens/domain/model/TokenResponse.kt @@ -8,9 +8,15 @@ package com.homebox.lens.domain.model /** * @summary Data model representing a response from the server with an authentication token. * @param token A string containing a JWT or other access token. + * @param attachmentToken A token for accessing attachments. + * @param expiresAt The expiration date of the token. * @invariant `token` must not be blank. */ -data class TokenResponse(val token: String) { +data class TokenResponse( + val token: String, + val attachmentToken: String, + val expiresAt: String +) { init { require(token.isNotBlank()) { "Token cannot be blank." } } diff --git a/domain/src/main/java/com/homebox/lens/domain/usecase/LoginUseCase.kt b/domain/src/main/java/com/homebox/lens/domain/usecase/LoginUseCase.kt index ae6b253..befb896 100644 --- a/domain/src/main/java/com/homebox/lens/domain/usecase/LoginUseCase.kt +++ b/domain/src/main/java/com/homebox/lens/domain/usecase/LoginUseCase.kt @@ -31,17 +31,19 @@ class LoginUseCase @Inject constructor( "Server URL and username must not be blank." } - val loginResult: com.homebox.lens.domain.model.Result = authRepository.login(credentials) - - return loginResult.fold( - onSuccess = { - authRepository.saveToken(it.token) - com.homebox.lens.domain.model.Result.Success(Unit) - }, - onFailure = { - com.homebox.lens.domain.model.Result.Error(it as Exception) + return try { + when (val loginResult = authRepository.login(credentials)) { + is com.homebox.lens.domain.model.Result.Success -> { + authRepository.saveToken(loginResult.data.token) + Result.success(Unit) + } + is com.homebox.lens.domain.model.Result.Error -> { + Result.failure(loginResult.exception) + } } - ) + } catch (e: Exception) { + Result.failure(e) + } } // [END_ENTITY: Function('invoke')] } diff --git a/tasks/enrichment_task_1.xml b/tasks/enrichment_task_1.xml deleted file mode 100644 index 6c1763a..0000000 --- a/tasks/enrichment_task_1.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - enrichment-task-001 - Perform initial semantic enrichment - agent-enrichment - type::enrichment - status::pending - - - - full_project - - - - -]]> \ No newline at end of file diff --git a/tasks/enrichment_ui.xml b/tasks/enrichment_ui.xml deleted file mode 100644 index 2707fc1..0000000 --- a/tasks/enrichment_ui.xml +++ /dev/null @@ -1,6 +0,0 @@ - - directory - app/src/main/java/com/homebox/lens/ui - -]]> \ No newline at end of file diff --git a/tasks/work_order_item_edit_screen.xml b/tasks/work_order_item_edit_screen.xml deleted file mode 100644 index 12145a2..0000000 --- a/tasks/work_order_item_edit_screen.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - WO-ITEMEDIT-FIX - [ARCHITECT -> DEV] Исправление выбора локации и меток на экране ItemEdit - В текущей реализации на экране редактирования/создания элемента (ItemEditScreen) поля "Location" и "Labels" неактивны. Необходимо реализовать функционал выбора значения для этих полей из списка доступных. - architect-agent - developer-agent - pending - - - - - Загрузка списков локаций и меток. -
- 1. Внедрите `GetAllLocationsUseCase` и `GetAllLabelsUseCase` в `ItemEditViewModel`. - 2. Обновите `ItemEditUiState`, добавив два новых поля: `val allLocations: List = emptyList()` и `val allLabels: List
-
- - - Реализация UI для выбора локации. -
- 1. Замените `OutlinedTextField` для локации на `ExposedDropdownMenuBox`. - 2. В качестве `dropdownMenu` используйте `DropdownMenuItem` для каждого элемента из `uiState.allLocations`. - 3. При выборе элемента из списка вызывайте `viewModel.updateLocation(selectedLocation)`. - 4. В `ExposedDropdownMenuBox` должно отображаться `item.location?.name`. -
-
- - - Реализация UI для выбора меток (множественный выбор). -
- 1. Поле для меток `Labels` должно оставаться `OutlinedTextField` (read-only), но `onClick` по нему должен открывать диалоговое окно (`AlertDialog`). - 2. В `AlertDialog` отобразите список всех меток (`uiState.allLabels`) с `Checkbox`'ами. - 3. Состояние `Checkbox`'ов должно соответствовать списку `item.labels`. - 4. При нажатии на "OK" в диалоге, вызывайте `viewModel.updateLabels(selectedLabels)`. -
-
-
- - - При нажатии на поле "Location" открывается выпадающий список со всеми локациями. - Выбранная локация отображается в поле и сохраняется вместе с элементом. - При нажатии на поле "Labels" открывается диалоговое окно со списком всех меток и чекбоксами. - Выбранные метки отображаются в поле и сохраняются вместе с элементом. - - -
\ No newline at end of file diff --git a/tasks/work_order_login_screen.xml b/tasks/work_order_login_screen.xml deleted file mode 100644 index c43e4c1..0000000 --- a/tasks/work_order_login_screen.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - WO-LOGIN-REFACTOR - [ARCHITECT -> DEV] Рефакторинг экрана входа и логики первого запуска - Цель этой задачи - изменить логику запуска приложения. Экран входа (SetupScreen) должен появляться только при первом запуске, когда учетные данные еще не сохранены. В последующие запуски пользователь должен сразу попадать на главный экран (Dashboard). Также необходимо улучшить визуальное оформление экрана входа. - architect-agent - developer-agent - pending - - - - - Добавить public-метод для синхронной проверки наличия учетных данных. -
- Добавьте в класс `SetupViewModel` новый метод `fun areCredentialsSaved(): Boolean`. - Этот метод должен синхронно проверять, сохранены ли учетные данные в `CredentialsRepository`. - Текущая реализация `getCredentials()` асинхронна, что не подходит для быстрой проверки в `NavGraph`. - Вам может потребоваться изменить `CredentialsRepository` для поддержки синхронной проверки (например, используя `SharedPreferences` напрямую). -
-
- - - Создать новый `SplashScreen`. -
- Создайте новый Composable-экран `SplashScreen.kt`. - Этот экран будет новой точкой входа в `NavGraph`. - Он будет использовать `SetupViewModel` для вызова `areCredentialsSaved()` и, в зависимости от результата, немедленно навигироваться либо на `Screen.Setup`, либо на `Screen.Dashboard`. - Пока идет проверка, на экране должен отображаться `CircularProgressIndicator`. -
-
- - - Обновить `NavGraph` для использования `SplashScreen`. -
- Измените `startDestination` в `NavHost` на `Screen.Splash.route`. - Добавьте `composable` для `SplashScreen`. - В `SplashScreen` вызовите `navController.navigate` с очисткой бэкстека (`popUpTo(Screen.Splash.route) { inclusive = true }`), чтобы пользователь не мог вернуться на сплэш-экран. -
-
- - - Улучшить UI экрана `SetupScreen`. -
- Текущий UI слишком прост. Добавьте заголовок, иконку приложения, и более приятное расположение элементов. - Используйте `Card` для группировки полей ввода. Добавьте `Spacer` для лучшего отступа. - Кнопку "Connect" сделайте более заметной. -
-
- -
- - - При первом запуске приложения открывается `SetupScreen`. - После успешного ввода данных и входа, при последующих перезапусках приложения открывается `DashboardScreen`, минуя `SetupScreen`. - `SetupScreen` имеет улучшенный и более привлекательный дизайн. - - -
\ No newline at end of file