diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9e700f0..b68afb1 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -91,4 +91,7 @@ dependencies {
implementation("com.google.android.material:material:1.2.0")
implementation(libs.protobuf.javalite)
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")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d3a5163..7f87d3e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,6 +27,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidget.kt b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidget.kt
new file mode 100644
index 0000000..5dc1396
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidget.kt
@@ -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(null) }
+ var bitmapIdle2 by remember { mutableStateOf(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"
+ )
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetPreferences.kt b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetPreferences.kt
new file mode 100644
index 0000000..7d0f825
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetPreferences.kt
@@ -0,0 +1,3 @@
+package com.github.nacabaro.vbhelper.widget
+
+import androidx.glance.state.PreferencesGlanceStateDefinition
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetReceiver.kt b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetReceiver.kt
new file mode 100644
index 0000000..cea351d
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetReceiver.kt
@@ -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()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetWorker.kt b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetWorker.kt
new file mode 100644
index 0000000..5fa9d6e
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/widget/CharacterDisplayWidgetWorker.kt
@@ -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()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/xml/widget_info.xml b/app/src/main/res/xml/widget_info.xml
new file mode 100644
index 0000000..5297356
--- /dev/null
+++ b/app/src/main/res/xml/widget_info.xml
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file