fix: make Android prototype buildable
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
|||||||
.learnings/
|
.learnings/
|
||||||
.tools/
|
.tools/
|
||||||
.android-sdk/
|
.android-sdk/
|
||||||
|
.gradle/
|
||||||
local.properties
|
local.properties
|
||||||
app/build/
|
app/build/
|
||||||
build/
|
build/
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user