mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-10-01 07:31:37 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93f568dd8d | ||
|
|
d46769b0cb | ||
|
|
fce05870c5 | ||
|
|
d749af0a9c | ||
|
|
076f6bfacf | ||
|
|
a4f3b701e5 | ||
|
|
da134247b1 | ||
|
|
e36a700d9f | ||
|
|
fb6b6d2825 | ||
|
|
e17f6c23e4 | ||
|
|
409474b5d1 | ||
|
|
547318864b | ||
|
|
1a38cefb92 |
@@ -15,7 +15,7 @@ android {
|
|||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "1.0"
|
versionName = "Alpha 0.1"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -91,4 +91,7 @@ dependencies {
|
|||||||
implementation("com.google.android.material:material:1.2.0")
|
implementation("com.google.android.material:material:1.2.0")
|
||||||
implementation(libs.protobuf.javalite)
|
implementation(libs.protobuf.javalite)
|
||||||
implementation("androidx.compose.material:material")
|
implementation("androidx.compose.material:material")
|
||||||
|
implementation("androidx.glance:glance:1.1.1")
|
||||||
|
implementation("androidx.glance:glance-appwidget:1.1.1")
|
||||||
|
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,15 @@
|
|||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<receiver android:name=".widget.CharacterDisplayWidgetReceiver"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/widget_info" />
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
Binary file not shown.
@@ -9,9 +9,12 @@ import androidx.compose.runtime.Composable
|
|||||||
import com.github.nacabaro.vbhelper.navigation.AppNavigation
|
import com.github.nacabaro.vbhelper.navigation.AppNavigation
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.navigation.AppNavigationHandlers
|
import com.github.nacabaro.vbhelper.navigation.AppNavigationHandlers
|
||||||
|
import com.github.nacabaro.vbhelper.screens.homeScreens.HomeScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
|
||||||
|
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
|
||||||
|
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
||||||
|
|
||||||
|
|
||||||
@@ -39,6 +42,9 @@ class MainActivity : ComponentActivity() {
|
|||||||
)
|
)
|
||||||
val settingsScreenController = SettingsScreenControllerImpl(this)
|
val settingsScreenController = SettingsScreenControllerImpl(this)
|
||||||
val itemsScreenController = ItemsScreenControllerImpl(this)
|
val itemsScreenController = ItemsScreenControllerImpl(this)
|
||||||
|
val adventureScreenController = AdventureScreenControllerImpl(this)
|
||||||
|
val storageScreenController = StorageScreenControllerImpl(this)
|
||||||
|
val homeScreenController = HomeScreenControllerImpl(this)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
@@ -49,7 +55,10 @@ class MainActivity : ComponentActivity() {
|
|||||||
MainApplication(
|
MainApplication(
|
||||||
scanScreenController = scanScreenController,
|
scanScreenController = scanScreenController,
|
||||||
settingsScreenController = settingsScreenController,
|
settingsScreenController = settingsScreenController,
|
||||||
itemsScreenController = itemsScreenController
|
itemsScreenController = itemsScreenController,
|
||||||
|
adventureScreenController = adventureScreenController,
|
||||||
|
homeScreenController = homeScreenController,
|
||||||
|
storageScreenController = storageScreenController
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,13 +86,20 @@ class MainActivity : ComponentActivity() {
|
|||||||
private fun MainApplication(
|
private fun MainApplication(
|
||||||
scanScreenController: ScanScreenControllerImpl,
|
scanScreenController: ScanScreenControllerImpl,
|
||||||
settingsScreenController: SettingsScreenControllerImpl,
|
settingsScreenController: SettingsScreenControllerImpl,
|
||||||
itemsScreenController: ItemsScreenControllerImpl
|
itemsScreenController: ItemsScreenControllerImpl,
|
||||||
|
adventureScreenController: AdventureScreenControllerImpl,
|
||||||
|
storageScreenController: StorageScreenControllerImpl,
|
||||||
|
homeScreenController: HomeScreenControllerImpl,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
AppNavigation(
|
AppNavigation(
|
||||||
applicationNavigationHandlers = AppNavigationHandlers(
|
applicationNavigationHandlers = AppNavigationHandlers(
|
||||||
settingsScreenController,
|
settingsScreenController,
|
||||||
scanScreenController,
|
scanScreenController,
|
||||||
itemsScreenController
|
itemsScreenController,
|
||||||
|
adventureScreenController,
|
||||||
|
storageScreenController,
|
||||||
|
homeScreenController
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ fun CharacterEntry(
|
|||||||
icon: BitmapData,
|
icon: BitmapData,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
obscure: Boolean = false,
|
obscure: Boolean = false,
|
||||||
|
disabled: Boolean = false,
|
||||||
shape: Shape = MaterialTheme.shapes.medium,
|
shape: Shape = MaterialTheme.shapes.medium,
|
||||||
multiplier: Int = 4,
|
multiplier: Int = 4,
|
||||||
onClick: () -> Unit = { }
|
onClick: () -> Unit = { }
|
||||||
@@ -48,7 +49,10 @@ fun CharacterEntry(
|
|||||||
|
|
||||||
Card(
|
Card(
|
||||||
shape = shape,
|
shape = shape,
|
||||||
onClick = onClick,
|
onClick = when (disabled) {
|
||||||
|
true -> { {} }
|
||||||
|
false -> onClick
|
||||||
|
},
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.aspectRatio(1f)
|
.aspectRatio(1f)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ fun TopBanner(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onGearClick: (() -> Unit)? = null,
|
onGearClick: (() -> Unit)? = null,
|
||||||
onBackClick: (() -> Unit)? = null,
|
onBackClick: (() -> Unit)? = null,
|
||||||
onScanClick: (() -> Unit)? = null
|
onScanClick: (() -> Unit)? = null,
|
||||||
|
onAdventureClick: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
Box( // Use Box to overlay elements
|
Box( // Use Box to overlay elements
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
@@ -49,6 +50,17 @@ fun TopBanner(
|
|||||||
contentDescription = "Settings"
|
contentDescription = "Settings"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else if (onAdventureClick != null) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onAdventureClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterEnd) // Place gear icon at the end
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.baseline_fort_24), // Use a gear icon
|
||||||
|
contentDescription = "Adventure"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onScanClick != null) {
|
if (onScanClick != null) {
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface AdventureDao {
|
||||||
|
@Query("""
|
||||||
|
INSERT INTO Adventure (characterId, originalDuration, finishesAdventure)
|
||||||
|
VALUES (:characterId, :originalDuration, strftime('%s', 'now') + :timeInSeconds)
|
||||||
|
""")
|
||||||
|
fun insertNewAdventure(characterId: Long, originalDuration: Long, timeInSeconds: Long)
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT COUNT(*) FROM Adventure
|
||||||
|
""")
|
||||||
|
fun getAdventureCount(): Int
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT
|
||||||
|
uc.*,
|
||||||
|
c.stage,
|
||||||
|
c.attribute,
|
||||||
|
c.sprite1 AS spriteIdle,
|
||||||
|
c.spritesWidth AS spriteWidth,
|
||||||
|
c.spritesHeight AS spriteHeight,
|
||||||
|
d.isBEm as isBemCard,
|
||||||
|
a.finishesAdventure AS finishesAdventure,
|
||||||
|
a.originalDuration AS originalTimeInMinutes
|
||||||
|
FROM UserCharacter uc
|
||||||
|
JOIN Character c ON uc.charId = c.id
|
||||||
|
JOIN Card d ON c.dimId = d.id
|
||||||
|
JOIN Adventure a ON uc.id = a.characterId
|
||||||
|
""")
|
||||||
|
suspend fun getAdventureCharacters(): List<CharacterDtos.AdventureCharacterWithSprites>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
DELETE FROM Adventure
|
||||||
|
WHERE characterId = :characterId
|
||||||
|
""")
|
||||||
|
suspend fun deleteAdventure(characterId: Long)
|
||||||
|
}
|
||||||
@@ -6,40 +6,48 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
|||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface ItemDao {
|
interface ItemDao {
|
||||||
@Query("""
|
@Query(
|
||||||
SELECT Items.*, UserItems.quantity
|
"""
|
||||||
|
SELECT *
|
||||||
FROM Items
|
FROM Items
|
||||||
LEFT JOIN UserItems ON Items.id = UserItems.itemId
|
|
||||||
ORDER BY Items.itemIcon ASC
|
ORDER BY Items.itemIcon ASC
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
suspend fun getAllItems(): List<ItemDtos.ItemsWithQuantities>
|
suspend fun getAllItems(): List<ItemDtos.ItemsWithQuantities>
|
||||||
|
|
||||||
@Query("""
|
@Query(
|
||||||
SELECT Items.*, UserItems.quantity
|
"""
|
||||||
|
SELECT *
|
||||||
FROM Items
|
FROM Items
|
||||||
JOIN UserItems ON Items.id = UserItems.itemId
|
WHERE quantity > 0
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
suspend fun getAllUserItems(): List<ItemDtos.ItemsWithQuantities>
|
suspend fun getAllUserItems(): List<ItemDtos.ItemsWithQuantities>
|
||||||
|
|
||||||
@Query("""
|
@Query(
|
||||||
SELECT Items.*, UserItems.quantity
|
"""
|
||||||
|
SELECT *
|
||||||
FROM Items
|
FROM Items
|
||||||
JOIN UserItems ON Items.id = UserItems.itemId
|
WHERE Items.id = :itemId
|
||||||
WHERE UserItems.itemId = :itemId
|
"""
|
||||||
""")
|
)
|
||||||
fun getUserItem(itemId: Long): ItemDtos.ItemsWithQuantities
|
fun getItem(itemId: Long): ItemDtos.ItemsWithQuantities
|
||||||
|
|
||||||
@Query("""
|
@Query(
|
||||||
UPDATE UserItems
|
"""
|
||||||
|
UPDATE Items
|
||||||
SET quantity = quantity - 1
|
SET quantity = quantity - 1
|
||||||
WHERE itemId = :itemId
|
WHERE id = :itemId
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
fun useItem(itemId: Long)
|
fun useItem(itemId: Long)
|
||||||
|
|
||||||
@Query("""
|
@Query(
|
||||||
UPDATE UserItems
|
"""
|
||||||
SET quantity = quantity - :itemAmount
|
UPDATE Items
|
||||||
WHERE itemId = :itemId
|
SET quantity = quantity + :itemAmount
|
||||||
""")
|
WHERE id = :itemId
|
||||||
|
"""
|
||||||
|
)
|
||||||
suspend fun purchaseItem(itemId: Long, itemAmount: Int)
|
suspend fun purchaseItem(itemId: Long, itemAmount: Int)
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import androidx.room.Insert
|
|||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Upsert
|
import androidx.room.Upsert
|
||||||
|
import com.github.nacabaro.vbhelper.domain.characters.Character
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
|
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
|
||||||
@@ -45,17 +46,46 @@ interface UserCharacterDao {
|
|||||||
"""
|
"""
|
||||||
SELECT
|
SELECT
|
||||||
uc.*,
|
uc.*,
|
||||||
|
c.stage,
|
||||||
|
c.attribute,
|
||||||
c.sprite1 AS spriteIdle,
|
c.sprite1 AS spriteIdle,
|
||||||
c.spritesWidth AS spriteWidth,
|
c.spritesWidth AS spriteWidth,
|
||||||
c.spritesHeight AS spriteHeight,
|
c.spritesHeight AS spriteHeight,
|
||||||
d.isBEm as isBemCard
|
c.name as nameSprite,
|
||||||
|
c.nameWidth as nameSpriteWidth,
|
||||||
|
c.nameHeight as nameSpriteHeight,
|
||||||
|
d.isBEm as isBemCard,
|
||||||
|
a.characterId = uc.id as isInAdventure
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN Character c ON uc.charId = c.id
|
JOIN Character c ON uc.charId = c.id
|
||||||
JOIN Card d ON c.dimId = d.id
|
JOIN Card d ON c.dimId = d.id
|
||||||
|
LEFT JOIN Adventure a ON a.characterId = uc.id
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getAllCharacters(): List<CharacterDtos.CharacterWithSprites>
|
suspend fun getAllCharacters(): List<CharacterDtos.CharacterWithSprites>
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
SELECT
|
||||||
|
uc.*,
|
||||||
|
c.stage,
|
||||||
|
c.attribute,
|
||||||
|
c.sprite1 AS spriteIdle,
|
||||||
|
c.spritesWidth AS spriteWidth,
|
||||||
|
c.spritesHeight AS spriteHeight,
|
||||||
|
c.name as nameSprite,
|
||||||
|
c.nameWidth as nameSpriteWidth,
|
||||||
|
c.nameHeight as nameSpriteHeight,
|
||||||
|
d.isBEm as isBemCard,
|
||||||
|
a.characterId = uc.id as isInAdventure
|
||||||
|
FROM UserCharacter uc
|
||||||
|
JOIN Character c ON uc.charId = c.id
|
||||||
|
JOIN Card d ON c.dimId = d.id
|
||||||
|
LEFT JOIN Adventure a ON a.characterId = uc.id
|
||||||
|
WHERE uc.id = :id
|
||||||
|
""")
|
||||||
|
suspend fun getCharacterWithSprites(id: Long): CharacterDtos.CharacterWithSprites
|
||||||
|
|
||||||
@Query("SELECT * FROM UserCharacter WHERE id = :id")
|
@Query("SELECT * FROM UserCharacter WHERE id = :id")
|
||||||
suspend fun getCharacter(id: Long): UserCharacter
|
suspend fun getCharacter(id: Long): UserCharacter
|
||||||
|
|
||||||
@@ -66,17 +96,23 @@ interface UserCharacterDao {
|
|||||||
"""
|
"""
|
||||||
SELECT
|
SELECT
|
||||||
uc.*,
|
uc.*,
|
||||||
|
c.stage,
|
||||||
|
c.attribute,
|
||||||
c.sprite1 AS spriteIdle,
|
c.sprite1 AS spriteIdle,
|
||||||
c.spritesWidth AS spriteWidth,
|
c.spritesWidth AS spriteWidth,
|
||||||
c.spritesHeight AS spriteHeight,
|
c.spritesHeight AS spriteHeight,
|
||||||
d.isBEm as isBemCard
|
c.name as nameSprite,
|
||||||
|
c.nameWidth as nameSpriteWidth,
|
||||||
|
c.nameHeight as nameSpriteHeight,
|
||||||
|
d.isBEm as isBemCard,
|
||||||
|
a.characterId as isInAdventure
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN Character c ON uc.charId = c.id
|
JOIN Character c ON uc.charId = c.id
|
||||||
JOIN Card d ON c.dimId = d.id
|
JOIN Card d ON c.dimId = d.id
|
||||||
|
LEFT JOIN Adventure a ON a.characterId = uc.id
|
||||||
WHERE uc.isActive = 1
|
WHERE uc.isActive = 1
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
suspend fun getActiveCharacter(): CharacterDtos.CharacterWithSprites?
|
suspend fun getActiveCharacter(): CharacterDtos.CharacterWithSprites?
|
||||||
|
|
||||||
@Query("DELETE FROM UserCharacter WHERE id = :id")
|
@Query("DELETE FROM UserCharacter WHERE id = :id")
|
||||||
@@ -87,4 +123,15 @@ interface UserCharacterDao {
|
|||||||
|
|
||||||
@Query("UPDATE UserCharacter SET isActive = 1 WHERE id = :id")
|
@Query("UPDATE UserCharacter SET isActive = 1 WHERE id = :id")
|
||||||
fun setActiveCharacter(id: Long)
|
fun setActiveCharacter(id: Long)
|
||||||
|
|
||||||
|
@Query(
|
||||||
|
"""
|
||||||
|
SELECT c.*
|
||||||
|
FROM Character c
|
||||||
|
join UserCharacter uc on c.id = uc.charId
|
||||||
|
where uc.id = :charId
|
||||||
|
LIMIT 1
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
suspend fun getCharacterInfo(charId: Long): Character
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.github.nacabaro.vbhelper.database
|
|||||||
|
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
|
import com.github.nacabaro.vbhelper.daos.AdventureDao
|
||||||
import com.github.nacabaro.vbhelper.daos.CharacterDao
|
import com.github.nacabaro.vbhelper.daos.CharacterDao
|
||||||
import com.github.nacabaro.vbhelper.daos.DexDao
|
import com.github.nacabaro.vbhelper.daos.DexDao
|
||||||
import com.github.nacabaro.vbhelper.daos.DiMDao
|
import com.github.nacabaro.vbhelper.daos.DiMDao
|
||||||
@@ -10,12 +11,12 @@ import com.github.nacabaro.vbhelper.daos.UserCharacterDao
|
|||||||
import com.github.nacabaro.vbhelper.domain.characters.Character
|
import com.github.nacabaro.vbhelper.domain.characters.Character
|
||||||
import com.github.nacabaro.vbhelper.domain.characters.Card
|
import com.github.nacabaro.vbhelper.domain.characters.Card
|
||||||
import com.github.nacabaro.vbhelper.domain.Sprites
|
import com.github.nacabaro.vbhelper.domain.Sprites
|
||||||
|
import com.github.nacabaro.vbhelper.domain.characters.Adventure
|
||||||
import com.github.nacabaro.vbhelper.domain.characters.Dex
|
import com.github.nacabaro.vbhelper.domain.characters.Dex
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
|
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
||||||
import com.github.nacabaro.vbhelper.domain.items.Items
|
import com.github.nacabaro.vbhelper.domain.items.Items
|
||||||
import com.github.nacabaro.vbhelper.domain.items.UserItems
|
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 1,
|
version = 1,
|
||||||
@@ -28,7 +29,7 @@ import com.github.nacabaro.vbhelper.domain.items.UserItems
|
|||||||
TransformationHistory::class,
|
TransformationHistory::class,
|
||||||
Dex::class,
|
Dex::class,
|
||||||
Items::class,
|
Items::class,
|
||||||
UserItems::class
|
Adventure::class
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
@@ -37,4 +38,5 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract fun userCharacterDao(): UserCharacterDao
|
abstract fun userCharacterDao(): UserCharacterDao
|
||||||
abstract fun dexDao(): DexDao
|
abstract fun dexDao(): DexDao
|
||||||
abstract fun itemDao(): ItemDao
|
abstract fun itemDao(): ItemDao
|
||||||
|
abstract fun adventureDao(): AdventureDao
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.domain.characters
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = UserCharacter::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["characterId"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class Adventure(
|
||||||
|
@PrimaryKey val characterId: Long,
|
||||||
|
val originalDuration: Long,
|
||||||
|
val finishesAdventure: Long
|
||||||
|
)
|
||||||
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.domain.characters
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import androidx.room.ForeignKey
|
import androidx.room.ForeignKey
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
foreignKeys = [
|
foreignKeys = [
|
||||||
@@ -14,13 +15,18 @@ import androidx.room.ForeignKey
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
/*
|
||||||
|
* Character represents a character on a DIM card. There should only be one of these per dimId
|
||||||
|
* and monIndex.
|
||||||
|
* TODO: Customs will mean this should be unique per cardName and monIndex
|
||||||
|
*/
|
||||||
data class Character (
|
data class Character (
|
||||||
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
||||||
val dimId: Long,
|
val dimId: Long,
|
||||||
val monIndex: Int,
|
val monIndex: Int,
|
||||||
val name: ByteArray,
|
val name: ByteArray,
|
||||||
val stage: Int, // These should be replaced with enums
|
val stage: Int, // These should be replaced with enums
|
||||||
val attribute: Int, // This one too
|
val attribute: NfcCharacter.Attribute, // This one too
|
||||||
val baseHp: Int,
|
val baseHp: Int,
|
||||||
val baseBp: Int,
|
val baseBp: Int,
|
||||||
val baseAp: Int,
|
val baseAp: Int,
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ import com.github.nacabaro.vbhelper.domain.characters.Character
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
/**
|
||||||
|
* UserCharacter represents and instance of a character. The charId should map to a Character
|
||||||
|
*/
|
||||||
data class UserCharacter (
|
data class UserCharacter (
|
||||||
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
||||||
var charId: Long,
|
var charId: Long,
|
||||||
var stage: Int,
|
|
||||||
var attribute: NfcCharacter.Attribute,
|
|
||||||
var ageInDays: Int,
|
var ageInDays: Int,
|
||||||
var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim
|
var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim
|
||||||
var mood: Int,
|
var mood: Int,
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ data class Items(
|
|||||||
val description: String,
|
val description: String,
|
||||||
val itemIcon: Int,
|
val itemIcon: Int,
|
||||||
val itemLength: Int,
|
val itemLength: Int,
|
||||||
val price: Int
|
val price: Int,
|
||||||
|
val quantity: Int
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.github.nacabaro.vbhelper.domain.items
|
|
||||||
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.ForeignKey
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
|
|
||||||
@Entity(
|
|
||||||
foreignKeys = [
|
|
||||||
ForeignKey(
|
|
||||||
entity = Items::class,
|
|
||||||
parentColumns = ["id"],
|
|
||||||
childColumns = ["itemId"],
|
|
||||||
onDelete = ForeignKey.CASCADE
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
data class UserItems(
|
|
||||||
@PrimaryKey val itemId: Long,
|
|
||||||
val quantity: Int,
|
|
||||||
)
|
|
||||||
@@ -27,7 +27,11 @@ object CharacterDtos {
|
|||||||
val spriteIdle: ByteArray,
|
val spriteIdle: ByteArray,
|
||||||
val spriteWidth: Int,
|
val spriteWidth: Int,
|
||||||
val spriteHeight: Int,
|
val spriteHeight: Int,
|
||||||
val isBemCard: Boolean
|
val nameSprite: ByteArray,
|
||||||
|
val nameSpriteWidth: Int,
|
||||||
|
val nameSpriteHeight: Int,
|
||||||
|
val isBemCard: Boolean,
|
||||||
|
val isInAdventure: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
data class DiMInfo(
|
data class DiMInfo(
|
||||||
@@ -51,4 +55,31 @@ object CharacterDtos {
|
|||||||
val spriteHeight: Int,
|
val spriteHeight: Int,
|
||||||
val discoveredOn: Long?
|
val discoveredOn: Long?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class AdventureCharacterWithSprites(
|
||||||
|
var id: Long = 0,
|
||||||
|
var charId: Long,
|
||||||
|
var stage: Int,
|
||||||
|
var attribute: NfcCharacter.Attribute,
|
||||||
|
var ageInDays: Int,
|
||||||
|
var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim
|
||||||
|
var mood: Int,
|
||||||
|
var vitalPoints: Int,
|
||||||
|
var transformationCountdown: Int,
|
||||||
|
var injuryStatus: NfcCharacter.InjuryStatus,
|
||||||
|
var trophies: Int,
|
||||||
|
var currentPhaseBattlesWon: Int,
|
||||||
|
var currentPhaseBattlesLost: Int,
|
||||||
|
var totalBattlesWon: Int,
|
||||||
|
var totalBattlesLost: Int,
|
||||||
|
var activityLevel: Int,
|
||||||
|
var heartRateCurrent: Int,
|
||||||
|
var characterType: DeviceType,
|
||||||
|
val spriteIdle: ByteArray,
|
||||||
|
val spriteWidth: Int,
|
||||||
|
val spriteHeight: Int,
|
||||||
|
val isBemCard: Boolean,
|
||||||
|
val finishesAdventure: Long,
|
||||||
|
val originalTimeInMinutes: Long
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package com.github.nacabaro.vbhelper.dtos
|
|||||||
|
|
||||||
|
|
||||||
object ItemDtos {
|
object ItemDtos {
|
||||||
data class ItemsWithQuantities (
|
data class ItemsWithQuantities(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
@@ -11,4 +11,13 @@ object ItemDtos {
|
|||||||
val price: Int,
|
val price: Int,
|
||||||
val quantity: Int,
|
val quantity: Int,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class PurchasedItem(
|
||||||
|
val itemId: Long,
|
||||||
|
val itemName: String,
|
||||||
|
val itemDescription: String,
|
||||||
|
val itemIcon: Int,
|
||||||
|
val itemLength: Int,
|
||||||
|
val itemAmount: Int
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -16,15 +16,23 @@ import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreen
|
|||||||
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreen
|
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreen
|
||||||
import com.github.nacabaro.vbhelper.screens.SpriteViewer
|
import com.github.nacabaro.vbhelper.screens.SpriteViewer
|
||||||
import com.github.nacabaro.vbhelper.screens.StorageScreen
|
import com.github.nacabaro.vbhelper.screens.homeScreens.HomeScreenControllerImpl
|
||||||
|
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreen
|
||||||
import com.github.nacabaro.vbhelper.screens.itemsScreen.ChooseCharacterScreen
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.ChooseCharacterScreen
|
||||||
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
|
||||||
|
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreen
|
||||||
|
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
|
||||||
|
import com.github.nacabaro.vbhelper.screens.settingsScreen.CreditsScreen
|
||||||
|
import com.github.nacabaro.vbhelper.screens.storageScreen.StorageScreenControllerImpl
|
||||||
|
|
||||||
data class AppNavigationHandlers(
|
data class AppNavigationHandlers(
|
||||||
val settingsScreenController: SettingsScreenControllerImpl,
|
val settingsScreenController: SettingsScreenControllerImpl,
|
||||||
val scanScreenController: ScanScreenControllerImpl,
|
val scanScreenController: ScanScreenControllerImpl,
|
||||||
val itemsScreenController: ItemsScreenControllerImpl
|
val itemsScreenController: ItemsScreenControllerImpl,
|
||||||
|
val adventureScreenController: AdventureScreenControllerImpl,
|
||||||
|
val storageScreenController: StorageScreenControllerImpl,
|
||||||
|
val homeScreenController: HomeScreenControllerImpl
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -49,12 +57,15 @@ fun AppNavigation(
|
|||||||
}
|
}
|
||||||
composable(NavigationItems.Home.route) {
|
composable(NavigationItems.Home.route) {
|
||||||
HomeScreen(
|
HomeScreen(
|
||||||
navController = navController
|
navController = navController,
|
||||||
|
homeScreenController = applicationNavigationHandlers.homeScreenController
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(NavigationItems.Storage.route) {
|
composable(NavigationItems.Storage.route) {
|
||||||
StorageScreen(
|
StorageScreen(
|
||||||
navController = navController
|
navController = navController,
|
||||||
|
adventureScreenController = applicationNavigationHandlers.adventureScreenController,
|
||||||
|
storageScreenController = applicationNavigationHandlers.storageScreenController
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(NavigationItems.Scan.route) {
|
composable(NavigationItems.Scan.route) {
|
||||||
@@ -108,6 +119,18 @@ fun AppNavigation(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
composable(NavigationItems.Adventure.route) {
|
||||||
|
AdventureScreen(
|
||||||
|
navController = navController,
|
||||||
|
storageScreenController = applicationNavigationHandlers
|
||||||
|
.adventureScreenController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
composable(NavigationItems.Credits.route) {
|
||||||
|
CreditsScreen(
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ fun BottomNavigationBar(navController: NavController) {
|
|||||||
NavigationItems.Dex,
|
NavigationItems.Dex,
|
||||||
NavigationItems.Storage,
|
NavigationItems.Storage,
|
||||||
)
|
)
|
||||||
|
|
||||||
NavigationBar {
|
NavigationBar {
|
||||||
val currentBackStackEntry = navController.currentBackStackEntryAsState()
|
val currentBackStackEntry = navController.currentBackStackEntryAsState()
|
||||||
val currentRoute = currentBackStackEntry.value?.destination?.route
|
val currentRoute = currentBackStackEntry.value?.destination?.route
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ sealed class NavigationItems (
|
|||||||
object MyItems : NavigationItems("MyItems", R.drawable.baseline_data_24, "My items")
|
object MyItems : NavigationItems("MyItems", R.drawable.baseline_data_24, "My items")
|
||||||
object ItemsStore : NavigationItems("ItemsStore", R.drawable.baseline_data_24, "Items store")
|
object ItemsStore : NavigationItems("ItemsStore", R.drawable.baseline_data_24, "Items store")
|
||||||
object ApplyItem : NavigationItems("ApplyItem/{itemId}", R.drawable.baseline_data_24, "Apply item")
|
object ApplyItem : NavigationItems("ApplyItem/{itemId}", R.drawable.baseline_data_24, "Apply item")
|
||||||
|
object Adventure : NavigationItems("Adventure", R.drawable.baseline_fort_24, "Adventure")
|
||||||
|
object Credits : NavigationItems("Credits", R.drawable.baseline_data_24, "Credits")
|
||||||
}
|
}
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens
|
|
||||||
|
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
|
||||||
import androidx.compose.foundation.gestures.scrollable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Card
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.window.Dialog
|
|
||||||
import androidx.compose.ui.window.DialogProperties
|
|
||||||
import androidx.navigation.NavController
|
|
||||||
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
|
||||||
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
|
||||||
import com.github.nacabaro.vbhelper.source.StorageRepository
|
|
||||||
import com.github.nacabaro.vbhelper.utils.BitmapData
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun StorageScreen(
|
|
||||||
navController: NavController
|
|
||||||
) {
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
|
||||||
val storageRepository = StorageRepository(application.container.db)
|
|
||||||
val monList = remember { mutableStateOf<List<CharacterDtos.CharacterWithSprites>>(emptyList()) }
|
|
||||||
|
|
||||||
var selectedCharacter by remember { mutableStateOf<Long?>(null) }
|
|
||||||
|
|
||||||
LaunchedEffect(storageRepository) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
val characterList = storageRepository.getAllCharacters()
|
|
||||||
monList.value = characterList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold (
|
|
||||||
topBar = { TopBanner(text = "My characters") }
|
|
||||||
) { contentPadding ->
|
|
||||||
if (monList.value.isEmpty()) {
|
|
||||||
Column (
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(top = contentPadding.calculateTopPadding())
|
|
||||||
.fillMaxSize()
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "Nothing to see here",
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyVerticalGrid(
|
|
||||||
columns = GridCells.Fixed(3),
|
|
||||||
modifier = Modifier
|
|
||||||
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
|
|
||||||
.padding(top = contentPadding.calculateTopPadding())
|
|
||||||
) {
|
|
||||||
items(monList.value) { index ->
|
|
||||||
CharacterEntry(
|
|
||||||
icon = BitmapData(
|
|
||||||
bitmap = index.spriteIdle,
|
|
||||||
width = index.spriteWidth,
|
|
||||||
height = index.spriteHeight
|
|
||||||
),
|
|
||||||
onClick = {
|
|
||||||
selectedCharacter = index.id
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedCharacter != null) {
|
|
||||||
StorageDialog(
|
|
||||||
characterId = selectedCharacter!!,
|
|
||||||
onDismissRequest = { selectedCharacter = null },
|
|
||||||
onClickSetActive = {
|
|
||||||
coroutineScope.launch {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
storageRepository.setActiveCharacter(selectedCharacter!!)
|
|
||||||
selectedCharacter = null
|
|
||||||
}
|
|
||||||
navController.navigate(NavigationItems.Home.route)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSendToBracelet = {
|
|
||||||
navController.navigate(
|
|
||||||
NavigationItems.Scan.route.replace(
|
|
||||||
"{characterId}",
|
|
||||||
selectedCharacter.toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun StorageDialog(
|
|
||||||
characterId: Long,
|
|
||||||
onDismissRequest: () -> Unit,
|
|
||||||
onSendToBracelet: () -> Unit,
|
|
||||||
onClickSetActive: () -> Unit
|
|
||||||
) {
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
|
||||||
val storageRepository = StorageRepository(application.container.db)
|
|
||||||
val character = remember { mutableStateOf<UserCharacter?>(null) }
|
|
||||||
|
|
||||||
LaunchedEffect(storageRepository) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
character.value = storageRepository.getSingleCharacter(characterId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
properties = DialogProperties(
|
|
||||||
dismissOnBackPress = true,
|
|
||||||
dismissOnClickOutside = true
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Card(
|
|
||||||
shape = RoundedCornerShape(16.dp)
|
|
||||||
) {
|
|
||||||
Column (
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
|
||||||
if (character.value != null) {
|
|
||||||
Text(
|
|
||||||
text = character.value?.toString() ?: "Loading...",
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(8.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row (
|
|
||||||
modifier = Modifier
|
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
) {
|
|
||||||
Button(
|
|
||||||
onClick = onSendToBracelet
|
|
||||||
) {
|
|
||||||
Text(text = "Send to bracelet")
|
|
||||||
}
|
|
||||||
Button(
|
|
||||||
onClick = onClickSetActive
|
|
||||||
) {
|
|
||||||
Text(text = "Set active")
|
|
||||||
}
|
|
||||||
Button(
|
|
||||||
onClick = onDismissRequest
|
|
||||||
) {
|
|
||||||
Text(text = "Close")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.adventureScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getBitmap
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AdventureEntry(
|
||||||
|
icon: BitmapData,
|
||||||
|
timeLeft: Long,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
val bitmap = remember (icon.bitmap) { icon.getBitmap() }
|
||||||
|
val imageBitmap = remember(bitmap) { bitmap.asImageBitmap() }
|
||||||
|
val density: Float = LocalContext.current.resources.displayMetrics.density
|
||||||
|
val dpSize = (icon.width * 4 / density).dp
|
||||||
|
|
||||||
|
Card(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
.height(96.dp)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
bitmap = imageBitmap,
|
||||||
|
contentDescription = null,
|
||||||
|
filterQuality = FilterQuality.None,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(dpSize)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = when {
|
||||||
|
timeLeft < 0 -> "Adventure finished"
|
||||||
|
else -> "Time left: ${formatSeconds(timeLeft)}"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formatSeconds(totalSeconds: Long): String {
|
||||||
|
val hours = totalSeconds / 3600
|
||||||
|
val minutes = (totalSeconds % 3600) / 60
|
||||||
|
val seconds = totalSeconds % 60
|
||||||
|
|
||||||
|
return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, seconds)
|
||||||
|
}
|
||||||
+145
@@ -0,0 +1,145 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.adventureScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.produceState
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.ObtainedItemDialog
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AdventureScreen(
|
||||||
|
navController: NavController,
|
||||||
|
storageScreenController: AdventureScreenControllerImpl
|
||||||
|
) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val database = application.container.db
|
||||||
|
val storageRepository = StorageRepository(database)
|
||||||
|
val characterList = remember {
|
||||||
|
mutableStateOf<List<CharacterDtos.AdventureCharacterWithSprites>>(emptyList())
|
||||||
|
}
|
||||||
|
var obtainedItem by remember {
|
||||||
|
mutableStateOf<ItemDtos.PurchasedItem?>(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentTime by produceState(initialValue = Instant.now().epochSecond) {
|
||||||
|
while (true) {
|
||||||
|
value = Instant.now().epochSecond
|
||||||
|
delay(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cancelAdventureDialog by remember {
|
||||||
|
mutableStateOf<CharacterDtos.AdventureCharacterWithSprites?>(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(storageRepository) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
characterList.value = storageRepository
|
||||||
|
.getAdventureCharacters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Adventure",
|
||||||
|
onBackClick = {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { contentPadding ->
|
||||||
|
if (characterList.value.isEmpty()) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text(text = "Nothing to see here")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
) {
|
||||||
|
items(characterList.value) {
|
||||||
|
AdventureEntry(
|
||||||
|
icon = BitmapData(
|
||||||
|
bitmap = it.spriteIdle,
|
||||||
|
width = it.spriteWidth,
|
||||||
|
height = it.spriteHeight
|
||||||
|
),
|
||||||
|
timeLeft = it.finishesAdventure - currentTime,
|
||||||
|
onClick = {
|
||||||
|
if (it.finishesAdventure < currentTime) {
|
||||||
|
storageScreenController
|
||||||
|
.getItemFromAdventure(it.id) { adventureResult ->
|
||||||
|
obtainedItem = adventureResult
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cancelAdventureDialog = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obtainedItem != null) {
|
||||||
|
ObtainedItemDialog(
|
||||||
|
obtainedItem = obtainedItem!!,
|
||||||
|
onClickDismiss = {
|
||||||
|
obtainedItem = null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelAdventureDialog != null) {
|
||||||
|
CancelAdventureDialog(
|
||||||
|
characterSprite = BitmapData(
|
||||||
|
bitmap = cancelAdventureDialog!!.spriteIdle,
|
||||||
|
width = cancelAdventureDialog!!.spriteWidth,
|
||||||
|
height = cancelAdventureDialog!!.spriteHeight
|
||||||
|
),
|
||||||
|
onDismissRequest = {
|
||||||
|
cancelAdventureDialog = null
|
||||||
|
},
|
||||||
|
onClickConfirm = {
|
||||||
|
storageScreenController.cancelAdventure(cancelAdventureDialog!!.id) {
|
||||||
|
navController.navigate(NavigationItems.Storage.route)
|
||||||
|
}
|
||||||
|
cancelAdventureDialog = null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.adventureScreen
|
||||||
|
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
|
|
||||||
|
interface AdventureScreenController {
|
||||||
|
fun sendCharacterToAdventure(characterId: Long, timeInMinutes: Long)
|
||||||
|
fun getItemFromAdventure(characterId: Long, onResult: (ItemDtos.PurchasedItem) -> Unit)
|
||||||
|
fun cancelAdventure(characterId: Long, onResult: () -> Unit)
|
||||||
|
}
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.adventureScreen
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
class AdventureScreenControllerImpl(
|
||||||
|
private val componentActivity: ComponentActivity,
|
||||||
|
) : AdventureScreenController {
|
||||||
|
private val application = componentActivity.applicationContext as VBHelper
|
||||||
|
private val database = application.container.db
|
||||||
|
|
||||||
|
override fun sendCharacterToAdventure(characterId: Long, timeInMinutes: Long) {
|
||||||
|
val finishesAdventureAt = timeInMinutes * 60
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val characterData = database
|
||||||
|
.userCharacterDao()
|
||||||
|
.getCharacter(characterId)
|
||||||
|
|
||||||
|
if (characterData.isActive) {
|
||||||
|
database
|
||||||
|
.userCharacterDao()
|
||||||
|
.clearActiveCharacter()
|
||||||
|
}
|
||||||
|
|
||||||
|
database
|
||||||
|
.adventureDao()
|
||||||
|
.insertNewAdventure(characterId, timeInMinutes, finishesAdventureAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemFromAdventure(
|
||||||
|
characterId: Long,
|
||||||
|
onResult: (ItemDtos.PurchasedItem) -> Unit
|
||||||
|
) {
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
database
|
||||||
|
.adventureDao()
|
||||||
|
.deleteAdventure(characterId)
|
||||||
|
|
||||||
|
val generatedItem = generateItem(characterId)
|
||||||
|
|
||||||
|
onResult(generatedItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancelAdventure(characterId: Long, onResult: () -> Unit) {
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
database
|
||||||
|
.adventureDao()
|
||||||
|
.deleteAdventure(characterId)
|
||||||
|
|
||||||
|
componentActivity
|
||||||
|
.runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
componentActivity,
|
||||||
|
"Adventure canceled",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
onResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun generateItem(characterId: Long): ItemDtos.PurchasedItem {
|
||||||
|
val character = database
|
||||||
|
.userCharacterDao()
|
||||||
|
.getCharacterInfo(characterId)
|
||||||
|
|
||||||
|
val randomItem = database
|
||||||
|
.itemDao()
|
||||||
|
.getAllItems()
|
||||||
|
.random()
|
||||||
|
|
||||||
|
val random = ((Random.nextFloat() * character.stage) + 3).roundToInt()
|
||||||
|
|
||||||
|
database
|
||||||
|
.itemDao()
|
||||||
|
.purchaseItem(
|
||||||
|
itemId = randomItem.id,
|
||||||
|
itemAmount = random
|
||||||
|
)
|
||||||
|
|
||||||
|
return ItemDtos.PurchasedItem(
|
||||||
|
itemId = randomItem.id,
|
||||||
|
itemAmount = random,
|
||||||
|
itemName = randomItem.name,
|
||||||
|
itemIcon = randomItem.itemIcon,
|
||||||
|
itemLength = randomItem.itemLength,
|
||||||
|
itemDescription = randomItem.description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.adventureScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getBitmap
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CancelAdventureDialog(
|
||||||
|
characterSprite: BitmapData,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onClickConfirm: () -> Unit
|
||||||
|
) {
|
||||||
|
val bitmap = remember (characterSprite) { characterSprite.getBitmap() }
|
||||||
|
val imageBitmap = remember(bitmap) { bitmap.asImageBitmap() }
|
||||||
|
val density: Float = LocalContext.current.resources.displayMetrics.density
|
||||||
|
val dpSize = (characterSprite.width * 4 / density).dp
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onDismissRequest
|
||||||
|
) {
|
||||||
|
Card {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Image(
|
||||||
|
bitmap = imageBitmap,
|
||||||
|
contentDescription = null,
|
||||||
|
filterQuality = FilterQuality.None,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(dpSize)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Are you sure you want to cancel this character's adventure?"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onClickConfirm
|
||||||
|
) {
|
||||||
|
Text(text = "Confirm")
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.padding(4.dp))
|
||||||
|
Button(
|
||||||
|
onClick = onDismissRequest
|
||||||
|
) {
|
||||||
|
Text(text = "Dismiss")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -15,7 +15,7 @@ import com.github.nacabaro.vbhelper.R
|
|||||||
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
||||||
import com.github.nacabaro.vbhelper.components.ItemDisplay
|
import com.github.nacabaro.vbhelper.components.ItemDisplay
|
||||||
import com.github.nacabaro.vbhelper.components.TransformationHistoryCard
|
import com.github.nacabaro.vbhelper.components.TransformationHistoryCard
|
||||||
import com.github.nacabaro.vbhelper.components.getIconResource
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.getIconResource
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ import com.github.nacabaro.vbhelper.R
|
|||||||
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
||||||
import com.github.nacabaro.vbhelper.components.ItemDisplay
|
import com.github.nacabaro.vbhelper.components.ItemDisplay
|
||||||
import com.github.nacabaro.vbhelper.components.TransformationHistoryCard
|
import com.github.nacabaro.vbhelper.components.TransformationHistoryCard
|
||||||
import com.github.nacabaro.vbhelper.components.getIconResource
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.getIconResource
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.homeScreens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BetaWarning(
|
||||||
|
onDismissRequest: () -> Unit
|
||||||
|
) {
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onDismissRequest
|
||||||
|
) {
|
||||||
|
Card {
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "This application is currently in alpha and it is not complete. Do not use to store important characters for you, as any future updates might delete all your characters. Sorry for the inconvenience!"
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.padding(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "Also, this application does not work yet with the original VB."
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.padding(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "Thank you for your understanding and patience. Sincerely, the dev team."
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.padding(8.dp))
|
||||||
|
Button(
|
||||||
|
onClick = onDismissRequest
|
||||||
|
) {
|
||||||
|
Text(text = "Dismiss")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,16 +3,25 @@ package com.github.nacabaro.vbhelper.screens.homeScreens
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
@@ -27,7 +36,8 @@ import kotlinx.coroutines.withContext
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen(
|
fun HomeScreen(
|
||||||
navController: NavController
|
navController: NavController,
|
||||||
|
homeScreenController: HomeScreenControllerImpl
|
||||||
) {
|
) {
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
val storageRepository = StorageRepository(application.container.db)
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
@@ -35,6 +45,8 @@ fun HomeScreen(
|
|||||||
val transformationHistory = remember { mutableStateOf<List<CharacterDtos.TransformationHistory>?>(null) }
|
val transformationHistory = remember { mutableStateOf<List<CharacterDtos.TransformationHistory>?>(null) }
|
||||||
val beData = remember { mutableStateOf<BECharacterData?>(null) }
|
val beData = remember { mutableStateOf<BECharacterData?>(null) }
|
||||||
val vbData = remember { mutableStateOf<VBCharacterData?>(null) }
|
val vbData = remember { mutableStateOf<VBCharacterData?>(null) }
|
||||||
|
var adventureMissionsFinished by rememberSaveable { mutableStateOf(false) }
|
||||||
|
var betaWarning by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
LaunchedEffect(storageRepository, activeMon) {
|
LaunchedEffect(storageRepository, activeMon) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
@@ -46,6 +58,13 @@ fun HomeScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(true) {
|
||||||
|
homeScreenController
|
||||||
|
.didAdventureMissionsFinish {
|
||||||
|
adventureMissionsFinished = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBanner(
|
TopBanner(
|
||||||
@@ -94,6 +113,40 @@ fun HomeScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adventureMissionsFinished) {
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = { adventureMissionsFinished = false },
|
||||||
|
) {
|
||||||
|
Card {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "One of your characters has finished their adventure mission!",
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
adventureMissionsFinished = false
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = "Dismiss")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (betaWarning) {
|
||||||
|
BetaWarning {
|
||||||
|
betaWarning = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.homeScreens
|
||||||
|
|
||||||
|
interface HomeScreenController {
|
||||||
|
fun didAdventureMissionsFinish(onCompletion: (Boolean) -> Unit)
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.homeScreens
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class HomeScreenControllerImpl(
|
||||||
|
private val componentActivity: ComponentActivity,
|
||||||
|
): HomeScreenController {
|
||||||
|
private val application = componentActivity.applicationContext as VBHelper
|
||||||
|
private val database = application.container.db
|
||||||
|
|
||||||
|
override fun didAdventureMissionsFinish(onCompletion: (Boolean) -> Unit) {
|
||||||
|
componentActivity.lifecycleScope.launch {
|
||||||
|
val currentTime = Instant.now().epochSecond
|
||||||
|
val adventureCharacters = database
|
||||||
|
.adventureDao()
|
||||||
|
.getAdventureCharacters()
|
||||||
|
|
||||||
|
val finishedAdventureCharacters = adventureCharacters.filter { character ->
|
||||||
|
character.finishesAdventure <= currentTime
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompletion(finishedAdventureCharacters.isNotEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-4
@@ -1,4 +1,4 @@
|
|||||||
package com.github.nacabaro.vbhelper.components
|
package com.github.nacabaro.vbhelper.screens.itemsScreen
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.github.nacabaro.vbhelper.R
|
import com.github.nacabaro.vbhelper.R
|
||||||
import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl
|
|
||||||
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -123,7 +122,10 @@ fun ItemDialog(
|
|||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
|
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
|
||||||
fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
|
fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
|
||||||
text = description
|
text = description,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(4.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
@@ -132,7 +134,7 @@ fun ItemDialog(
|
|||||||
text = "You have $amount of this item",
|
text = "You have $amount of this item",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(16.dp)
|
.padding(8.dp)
|
||||||
)
|
)
|
||||||
Row (
|
Row (
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
+1
-1
@@ -107,7 +107,7 @@ class ItemsScreenControllerImpl (
|
|||||||
private fun getItem(itemId: Long): ItemDtos.ItemsWithQuantities {
|
private fun getItem(itemId: Long): ItemDtos.ItemsWithQuantities {
|
||||||
return database
|
return database
|
||||||
.itemDao()
|
.itemDao()
|
||||||
.getUserItem(itemId)
|
.getItem(itemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeItem(itemId: Long) {
|
private fun consumeItem(itemId: Long) {
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.github.nacabaro.vbhelper.components.ItemDialog
|
|
||||||
import com.github.nacabaro.vbhelper.components.ItemElement
|
|
||||||
import com.github.nacabaro.vbhelper.components.getIconResource
|
|
||||||
import com.github.nacabaro.vbhelper.components.getLengthResource
|
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
import com.github.nacabaro.vbhelper.source.ItemsRepository
|
import com.github.nacabaro.vbhelper.source.ItemsRepository
|
||||||
|
|||||||
@@ -19,10 +19,6 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.github.nacabaro.vbhelper.components.ItemDialog
|
|
||||||
import com.github.nacabaro.vbhelper.components.ItemElement
|
|
||||||
import com.github.nacabaro.vbhelper.components.getIconResource
|
|
||||||
import com.github.nacabaro.vbhelper.components.getLengthResource
|
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
|
|||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.itemsScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
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.layout.size
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ObtainedItemDialog(
|
||||||
|
obtainedItem: ItemDtos.PurchasedItem,
|
||||||
|
onClickDismiss: () -> Unit
|
||||||
|
) {
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onClickDismiss
|
||||||
|
) {
|
||||||
|
Card {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Box(modifier = Modifier) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = getIconResource(obtainedItem.itemIcon)),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(96.dp)
|
||||||
|
.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = getLengthResource(obtainedItem.itemLength)),
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.outline,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(64.dp)
|
||||||
|
.align(Alignment.BottomEnd)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
fontSize = MaterialTheme.typography.titleLarge.fontSize,
|
||||||
|
text = obtainedItem.itemName,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
|
||||||
|
fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
|
||||||
|
text = obtainedItem.itemDescription,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(4.dp)
|
||||||
|
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
|
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||||
|
text = "You have obtained ${obtainedItem.itemAmount} of this item",
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(5.dp)
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
onClick = onClickDismiss,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = "Dismiss")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-2
@@ -167,8 +167,6 @@ class ScanScreenControllerImpl(
|
|||||||
|
|
||||||
val characterData = UserCharacter(
|
val characterData = UserCharacter(
|
||||||
charId = cardCharData.id,
|
charId = cardCharData.id,
|
||||||
stage = nfcCharacter.stage.toInt(),
|
|
||||||
attribute = nfcCharacter.attribute,
|
|
||||||
ageInDays = nfcCharacter.ageInDays.toInt(),
|
ageInDays = nfcCharacter.ageInDays.toInt(),
|
||||||
nextAdventureMissionStage = nfcCharacter.nextAdventureMissionStage.toInt(),
|
nextAdventureMissionStage = nfcCharacter.nextAdventureMissionStage.toInt(),
|
||||||
mood = nfcCharacter.mood.toInt(),
|
mood = nfcCharacter.mood.toInt(),
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.settingsScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CreditsScreen(
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
Scaffold (
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Credits",
|
||||||
|
onBackClick = {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) { contentPadding ->
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
) {
|
||||||
|
SettingsSection("Reverse engineering")
|
||||||
|
SettingsEntry(title = "cyanic", description = "Reversed the firmware and helped us during development.") { }
|
||||||
|
SettingsSection("Application development")
|
||||||
|
SettingsEntry(title = "cfogrady", description = "Developed vb-lib-nfc and part of this application.") { }
|
||||||
|
SettingsEntry(title = "nacabaro", description = "Developed this application.") { }
|
||||||
|
SettingsEntry(title = "lightheel", description = "Developing the battling part for this application, including server. Still in the works.") { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-8
@@ -18,6 +18,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(
|
fun SettingsScreen(
|
||||||
@@ -46,6 +47,16 @@ fun SettingsScreen(
|
|||||||
SettingsEntry(title = "Import APK", description = "Import Secrets From Vital Arean 2.1.0 APK") {
|
SettingsEntry(title = "Import APK", description = "Import Secrets From Vital Arean 2.1.0 APK") {
|
||||||
settingsScreenController.onClickImportApk()
|
settingsScreenController.onClickImportApk()
|
||||||
}
|
}
|
||||||
|
SettingsSection("DiM/BEm management")
|
||||||
|
SettingsEntry(title = "Import card", description = "Import DiM/BEm card file") {
|
||||||
|
settingsScreenController.onClickImportCard()
|
||||||
|
}
|
||||||
|
SettingsEntry(title = "Rename DiM/BEm", description = "Set card name") { }
|
||||||
|
SettingsSection("About and credits")
|
||||||
|
SettingsEntry(title = "Credits", description = "Credits") {
|
||||||
|
navController.navigate(NavigationItems.Credits.route)
|
||||||
|
}
|
||||||
|
SettingsEntry(title = "About", description = "About") { }
|
||||||
SettingsSection("Data management")
|
SettingsSection("Data management")
|
||||||
SettingsEntry(title = "Export data", description = "Export application database") {
|
SettingsEntry(title = "Export data", description = "Export application database") {
|
||||||
settingsScreenController.onClickOpenDirectory()
|
settingsScreenController.onClickOpenDirectory()
|
||||||
@@ -53,14 +64,6 @@ fun SettingsScreen(
|
|||||||
SettingsEntry(title = "Import data", description = "Import application database") {
|
SettingsEntry(title = "Import data", description = "Import application database") {
|
||||||
settingsScreenController.onClickImportDatabase()
|
settingsScreenController.onClickImportDatabase()
|
||||||
}
|
}
|
||||||
SettingsSection("DiM/BEm management")
|
|
||||||
SettingsEntry(title = "Import DiM card", description = "Import DiM/BEm card file") {
|
|
||||||
settingsScreenController.onClickImportCard()
|
|
||||||
}
|
|
||||||
SettingsEntry(title = "Rename DiM/BEm", description = "Set card name") { }
|
|
||||||
SettingsSection("About and credits")
|
|
||||||
SettingsEntry(title = "Credits", description = "Credits") { }
|
|
||||||
SettingsEntry(title = "About", description = "About") { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -11,6 +11,7 @@ import androidx.activity.result.ActivityResultLauncher
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import com.github.cfogrady.vb.dim.card.BemCard
|
import com.github.cfogrady.vb.dim.card.BemCard
|
||||||
import com.github.cfogrady.vb.dim.card.DimReader
|
import com.github.cfogrady.vb.dim.card.DimReader
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
import com.github.nacabaro.vbhelper.database.AppDatabase
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.domain.Sprites
|
import com.github.nacabaro.vbhelper.domain.Sprites
|
||||||
@@ -131,7 +132,7 @@ class SettingsScreenControllerImpl(
|
|||||||
val characters = card.characterStats.characterEntries
|
val characters = card.characterStats.characterEntries
|
||||||
|
|
||||||
var spriteCounter = when (card is BemCard) {
|
var spriteCounter = when (card is BemCard) {
|
||||||
true -> 55
|
true -> 54
|
||||||
false -> 10
|
false -> 10
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ class SettingsScreenControllerImpl(
|
|||||||
monIndex = index,
|
monIndex = index,
|
||||||
name = card.spriteData.sprites[spriteCounter].pixelData,
|
name = card.spriteData.sprites[spriteCounter].pixelData,
|
||||||
stage = characters[index].stage,
|
stage = characters[index].stage,
|
||||||
attribute = characters[index].attribute,
|
attribute = NfcCharacter.Attribute.entries[characters[index].attribute],
|
||||||
baseHp = characters[index].hp,
|
baseHp = characters[index].hp,
|
||||||
baseBp = characters[index].dp,
|
baseBp = characters[index].dp,
|
||||||
baseAp = characters[index].ap,
|
baseAp = characters[index].ap,
|
||||||
|
|||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.storageScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.github.nacabaro.vbhelper.R
|
||||||
|
|
||||||
|
fun getAdventureTime(time: Int): String {
|
||||||
|
return when (time) {
|
||||||
|
360 -> "6 hours"
|
||||||
|
720 -> "12 hours"
|
||||||
|
1440 -> "24 hours"
|
||||||
|
else -> "Unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun StorageAdventureTimeDialog(
|
||||||
|
onClickSendToAdventure: (time: Long) -> Unit,
|
||||||
|
onDismissRequest: () -> Unit
|
||||||
|
) {
|
||||||
|
val times = arrayOf(360, 720, 1440)
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
var itemPosition by remember { mutableIntStateOf(-1) }
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onDismissRequest
|
||||||
|
) {
|
||||||
|
Card {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Row (
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
modifier = Modifier
|
||||||
|
.width(256.dp)
|
||||||
|
.clickable(true) {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = when (itemPosition) {
|
||||||
|
-1 -> "Choose time"
|
||||||
|
else -> getAdventureTime(times[itemPosition])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.baseline_single_arrow_down),
|
||||||
|
contentDescription = "Show more"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false },
|
||||||
|
modifier = Modifier
|
||||||
|
.width(256.dp)
|
||||||
|
) {
|
||||||
|
times.forEach { time ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(getAdventureTime(time)) },
|
||||||
|
onClick = {
|
||||||
|
itemPosition = times.indexOf(time)
|
||||||
|
expanded = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
onClick = {
|
||||||
|
if (itemPosition != -1) {
|
||||||
|
onClickSendToAdventure(times[itemPosition].toLong())
|
||||||
|
onDismissRequest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(text = "Send on adventure")
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
onClick = onDismissRequest
|
||||||
|
) {
|
||||||
|
Text(text = "Dismiss")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+163
@@ -0,0 +1,163 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.storageScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getBitmap
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun StorageDialog(
|
||||||
|
characterId: Long,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onSendToBracelet: () -> Unit,
|
||||||
|
onClickSetActive: () -> Unit,
|
||||||
|
onClickSendToAdventure: (time: Long) -> Unit
|
||||||
|
) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
|
val character = remember { mutableStateOf<CharacterDtos.CharacterWithSprites?>(null) }
|
||||||
|
val characterSprite = remember { mutableStateOf<BitmapData?>(null) }
|
||||||
|
val characterName = remember { mutableStateOf<BitmapData?>(null) }
|
||||||
|
var onSendToAdventureClicked by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
LaunchedEffect(storageRepository) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
character.value = storageRepository.getSingleCharacter(characterId)
|
||||||
|
characterSprite.value = BitmapData(
|
||||||
|
bitmap = character.value!!.spriteIdle,
|
||||||
|
width = character.value!!.spriteWidth,
|
||||||
|
height = character.value!!.spriteHeight
|
||||||
|
)
|
||||||
|
characterName.value = BitmapData(
|
||||||
|
bitmap = character.value!!.nameSprite,
|
||||||
|
width = character.value!!.nameSpriteWidth,
|
||||||
|
height = character.value!!.nameSpriteHeight
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
properties = DialogProperties(
|
||||||
|
dismissOnBackPress = true,
|
||||||
|
dismissOnClickOutside = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
) {
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
if (character.value != null &&
|
||||||
|
characterSprite.value != null &&
|
||||||
|
characterName.value != null
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
val bitmap = remember (characterSprite.value!!) { characterSprite.value!!.getBitmap() }
|
||||||
|
val imageBitmap = remember(bitmap) { bitmap.asImageBitmap() }
|
||||||
|
val density: Float = LocalContext.current.resources.displayMetrics.density
|
||||||
|
val dpSize = (characterSprite.value!!.width * 4 / density).dp
|
||||||
|
Image(
|
||||||
|
bitmap = imageBitmap,
|
||||||
|
contentDescription = "Character image",
|
||||||
|
filterQuality = FilterQuality.None,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(dpSize)
|
||||||
|
)
|
||||||
|
val nameBitmap = remember (characterName.value!!) { characterName.value!!.getBitmap() }
|
||||||
|
val nameImageBitmap = remember(nameBitmap) { nameBitmap.asImageBitmap() }
|
||||||
|
val nameDpSize = (characterName.value!!.width * 4 / density).dp
|
||||||
|
Image(
|
||||||
|
bitmap = nameImageBitmap,
|
||||||
|
contentDescription = "Character image",
|
||||||
|
filterQuality = FilterQuality.None,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(nameDpSize)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onSendToBracelet,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
Text(text = "Send to watch")
|
||||||
|
}
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(4.dp)
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
onClick = onClickSetActive,
|
||||||
|
) {
|
||||||
|
Text(text = "Set active")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
onSendToAdventureClicked = true
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(text = "Send on adventure")
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
onClick = onDismissRequest
|
||||||
|
) {
|
||||||
|
Text(text = "Close")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onSendToAdventureClicked) {
|
||||||
|
StorageAdventureTimeDialog(
|
||||||
|
onClickSendToAdventure = { time ->
|
||||||
|
onClickSendToAdventure(time)
|
||||||
|
},
|
||||||
|
onDismissRequest = { onSendToAdventureClicked = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+145
@@ -0,0 +1,145 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.storageScreen
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
|
import androidx.compose.foundation.gestures.scrollable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
|
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
|
||||||
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun StorageScreen(
|
||||||
|
navController: NavController,
|
||||||
|
storageScreenController: StorageScreenControllerImpl,
|
||||||
|
adventureScreenController: AdventureScreenControllerImpl
|
||||||
|
) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
|
val monList = remember { mutableStateOf<List<CharacterDtos.CharacterWithSprites>>(emptyList()) }
|
||||||
|
var selectedCharacter by remember { mutableStateOf<Long?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(storageRepository, selectedCharacter) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
val characterList = storageRepository.getAllCharacters()
|
||||||
|
monList.value = characterList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold (
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "My characters",
|
||||||
|
onAdventureClick = {
|
||||||
|
navController.navigate(NavigationItems.Adventure.route)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { contentPadding ->
|
||||||
|
if (monList.value.isEmpty()) {
|
||||||
|
Column (
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Nothing to see here",
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LazyVerticalGrid(
|
||||||
|
columns = GridCells.Fixed(3),
|
||||||
|
modifier = Modifier
|
||||||
|
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
) {
|
||||||
|
items(monList.value) { index ->
|
||||||
|
CharacterEntry(
|
||||||
|
icon = BitmapData(
|
||||||
|
bitmap = index.spriteIdle,
|
||||||
|
width = index.spriteWidth,
|
||||||
|
height = index.spriteHeight
|
||||||
|
),
|
||||||
|
onClick = {
|
||||||
|
if (!index.isInAdventure) {
|
||||||
|
selectedCharacter = index.id
|
||||||
|
} else {
|
||||||
|
Toast.makeText(
|
||||||
|
application,
|
||||||
|
"This character is in an adventure",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
navController.navigate(
|
||||||
|
NavigationItems.Adventure.route
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedCharacter != null) {
|
||||||
|
StorageDialog(
|
||||||
|
characterId = selectedCharacter!!,
|
||||||
|
onDismissRequest = { selectedCharacter = null },
|
||||||
|
onClickSetActive = {
|
||||||
|
storageScreenController
|
||||||
|
.setActive(selectedCharacter!!) {
|
||||||
|
selectedCharacter = null
|
||||||
|
navController.navigate(NavigationItems.Home.route)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSendToBracelet = {
|
||||||
|
navController.navigate(
|
||||||
|
NavigationItems.Scan.route.replace(
|
||||||
|
"{characterId}",
|
||||||
|
selectedCharacter.toString()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClickSendToAdventure = { time ->
|
||||||
|
adventureScreenController
|
||||||
|
.sendCharacterToAdventure(
|
||||||
|
characterId = selectedCharacter!!,
|
||||||
|
timeInMinutes = time
|
||||||
|
)
|
||||||
|
selectedCharacter = null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.storageScreen
|
||||||
|
|
||||||
|
interface StorageScreenController {
|
||||||
|
fun setActive(characterId: Long, onCompletion: () -> Unit)
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.storageScreen
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class StorageScreenControllerImpl(
|
||||||
|
private val componentActivity: ComponentActivity
|
||||||
|
): StorageScreenController {
|
||||||
|
private val application = componentActivity.applicationContext as VBHelper
|
||||||
|
private val database = application.container.db
|
||||||
|
|
||||||
|
override fun setActive(characterId: Long, onCompletion: () -> Unit) {
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
database.userCharacterDao().clearActiveCharacter()
|
||||||
|
database.userCharacterDao().setActiveCharacter(characterId)
|
||||||
|
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
componentActivity,
|
||||||
|
"Active character updated!",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
onCompletion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,6 @@ package com.github.nacabaro.vbhelper.source
|
|||||||
|
|
||||||
import com.github.nacabaro.vbhelper.database.AppDatabase
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
|
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
|
||||||
class StorageRepository (
|
class StorageRepository (
|
||||||
@@ -13,8 +11,8 @@ class StorageRepository (
|
|||||||
return db.userCharacterDao().getAllCharacters()
|
return db.userCharacterDao().getAllCharacters()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getSingleCharacter(id: Long): UserCharacter {
|
suspend fun getSingleCharacter(id: Long): CharacterDtos.CharacterWithSprites {
|
||||||
return db.userCharacterDao().getCharacter(id)
|
return db.userCharacterDao().getCharacterWithSprites(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCharacterBeData(id: Long): BECharacterData {
|
suspend fun getCharacterBeData(id: Long): BECharacterData {
|
||||||
@@ -37,8 +35,7 @@ class StorageRepository (
|
|||||||
return db.userCharacterDao().deleteCharacterById(id)
|
return db.userCharacterDao().deleteCharacterById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setActiveCharacter(id: Long) {
|
suspend fun getAdventureCharacters(): List<CharacterDtos.AdventureCharacterWithSprites> {
|
||||||
db.userCharacterDao().clearActiveCharacter()
|
return db.adventureDao().getAdventureCharacters()
|
||||||
return db.userCharacterDao().setActiveCharacter(id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.glance.GlanceTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.glance.background
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||||
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import androidx.glance.GlanceId
|
||||||
|
import androidx.glance.GlanceModifier
|
||||||
|
import androidx.glance.Image
|
||||||
|
import androidx.glance.ImageProvider
|
||||||
|
import androidx.glance.appwidget.GlanceAppWidget
|
||||||
|
import androidx.glance.appwidget.provideContent
|
||||||
|
import androidx.glance.layout.Alignment
|
||||||
|
import androidx.glance.layout.Column
|
||||||
|
import androidx.glance.layout.fillMaxSize
|
||||||
|
import androidx.glance.layout.size
|
||||||
|
import androidx.glance.state.PreferencesGlanceStateDefinition
|
||||||
|
import androidx.glance.text.Text
|
||||||
|
import androidx.glance.unit.ColorProvider
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getBitmap
|
||||||
|
|
||||||
|
/*
|
||||||
|
RANT: Why did they have to create the components from Jetpack Compose
|
||||||
|
with a different API for Glance? Now there are things I use in Jetpack Compose
|
||||||
|
like the filterQuality, which isn't here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
val CURRENT_IMAGE_KEY = booleanPreferencesKey("current_image")
|
||||||
|
|
||||||
|
class CharacterDisplayWidget : GlanceAppWidget() {
|
||||||
|
override suspend fun provideGlance(context: Context, id: GlanceId) {
|
||||||
|
val application = context.applicationContext as VBHelper
|
||||||
|
val storageRepository = application.container.db
|
||||||
|
|
||||||
|
val currentCharacter = storageRepository
|
||||||
|
.userCharacterDao()
|
||||||
|
.getActiveCharacter()
|
||||||
|
|
||||||
|
val multiplier = 4
|
||||||
|
|
||||||
|
provideContent {
|
||||||
|
var bitmapIdle1 by remember { mutableStateOf<Bitmap?>(null) }
|
||||||
|
var bitmapIdle2 by remember { mutableStateOf<Bitmap?>(null) }
|
||||||
|
var dpSize by remember { mutableStateOf(0.dp) }
|
||||||
|
|
||||||
|
if (currentCharacter != null) {
|
||||||
|
val currentCharacterBitmapIdle1 = BitmapData(
|
||||||
|
currentCharacter.spriteIdle,
|
||||||
|
currentCharacter.spriteWidth,
|
||||||
|
currentCharacter.spriteHeight
|
||||||
|
)
|
||||||
|
|
||||||
|
val currentCharacterBitmapIdle2 = BitmapData(
|
||||||
|
currentCharacter.spriteIdle2,
|
||||||
|
currentCharacter.spriteWidth,
|
||||||
|
currentCharacter.spriteHeight
|
||||||
|
)
|
||||||
|
|
||||||
|
bitmapIdle1 = currentCharacterBitmapIdle1.getBitmap()
|
||||||
|
bitmapIdle2 = currentCharacterBitmapIdle2.getBitmap()
|
||||||
|
|
||||||
|
val density: Float = application.resources.displayMetrics.density
|
||||||
|
dpSize = (currentCharacterBitmapIdle1.width * multiplier / density).dp
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetContent(
|
||||||
|
imageBitmapFrame1 = bitmapIdle1,
|
||||||
|
imageBitmapFrame2 = bitmapIdle2,
|
||||||
|
dpSize = dpSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun WidgetContent(
|
||||||
|
imageBitmapFrame1: Bitmap?,
|
||||||
|
imageBitmapFrame2: Bitmap?,
|
||||||
|
dpSize: Dp
|
||||||
|
) {
|
||||||
|
GlanceTheme {
|
||||||
|
Column (
|
||||||
|
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
|
||||||
|
verticalAlignment = Alignment.Vertical.CenterVertically,
|
||||||
|
modifier = GlanceModifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(ColorProvider(MaterialTheme.colorScheme.background))
|
||||||
|
) {
|
||||||
|
if (imageBitmapFrame1 != null) {
|
||||||
|
Image(
|
||||||
|
provider = ImageProvider(
|
||||||
|
bitmap = imageBitmapFrame1
|
||||||
|
),
|
||||||
|
contentDescription = "Character",
|
||||||
|
modifier = GlanceModifier
|
||||||
|
.size(dpSize)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = "No character selected"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.widget
|
||||||
|
|
||||||
|
import androidx.glance.state.PreferencesGlanceStateDefinition
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.widget
|
||||||
|
|
||||||
|
import androidx.glance.appwidget.GlanceAppWidget
|
||||||
|
import androidx.glance.appwidget.GlanceAppWidgetReceiver
|
||||||
|
|
||||||
|
class CharacterDisplayWidgetReceiver : GlanceAppWidgetReceiver() {
|
||||||
|
override val glanceAppWidget: GlanceAppWidget = CharacterDisplayWidget()
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.glance.appwidget.GlanceAppWidgetManager
|
||||||
|
import androidx.glance.appwidget.state.updateAppWidgetState
|
||||||
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
|
||||||
|
class CharacterDisplayWidgetWorker(
|
||||||
|
appContext: Context,
|
||||||
|
workerParams: WorkerParameters
|
||||||
|
) : CoroutineWorker(appContext, workerParams) {
|
||||||
|
|
||||||
|
override suspend fun doWork(): Result {
|
||||||
|
// Get all widget IDs for your ImageSwapWidget
|
||||||
|
val glanceIds = GlanceAppWidgetManager(applicationContext)
|
||||||
|
.getGlanceIds(CharacterDisplayWidget::class.java)
|
||||||
|
|
||||||
|
glanceIds.forEach { glanceId ->
|
||||||
|
// Update the widget's state (toggle the boolean)
|
||||||
|
updateAppWidgetState(
|
||||||
|
context = applicationContext,
|
||||||
|
glanceId = glanceId
|
||||||
|
) { prefs ->
|
||||||
|
val currentImageIsImage1 = prefs[CURRENT_IMAGE_KEY] ?: true
|
||||||
|
prefs[CURRENT_IMAGE_KEY] = !currentImageIsImage1 // Toggle the boolean
|
||||||
|
}
|
||||||
|
// Trigger the widget to redraw itself with the new state
|
||||||
|
CharacterDisplayWidget().update(applicationContext, glanceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate that the work was successful
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:pathData="M40,840v-160l80,-80v-240l-80,-80v-160h80v80h80v-80h80v80h80v-80h80v160l-80,80v40h240v-40l-80,-80v-160h80v80h80v-80h80v80h80v-80h80v160l-80,80v240l80,80v160L560,840v-120q0,-33 -23.5,-56.5T480,640q-33,0 -56.5,23.5T400,720v120L40,840ZM120,760h200v-40q0,-66 47,-113t113,-47q66,0 113,47t47,113v40h200v-47l-80,-80v-306l47,-47L633,280l47,47v153L280,480v-153l47,-47L153,280l47,47v306l-80,80v47ZM480,520Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:initialLayout="@layout/glance_default_loading_layout"
|
||||||
|
android:minWidth="40dp"
|
||||||
|
android:minHeight="20dp"
|
||||||
|
android:minResizeWidth="20dp"
|
||||||
|
android:previewImage="@drawable/baseline_image_24"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:updatePeriodMillis="300000"
|
||||||
|
android:widgetCategory="home_screen" />
|
||||||
Reference in New Issue
Block a user