Skip to content
Merged

Theme #588

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
4 changes: 2 additions & 2 deletions app/build.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Build Properties
#Sat Jan 17 10:15:29 EST 2026
version_build=1
#Sat Jan 17 13:51:56 EST 2026
version_build=2
version_major=3
version_minor=2
version_patch=2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,9 @@ class MainInstrumentedTest {
fun settings() {
SettingsInstrumentedTest().run()
}

@Test
fun theme() {
ThemeInstrumentedTest().run()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* WiFiAnalyzer
* Copyright (C) 2015 - 2026 VREM Software Development <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.vrem.wifianalyzer

import androidx.appcompat.app.AppCompatDelegate
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withText
import org.junit.Assert.assertEquals

internal class ThemeInstrumentedTest : Runnable {
override fun run() {
listOf(
"Light" to AppCompatDelegate.MODE_NIGHT_NO,
"System" to AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
"Black" to AppCompatDelegate.MODE_NIGHT_YES,
"Dark" to AppCompatDelegate.MODE_NIGHT_YES,
).forEach { (themeName, expectedNightMode) ->
changeThemeAndVerify(themeName, expectedNightMode)
}
}

private fun changeThemeAndVerify(
themeName: String,
expectedNightMode: Int,
) {
selectMenuItem(R.id.nav_drawer_settings, "Settings")
scrollToAndVerify("Theme")
onView(withText("Theme")).perform(click())
pauseShort()
onView(withText(themeName)).check(matches(isDisplayed()))
onView(withText(themeName)).perform(click())
pauseShort()
assertEquals(
"Theme $themeName should set night mode to $expectedNightMode",
expectedNightMode,
AppCompatDelegate.getDefaultNightMode(),
)
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/com/vrem/wifianalyzer/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class MainActivity :

val settings = mainContext.settings
settings.initializeDefaultValues()
setTheme(settings.themeStyle().themeNoActionBar)
settings.themeStyle().setTheme(this)

mainReload = MainReload(settings)

Expand Down
20 changes: 14 additions & 6 deletions app/src/main/kotlin/com/vrem/wifianalyzer/settings/ThemeStyle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,23 @@ package com.vrem.wifianalyzer.settings
import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.StyleRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import com.vrem.wifianalyzer.R

enum class ThemeStyle(
@param:StyleRes val theme: Int,
@param:StyleRes val themeNoActionBar: Int,
@param:ColorInt val colorGraphText: Int,
@param:StyleRes private val theme: Int,
private val nightMode: Int,
) {
DARK(R.style.ThemeDark, R.style.ThemeDarkNoActionBar, Color.WHITE),
LIGHT(R.style.ThemeLight, R.style.ThemeLightNoActionBar, Color.BLACK),
SYSTEM(R.style.ThemeSystem, R.style.ThemeSystemNoActionBar, Color.GRAY),
BLACK(R.style.ThemeBlack, R.style.ThemeBlackNoActionBar, Color.WHITE),
DARK(Color.WHITE, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
LIGHT(Color.BLACK, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_NO),
SYSTEM(Color.GRAY, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM),
BLACK(Color.WHITE, R.style.ThemeBlackNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
;

fun setTheme(activity: AppCompatActivity) {
activity.setTheme(theme)
AppCompatDelegate.setDefaultNightMode(nightMode)
}
}
20 changes: 0 additions & 20 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,6 @@

<resources>

<!-- Dark theme -->
<style name="ThemeDark" parent="Theme.AppCompat">
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
<item name="android:actionMenuTextColor">@color/selected</item>
</style>
<style name="ThemeDarkNoActionBar" parent="ThemeDark">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<!-- Light theme -->
<style name="ThemeLight" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
<item name="android:actionMenuTextColor">@color/selected</item>
</style>
<style name="ThemeLightNoActionBar" parent="ThemeLight">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<!-- Black theme -->
<style name="ThemeBlack" parent="Theme.AppCompat">
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* WiFiAnalyzer
* Copyright (C) 2015 - 2026 VREM Software Development <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.vrem.wifianalyzer.settings

import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import com.vrem.wifianalyzer.R
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.mockito.Mockito
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify

@RunWith(Parameterized::class)
class ThemeStyleParameterizedTest(
private val themeStyle: ThemeStyle,
private val expectedTheme: Int,
private val expectedNightMode: Int,
) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{0}")
fun data(): Collection<Array<Any>> =
listOf(
arrayOf(ThemeStyle.DARK, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
arrayOf(ThemeStyle.LIGHT, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_NO),
arrayOf(ThemeStyle.SYSTEM, R.style.ThemeSystemNoActionBar, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM),
arrayOf(ThemeStyle.BLACK, R.style.ThemeBlackNoActionBar, AppCompatDelegate.MODE_NIGHT_YES),
)
}

@Test
fun setThemeParameterized() {
// Arrange
val activity: AppCompatActivity = mock()
Mockito.mockStatic(AppCompatDelegate::class.java).use { mockedStatic ->
// Act
themeStyle.setTheme(activity)
// Assert
verify(activity).setTheme(expectedTheme)
mockedStatic.verify { AppCompatDelegate.setDefaultNightMode(expectedNightMode) }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package com.vrem.wifianalyzer.settings

import android.graphics.Color
import com.vrem.wifianalyzer.R
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test

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

@Test
fun theme() {
assertThat(ThemeStyle.LIGHT.theme).isEqualTo(R.style.ThemeLight)
assertThat(ThemeStyle.DARK.theme).isEqualTo(R.style.ThemeDark)
assertThat(ThemeStyle.SYSTEM.theme).isEqualTo(R.style.ThemeSystem)
assertThat(ThemeStyle.BLACK.theme).isEqualTo(R.style.ThemeBlack)
}

@Test
fun themeNoActionBar() {
assertThat(ThemeStyle.DARK.themeNoActionBar).isEqualTo(R.style.ThemeDarkNoActionBar)
assertThat(ThemeStyle.LIGHT.themeNoActionBar).isEqualTo(R.style.ThemeLightNoActionBar)
assertThat(ThemeStyle.SYSTEM.themeNoActionBar).isEqualTo(R.style.ThemeSystemNoActionBar)
assertThat(ThemeStyle.BLACK.themeNoActionBar).isEqualTo(R.style.ThemeBlackNoActionBar)
}

@Test
fun colorGraphText() {
assertThat(ThemeStyle.DARK.colorGraphText).isEqualTo(Color.WHITE)
Expand Down