лаба 4 (что-то не так с навигацией)
This commit is contained in:
@@ -51,6 +51,10 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.datastore:datastore-preferences:1.0.0")
|
||||
implementation("io.github.vanpra.compose-material-dialogs:datetime:0.8.1-rc")
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.6")
|
||||
|
||||
implementation("com.jakewharton.threetenabp:threetenabp:1.2.1")
|
||||
implementation("androidx.paging:paging-compose:3.2.1")
|
||||
val room_version = "2.6.1"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:name=".GenshinApplication"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
application.deleteDatabase("genshin_db")
|
||||
setContent {
|
||||
Android_GenshinTheme {
|
||||
// A surface container using the 'background' color from the theme
|
||||
|
||||
@@ -16,7 +16,10 @@ enum class Screen(
|
||||
) {
|
||||
CharacterList("character_list", R.string.character_main_title, Icons.Filled.List),
|
||||
About("about", R.string.about_title, Icons.Filled.Info),
|
||||
CharacterView("character-view/{id}", R.string.character_view_title, showInBottomBar = false),
|
||||
CharacterView("character_view/{id}", R.string.character_view_title, showInBottomBar = false),
|
||||
CharacterEdit("character_edit/{id}", R.string.character_view_title, showInBottomBar = false),
|
||||
RarityEdit("rarity_edit/{id}", R.string.rarity_view_title, showInBottomBar = false),
|
||||
WeaponEdit("weapon_edit/{id}", R.string.weapon_view_title, showInBottomBar = false),
|
||||
RarityList("rarity_list", R.string.rarity_main_title, Icons.Filled.List),
|
||||
VisionList("vision_list", R.string.vision_main_title, Icons.Filled.List),
|
||||
WeaponList("weapon_list", R.string.weapon_main_title, Icons.Filled.List),
|
||||
|
||||
@@ -83,9 +83,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
visionDao.insert(vision3)
|
||||
// Weapons
|
||||
val weaponDao = database.weaponDao()
|
||||
val weapon1 = Weapon(1, "Weapon 1", "Spear", 545)
|
||||
val weapon2 = Weapon(2, "Weapon 2", "Sword", 455)
|
||||
val weapon3 = Weapon(3, "Weapon 3", "Claymore", 582)
|
||||
val weapon1 = Weapon(1, "Weapon 1", "Spear", 545, createColoredImage(Color.CYAN))
|
||||
val weapon2 = Weapon(2, "Weapon 2", "Sword", 455, createColoredImage(Color.YELLOW))
|
||||
val weapon3 = Weapon(3, "Weapon 3", "Claymore", 582, createColoredImage(Color.RED))
|
||||
weaponDao.insert(weapon1)
|
||||
weaponDao.insert(weapon2)
|
||||
weaponDao.insert(weapon3)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.createSavedStateHandle
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
@@ -12,28 +13,34 @@ object AppViewModelProvider {
|
||||
RarityListViewModel(genshinApplication().container.rarityRepository)
|
||||
}
|
||||
initializer {
|
||||
RarityEditViewModel()
|
||||
}
|
||||
initializer {
|
||||
RarityViewModel()
|
||||
RarityEditViewModel(this.createSavedStateHandle(),
|
||||
genshinApplication().container.rarityRepository)
|
||||
}
|
||||
//initializer {
|
||||
// RarityViewModel(this.createSavedStateHandle(),
|
||||
// genshinApplication().container.rarityRepository)
|
||||
//}
|
||||
initializer {
|
||||
VisionListViewModel(genshinApplication().container.visionRepository)
|
||||
}
|
||||
initializer {
|
||||
VisionEditViewModel()
|
||||
}
|
||||
initializer {
|
||||
VisionViewModel()
|
||||
}
|
||||
//initializer {
|
||||
// VisionEditViewModel(this.createSavedStateHandle(),
|
||||
// genshinApplication().container.visionRepository)
|
||||
//}
|
||||
//initializer {
|
||||
// VisionViewModel(this.createSavedStateHandle(),
|
||||
// genshinApplication().container.visionRepository)
|
||||
//}
|
||||
initializer {
|
||||
WeaponListViewModel(genshinApplication().container.weaponRepository)
|
||||
}
|
||||
initializer {
|
||||
WeaponEditViewModel()
|
||||
WeaponEditViewModel(this.createSavedStateHandle(),
|
||||
genshinApplication().container.weaponRepository)
|
||||
}
|
||||
initializer {
|
||||
WeaponViewModel()
|
||||
WeaponViewModel(this.createSavedStateHandle(),
|
||||
genshinApplication().container.weaponRepository)
|
||||
}
|
||||
initializer {
|
||||
CharacterListViewModel(
|
||||
@@ -45,8 +52,11 @@ object AppViewModelProvider {
|
||||
)
|
||||
}
|
||||
initializer {
|
||||
CharacterViewModel(
|
||||
genshinApplication().container.characterRepository
|
||||
CharacterViewModel( this.createSavedStateHandle(),
|
||||
genshinApplication().container.characterRepository,
|
||||
genshinApplication().container.characterRarityRepository,
|
||||
genshinApplication().container.characterVisionRepository,
|
||||
genshinApplication().container.characterWeaponRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,273 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
class CharacterEdit {
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||
import androidx.compose.material3.ExposedDropdownMenuDefaults.TrailingIcon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.android_genshin.R
|
||||
import com.example.android_genshin.database.entities.model.Rarity
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import com.example.android_genshin.database.entities.model.Weapon
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun CharacterEdit(
|
||||
navController: NavController,
|
||||
viewModel: CharacterEditViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
rarityViewModel: RarityDropDownViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
visionViewModel: VisionDropDownViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
weaponViewModel: WeaponDropDownViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
CharacterEdit(
|
||||
characterUiState = viewModel.characterUiState,
|
||||
rarityUiState = rarityViewModel.rarityUiState,
|
||||
visionUiState = visionViewModel.visionUiState,
|
||||
weaponUiState = weaponViewModel.weaponUiState,
|
||||
raritiesListUiState = rarityViewModel.raritiesListUiState,
|
||||
visionsListUiState = visionViewModel.visionsListUiState,
|
||||
weaponsListUiState = weaponViewModel.weaponsListUiState,
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
viewModel.saveCharacter()
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
onUpdate = viewModel::updateUiState,
|
||||
onRarityUpdate = viewModel::updateUiStateRarity,
|
||||
onVisionUpdate = viewModel::updateUiStateVision,
|
||||
onWeaponUpdate = viewModel::updateUiStateWeapon
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun RarityDropDown(
|
||||
rarityUiState: RarityUiState,
|
||||
raritiesListUiState: RaritiesListUiState,
|
||||
onRarityUpdate: (Rarity) -> Unit
|
||||
) {
|
||||
var expanded: Boolean by remember { mutableStateOf(false) }
|
||||
ExposedDropdownMenuBox(
|
||||
modifier = Modifier
|
||||
.padding(top = 7.dp),
|
||||
expanded = expanded,
|
||||
onExpandedChange = {
|
||||
expanded = !expanded
|
||||
}
|
||||
) {
|
||||
TextField(
|
||||
value = rarityUiState.rarity?.rarityName
|
||||
?: stringResource(id = R.string.character_rarity_not_select),
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
TrailingIcon(expanded = expanded)
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor()
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
modifier = Modifier
|
||||
.background(Color.White)
|
||||
.exposedDropdownSize()
|
||||
) {
|
||||
raritiesListUiState.rarityList.forEach { rarity ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(text = rarity.rarityName)
|
||||
},
|
||||
onClick = {
|
||||
onRarityUpdate(rarity)
|
||||
expanded = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun VisionDropDown(
|
||||
visionUiState: VisionUiState,
|
||||
visionsListUiState: VisionsListUiState,
|
||||
onVisionUpdate: (Vision) -> Unit
|
||||
) {
|
||||
var expanded: Boolean by remember { mutableStateOf(false) }
|
||||
ExposedDropdownMenuBox(
|
||||
modifier = Modifier
|
||||
.padding(top = 7.dp),
|
||||
expanded = expanded,
|
||||
onExpandedChange = {
|
||||
expanded = !expanded
|
||||
}
|
||||
) {
|
||||
TextField(
|
||||
value = visionUiState.vision?.visionName
|
||||
?: stringResource(id = R.string.character_vision_not_select),
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
TrailingIcon(expanded = expanded)
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor()
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
modifier = Modifier
|
||||
.background(Color.White)
|
||||
.exposedDropdownSize()
|
||||
) {
|
||||
visionsListUiState.visionList.forEach { vision ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(text = vision.visionName)
|
||||
},
|
||||
onClick = {
|
||||
onVisionUpdate(vision)
|
||||
expanded = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun WeaponDropDown(
|
||||
weaponUiState: WeaponUiState,
|
||||
weaponsListUiState: WeaponsListUiState,
|
||||
onWeaponUpdate: (Weapon) -> Unit
|
||||
) {
|
||||
var expanded: Boolean by remember { mutableStateOf(false) }
|
||||
ExposedDropdownMenuBox(
|
||||
modifier = Modifier
|
||||
.padding(top = 7.dp),
|
||||
expanded = expanded,
|
||||
onExpandedChange = {
|
||||
expanded = !expanded
|
||||
}
|
||||
) {
|
||||
TextField(
|
||||
value = weaponUiState.weapon?.weaponName
|
||||
?: stringResource(id = R.string.character_weapon_not_select),
|
||||
onValueChange = {},
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
TrailingIcon(expanded = expanded)
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.menuAnchor()
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
modifier = Modifier
|
||||
.background(Color.White)
|
||||
.exposedDropdownSize()
|
||||
) {
|
||||
weaponsListUiState.weaponList.forEach { weapon ->
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Text(text = weapon.weaponName)
|
||||
},
|
||||
onClick = {
|
||||
onWeaponUpdate(weapon)
|
||||
expanded = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun CharacterEdit(
|
||||
characterUiState: CharacterUiStateEdit,
|
||||
rarityUiState: RarityUiState,
|
||||
raritiesListUiState: RaritiesListUiState,
|
||||
visionUiState: VisionUiState,
|
||||
visionsListUiState: VisionsListUiState,
|
||||
weaponUiState: WeaponUiState,
|
||||
weaponsListUiState: WeaponsListUiState,
|
||||
onClick: () -> Unit,
|
||||
onUpdate: (CharacterDetails) -> Unit,
|
||||
onRarityUpdate: (CharacterRarityDetails) -> Unit,
|
||||
onVisionUpdate: (CharacterVisionDetails) -> Unit,
|
||||
onWeaponUpdate: (CharacterWeaponDetails) -> Unit
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 10.dp)
|
||||
) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = characterUiState.characterDetails.characterName,
|
||||
onValueChange = { onUpdate(characterUiState.characterDetails.copy(characterName = it)) },
|
||||
label = { Text(stringResource(id = R.string.character_characterName)) },
|
||||
singleLine = true
|
||||
)
|
||||
RarityDropDown(
|
||||
rarityUiState = rarityUiState,
|
||||
raritiesListUiState = raritiesListUiState,
|
||||
onRarityUpdate = {
|
||||
onRarityUpdate(characterUiState.characterRarityDetails.copy(rarityId = it.rarityId))
|
||||
}
|
||||
)
|
||||
VisionDropDown(
|
||||
visionUiState = visionUiState,
|
||||
visionsListUiState = visionsListUiState,
|
||||
onVisionUpdate = {
|
||||
onVisionUpdate(characterUiState.characterVisionDetails.copy(visionId = it.visionId))
|
||||
}
|
||||
)
|
||||
WeaponDropDown(
|
||||
weaponUiState = weaponUiState,
|
||||
weaponsListUiState = weaponsListUiState,
|
||||
onWeaponUpdate = {
|
||||
onWeaponUpdate(characterUiState.characterWeaponDetails.copy(weaponId = it.weaponId))
|
||||
}
|
||||
)
|
||||
Button(
|
||||
onClick = onClick,
|
||||
enabled = characterUiState.isEntryValid,
|
||||
shape = MaterialTheme.shapes.small,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = stringResource(R.string.character_save_button))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,15 +10,10 @@ import com.example.android_genshin.database.entities.model.Character
|
||||
import com.example.android_genshin.database.entities.model.CharacterRarityCrossRef
|
||||
import com.example.android_genshin.database.entities.model.CharacterVisionCrossRef
|
||||
import com.example.android_genshin.database.entities.model.CharacterWeaponCrossRef
|
||||
import com.example.android_genshin.database.entities.model.CharacterWithRarities
|
||||
import com.example.android_genshin.database.entities.model.Rarity
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import com.example.android_genshin.database.entities.model.Weapon
|
||||
import com.example.android_genshin.database.entities.repository.CharacterRarityRepository
|
||||
import com.example.android_genshin.database.entities.repository.CharacterRepository
|
||||
import com.example.android_genshin.database.entities.repository.CharacterVisionRepository
|
||||
import com.example.android_genshin.database.entities.repository.CharacterWeaponRepository
|
||||
import com.example.android_genshin.database.entities.repository.UserRepository
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -29,24 +24,15 @@ class CharacterEditViewModel(
|
||||
private val characterRarityRepository: CharacterRarityRepository,
|
||||
private val characterVisionRepository: CharacterVisionRepository,
|
||||
private val characterWeaponRepository: CharacterWeaponRepository,
|
||||
|
||||
) : ViewModel() {
|
||||
var characterUiState by mutableStateOf(CharacterUiStateEdit())
|
||||
private set
|
||||
var characterRarityUiState by mutableStateOf(CharacterRarityUiState())
|
||||
private set
|
||||
|
||||
var characterVisionUiState by mutableStateOf(CharacterVisionUiState())
|
||||
private set
|
||||
var characterWeaponUiState by mutableStateOf(CharacterWeaponUiState())
|
||||
private set
|
||||
|
||||
private val characterUid: Int = checkNotNull(savedStateHandle["characterId"])
|
||||
private val characterUid: Int = checkNotNull(savedStateHandle["id"])
|
||||
private val rarityUid: Int = checkNotNull(savedStateHandle["rarityId"])
|
||||
private val visionUid: Int = checkNotNull(savedStateHandle["visionId"])
|
||||
private val weaponUid: Int = checkNotNull(savedStateHandle["weaponId"])
|
||||
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
if(characterUid > 0){
|
||||
@@ -54,18 +40,6 @@ class CharacterEditViewModel(
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.toUiState(true)
|
||||
characterRarityUiState = characterRarityRepository.getRaritiesFromCharacter(characterUid)
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.toUiState()
|
||||
characterVisionUiState = characterVisionRepository.getVisionsFromCharacter(characterUid)
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.toUiState()
|
||||
characterWeaponUiState = characterWeaponRepository.getWeaponsFromCharacter(characterUid)
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.toUiState()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,24 +51,48 @@ class CharacterEditViewModel(
|
||||
)
|
||||
}
|
||||
|
||||
fun updateUiStateRarity(characterRarityDetails: CharacterRarityDetails) {
|
||||
characterUiState = CharacterUiStateEdit(
|
||||
characterRarityDetails = characterRarityDetails
|
||||
)
|
||||
}
|
||||
|
||||
fun updateUiStateVision(characterVisionDetails: CharacterVisionDetails) {
|
||||
characterUiState = CharacterUiStateEdit(
|
||||
characterVisionDetails = characterVisionDetails
|
||||
)
|
||||
}
|
||||
|
||||
fun updateUiStateWeapon(characterWeaponDetails: CharacterWeaponDetails) {
|
||||
characterUiState = CharacterUiStateEdit(
|
||||
characterWeaponDetails = characterWeaponDetails
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun saveCharacter() {
|
||||
if (validateInput()) {
|
||||
if (rarityUid > 0) {
|
||||
if (characterUid > 0) {
|
||||
characterRarityRepository.updateCharacterRarity(CharacterRarityUiState.characterRarityDetails.toCharacterRarity(characterUid, rarityUid))
|
||||
characterRepository.updateCharacter(CharacterUiStateEdit..toCharacter(characterUid))
|
||||
if(characterUid > 0) {
|
||||
characterRepository.updateCharacter(characterUiState.characterDetails.toCharacter(characterUid))
|
||||
if (rarityUid > 0) {
|
||||
characterRarityRepository.updateCharacterRarity(characterUiState.characterRarityDetails.toCharacterRarity(characterUid, rarityUid ))
|
||||
}
|
||||
}
|
||||
if (visionUid > 0) {
|
||||
characterVisionRepository.updateCharacterVision(CharacterVisionUiState.characterVisionDetails.toCharacterVision(characterUid))
|
||||
characterRepository.updateCharacter(CharacterUiStateEdit.characterDetails.toCharacter(characterUid))
|
||||
}
|
||||
if (weaponUid > 0) {
|
||||
characterWeaponRepository.updateCharacterWeapon(CharacterUiStateEdit.characterDetails.toCharacter(characterUid))
|
||||
characterRepository.updateCharacter(CharacterUiStateEdit.characterDetails.toCharacter(characterUid))
|
||||
}
|
||||
if (rarityUid < 0 && visionUid < 0 && weaponUid < 0) {
|
||||
characterRepository.insertCharacter(CharacterUiStateEdit.characterDetails.toCharacter(characterUid))
|
||||
else {
|
||||
characterRarityRepository.insertCharacterRarity(characterUiState.characterRarityDetails.toCharacterRarity(characterUid, rarityUid))
|
||||
}
|
||||
if (visionUid > 0) {
|
||||
characterVisionRepository.updateCharacterVision(characterUiState.characterVisionDetails.toCharacterVision(characterUid, visionUid))
|
||||
}
|
||||
else {
|
||||
characterVisionRepository.insertCharacterVision(characterUiState.characterVisionDetails.toCharacterVision(characterUid, visionUid))
|
||||
}
|
||||
if (weaponUid > 0) {
|
||||
characterWeaponRepository.updateCharacterWeapon(characterUiState.characterWeaponDetails.toCharacterWeapon(characterUid, weaponUid))
|
||||
}
|
||||
else {
|
||||
characterWeaponRepository.insertCharacterWeapon(characterUiState.characterWeaponDetails.toCharacterWeapon(characterUid, weaponUid))
|
||||
}
|
||||
} else {
|
||||
characterRepository.insertCharacter(characterUiState.characterDetails.toCharacter())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,12 +106,36 @@ class CharacterEditViewModel(
|
||||
|
||||
data class CharacterUiStateEdit(
|
||||
val characterDetails: CharacterDetails = CharacterDetails(),
|
||||
val characterRarityDetails: CharacterRarityDetails = CharacterRarityDetails(),
|
||||
val characterVisionDetails: CharacterVisionDetails = CharacterVisionDetails(),
|
||||
val characterWeaponDetails: CharacterWeaponDetails = CharacterWeaponDetails(),
|
||||
val isEntryValid: Boolean = false
|
||||
)
|
||||
|
||||
data class CharacterDetails(
|
||||
val characterId: Int = 0,
|
||||
val characterName: String = ""
|
||||
val characterName: String = "",
|
||||
val image: ByteArray? = null,
|
||||
val userUid: Int? = 0
|
||||
)
|
||||
|
||||
fun CharacterDetails.toCharacter(uid: Int = 0): Character = Character(
|
||||
characterId = uid,
|
||||
characterName = characterName,
|
||||
userId = userUid,
|
||||
image = image
|
||||
)
|
||||
|
||||
fun Character.toDetails(): CharacterDetails = CharacterDetails(
|
||||
characterId = characterId,
|
||||
characterName = characterName,
|
||||
image = image,
|
||||
userUid = userId
|
||||
)
|
||||
|
||||
fun Character.toUiState(isEntryValid: Boolean = false): CharacterUiStateEdit = CharacterUiStateEdit(
|
||||
characterDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
data class CharacterRarityDetails(
|
||||
@@ -121,31 +143,61 @@ data class CharacterRarityDetails(
|
||||
val rarityId: Int = 0
|
||||
)
|
||||
|
||||
data class CharacterVisionDetails(
|
||||
val characterId: Int = 0,
|
||||
val visionId: Int = 0
|
||||
)
|
||||
|
||||
data class CharacterWeaponDetails(
|
||||
val characterId: Int = 0,
|
||||
val weaponId: Int = 0
|
||||
)
|
||||
|
||||
fun CharacterRarityDetails.toCharacterRarity(characterId: Int = 0, rarityId: Int = 0): CharacterRarityCrossRef = CharacterRarityCrossRef(
|
||||
characterId = characterId,
|
||||
rarityId = rarityId
|
||||
)
|
||||
|
||||
fun CharacterRarityCrossRef.toDetails(): CharacterRarityDetails = CharacterRarityDetails(
|
||||
characterId = characterId,
|
||||
rarityId = rarityId
|
||||
)
|
||||
|
||||
fun CharacterRarityCrossRef.toUiState(isEntryValid: Boolean = false): CharacterUiStateEdit = CharacterUiStateEdit(
|
||||
characterRarityDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
data class CharacterVisionDetails(
|
||||
val characterId: Int = 0,
|
||||
val visionId: Int = 0
|
||||
)
|
||||
|
||||
fun CharacterVisionDetails.toCharacterVision(characterId: Int = 0, visionId: Int = 0): CharacterVisionCrossRef = CharacterVisionCrossRef(
|
||||
characterId = characterId,
|
||||
visionId = visionId
|
||||
)
|
||||
|
||||
fun CharacterVisionCrossRef.toDetails(): CharacterVisionDetails = CharacterVisionDetails(
|
||||
characterId = characterId,
|
||||
visionId = visionId
|
||||
)
|
||||
|
||||
fun CharacterVisionCrossRef.toUiState(isEntryValid: Boolean = false): CharacterUiStateEdit = CharacterUiStateEdit(
|
||||
characterVisionDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
data class CharacterWeaponDetails(
|
||||
val characterId: Int = 0,
|
||||
val weaponId: Int = 0
|
||||
)
|
||||
|
||||
fun CharacterWeaponDetails.toCharacterWeapon(characterId: Int = 0, weaponId: Int = 0): CharacterWeaponCrossRef = CharacterWeaponCrossRef(
|
||||
characterId = characterId,
|
||||
weaponId = weaponId
|
||||
)
|
||||
|
||||
fun CharacterWeaponCrossRef.toDetails(): CharacterWeaponDetails = CharacterWeaponDetails(
|
||||
characterId = characterId,
|
||||
weaponId = weaponId
|
||||
)
|
||||
|
||||
fun CharacterWeaponCrossRef.toUiState(isEntryValid: Boolean = false): CharacterUiStateEdit = CharacterUiStateEdit(
|
||||
characterWeaponDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
data class CharacterRarityUiState(
|
||||
val characterRarityDetails: CharacterRarityDetails = CharacterRarityDetails(),
|
||||
val isEntryValid: Boolean = false
|
||||
@@ -161,41 +213,11 @@ data class CharacterWeaponUiState(
|
||||
val isEntryValid: Boolean = false
|
||||
)
|
||||
|
||||
fun CharacterRarityCrossRef.toDetails(): CharacterRarityDetails = CharacterRarityDetails(
|
||||
characterId = characterId,
|
||||
rarityId = rarityId
|
||||
)
|
||||
//fun List<Rarity>.toDetails(): CharacterRarityDetails = CharacterRarityDetails(
|
||||
// rarityId = rarityId
|
||||
//)
|
||||
|
||||
fun CharacterRarityCrossRef.toUiState(isEntryValid: Boolean = false): CharacterRarityUiState = CharacterRarityUiState(
|
||||
characterRarityDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
fun CharacterVisionCrossRef.toDetails(): CharacterVisionDetails = CharacterVisionDetails(
|
||||
characterId = characterId,
|
||||
visionId = visionId
|
||||
)
|
||||
|
||||
fun CharacterVisionCrossRef.toUiState(isEntryValid: Boolean = false): CharacterVisionUiState = CharacterVisionUiState(
|
||||
characterVisionDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
fun CharacterWeaponCrossRef.toDetails(): CharacterWeaponDetails = CharacterWeaponDetails(
|
||||
characterId = characterId,
|
||||
weaponId = weaponId
|
||||
)
|
||||
|
||||
fun CharacterWeaponCrossRef.toUiState(isEntryValid: Boolean = false): CharacterWeaponUiState = CharacterWeaponUiState(
|
||||
characterWeaponDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
|
||||
fun List<Rarity>.toDetails(): CharacterRarityDetails = CharacterRarityDetails(
|
||||
rarityId = rarityId
|
||||
)
|
||||
|
||||
fun List<Rarity>.toUiState(isEntryValid: Boolean = false): CharacterRarityUiState = CharacterRarityUiState(
|
||||
characterRarityDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
//fun List<Rarity>.toUiState(isEntryValid: Boolean = false): CharacterRarityUiState = CharacterRarityUiState(
|
||||
// characterRarityDetails = this.toDetails(),
|
||||
// isEntryValid = isEntryValid
|
||||
//)
|
||||
@@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
@@ -30,16 +29,10 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
@@ -47,12 +40,9 @@ import androidx.navigation.NavController
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.example.android_genshin.composeui.navigation.Screen
|
||||
import com.example.android_genshin.database.AppDatabase
|
||||
import com.example.android_genshin.database.entities.model.Character
|
||||
import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -70,7 +60,7 @@ fun CharacterList(
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
val route = Screen.CharacterEdit.route.replace("{id}", 0.toString())
|
||||
navController.navigate(route)
|
||||
navController?.navigate(route)
|
||||
},
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
@@ -95,12 +85,12 @@ fun CharacterList(
|
||||
},
|
||||
onDeleteClick = { character: Character ->
|
||||
coroutineScope.launch {
|
||||
viewModel.removeCharacter(character.)
|
||||
viewModel.removeCharacter(character)
|
||||
}
|
||||
},
|
||||
onEditClick = { uid: Int ->
|
||||
val route = Screen.CharacterEdit.route.replace("{id}", uid.toString())
|
||||
navController.navigate(route)
|
||||
navController?.navigate(route)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.example.android_genshin.database.entities.model.Character
|
||||
import com.example.android_genshin.database.entities.model.CharacterRarityCrossRef
|
||||
import com.example.android_genshin.database.entities.model.CharacterVisionCrossRef
|
||||
import com.example.android_genshin.database.entities.model.CharacterWeaponCrossRef
|
||||
import com.example.android_genshin.database.entities.model.CharacterWithRarities
|
||||
import com.example.android_genshin.database.entities.model.CharacterWithVisions
|
||||
import com.example.android_genshin.database.entities.model.CharacterWithWeapons
|
||||
@@ -69,55 +66,15 @@ class CharacterListViewModel(
|
||||
rarities: List<Rarity>,
|
||||
visions: List<Vision>,
|
||||
weapons: List<Weapon>) {
|
||||
val byteArrayImage = ByteArray(1)
|
||||
if (rarities.isEmpty())
|
||||
return
|
||||
if (visions.isEmpty())
|
||||
return
|
||||
if (weapons.isEmpty())
|
||||
return
|
||||
val byteArrayImage = ByteArray(100)
|
||||
val character = Character(0, "", userId, byteArrayImage)
|
||||
val characterId = characterRepository.insertCharacter(character)
|
||||
rarities.forEach { rarity ->
|
||||
characterRarityRepository.insertCharacterRarity(
|
||||
CharacterRarityCrossRef(
|
||||
character.characterId,
|
||||
rarity.rarityId
|
||||
)
|
||||
)
|
||||
}
|
||||
visions.forEach { vision ->
|
||||
characterVisionRepository.insertCharacterVision(
|
||||
CharacterVisionCrossRef(
|
||||
character.characterId,
|
||||
vision.visionId
|
||||
)
|
||||
)
|
||||
}
|
||||
weapons.forEach { weapon ->
|
||||
characterWeaponRepository.insertCharacterWeapon(
|
||||
CharacterWeaponCrossRef(
|
||||
character.characterId,
|
||||
weapon.weaponId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun removeCharacter(
|
||||
character: Character) {
|
||||
characterRepository.deleteCharacter(character)
|
||||
}
|
||||
|
||||
suspend fun updateCharacter(character: Character,
|
||||
rarity: Rarity,
|
||||
vision: Vision,
|
||||
weapon: Weapon) {
|
||||
characterRepository.updateCharacter(character)
|
||||
characterRarityRepository.updateCharacterRarity(CharacterRarityCrossRef(character.characterId, rarity.rarityId))
|
||||
characterVisionRepository.updateCharacterVision(CharacterVisionCrossRef(character.characterId, vision.visionId))
|
||||
characterWeaponRepository.updateCharacterWeapon(CharacterWeaponCrossRef(character.characterId, weapon.weaponId))
|
||||
}
|
||||
}
|
||||
|
||||
data class CharacterListUiState(
|
||||
|
||||
@@ -1,4 +1,120 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
class ImageUploader {
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
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.unit.dp
|
||||
import com.example.android_genshin.R
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
@Composable
|
||||
fun ImageUploader(
|
||||
bitmap: Bitmap?,
|
||||
onResult: (ByteArray) -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val title: String = if (bitmap == null) {
|
||||
stringResource(R.string.not_uploaded)
|
||||
} else {
|
||||
stringResource(R.string.size, bitmap.width, bitmap.height)
|
||||
}
|
||||
|
||||
val launcher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.GetContent(),
|
||||
onResult = { uri: Uri? ->
|
||||
uri?.let {
|
||||
val inputStream = context.contentResolver.openInputStream(uri)
|
||||
val newBitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
val scaledBitmap = resizeBitmapWithAspectRatio(newBitmap, 200)
|
||||
val stream = ByteArrayOutputStream()
|
||||
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
|
||||
onResult(stream.toByteArray())
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
shape = RoundedCornerShape(10.dp)
|
||||
)
|
||||
.aspectRatio(1f)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
shape = RoundedCornerShape(10.dp)
|
||||
)
|
||||
.clickable { launcher.launch("image/*") }
|
||||
.padding(16.dp)
|
||||
) {
|
||||
if (bitmap != null) {
|
||||
Image(
|
||||
bitmap = bitmap.asImageBitmap(),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clip(shape = RoundedCornerShape(10.dp))
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.xiao_wbgr),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clip(shape = RoundedCornerShape(10.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = title,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun resizeBitmapWithAspectRatio(bitmap: Bitmap, maxHeight: Int): Bitmap {
|
||||
if (bitmap.height <= maxHeight) {
|
||||
return bitmap
|
||||
}
|
||||
|
||||
val aspectRatio = bitmap.width.toFloat() / bitmap.height
|
||||
val newWidth = (maxHeight * aspectRatio).toInt()
|
||||
|
||||
return Bitmap.createScaledBitmap(bitmap, newWidth, maxHeight, true)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.android_genshin.database.entities.model.Rarity
|
||||
import com.example.android_genshin.database.entities.repository.RarityRepository
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RarityDropDownViewModel(
|
||||
private val rarityRepository: RarityRepository
|
||||
) : ViewModel() {
|
||||
var raritiesListUiState by mutableStateOf(RaritiesListUiState())
|
||||
private set
|
||||
|
||||
var rarityUiState by mutableStateOf(RarityUiState())
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
raritiesListUiState = RaritiesListUiState(rarityRepository.getAllRarities())
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUiState(rarity: Rarity) {
|
||||
rarityUiState = RarityUiState(
|
||||
rarity = rarity
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class RaritiesListUiState(val rarityList: List<Rarity> = listOf())
|
||||
|
||||
data class RarityUiState(val rarity: Rarity? = null)
|
||||
|
||||
fun Rarity.toUiState() = RarityUiState(rarity = Rarity(rarityId = rarityId, rarityName = rarityName))
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.android_genshin.R
|
||||
import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun RarityEdit(
|
||||
navController: NavController,
|
||||
viewModel: RarityEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
RarityEdit(
|
||||
rarityUiState = viewModel.rarityUiState,
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
viewModel.saveRarity()
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
onUpdate = viewModel::updateUiState
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun RarityEdit(
|
||||
rarityUiState: RarityUiStateEdit,
|
||||
onClick: () -> Unit,
|
||||
onUpdate: (RarityDetails) -> Unit
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 10.dp)
|
||||
) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = rarityUiState.rarityDetails.rarityName,
|
||||
onValueChange = { onUpdate(rarityUiState.rarityDetails.copy(rarityName = it)) },
|
||||
label = { Text(stringResource(id = R.string.rarity_rarityName)) },
|
||||
singleLine = true
|
||||
)
|
||||
Button(
|
||||
onClick = onClick,
|
||||
enabled = rarityUiState.isEntryValid,
|
||||
shape = MaterialTheme.shapes.small,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = stringResource(R.string.character_save_button))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
fun RarityEditPreview() {
|
||||
Android_GenshinTheme {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
RarityEdit(
|
||||
rarityUiState = RarityUiStateEdit(),
|
||||
onClick = {},
|
||||
onUpdate = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.android_genshin.database.entities.model.Rarity
|
||||
import com.example.android_genshin.database.entities.repository.RarityRepository
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RarityEditViewModel(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val rarityRepository: RarityRepository
|
||||
) : ViewModel() {
|
||||
var rarityUiState by mutableStateOf(RarityUiStateEdit())
|
||||
|
||||
private val rarityUid : Int = checkNotNull(savedStateHandle["id"])
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
if(rarityUid > 0) {
|
||||
rarityUiState = rarityRepository.getRarity(rarityUid)
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.toUiState(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUiState(rarityDetails : RarityDetails) {
|
||||
rarityUiState = RarityUiStateEdit(
|
||||
rarityDetails = rarityDetails,
|
||||
isEntryValid = validateInput(rarityDetails)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun saveRarity() {
|
||||
if (validateInput()) {
|
||||
if (rarityUid > 0) {
|
||||
rarityRepository.updateRarity(rarityUiState.rarityDetails.toRarity(rarityUid))
|
||||
} else {
|
||||
rarityRepository.insertRarity(rarityUiState.rarityDetails.toRarity())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateInput(uiState: RarityDetails = rarityUiState.rarityDetails): Boolean {
|
||||
return with(uiState) {
|
||||
rarityName.isNotBlank()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class RarityUiStateEdit(
|
||||
val rarityDetails: RarityDetails = RarityDetails(),
|
||||
val isEntryValid: Boolean = false
|
||||
)
|
||||
|
||||
data class RarityDetails(
|
||||
val rarityId: Int = 0,
|
||||
val rarityName: String = ""
|
||||
)
|
||||
|
||||
fun RarityDetails.toRarity(uid: Int = 0): Rarity = Rarity(
|
||||
rarityId = uid,
|
||||
rarityName = rarityName
|
||||
)
|
||||
|
||||
fun Rarity.toDetails(): RarityDetails = RarityDetails(
|
||||
rarityId = rarityId,
|
||||
rarityName = rarityName
|
||||
)
|
||||
|
||||
fun Rarity.toUiState(isEntryValid: Boolean = false): RarityUiStateEdit = RarityUiStateEdit(
|
||||
rarityDetails = this.toDetails(),
|
||||
isEntryValid = isEntryValid
|
||||
)
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -13,49 +11,34 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.example.android_genshin.composeui.navigation.Screen
|
||||
import com.example.android_genshin.database.AppDatabase
|
||||
import com.example.android_genshin.database.entities.model.CharacterWithRarities
|
||||
import com.example.android_genshin.database.entities.model.Rarity
|
||||
import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RarityList(
|
||||
characterWithRarities: CharacterWithRarities,
|
||||
navController: NavController,
|
||||
viewModel: RarityListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
@@ -98,11 +81,7 @@ fun RarityList(
|
||||
coroutineScope.launch {
|
||||
viewModel.deleteRarity(rarity)
|
||||
}
|
||||
},
|
||||
onEditClick = { uid: Int ->
|
||||
val route = Screen.RarityEdit.route.replace("{id}", uid.toString())
|
||||
navController.navigate(route)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -111,8 +90,7 @@ fun RarityList(
|
||||
private fun RarityList(
|
||||
modifier: Modifier = Modifier,
|
||||
pagingRarity: LazyPagingItems<Rarity>,
|
||||
onDeleteClick: (rarity: Rarity) -> Unit,
|
||||
onEditClick: (rarity: Int) -> Unit
|
||||
onDeleteClick: (rarity: Rarity) -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
@@ -133,8 +111,7 @@ private fun RarityList(
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
),
|
||||
onDeleteClick = onDeleteClick,
|
||||
onEditClick = onEditClick,
|
||||
onDeleteClick = onDeleteClick
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -146,8 +123,7 @@ private fun RarityList(
|
||||
private fun RarityListItem(
|
||||
rarity: Rarity,
|
||||
modifier: Modifier = Modifier,
|
||||
onDeleteClick: (rarity: Rarity) -> Unit,
|
||||
onEditClick: (rarity: Int) -> Unit
|
||||
onDeleteClick: (rarity: Rarity) -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
@@ -166,16 +142,6 @@ private fun RarityListItem(
|
||||
|
||||
// Добавляем пустое пространство для разделения текста и кнопки
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(
|
||||
onClick = { onEditClick(rarity.rarityId) },
|
||||
modifier = Modifier.size(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
contentDescription = "Редактировать",
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
onClick = { onDeleteClick(rarity) },
|
||||
modifier = Modifier.size(24.dp)
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -16,25 +13,25 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.android_genshin.R
|
||||
import com.example.android_genshin.database.AppDatabase
|
||||
import com.example.android_genshin.database.entities.model.Rarity
|
||||
import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RarityView(id: Int) {
|
||||
fun RarityView(navController: NavController,
|
||||
viewModel: RarityEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val rarity = remember {
|
||||
mutableStateOf(Rarity(0, ""))
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
rarity.value = AppDatabase.getInstance(context).rarityDao().getByUid(id)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
@@ -49,17 +46,4 @@ fun RarityView(id: Int) {
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
fun RarityViewPreview() {
|
||||
Android_GenshinTheme {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
RarityView(id = 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import com.example.android_genshin.database.entities.repository.VisionRepository
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class VisionDropDownViewModel(
|
||||
private val visionRepository: VisionRepository
|
||||
) : ViewModel() {
|
||||
var visionsListUiState by mutableStateOf(VisionsListUiState())
|
||||
private set
|
||||
|
||||
var visionUiState by mutableStateOf(VisionUiState())
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
visionsListUiState = VisionsListUiState(visionRepository.getAllVisions())
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUiState(vision: Vision) {
|
||||
visionUiState = VisionUiState(
|
||||
vision = vision
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class VisionsListUiState(val visionList: List<Vision> = listOf())
|
||||
|
||||
data class VisionUiState(val vision: Vision? = null)
|
||||
|
||||
fun Vision.toUiState() = VisionUiState(vision = Vision(visionId = visionId, visionName = visionName))
|
||||
@@ -1,78 +1,156 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.android_genshin.database.AppDatabase
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.example.android_genshin.composeui.navigation.Screen
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun VisionList(navController: NavController?) {
|
||||
val context = LocalContext.current
|
||||
val visions = remember { mutableStateListOf<Vision>() }
|
||||
LaunchedEffect(Unit) {
|
||||
withContext(Dispatchers.IO) {
|
||||
AppDatabase.getInstance(context).visionDao().getAll().collect { data ->
|
||||
visions.clear()
|
||||
visions.addAll(data)
|
||||
}
|
||||
fun VisionList(navController: NavController,
|
||||
viewModel: VisionListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val visionPagingItems = viewModel.visionPagerState.visionPagingData.collectAsLazyPagingItems()
|
||||
|
||||
fun findVisions() {
|
||||
coroutineScope.launch {
|
||||
viewModel.findVisions()
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 10.dp)
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
LaunchedEffect(1) {
|
||||
findVisions()
|
||||
}
|
||||
Scaffold(
|
||||
topBar = {},
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
val route = Screen.RarityEdit.route.replace("{id}", 0.toString())
|
||||
navController.navigate(route)
|
||||
},
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
Icons.Filled.Add,
|
||||
"Добавить",
|
||||
tint = MaterialTheme.colorScheme.onPrimary
|
||||
)
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
VisionList(
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
pagingVision = visionPagingItems,
|
||||
onDeleteClick = { vision: Vision ->
|
||||
coroutineScope.launch {
|
||||
viewModel.deleteVision(vision)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun VisionList(
|
||||
modifier: Modifier = Modifier,
|
||||
pagingVision: LazyPagingItems<Vision>,
|
||||
onDeleteClick: (vision: Vision) -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(all = 10.dp)
|
||||
) {
|
||||
items(visions) { vision ->
|
||||
Text(
|
||||
text = "${vision.visionId}: ${vision.visionName}",
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
items(pagingVision.itemCount) { index ->
|
||||
val vision = pagingVision[index]
|
||||
if (vision != null) {
|
||||
VisionListItem(
|
||||
vision = vision,
|
||||
modifier = Modifier
|
||||
.padding(vertical = 7.dp)
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
),
|
||||
onDeleteClick = onDeleteClick
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
fun VisionListPreview() {
|
||||
Android_GenshinTheme {
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.background
|
||||
private fun VisionListItem(
|
||||
vision: Vision,
|
||||
modifier: Modifier = Modifier,
|
||||
onDeleteClick: (vision: Vision) -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
VisionList(navController = null)
|
||||
Text(
|
||||
"${vision.visionName}",
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
// Добавляем пустое пространство для разделения текста и кнопки
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(
|
||||
onClick = { onDeleteClick(vision) },
|
||||
modifier = Modifier.size(24.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
contentDescription = "Удалить",
|
||||
tint = MaterialTheme.colorScheme.onSecondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.android_genshin.database.entities.model.Weapon
|
||||
import com.example.android_genshin.database.entities.repository.WeaponRepository
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class WeaponDropDownViewModel(
|
||||
private val weaponRepository: WeaponRepository
|
||||
) : ViewModel() {
|
||||
var weaponsListUiState by mutableStateOf(WeaponsListUiState())
|
||||
private set
|
||||
|
||||
var weaponUiState by mutableStateOf(WeaponUiState())
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
weaponsListUiState = WeaponsListUiState(weaponRepository.getAllWeapons())
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUiState(weapon: Weapon) {
|
||||
weaponUiState = WeaponUiState(
|
||||
weapon = weapon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class WeaponsListUiState(val weaponList: List<Weapon> = listOf())
|
||||
|
||||
data class WeaponUiState(val weapon: Weapon? = null)
|
||||
|
||||
fun Weapon.toUiState() = WeaponUiState(weapon = Weapon(weaponId = weaponId, weaponName = weaponName, weaponType = weaponType, weaponDamage = weaponDamage, image = image))
|
||||
@@ -1,4 +1,128 @@
|
||||
package com.example.android_genshin.database.entities.composeui
|
||||
|
||||
class WeaponEdit {
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import com.example.android_genshin.R
|
||||
import com.example.android_genshin.ui.theme.Android_GenshinTheme
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun WeaponEdit(
|
||||
navController: NavController,
|
||||
viewModel: WeaponEditViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
WeaponEdit(
|
||||
weaponUiState = viewModel.weaponUiState,
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
viewModel.saveWeapon()
|
||||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
onUpdate = viewModel::updateUiState
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun WeaponEdit(
|
||||
weaponUiState: WeaponUiStateEdit,
|
||||
onClick: () -> Unit,
|
||||
onUpdate: (WeaponDetails) -> Unit
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 10.dp)
|
||||
) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = weaponUiState.weaponDetails.weaponName,
|
||||
onValueChange = { onUpdate(weaponUiState.weaponDetails.copy(weaponName = it)) },
|
||||
label = { Text(stringResource(id = R.string.weapon_weaponName)) },
|
||||
singleLine = true
|
||||
)
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = weaponUiState.weaponDetails.weaponType,
|
||||
onValueChange = { onUpdate(weaponUiState.weaponDetails.copy(weaponType = it)) },
|
||||
label = { Text(stringResource(id = R.string.weapon_weaponType)) },
|
||||
singleLine = true
|
||||
)
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = weaponUiState.weaponDetails.weaponDamage.toString(),
|
||||
onValueChange = { newValue ->
|
||||
val parsedDamage = newValue.toInt()
|
||||
onUpdate(weaponUiState.weaponDetails.copy(weaponDamage = parsedDamage))
|
||||
},
|
||||
label = { Text(stringResource(id = R.string.weapon_weaponDamage)) },
|
||||
singleLine = true,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
visualTransformation = VisualTransformation.None // Отключает маскировку
|
||||
)
|
||||
if (weaponUiState.weaponDetails.image != null)
|
||||
ImageUploader(
|
||||
bitmap = BitmapFactory.decodeByteArray(
|
||||
weaponUiState.weaponDetails.image,
|
||||
0,
|
||||
weaponUiState.weaponDetails.image.size
|
||||
),
|
||||
onResult = { byteArray: ByteArray? ->
|
||||
onUpdate(
|
||||
weaponUiState.weaponDetails.copy(
|
||||
image = byteArray
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
Button(
|
||||
onClick = onClick,
|
||||
enabled = weaponUiState.isEntryValid,
|
||||
shape = MaterialTheme.shapes.small,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = stringResource(R.string.character_save_button))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
fun WeaponEditPreview() {
|
||||
Android_GenshinTheme {
|
||||
Surface(
|
||||
color = colorScheme.background
|
||||
) {
|
||||
WeaponEdit(
|
||||
weaponUiState = WeaponUiStateEdit(),
|
||||
onClick = {},
|
||||
onUpdate = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,6 @@ data class WeaponUiStateEdit(
|
||||
)
|
||||
|
||||
data class WeaponDetails(
|
||||
val weaponId: Int = 0,
|
||||
val weaponName: String = "",
|
||||
val weaponType: String = "",
|
||||
val weaponDamage: Int = 0,
|
||||
@@ -79,7 +78,6 @@ fun WeaponDetails.toWeapon(uid: Int = 0): Weapon = Weapon(
|
||||
)
|
||||
|
||||
fun Weapon.toDetails(): WeaponDetails = WeaponDetails(
|
||||
weaponId = weaponId,
|
||||
weaponName = weaponName,
|
||||
weaponType = weaponType,
|
||||
weaponDamage = weaponDamage,
|
||||
|
||||
@@ -17,14 +17,14 @@ class WeaponViewModel(
|
||||
) : ViewModel() {
|
||||
private val weaponUid: Int = checkNotNull(savedStateHandle["id"])
|
||||
|
||||
val weaponUiState: StateFlow<WeaponUiState> = weaponRepository.getWeapon(weaponUid)
|
||||
val weaponUiState: StateFlow<WeaponViewUiState> = weaponRepository.getWeapon(weaponUid)
|
||||
.map {
|
||||
WeaponUiState(it)
|
||||
WeaponViewUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = WeaponUiState()
|
||||
initialValue = WeaponViewUiState()
|
||||
)
|
||||
}
|
||||
|
||||
data class WeaponUiState(val weapon: Weapon? = null)
|
||||
data class WeaponViewUiState(val weapon: Weapon? = null)
|
||||
@@ -12,13 +12,13 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface RarityDao {
|
||||
@Query("SELECT * FROM rarities ORDER BY rarityName")
|
||||
fun getAll(): Flow<List<Rarity>>
|
||||
fun getAll(): List<Rarity>
|
||||
|
||||
@Query("select * from rarities order by rarityName")
|
||||
fun getAllRaritiesPaged(): PagingSource<Int, Rarity>
|
||||
|
||||
@Query("select * from rarities where rarities.rarityId = :uid")
|
||||
suspend fun getByUid(uid: Int?): Rarity
|
||||
fun getByUid(uid: Int?): Flow<Rarity>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(rarity: Rarity)
|
||||
|
||||
@@ -7,12 +7,11 @@ import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface VisionDao {
|
||||
@Query("SELECT * FROM visions ORDER BY visionName")
|
||||
fun getAll(): Flow<List<Vision>>
|
||||
fun getAll(): List<Vision>
|
||||
|
||||
@Query("select * from visions where visions.visionId = :uid")
|
||||
suspend fun getByUid(uid: Int): Vision
|
||||
|
||||
@@ -12,13 +12,13 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface WeaponDao {
|
||||
@Query("SELECT * FROM weapons ORDER BY weaponName")
|
||||
fun getAll(): Flow<List<Weapon>>
|
||||
fun getAll(): List<Weapon>
|
||||
|
||||
@Query("select * from weapons order by weaponName")
|
||||
fun getAllWeaponsPaged(): PagingSource<Int, Weapon>
|
||||
|
||||
@Query("select * from weapons where weapons.weaponId = :uid")
|
||||
suspend fun getByUid(uid: Int): Weapon
|
||||
fun getByUid(uid: Int): Flow<Weapon>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(weapon: Weapon)
|
||||
|
||||
@@ -6,11 +6,11 @@ import com.example.android_genshin.database.entities.model.Rarity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineRarityRepository(private val rarityDao: RarityDao) : RarityRepository {
|
||||
override fun getAllRarities(): Flow<List<Rarity>> = rarityDao.getAll()
|
||||
override fun getAllRarities(): List<Rarity> = rarityDao.getAll()
|
||||
|
||||
override fun getAllRaritiesPaged(): PagingSource<Int, Rarity> = rarityDao.getAllRaritiesPaged()
|
||||
|
||||
override suspend fun getRarity(uid: Int): Rarity = rarityDao.getByUid(uid)
|
||||
override fun getRarity(uid: Int): Flow<Rarity> = rarityDao.getByUid(uid)
|
||||
|
||||
override suspend fun insertRarity(rarity: Rarity) = rarityDao.insert(rarity)
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@ package com.example.android_genshin.database.entities.repository
|
||||
import androidx.paging.PagingSource
|
||||
import com.example.android_genshin.database.entities.dao.VisionDao
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineVisionRepository(private val visionDao: VisionDao) : VisionRepository {
|
||||
override fun getAllVisions(): Flow<List<Vision>> = visionDao.getAll()
|
||||
override fun getAllVisions(): List<Vision> = visionDao.getAll()
|
||||
|
||||
override fun getAllVisionsPaged(): PagingSource<Int, Vision> = visionDao.getAllVisionsPaged()
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import com.example.android_genshin.database.entities.model.Weapon
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineWeaponRepository(private val weaponDao: WeaponDao) : WeaponRepository {
|
||||
override fun getAllWeapons(): Flow<List<Weapon>> = weaponDao.getAll()
|
||||
override fun getAllWeapons(): List<Weapon> = weaponDao.getAll()
|
||||
|
||||
override fun getAllWeaponsPaged(): PagingSource<Int, Weapon> = weaponDao.getAllWeaponsPaged()
|
||||
|
||||
override suspend fun getWeapon(uid: Int): Weapon = weaponDao.getByUid(uid)
|
||||
override fun getWeapon(uid: Int): Flow<Weapon> = weaponDao.getByUid(uid)
|
||||
|
||||
override suspend fun insertWeapon(weapon: Weapon) = weaponDao.insert(weapon)
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import com.example.android_genshin.database.entities.model.Rarity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface RarityRepository {
|
||||
fun getAllRarities(): Flow<List<Rarity>>
|
||||
fun getAllRarities(): List<Rarity>
|
||||
fun getAllRaritiesPaged(): PagingSource<Int, Rarity>
|
||||
suspend fun getRarity(uid: Int): Rarity
|
||||
fun getRarity(uid: Int): Flow<Rarity>
|
||||
suspend fun insertRarity(rarity: Rarity)
|
||||
suspend fun updateRarity(rarity: Rarity)
|
||||
suspend fun deleteRarity(rarity: Rarity)
|
||||
|
||||
@@ -2,10 +2,9 @@ package com.example.android_genshin.database.entities.repository
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import com.example.android_genshin.database.entities.model.Vision
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface VisionRepository {
|
||||
fun getAllVisions(): Flow<List<Vision>>
|
||||
fun getAllVisions(): List<Vision>
|
||||
fun getAllVisionsPaged(): PagingSource<Int, Vision>
|
||||
suspend fun getVision(uid: Int): Vision
|
||||
suspend fun insertVision(vision: Vision)
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.example.android_genshin.database.entities.model.Weapon
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface WeaponRepository {
|
||||
fun getAllWeapons(): Flow<List<Weapon>>
|
||||
fun getAllWeapons(): List<Weapon>
|
||||
fun getAllWeaponsPaged(): PagingSource<Int, Weapon>
|
||||
fun getWeapon(uid: Int): Flow<Weapon>
|
||||
suspend fun insertWeapon(weapon: Weapon)
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
<string name="weapon_view_title">Об оружии</string>
|
||||
<string name="about_title">Genshin Wiki</string>
|
||||
<string name="profile_title">Профиль пользователя</string>
|
||||
<string name="character_rarity_not_select">Выбери редкость</string>
|
||||
<string name="character_vision_not_select">Выбери Глаз Бога</string>
|
||||
<string name="character_weapon_not_select">Выбери оружие</string>
|
||||
<string name="character_save_button">Сохранить</string>
|
||||
<string name="not_uploaded">Не загружена картинка</string>
|
||||
<string name="size">Размер картинки</string>
|
||||
|
||||
<string name="about_text">
|
||||
<p>Это текст <b>о нас</b>!</p>\n\n
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
org.gradle.jvmargs=-Xmx4608m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
|
||||
Reference in New Issue
Block a user