Update the map feature.
This commit is contained in:
		
							parent
							
								
									86b2054f0a
								
							
						
					
					
						commit
						53969a4174
					
				
					 122 changed files with 775 additions and 785 deletions
				
			
		| 
						 | 
				
			
			@ -6,18 +6,18 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.compose.runtime.setValue
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.EquipmentRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.InventoryRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LocationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.QuestRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.InventoryRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LocationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.QuestRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.error.FetchErrorUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.error.FetchErrorUio.Structure.Type
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ class LauncherViewModel @Inject constructor(
 | 
			
		|||
            }
 | 
			
		||||
            val location = async {
 | 
			
		||||
                try {
 | 
			
		||||
                    locationRepository.fetchLocation()
 | 
			
		||||
                    locationRepository.fetchMap()
 | 
			
		||||
                } catch (exception: Exception) {
 | 
			
		||||
                    Log.e(TAG, exception.message, exception)
 | 
			
		||||
                    _error.emit(FetchErrorUio.Structure(type = Type.LOCATION))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding
 | 
			
		|||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.shape.CutCornerShape
 | 
			
		||||
import androidx.compose.foundation.shape.RoundedCornerShape
 | 
			
		||||
import androidx.compose.material3.ButtonDefaults
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Scaffold
 | 
			
		||||
import androidx.compose.material3.Snackbar
 | 
			
		||||
| 
						 | 
				
			
			@ -20,9 +21,10 @@ import androidx.compose.material3.SnackbarHost
 | 
			
		|||
import androidx.compose.material3.SnackbarHostState
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.material3.TextButton
 | 
			
		||||
import androidx.compose.material3.surfaceColorAtElevation
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.CompositionLocalProvider
 | 
			
		||||
import androidx.compose.runtime.LaunchedEffect
 | 
			
		||||
import androidx.compose.runtime.compositionLocalOf
 | 
			
		||||
import androidx.compose.runtime.derivedStateOf
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +44,8 @@ import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		|||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
			
		||||
import dagger.hilt.android.AndroidEntryPoint
 | 
			
		||||
 | 
			
		||||
val NO_WINDOW_INSETS = WindowInsets(0, 0, 0, 0)
 | 
			
		||||
 | 
			
		||||
val LocalActivity = staticCompositionLocalOf<Activity> {
 | 
			
		||||
    error("Activity not available")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +55,6 @@ val LocalSnack = staticCompositionLocalOf<SnackbarHostState> {
 | 
			
		|||
val LocalRollOverlay = compositionLocalOf<BlurredRollOverlayHostState> {
 | 
			
		||||
    error("LocalRollOverlay not yet ready")
 | 
			
		||||
}
 | 
			
		||||
val NO_WINDOW_INSETS = WindowInsets(0, 0, 0, 0)
 | 
			
		||||
 | 
			
		||||
@AndroidEntryPoint
 | 
			
		||||
class MainActivity : ComponentActivity() {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +116,15 @@ class MainActivity : ComponentActivity() {
 | 
			
		|||
                                modifier = Modifier.navigationBarsPadding(),
 | 
			
		||||
                                hostState = LocalSnack.current,
 | 
			
		||||
                            ) {
 | 
			
		||||
                                val actionComposable: (@Composable () -> Unit)? =
 | 
			
		||||
                                    it.visuals.actionLabel?.let { actionLabel ->
 | 
			
		||||
                                        @Composable {
 | 
			
		||||
                                            TextButton(
 | 
			
		||||
                                                onClick = { it.performAction() },
 | 
			
		||||
                                                content = { Text(actionLabel) }
 | 
			
		||||
                                            )
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                Snackbar(
 | 
			
		||||
                                    modifier = Modifier
 | 
			
		||||
                                        .padding(horizontal = 16.dp)
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +135,7 @@ class MainActivity : ComponentActivity() {
 | 
			
		|||
                                    containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
 | 
			
		||||
                                        elevation = elevation.value
 | 
			
		||||
                                    ),
 | 
			
		||||
                                    action = actionComposable,
 | 
			
		||||
                                    content = {
 | 
			
		||||
                                        Text(
 | 
			
		||||
                                            modifier = Modifier.padding(vertical = 8.dp),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,19 +3,19 @@ package com.pixelized.rplexicon.business
 | 
			
		|||
import android.app.Application
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.model.Throw
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Throw
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.icon
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Alteration(
 | 
			
		||||
    val name: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class AssignedSpell(
 | 
			
		||||
    val hit: Throw?,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Attack(
 | 
			
		||||
    val title: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class CharacterSheet(
 | 
			
		||||
    val name: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Keep
 | 
			
		||||
import com.google.firebase.database.IgnoreExtraProperties
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Description(
 | 
			
		||||
    val name: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
sealed class DiceThrow(val character: String) {
 | 
			
		||||
    class Initiative(character: String) : DiceThrow(character)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Equipment(
 | 
			
		||||
    var silhouette: String? = null,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Inventory(
 | 
			
		||||
    val items: List<Item>,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.compose.runtime.Stable
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
 | 
			
		||||
data class Location(
 | 
			
		||||
    val id: String,
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val uri: Uri?,
 | 
			
		||||
    val description: String?,
 | 
			
		||||
    val child: List<Pair<Offset, Location>> = emptyList(),
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class ObjectAction(
 | 
			
		||||
    val name: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
enum class Property(val key: String) {
 | 
			
		||||
    PROFICIENCY("Maîtrise"),
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.compose.runtime.Stable
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Roll(
 | 
			
		||||
    val character: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Skill(
 | 
			
		||||
    val name: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
data class Spell(
 | 
			
		||||
    val name: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
package com.pixelized.rplexicon.data.model
 | 
			
		||||
 | 
			
		||||
class Throw(
 | 
			
		||||
    val amount: Int,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.roll.ThrowParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +19,7 @@ class AttackParser @Inject constructor(
 | 
			
		|||
        // declare helper method to parse String
 | 
			
		||||
        val actions = hashMapOf<String, MutableList<Attack>>()
 | 
			
		||||
 | 
			
		||||
        value.forEachRow { index, row ->
 | 
			
		||||
        value.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
data class Column(
 | 
			
		||||
    val names: List<String>,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Description
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Description
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ class DescriptionParser @Inject constructor() {
 | 
			
		|||
    fun parse(sheet: ValueRange): Map<String, Description> = parserScope {
 | 
			
		||||
        val descriptions = hashMapOf<String, Description>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class GenderParser @Inject constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ class LexiconParser @Inject constructor(
 | 
			
		|||
        var id = 0
 | 
			
		||||
        val lexicons = mutableListOf<Lexicon>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,8 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.ObjectAction
 | 
			
		||||
import com.pixelized.rplexicon.data.model.ObjectAction
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.roll.ThrowParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +13,7 @@ class ObjectActionParser @Inject constructor(
 | 
			
		|||
    fun parse(data: ValueRange): Map<String, List<ObjectAction>> = parserScope {
 | 
			
		||||
        val objects = hashMapOf<String, MutableList<ObjectAction>>()
 | 
			
		||||
 | 
			
		||||
        data.forEachRow { index, row ->
 | 
			
		||||
        data.forEachRowIndexed { index, row ->
 | 
			
		||||
            when {
 | 
			
		||||
                index == 0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.toUriOrNull
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.QuestEntry
 | 
			
		||||
import com.pixelized.rplexicon.data.model.QuestEntry
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class QuestParser @Inject constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ class QuestParser @Inject constructor(
 | 
			
		|||
    fun parse(sheet: ValueRange): List<QuestEntry> = parserScope {
 | 
			
		||||
        val quest = mutableListOf<QuestEntry>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, item ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, item ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = item, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class RaceParser @Inject constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.core.net.toUri
 | 
			
		||||
| 
						 | 
				
			
			@ -23,11 +23,38 @@ class SheetParserScope<T> {
 | 
			
		|||
        return this.block()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun ValueRange.forEachRow(block: (index: Int, row: List<*>) -> Unit) {
 | 
			
		||||
    inline fun ValueRange.forEachRow(
 | 
			
		||||
        crossinline block: (row: List<*>) -> Unit,
 | 
			
		||||
    ) = forEachRowIndexed(
 | 
			
		||||
        block = { _, row -> block(row) }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    fun ValueRange.forEachRowIndexed(block: (index: Int, row: List<*>) -> Unit) {
 | 
			
		||||
        val sheet = this.values.sheet()
 | 
			
		||||
        sheet?.mapNotNull { it as? List<*> }?.forEachIndexed(block)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline fun ValueRange.forEachDataLine(
 | 
			
		||||
        columns: List<Column>,
 | 
			
		||||
        crossinline block: (row: List<*>) -> Unit
 | 
			
		||||
    ) = forEachDataLineIndexed(
 | 
			
		||||
        columns = columns,
 | 
			
		||||
        block = { _, line -> block(line) },
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    fun ValueRange.forEachDataLineIndexed(
 | 
			
		||||
        columns: List<Column>,
 | 
			
		||||
        block: (index: Int, row: List<*>) -> Unit
 | 
			
		||||
    ) {
 | 
			
		||||
        val sheet = this.values.sheet()
 | 
			
		||||
        sheet?.mapNotNull { it as? List<*> }?.forEachIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = columns)
 | 
			
		||||
                else -> block(index - 1, row)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun Any?.toItem(): String? =
 | 
			
		||||
        this.toString().takeIf { it.isNotBlank() }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +64,11 @@ class SheetParserScope<T> {
 | 
			
		|||
    fun List<*>.parseInt(column: Column): Int? =
 | 
			
		||||
        parse(column)?.toIntOrNull()
 | 
			
		||||
 | 
			
		||||
    fun List<*>.parseFloat(column: Column): Float? =
 | 
			
		||||
        parse(column = column)
 | 
			
		||||
            ?.replace(oldValue = ",", newValue = ".")
 | 
			
		||||
            ?.toFloatOrNull()
 | 
			
		||||
 | 
			
		||||
    fun List<*>.parseBool(column: Column): Boolean? =
 | 
			
		||||
        parse(column)?.equals("TRUE", ignoreCase = true)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,8 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.roll.ThrowParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +13,7 @@ class SkillParser @Inject constructor(
 | 
			
		|||
    fun parse(sheet: ValueRange): Map<String, List<Skill>> = parserScope {
 | 
			
		||||
        val skills = hashMapOf<String, MutableList<Skill>>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,13 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.alteration
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.alteration
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.roll.DiceParser
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.roll.FlatValueParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.roll.DiceParser
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.roll.FlatValueParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ class AlterationParser @Inject constructor(
 | 
			
		|||
        val properties = Property.values()
 | 
			
		||||
        val alterations = hashMapOf<String, MutableList<Alteration>>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS + characterSheets.map { column(it.name) })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.alteration
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.alteration
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ class AssignedAlterationParser @Inject constructor() {
 | 
			
		|||
    ): Map<String, List<String>> = parserScope {
 | 
			
		||||
        val status = hashMapOf<String, MutableList<String>>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = characterNames.map { column(it) })
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.alteration
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.alteration
 | 
			
		||||
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class PropertyParser @Inject constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.inventory
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.inventory
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Equipment
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.parserScope
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ class EquipmentParser @Inject constructor() {
 | 
			
		|||
        lateinit var characters: List<String>
 | 
			
		||||
        val equipments = hashMapOf<String, Equipment.Builder>()
 | 
			
		||||
 | 
			
		||||
        data.forEachRow { index, row ->
 | 
			
		||||
        data.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                // ignore the first column
 | 
			
		||||
                0 -> characters = row.drop(1).map { it.toString() }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.inventory
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.inventory
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Inventory
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Inventory
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ class InventoryParser @Inject constructor() {
 | 
			
		|||
    fun parse(sheet: ValueRange): Map<String, Inventory> = parserScope {
 | 
			
		||||
        val inventories = hashMapOf<String, Inventory.Builder>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when {
 | 
			
		||||
                index == 0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
package com.pixelized.rplexicon.data.parser.map
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Location
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class LocationParser @Inject constructor(
 | 
			
		||||
    private val mapParser: MapParser,
 | 
			
		||||
    private val worldParser: WorldParser,
 | 
			
		||||
) {
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    fun parse(mapSheet: ValueRange, worldSheet: ValueRange): List<Location> {
 | 
			
		||||
        val localMaps = mapParser.parse(sheet = mapSheet)
 | 
			
		||||
        val localWorld = worldParser.parse(sheet = worldSheet)
 | 
			
		||||
 | 
			
		||||
        val mapHash = localMaps
 | 
			
		||||
            .map { localMap ->
 | 
			
		||||
                Location(
 | 
			
		||||
                    id = localMap.name,
 | 
			
		||||
                    name = localMap.name,
 | 
			
		||||
                    uri = localMap.uri,
 | 
			
		||||
                    description = localMap.description,
 | 
			
		||||
                    child = emptyList(),
 | 
			
		||||
                )
 | 
			
		||||
            }.associateBy { it.name }
 | 
			
		||||
 | 
			
		||||
        val maps = mapHash.map { entry ->
 | 
			
		||||
            entry.value.copy(
 | 
			
		||||
                child = localWorld
 | 
			
		||||
                    .filter { it.parent == entry.key }
 | 
			
		||||
                    .mapNotNull { world -> mapHash[world.child]?.let { map -> world.position to map } }
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return maps
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
package com.pixelized.rplexicon.data.parser.map
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class MapParser @Inject constructor() {
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    fun parse(sheet: ValueRange): List<MapDto> = parserScope {
 | 
			
		||||
        val maps = mutableListOf<MapDto>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachDataLine(columns = COLUMNS) {
 | 
			
		||||
            val name = it.parse(column = NAME)
 | 
			
		||||
            val uri = it.parseUri(column = URI)
 | 
			
		||||
            val description = it.parse(column = DESCRIPTION)
 | 
			
		||||
            if (name != null) {
 | 
			
		||||
                val map = MapDto(
 | 
			
		||||
                    name = name,
 | 
			
		||||
                    uri = uri,
 | 
			
		||||
                    description = description,
 | 
			
		||||
                )
 | 
			
		||||
                maps.add(map)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return@parserScope maps
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data class MapDto(
 | 
			
		||||
        val name: String,
 | 
			
		||||
        val uri: Uri?,
 | 
			
		||||
        val description: String?,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val NAME = column("Nom")
 | 
			
		||||
        private val URI = column("Carte")
 | 
			
		||||
        private val DESCRIPTION = column("Description")
 | 
			
		||||
        private val COLUMNS get() = listOf(NAME, URI, DESCRIPTION)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
package com.pixelized.rplexicon.data.parser.map
 | 
			
		||||
 | 
			
		||||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class WorldParser @Inject constructor() {
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    fun parse(sheet: ValueRange): List<WorldDto> = parserScope {
 | 
			
		||||
        val worlds = mutableListOf<WorldDto>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachDataLine(columns = COLUMNS) { line ->
 | 
			
		||||
            val parent = line.parse(column = PARENT)
 | 
			
		||||
            val child = line.parse(column = CHILD)
 | 
			
		||||
            val x = line.parseFloat(column = X)
 | 
			
		||||
            val y = line.parseFloat(column = Y)
 | 
			
		||||
            if (child != null && x != null && y != null) {
 | 
			
		||||
                val world = WorldDto(
 | 
			
		||||
                    parent = parent,
 | 
			
		||||
                    child = child,
 | 
			
		||||
                    position = Offset(x = x, y = y),
 | 
			
		||||
                )
 | 
			
		||||
                worlds.add(world)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return@parserScope worlds
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data class WorldDto(
 | 
			
		||||
        val parent: String?,
 | 
			
		||||
        val child: String,
 | 
			
		||||
        val position: Offset,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val PARENT = column("Parent")
 | 
			
		||||
        private val CHILD = column("Enfant")
 | 
			
		||||
        private val X = column("X")
 | 
			
		||||
        private val Y = column("Y")
 | 
			
		||||
        private val COLUMNS get() = listOf(PARENT, CHILD, X, Y)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.roll
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.roll
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Roll
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Roll
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class DiceParser @Inject constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.roll
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.roll
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Roll
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Roll
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class FlatValueParser @Inject constructor() {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.roll
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.roll
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.alteration.PropertyParser
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.alteration.PropertyParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class ModifierParser @Inject constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,6 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.roll
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Throw
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.roll.DiceParser
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.roll.FlatValueParser
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.roll.ModifierParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Throw
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class ThrowParser @Inject constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.spell
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.spell
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.ThrowParser
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.roll.ThrowParser
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ class AssignedSpellParser @Inject constructor(
 | 
			
		|||
    ): Map<String, List<AssignedSpell>> = parserScope {
 | 
			
		||||
        val spellsBook = spells.associateBy { it.name }
 | 
			
		||||
        val assignedSpells = hashMapOf<String, MutableList<AssignedSpell>>()
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser.spell
 | 
			
		||||
package com.pixelized.rplexicon.data.parser.spell
 | 
			
		||||
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.column
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.parserScope
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ class SpellBookParser @Inject constructor() {
 | 
			
		|||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    fun parse(sheet: ValueRange): List<Spell> = parserScope {
 | 
			
		||||
        val spells = mutableListOf<Spell>()
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
        sheet.forEachRowIndexed { index, row ->
 | 
			
		||||
            when {
 | 
			
		||||
                index == 0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository
 | 
			
		||||
package com.pixelized.rplexicon.data.repository
 | 
			
		||||
 | 
			
		||||
import android.app.Application
 | 
			
		||||
import com.google.api.client.extensions.android.http.AndroidHttp
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,12 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data
 | 
			
		||||
package com.pixelized.rplexicon.data.repository
 | 
			
		||||
 | 
			
		||||
object LexiconBinder {
 | 
			
		||||
    const val ID = "1oL9Nu5y37BPEbKxHre4TN9o8nrgy2JQoON4RRkdAHMs"
 | 
			
		||||
 | 
			
		||||
    const val LEXICON = "Lexique"
 | 
			
		||||
    const val QUEST_JOURNAL = "Journal de quêtes"
 | 
			
		||||
    const val MAP = "Lieux"
 | 
			
		||||
    const val MARQUEE = "Points d'intérêt"
 | 
			
		||||
    const val MAP = "Cartes"
 | 
			
		||||
    const val WORLD = "Monde"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object CharacterBinder {
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.authentication
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.authentication
 | 
			
		||||
 | 
			
		||||
import android.accounts.Account
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import androidx.compose.runtime.State
 | 
			
		||||
import androidx.compose.runtime.derivedStateOf
 | 
			
		||||
import androidx.compose.runtime.getValue
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import com.google.android.gms.auth.api.identity.SignInCredential
 | 
			
		||||
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
 | 
			
		||||
import com.google.api.client.util.ExponentialBackOff
 | 
			
		||||
import com.google.api.services.sheets.v4.SheetsScopes
 | 
			
		||||
import dagger.hilt.android.qualifiers.ApplicationContext
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
import javax.inject.Singleton
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.authentication
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.authentication
 | 
			
		||||
 | 
			
		||||
import android.app.Application
 | 
			
		||||
import android.util.Log
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ import com.google.firebase.database.ValueEventListener
 | 
			
		|||
import com.google.firebase.database.ktx.database
 | 
			
		||||
import com.google.firebase.ktx.Firebase
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheetFire
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
			
		||||
import kotlinx.coroutines.cancel
 | 
			
		||||
import kotlinx.coroutines.channels.awaitClose
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.AttackParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.AttackParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.alteration.AlterationParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.alteration.AlterationParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.CharacterSheetParser
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.CharacterSheetParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Description
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.DescriptionParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Description
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.DescriptionParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Equipment
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.inventory.EquipmentParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Equipment
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.inventory.EquipmentParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Inventory
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.inventory.InventoryParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Inventory
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.inventory.InventoryParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.ObjectAction
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.ObjectActionParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.ObjectAction
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.ObjectActionParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.SkillParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.SkillParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.character
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.character
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.spell.AssignedSpellParser
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.spell.SpellBookParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.CharacterBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.spell.AssignedSpellParser
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.spell.SpellBookParser
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.async
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.lexicon
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.lexicon
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.LexiconParser
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.LexiconBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.LexiconParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.LexiconBinder
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
package com.pixelized.rplexicon.data.repository.lexicon
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Location
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.map.LocationParser
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.LexiconBinder
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.async
 | 
			
		||||
import kotlinx.coroutines.awaitAll
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
import javax.inject.Singleton
 | 
			
		||||
 | 
			
		||||
@Singleton
 | 
			
		||||
class LocationRepository @Inject constructor(
 | 
			
		||||
    private val googleRepository: GoogleSheetServiceRepository,
 | 
			
		||||
    private val parser: LocationParser,
 | 
			
		||||
) {
 | 
			
		||||
    private val _data = MutableStateFlow<List<Location>>(emptyList())
 | 
			
		||||
    val data: StateFlow<List<Location>> get() = _data
 | 
			
		||||
 | 
			
		||||
    var lastSuccessFullUpdate: Update = Update.INITIAL
 | 
			
		||||
        private set
 | 
			
		||||
 | 
			
		||||
    fun find(id: String): Location? {
 | 
			
		||||
        return _data.value.firstOrNull { it.id == id }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class, Exception::class)
 | 
			
		||||
    suspend fun fetchMap() {
 | 
			
		||||
        googleRepository.fetch { sheets ->
 | 
			
		||||
            val (map, world) = awaitAll(
 | 
			
		||||
                async { sheets.get(LexiconBinder.ID, LexiconBinder.MAP).execute() },
 | 
			
		||||
                async { sheets.get(LexiconBinder.ID, LexiconBinder.WORLD).execute() },
 | 
			
		||||
            )
 | 
			
		||||
            val data = parser.parse(mapSheet = map, worldSheet = world)
 | 
			
		||||
            _data.emit(data)
 | 
			
		||||
            lastSuccessFullUpdate = Update.currentTime()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val WORLD_SHEET_URL =
 | 
			
		||||
            "https://docs.google.com/spreadsheets/d/${LexiconBinder.ID}/edit#gid=1943877267"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.lexicon
 | 
			
		||||
package com.pixelized.rplexicon.data.repository.lexicon
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.QuestParser
 | 
			
		||||
import com.pixelized.rplexicon.model.Quest
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.LexiconBinder
 | 
			
		||||
import com.pixelized.rplexicon.data.parser.QuestParser
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Quest
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.LexiconBinder
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
| 
						 | 
				
			
			@ -1,22 +0,0 @@
 | 
			
		|||
package com.pixelized.rplexicon.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.compose.runtime.Stable
 | 
			
		||||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
data class Location(
 | 
			
		||||
    val id: Int,
 | 
			
		||||
    val sheetIndex: Int,
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val uri: Uri,
 | 
			
		||||
    val marquees: List<Marquee>,
 | 
			
		||||
) {
 | 
			
		||||
    @Stable
 | 
			
		||||
    data class Marquee(
 | 
			
		||||
        val map: String,
 | 
			
		||||
        val name: String?,
 | 
			
		||||
        val position: Offset,
 | 
			
		||||
        val description: String?,
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,70 +0,0 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.data.lexicon
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.LocationParser
 | 
			
		||||
import com.pixelized.rplexicon.repository.parser.MarqueeParser
 | 
			
		||||
import com.pixelized.rplexicon.model.Location
 | 
			
		||||
import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.LexiconBinder
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.Update
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import kotlinx.coroutines.async
 | 
			
		||||
import kotlinx.coroutines.awaitAll
 | 
			
		||||
import kotlinx.coroutines.flow.MutableStateFlow
 | 
			
		||||
import kotlinx.coroutines.flow.StateFlow
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
import javax.inject.Singleton
 | 
			
		||||
 | 
			
		||||
@Singleton
 | 
			
		||||
class LocationRepository @Inject constructor(
 | 
			
		||||
    private val googleRepository: GoogleSheetServiceRepository,
 | 
			
		||||
    private val locationParser: LocationParser,
 | 
			
		||||
    private val marqueeParser: MarqueeParser,
 | 
			
		||||
) {
 | 
			
		||||
    private val _data = MutableStateFlow<List<Location>>(emptyList())
 | 
			
		||||
    val data: StateFlow<List<Location>> get() = _data
 | 
			
		||||
 | 
			
		||||
    var lastSuccessFullUpdate: Update = Update.INITIAL
 | 
			
		||||
        private set
 | 
			
		||||
 | 
			
		||||
    fun findId(name: String?): Int? {
 | 
			
		||||
        return name?.let { _data.value.firstOrNull { item -> item.name == it }?.id }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class, Exception::class)
 | 
			
		||||
    suspend fun fetchLocation() {
 | 
			
		||||
        googleRepository.fetch { sheet ->
 | 
			
		||||
            val (map, marquee) = awaitAll(
 | 
			
		||||
                async { sheet.get(LexiconBinder.ID, LexiconBinder.MAP).execute() },
 | 
			
		||||
                async { sheet.get(LexiconBinder.ID, LexiconBinder.MARQUEE).execute() },
 | 
			
		||||
            )
 | 
			
		||||
            updateData(map = map, marquee = marquee)
 | 
			
		||||
            lastSuccessFullUpdate = Update.currentTime()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    private suspend fun updateData(map: ValueRange, marquee: ValueRange) {
 | 
			
		||||
        val marquees = marqueeParser
 | 
			
		||||
            .parse(sheet = marquee)
 | 
			
		||||
            .groupBy { it.map }
 | 
			
		||||
 | 
			
		||||
        val maps = locationParser
 | 
			
		||||
            .parse(sheet = map)
 | 
			
		||||
            .map {
 | 
			
		||||
                val associatedMarquees = marquees[it.name]
 | 
			
		||||
                if (associatedMarquees != null) {
 | 
			
		||||
                    it.copy(marquees = associatedMarquees)
 | 
			
		||||
                } else {
 | 
			
		||||
                    it
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        _data.emit(maps)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val SHEET_URL =
 | 
			
		||||
            "https://docs.google.com/spreadsheets/d/${LexiconBinder.ID}/edit#gid=1985553511"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,43 +0,0 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Location
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class LocationParser @Inject constructor() {
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    fun parse(sheet: ValueRange): List<Location> = parserScope {
 | 
			
		||||
        val locations = mutableListOf<Location>()
 | 
			
		||||
        var id = 0
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, row ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = row, columns = COLUMNS)
 | 
			
		||||
                else -> {
 | 
			
		||||
                    val name = row.parse(column = NAME)
 | 
			
		||||
                    val uri = row.parseUri(column = MAP)
 | 
			
		||||
                    if (name != null && uri != null) {
 | 
			
		||||
                        val location = Location(
 | 
			
		||||
                            id = id++,
 | 
			
		||||
                            sheetIndex = index,
 | 
			
		||||
                            name = name,
 | 
			
		||||
                            uri = uri,
 | 
			
		||||
                            marquees = emptyList(),
 | 
			
		||||
                        )
 | 
			
		||||
                        locations.add(location)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return@parserScope locations
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val NAME = column("Nom")
 | 
			
		||||
        private val MAP = column("Carte")
 | 
			
		||||
        private val COLUMNS get() = listOf(NAME, MAP)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,54 +0,0 @@
 | 
			
		|||
package com.pixelized.rplexicon.repository.parser
 | 
			
		||||
 | 
			
		||||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
import com.google.api.services.sheets.v4.model.ValueRange
 | 
			
		||||
import com.pixelized.rplexicon.model.Location
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class MarqueeParser @Inject constructor() {
 | 
			
		||||
 | 
			
		||||
    @Throws(IncompatibleSheetStructure::class)
 | 
			
		||||
    fun parse(sheet: ValueRange): List<Location.Marquee> = parserScope {
 | 
			
		||||
        val marquees = mutableListOf<Location.Marquee>()
 | 
			
		||||
 | 
			
		||||
        sheet.forEachRow { index, item ->
 | 
			
		||||
            when (index) {
 | 
			
		||||
                0 -> updateStructure(row = item, columns = COLUMNS)
 | 
			
		||||
 | 
			
		||||
                else -> {
 | 
			
		||||
                    val map = item.parse(column = MAP)
 | 
			
		||||
                    val x = item.parse(column = X)
 | 
			
		||||
                        ?.replace(oldValue = ",", newValue = ".")
 | 
			
		||||
                        ?.toFloatOrNull()
 | 
			
		||||
                    val y = item.parse(column = Y)
 | 
			
		||||
                        ?.replace(oldValue = ",", newValue = ".")
 | 
			
		||||
                        ?.toFloatOrNull()
 | 
			
		||||
                    if (map != null) {
 | 
			
		||||
                        val marquee = Location.Marquee(
 | 
			
		||||
                            map = map,
 | 
			
		||||
                            name = item.parse(column = NAME),
 | 
			
		||||
                            position = when {
 | 
			
		||||
                                x != null && y != null -> Offset(x, y)
 | 
			
		||||
                                else -> Offset.Unspecified
 | 
			
		||||
                            },
 | 
			
		||||
                            description = item.parse(column = DESCRIPTION),
 | 
			
		||||
                        )
 | 
			
		||||
                        marquees.add(marquee)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return@parserScope marquees
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val MAP = column("Carte")
 | 
			
		||||
        private val NAME = column("Nom")
 | 
			
		||||
        private val X = column("X")
 | 
			
		||||
        private val Y = column("Y")
 | 
			
		||||
        private val DESCRIPTION = column("Description")
 | 
			
		||||
        private val COLUMNS get() = listOf(MAP, NAME, X, Y, DESCRIPTION)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,6 @@ import androidx.compose.animation.ExperimentalAnimationApi
 | 
			
		|||
import androidx.compose.animation.fadeIn
 | 
			
		||||
import androidx.compose.animation.fadeOut
 | 
			
		||||
import androidx.compose.animation.togetherWith
 | 
			
		||||
import androidx.compose.animation.with
 | 
			
		||||
import androidx.compose.foundation.layout.Box
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +39,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.composable.stringResource
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ import androidx.navigation.NavHostController
 | 
			
		|||
import androidx.navigation.NavOptionsBuilder
 | 
			
		||||
import androidx.navigation.NavType
 | 
			
		||||
import androidx.navigation.navArgument
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.NavigationAnimation
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.animatedComposable
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.lexicon.detail.LexiconDetailScreen
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ val LOCATION_DETAIL_ROUTE = ROUTE +
 | 
			
		|||
@Stable
 | 
			
		||||
@Immutable
 | 
			
		||||
data class LocationDetailArgument(
 | 
			
		||||
    val id: Int,
 | 
			
		||||
    val id: String,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
val SavedStateHandle.locationDetailArgument: LocationDetailArgument
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ fun NavGraphBuilder.composableLocationDetail() {
 | 
			
		|||
        route = LOCATION_DETAIL_ROUTE,
 | 
			
		||||
        arguments = listOf(
 | 
			
		||||
            navArgument(name = ARG_ID) {
 | 
			
		||||
                type = NavType.IntType
 | 
			
		||||
                type = NavType.StringType
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
        animation = NavigationAnimation.Push,
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ fun NavGraphBuilder.composableLocationDetail() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
fun NavHostController.navigateToLocationDetail(
 | 
			
		||||
    id: Int,
 | 
			
		||||
    id: String,
 | 
			
		||||
    option: NavOptionsBuilder.() -> Unit = {},
 | 
			
		||||
) {
 | 
			
		||||
    val route = ROUTE +
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ import com.google.firebase.auth.GoogleAuthProvider
 | 
			
		|||
import com.google.firebase.auth.ktx.auth
 | 
			
		||||
import com.google.firebase.ktx.Firebase
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.repository.authentication.AuthenticationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.authentication.AuthenticationRepository
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,16 +6,16 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.EquipmentRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.InventoryRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.InventoryRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.error.FetchErrorUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.error.FetchErrorUio.Structure.Type
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.common.DiceButton
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.common.DiceButton
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.local.icon
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ import androidx.compose.runtime.State
 | 
			
		|||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.compose.runtime.remember
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Spell
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.local.icon
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.character.factory
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AttackUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.icon
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.modifier
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.character.factory
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Alteration
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.ProficiencyUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.character.factory
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.Inventory
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Inventory
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.character.factory
 | 
			
		||||
 | 
			
		||||
import com.pixelized.rplexicon.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.icon
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.local.icon
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,12 +6,12 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.AndroidViewModel
 | 
			
		||||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Attack
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AttackUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.factory.AttackUioFactory
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,11 +7,11 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.edit.HpPointDialogUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,9 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.ObjectItemUio
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,15 +6,15 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.AndroidViewModel
 | 
			
		||||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheetFire
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Skill
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SkillRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.edit.SkillEditDialogUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,15 +7,15 @@ import androidx.lifecycle.AndroidViewModel
 | 
			
		|||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.model.CharacterSheetFire
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.model.Throw
 | 
			
		||||
import com.pixelized.rplexicon.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
			
		||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Property
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Throw
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.SpellRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.edit.SpellEditDialogUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,8 +7,8 @@ import androidx.lifecycle.AndroidViewModel
 | 
			
		|||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItemUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,9 +7,9 @@ import androidx.lifecycle.AndroidViewModel
 | 
			
		|||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.EquipmentRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.InventoryRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.InventoryRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.EquipmentItemUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,9 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.AndroidViewModel
 | 
			
		||||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.ProficiencyUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ import androidx.compose.ui.unit.Dp
 | 
			
		|||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import androidx.hilt.navigation.compose.hiltViewModel
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.AsyncImage
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.BackgroundImage
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.FullScreenImageHandler
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ import androidx.compose.runtime.State
 | 
			
		|||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.lexiconDetailArgument
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,9 @@ import androidx.compose.runtime.mutableStateOf
 | 
			
		|||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.error.FetchErrorUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
 | 
			
		|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.composable.stringResource
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.annotatedSpan
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ import androidx.compose.ui.unit.dp
 | 
			
		|||
import androidx.hilt.navigation.compose.hiltViewModel
 | 
			
		||||
import com.pixelized.rplexicon.NO_WINDOW_INSETS
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.CollapsingHeader
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.form.DropDownField
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.form.DropDownFieldUio
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,10 +4,10 @@ import androidx.compose.runtime.derivedStateOf
 | 
			
		|||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon.Gender
 | 
			
		||||
import com.pixelized.rplexicon.model.Lexicon.Race
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon.Gender
 | 
			
		||||
import com.pixelized.rplexicon.data.model.Lexicon.Race
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LexiconRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.form.DropDownFieldUio
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.form.TextFieldUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.composable.stringResource
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ fun FantasyMap(
 | 
			
		|||
    contentScale: ContentScale = ContentScale.Fit,
 | 
			
		||||
    items: State<List<MarqueeUio>>,
 | 
			
		||||
    highlight: State<Offset>,
 | 
			
		||||
    selectedItem: State<Int>,
 | 
			
		||||
    selectedItem: State<Int?>,
 | 
			
		||||
    onMarquee: (MarqueeUio) -> Unit,
 | 
			
		||||
    onTap: (Offset) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +67,10 @@ fun FantasyMap(
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    LaunchedEffect(key1 = "CenterOnMarquee:${selectedItem.value}") {
 | 
			
		||||
        items.value.getOrNull(selectedItem.value)?.position
 | 
			
		||||
            ?.let { state.pan(state.computeMarqueeOffset(it)) }
 | 
			
		||||
        selectedItem.value?.let {
 | 
			
		||||
            items.value.getOrNull(it)?.position
 | 
			
		||||
                ?.let { state.pan(state.computeMarqueeOffset(it)) }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Box(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,22 +2,24 @@ package com.pixelized.rplexicon.ui.screens.location.detail
 | 
			
		|||
 | 
			
		||||
import android.content.res.Configuration
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.compose.foundation.ExperimentalFoundationApi
 | 
			
		||||
import androidx.compose.animation.AnimatedVisibility
 | 
			
		||||
import androidx.compose.animation.expandVertically
 | 
			
		||||
import androidx.compose.animation.fadeIn
 | 
			
		||||
import androidx.compose.animation.fadeOut
 | 
			
		||||
import androidx.compose.animation.shrinkVertically
 | 
			
		||||
import androidx.compose.foundation.ScrollState
 | 
			
		||||
import androidx.compose.foundation.gestures.scrollBy
 | 
			
		||||
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.BoxWithConstraints
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.PaddingValues
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxSize
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.height
 | 
			
		||||
import androidx.compose.foundation.layout.heightIn
 | 
			
		||||
import androidx.compose.foundation.layout.offset
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.pager.HorizontalPager
 | 
			
		||||
import androidx.compose.foundation.pager.PagerState
 | 
			
		||||
import androidx.compose.foundation.pager.rememberPagerState
 | 
			
		||||
import androidx.compose.foundation.rememberScrollState
 | 
			
		||||
import androidx.compose.foundation.verticalScroll
 | 
			
		||||
import androidx.compose.material3.ExperimentalMaterial3Api
 | 
			
		||||
| 
						 | 
				
			
			@ -33,8 +35,8 @@ import androidx.compose.material3.SnackbarResult
 | 
			
		|||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
import androidx.compose.material3.TopAppBar
 | 
			
		||||
import androidx.compose.material3.minimumInteractiveComponentSize
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.LaunchedEffect
 | 
			
		||||
import androidx.compose.runtime.Stable
 | 
			
		||||
import androidx.compose.runtime.State
 | 
			
		||||
import androidx.compose.runtime.derivedStateOf
 | 
			
		||||
| 
						 | 
				
			
			@ -49,10 +51,8 @@ import androidx.compose.ui.draw.shadow
 | 
			
		|||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
import androidx.compose.ui.graphics.RectangleShape
 | 
			
		||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 | 
			
		||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
 | 
			
		||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
 | 
			
		||||
import androidx.compose.ui.layout.ContentScale
 | 
			
		||||
import androidx.compose.ui.layout.onSizeChanged
 | 
			
		||||
import androidx.compose.ui.platform.LocalContext
 | 
			
		||||
import androidx.compose.ui.platform.LocalDensity
 | 
			
		||||
import androidx.compose.ui.platform.LocalUriHandler
 | 
			
		||||
| 
						 | 
				
			
			@ -66,24 +66,24 @@ import androidx.compose.ui.unit.dp
 | 
			
		|||
import androidx.hilt.navigation.compose.hiltViewModel
 | 
			
		||||
import com.pixelized.rplexicon.LocalSnack
 | 
			
		||||
import com.pixelized.rplexicon.R
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.Handle
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.rememberBackgroundGradient
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLocationDetail
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.annotateWithDropCap
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
 | 
			
		||||
import kotlinx.coroutines.CoroutineScope
 | 
			
		||||
import kotlinx.coroutines.Job
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import kotlin.math.max
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
data class LocationDetailUio(
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val map: Uri,
 | 
			
		||||
    val map: Uri?,
 | 
			
		||||
    val description: String?,
 | 
			
		||||
    val marquees: List<MarqueeUio>,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@OptIn(ExperimentalFoundationApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
fun LocationDetail(
 | 
			
		||||
    viewModel: LocationDetailViewModel = hiltViewModel()
 | 
			
		||||
| 
						 | 
				
			
			@ -95,40 +95,30 @@ fun LocationDetail(
 | 
			
		|||
 | 
			
		||||
    val scope = rememberCoroutineScope()
 | 
			
		||||
    val scroll = rememberScrollState()
 | 
			
		||||
    val pager = rememberPagerState(
 | 
			
		||||
        pageCount = { viewModel.location.value.marquees.size },
 | 
			
		||||
    )
 | 
			
		||||
    val fantasy = rememberFantasyMapState()
 | 
			
		||||
    val snapBehavior = rememberSnapConnection(scrollState = scroll)
 | 
			
		||||
    val scrollBehavior = rememberScrollConnection(scrollState = scroll)
 | 
			
		||||
 | 
			
		||||
    val ok = stringResource(id = android.R.string.ok)
 | 
			
		||||
 | 
			
		||||
    val snackJob = remember { mutableStateOf<Job?>(null) }
 | 
			
		||||
    val mapHighlight = remember { mutableStateOf(Offset.Unspecified) }
 | 
			
		||||
    val selectedIndex = remember { mutableIntStateOf(0) }
 | 
			
		||||
 | 
			
		||||
    Surface {
 | 
			
		||||
        LocationContent(
 | 
			
		||||
            modifier = Modifier
 | 
			
		||||
                .fillMaxSize()
 | 
			
		||||
                .nestedScroll(connection = snapBehavior),
 | 
			
		||||
            connection = scrollBehavior,
 | 
			
		||||
            scrollState = scroll,
 | 
			
		||||
            pagerState = pager,
 | 
			
		||||
            fantasyMapState = fantasy,
 | 
			
		||||
            item = viewModel.location,
 | 
			
		||||
            selectedIndex = selectedIndex,
 | 
			
		||||
            selectedIndex = viewModel.selectedMarquee,
 | 
			
		||||
            mapHighlight = mapHighlight,
 | 
			
		||||
            onBack = {
 | 
			
		||||
                screen.popBackStack()
 | 
			
		||||
            },
 | 
			
		||||
            onMarquee = {
 | 
			
		||||
                scope.launch {
 | 
			
		||||
                    val index = max(viewModel.location.value.marquees.indexOf(it), 0)
 | 
			
		||||
                    selectedIndex.value = index
 | 
			
		||||
                    pager.animateScrollToPage(page = index)
 | 
			
		||||
                }
 | 
			
		||||
            onMarquee = viewModel::onSelectMarquee,
 | 
			
		||||
            onDestination = {
 | 
			
		||||
                screen.navigateToLocationDetail(id = it.id)
 | 
			
		||||
            },
 | 
			
		||||
            onMapTap = {
 | 
			
		||||
                snackJob.value?.cancel()
 | 
			
		||||
| 
						 | 
				
			
			@ -192,33 +182,21 @@ fun LocationDetail(
 | 
			
		|||
                }
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        HandlePagerScroll(
 | 
			
		||||
            pagerState = pager,
 | 
			
		||||
            index = selectedIndex,
 | 
			
		||||
            onIndexChange = { page ->
 | 
			
		||||
                pager.animateScrollToPage(page = page)
 | 
			
		||||
            },
 | 
			
		||||
            onPageChange = { page ->
 | 
			
		||||
                selectedIndex.value = page
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
 | 
			
		||||
@OptIn(ExperimentalMaterial3Api::class)
 | 
			
		||||
@Composable
 | 
			
		||||
private fun LocationContent(
 | 
			
		||||
    modifier: Modifier,
 | 
			
		||||
    connection: NestedScrollConnection,
 | 
			
		||||
    scrollState: ScrollState,
 | 
			
		||||
    pagerState: PagerState,
 | 
			
		||||
    fantasyMapState: FantasyMapState,
 | 
			
		||||
    item: State<LocationDetailUio>,
 | 
			
		||||
    selectedIndex: State<Int>,
 | 
			
		||||
    item: State<LocationDetailUio?>,
 | 
			
		||||
    selectedIndex: State<Int?>,
 | 
			
		||||
    mapHighlight: State<Offset>,
 | 
			
		||||
    onBack: () -> Unit,
 | 
			
		||||
    onMarquee: (MarqueeUio) -> Unit,
 | 
			
		||||
    onDestination: (MarqueeUio) -> Unit,
 | 
			
		||||
    onMapTap: (Offset) -> Unit,
 | 
			
		||||
    onTouch: (Boolean) -> Unit,
 | 
			
		||||
    onCenter: () -> Unit,
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +204,6 @@ private fun LocationContent(
 | 
			
		|||
    onZoomOut: () -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    val density = LocalDensity.current
 | 
			
		||||
    val itemNameSize = remember { mutableStateOf(0.dp) }
 | 
			
		||||
 | 
			
		||||
    val filledIconButtonColors = IconButtonDefaults.filledIconButtonColors(
 | 
			
		||||
        containerColor = MaterialTheme.colorScheme.surface,
 | 
			
		||||
| 
						 | 
				
			
			@ -265,118 +242,145 @@ private fun LocationContent(
 | 
			
		|||
            Column(
 | 
			
		||||
                modifier = Modifier.verticalScroll(state = scrollState),
 | 
			
		||||
            ) {
 | 
			
		||||
                Surface(
 | 
			
		||||
                    tonalElevation = 2.dp,
 | 
			
		||||
                ) {
 | 
			
		||||
                    Box(
 | 
			
		||||
                        modifier = Modifier.clip(shape = RectangleShape),
 | 
			
		||||
                if (item.value?.map != null) {
 | 
			
		||||
                    Surface(
 | 
			
		||||
                        tonalElevation = 2.dp,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        FantasyMap(
 | 
			
		||||
                            modifier = Modifier
 | 
			
		||||
                                .fillMaxWidth()
 | 
			
		||||
                                .heightIn(
 | 
			
		||||
                                    min = this@constraint.maxHeight / 2,
 | 
			
		||||
                                    max = this@constraint.maxHeight * 2 / 3,
 | 
			
		||||
                                )
 | 
			
		||||
                                .offset(scrollState = scrollState),
 | 
			
		||||
                            state = fantasyMapState,
 | 
			
		||||
                            model = item.value.map,
 | 
			
		||||
                            contentScale = ContentScale.Fit,
 | 
			
		||||
                            items = remember { derivedStateOf { item.value.marquees } },
 | 
			
		||||
                            selectedItem = selectedIndex,
 | 
			
		||||
                            highlight = mapHighlight,
 | 
			
		||||
                            onMarquee = onMarquee,
 | 
			
		||||
                            onTap = onMapTap,
 | 
			
		||||
                        )
 | 
			
		||||
 | 
			
		||||
                        FilledIconToggleButton(
 | 
			
		||||
                            modifier = Modifier
 | 
			
		||||
                                .align(alignment = Alignment.TopEnd)
 | 
			
		||||
                                .padding(all = 16.dp),
 | 
			
		||||
                            checked = fantasyMapState.freeHand,
 | 
			
		||||
                            onCheckedChange = onTouch,
 | 
			
		||||
                            colors = filledIconToggleButtonColors,
 | 
			
		||||
                        Box(
 | 
			
		||||
                            modifier = Modifier.clip(shape = RectangleShape),
 | 
			
		||||
                        ) {
 | 
			
		||||
                            Icon(
 | 
			
		||||
                                painter = painterResource(id = R.drawable.ic_baseline_touch_app_24),
 | 
			
		||||
                                contentDescription = null
 | 
			
		||||
                            FantasyMap(
 | 
			
		||||
                                modifier = Modifier
 | 
			
		||||
                                    .fillMaxWidth()
 | 
			
		||||
                                    .heightIn(
 | 
			
		||||
                                        min = this@constraint.maxHeight / 2,
 | 
			
		||||
                                        max = this@constraint.maxHeight * 2 / 3,
 | 
			
		||||
                                    )
 | 
			
		||||
                                    .offset(scrollState = scrollState),
 | 
			
		||||
                                state = fantasyMapState,
 | 
			
		||||
                                model = item.value?.map,
 | 
			
		||||
                                contentScale = ContentScale.Fit,
 | 
			
		||||
                                items = remember {
 | 
			
		||||
                                    derivedStateOf {
 | 
			
		||||
                                        item.value?.marquees ?: emptyList()
 | 
			
		||||
                                    }
 | 
			
		||||
                                },
 | 
			
		||||
                                selectedItem = selectedIndex,
 | 
			
		||||
                                highlight = mapHighlight,
 | 
			
		||||
                                onMarquee = onMarquee,
 | 
			
		||||
                                onTap = onMapTap,
 | 
			
		||||
                            )
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        Column(
 | 
			
		||||
                            modifier = Modifier
 | 
			
		||||
                                .align(alignment = Alignment.BottomEnd)
 | 
			
		||||
                                .padding(all = 16.dp),
 | 
			
		||||
                        ) {
 | 
			
		||||
                            FilledIconButton(
 | 
			
		||||
                                onClick = onZoomOut,
 | 
			
		||||
                                colors = filledIconButtonColors,
 | 
			
		||||
                            Column(
 | 
			
		||||
                                modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
                                horizontalAlignment = Alignment.End,
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Icon(
 | 
			
		||||
                                    painter = painterResource(id = R.drawable.ic_baseline_remove_24),
 | 
			
		||||
                                    contentDescription = null
 | 
			
		||||
                                )
 | 
			
		||||
                                val marquee = remember {
 | 
			
		||||
                                    derivedStateOf {
 | 
			
		||||
                                        when (val index = selectedIndex.value) {
 | 
			
		||||
                                            null -> null
 | 
			
		||||
                                            else -> item.value?.marquees?.get(index)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                AnimatedVisibility(
 | 
			
		||||
                                    visible = marquee.value != null && fantasyMapState.freeHand.not(),
 | 
			
		||||
                                    enter = fadeIn() + expandVertically(),
 | 
			
		||||
                                    exit = shrinkVertically() + fadeOut(),
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    Text(
 | 
			
		||||
                                        modifier = Modifier
 | 
			
		||||
                                            .clickable { marquee.value?.let(onDestination) }
 | 
			
		||||
                                            .background(
 | 
			
		||||
                                                brush = rememberBackgroundGradient(
 | 
			
		||||
                                                    from = 0.8f,
 | 
			
		||||
                                                    to = 0.4f,
 | 
			
		||||
                                                )
 | 
			
		||||
                                            )
 | 
			
		||||
                                            .minimumInteractiveComponentSize()
 | 
			
		||||
                                            .fillMaxWidth(),
 | 
			
		||||
                                        style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                                        textAlign = TextAlign.Center,
 | 
			
		||||
                                        text = annotateWithDropCap(
 | 
			
		||||
                                            text = marquee.value?.name ?: "",
 | 
			
		||||
                                            style = MaterialTheme.lexicon.typography.titleMediumDropCap,
 | 
			
		||||
                                        )
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                FilledIconToggleButton(
 | 
			
		||||
                                    modifier = Modifier.padding(all = 8.dp),
 | 
			
		||||
                                    checked = fantasyMapState.freeHand,
 | 
			
		||||
                                    onCheckedChange = onTouch,
 | 
			
		||||
                                    colors = filledIconToggleButtonColors,
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    Icon(
 | 
			
		||||
                                        painter = painterResource(id = R.drawable.ic_baseline_touch_app_24),
 | 
			
		||||
                                        contentDescription = null
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            FilledIconButton(
 | 
			
		||||
                                onClick = onZoomIn,
 | 
			
		||||
                                colors = filledIconButtonColors,
 | 
			
		||||
 | 
			
		||||
                            Column(
 | 
			
		||||
                                modifier = Modifier
 | 
			
		||||
                                    .align(alignment = Alignment.BottomEnd)
 | 
			
		||||
                                    .padding(all = 8.dp),
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Icon(
 | 
			
		||||
                                    painter = painterResource(id = R.drawable.ic_baseline_add_24),
 | 
			
		||||
                                    contentDescription = null
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
                            FilledIconButton(
 | 
			
		||||
                                onClick = onCenter,
 | 
			
		||||
                                colors = filledIconButtonColors,
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Icon(
 | 
			
		||||
                                    painter = painterResource(id = R.drawable.ic_baseline_zoom_in_map_24),
 | 
			
		||||
                                    contentDescription = null
 | 
			
		||||
                                )
 | 
			
		||||
                                FilledIconButton(
 | 
			
		||||
                                    onClick = onZoomOut,
 | 
			
		||||
                                    colors = filledIconButtonColors,
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    Icon(
 | 
			
		||||
                                        painter = painterResource(id = R.drawable.ic_baseline_remove_24),
 | 
			
		||||
                                        contentDescription = null
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                                FilledIconButton(
 | 
			
		||||
                                    onClick = onZoomIn,
 | 
			
		||||
                                    colors = filledIconButtonColors,
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    Icon(
 | 
			
		||||
                                        painter = painterResource(id = R.drawable.ic_baseline_add_24),
 | 
			
		||||
                                        contentDescription = null
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                                FilledIconButton(
 | 
			
		||||
                                    onClick = onCenter,
 | 
			
		||||
                                    colors = filledIconButtonColors,
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    Icon(
 | 
			
		||||
                                        painter = painterResource(id = R.drawable.ic_baseline_zoom_in_map_24),
 | 
			
		||||
                                        contentDescription = null
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Handle(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .align(alignment = Alignment.CenterHorizontally)
 | 
			
		||||
                        .padding(vertical = 16.dp)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                Column(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .onSizeChanged { itemNameSize.value = with(density) { it.height.toDp() } }
 | 
			
		||||
                        .padding(horizontal = 16.dp)
 | 
			
		||||
                        .fillMaxWidth(),
 | 
			
		||||
                        .fillMaxWidth()
 | 
			
		||||
                        .heightIn(min = this@constraint.maxHeight)
 | 
			
		||||
                        .padding(all = 16.dp),
 | 
			
		||||
                    horizontalAlignment = Alignment.CenterHorizontally,
 | 
			
		||||
                    verticalArrangement = Arrangement.spacedBy(space = 24.dp),
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(
 | 
			
		||||
                        textAlign = TextAlign.Center,
 | 
			
		||||
                        style = MaterialTheme.typography.headlineSmall,
 | 
			
		||||
                        text = annotateWithDropCap(
 | 
			
		||||
                            text = item.value.name,
 | 
			
		||||
                            text = item.value?.name ?: "",
 | 
			
		||||
                            style = MaterialTheme.lexicon.typography.headlineSmallDropCap,
 | 
			
		||||
                        ),
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                HorizontalPager(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .fillMaxWidth()
 | 
			
		||||
                        .nestedScroll(connection),
 | 
			
		||||
                    state = pagerState,
 | 
			
		||||
                    verticalAlignment = Alignment.Top,
 | 
			
		||||
                    contentPadding = PaddingValues(all = 16.dp),
 | 
			
		||||
                    pageSpacing = 16.dp,
 | 
			
		||||
                ) {
 | 
			
		||||
                    item.value.marquees.getOrNull(it)?.let { marquee ->
 | 
			
		||||
                        MarqueeItem(
 | 
			
		||||
                            modifier = Modifier
 | 
			
		||||
                                .fillMaxWidth()
 | 
			
		||||
                                .height(this@constraint.maxHeight - 32.dp - itemNameSize.value),
 | 
			
		||||
                            marquee = marquee,
 | 
			
		||||
                    item.value?.description?.let {
 | 
			
		||||
                        Text(
 | 
			
		||||
                            style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                            text = annotateWithDropCap(
 | 
			
		||||
                                text = it,
 | 
			
		||||
                                style = MaterialTheme.lexicon.typography.bodyMediumDropCap
 | 
			
		||||
                            ),
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -385,24 +389,6 @@ private fun LocationContent(
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@OptIn(ExperimentalFoundationApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
private fun HandlePagerScroll(
 | 
			
		||||
    pagerState: PagerState,
 | 
			
		||||
    index: State<Int>,
 | 
			
		||||
    onIndexChange: suspend (page: Int) -> Unit,
 | 
			
		||||
    onPageChange: suspend (page: Int) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    if (!pagerState.isScrollInProgress) {
 | 
			
		||||
        LaunchedEffect(Unit) {
 | 
			
		||||
            onPageChange.invoke(pagerState.currentPage)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    LaunchedEffect(key1 = index.value) {
 | 
			
		||||
        onIndexChange.invoke(index.value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
@Stable
 | 
			
		||||
private fun rememberSnapConnection(
 | 
			
		||||
| 
						 | 
				
			
			@ -410,56 +396,23 @@ private fun rememberSnapConnection(
 | 
			
		|||
    scrollState: ScrollState,
 | 
			
		||||
): NestedScrollConnection {
 | 
			
		||||
    val dimens = MaterialTheme.lexicon.dimens
 | 
			
		||||
 | 
			
		||||
    return remember(scope, scrollState) {
 | 
			
		||||
        object : NestedScrollConnection {
 | 
			
		||||
            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
 | 
			
		||||
                if (scrollState.value < dimens.map.mapSnapPx) {
 | 
			
		||||
                    scope.launch { scrollState.animateScrollTo(0) }
 | 
			
		||||
                }
 | 
			
		||||
                if ((scrollState.maxValue - scrollState.value) < dimens.map.mapSnapPx) {
 | 
			
		||||
                    scope.launch { scrollState.animateScrollTo(scrollState.maxValue) }
 | 
			
		||||
                }
 | 
			
		||||
                return super.onPostFling(consumed, available)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
@Stable
 | 
			
		||||
private fun rememberScrollConnection(
 | 
			
		||||
    scope: CoroutineScope = rememberCoroutineScope(),
 | 
			
		||||
    scrollState: ScrollState,
 | 
			
		||||
): NestedScrollConnection {
 | 
			
		||||
    return remember(scrollState) {
 | 
			
		||||
        object : NestedScrollConnection {
 | 
			
		||||
            override fun onPreScroll(
 | 
			
		||||
                available: Offset,
 | 
			
		||||
                source: NestedScrollSource,
 | 
			
		||||
            ): Offset {
 | 
			
		||||
                val delta = when {
 | 
			
		||||
                    scrollState.value == 0 && available.y > 0f -> 0f
 | 
			
		||||
 | 
			
		||||
                    scrollState.value == scrollState.maxValue -> 0f
 | 
			
		||||
 | 
			
		||||
                    else -> {
 | 
			
		||||
                        scope.launch { scrollState.scrollBy(-available.y) }
 | 
			
		||||
                        available.y
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return Offset(x = 0f, y = delta)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
private fun Modifier.offset(scrollState: ScrollState) = this.offset {
 | 
			
		||||
    IntOffset(x = 0, y = scrollState.value / 2)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@OptIn(ExperimentalFoundationApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
 | 
			
		||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
 | 
			
		||||
| 
						 | 
				
			
			@ -468,34 +421,49 @@ private fun LocationPreview() {
 | 
			
		|||
        Surface {
 | 
			
		||||
            LocationContent(
 | 
			
		||||
                modifier = Modifier.fillMaxSize(),
 | 
			
		||||
                connection = remember { object : NestedScrollConnection {} },
 | 
			
		||||
                scrollState = rememberScrollState(),
 | 
			
		||||
                pagerState = rememberPagerState(pageCount = { 2 }),
 | 
			
		||||
                fantasyMapState = rememberFantasyMapState(),
 | 
			
		||||
                item = remember {
 | 
			
		||||
                    mutableStateOf(
 | 
			
		||||
                        LocationDetailUio(
 | 
			
		||||
                            name = "Daggerfall",
 | 
			
		||||
                            map = Uri.parse("https://i.pinimg.com/originals/6d/56/cd/6d56cd9358cc94a7077157ea3c1b5842.jpg"),
 | 
			
		||||
                            name = "Barovie",
 | 
			
		||||
                            map = Uri.parse("https://cdn.discordapp.com/attachments/1123326578508714106/1161014438736969759/Map_of_Barovia_-_4k_-_Names_-_No_Special_Locations_-_Without_Hex.jpg?ex=6536c1f4&is=65244cf4&hm=671ddc88d073e5559bd37af14dc731e497b78457dc37a3ea5620a5342004b733&"),
 | 
			
		||||
                            description = "Contrée sombre et maudite soumise au joug de Stradh von Zarovith",
 | 
			
		||||
                            marquees = listOf(
 | 
			
		||||
                                MarqueeUio(
 | 
			
		||||
                                    name = "start",
 | 
			
		||||
                                    position = Offset.Zero,
 | 
			
		||||
                                    description = "Marquee en haut à gauche."
 | 
			
		||||
                                    id = "Barovie (village)",
 | 
			
		||||
                                    name = "Barovie (village)",
 | 
			
		||||
                                    position = Offset(0.79310584f, 0.61436355f)
 | 
			
		||||
                                ),
 | 
			
		||||
                                MarqueeUio(
 | 
			
		||||
                                    name = "end",
 | 
			
		||||
                                    position = Offset(1f, 1f),
 | 
			
		||||
                                    description = "Marquee en bas à droite."
 | 
			
		||||
                                    id = "Vallaki",
 | 
			
		||||
                                    name = "Vallaki",
 | 
			
		||||
                                    position = Offset(0.42546257f, 0.31059146f)
 | 
			
		||||
                                ),
 | 
			
		||||
                                MarqueeUio(
 | 
			
		||||
                                    id = "Krezk",
 | 
			
		||||
                                    name = "Krezk",
 | 
			
		||||
                                    position = Offset(0.1110163f, 0.29166123f)
 | 
			
		||||
                                ),
 | 
			
		||||
                                MarqueeUio(
 | 
			
		||||
                                    id = "Campement Vistani",
 | 
			
		||||
                                    name = "Campement Vistani",
 | 
			
		||||
                                    position = Offset(0.6623672f, 0.6120087f)
 | 
			
		||||
                                ),
 | 
			
		||||
                                MarqueeUio(
 | 
			
		||||
                                    id = "Vieux moulin",
 | 
			
		||||
                                    name = "Vieux moulin",
 | 
			
		||||
                                    position = Offset(0.49444568f, 0.40867198f)
 | 
			
		||||
                                ),
 | 
			
		||||
                            ),
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
                selectedIndex = remember { mutableStateOf(0) },
 | 
			
		||||
                selectedIndex = remember { mutableIntStateOf(0) },
 | 
			
		||||
                mapHighlight = remember { mutableStateOf(Offset(0.5f, 0.5f)) },
 | 
			
		||||
                onBack = { },
 | 
			
		||||
                onMarquee = { },
 | 
			
		||||
                onDestination = { },
 | 
			
		||||
                onMapTap = { },
 | 
			
		||||
                onTouch = { },
 | 
			
		||||
                onCenter = { },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,18 +4,21 @@ import android.app.Application
 | 
			
		|||
import android.content.ClipData
 | 
			
		||||
import android.content.ClipboardManager
 | 
			
		||||
import android.content.Context.CLIPBOARD_SERVICE
 | 
			
		||||
import androidx.compose.runtime.IntState
 | 
			
		||||
import androidx.compose.runtime.State
 | 
			
		||||
import androidx.compose.runtime.mutableIntStateOf
 | 
			
		||||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.compose.ui.geometry.Offset
 | 
			
		||||
import androidx.lifecycle.AndroidViewModel
 | 
			
		||||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LocationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LocationRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.locationDetailArgument
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.cells
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.line
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.table
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
import kotlin.math.max
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class LocationDetailViewModel @Inject constructor(
 | 
			
		||||
| 
						 | 
				
			
			@ -25,28 +28,39 @@ class LocationDetailViewModel @Inject constructor(
 | 
			
		|||
) : AndroidViewModel(application) {
 | 
			
		||||
    private val clipboard = application.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
 | 
			
		||||
 | 
			
		||||
    val sheetUri = LocationRepository.SHEET_URL
 | 
			
		||||
    val location: State<LocationDetailUio>
 | 
			
		||||
    val sheetUri = LocationRepository.WORLD_SHEET_URL
 | 
			
		||||
    val location: State<LocationDetailUio?>
 | 
			
		||||
 | 
			
		||||
    private val _selectedMarquee = mutableStateOf<Int?>(null)
 | 
			
		||||
    val selectedMarquee: State<Int?> get() = _selectedMarquee
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        val argument = savedStateHandle.locationDetailArgument
 | 
			
		||||
        val source = repository.data.value[argument.id]
 | 
			
		||||
        val source = repository.find(id = argument.id)
 | 
			
		||||
 | 
			
		||||
        location = mutableStateOf(
 | 
			
		||||
            LocationDetailUio(
 | 
			
		||||
                name = source.name,
 | 
			
		||||
                map = source.uri,
 | 
			
		||||
                marquees = source.marquees.map { marquee ->
 | 
			
		||||
                    MarqueeUio(
 | 
			
		||||
                        name = marquee.name,
 | 
			
		||||
                        position = marquee.position,
 | 
			
		||||
                        description = marquee.description,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            )
 | 
			
		||||
            source?.let {
 | 
			
		||||
                LocationDetailUio(
 | 
			
		||||
                    name = it.name,
 | 
			
		||||
                    map = it.uri,
 | 
			
		||||
                    description = it.description,
 | 
			
		||||
                    marquees = it.child.map { child ->
 | 
			
		||||
                        MarqueeUio(
 | 
			
		||||
                            id = child.second.id,
 | 
			
		||||
                            name = child.second.name,
 | 
			
		||||
                            position = child.first,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onSelectMarquee(marqueeUio: MarqueeUio) {
 | 
			
		||||
        val index = max(location.value?.marquees?.indexOf(marqueeUio) ?: 0, 0)
 | 
			
		||||
        _selectedMarquee.value = index
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun clip(
 | 
			
		||||
        label: String,
 | 
			
		||||
        coordinate: Offset,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,7 @@
 | 
			
		|||
package com.pixelized.rplexicon.ui.screens.location.detail
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
import androidx.compose.foundation.layout.padding
 | 
			
		||||
import androidx.compose.foundation.rememberScrollState
 | 
			
		||||
import androidx.compose.foundation.verticalScroll
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.Surface
 | 
			
		||||
import androidx.compose.material3.Text
 | 
			
		||||
| 
						 | 
				
			
			@ -20,15 +15,14 @@ import androidx.compose.ui.text.style.TextOverflow
 | 
			
		|||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.LOS_HOLLOW
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.annotateWithDropCap
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
 | 
			
		||||
 | 
			
		||||
@Stable
 | 
			
		||||
data class MarqueeUio(
 | 
			
		||||
    val name: String?,
 | 
			
		||||
    val id: String,
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val position: Offset,
 | 
			
		||||
    val description: String?,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
| 
						 | 
				
			
			@ -36,43 +30,18 @@ fun MarqueeItem(
 | 
			
		|||
    modifier: Modifier = Modifier,
 | 
			
		||||
    marquee: MarqueeUio,
 | 
			
		||||
) {
 | 
			
		||||
    Column(
 | 
			
		||||
    Text(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        verticalArrangement = Arrangement.spacedBy(space = 8.dp)
 | 
			
		||||
    ) {
 | 
			
		||||
        marquee.name?.let {
 | 
			
		||||
            Row(
 | 
			
		||||
                horizontalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
            ) {
 | 
			
		||||
                Text(
 | 
			
		||||
                    modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                    text = LOS_HOLLOW,
 | 
			
		||||
                )
 | 
			
		||||
                Text(
 | 
			
		||||
                    modifier = Modifier.alignByBaseline(),
 | 
			
		||||
                    style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                    fontWeight = FontWeight.Bold,
 | 
			
		||||
                    textAlign = TextAlign.Center,
 | 
			
		||||
                    overflow = TextOverflow.Ellipsis,
 | 
			
		||||
                    maxLines = 3,
 | 
			
		||||
                    text = annotateWithDropCap(
 | 
			
		||||
                        text = it,
 | 
			
		||||
                        style = MaterialTheme.lexicon.typography.titleMediumDropCap,
 | 
			
		||||
                    ),
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        marquee.description?.let {
 | 
			
		||||
            Text(
 | 
			
		||||
                modifier = Modifier.verticalScroll(rememberScrollState()),
 | 
			
		||||
                style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                text = annotateWithDropCap(
 | 
			
		||||
                    text = it,
 | 
			
		||||
                    style = MaterialTheme.lexicon.typography.bodyMediumDropCap,
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
        fontWeight = FontWeight.Bold,
 | 
			
		||||
        textAlign = TextAlign.Center,
 | 
			
		||||
        overflow = TextOverflow.Ellipsis,
 | 
			
		||||
        maxLines = 3,
 | 
			
		||||
        text = annotateWithDropCap(
 | 
			
		||||
            text = marquee.name,
 | 
			
		||||
            style = MaterialTheme.lexicon.typography.titleMediumDropCap,
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
| 
						 | 
				
			
			@ -85,9 +54,9 @@ private fun MarqueeItemPreview() {
 | 
			
		|||
                    .fillMaxWidth()
 | 
			
		||||
                    .padding(all = 16.dp),
 | 
			
		||||
                marquee = MarqueeUio(
 | 
			
		||||
                    id = "Barovie",
 | 
			
		||||
                    name = "Barovie",
 | 
			
		||||
                    position = Offset.Zero,
 | 
			
		||||
                    description = "Village lugubre à la population clairsemé théatre récent d'une d'une rebelion sanglante.",
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,13 +27,13 @@ import com.pixelized.rplexicon.utilitary.extentions.placeholder
 | 
			
		|||
 | 
			
		||||
@Stable
 | 
			
		||||
data class LocationItemUio(
 | 
			
		||||
    val id: Int,
 | 
			
		||||
    val id: String,
 | 
			
		||||
    val title: String,
 | 
			
		||||
    val placeholder: Boolean = false,
 | 
			
		||||
) {
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun preview(
 | 
			
		||||
            id: Int = 0,
 | 
			
		||||
            id: String = "0",
 | 
			
		||||
            title: String = "Daggerfall",
 | 
			
		||||
            placeHolder: Boolean = false,
 | 
			
		||||
        ): LocationItemUio {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -152,8 +152,8 @@ private fun QuestListPreview() {
 | 
			
		|||
                items = remember {
 | 
			
		||||
                    mutableStateOf(
 | 
			
		||||
                        listOf(
 | 
			
		||||
                            LocationItemUio.preview(id = 0, title = "Daggerfall"),
 | 
			
		||||
                            LocationItemUio.preview(id = 1, title = "Athkatla"),
 | 
			
		||||
                            LocationItemUio.preview(id = "0", title = "Daggerfall"),
 | 
			
		||||
                            LocationItemUio.preview(id = "1", title = "Athkatla"),
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ import androidx.compose.runtime.State
 | 
			
		|||
import androidx.compose.runtime.mutableStateOf
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import androidx.lifecycle.viewModelScope
 | 
			
		||||
import com.pixelized.rplexicon.repository.data.lexicon.LocationRepository
 | 
			
		||||
import com.pixelized.rplexicon.data.repository.lexicon.LocationRepository
 | 
			
		||||
import com.pixelized.rplexicon.ui.composable.error.FetchErrorUio
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ class LocationViewModel @Inject constructor(
 | 
			
		|||
                repository.data.collect { items ->
 | 
			
		||||
                    _items.value = items.map { item ->
 | 
			
		||||
                        LocationItemUio(
 | 
			
		||||
                            id = item.id,
 | 
			
		||||
                            id = item.name,
 | 
			
		||||
                            title = item.name,
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +50,7 @@ class LocationViewModel @Inject constructor(
 | 
			
		|||
        _isLoading.value = true
 | 
			
		||||
        try {
 | 
			
		||||
            if (force || repository.lastSuccessFullUpdate.shouldUpdate()) {
 | 
			
		||||
                repository.fetchLocation()
 | 
			
		||||
                repository.fetchMap()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // the data sheet structure is not as expected
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue