diff --git a/android/app/build.gradle b/android/app/build.gradle
index e3b3bf3..0dee8d9 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -13,6 +13,7 @@ dependencies {
implementation "androidx.glance:glance:1.1.1"
implementation "androidx.glance:glance-appwidget:1.1.1"
implementation 'androidx.compose.foundation:foundation-layout-android:1.7.6'
+ implementation 'com.google.code.gson:gson:2.10.1'
}
android {
@@ -25,8 +26,12 @@ android {
ndkVersion = "27.0.12077973"
compileOptions {
- sourceCompatibility JavaVersion.VERSION_17
- targetCompatibility JavaVersion.VERSION_17
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.4.8"
}
kotlinOptions {
@@ -35,7 +40,7 @@ android {
defaultConfig {
applicationId = "dev.solsynth.solian"
- minSdk = flutter.minSdkVersion
+ minSdk = 26
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c1a347f..8373f81 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -80,14 +80,23 @@
android:value="2" />
-
+ android:resource="@xml/check_in_widget" />
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/dev/solsynth/solian/data/SolarTime.kt b/android/app/src/main/kotlin/dev/solsynth/solian/data/SolarTime.kt
new file mode 100644
index 0000000..121eb68
--- /dev/null
+++ b/android/app/src/main/kotlin/dev/solsynth/solian/data/SolarTime.kt
@@ -0,0 +1,37 @@
+package dev.solsynth.solian.data
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import com.google.gson.JsonParseException
+import com.google.gson.JsonPrimitive
+import com.google.gson.JsonSerializationContext
+import com.google.gson.JsonSerializer
+import java.lang.reflect.Type
+import java.time.Instant
+import java.time.format.DateTimeFormatter
+
+
+class InstantAdapter : JsonSerializer,
+ JsonDeserializer {
+ override fun serialize(
+ src: Instant?,
+ typeOfSrc: Type?,
+ context: JsonSerializationContext?
+ ): JsonElement {
+ return JsonPrimitive(formatter.format(src))
+ }
+
+ @Throws(JsonParseException::class)
+ override fun deserialize(
+ json: JsonElement,
+ typeOfT: Type?,
+ context: JsonDeserializationContext?
+ ): Instant {
+ return Instant.parse(json.asString)
+ }
+
+ companion object {
+ private val formatter: DateTimeFormatter = DateTimeFormatter.ISO_INSTANT
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/dev/solsynth/solian/data/SolarUser.kt b/android/app/src/main/kotlin/dev/solsynth/solian/data/SolarUser.kt
new file mode 100644
index 0000000..64f21fa
--- /dev/null
+++ b/android/app/src/main/kotlin/dev/solsynth/solian/data/SolarUser.kt
@@ -0,0 +1,16 @@
+package dev.solsynth.solian.data
+
+import java.time.Instant
+
+data class SolarUser(
+ val id: Int,
+ val name: String,
+ val nick: String
+)
+
+data class SolarCheckInRecord(
+ val id: Int,
+ val resultTier: Int,
+ val resultExperience: Int,
+ val createdAt: Instant
+)
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/dev/solsynth/solian/widgets/CheckInWidget.kt b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/CheckInWidget.kt
new file mode 100644
index 0000000..cd4b2dd
--- /dev/null
+++ b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/CheckInWidget.kt
@@ -0,0 +1,98 @@
+import android.content.Context
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.glance.Button
+import androidx.glance.GlanceId
+import androidx.glance.GlanceModifier
+import androidx.glance.appwidget.GlanceAppWidget
+import androidx.glance.appwidget.provideContent
+import androidx.glance.background
+import androidx.glance.currentState
+import androidx.glance.layout.Alignment
+import androidx.glance.layout.Box
+import androidx.glance.layout.Column
+import androidx.glance.layout.Row
+import androidx.glance.layout.Spacer
+import androidx.glance.layout.fillMaxWidth
+import androidx.glance.layout.height
+import androidx.glance.layout.padding
+import androidx.glance.state.GlanceStateDefinition
+import androidx.glance.text.FontFamily
+import androidx.glance.text.FontWeight
+import androidx.glance.text.Text
+import androidx.glance.text.TextStyle
+import com.google.gson.FieldNamingPolicy
+import com.google.gson.GsonBuilder
+import dev.solsynth.solian.data.InstantAdapter
+import dev.solsynth.solian.data.SolarCheckInRecord
+import java.time.Instant
+import java.time.OffsetDateTime
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+
+class CheckInWidget : GlanceAppWidget() {
+ override val stateDefinition: GlanceStateDefinition<*>?
+ get() = HomeWidgetGlanceStateDefinition()
+
+ override suspend fun provideGlance(context: Context, id: GlanceId) {
+ provideContent {
+ GlanceContent(context, currentState())
+ }
+ }
+
+ @Composable
+ private fun GlanceContent(context: Context, currentState: HomeWidgetGlanceState) {
+ val gson =
+ GsonBuilder()
+ .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
+ .registerTypeAdapter(Instant::class.java, InstantAdapter())
+ .create()
+ val resultTierSymbols = listOf("大凶", "凶", "中平", "大吉", "吉")
+
+ val prefs = currentState.preferences
+ val checkInRaw = prefs.getString("today_check_in", null)
+
+ Column(
+ modifier = GlanceModifier
+ .fillMaxWidth()
+ .background(Color.White)
+ .padding(16.dp)
+ ) {
+ if (checkInRaw != null) {
+ val checkIn = gson.fromJson(checkInRaw, SolarCheckInRecord::class.java)
+ val dateFormatter = DateTimeFormatter.ofPattern("EEE, MM/dd")
+
+ Column {
+ Text(
+ text = resultTierSymbols[checkIn.resultTier],
+ style = TextStyle(fontSize = 25.sp, fontFamily = FontFamily.Serif)
+ )
+ Text(
+ text = "+${checkIn.resultExperience} EXP",
+ style = TextStyle(fontSize = 15.sp, fontFamily = FontFamily.Monospace)
+ )
+ }
+ Spacer(modifier = GlanceModifier.height(8.dp))
+ Row(horizontalAlignment = Alignment.CenterHorizontally) {
+ Text(
+ text = OffsetDateTime.ofInstant(checkIn.createdAt, ZoneId.systemDefault())
+ .format(dateFormatter),
+ style = TextStyle(fontSize = 13.sp)
+ )
+ }
+ } else {
+ Text(
+ text = "You haven't checked in today",
+ style = TextStyle(fontSize = 15.sp)
+ )
+ Spacer(modifier = GlanceModifier.height(8.dp))
+ Button(
+ text = "Check In",
+ onClick = {}
+ )
+ }
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/dev/solsynth/solian/widgets/CheckInWidgetReceiver.kt b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/CheckInWidgetReceiver.kt
new file mode 100644
index 0000000..c617065
--- /dev/null
+++ b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/CheckInWidgetReceiver.kt
@@ -0,0 +1,8 @@
+package dev.solsynth.solian.widgets
+
+import CheckInWidget
+import HomeWidgetGlanceWidgetReceiver
+
+class CheckInWidgetReceiver : HomeWidgetGlanceWidgetReceiver() {
+ override val glanceAppWidget = CheckInWidget()
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/dev/solsynth/solian/widgets/AppWidget.kt b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/FeaturedPostWidget.kt
similarity index 81%
rename from android/app/src/main/kotlin/dev/solsynth/solian/widgets/AppWidget.kt
rename to android/app/src/main/kotlin/dev/solsynth/solian/widgets/FeaturedPostWidget.kt
index 8ebf8ab..b6f535f 100644
--- a/android/app/src/main/kotlin/dev/solsynth/solian/widgets/AppWidget.kt
+++ b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/FeaturedPostWidget.kt
@@ -13,7 +13,7 @@ import androidx.glance.layout.padding
import androidx.glance.state.GlanceStateDefinition
import androidx.glance.text.Text
-class AppWidget : GlanceAppWidget() {
+class FeaturedPostWidget : GlanceAppWidget() {
override val stateDefinition: GlanceStateDefinition<*>?
get() = HomeWidgetGlanceStateDefinition()
@@ -26,11 +26,13 @@ class AppWidget : GlanceAppWidget() {
@Composable
private fun GlanceContent(context: Context, currentState: HomeWidgetGlanceState) {
val prefs = currentState.preferences
- val counter = prefs.getInt("counter", 0)
+ val checkIn = prefs.getString("post_featured", null)
Box(modifier = GlanceModifier.background(Color.White).padding(16.dp)) {
- Text(
- counter.toString()
- )
+ checkIn?.let {
+ Text(it)
+ } ?: run {
+ Text("No featured posts")
+ }
}
}
}
diff --git a/android/app/src/main/kotlin/dev/solsynth/solian/widgets/FeaturedPostWidgetReceiver.kt b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/FeaturedPostWidgetReceiver.kt
new file mode 100644
index 0000000..03dab9d
--- /dev/null
+++ b/android/app/src/main/kotlin/dev/solsynth/solian/widgets/FeaturedPostWidgetReceiver.kt
@@ -0,0 +1,8 @@
+package dev.solsynth.solian.widgets
+
+import FeaturedPostWidget
+import HomeWidgetGlanceWidgetReceiver
+
+class FeaturedPostWidgetReceiver : HomeWidgetGlanceWidgetReceiver() {
+ override val glanceAppWidget = FeaturedPostWidget()
+}
\ No newline at end of file
diff --git a/android/app/src/main/res/xml/home_widget.xml b/android/app/src/main/res/xml/check_in_widget.xml
similarity index 100%
rename from android/app/src/main/res/xml/home_widget.xml
rename to android/app/src/main/res/xml/check_in_widget.xml
diff --git a/android/app/src/main/res/xml/featured_post_widget.xml b/android/app/src/main/res/xml/featured_post_widget.xml
new file mode 100644
index 0000000..0b33ead
--- /dev/null
+++ b/android/app/src/main/res/xml/featured_post_widget.xml
@@ -0,0 +1,7 @@
+
+
diff --git a/android/gradle.properties b/android/gradle.properties
index 2597170..768b3b2 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
+kotlin.suppressKotlinVersionCompatibilityCheck=true
diff --git a/android/settings.gradle b/android/settings.gradle
index 7e7f058..4c34d90 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -18,7 +18,7 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
- id "com.android.application" version '8.7.2' apply false
+ id "com.android.application" version '8.7.3' apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
id "com.google.firebase.crashlytics" version "2.8.1" apply false
diff --git a/lib/providers/widget.dart b/lib/providers/widget.dart
index 77324e0..96cc551 100644
--- a/lib/providers/widget.dart
+++ b/lib/providers/widget.dart
@@ -15,7 +15,8 @@ class HomeWidgetProvider {
}
}
- Future saveWidgetData(String id, dynamic data, {bool update = true}) async {
+ Future saveWidgetData(String id, dynamic data,
+ {bool update = true}) async {
if (kIsWeb || !(Platform.isAndroid || Platform.isIOS)) return;
await HomeWidget.saveWidgetData(id, jsonEncode(data));
if (update) await updateWidget();
@@ -29,8 +30,14 @@ class HomeWidgetProvider {
await HomeWidget.updateWidget(
name: widget,
iOSName: widget,
- androidName: "com.solsynth.solian.$widget",
- qualifiedAndroidName: "group.solsynth.solian.$widget",
+ );
+ }
+ } else if (Platform.isAndroid) {
+ const widgets = ["FeaturedPostWidget", "CheckInWidget"];
+ for (final widget in widgets) {
+ await HomeWidget.updateWidget(
+ androidName: "${widget}Receiver",
+ qualifiedAndroidName: "dev.solsynth.solian.widgets.${widget}Receiver",
);
}
}