diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..296046a
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+Topten
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7643783..3cc336b 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,10 +1,25 @@
+
+
-
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 61a9130..fb7f4a8 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 23a89bb..ac6b0ae 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -15,7 +15,6 @@
-
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d5d35ec..4700283 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/app/build.gradle b/app/build.gradle
index 6026007..b42d3a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -72,7 +72,7 @@ android {
dependencies {
- implementation 'androidx.work:work-runtime:2.3.4'
+ implementation 'androidx.work:work-runtime:2.4.0'
def work_version = "2.4.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
@@ -95,9 +95,12 @@ dependencies {
// Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:2.2.5"
+ // LiveData
+ implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
+
// Coroutines
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.6'
// Navigation Components
@@ -112,11 +115,13 @@ dependencies {
implementation 'io.coil-kt:coil:0.11.0'
// JSoup for HTML parsing
- implementation 'org.jsoup:jsoup:1.12.1'
+ implementation 'org.jsoup:jsoup:1.13.1'
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
+ // Preferences DataStore
+ implementation "androidx.datastore:datastore-preferences:1.0.0-alpha01"
}
\ No newline at end of file
diff --git a/app/src/main/java/www/thecodemonks/techbytes/NYTimes.kt b/app/src/main/java/www/thecodemonks/techbytes/NYTimes.kt
index 8232bed..5adf471 100644
--- a/app/src/main/java/www/thecodemonks/techbytes/NYTimes.kt
+++ b/app/src/main/java/www/thecodemonks/techbytes/NYTimes.kt
@@ -27,21 +27,5 @@
package www.thecodemonks.techbytes
import android.app.Application
-import androidx.appcompat.app.AppCompatDelegate
-import www.thecodemonks.techbytes.utils.isNight
-class NYTimes : Application() {
-
- override fun onCreate() {
- super.onCreate()
-
- // check for ui mode & set accordingly
- val mode = if (isNight()) {
- AppCompatDelegate.MODE_NIGHT_YES
- } else {
- AppCompatDelegate.MODE_NIGHT_NO
- }
-
- AppCompatDelegate.setDefaultNightMode(mode)
- }
-}
\ No newline at end of file
+class NYTimes : Application()
\ No newline at end of file
diff --git a/app/src/main/java/www/thecodemonks/techbytes/utils/TimeUtils.kt b/app/src/main/java/www/thecodemonks/techbytes/datastore/UIModePreference.kt
similarity index 55%
rename from app/src/main/java/www/thecodemonks/techbytes/utils/TimeUtils.kt
rename to app/src/main/java/www/thecodemonks/techbytes/datastore/UIModePreference.kt
index daaa7ba..b303abb 100644
--- a/app/src/main/java/www/thecodemonks/techbytes/utils/TimeUtils.kt
+++ b/app/src/main/java/www/thecodemonks/techbytes/datastore/UIModePreference.kt
@@ -24,11 +24,36 @@
*
*/
-package www.thecodemonks.techbytes.utils
+package www.thecodemonks.techbytes.datastore
-import java.util.*
+import android.content.Context
+import androidx.datastore.DataStore
+import androidx.datastore.preferences.Preferences
+import androidx.datastore.preferences.createDataStore
+import androidx.datastore.preferences.edit
+import androidx.datastore.preferences.preferencesKey
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
-fun isNight(): Boolean {
- val currentHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
- return (currentHour <= 7 || currentHour >= 18)
+class UIModePreference(context: Context) {
+
+ companion object {
+ private val UI_MODE_KEY = preferencesKey("ui_mode")
+ }
+
+ private val dataStore: DataStore = context.createDataStore(
+ name = "ui_mode_preference"
+ )
+
+ suspend fun saveToDataStore(isNightMode: Boolean) {
+ dataStore.edit { preferences ->
+ preferences[UI_MODE_KEY] = isNightMode
+ }
+ }
+
+ val uiMode: Flow = dataStore.data
+ .map { preferences ->
+ val uiMode = preferences[UI_MODE_KEY] ?: false
+ uiMode
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/www/thecodemonks/techbytes/ui/articles/ArticlesFragment.kt b/app/src/main/java/www/thecodemonks/techbytes/ui/articles/ArticlesFragment.kt
index 6327b28..4449c33 100644
--- a/app/src/main/java/www/thecodemonks/techbytes/ui/articles/ArticlesFragment.kt
+++ b/app/src/main/java/www/thecodemonks/techbytes/ui/articles/ArticlesFragment.kt
@@ -30,11 +30,15 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
+import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
+import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.fragment_articles.*
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
import www.thecodemonks.techbytes.R
import www.thecodemonks.techbytes.model.Category
import www.thecodemonks.techbytes.ui.adapter.CategoryAdapter
@@ -132,19 +136,43 @@ class ArticlesFragment : Fragment(R.layout.fragment_articles) {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.menu, menu)
+
+ // Set the item state
+ lifecycleScope.launch {
+ val isChecked = viewModel.readDataStore.first()
+ val item = menu.findItem(R.id.action_night_mode)
+ item.isChecked = isChecked
+ setUIMode(isChecked)
+ }
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here.
return when (item.itemId) {
- R.id.action_one -> {
+ R.id.action_bookmark -> {
findNavController().navigate(R.id.action_articlesFragment_to_bookmarksFragment)
true
}
+
+ R.id.action_night_mode -> {
+ item.isChecked = !item.isChecked
+ setUIMode(item.isChecked)
+ true
+ }
else -> super.onOptionsItemSelected(item)
}
}
+ private fun setUIMode(isChecked: Boolean) {
+ if (isChecked) {
+ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
+ viewModel.saveToDataStore(true)
+ } else {
+ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
+ viewModel.saveToDataStore(false)
+ }
+ }
+
private fun setUpArticleRV() {
newsAdapter = NewsAdapter()
article_rv.apply {
diff --git a/app/src/main/java/www/thecodemonks/techbytes/ui/base/BaseActivity.kt b/app/src/main/java/www/thecodemonks/techbytes/ui/base/BaseActivity.kt
index 3d37085..17e036a 100644
--- a/app/src/main/java/www/thecodemonks/techbytes/ui/base/BaseActivity.kt
+++ b/app/src/main/java/www/thecodemonks/techbytes/ui/base/BaseActivity.kt
@@ -60,10 +60,10 @@ class BaseActivity : AppCompatActivity() {
val repo = Repo(
ArticleDatabase(this)
)
- val viewModelProviderFactory =
- NewsViewModelProviderFactory(
- repo
- )
+
+ // Passing application to ViewModel for DataStore
+ val viewModelProviderFactory = NewsViewModelProviderFactory(this.application, repo)
+
viewModel =
ViewModelProvider(this, viewModelProviderFactory).get(ArticleViewModel::class.java)
diff --git a/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ArticleViewModel.kt b/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ArticleViewModel.kt
index 7db1f26..8502966 100644
--- a/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ArticleViewModel.kt
+++ b/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ArticleViewModel.kt
@@ -26,23 +26,29 @@
package www.thecodemonks.techbytes.ui.viewmodel
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
+import www.thecodemonks.techbytes.datastore.UIModePreference
import www.thecodemonks.techbytes.model.Article
import www.thecodemonks.techbytes.repo.Repo
import www.thecodemonks.techbytes.utils.Constants
-class ArticleViewModel(private val repo: Repo) : ViewModel() {
+class ArticleViewModel(application: Application, private val repo: Repo) :
+ AndroidViewModel(application) {
private val _articles = MutableLiveData>()
val articles: LiveData>
get() = _articles
+ // DataStore
+ private val uiDataStore = UIModePreference(application)
+
val currentTopic: MutableLiveData by lazy {
MutableLiveData().defaultTopic(Constants.NY_TECH)
}
@@ -67,6 +73,16 @@ class ArticleViewModel(private val repo: Repo) : ViewModel() {
}
}
+ // Get From DataStore
+ val readDataStore = uiDataStore.uiMode
+
+ // Save to DataStore
+ fun saveToDataStore(isNightMode: Boolean) {
+ viewModelScope.launch(IO) {
+ uiDataStore.saveToDataStore(isNightMode)
+ }
+ }
+
private fun MutableLiveData.defaultTopic(initialValue: T) =
apply { setValue(initialValue) }
diff --git a/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ViewModelProviderFactory.kt b/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ViewModelProviderFactory.kt
index 901d19f..8ba34e9 100644
--- a/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ViewModelProviderFactory.kt
+++ b/app/src/main/java/www/thecodemonks/techbytes/ui/viewmodel/ViewModelProviderFactory.kt
@@ -26,15 +26,16 @@
package www.thecodemonks.techbytes.ui.viewmodel
+import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import www.thecodemonks.techbytes.repo.Repo
-class NewsViewModelProviderFactory(private val repo: Repo) :
+class NewsViewModelProviderFactory(private val application: Application, private val repo: Repo) :
ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
- return ArticleViewModel(repo) as T
+ return ArticleViewModel(application, repo) as T
}
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_outline_dark.xml b/app/src/main/res/drawable/ic_outline_dark.xml
new file mode 100644
index 0000000..5652851
--- /dev/null
+++ b/app/src/main/res/drawable/ic_outline_dark.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/app/src/main/res/menu/menu.xml b/app/src/main/res/menu/menu.xml
index fffc197..8b66a6e 100644
--- a/app/src/main/res/menu/menu.xml
+++ b/app/src/main/res/menu/menu.xml
@@ -2,9 +2,15 @@
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9d30b41..a5acb1f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -29,7 +29,11 @@
Facebook Said Not to Consider Banning Political Ads
The social network has been under intense pressure for allowing misinformation and hate speech to spread on its site.
By Sanju S
+
+
Bookmark
+ Night Mode Switch
+
Bookmarks
No bookmarks yet
Hello blank fragment
diff --git a/build.gradle b/build.gradle
index 6fb8a5d..7595777 100644
--- a/build.gradle
+++ b/build.gradle
@@ -26,13 +26,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = "1.3.72"
+ ext.kotlin_version = "1.4.10"
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.2.0-alpha09'
+ classpath 'com.android.tools.build:gradle:4.2.0-alpha12'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.0"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index b9ad6d7..4522e33 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -29,4 +29,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-rc-6-all.zip
+distributionUrl=https://services.gradle.org/distributions/gradle-6.6.1-bin.zip