fix: make Android prototype buildable

This commit is contained in:
Mimikko-zeus
2026-06-23 11:42:35 +08:00
parent 961554712b
commit 4f1fb80851
4 changed files with 30 additions and 21 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
.learnings/ .learnings/
.tools/ .tools/
.android-sdk/ .android-sdk/
.gradle/
local.properties local.properties
app/build/ app/build/
build/ build/

View File

@@ -22,6 +22,15 @@ android {
buildFeatures { buildFeatures {
compose = true compose = true
} }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
} }
dependencies { dependencies {

View File

@@ -2,9 +2,9 @@ package com.sub2api.monitor.widget
import android.content.Context import android.content.Context
import androidx.glance.GlanceId import androidx.glance.GlanceId
import androidx.glance.action.ActionCallback
import androidx.glance.action.ActionParameters import androidx.glance.action.ActionParameters
import androidx.glance.appwidget.update import androidx.glance.appwidget.action.ActionCallback
import androidx.glance.appwidget.updateAll
import com.sub2api.monitor.data.DataStoreConfigRepository import com.sub2api.monitor.data.DataStoreConfigRepository
import com.sub2api.monitor.data.MockSub2ApiRepository import com.sub2api.monitor.data.MockSub2ApiRepository
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@@ -19,7 +19,7 @@ class RefreshWidgetAction : ActionCallback {
val widgetStateRepository = WidgetStateRepository(context) val widgetStateRepository = WidgetStateRepository(context)
if (!config.isConfigured) { if (!config.isConfigured) {
Sub2ApiMonitorWidget().update(context, glanceId) Sub2ApiMonitorWidget().updateAll(context)
return return
} }
@@ -34,6 +34,6 @@ class RefreshWidgetAction : ActionCallback {
}, },
) )
Sub2ApiMonitorWidget().update(context, glanceId) Sub2ApiMonitorWidget().updateAll(context)
} }
} }

View File

@@ -9,8 +9,8 @@ import androidx.glance.GlanceId
import androidx.glance.GlanceModifier import androidx.glance.GlanceModifier
import androidx.glance.Image import androidx.glance.Image
import androidx.glance.ImageProvider import androidx.glance.ImageProvider
import androidx.glance.action.actionRunCallback
import androidx.glance.appwidget.GlanceAppWidget import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.action.actionRunCallback
import androidx.glance.appwidget.cornerRadius import androidx.glance.appwidget.cornerRadius
import androidx.glance.appwidget.provideContent import androidx.glance.appwidget.provideContent
import androidx.glance.background import androidx.glance.background
@@ -19,7 +19,6 @@ import androidx.glance.layout.Box
import androidx.glance.layout.Column import androidx.glance.layout.Column
import androidx.glance.layout.Row import androidx.glance.layout.Row
import androidx.glance.layout.Spacer import androidx.glance.layout.Spacer
import androidx.glance.layout.defaultWeight
import androidx.glance.layout.fillMaxSize import androidx.glance.layout.fillMaxSize
import androidx.glance.layout.fillMaxWidth import androidx.glance.layout.fillMaxWidth
import androidx.glance.layout.height import androidx.glance.layout.height
@@ -118,7 +117,7 @@ private fun DashboardState(state: Sub2ApiWidgetState) {
modifier = GlanceModifier.fillMaxWidth(), modifier = GlanceModifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Column(modifier = GlanceModifier.defaultWeight()) { Column(modifier = GlanceModifier.width(180.dp)) {
Text("Sub2API", style = titleStyle()) Text("Sub2API", style = titleStyle())
Text( Text(
text = "更新 ${formatDisplayTime(snapshot.lastUpdatedAtMillis)}", text = "更新 ${formatDisplayTime(snapshot.lastUpdatedAtMillis)}",
@@ -135,34 +134,34 @@ private fun DashboardState(state: Sub2ApiWidgetState) {
Spacer(modifier = GlanceModifier.height(8.dp)) Spacer(modifier = GlanceModifier.height(8.dp))
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
MetricBlock("今日 Token", formatTokens(snapshot.todayTokens), Color(0xFF2563EB), GlanceModifier.defaultWeight()) MetricBlock("今日 Token", formatTokens(snapshot.todayTokens), Color(0xFF2563EB), GlanceModifier.width(130.dp))
Spacer(modifier = GlanceModifier.width(8.dp)) Spacer(modifier = GlanceModifier.width(8.dp))
MetricBlock("今日消耗", formatCurrency(snapshot.todayCost), Color(0xFF0F766E), GlanceModifier.defaultWeight()) MetricBlock("今日消耗", formatCurrency(snapshot.todayCost), Color(0xFF0F766E), GlanceModifier.width(130.dp))
} }
Spacer(modifier = GlanceModifier.height(8.dp)) Spacer(modifier = GlanceModifier.height(8.dp))
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
MetricBlock("请求次数", snapshot.todayRequests.toString(), Color(0xFF7C3AED), GlanceModifier.defaultWeight()) MetricBlock("请求次数", snapshot.todayRequests.toString(), Color(0xFF7C3AED), GlanceModifier.width(130.dp))
Spacer(modifier = GlanceModifier.width(8.dp)) Spacer(modifier = GlanceModifier.width(8.dp))
MetricBlock("服务状态", statusText(snapshot.serviceStatus), statusColor(snapshot.serviceStatus), GlanceModifier.defaultWeight()) MetricBlock("服务状态", statusText(snapshot.serviceStatus), statusColor(snapshot.serviceStatus), GlanceModifier.width(130.dp))
} }
Spacer(modifier = GlanceModifier.height(8.dp)) Spacer(modifier = GlanceModifier.height(8.dp))
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
TinyMetric("平均", formatLatency(snapshot.averageLatencyMs), GlanceModifier.defaultWeight()) TinyMetric("平均", formatLatency(snapshot.averageLatencyMs), GlanceModifier.width(58.dp))
TinyMetric("RPM", formatRpm(snapshot.rpm), GlanceModifier.defaultWeight()) TinyMetric("RPM", formatRpm(snapshot.rpm), GlanceModifier.width(54.dp))
TinyMetric("TPM", formatTpm(snapshot.tpm), GlanceModifier.defaultWeight()) TinyMetric("TPM", formatTpm(snapshot.tpm), GlanceModifier.width(62.dp))
TinyMetric("Key", snapshot.activeKeyCount.toString(), GlanceModifier.defaultWeight()) TinyMetric("Key", snapshot.activeKeyCount.toString(), GlanceModifier.width(42.dp))
TinyMetric("用户", snapshot.userCount.toString(), GlanceModifier.defaultWeight()) TinyMetric("用户", snapshot.userCount.toString(), GlanceModifier.width(42.dp))
} }
Spacer(modifier = GlanceModifier.height(8.dp)) Spacer(modifier = GlanceModifier.height(8.dp))
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
Column(modifier = GlanceModifier.defaultWeight()) { Column(modifier = GlanceModifier.width(145.dp)) {
SectionTitle("最近调用") SectionTitle("最近调用")
snapshot.recentCalls.take(5).forEach { RecentCallRow(it) } snapshot.recentCalls.take(5).forEach { RecentCallRow(it) }
} }
Spacer(modifier = GlanceModifier.width(10.dp)) Spacer(modifier = GlanceModifier.width(10.dp))
Column(modifier = GlanceModifier.defaultWeight()) { Column(modifier = GlanceModifier.width(125.dp)) {
SectionTitle("模型 TOP4") SectionTitle("模型 TOP4")
snapshot.modelTop.take(4).forEach { ModelUsageRow(it) } snapshot.modelTop.take(4).forEach { ModelUsageRow(it) }
} }
@@ -170,7 +169,7 @@ private fun DashboardState(state: Sub2ApiWidgetState) {
Spacer(modifier = GlanceModifier.height(6.dp)) Spacer(modifier = GlanceModifier.height(6.dp))
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
Text("累计 ${formatTokens(snapshot.totalTokens)}", style = mutedStyle(), modifier = GlanceModifier.defaultWeight()) Text("累计 ${formatTokens(snapshot.totalTokens)}", style = mutedStyle(), modifier = GlanceModifier.width(140.dp))
Text("累计 ${formatCurrency(snapshot.totalCost)}", style = mutedStyle()) Text("累计 ${formatCurrency(snapshot.totalCost)}", style = mutedStyle())
} }
} }
@@ -212,7 +211,7 @@ private fun SectionTitle(text: String) {
@Composable @Composable
private fun RecentCallRow(call: RecentCall) { private fun RecentCallRow(call: RecentCall) {
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
Text(call.model, style = mutedStyle(), modifier = GlanceModifier.defaultWeight()) Text(call.model, style = mutedStyle(), modifier = GlanceModifier.width(95.dp))
Text("${call.statusCode}", style = mutedStyle()) Text("${call.statusCode}", style = mutedStyle())
} }
} }
@@ -220,7 +219,7 @@ private fun RecentCallRow(call: RecentCall) {
@Composable @Composable
private fun ModelUsageRow(model: ModelUsage) { private fun ModelUsageRow(model: ModelUsage) {
Row(modifier = GlanceModifier.fillMaxWidth()) { Row(modifier = GlanceModifier.fillMaxWidth()) {
Text(model.model, style = mutedStyle(), modifier = GlanceModifier.defaultWeight()) Text(model.model, style = mutedStyle(), modifier = GlanceModifier.width(82.dp))
Text(formatCurrency(model.cost), style = mutedStyle()) Text(formatCurrency(model.cost), style = mutedStyle())
} }
} }