♻️ Android use background info too

This commit is contained in:
LittleSheep 2024-12-21 13:03:07 +08:00
parent 73468c5c6d
commit 435b730f3b
8 changed files with 95 additions and 96 deletions

View File

@ -27,6 +27,11 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Widgets Indents -->
<intent-filter>
<action android:name="es.antonborri.home_widget.action.LAUNCH" />
</intent-filter>
<!-- Sharing Intents -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@ -100,15 +105,15 @@
android:name="android.appwidget.provider"
android:resource="@xml/check_in_widget" />
</receiver>
<receiver android:name=".widgets.FeaturedPostWidgetReceiver"
android:label="Featured Post"
<receiver android:name=".widgets.RandomPostWidgetReceiver"
android:label="Random Post"
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/featured_post_widget" />
android:resource="@xml/random_post_widget" />
</receiver>
</application>

View File

@ -1,10 +1,12 @@
import android.content.Context
import android.net.Uri
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.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.provideContent
import androidx.glance.background
@ -26,11 +28,11 @@ import com.google.gson.GsonBuilder
import dev.solsynth.solian.data.InstantAdapter
import dev.solsynth.solian.data.SolarCheckInRecord
import java.time.Instant
import java.time.LocalDate
import java.time.OffsetDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
class CheckInWidget : GlanceAppWidget() {
override val stateDefinition: GlanceStateDefinition<*>?
get() = HomeWidgetGlanceStateDefinition()
@ -51,7 +53,7 @@ class CheckInWidget : GlanceAppWidget() {
val resultTierSymbols = listOf("大凶", "", "中平", "", "大吉")
val prefs = currentState.preferences
val checkInRaw = prefs.getString("today_check_in", null)
val checkInRaw = prefs.getString("pas_check_in_record", null)
Column(
modifier = GlanceModifier
@ -61,33 +63,43 @@ class CheckInWidget : GlanceAppWidget() {
.padding(16.dp)
) {
if (checkInRaw != null) {
val checkIn = gson.fromJson(checkInRaw, SolarCheckInRecord::class.java)
val checkIn: SolarCheckInRecord =
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)
)
val checkDate = checkIn.createdAt.atZone(ZoneId.of("UTC")).toLocalDate()
val currentDate = LocalDate.now()
if (checkDate.isEqual(currentDate)) {
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)
)
}
return@Column;
}
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)
)
}
}
Text(
text = "You haven't checked in today",
style = TextStyle(fontSize = 15.sp)
)
}
}

View File

@ -1,8 +0,0 @@
package dev.solsynth.solian.widgets
import FeaturedPostWidget
import HomeWidgetGlanceWidgetReceiver
class FeaturedPostWidgetReceiver : HomeWidgetGlanceWidgetReceiver<FeaturedPostWidget>() {
override val glanceAppWidget = FeaturedPostWidget()
}

View File

@ -1,6 +1,7 @@
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@ -10,10 +11,12 @@ import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.action.clickable
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.cornerRadius
import androidx.glance.appwidget.provideContent
import androidx.glance.background
import androidx.glance.currentState
import androidx.glance.layout.Alignment
import androidx.glance.layout.Column
import androidx.glance.layout.ContentScale
@ -30,23 +33,12 @@ import androidx.glance.text.FontFamily
import androidx.glance.text.FontWeight
import androidx.glance.text.Text
import androidx.glance.text.TextStyle
import coil3.Image
import coil3.compose.AsyncImagePainter
import coil3.compose.rememberAsyncImagePainter
import coil3.imageLoader
import coil3.request.ErrorResult
import coil3.request.ImageRequest
import coil3.request.SuccessResult
import coil3.request.crossfade
import coil3.toBitmap
import com.google.gson.FieldNamingPolicy
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import dev.solsynth.solian.MainActivity
import dev.solsynth.solian.data.InstantAdapter
import dev.solsynth.solian.data.SolarPagination
import dev.solsynth.solian.data.SolarPost
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import es.antonborri.home_widget.actionStartActivity
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
@ -56,31 +48,16 @@ import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
class FeaturedPostWidget : GlanceAppWidget() {
class RandomPostWidget : GlanceAppWidget() {
override val stateDefinition: GlanceStateDefinition<*>?
get() = HomeWidgetGlanceStateDefinition()
private val defaultUrl = "https://api.sn.solsynth.dev"
override suspend fun provideGlance(context: Context, id: GlanceId) {
// TODO: Fix this
// val state = currentState<HomeWidgetGlanceState>()
// val prefs = state.preferences
// var baseUrl = prefs.getString("nex_server_url", null) ?: defaultUrl
// if (baseUrl.startsWith("\"") && baseUrl.endsWith("\"")) {
// baseUrl = baseUrl.substring(1, baseUrl.length - 1)
// }
val postData = withContext(Dispatchers.IO) { fetchPostRandomly(defaultUrl) }
val avatarImage = withContext(Dispatchers.IO) {
postData?.publisher?.avatar?.let {
loadImageFromUrl(it)
}
}
provideContent {
GlanceTheme {
GlanceContent(context, postData, avatarImage)
GlanceContent(context, currentState(), null)
}
}
}
@ -109,40 +86,37 @@ class FeaturedPostWidget : GlanceAppWidget() {
}
}
private fun fetchPostRandomly(baseUrl: String): SolarPost? {
@Composable
private fun GlanceContent(
context: Context,
currentState: HomeWidgetGlanceState,
avatar: Bitmap?
) {
val prefs = currentState.preferences
val postRaw = prefs.getString("int_random_post", null)
val gson =
GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Instant::class.java, InstantAdapter())
.create()
val type = object : TypeToken<SolarPagination<SolarPost>>() {}.type
val request = Request.Builder()
.url("$baseUrl/cgi/co/recommendations/shuffle?take=1")
.build()
val data: SolarPost? = postRaw?.let { postRaw ->
gson.fromJson(postRaw, SolarPost::class.java)
} ?: null;
return try {
val response: Response = client.newCall(request).execute()
if (response.isSuccessful) {
val body = response.body?.string()
val resp = gson.fromJson<SolarPagination<SolarPost>>(body, type)
resp.data.firstOrNull()
} else {
null
}
} catch (e: IOException) {
null
}
}
@Composable
private fun GlanceContent(context: Context, data: SolarPost?, avatar: Bitmap?) {
Column(
modifier = GlanceModifier
.fillMaxWidth()
.fillMaxHeight()
.background(Color.White)
.padding(16.dp)
.clickable(
onClick = actionStartActivity<MainActivity>(
context,
Uri.parse("https://sn.solsynth.dev/posts/${data!!.id}")
)
)
) {
if (data != null) {
Row(verticalAlignment = Alignment.CenterVertically) {
@ -154,10 +128,9 @@ class FeaturedPostWidget : GlanceAppWidget() {
.cornerRadius(18.dp),
contentScale = ContentScale.Crop
)
Spacer(modifier = GlanceModifier.width(8.dp))
}
Spacer(modifier = GlanceModifier.width(8.dp))
Text(
text = data.publisher.nick,
style = TextStyle(fontSize = 15.sp)
@ -174,13 +147,13 @@ class FeaturedPostWidget : GlanceAppWidget() {
if (data.body.title != null) {
Text(
text = data.body.title,
style = TextStyle(fontSize = 25.sp, fontFamily = FontFamily.Serif)
style = TextStyle(fontSize = 25.sp)
)
}
if (data.body.description != null) {
Text(
text = data.body.description,
style = TextStyle(fontSize = 19.sp, fontFamily = FontFamily.Serif)
style = TextStyle(fontSize = 19.sp)
)
}
@ -203,7 +176,7 @@ class FeaturedPostWidget : GlanceAppWidget() {
)
Text(
"Solar Network Featured Post",
"#${data.id}",
style = TextStyle(fontSize = 11.sp, fontWeight = FontWeight.Bold),
)

View File

@ -0,0 +1,8 @@
package dev.solsynth.solian.widgets
import RandomPostWidget
import HomeWidgetGlanceWidgetReceiver
class RandomPostWidgetReceiver : HomeWidgetGlanceWidgetReceiver<RandomPostWidget>() {
override val glanceAppWidget = RandomPostWidget()
}

View File

@ -1,6 +1,6 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout"
android:minWidth="280dp"
android:minWidth="240dp"
android:minHeight="40dp"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="10000">

View File

@ -3,6 +3,15 @@ allprojects {
google()
mavenCentral()
}
configurations.all {
resolutionStrategy {
eachDependency {
if ((requested.group == "androidx.work") && (requested.name.startsWith("work-runtime"))) {
useVersion("2.9.1")
}
}
}
}
}
rootProject.buildDir = "../build"

View File

@ -34,7 +34,7 @@ class HomeWidgetProvider {
);
}
} else if (Platform.isAndroid) {
const widgets = ["FeaturedPostWidget", "CheckInWidget"];
const widgets = ["RandomPostWidget", "CheckInWidget"];
for (final widget in widgets) {
await HomeWidget.updateWidget(
androidName: "${widget}Receiver",
@ -53,7 +53,7 @@ Future<void> widgetUpdateRandomPost() async {
await HomeWidget.updateWidget(
name: "SolarRandomPostWidget",
iOSName: "SolarRandomPostWidget",
androidName: "FeaturedPostWidgetReceiver",
qualifiedAndroidName: "dev.solsynth.solian.widgets.FeaturedPostWidgetReceiver",
androidName: "RandomPostWidgetReceiver",
qualifiedAndroidName: "dev.solsynth.solian.widgets.RandomPostWidgetReceiver",
);
}