Skip to content

Commit 5b971dc

Browse files
Theme (#588)
* update theme style implementation and use AppCompatDelegate for night… (#584) * update theme style implementation and use AppCompatDelegate for night mode * change default theme style to DARK * update theme style default to dark in SettingsTest * fix theme style default value in SettingsTest * refactor MainActivity to streamline theme style initialization * add ThemeInstrumentedTest to verify theme settings and functionality * refactor theme and add more tests * ktlint fix formatting * workflows cleanup * fix instrumented tests * ktlint --------- Co-authored-by: Akihiro Nagai <77012577+314systems@users.noreply.github.com>
1 parent 8c45e0b commit 5b971dc

8 files changed

Lines changed: 139 additions & 46 deletions

File tree

app/build.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Build Properties
2-
#Sat Jan 17 10:15:29 EST 2026
3-
version_build=1
2+
#Sat Jan 17 13:51:56 EST 2026
3+
version_build=2
44
version_major=3
55
version_minor=2
66
version_patch=2

app/src/androidTest/kotlin/com/vrem/wifianalyzer/MainInstrumentedTest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,9 @@ class MainInstrumentedTest {
115115
fun settings() {
116116
SettingsInstrumentedTest().run()
117117
}
118+
119+
@Test
120+
fun theme() {
121+
ThemeInstrumentedTest().run()
122+
}
118123
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* WiFiAnalyzer
3+
* Copyright (C) 2015 - 2026 VREM Software Development <VREMSoftwareDevelopment@gmail.com>
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>
17+
*/
18+
package com.vrem.wifianalyzer
19+
20+
import androidx.appcompat.app.AppCompatDelegate
21+
import androidx.test.espresso.Espresso.onView
22+
import androidx.test.espresso.action.ViewActions.click
23+
import androidx.test.espresso.assertion.ViewAssertions.matches
24+
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
25+
import androidx.test.espresso.matcher.ViewMatchers.withText
26+
import org.junit.Assert.assertEquals
27+
28+
internal class ThemeInstrumentedTest : Runnable {
29+
override fun run() {
30+
listOf(
31+
"Light" to AppCompatDelegate.MODE_NIGHT_NO,
32+
"System" to AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
33+
"Black" to AppCompatDelegate.MODE_NIGHT_YES,
34+
"Dark" to AppCompatDelegate.MODE_NIGHT_YES,
35+
).forEach { (themeName, expectedNightMode) ->
36+
changeThemeAndVerify(themeName, expectedNightMode)
37+
}
38+
}
39+
40+
private fun changeThemeAndVerify(
41+
themeName: String,
42+
expectedNightMode: Int,
43+
) {
44+
selectMenuItem(R.id.nav_drawer_settings, "Settings")
45+
scrollToAndVerify("Theme")
46+
onView(withText("Theme")).perform(click())
47+
pauseShort()
48+
onView(withText(themeName)).check(matches(isDisplayed()))
49+
onView(withText(themeName)).perform(click())
50+
pauseShort()
51+
assertEquals(
52+
"Theme $themeName should set night mode to $expectedNightMode",
53+
expectedNightMode,
54+
AppCompatDelegate.getDefaultNightMode(),
55+
)
56+
}
57+
}

app/src/main/kotlin/com/vrem/wifianalyzer/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class MainActivity :
6161

6262
val settings = mainContext.settings
6363
settings.initializeDefaultValues()
64-
setTheme(settings.themeStyle().themeNoActionBar)
64+
settings.themeStyle().setTheme(this)
6565

6666
mainReload = MainReload(settings)
6767

app/src/main/kotlin/com/vrem/wifianalyzer/settings/ThemeStyle.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,23 @@ package com.vrem.wifianalyzer.settings
2020
import android.graphics.Color
2121
import androidx.annotation.ColorInt
2222
import androidx.annotation.StyleRes
23+
import androidx.appcompat.app.AppCompatActivity
24+
import androidx.appcompat.app.AppCompatDelegate
2325
import com.vrem.wifianalyzer.R
2426

2527
enum class ThemeStyle(
26-
@param:StyleRes val theme: Int,
27-
@param:StyleRes val themeNoActionBar: Int,
2828
@param:ColorInt val colorGraphText: Int,
29+
@param:StyleRes private val theme: Int,
30+
private val nightMode: Int,
2931
) {
30-
DARK(R.style.ThemeDark, R.style.ThemeDarkNoActionBar, Color.WHITE),
31-
LIGHT(R.style.ThemeLight, R.style.ThemeLightNoActionBar, Color.BLACK),
32-
SYSTEM(R.style.ThemeSystem, R.style.ThemeSystemNoActionBar, Color.GRAY),
33-
BLACK(R.style.ThemeBlack, R.style.ThemeBlackNoActionBar, Color.WHITE),
32+
DARK(Color.WHITE, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
33+
LIGHT(Color.BLACK, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_NO),
34+
SYSTEM(Color.GRAY, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM),
35+
BLACK(Color.WHITE, R.style.ThemeBlackNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
36+
;
37+
38+
fun setTheme(activity: AppCompatActivity) {
39+
activity.setTheme(theme)
40+
AppCompatDelegate.setDefaultNightMode(nightMode)
41+
}
3442
}

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

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,6 @@
1818

1919
<resources>
2020

21-
<!-- Dark theme -->
22-
<style name="ThemeDark" parent="Theme.AppCompat">
23-
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
24-
<item name="android:actionMenuTextColor">@color/selected</item>
25-
</style>
26-
<style name="ThemeDarkNoActionBar" parent="ThemeDark">
27-
<item name="windowActionBar">false</item>
28-
<item name="windowNoTitle">true</item>
29-
</style>
30-
31-
<!-- Light theme -->
32-
<style name="ThemeLight" parent="Theme.AppCompat.Light.DarkActionBar">
33-
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
34-
<item name="android:actionMenuTextColor">@color/selected</item>
35-
</style>
36-
<style name="ThemeLightNoActionBar" parent="ThemeLight">
37-
<item name="windowActionBar">false</item>
38-
<item name="windowNoTitle">true</item>
39-
</style>
40-
4121
<!-- Black theme -->
4222
<style name="ThemeBlack" parent="Theme.AppCompat">
4323
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* WiFiAnalyzer
3+
* Copyright (C) 2015 - 2026 VREM Software Development <VREMSoftwareDevelopment@gmail.com>
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>
17+
*/
18+
package com.vrem.wifianalyzer.settings
19+
20+
import androidx.appcompat.app.AppCompatActivity
21+
import androidx.appcompat.app.AppCompatDelegate
22+
import com.vrem.wifianalyzer.R
23+
import org.junit.Test
24+
import org.junit.runner.RunWith
25+
import org.junit.runners.Parameterized
26+
import org.mockito.Mockito
27+
import org.mockito.kotlin.mock
28+
import org.mockito.kotlin.verify
29+
30+
@RunWith(Parameterized::class)
31+
class ThemeStyleParameterizedTest(
32+
private val themeStyle: ThemeStyle,
33+
private val expectedTheme: Int,
34+
private val expectedNightMode: Int,
35+
) {
36+
companion object {
37+
@JvmStatic
38+
@Parameterized.Parameters(name = "{0}")
39+
fun data(): Collection<Array<Any>> =
40+
listOf(
41+
arrayOf(ThemeStyle.DARK, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
42+
arrayOf(ThemeStyle.LIGHT, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_NO),
43+
arrayOf(ThemeStyle.SYSTEM, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM),
44+
arrayOf(ThemeStyle.BLACK, R.style.ThemeBlackNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
45+
)
46+
}
47+
48+
@Test
49+
fun setThemeParameterized() {
50+
// Arrange
51+
val activity: AppCompatActivity = mock()
52+
Mockito.mockStatic(AppCompatDelegate::class.java).use { mockedStatic ->
53+
// Act
54+
themeStyle.setTheme(activity)
55+
// Assert
56+
verify(activity).setTheme(expectedTheme)
57+
mockedStatic.verify { AppCompatDelegate.setDefaultNightMode(expectedNightMode) }
58+
}
59+
}
60+
}

app/src/test/kotlin/com/vrem/wifianalyzer/settings/ThemeStyleTest.kt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
package com.vrem.wifianalyzer.settings
1919

2020
import android.graphics.Color
21-
import com.vrem.wifianalyzer.R
2221
import org.assertj.core.api.Assertions.assertThat
2322
import org.junit.Test
2423

@@ -30,22 +29,6 @@ class ThemeStyleTest {
3029
.containsExactly(ThemeStyle.DARK, ThemeStyle.LIGHT, ThemeStyle.SYSTEM, ThemeStyle.BLACK)
3130
}
3231

33-
@Test
34-
fun theme() {
35-
assertThat(ThemeStyle.LIGHT.theme).isEqualTo(R.style.ThemeLight)
36-
assertThat(ThemeStyle.DARK.theme).isEqualTo(R.style.ThemeDark)
37-
assertThat(ThemeStyle.SYSTEM.theme).isEqualTo(R.style.ThemeSystem)
38-
assertThat(ThemeStyle.BLACK.theme).isEqualTo(R.style.ThemeBlack)
39-
}
40-
41-
@Test
42-
fun themeNoActionBar() {
43-
assertThat(ThemeStyle.DARK.themeNoActionBar).isEqualTo(R.style.ThemeDarkNoActionBar)
44-
assertThat(ThemeStyle.LIGHT.themeNoActionBar).isEqualTo(R.style.ThemeLightNoActionBar)
45-
assertThat(ThemeStyle.SYSTEM.themeNoActionBar).isEqualTo(R.style.ThemeSystemNoActionBar)
46-
assertThat(ThemeStyle.BLACK.themeNoActionBar).isEqualTo(R.style.ThemeBlackNoActionBar)
47-
}
48-
4932
@Test
5033
fun colorGraphText() {
5134
assertThat(ThemeStyle.DARK.colorGraphText).isEqualTo(Color.WHITE)

0 commit comments

Comments
 (0)