Compare commits

...

10 commits

Author SHA1 Message Date
Andres Gomez, Thomas (ITDV RL)
56f95094c6 Bump version to 0.13.5 2025-02-25 20:49:26 +01:00
Andres Gomez, Thomas (ITDV RL)
e776b7d870 Fix scrollable content on item dialog. 2025-02-12 14:43:51 +01:00
Andres Gomez, Thomas (ITDV RL)
381f9e7204 Bump version to 0.13.4 2025-02-12 13:23:39 +01:00
Andres Gomez, Thomas (ITDV RL)
8f45fe7a77 Fix inventory recomposition 2025-02-12 13:16:01 +01:00
Andres Gomez, Thomas (ITDV RL)
c11dc62a18 Update image cache + add support for Champion alteration 2025-02-12 11:31:57 +01:00
Andres Gomez, Thomas (ITDV RL)
6d77c94611 Bump version to 0.13.3 2025-01-21 10:39:59 +01:00
Andres Gomez, Thomas (ITDV RL)
42d865c4e3 Fix gamemaster roll sharing. 2025-01-21 10:35:27 +01:00
Andres Gomez, Thomas (ITDV RL)
86b8de9dcd Bump version to 1.13.2 2025-01-20 14:49:11 +01:00
Andres Gomez, Thomas (ITDV RL)
5fdf262bde Nam integration into the app and some small releated fixes. 2025-01-17 10:48:34 +01:00
Andres Gomez, Thomas (ITDV RL)
d5736c99ee Bump version to 0.13.1 2024-09-06 13:35:41 +02:00
80 changed files with 134 additions and 174 deletions

View file

@ -34,7 +34,7 @@ android {
applicationId = "com.pixelized.rplexicon" applicationId = "com.pixelized.rplexicon"
minSdk = 26 minSdk = 26
targetSdk = 34 targetSdk = 34
versionName = "0.13.0" versionName = "0.13.5"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {

View file

@ -10,7 +10,6 @@ import com.pixelized.rplexicon.data.repository.character.ActionRepository
import com.pixelized.rplexicon.data.repository.character.AlterationRepository import com.pixelized.rplexicon.data.repository.character.AlterationRepository
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
import com.pixelized.rplexicon.data.repository.character.ItemsRepository import com.pixelized.rplexicon.data.repository.character.ItemsRepository
import com.pixelized.rplexicon.data.repository.character.SkillRepository import com.pixelized.rplexicon.data.repository.character.SkillRepository
import com.pixelized.rplexicon.data.repository.character.SpellRepository import com.pixelized.rplexicon.data.repository.character.SpellRepository
@ -44,7 +43,6 @@ class LauncherViewModel @Inject constructor(
skillRepository: SkillRepository, skillRepository: SkillRepository,
descriptionRepository: DescriptionRepository, descriptionRepository: DescriptionRepository,
itemsRepository: ItemsRepository, itemsRepository: ItemsRepository,
equipmentRepository: EquipmentRepository,
removeConRepository: RemoteConfigRepository // Unused but injected to initialize it. removeConRepository: RemoteConfigRepository // Unused but injected to initialize it.
) : ViewModel() { ) : ViewModel() {
@ -112,14 +110,6 @@ class LauncherViewModel @Inject constructor(
_error.emit(FetchErrorUio.Structure(type = Type.INVENTORY)) _error.emit(FetchErrorUio.Structure(type = Type.INVENTORY))
} }
} }
val equipment = async {
try {
equipmentRepository.fetchEquipment()
} catch (exception: Exception) {
Log.e(TAG, exception.message, exception)
_error.emit(FetchErrorUio.Structure(type = Type.EQUIPMENT))
}
}
awaitAll(characterSheet) awaitAll(characterSheet)
val alteration = async { val alteration = async {
@ -156,7 +146,7 @@ class LauncherViewModel @Inject constructor(
} }
awaitAll(order, lexicon, location, quest) awaitAll(order, lexicon, location, quest)
awaitAll(description, inventory, equipment, alteration, action, spell, skill) awaitAll(description, inventory, alteration, action, spell, skill)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
isLoading = false isLoading = false

View file

@ -28,6 +28,7 @@ import com.pixelized.rplexicon.utilitary.extentions.local.emphasis
import com.pixelized.rplexicon.utilitary.extentions.local.fail import com.pixelized.rplexicon.utilitary.extentions.local.fail
import com.pixelized.rplexicon.utilitary.extentions.local.isBrutalCritical import com.pixelized.rplexicon.utilitary.extentions.local.isBrutalCritical
import com.pixelized.rplexicon.utilitary.extentions.local.isCritical import com.pixelized.rplexicon.utilitary.extentions.local.isCritical
import com.pixelized.rplexicon.utilitary.extentions.local.isImprovedCritical
import com.pixelized.rplexicon.utilitary.extentions.local.isSavageAttacks import com.pixelized.rplexicon.utilitary.extentions.local.isSavageAttacks
import com.pixelized.rplexicon.utilitary.extentions.local.primary import com.pixelized.rplexicon.utilitary.extentions.local.primary
import com.pixelized.rplexicon.utilitary.extentions.local.secondary import com.pixelized.rplexicon.utilitary.extentions.local.secondary
@ -738,7 +739,7 @@ class DiceThrowUseCase @Inject constructor(
val emphasis = status[ability].emphasis val emphasis = status[ability].emphasis
// compute the amount of main dice to throw. // compute the amount of main dice to throw.
val amount = if (status.isCritical) { val amount = if (status[ability].isCritical) {
diceThrow?.dice?.count?.times(2)?.let { diceThrow?.dice?.count?.times(2)?.let {
if (ability == Property.PHYSICAL_MELEE_DAMAGE && status.isSavageAttacks) it.plus( if (ability == Property.PHYSICAL_MELEE_DAMAGE && status.isSavageAttacks) it.plus(
1 1
@ -774,9 +775,17 @@ class DiceThrowUseCase @Inject constructor(
// check for flat dice bonus (ex: healing potion 2d4 + 2) // check for flat dice bonus (ex: healing potion 2d4 + 2)
val relatedFlatBonus = diceThrow.flatBonus(name = action) val relatedFlatBonus = diceThrow.flatBonus(name = action)
// compute the final roll result // if the roll can be a critical roll check if the roll is one.
val isCriticalSuccess = when {
canMakeCriticalRoll && result.value == 20 -> true
canMakeCriticalRoll && result.value == 19 && status.isImprovedCritical -> true
else -> false
}
// compute the roll result. by default display a sum of everything except on a critical
val rollResult = when { val rollResult = when {
canMakeCriticalRoll && result.value == 20 -> "20" isCriticalSuccess && result.value == 20 -> "20"
isCriticalSuccess && result.value == 19 -> "19"
canMakeCriticalRoll && result.value == 1 -> "1" canMakeCriticalRoll && result.value == 1 -> "1"
else -> "${allValue.sum()}" else -> "${allValue.sum()}"
} }
@ -785,7 +794,7 @@ class DiceThrowUseCase @Inject constructor(
return DiceThrowResult( return DiceThrowResult(
dice = RollDiceUio( dice = RollDiceUio(
icon = diceThrow?.dice?.icon ?: R.drawable.ic_d20_24, icon = diceThrow?.dice?.icon ?: R.drawable.ic_d20_24,
isCriticalSuccess = canMakeCriticalRoll && result.value == 20, isCriticalSuccess = isCriticalSuccess,
isCriticalFailure = canMakeCriticalRoll && result.value == 1, isCriticalFailure = canMakeCriticalRoll && result.value == 1,
result = rollResult, result = rollResult,
), ),
@ -794,7 +803,7 @@ class DiceThrowUseCase @Inject constructor(
title = titleString.uppercase(), title = titleString.uppercase(),
highlight = action.uppercase(), highlight = action.uppercase(),
face = diceThrow?.dice?.faces ?: 20, face = diceThrow?.dice?.faces ?: 20,
isCriticalSuccess = canMakeCriticalRoll && result.value == 20, isCriticalSuccess = isCriticalSuccess,
isCriticalFailure = canMakeCriticalRoll && result.value == 1, isCriticalFailure = canMakeCriticalRoll && result.value == 1,
roll = allValue.toLabel(), roll = allValue.toLabel(),
result = rollResult, result = rollResult,
@ -1070,7 +1079,7 @@ class DiceThrowUseCase @Inject constructor(
return this?.flatMap { status -> return this?.flatMap { status ->
status.dices.map { dice -> status.dices.map { dice ->
val localRoll = roll( val localRoll = roll(
amount = if (this@ThrowScope.status.isCritical) dice.count * 2 else dice.count, amount = if (isCritical) dice.count * 2 else dice.count,
faces = dice.faces, faces = dice.faces,
advantage = dice.advantage, advantage = dice.advantage,
disadvantage = dice.disadvantage, disadvantage = dice.disadvantage,

View file

@ -5,6 +5,7 @@ import androidx.annotation.StringRes
import com.pixelized.rplexicon.R import com.pixelized.rplexicon.R
data class CharacterSheet( data class CharacterSheet(
val active: Boolean,
val name: String, val name: String,
val race: String?, val race: String?,
val proficiency: Int, // Bonus de maîtrise val proficiency: Int, // Bonus de maîtrise
@ -22,7 +23,7 @@ data class CharacterSheet(
val spell9: Int?, // level 9 spell slot val spell9: Int?, // level 9 spell slot
val dC: Int?, // offensive saving throw. val dC: Int?, // offensive saving throw.
val armorClass: Int, // Classe d'armure val armorClass: Int, // Classe d'armure
val speed: Int, // Vitesse val speed: Float, // Vitesse
val strength: Int, // Force val strength: Int, // Force
val dexterity: Int, // Dextérité val dexterity: Int, // Dextérité
val constitution: Int, // Constitution val constitution: Int, // Constitution

View file

@ -33,6 +33,7 @@ class CharacterSheetParser @Inject constructor(
val name = item.parse(column = NAME) val name = item.parse(column = NAME)
if (name != null) { if (name != null) {
CharacterSheet( CharacterSheet(
active = item.parseBool(column = ACTIVE) ?: false,
name = name, name = name,
race = item.parse(column = RACE), race = item.parse(column = RACE),
proficiency = item.parseInt(column = MASTERY) ?: 2, proficiency = item.parseInt(column = MASTERY) ?: 2,
@ -50,7 +51,7 @@ class CharacterSheetParser @Inject constructor(
spell9 = item.parseInt(column = SPELL_LEVEL_9), spell9 = item.parseInt(column = SPELL_LEVEL_9),
dC = item.parseInt(column = DD_SAVE_THROW), dC = item.parseInt(column = DD_SAVE_THROW),
armorClass = item.parseInt(column = ARMOR_CLASS) ?: 10, armorClass = item.parseInt(column = ARMOR_CLASS) ?: 10,
speed = item.parseInt(column = SPEED) ?: 10, speed = item.parseFloat(column = SPEED) ?: 10f,
strength = item.parseInt(column = STRENGTH) ?: 10, strength = item.parseInt(column = STRENGTH) ?: 10,
dexterity = item.parseInt(column = DEXTERITY) ?: 10, dexterity = item.parseInt(column = DEXTERITY) ?: 10,
constitution = item.parseInt(column = CONSTITUTION) ?: 10, constitution = item.parseInt(column = CONSTITUTION) ?: 10,
@ -103,6 +104,7 @@ class CharacterSheetParser @Inject constructor(
} }
companion object { companion object {
private val ACTIVE = column("Actif")
private val NAME = column("Nom") private val NAME = column("Nom")
private val RACE = column("Race") private val RACE = column("Race")
private val LEVEL = column("Niveau") private val LEVEL = column("Niveau")
@ -157,6 +159,7 @@ class CharacterSheetParser @Inject constructor(
private val ROWS private val ROWS
get() = listOf( get() = listOf(
ACTIVE,
NAME, NAME,
RACE, RACE,
LEVEL, LEVEL,

View file

@ -1,71 +0,0 @@
package com.pixelized.rplexicon.data.parser.inventory
import com.google.api.services.sheets.v4.model.ValueRange
import com.pixelized.rplexicon.data.model.Equipment
import com.pixelized.rplexicon.data.parser.parserScope
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
import javax.inject.Inject
class EquipmentParser @Inject constructor() {
@Throws(IncompatibleSheetStructure::class)
fun parse(data: ValueRange): Map<String, Equipment> = parserScope {
lateinit var characters: List<String>
val equipments = hashMapOf<String, Equipment.Builder>()
data.forEachRowIndexed { index, row ->
when (index) {
// ignore the first column
0 -> characters = row.drop(1).map { it.toString() }
else -> row.drop(1).forEachIndexed { column, item ->
val character = characters[column]
equipments.getEquipment(name = character).let {
when (row[0]) {
BACKGROUND -> it.background = item.toItem()
HEAD -> it.head = item.toItem()
FACE -> it.face = item.toItem()
NECK -> it.neck = item.toItem()
SHOULDER -> it.shoulder = item.toItem()
BODY -> it.body = item.toItem()
CHEST -> it.chest = item.toItem()
ARM -> it.arm = item.toItem()
HAND -> it.hand = item.toItem()
RING_1 -> it.ring1 = item.toItem()
RING_2 -> it.ring2 = item.toItem()
WAIST -> it.waist = item.toItem()
FOOT -> it.foot = item.toItem()
MAIN_HAND -> it.mainHand = item.toItem()
OFF_HAND -> it.offHand = item.toItem()
}
}
}
}
}
return@parserScope characters.associateWith {
equipments.getEquipment(name = it).build()
}
}
private fun HashMap<String, Equipment.Builder>.getEquipment(name: String) =
this.getOrPut(name) { Equipment.Builder() }
companion object {
private const val BACKGROUND = "Silhouette"
private const val HEAD = "Tête"
private const val FACE = "Visage"
private const val NECK = "Gorge"
private const val SHOULDER = "Épaules"
private const val BODY = "Corp"
private const val CHEST = "Torse"
private const val ARM = "Bras"
private const val HAND = "Mains"
private const val RING_1 = "Anneau 1"
private const val RING_2 = "Anneau 2"
private const val WAIST = "Taille"
private const val FOOT = "Pieds"
private const val MAIN_HAND = "Main droite"
private const val OFF_HAND = "Main gauche"
}
}

View file

@ -1,36 +0,0 @@
package com.pixelized.rplexicon.data.repository.character
import com.pixelized.rplexicon.data.model.Equipment
import com.pixelized.rplexicon.data.parser.inventory.EquipmentParser
import com.pixelized.rplexicon.data.repository.CharacterBinder
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
import com.pixelized.rplexicon.utilitary.Update
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class EquipmentRepository @Inject constructor(
private val googleRepository: GoogleSheetServiceRepository,
private val equipmentParser: EquipmentParser,
) {
private val _data = MutableStateFlow<Map<String, Equipment>>(emptyMap())
val data: StateFlow<Map<String, Equipment>> get() = _data
var lastSuccessFullUpdate: Update = Update.INITIAL
private set
fun find(name: String?): Equipment? = _data.value[name]
@Throws(IncompatibleSheetStructure::class, Exception::class)
suspend fun fetchEquipment() {
googleRepository.fetch { sheet ->
val request = sheet.get(CharacterBinder.ID, CharacterBinder.EQUIPMENT)
val data = equipmentParser.parse(data = request.execute())
_data.tryEmit(data)
lastSuccessFullUpdate = Update.currentTime()
}
}
}

View file

@ -320,7 +320,10 @@ private fun rememberPortrait(): List<Int> = rememberSaveable {
listOf( listOf(
R.drawable.im_brulkhai, R.drawable.im_brulkhai,
R.drawable.im_leandre, R.drawable.im_leandre,
R.drawable.im_nelia, listOf(
R.drawable.im_nelia,
R.drawable.im_nam,
).shuffled().first(),
R.drawable.im_tigrane, R.drawable.im_tigrane,
R.drawable.im_unathana, R.drawable.im_unathana,
).shuffled() ).shuffled()

View file

@ -105,10 +105,7 @@ enum class CharacterTabUio(@StringRes val label: Int) {
Proficiency(R.string.character_sheet_tab_proficiency), Proficiency(R.string.character_sheet_tab_proficiency),
} }
@OptIn( @OptIn(ExperimentalMaterialApi::class)
ExperimentalMaterialApi::class,
ExperimentalFoundationApi::class,
)
@Composable @Composable
fun CharacterSheetScreen( fun CharacterSheetScreen(
viewModel: CharacterSheetViewModel = hiltViewModel(), viewModel: CharacterSheetViewModel = hiltViewModel(),
@ -490,7 +487,6 @@ private fun CharacterScreenPreview(
} }
} }
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)
@Composable @Composable
private fun BackHandler( private fun BackHandler(
sheetState: ModalBottomSheetState, sheetState: ModalBottomSheetState,

View file

@ -10,7 +10,6 @@ import com.pixelized.rplexicon.data.repository.character.ActionRepository
import com.pixelized.rplexicon.data.repository.character.AlterationRepository import com.pixelized.rplexicon.data.repository.character.AlterationRepository
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
import com.pixelized.rplexicon.data.repository.character.ItemsRepository import com.pixelized.rplexicon.data.repository.character.ItemsRepository
import com.pixelized.rplexicon.data.repository.character.SkillRepository import com.pixelized.rplexicon.data.repository.character.SkillRepository
import com.pixelized.rplexicon.data.repository.character.SpellRepository import com.pixelized.rplexicon.data.repository.character.SpellRepository
@ -33,7 +32,6 @@ class CharacterSheetViewModel @Inject constructor(
private val descriptionRepository: DescriptionRepository, private val descriptionRepository: DescriptionRepository,
private val alterationRepository: AlterationRepository, private val alterationRepository: AlterationRepository,
private val itemsRepository: ItemsRepository, private val itemsRepository: ItemsRepository,
private val equipmentRepository: EquipmentRepository,
private val actionRepository: ActionRepository, private val actionRepository: ActionRepository,
private val spellRepository: SpellRepository, private val spellRepository: SpellRepository,
private val skillRepository: SkillRepository, private val skillRepository: SkillRepository,
@ -93,16 +91,6 @@ class CharacterSheetViewModel @Inject constructor(
} }
} }
} }
val equipment = async {
if (force || equipmentRepository.lastSuccessFullUpdate.shouldUpdate()) {
try {
equipmentRepository.fetchEquipment()
} catch (exception: Exception) {
Log.e(TAG, exception.message, exception)
_error.emit(FetchErrorUio.Structure(type = Type.EQUIPMENT))
}
}
}
awaitAll(characters) awaitAll(characters)
val alterations = async { val alterations = async {
if (force || alterationRepository.lastSuccessFullUpdate.shouldUpdate()) { if (force || alterationRepository.lastSuccessFullUpdate.shouldUpdate()) {
@ -144,7 +132,7 @@ class CharacterSheetViewModel @Inject constructor(
} }
} }
} }
awaitAll(description, alterations, inventory, equipment, actions, spells, skills) awaitAll(description, alterations, inventory, actions, spells, skills)
_isLoading.value = false _isLoading.value = false
} }

View file

@ -281,7 +281,7 @@ class CharacterSheetUioFactory @Inject constructor() {
), ),
speed = LabelPointUio( speed = LabelPointUio(
label = R.string.character_sheet_title_speed, label = R.string.character_sheet_title_speed,
value = "${max(sheet.speed + status[Property.SPEED].sum, 0)}m", value = "${max(sheet.speed + status[Property.SPEED].sum.toFloat(), 0f)}m",
), ),
masteries = MasteriesUio( masteries = MasteriesUio(
martial = sheet.martial, martial = sheet.martial,

View file

@ -25,6 +25,9 @@ class SpellUioFactory @Inject constructor(
val modifier = diceThrow.modifier.sumOf { val modifier = diceThrow.modifier.sumOf {
when (it) { when (it) {
Property.PROFICIENCY -> characterSheet.proficiency Property.PROFICIENCY -> characterSheet.proficiency
Property.STRENGTH -> characterSheet.strength.modifier
Property.DEXTERITY -> characterSheet.dexterity.modifier
Property.CONSTITUTION -> characterSheet.constitution.modifier
Property.INTELLIGENCE -> characterSheet.intelligence.modifier Property.INTELLIGENCE -> characterSheet.intelligence.modifier
Property.WISDOM -> characterSheet.wisdom.modifier Property.WISDOM -> characterSheet.wisdom.modifier
Property.CHARISMA -> characterSheet.charisma.modifier Property.CHARISMA -> characterSheet.charisma.modifier

View file

@ -170,7 +170,6 @@ fun InventoryPage(
} }
} }
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
private fun InventoryContent( private fun InventoryContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -248,7 +247,6 @@ private fun InventoryContent(
when (item) { when (item) {
is String -> CategoryHeader( is String -> CategoryHeader(
modifier = Modifier modifier = Modifier
.animateItem()
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(
start = 16.dp, start = 16.dp,

View file

@ -1,15 +1,12 @@
package com.pixelized.rplexicon.ui.screens.character.pages.inventory.composable.draggable package com.pixelized.rplexicon.ui.screens.character.pages.inventory.composable.draggable
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun LazyGridItemScope.DraggableInventoryElement( fun DraggableInventoryElement(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
dragDropState: InventoryDragDropState, dragDropState: InventoryDragDropState,
index: Int, index: Int,
@ -18,7 +15,6 @@ fun LazyGridItemScope.DraggableInventoryElement(
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
.animateItem()
.graphicsLayer { .graphicsLayer {
dragDropState.draggedItemElement?.let { element -> dragDropState.draggedItemElement?.let { element ->
this.alpha = when { this.alpha = when {

View file

@ -24,11 +24,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
@ -183,7 +185,9 @@ private fun ItemDetailContent(
) )
} }
Column( Column(
modifier = Modifier.fillMaxWidth(), modifier = Modifier
.fillMaxWidth()
.verticalScroll(state = rememberScrollState()),
) { ) {
Text( Text(
modifier = Modifier.padding( modifier = Modifier.padding(

View file

@ -36,7 +36,9 @@ import com.pixelized.rplexicon.utilitary.extentions.toLabel
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
@ -146,7 +148,7 @@ class SummaryFactory @Inject constructor(
val data = DataStruct() val data = DataStruct()
characterSheetRepository.data characterSheetRepository.data
.combine(activeAlterationRepository.getActiveAlterations()) { sheets, alterations -> .combine(activeAlterationRepository.getActiveAlterations()) { sheets, alterations ->
data.sheets = sheets data.sheets = sheets.filter { entry -> entry.value.active }
data.alterations = alterations data.alterations = alterations
} }
.combine(firebaseRepository.getCharacters()) { _, fire -> .combine(firebaseRepository.getCharacters()) { _, fire ->
@ -216,7 +218,7 @@ class SummaryFactory @Inject constructor(
label = (dexterity.modifier + status[Property.INITIATIVE].sum).toLabel() label = (dexterity.modifier + status[Property.INITIATIVE].sum).toLabel()
) )
val speed = label( val speed = label(
label = "${max(sheet.speed + status[Property.SPEED].sum, 0)}m", label = "${max(sheet.speed + status[Property.SPEED].sum.toFloat(), 0f)}m",
) )
val inspiration = proficiency( val inspiration = proficiency(
label = null, label = null,
@ -653,7 +655,7 @@ class SummaryFactory @Inject constructor(
val data = HeaderStatStruct() val data = HeaderStatStruct()
characterSheetRepository.data characterSheetRepository.data
.combine(throwRepository.getThrows()) { sheets, fire -> .combine(throwRepository.getThrows()) { sheets, fire ->
data.sheets = sheets data.sheets = sheets.filter { entry -> entry.value.active }
data.fires = fire.details data.fires = fire.details
} }
.collect { .collect {

View file

@ -224,7 +224,65 @@ object ImageCache {
"https://bg3.wiki/w/images/f/f7/Magic_Initiate_Bard_Icon.webp" to R.drawable.icbg_magic_initiate_bard, "https://bg3.wiki/w/images/f/f7/Magic_Initiate_Bard_Icon.webp" to R.drawable.icbg_magic_initiate_bard,
"https://bg3.wiki/w/images/f/f9/Mage_Hand_Icon.webp" to R.drawable.icbg_mage_hand, "https://bg3.wiki/w/images/f/f9/Mage_Hand_Icon.webp" to R.drawable.icbg_mage_hand,
"https://bg3.wiki/w/images/f/fb/Camp_Rich_B_Purple_Unfaded.png" to R.drawable.icbg_camp_rich_b_purple_unfaded, "https://bg3.wiki/w/images/f/fb/Camp_Rich_B_Purple_Unfaded.png" to R.drawable.icbg_camp_rich_b_purple_unfaded,
"https://bg3.wiki/w/images/b/ba/Rakish_Audacity_Icon.webp" to R.drawable.icbg_rakish_audacity,
"https://bg3.wiki/w/images/4/4d/Action_Surge_Icon.webp" to R.drawable.icbg_action_surge_icon,
"https://bg3.wiki/w/images/a/a6/Lever_Handle_Unfaded_Icon.png" to R.drawable.icbg_lever_handle_unfaded_icon,
"https://bg3.wiki/w/images/a/a5/Pouch_A_Unfaded_Icon.webp" to R.drawable.icbg_pouch_a_unfaded_icon,
"https://bg3.wiki/w/images/8/8f/Knife_A_Unfaded_Icon.png" to R.drawable.icbg_knife_a_unfaded_icon,
"https://bg3.wiki/w/images/7/78/Studded_Leather_Unfaded_Icon.png" to R.drawable.icbg_studded_leather_unfaded_icon,
"https://bg3.wiki/w/images/3/34/Book_Parchment_A_Unfaded.png" to R.drawable.icbg_book_parchment_a_unfaded,
"https://bg3.wiki/w/images/2/21/Book_Note_H_Unfaded.png" to R.drawable.icbg_book_note_h_unfaded,
"https://bg3.wiki/w/images/7/7b/Book_Grimoire_Unfaded_Icon.png" to R.drawable.icbg_book_grimoire_unfaded_icon,
"https://bg3.wiki/w/images/0/02/Gnome_Cunning_Icon.webp" to R.drawable.icbg_gnome_cunning_icon,
"https://bg3.wiki/w/images/d/d2/Training_in_War_and_Song_Icon.webp" to R.drawable.icbg_training_in_war_and_song_icon,
"https://bg3.wiki/w/images/e/ed/Arcane_Recovery_Icon.webp" to R.drawable.icbg_arcane_recovery_icon,
"https://bg3.wiki/w/images/8/80/Bladesong_Icon.webp" to R.drawable.icbg_bladesong_icon,
"https://bg3.wiki/w/images/f/fd/Booming_Blade_Icon.webp" to R.drawable.icbg_booming_blade_icon,
"https://bg3.wiki/w/images/2/23/Fire_Bolt_Icon.webp" to R.drawable.icbg_fire_bolt_icon,
"https://bg3.wiki/w/images/7/7f/Command_Halt_Icon.webp" to R.drawable.icbg_command_halt_icon,
"https://bg3.wiki/w/images/0/0d/Mage_Armour_Icon.webp" to R.drawable.icbg_mage_armour_icon,
"https://bg3.wiki/w/images/1/17/Ice_Knife_Icon.webp" to R.drawable.icbg_ice_knife_icon,
"https://bg3.wiki/w/images/8/8d/Disguise_Self_Icon.webp" to R.drawable.icbg_disguise_self_icon,
"https://bg3.wiki/w/images/d/d4/Magic_Missile_Icon.webp" to R.drawable.icbg_magic_missile_icon,
"https://bg3.wiki/w/images/6/6e/Shadow_Blade_Icon.webp" to R.drawable.icbg_shadow_blade_icon,
"https://bg3.wiki/w/images/b/b9/Wild_Shape_Icon.webp" to R.drawable.icbg_wild_shape_icon,
"https://bg3.wiki/w/images/c/c3/See_Invisibility_Icon.webp" to R.drawable.icbg_see_invisibility_icon,
"https://bg3.wiki/w/images/5/50/Counterspell_Icon.webp" to R.drawable.icbg_counterspell_icon,
"https://bg3.wiki/w/images/0/0a/Unshackling_Strike_Icon.webp" to R.drawable.icbg_unshackling_strike_icon,
"https://bg3.wiki/w/images/7/7f/Remove_Curse_Icon.webp" to R.drawable.icbg_remove_curse_icon,
"https://bg3.wiki/w/images/4/46/Aberrant_Shape_Icon.webp" to R.drawable.icbg_aberrant_shape_icon,
"https://bg3.wiki/w/images/f/f6/Polymorph_Icon.webp" to R.drawable.icbg_polymorph_icon,
"https://bg3.wiki/w/images/8/8b/Dueller%27s_Enthusiasm_Icon.webp" to R.drawable.icbg_dueller_enthusiasm_icon,
"https://bg3.wiki/w/images/f/ff/Camp_Circus_B_Unfaded_Icon.webp" to R.drawable.icbg_camp_circus_b_unfaded_icon,
"https://bg3.wiki/w/images/f/f2/Camp_Aristocrat_Unfaded_Icon.webp" to R.drawable.icbg_camp_aristocrat_unfaded_icon,
"https://bg3.wiki/w/images/1/1d/Camp_Rich_C_Red_Unfaded_Icon.webp" to R.drawable.icbg_camp_rich_c_red_unfaded_icon,
"https://bg3.wiki/w/images/8/85/Strange_Chunk_of_Amber_Unfaded_Icon.png" to R.drawable.icbg_strange_chunk_of_amber_unfaded_icon,
"https://bg3.wiki/w/images/7/72/Toy_Block_A_Unfaded_Icon.png" to R.drawable.icbg_toy_block_a_unfaded_icon,
"https://bg3.wiki/w/images/f/f5/Keepsake_Locket_A_Unfaded.png" to R.drawable.icbg_keepsake_locket_a_unfaded,
"https://bg3.wiki/w/images/4/4e/Crystal_Fluorite_Shard_Unfaded.png" to R.drawable.icbg_crystal_fluorite_shard_unfaded,
"https://bg3.wiki/w/images/1/1b/Moondrop_Pendant_Unfaded.png" to R.drawable.icbg_moondrop_pendant_unfaded,
"https://bg3.wiki/w/images/4/47/Gortash%27s_Netherstone_Unfaded_Icon.png" to R.drawable.icbg_gortash_netherstone_unfaded_icon,
"https://bg3.wiki/w/images/thumb/0/0a/Unshackling_Strike_Icon.webp/144px-Unshackling_Strike_Icon.webp.png" to R.drawable.icbg_unshackling_strike, "https://bg3.wiki/w/images/thumb/0/0a/Unshackling_Strike_Icon.webp/144px-Unshackling_Strike_Icon.webp.png" to R.drawable.icbg_unshackling_strike,
"https://bg3.wiki/w/images/thumb/e/e9/Poisoned_Condition_Icon.webp/45px-Poisoned_Condition_Icon.webp.png" to R.drawable.icbg_poisoned_condition_icon,
"https://bg3.wiki/w/images/thumb/0/09/Paralysed_Condition_Icon.webp/45px-Paralysed_Condition_Icon.webp.png" to R.drawable.icbg_paralysed_condition_icon,
"https://bg3.wiki/w/images/thumb/8/8e/Prone_Condition_Icon.webp/38px-Prone_Condition_Icon.webp.png" to R.drawable.icbg_prone_condition_icon,
"https://bg3.wiki/w/images/thumb/6/60/Grappled_Condition_Icon.webp/45px-Grappled_Condition_Icon.webp.png" to R.drawable.icbg_grappled_condition_icon,
"https://bg3.wiki/w/images/thumb/7/70/Blinded_Condition_Icon.webp/38px-Blinded_Condition_Icon.webp.png" to R.drawable.icbg_blinded_condition_icon,
"https://bg3.wiki/w/images/thumb/4/47/Charmed_Condition_Icon.webp/38px-Charmed_Condition_Icon.webp.png" to R.drawable.icbg_charmed_condition_icon,
"https://bg3.wiki/w/images/thumb/7/75/Frightened_Condition_Icon.webp/38px-Frightened_Condition_Icon.webp.png" to R.drawable.icbg_frightened_condition_icon,
"https://bg3.wiki/w/images/thumb/2/20/Restrained_Condition_Icon.webp/45px-Restrained_Condition_Icon.webp.png" to R.drawable.icbg_restrained_condition_icon,
"https://bg3.wiki/w/images/thumb/3/32/Stunned_Condition_Icon.webp/45px-Stunned_Condition_Icon.webp.png" to R.drawable.icbg_stunned_condition_icon,
"https://bg3.wiki/w/images/thumb/9/98/Incapacitated_Condition_Icon.webp/38px-Incapacitated_Condition_Icon.webp.png" to R.drawable.icbg_incapacitated_condition_icon,
"https://bg3.wiki/w/images/thumb/a/a6/Unconscious_Condition_Icon.webp/64px-Unconscious_Condition_Icon.webp.png?20231130005748" to R.drawable.icbg_unconscious_condition_icon,
"https://bg3.wiki/w/images/thumb/d/d7/Invisible_Condition_Icon.webp/45px-Invisible_Condition_Icon.webp.png" to R.drawable.icbg_invisible_condition_icon,
"https://bg3.wiki/w/images/thumb/c/c0/Petrified_Condition_Icon.webp/45px-Petrified_Condition_Icon.webp.png" to R.drawable.icbg_petrified_condition_icon,
"https://bg3.wiki/w/images/thumb/2/2e/Background_Sage_Icon.png/180px-Background_Sage_Icon.png" to R.drawable.icbg_background_sage_icon,
"https://static.wikia.nocookie.net/witcher/images/3/3d/Tw3_weapon_repair_kit_masters.png/revision/latest?cb=20160410121438" to R.drawable.tw_weapon_repair_kit_masters,
"https://static.wikia.nocookie.net/witcher/images/c/c3/Tw3_concealment_kit.png/revision/latest?cb=20170416212412" to R.drawable.tw_concealment_kit,
"https://static.wikia.nocookie.net/forgottenrealms/images/e/ee/Forgery_Kit.png/revision/latest?cb=20231120043151" to R.drawable.tw_forgery_kit,
"https://static.wikia.nocookie.net/witcher/images/1/1d/Tw3_cloth_doll.png/revision/latest?cb=20160519181719" to R.drawable.tw_cloth_doll,
"https://static.wikia.nocookie.net/gensin-impact/images/e/ee/Item_Sentry%27s_Wooden_Whistle.png/revision/latest?cb=20240826125031" to R.drawable.tw_item_sentry_wooden_whistle,
"https://s3.eu-west-2.amazonaws.com/www.partynutters.com/img/va093-frog-toad-deluxe-venetian-mask.jpg" to R.drawable.frog_toad_deluxe_venetian_mask,
"https://drive.google.com/uc?export=view&id=15D3Jum_X_nw4tWfbaLbEvhTQQbmYCMwf" to R.drawable.ic_dice_advantage, "https://drive.google.com/uc?export=view&id=15D3Jum_X_nw4tWfbaLbEvhTQQbmYCMwf" to R.drawable.ic_dice_advantage,
"https://drive.google.com/uc?export=view&id=17MrL-HAlpqPI5c6APjz5arGYrfma42on" to R.drawable.ic_drive_orc_mask, "https://drive.google.com/uc?export=view&id=17MrL-HAlpqPI5c6APjz5arGYrfma42on" to R.drawable.ic_drive_orc_mask,
"https://drive.google.com/uc?export=view&id=1AeSHg792EwVbkjCNjJaqzC4v0uNj9NRn" to R.drawable.ic_drive_fire_starter, "https://drive.google.com/uc?export=view&id=1AeSHg792EwVbkjCNjJaqzC4v0uNj9NRn" to R.drawable.ic_drive_fire_starter,
@ -247,9 +305,13 @@ object ImageCache {
"https://drive.google.com/uc?export=view&id=1hPiuG7LQc4KVqBfytAXlo0QVLpWwoKdm" to R.drawable.ic_drive_copper_coin_pile, "https://drive.google.com/uc?export=view&id=1hPiuG7LQc4KVqBfytAXlo0QVLpWwoKdm" to R.drawable.ic_drive_copper_coin_pile,
"https://drive.google.com/uc?export=view&id=1N73d_elaDPND3TVN2SgmBGOStSuY1aB9" to R.drawable.ic_drive_silver_coin_pile, "https://drive.google.com/uc?export=view&id=1N73d_elaDPND3TVN2SgmBGOStSuY1aB9" to R.drawable.ic_drive_silver_coin_pile,
"https://drive.google.com/uc?export=view&id=1N-Rp4d8gTctHE5ST2qzYmT-nqoX6iyjg" to R.drawable.ic_drive_electrum_coin_pile, "https://drive.google.com/uc?export=view&id=1N-Rp4d8gTctHE5ST2qzYmT-nqoX6iyjg" to R.drawable.ic_drive_electrum_coin_pile,
"https://drive.google.com/uc?export=view&id=1sKiDdIakpe1shE0zi-Ip0CineEe1M2H2" to R.drawable.ic_drive_gold_coin_pile "https://drive.google.com/uc?export=view&id=1sKiDdIakpe1shE0zi-Ip0CineEe1M2H2" to R.drawable.ic_drive_gold_coin_pile,
"https://drive.google.com/uc?export=view&id=1Sk2-3paCI59ET9k28HSuZaQVcGb90-A_" to R.drawable.icbg_deafened,
"https://drive.google.com/uc?export=view&id=1Amdb2gHrS6SCOa34JlQijWi0u25z62QD" to R.drawable.icbg_green_flame_sword,
) )
private val missingUri = mutableSetOf<Uri>()
fun cache(uri: Uri?): ImageUio = when (uri) { fun cache(uri: Uri?): ImageUio = when (uri) {
null -> { null -> {
R.drawable.icbg_generic_darkness_icon.toImage() R.drawable.icbg_generic_darkness_icon.toImage()
@ -261,8 +323,12 @@ object ImageCache {
} }
else -> { else -> {
Log.v("ImageCache", "$uri") uri.also {
uri.toImage() if (missingUri.contains(it).not()) {
Log.v("ImageCache", "$it")
}
missingUri.add(it)
}.toImage()
} }
} }
} }

View file

@ -37,22 +37,34 @@ val List<Alteration.Status>?.mastery: Int
} }
} ?: 0 } ?: 0
val List<Alteration.Status>?.fail: Boolean
get() = this?.any { it.fail } ?: false
val List<Alteration.Status>?.passivesBonus: Int val List<Alteration.Status>?.passivesBonus: Int
get() = (if (advantage) 5 else 0) - (if (disadvantage) 5 else 0) get() = (if (advantage) 5 else 0) - (if (disadvantage) 5 else 0)
// force a roll to hit a 20 val List<Alteration.Status>?.isCritical: Boolean
get() = this?.any { it.name == CRITIQUE } == true
// Force a roll to hit a 1
val List<Alteration.Status>?.fail: Boolean
get() = this?.any { it.fail } ?: false
// Force a roll to hit a 20
val List<Alteration.Status>?.critical: Boolean val List<Alteration.Status>?.critical: Boolean
get() = this?.any { it.critical } ?: false get() = this?.any { it.critical } ?: false
// Add a dice to a critical roll.
val Map<Property, List<Alteration.Status>>.isSavageAttacks: Boolean val Map<Property, List<Alteration.Status>>.isSavageAttacks: Boolean
get() = this[Property.PHYSICAL_MELEE_DAMAGE]?.any { it.name == "Attaques sauvages" } == true get() = this[Property.PHYSICAL_MELEE_DAMAGE]?.any { it.name == SAVAGE_ATTACK } == true
// Add a dice to a critical roll.
val Map<Property, List<Alteration.Status>>.isBrutalCritical: Boolean val Map<Property, List<Alteration.Status>>.isBrutalCritical: Boolean
get() = this[Property.PHYSICAL_MELEE_DAMAGE]?.any { it.name == "Critique brutal" } == true get() = this[Property.PHYSICAL_MELEE_DAMAGE]?.any { it.name == BRUTAL_CRITICAL } == true
// for damage roll, previous attack roll was critical // for attack roll, can crit on an 19 or 20
val Map<Property, List<Alteration.Status>>.isCritical: Boolean val Map<Property, List<Alteration.Status>>.isImprovedCritical: Boolean
get() = this[Property.PHYSICAL_MELEE_DAMAGE]?.any { it.name == "Critique" } == true get() = this[Property.PHYSICAL_MELEE_ATTACK]?.any { it.name == IMPROVED_CRITICAL } == true ||
this[Property.PHYSICAL_RANGE_ATTACK]?.any { it.name == IMPROVED_CRITICAL } == true
private const val CRITIQUE = "Critique"
private const val SAVAGE_ATTACK = "Attaques sauvages"
private const val BRUTAL_CRITICAL = "Critique brutal"
private const val IMPROVED_CRITICAL = "Critique amélioré"

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -6,10 +6,6 @@ pluginManagement {
} }
} }
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.6.0"
}
dependencyResolutionManagement { dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories { repositories {