Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions app/src/main/java/io/nekohasekai/sagernet/ktx/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.system.Os
import android.system.OsConstants
Expand Down Expand Up @@ -284,9 +285,22 @@ fun Context.getColour(@ColorRes colorRes: Int): Int {
}

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

val isExpert: Boolean by lazy { BuildConfig.DEBUG || DataStore.isExpert }
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/io/nekohasekai/sagernet/widget/StatsBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,13 @@ class StatsBar @JvmOverloads constructor(

private fun setStatusColorByState(state: BaseService.State) {
// Connected = statusConnectedColor (green), Stopped/Stopping = statusStoppedColor
// (red — "Shutting down…" reads as red), Connecting/other = colorOnPrimary.
// (red — "Shutting down…" reads as red), Connecting = statusConnectingColor (Dracula
// yellow; colorOnPrimary elsewhere), other = colorOnPrimary.
// Non-Dracula themes default these attrs to colorOnPrimary, so no change.
val attr = when (state) {
BaseService.State.Connected -> R.attr.statusConnectedColor
BaseService.State.Stopped, BaseService.State.Stopping -> R.attr.statusStoppedColor
BaseService.State.Connecting -> R.attr.statusConnectingColor
else -> com.google.android.material.R.attr.colorOnPrimary
}
statusText.setTextColor(context.getColorAttr(attr))
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values-night/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<item name="profileNameColor">@color/color_dracula_yellow</item>
<item name="statusConnectedColor">@color/color_dracula_green</item>
<item name="statusStoppedColor">@color/color_dracula_red</item>
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
<item name="testFailColor">@color/color_dracula_red</item>
<item name="speedTextColor">@color/color_dracula_cyan</item>
<item name="fabStoppedColor">@color/color_dracula_cyan</item>
Expand All @@ -57,6 +58,7 @@
<item name="profileNameColor">@color/color_dracula_yellow</item>
<item name="statusConnectedColor">@color/color_dracula_green</item>
<item name="statusStoppedColor">@color/color_dracula_red</item>
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
<item name="testFailColor">@color/color_dracula_red</item>
<item name="speedTextColor">@color/color_dracula_cyan</item>
<item name="fabStoppedColor">@color/color_dracula_cyan</item>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-v26/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<item name="profileNameColor">?android:attr/textColorPrimary</item>
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
<item name="statusStoppedColor">?attr/colorOnPrimary</item>
<item name="statusConnectingColor">?attr/colorOnPrimary</item>
<item name="testFailColor">@color/material_red_500</item>
<item name="speedTextColor">?attr/colorOnPrimary</item>
<item name="fabStoppedColor">?attr/colorOnPrimary</item>
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
Dracula themes are unchanged; Dracula tints connected=green, stopped=red. -->
<attr name="statusConnectedColor" format="color" />
<attr name="statusStoppedColor" format="color" />
<!-- "Connecting…" in-progress status text. Default on-primary; Dracula = yellow
(on-primary resolved to dark on Dracula's light-purple primary). -->
<attr name="statusConnectingColor" format="color" />
<!-- Connection-test failure color. Default Material red; Dracula = #ff5555. -->
<attr name="testFailColor" format="color" />
<!-- Bottom-bar speed text (arrows + rate). Default on-primary; Dracula = yellow. -->
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<item name="profileNameColor">?android:attr/textColorPrimary</item>
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
<item name="statusStoppedColor">?attr/colorOnPrimary</item>
<item name="statusConnectingColor">?attr/colorOnPrimary</item>
<item name="testFailColor">@color/material_red_500</item>
<item name="speedTextColor">?attr/colorOnPrimary</item>
<item name="fabStoppedColor">?attr/colorOnPrimary</item>
Expand Down Expand Up @@ -81,6 +82,7 @@
<item name="profileNameColor">?android:attr/textColorPrimary</item>
<item name="statusConnectedColor">?attr/colorOnPrimary</item>
<item name="statusStoppedColor">?attr/colorOnPrimary</item>
<item name="statusConnectingColor">?attr/colorOnPrimary</item>
<item name="testFailColor">@color/material_red_500</item>
<item name="speedTextColor">?attr/colorOnPrimary</item>
<item name="fabStoppedColor">?attr/colorOnPrimary</item>
Expand Down Expand Up @@ -642,6 +644,7 @@
<item name="profileNameColor">@color/color_dracula_yellow</item>
<item name="statusConnectedColor">@color/color_dracula_green</item>
<item name="statusStoppedColor">@color/color_dracula_red</item>
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
<item name="testFailColor">@color/color_dracula_red</item>
<item name="speedTextColor">@color/color_dracula_cyan</item>
<item name="fabStoppedColor">@color/color_dracula_cyan</item>
Expand Down Expand Up @@ -689,6 +692,7 @@
<item name="profileNameColor">@color/color_dracula_yellow</item>
<item name="statusConnectedColor">@color/color_dracula_green</item>
<item name="statusStoppedColor">@color/color_dracula_red</item>
<item name="statusConnectingColor">@color/color_dracula_yellow</item>
<item name="testFailColor">@color/color_dracula_red</item>
<item name="speedTextColor">@color/color_dracula_cyan</item>
<item name="fabStoppedColor">@color/color_dracula_cyan</item>
Expand Down
Loading