From 5a18ffc02f3f5f2d93dc4321e2494d11cfb465dd Mon Sep 17 00:00:00 2001
From: WaterRain <109326062+CATMIAOZHI@users.noreply.github.com>
Date: Fri, 19 Jun 2026 07:38:02 +0000
Subject: [PATCH] =?UTF-8?q?feat:=20MIUI=20Widget=20=E5=AE=8C=E6=95=B4?=
=?UTF-8?q?=E9=80=82=E9=85=8D=20+=20=E6=B7=B1=E8=89=B2=E6=A8=A1=E5=BC=8F?=
=?UTF-8?q?=E5=85=A8=E5=B1=80=E4=BF=AE=E5=A4=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
MIUI Widget 接入(负一屏 + 曝光刷新)
- AndroidManifest 新增 miuiWidget 全套标识
- intent-filter 新增 miui.appwidget.action.APPWIDGET_UPDATE
- 根布局改为 FrameLayout + @android:id/background
- minWidth 250→300dp(4x2 标准)
- onReceive() 处理 MIUI 曝光刷新
- 5min 冷却自动刷新
深色模式全面适配
- drawable-night/widget_bg.xml
- drawable-night/ic_opencode_go_logo.xml
- drawable-night/ic_deepseek_logo.png + wordmark
- layout-night/widget_opencode_go.xml
- DarkInkWarm/DarkInkMuted + inkWarm()/inkMuted()
- 全页面 51 处 InkMuted → inkMuted()
- ServiceIcon 白底 → 主题自适应
用户体验
- 顶部栏 + 按钮:一键添桌面小组件
- 负一屏底部遮挡修复(间距压缩 28dp)
---
.commit_msg | 22 ++
app/src/main/AndroidManifest.xml | 26 ++-
.../rainy/token/ui/components/ServiceIcon.kt | 3 +-
.../token/ui/dashboard/DashboardScreen.kt | 74 ++++--
.../token/ui/dashboard/UsageDataScreen.kt | 20 +-
.../token/ui/dashboard/UsageOverviewScreen.kt | 20 +-
.../ui/servicedetail/ServiceDetailScreen.kt | 28 +--
.../java/com/rainy/token/ui/theme/Color.kt | 3 +
.../java/com/rainy/token/ui/theme/Theme.kt | 12 +-
.../ui/widget/OpenCodeGoWidgetProvider.kt | 25 ++-
.../res/drawable-night/ic_deepseek_logo.png | Bin 0 -> 8650 bytes
.../drawable-night/ic_opencode_go_logo.xml | 20 ++
.../drawable-night/rainytoken_wordmark.png | Bin 0 -> 17411 bytes
app/src/main/res/drawable-night/widget_bg.xml | 10 +
.../res/drawable-nodpi/widget_preview.png | Bin 0 -> 8887 bytes
.../res/layout-night/widget_opencode_go.xml | 212 ++++++++++++++++++
.../main/res/layout/widget_opencode_go.xml | 32 ++-
.../res/layout/widget_opencode_go_preview.xml | 180 +++++++++++++++
app/src/main/res/values/strings.xml | 2 +
.../main/res/xml/widget_opencode_go_info.xml | 9 +-
20 files changed, 621 insertions(+), 77 deletions(-)
create mode 100644 .commit_msg
create mode 100644 app/src/main/res/drawable-night/ic_deepseek_logo.png
create mode 100644 app/src/main/res/drawable-night/ic_opencode_go_logo.xml
create mode 100644 app/src/main/res/drawable-night/rainytoken_wordmark.png
create mode 100644 app/src/main/res/drawable-night/widget_bg.xml
create mode 100644 app/src/main/res/drawable-nodpi/widget_preview.png
create mode 100644 app/src/main/res/layout-night/widget_opencode_go.xml
create mode 100644 app/src/main/res/layout/widget_opencode_go_preview.xml
diff --git a/.commit_msg b/.commit_msg
new file mode 100644
index 0000000..4210909
--- /dev/null
+++ b/.commit_msg
@@ -0,0 +1,22 @@
+feat: MIUI Widget 完整适配 + 深色模式全局修复
+
+MIUI Widget 接入(负一屏 + 曝光刷新)
+- AndroidManifest 新增 miuiWidget 全套标识
+- intent-filter 新增 miui.appwidget.action.APPWIDGET_UPDATE
+- 根布局改为 FrameLayout + @android:id/background
+- minWidth 250→300dp(4x2 标准)
+- onReceive() 处理 MIUI 曝光刷新
+- 5min 冷却自动刷新
+
+深色模式全面适配
+- drawable-night/widget_bg.xml
+- drawable-night/ic_opencode_go_logo.xml
+- drawable-night/ic_deepseek_logo.png + wordmark
+- layout-night/widget_opencode_go.xml
+- DarkInkWarm/DarkInkMuted + inkWarm()/inkMuted()
+- 全页面 51 处 InkMuted → inkMuted()
+- ServiceIcon 白底 → 主题自适应
+
+用户体验
+- 顶部栏 + 按钮:一键添桌面小组件
+- 负一屏底部遮挡修复(间距压缩 28dp)
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b238319..0bda2f5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,22 +28,44 @@
-
+
+
+ android:exported="true"
+ android:label="@string/widget_name">
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/rainy/token/ui/components/ServiceIcon.kt b/app/src/main/java/com/rainy/token/ui/components/ServiceIcon.kt
index 3cdcd4c..1ac174f 100644
--- a/app/src/main/java/com/rainy/token/ui/components/ServiceIcon.kt
+++ b/app/src/main/java/com/rainy/token/ui/components/ServiceIcon.kt
@@ -2,6 +2,7 @@ package com.rainy.token.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
+import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -40,7 +41,7 @@ fun ServiceIcon(
modifier = modifier
.size(size.dp)
.clip(RoundedCornerShape(8.dp))
- .background(Color.White),
+ .background(if (isSystemInDarkTheme()) Color(0xFF352329) else Color.White),
contentAlignment = Alignment.Center
) {
Image(
diff --git a/app/src/main/java/com/rainy/token/ui/dashboard/DashboardScreen.kt b/app/src/main/java/com/rainy/token/ui/dashboard/DashboardScreen.kt
index 817d122..5c7d997 100644
--- a/app/src/main/java/com/rainy/token/ui/dashboard/DashboardScreen.kt
+++ b/app/src/main/java/com/rainy/token/ui/dashboard/DashboardScreen.kt
@@ -22,6 +22,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Card
@@ -59,8 +60,14 @@ import com.rainy.token.ui.components.ServiceIcon
import com.rainy.token.ui.components.StatusChip
import com.rainy.token.ui.components.StatusLevel
import com.rainy.token.ui.components.StatusStyle
-import com.rainy.token.ui.theme.InkMuted
+import com.rainy.token.ui.theme.inkMuted
import com.rainy.token.ui.theme.StrawberryPink
+import android.appwidget.AppWidgetManager
+import android.content.ComponentName
+import android.content.Intent
+import androidx.compose.ui.platform.LocalContext
+import android.widget.Toast
+import com.rainy.token.ui.widget.OpenCodeGoWidgetProvider
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -110,11 +117,36 @@ fun DashboardScreen(
Text(
text = "AI 余额一览",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
},
actions = {
+ // 添加小组件:优先 requestPinAppWidget,不支持则打开系统小组件选择器
+ val context = LocalContext.current
+ IconButton(onClick = {
+ val appWidgetManager = AppWidgetManager.getInstance(context)
+ val component = ComponentName(context, OpenCodeGoWidgetProvider::class.java)
+ if (appWidgetManager.isRequestPinAppWidgetSupported) {
+ appWidgetManager.requestPinAppWidget(component, null, null)
+ } else {
+ // MIUI 等桌面回退:直接打开小组件选择器
+ try {
+ val pickerIntent = Intent(AppWidgetManager.ACTION_APPWIDGET_PICK).apply {
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID)
+ }
+ context.startActivity(pickerIntent)
+ } catch (e: Exception) {
+ Toast.makeText(context, "请在桌面长按 → 小组件 → 查找雨晴Token", Toast.LENGTH_LONG).show()
+ }
+ }
+ }) {
+ Icon(
+ imageVector = Icons.Filled.Add,
+ contentDescription = "添加小组件到桌面",
+ tint = StrawberryPink
+ )
+ }
IconButton(
onClick = { viewModel.refresh() },
enabled = !uiState.refreshing
@@ -165,7 +197,7 @@ fun DashboardScreen(
Text(
text = "服务余额",
style = MaterialTheme.typography.labelMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.padding(top = 8.dp)
)
}
@@ -204,7 +236,7 @@ private fun DashboardCard(card: DashboardCardUi, onClick: () -> Unit) {
Text(
text = secondaryLine(card),
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
StatusChip(style = card.statusBadgeStyle())
@@ -223,7 +255,7 @@ private fun DashboardCard(card: DashboardCardUi, onClick: () -> Unit) {
color = if (card.lastFetchError != null)
MaterialTheme.colorScheme.error
else
- InkMuted
+ inkMuted()
)
}
}
@@ -237,24 +269,24 @@ private fun BalanceMainArea(card: DashboardCardUi) {
Text(
text = "—",
style = MaterialTheme.typography.displayMedium,
- color = InkMuted
+ color = inkMuted()
)
Text(
text = "点击配置凭据",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
balance == null -> {
Text(
text = "—",
style = MaterialTheme.typography.displayMedium,
- color = InkMuted
+ color = inkMuted()
)
Text(
text = "下拉刷新",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
card.service == ServiceType.OPENCODE_GO -> {
@@ -278,7 +310,7 @@ private fun BalanceMainArea(card: DashboardCardUi) {
Text(
text = balance.unit,
style = MaterialTheme.typography.titleMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.padding(bottom = 6.dp)
)
}
@@ -293,7 +325,7 @@ private fun BalanceMainArea(card: DashboardCardUi) {
Text(
text = "本月已用 ${formatAmount(spent)}${balance.unit}",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
}
@@ -313,7 +345,7 @@ private fun OpenCodeGoMainBalance(balance: com.rainy.token.domain.model.ServiceB
Text(
text = "%",
style = MaterialTheme.typography.titleLarge,
- color = InkMuted,
+ color = inkMuted(),
fontWeight = FontWeight.SemiBold,
modifier = Modifier.padding(bottom = 6.dp, start = 2.dp)
)
@@ -321,7 +353,7 @@ private fun OpenCodeGoMainBalance(balance: com.rainy.token.domain.model.ServiceB
Text(
text = "5h 用量",
style = MaterialTheme.typography.titleMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.padding(bottom = 6.dp)
)
}
@@ -356,13 +388,13 @@ private fun CompactUsageRowEmpty(label: String, resetInSec: Long?) {
Text(
text = label,
style = MaterialTheme.typography.bodySmall,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.weight(1f)
)
Text(
text = "—",
style = MaterialTheme.typography.bodyMedium,
- color = InkMuted
+ color = inkMuted()
)
}
Spacer(modifier = Modifier.height(4.dp))
@@ -372,7 +404,7 @@ private fun CompactUsageRowEmpty(label: String, resetInSec: Long?) {
.fillMaxWidth()
.height(4.dp)
.clip(RoundedCornerShape(2.dp)),
- color = InkMuted.copy(alpha = 0.3f),
+ color = inkMuted().copy(alpha = 0.3f),
trackColor = MaterialTheme.colorScheme.surfaceVariant,
strokeCap = androidx.compose.ui.graphics.StrokeCap.Butt
)
@@ -381,7 +413,7 @@ private fun CompactUsageRowEmpty(label: String, resetInSec: Long?) {
Text(
text = "${formatResetInSec(resetInSec)}后重置",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
}
@@ -398,7 +430,7 @@ private fun CompactUsageRow(label: String, pct: Int, resetInSec: Long?) {
Text(
text = label,
style = MaterialTheme.typography.bodySmall,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.weight(1f)
)
Text(
@@ -433,7 +465,7 @@ private fun CompactUsageRow(label: String, pct: Int, resetInSec: Long?) {
Text(
text = "${formatResetInSec(resetInSec)}后重置",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
}
@@ -511,13 +543,13 @@ private fun DashboardFooter() {
Text(
text = "RainyToken · v1.0",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "本地加密存储,不上传任何数据",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/rainy/token/ui/dashboard/UsageDataScreen.kt b/app/src/main/java/com/rainy/token/ui/dashboard/UsageDataScreen.kt
index b481d03..db7f3a2 100644
--- a/app/src/main/java/com/rainy/token/ui/dashboard/UsageDataScreen.kt
+++ b/app/src/main/java/com/rainy/token/ui/dashboard/UsageDataScreen.kt
@@ -52,7 +52,7 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.rainy.token.data.local.UsageRecord
-import com.rainy.token.ui.theme.InkMuted
+import com.rainy.token.ui.theme.inkMuted
import com.rainy.token.ui.theme.StrawberryPink
import java.text.SimpleDateFormat
import java.time.Instant
@@ -121,7 +121,7 @@ fun UsageDataScreen(
})
}
}
- Text("UTC+0", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("UTC+0", style = MaterialTheme.typography.bodySmall, color = inkMuted())
Spacer(Modifier.weight(1f))
// 模型筛选
Box {
@@ -150,17 +150,17 @@ fun UsageDataScreen(
CustomTimeRangeRow(customStartMs, customEndMs,
{ showStartPicker = true }, { showEndPicker = true },
{ viewModel.setTimeFilter(TimeFilter.Custom(customStartMs, customEndMs)) })
- Text("所有时间按 UTC+0 计算", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("所有时间按 UTC+0 计算", style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
// ─── 记录数 + 分页 ───
Row(Modifier.fillMaxWidth().padding(vertical = 4.dp), Arrangement.SpaceBetween, Alignment.CenterVertically) {
- Text("${state.totalRecords} 条记录", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("${state.totalRecords} 条记录", style = MaterialTheme.typography.bodySmall, color = inkMuted())
if (state.totalPages > 1) {
Row(verticalAlignment = Alignment.CenterVertically) {
TextButton(onClick = { viewModel.prevPage() }, enabled = state.currentPage > 1) {
Text("◀", color = StrawberryPink, fontSize = 13.sp) }
- Text("${state.currentPage}/${state.totalPages}", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("${state.currentPage}/${state.totalPages}", style = MaterialTheme.typography.bodySmall, color = inkMuted())
TextButton(onClick = { viewModel.nextPage() }, enabled = state.currentPage < state.totalPages) {
Text("▶", color = StrawberryPink, fontSize = 13.sp) }
Spacer(Modifier.width(6.dp))
@@ -173,7 +173,7 @@ fun UsageDataScreen(
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = androidx.compose.ui.text.input.KeyboardType.Number),
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = StrawberryPink,
- unfocusedBorderColor = InkMuted.copy(alpha = 0.4f)
+ unfocusedBorderColor = inkMuted().copy(alpha = 0.4f)
)
)
TextButton(onClick = {
@@ -201,11 +201,11 @@ fun UsageDataScreen(
// ─── 记录列表 ───
if (state.loading) {
Box(Modifier.fillMaxWidth().height(200.dp), contentAlignment = Alignment.Center) {
- Text("加载中…", color = InkMuted)
+ Text("加载中…", color = inkMuted())
}
} else if (state.records.isEmpty()) {
Box(Modifier.fillMaxWidth().height(200.dp), contentAlignment = Alignment.Center) {
- Text("暂无数据", color = InkMuted)
+ Text("暂无数据", color = inkMuted())
}
} else {
LazyColumn(Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(1.dp)) {
@@ -265,7 +265,7 @@ fun UsageDataScreen(
@Composable
private fun HeaderCell(text: String, modifier: Modifier) {
Text(text, modifier = modifier, fontSize = 12.sp, fontWeight = FontWeight.Bold,
- color = InkMuted, textAlign = TextAlign.Center)
+ color = inkMuted(), textAlign = TextAlign.Center)
}
@Composable
@@ -293,7 +293,7 @@ private fun DataCell(text: String, modifier: Modifier) {
@Composable
private fun RawField(label: String, value: String) {
Row(Modifier.fillMaxWidth().padding(vertical = 1.dp)) {
- Text("$label: ", fontSize = 12.sp, fontWeight = FontWeight.Medium, color = InkMuted)
+ Text("$label: ", fontSize = 12.sp, fontWeight = FontWeight.Medium, color = inkMuted())
Text(value, fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurface)
}
}
diff --git a/app/src/main/java/com/rainy/token/ui/dashboard/UsageOverviewScreen.kt b/app/src/main/java/com/rainy/token/ui/dashboard/UsageOverviewScreen.kt
index 785d90f..efb2c93 100644
--- a/app/src/main/java/com/rainy/token/ui/dashboard/UsageOverviewScreen.kt
+++ b/app/src/main/java/com/rainy/token/ui/dashboard/UsageOverviewScreen.kt
@@ -43,7 +43,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.rainy.token.data.local.ModelStats
import com.rainy.token.data.local.OverviewStats
-import com.rainy.token.ui.theme.InkMuted
+import com.rainy.token.ui.theme.inkMuted
import com.rainy.token.ui.theme.StrawberryPink
import java.text.SimpleDateFormat
import java.util.Date
@@ -89,7 +89,7 @@ fun UsageOverviewScreen(
Text(uiState.timeFilter.label, color = StrawberryPink, fontWeight = FontWeight.SemiBold)
Icon(Icons.Filled.ArrowDropDown, null, tint = StrawberryPink)
}
- Text("UTC+0", style = MaterialTheme.typography.bodySmall, color = InkMuted, modifier = Modifier.padding(start = 4.dp))
+ Text("UTC+0", style = MaterialTheme.typography.bodySmall, color = inkMuted(), modifier = Modifier.padding(start = 4.dp))
DropdownMenu(menuExpanded, { menuExpanded = false }) {
listOf(TimeFilter.All, TimeFilter.Last5h, TimeFilter.Last24h,
TimeFilter.Today, TimeFilter.Yesterday,
@@ -112,7 +112,7 @@ fun UsageOverviewScreen(
CustomTimeRangeRow(customStartMs, customEndMs,
{ showStartPicker = true }, { showEndPicker = true },
{ viewModel.setTimeFilter(TimeFilter.Custom(customStartMs, customEndMs)) })
- Text("所有时间按 UTC+0 计算", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("所有时间按 UTC+0 计算", style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
}
// 总览
@@ -157,7 +157,7 @@ fun UsageOverviewScreen(
Row(Modifier.fillMaxWidth(), Arrangement.SpaceBetween, Alignment.CenterVertically) {
TextButton(onClick = { viewModel.prevDailyPage() }, enabled = uiState.dailyPage > 1) {
Text("◀ 上一页", color = StrawberryPink, style = MaterialTheme.typography.bodySmall) }
- Text("${uiState.dailyPage} / $totalPages", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("${uiState.dailyPage} / $totalPages", style = MaterialTheme.typography.bodySmall, color = inkMuted())
TextButton(onClick = { viewModel.nextDailyPage() }, enabled = uiState.dailyPage < totalPages) {
Text("下一页 ▶", color = StrawberryPink, style = MaterialTheme.typography.bodySmall) }
}
@@ -193,7 +193,7 @@ fun UsageOverviewScreen(
@Composable private fun CacheBreakdownCard(overview: OverviewStats) {
Card(Modifier.fillMaxWidth(), RoundedCornerShape(20.dp), CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)) {
Column(Modifier.padding(16.dp)) {
- Text("缓存 Token 细分", style = MaterialTheme.typography.labelMedium, color = InkMuted)
+ Text("缓存 Token 细分", style = MaterialTheme.typography.labelMedium, color = inkMuted())
Spacer(Modifier.height(8.dp))
Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
StatItem("缓存读取", formatTokenCount(overview.cacheReadTokens))
@@ -201,7 +201,7 @@ fun UsageOverviewScreen(
}
if (overview.cacheReadTokens > 0) {
Spacer(Modifier.height(4.dp))
- Text("※ 缓存读取已计入「输入 Token」", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("※ 缓存读取已计入「输入 Token」", style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
}
}
@@ -216,11 +216,11 @@ fun UsageOverviewScreen(
Row(Modifier.fillMaxWidth().padding(12.dp), verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) {
Text(stat.model, style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium)
- Text("${stat.count} 次调用", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("${stat.count} 次调用", style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
Column(horizontalAlignment = Alignment.End) {
Text(formatTokenCount(stat.totalTokens), style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, color = StrawberryPink)
- Text("$${String.format(Locale.US, "%.4f", stat.totalCost / 100_000_000.0)}", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("$${String.format(Locale.US, "%.4f", stat.totalCost / 100_000_000.0)}", style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
}
}
@@ -233,7 +233,7 @@ fun UsageOverviewScreen(
Text(utcFmt.format(Date(day.dayTs)), style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium, modifier = Modifier.weight(1f))
Column(horizontalAlignment = Alignment.End) {
Text(formatTokenCount(day.totalTokens), style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, color = StrawberryPink)
- Text("${day.count} 次 · $${String.format(Locale.US, "%.4f", day.totalCost / 100_000_000.0)}", style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text("${day.count} 次 · $${String.format(Locale.US, "%.4f", day.totalCost / 100_000_000.0)}", style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
}
}
@@ -242,7 +242,7 @@ fun UsageOverviewScreen(
@Composable private fun StatItem(label: String, value: String) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(value, style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, color = StrawberryPink)
- Text(label, style = MaterialTheme.typography.bodySmall, color = InkMuted)
+ Text(label, style = MaterialTheme.typography.bodySmall, color = inkMuted())
}
}
diff --git a/app/src/main/java/com/rainy/token/ui/servicedetail/ServiceDetailScreen.kt b/app/src/main/java/com/rainy/token/ui/servicedetail/ServiceDetailScreen.kt
index 7229173..a36b713 100644
--- a/app/src/main/java/com/rainy/token/ui/servicedetail/ServiceDetailScreen.kt
+++ b/app/src/main/java/com/rainy/token/ui/servicedetail/ServiceDetailScreen.kt
@@ -51,7 +51,7 @@ import com.rainy.token.ui.components.ServiceIcon
import com.rainy.token.ui.components.StatusChip
import com.rainy.token.ui.components.StatusLevel
import com.rainy.token.ui.components.StatusStyle
-import com.rainy.token.ui.theme.InkMuted
+import com.rainy.token.ui.theme.inkMuted
import com.rainy.token.ui.theme.StrawberryPink
import java.text.SimpleDateFormat
import java.util.Date
@@ -187,7 +187,7 @@ private fun OpenCodeGoWindowsCard(state: State) {
Text(
text = "用量窗口",
style = MaterialTheme.typography.labelLarge,
- color = InkMuted
+ color = inkMuted()
)
Spacer(modifier = Modifier.height(12.dp))
UsageWindowRow(
@@ -226,7 +226,7 @@ private fun UsageWindowRow(label: String, pct: Int?, resetInSec: Long?) {
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.weight(1f)
)
Row(verticalAlignment = Alignment.Bottom) {
@@ -238,7 +238,7 @@ private fun UsageWindowRow(label: String, pct: Int?, resetInSec: Long?) {
Text(
text = "%",
style = MaterialTheme.typography.bodyMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.padding(bottom = 2.dp, start = 2.dp)
)
}
@@ -262,7 +262,7 @@ private fun UsageWindowRow(label: String, pct: Int?, resetInSec: Long?) {
Text(
text = "${formatResetInSec(resetInSec)}后重置",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
}
@@ -293,7 +293,7 @@ private fun MainBalanceCard(state: State, service: ServiceType) {
Text(
text = mainCardLabel(service),
style = MaterialTheme.typography.labelLarge,
- color = InkMuted
+ color = inkMuted()
)
Spacer(modifier = Modifier.weight(1f))
StatusChip(style = stateToChip(state))
@@ -322,14 +322,14 @@ private fun MainBalanceCard(state: State, service: ServiceType) {
Text(
text = "显示的是上次成功获取的余额",
style = MaterialTheme.typography.bodySmall,
- color = InkMuted
+ color = inkMuted()
)
}
is State.ManualModeHint -> {
Text(
text = "—",
style = MaterialTheme.typography.displayMedium,
- color = InkMuted
+ color = inkMuted()
)
}
}
@@ -343,7 +343,7 @@ private fun BalanceBigNumber(balance: ServiceBalance?) {
Text(
text = "—",
style = MaterialTheme.typography.displayLarge,
- color = InkMuted
+ color = inkMuted()
)
return
}
@@ -358,7 +358,7 @@ private fun BalanceBigNumber(balance: ServiceBalance?) {
Text(
text = balance.unit,
style = MaterialTheme.typography.titleLarge,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.padding(bottom = 8.dp)
)
}
@@ -375,7 +375,7 @@ private fun BalanceBigNumber(balance: ServiceBalance?) {
Text(
text = "本月消费 ${formatAmount(spent)}${balance.unit}",
style = MaterialTheme.typography.bodyMedium,
- color = InkMuted
+ color = inkMuted()
)
}
}
@@ -406,7 +406,7 @@ private fun DeepSeekBreakdownCard(state: State) {
Text(
text = "余额构成",
style = MaterialTheme.typography.labelLarge,
- color = InkMuted
+ color = inkMuted()
)
Spacer(modifier = Modifier.height(12.dp))
BreakdownRow("赠送余额", granted, balance!!.unit)
@@ -427,7 +427,7 @@ private fun BreakdownRow(label: String, value: Double, unit: String) {
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.weight(1f)
)
Row(verticalAlignment = Alignment.Bottom) {
@@ -440,7 +440,7 @@ private fun BreakdownRow(label: String, value: Double, unit: String) {
Text(
text = unit,
style = MaterialTheme.typography.bodyMedium,
- color = InkMuted,
+ color = inkMuted(),
modifier = Modifier.padding(bottom = 2.dp)
)
}
diff --git a/app/src/main/java/com/rainy/token/ui/theme/Color.kt b/app/src/main/java/com/rainy/token/ui/theme/Color.kt
index ba89c31..467e195 100644
--- a/app/src/main/java/com/rainy/token/ui/theme/Color.kt
+++ b/app/src/main/java/com/rainy/token/ui/theme/Color.kt
@@ -37,3 +37,6 @@ val DarkBackground = Color(0xFF1F1419) // 暖深背景
val DarkSurface = Color(0xFF2A1F25) // 卡片
val DarkOnSurface = Color(0xFFEFE0E5) // 卡片文本
val DarkPrimary = Color(0xFFFFB3C6) // 暗色下主色更亮
+val DarkInkWarm = Color(0xFFEFE0E5) // 暗色下暖黑→浅粉白
+val DarkInkMuted = Color(0xFFC9B8BE) // 暗色下暖灰→浅灰粉
+val DarkInkOutline = Color(0xFF4D3A42) // 暗色下描边
diff --git a/app/src/main/java/com/rainy/token/ui/theme/Theme.kt b/app/src/main/java/com/rainy/token/ui/theme/Theme.kt
index 19fad57..c375f84 100644
--- a/app/src/main/java/com/rainy/token/ui/theme/Theme.kt
+++ b/app/src/main/java/com/rainy/token/ui/theme/Theme.kt
@@ -88,4 +88,14 @@ fun RainyTokenTheme(
typography = RainyTypography,
content = content
)
-}
\ No newline at end of file
+}
+
+/**
+ * 暗色模式自适应的文本颜色。
+ * 浅色模式下返回暖黑/暖灰,深色模式下自动切换到浅色。
+ */
+@Composable
+fun inkWarm(): Color = if (isSystemInDarkTheme()) DarkInkWarm else InkWarm
+
+@Composable
+fun inkMuted(): Color = if (isSystemInDarkTheme()) DarkInkMuted else InkMuted
\ No newline at end of file
diff --git a/app/src/main/java/com/rainy/token/ui/widget/OpenCodeGoWidgetProvider.kt b/app/src/main/java/com/rainy/token/ui/widget/OpenCodeGoWidgetProvider.kt
index fa2c64c..507380c 100644
--- a/app/src/main/java/com/rainy/token/ui/widget/OpenCodeGoWidgetProvider.kt
+++ b/app/src/main/java/com/rainy/token/ui/widget/OpenCodeGoWidgetProvider.kt
@@ -19,13 +19,30 @@ import java.util.Date
import java.util.Locale
/**
- * OpenCode Go 桌面小组件。
+ * OpenCode Go 桌面小组件(MIUI Widget)。
*
- * 显示 3 个用量窗口(5h / 本周 / 本月)的百分比 + 进度条 + 重置倒计时。
- * 优先展示缓存数据;缓存为空或超过 5 分钟冷却时间时,自动触发后台网络刷新。
+ * 显示 3 个用量窗口(5h / 本周 / 本月)的百分比 + 进度条 + 重置倒计时 + DeepSeek 余额。
+ *
+ * 刷新路径:
+ * - MIUI 曝光刷新:用户划到负一屏 → miui.appwidget.action.APPWIDGET_UPDATE → onReceive → onUpdate
+ * - 标准定时刷新:系统 30min 定时 → android.appwidget.action.APPWIDGET_UPDATE → onUpdate
+ * - 手动 ↻ 按钮:PendingIntent 直通 WidgetRefreshReceiver → 网络请求 → notifyDataChanged
+ * - APP 内刷新:notifyDataChanged() → 广播 ACTION_APPWIDGET_UPDATE → onUpdate
+ * - 缓存为空/过期时 onUpdate 自动触发后台刷新
*/
class OpenCodeGoWidgetProvider : AppWidgetProvider() {
+ override fun onReceive(context: Context, intent: Intent) {
+ if ("miui.appwidget.action.APPWIDGET_UPDATE" == intent.action) {
+ val appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)
+ if (appWidgetIds != null) {
+ onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds)
+ }
+ } else {
+ super.onReceive(context, intent)
+ }
+ }
+
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
@@ -44,7 +61,7 @@ class OpenCodeGoWidgetProvider : AppWidgetProvider() {
context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
- views.setOnClickPendingIntent(R.id.widget_root, pendingIntent)
+ views.setOnClickPendingIntent(R.id.widget_content, pendingIntent)
// 刷新按钮 → 后台广播刷新
val refreshPendingIntent = PendingIntent.getBroadcast(
diff --git a/app/src/main/res/drawable-night/ic_deepseek_logo.png b/app/src/main/res/drawable-night/ic_deepseek_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..85ca0b5ee465eed47ea50880b531e8a5b186497f
GIT binary patch
literal 8650
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
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-night/rainytoken_wordmark.png b/app/src/main/res/drawable-night/rainytoken_wordmark.png
new file mode 100644
index 0000000000000000000000000000000000000000..b4d65baa199009c3cb551c89afed727f4c4e5a87
GIT binary patch
literal 17411
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
T^!5QB?!n;c>gTe~DWM4fAlk=B
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable-night/widget_bg.xml b/app/src/main/res/drawable-night/widget_bg.xml
new file mode 100644
index 0000000..f99fb09
--- /dev/null
+++ b/app/src/main/res/drawable-night/widget_bg.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-nodpi/widget_preview.png b/app/src/main/res/drawable-nodpi/widget_preview.png
new file mode 100644
index 0000000000000000000000000000000000000000..187a47262da60fcc4f9ef342fa647880e93fcfb0
GIT binary patch
literal 8887
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_opencode_go.xml b/app/src/main/res/layout/widget_opencode_go.xml
index 6adf53b..b4a1722 100644
--- a/app/src/main/res/layout/widget_opencode_go.xml
+++ b/app/src/main/res/layout/widget_opencode_go.xml
@@ -1,11 +1,19 @@
-
+
+ android:background="@drawable/widget_bg">
+
+
+
+ android:layout_marginBottom="6dp">
+ android:layout_marginBottom="3dp">
+ android:layout_marginBottom="3dp">
+ android:layout_marginBottom="3dp">
+ android:layout_marginBottom="2dp">
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_opencode_go_preview.xml b/app/src/main/res/layout/widget_opencode_go_preview.xml
new file mode 100644
index 0000000..c6927ff
--- /dev/null
+++ b/app/src/main/res/layout/widget_opencode_go_preview.xml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 08ab72d..a787889 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
雨晴Token
+ AI用量面板
+OpenCode Go 用量 + DeepSeek 余额,自动刷新
\ No newline at end of file
diff --git a/app/src/main/res/xml/widget_opencode_go_info.xml b/app/src/main/res/xml/widget_opencode_go_info.xml
index 537cdaa..924714c 100644
--- a/app/src/main/res/xml/widget_opencode_go_info.xml
+++ b/app/src/main/res/xml/widget_opencode_go_info.xml
@@ -1,9 +1,12 @@