Skip to content

Commit 3261176

Browse files
Merge 7a3f5d9 into b69a5f4
2 parents b69a5f4 + 7a3f5d9 commit 3261176

File tree

36 files changed

+671
-119
lines changed

36 files changed

+671
-119
lines changed

app/build.gradle.kts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ android {
1515
versionName = Config.versionName
1616

1717
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18+
19+
multiDexEnabled = true
1820
}
1921

2022
buildTypes {
@@ -37,20 +39,39 @@ android {
3739
kotlinOptions {
3840
jvmTarget = "1.8"
3941
}
42+
43+
buildFeatures {
44+
viewBinding = true
45+
}
4046
}
4147

4248
dependencies {
4349
// androidx
4450
implementation(Dependencies.Androidx.appCompat)
51+
4552
implementation(Dependencies.Androidx.constraintLayout)
53+
4654
implementation(Dependencies.Androidx.core)
47-
implementation(Dependencies.Androidx.splashScreen)
55+
implementation(Dependencies.Androidx.coerSplashScreen)
56+
57+
implementation(Dependencies.Androidx.dataStorePrefs)
58+
59+
implementation(Dependencies.Androidx.lifecycleRunTime)
60+
implementation(Dependencies.Androidx.lifecycleLiveData)
61+
implementation(Dependencies.Androidx.lifecycleViewModel)
62+
63+
implementation(Dependencies.Androidx.multidex)
64+
65+
implementation(Dependencies.JetBrains.coroutinesAndroid)
66+
implementation(Dependencies.JetBrains.coroutinesCore)
4867

4968
// google
5069
implementation(Dependencies.Google.material)
5170

52-
// test
71+
// androidTest
5372
androidTestImplementation(Dependencies.Androidx.testEspresso)
5473
androidTestImplementation(Dependencies.Androidx.testJunit)
74+
75+
// test
5576
testImplementation(Dependencies.Junit.junit)
5677
}

app/proguard-rules.pro

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@
1818

1919
# If you keep the line number information, uncomment this to
2020
# hide the original source file name.
21-
#-renamesourcefileattribute SourceFile
21+
#-renamesourcefileattribute SourceFile
22+
23+
# Se você quiser minimizar sua compilação, certifique-se de adicionar uma regra adicional para evitar que seus campos sejam excluídos
24+
-keepclassmembers class * extends androidx.datastore.preferences.protobuf.GeneratedMessageLite {
25+
<fields>;
26+
}

app/src/androidTest/java/com/viniciusjanner/android_github_actions/ExampleInstrumentedTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.viniciusjanner.android_github_actions
22

3-
import androidx.test.platform.app.InstrumentationRegistry
43
import androidx.test.ext.junit.runners.AndroidJUnit4
4+
import androidx.test.platform.app.InstrumentationRegistry
55
import org.junit.Assert.assertEquals
66
import org.junit.Test
77
import org.junit.runner.RunWith

app/src/main/AndroidManifest.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:tools="http://schemas.android.com/tools">
44

5+
<!--API 19 : force usage (may lead to runtime failures)-->
6+
<uses-sdk tools:overrideLibrary="androidx.core.splashscreen"/>
7+
58
<application
9+
android:name=".App"
610
android:allowBackup="true"
711
android:dataExtractionRules="@xml/data_extraction_rules"
812
android:fullBackupContent="@xml/backup_rules"
@@ -15,7 +19,7 @@
1519
tools:targetApi="31">
1620

1721
<activity
18-
android:name=".HomeActivity"
22+
android:name=".ui.HomeActivity"
1923
android:exported="true"
2024
android:theme="@style/Theme.Splash">
2125
<intent-filter>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.viniciusjanner.android_github_actions
2+
3+
import android.util.Log
4+
import androidx.appcompat.app.AppCompatDelegate
5+
import androidx.multidex.MultiDexApplication
6+
import com.viniciusjanner.android_github_actions.prefs.DataStoreManager
7+
import kotlinx.coroutines.CoroutineExceptionHandler
8+
import kotlinx.coroutines.CoroutineScope
9+
import kotlinx.coroutines.Dispatchers
10+
import kotlinx.coroutines.launch
11+
import kotlin.coroutines.CoroutineContext
12+
13+
class App : MultiDexApplication() {
14+
15+
companion object {
16+
lateinit var dataStoreManager: DataStoreManager
17+
}
18+
19+
override fun onCreate() {
20+
super.onCreate()
21+
dataStoreManager = DataStoreManager(this@App)
22+
23+
val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
24+
Log.e("App", "coroutineExceptionHandler : throwable = ${throwable.message}")
25+
throwable.printStackTrace()
26+
}
27+
28+
val coroutineContext: CoroutineContext = Dispatchers.Default + coroutineExceptionHandler
29+
30+
CoroutineScope(coroutineContext).launch {
31+
dataStoreManager.getTheme().collect {
32+
AppCompatDelegate.setDefaultNightMode(
33+
if (it) AppCompatDelegate.MODE_NIGHT_YES
34+
else AppCompatDelegate.MODE_NIGHT_NO
35+
)
36+
}
37+
}
38+
}
39+
}

app/src/main/java/com/viniciusjanner/android_github_actions/HomeActivity.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.viniciusjanner.android_github_actions.prefs
2+
3+
import android.content.Context
4+
import androidx.datastore.core.DataStore
5+
import androidx.datastore.preferences.core.Preferences
6+
import androidx.datastore.preferences.core.booleanPreferencesKey
7+
import androidx.datastore.preferences.core.edit
8+
import androidx.datastore.preferences.core.emptyPreferences
9+
import androidx.datastore.preferences.preferencesDataStore
10+
import kotlinx.coroutines.flow.Flow
11+
import kotlinx.coroutines.flow.catch
12+
import kotlinx.coroutines.flow.map
13+
import java.io.IOException
14+
15+
class DataStoreManager(context: Context) {
16+
17+
private val dataStore = context.dataStore
18+
19+
companion object {
20+
21+
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "THEME_KEY")
22+
23+
val darkModeKey: Preferences.Key<Boolean> = booleanPreferencesKey("DARK_MODE_KEY")
24+
}
25+
26+
suspend fun setTheme(isDarkMode: Boolean) {
27+
dataStore.edit { mutablePrefs ->
28+
mutablePrefs[darkModeKey] = isDarkMode
29+
}
30+
}
31+
32+
fun getTheme(): Flow<Boolean> {
33+
return dataStore.data
34+
.catch {
35+
if (it is IOException) {
36+
it.printStackTrace()
37+
emit(emptyPreferences())
38+
} else {
39+
throw it
40+
}
41+
}
42+
.map { prefs ->
43+
val uiMode: Boolean = prefs[darkModeKey] ?: false
44+
uiMode
45+
}
46+
}
47+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.viniciusjanner.android_github_actions.prefs
2+
3+
enum class ThemeMode {
4+
LIGHT, DARK
5+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.viniciusjanner.android_github_actions.ui
2+
3+
import android.os.Build
4+
import android.os.Bundle
5+
import androidx.appcompat.app.AppCompatActivity
6+
import androidx.appcompat.app.AppCompatDelegate
7+
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
8+
import androidx.lifecycle.ViewModelProvider
9+
import com.viniciusjanner.android_github_actions.App
10+
import com.viniciusjanner.android_github_actions.R
11+
import com.viniciusjanner.android_github_actions.databinding.ActivityHomeBinding
12+
import com.viniciusjanner.android_github_actions.prefs.ThemeMode
13+
import com.viniciusjanner.android_github_actions.util.AppConstants
14+
import kotlinx.coroutines.delay
15+
import kotlinx.coroutines.runBlocking
16+
17+
class HomeActivity : AppCompatActivity() {
18+
19+
private var _binding: ActivityHomeBinding? = null
20+
private val binding get() = _binding!!
21+
22+
private lateinit var viewModel: HomeViewModel
23+
24+
override fun onCreate(savedInstanceState: Bundle?) {
25+
// Splash Screen
26+
runBlocking {
27+
when (Build.VERSION.SDK_INT) {
28+
in AppConstants.sdkMin..AppConstants.sdkMax -> {
29+
delay(AppConstants.delay)
30+
setTheme(R.style.Theme_Home)
31+
}
32+
else -> {
33+
installSplashScreen()
34+
delay(AppConstants.delay)
35+
}
36+
}
37+
}
38+
39+
// Home Screen
40+
super.onCreate(savedInstanceState)
41+
_binding = ActivityHomeBinding.inflate(layoutInflater)
42+
setContentView(binding.root)
43+
44+
initInstances()
45+
initObservers()
46+
initListeners()
47+
}
48+
49+
override fun onDestroy() {
50+
_binding = null
51+
super.onDestroy()
52+
}
53+
54+
@Suppress("MaxLineLength")
55+
private fun initInstances() {
56+
val dataStoreManager = App.dataStoreManager
57+
viewModel = ViewModelProvider(this, HomeViewModelFactory(this.application, dataStoreManager))[HomeViewModel::class.java]
58+
}
59+
60+
private fun initObservers() {
61+
viewModel.themeLiveData.observe(this@HomeActivity) { themeMode ->
62+
val isCheck = (themeMode == ThemeMode.DARK)
63+
64+
binding.switchTheme.apply {
65+
isChecked = isCheck
66+
text = getString(if (isCheck) R.string.home_mode_dark else R.string.home_mode_light)
67+
}
68+
69+
val nightMode = if (isCheck) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO
70+
AppCompatDelegate.setDefaultNightMode(nightMode)
71+
delegate.applyDayNight()
72+
}
73+
}
74+
75+
private fun initListeners() {
76+
binding.switchTheme.setOnCheckedChangeListener { _, isChecked ->
77+
val themeMode = if (isChecked) ThemeMode.DARK else ThemeMode.LIGHT
78+
viewModel.setTheme(themeMode)
79+
}
80+
}
81+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.viniciusjanner.android_github_actions.ui
2+
3+
import android.app.Application
4+
import androidx.lifecycle.AndroidViewModel
5+
import androidx.lifecycle.LiveData
6+
import androidx.lifecycle.asLiveData
7+
import androidx.lifecycle.viewModelScope
8+
import com.viniciusjanner.android_github_actions.prefs.DataStoreManager
9+
import com.viniciusjanner.android_github_actions.prefs.ThemeMode
10+
import kotlinx.coroutines.Dispatchers
11+
import kotlinx.coroutines.flow.map
12+
import kotlinx.coroutines.launch
13+
14+
class HomeViewModel(
15+
application: Application, private val dataStoreManager: DataStoreManager
16+
) : AndroidViewModel(application) {
17+
18+
val themeLiveData: LiveData<ThemeMode> = getTheme()
19+
20+
private fun getTheme(): LiveData<ThemeMode> = dataStoreManager.getTheme()
21+
.map { isDarkMode ->
22+
if (isDarkMode) ThemeMode.DARK else ThemeMode.LIGHT
23+
}
24+
.asLiveData()
25+
26+
fun setTheme(themeMode: ThemeMode) {
27+
val isDarkMode = (themeMode == ThemeMode.DARK)
28+
viewModelScope.launch(Dispatchers.Default) {
29+
dataStoreManager.setTheme(isDarkMode)
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)