Skip to content

Commit b1c4fde

Browse files
authored
Fix Dracula connecting-status color; harden getColorAttr (#52)
* fix(theme): color the in-progress status text (Dracula yellow) and harden getColorAttr The 'Connecting…' / 'Testing…' status text fell into the colorOnPrimary branch, which renders dark on Dracula's light-purple primary instead of yellow. Add a statusConnectingColor attr (default colorOnPrimary; Dracula = yellow) and use it for the Connecting state. While wiring it up, surfaced and fixed a latent crash in getColorAttr: when a theme attr resolves to a literal color value (resourceId == 0) rather than a @color resource ref, ContextCompat.getColor(0) threw Resources$NotFoundException (Resource ID #0x0). Now use the literal data when it is a color type, falling back to TRANSPARENT otherwise. This hardens every getColorAttr caller, not just the new attr. Verified on-device (Dracula): connect no longer crashes; in-progress status renders yellow. * fix(theme): add statusConnectingColor to night-Dracula and v26 base themes Per Greptile: Dracula forces night mode, so the active overrides live in values-night/themes.xml — which had statusConnected/Stopped but not the new statusConnectingColor, so connecting still inherited the dark base value in practice. Add statusConnectingColor=yellow to both night Dracula blocks, and to the API26+ base Theme.SagerNet in values-v26 (which redefines the status attrs) so the attr always resolves. Day-mode values were added in the previous commit.
1 parent 9e38302 commit b1c4fde

6 files changed

Lines changed: 30 additions & 4 deletions

File tree

app/src/main/java/io/nekohasekai/sagernet/ktx/Utils.kt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.content.Context
1111
import android.content.Intent
1212
import android.content.IntentFilter
1313
import android.content.res.Resources
14+
import android.graphics.Color
1415
import android.os.Build
1516
import android.system.Os
1617
import android.system.OsConstants
@@ -284,9 +285,22 @@ fun Context.getColour(@ColorRes colorRes: Int): Int {
284285
}
285286

286287
fun Context.getColorAttr(@AttrRes resId: Int): Int {
287-
return ContextCompat.getColor(this, TypedValue().also {
288-
theme.resolveAttribute(resId, it, true)
289-
}.resourceId)
288+
val tv = TypedValue()
289+
// resolveRefs = true follows ?attr chains (e.g. statusConnectingColor -> colorOnPrimary).
290+
// The result is either a color-resource reference (resourceId != 0) or a literal color
291+
// value (resourceId == 0); ContextCompat.getColor(0) would throw on the latter.
292+
theme.resolveAttribute(resId, tv, true)
293+
if (tv.resourceId != 0) {
294+
return ContextCompat.getColor(this, tv.resourceId)
295+
}
296+
// No backing resource: the attr resolved directly to a literal value. Use it only
297+
// when it is actually a color (e.g. ?attr/colorOnPrimary defined as a literal);
298+
// otherwise fall back to a safe default rather than returning a garbage int.
299+
return if (tv.type in TypedValue.TYPE_FIRST_COLOR_INT..TypedValue.TYPE_LAST_COLOR_INT) {
300+
tv.data
301+
} else {
302+
Color.TRANSPARENT
303+
}
290304
}
291305

292306
val isExpert: Boolean by lazy { BuildConfig.DEBUG || DataStore.isExpert }

app/src/main/java/io/nekohasekai/sagernet/widget/StatsBar.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,13 @@ class StatsBar @JvmOverloads constructor(
109109

110110
private fun setStatusColorByState(state: BaseService.State) {
111111
// Connected = statusConnectedColor (green), Stopped/Stopping = statusStoppedColor
112-
// (red — "Shutting down…" reads as red), Connecting/other = colorOnPrimary.
112+
// (red — "Shutting down…" reads as red), Connecting = statusConnectingColor (Dracula
113+
// yellow; colorOnPrimary elsewhere), other = colorOnPrimary.
113114
// Non-Dracula themes default these attrs to colorOnPrimary, so no change.
114115
val attr = when (state) {
115116
BaseService.State.Connected -> R.attr.statusConnectedColor
116117
BaseService.State.Stopped, BaseService.State.Stopping -> R.attr.statusStoppedColor
118+
BaseService.State.Connecting -> R.attr.statusConnectingColor
117119
else -> com.google.android.material.R.attr.colorOnPrimary
118120
}
119121
statusText.setTextColor(context.getColorAttr(attr))

app/src/main/res/values-night/themes.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<item name="profileNameColor">@color/color_dracula_yellow</item>
3333
<item name="statusConnectedColor">@color/color_dracula_green</item>
3434
<item name="statusStoppedColor">@color/color_dracula_red</item>
35+
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
3536
<item name="testFailColor">@color/color_dracula_red</item>
3637
<item name="speedTextColor">@color/color_dracula_cyan</item>
3738
<item name="fabStoppedColor">@color/color_dracula_cyan</item>
@@ -57,6 +58,7 @@
5758
<item name="profileNameColor">@color/color_dracula_yellow</item>
5859
<item name="statusConnectedColor">@color/color_dracula_green</item>
5960
<item name="statusStoppedColor">@color/color_dracula_red</item>
61+
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
6062
<item name="testFailColor">@color/color_dracula_red</item>
6163
<item name="speedTextColor">@color/color_dracula_cyan</item>
6264
<item name="fabStoppedColor">@color/color_dracula_cyan</item>

app/src/main/res/values-v26/themes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<item name="profileNameColor">?android:attr/textColorPrimary</item>
1111
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
1212
<item name="statusStoppedColor">?attr/colorOnPrimary</item>
13+
<item name="statusConnectingColor">?attr/colorOnPrimary</item>
1314
<item name="testFailColor">@color/material_red_500</item>
1415
<item name="speedTextColor">?attr/colorOnPrimary</item>
1516
<item name="fabStoppedColor">?attr/colorOnPrimary</item>

app/src/main/res/values/attrs.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
Dracula themes are unchanged; Dracula tints connected=green, stopped=red. -->
2020
<attr name="statusConnectedColor" format="color" />
2121
<attr name="statusStoppedColor" format="color" />
22+
<!-- "Connecting…" in-progress status text. Default on-primary; Dracula = yellow
23+
(on-primary resolved to dark on Dracula's light-purple primary). -->
24+
<attr name="statusConnectingColor" format="color" />
2225
<!-- Connection-test failure color. Default Material red; Dracula = #ff5555. -->
2326
<attr name="testFailColor" format="color" />
2427
<!-- Bottom-bar speed text (arrows + rate). Default on-primary; Dracula = yellow. -->

app/src/main/res/values/themes.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<item name="profileNameColor">?android:attr/textColorPrimary</item>
1010
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
1111
<item name="statusStoppedColor">?attr/colorOnPrimary</item>
12+
<item name="statusConnectingColor">?attr/colorOnPrimary</item>
1213
<item name="testFailColor">@color/material_red_500</item>
1314
<item name="speedTextColor">?attr/colorOnPrimary</item>
1415
<item name="fabStoppedColor">?attr/colorOnPrimary</item>
@@ -81,6 +82,7 @@
8182
<item name="profileNameColor">?android:attr/textColorPrimary</item>
8283
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
8384
<item name="statusStoppedColor">?attr/colorOnPrimary</item>
85+
<item name="statusConnectingColor">?attr/colorOnPrimary</item>
8486
<item name="testFailColor">@color/material_red_500</item>
8587
<item name="speedTextColor">?attr/colorOnPrimary</item>
8688
<item name="fabStoppedColor">?attr/colorOnPrimary</item>
@@ -642,6 +644,7 @@
642644
<item name="profileNameColor">@color/color_dracula_yellow</item>
643645
<item name="statusConnectedColor">@color/color_dracula_green</item>
644646
<item name="statusStoppedColor">@color/color_dracula_red</item>
647+
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
645648
<item name="testFailColor">@color/color_dracula_red</item>
646649
<item name="speedTextColor">@color/color_dracula_cyan</item>
647650
<item name="fabStoppedColor">@color/color_dracula_cyan</item>
@@ -689,6 +692,7 @@
689692
<item name="profileNameColor">@color/color_dracula_yellow</item>
690693
<item name="statusConnectedColor">@color/color_dracula_green</item>
691694
<item name="statusStoppedColor">@color/color_dracula_red</item>
695+
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
692696
<item name="testFailColor">@color/color_dracula_red</item>
693697
<item name="speedTextColor">@color/color_dracula_cyan</item>
694698
<item name="fabStoppedColor">@color/color_dracula_cyan</item>

0 commit comments

Comments
 (0)