Update libraries, create CircularRepository.kt

This commit is contained in:
2020-10-23 16:19:29 +02:00
committed by Matte23
parent f5fe6c1396
commit 3ca6539135
14 changed files with 198 additions and 111 deletions

View File

@@ -37,19 +37,17 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.core:core-ktx:1.3.1' implementation 'androidx.core:core-ktx:1.3.2'
implementation 'com.google.android.material:material:1.3.0-alpha02' implementation 'com.google.android.material:material:1.3.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation 'androidx.navigation:navigation-ui:2.3.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0' implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0' implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation "androidx.work:work-runtime-ktx:2.4.0" implementation "androidx.work:work-runtime-ktx:2.4.0"
implementation "androidx.room:room-runtime:2.2.5" implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5" kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5" implementation "androidx.room:room-ktx:2.2.5"
implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.3.0'

View File

@@ -0,0 +1,51 @@
package net.underdesk.circolapp.data
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.server.DataFetcher
import java.io.IOException
class CircularRepository(
val circularDao: CircularDao,
private val fetcher: DataFetcher = DataFetcher()
) {
suspend fun updateCirculars(returnNewCirculars: Boolean = true): Pair<List<Circular>, Boolean> {
var onlyNewCirculars = listOf<Circular>()
try {
withContext(Dispatchers.IO) {
val oldCirculars = circularDao.getCirculars()
val newCirculars = fetcher.getCircularsFromServer()
if (newCirculars.size != oldCirculars.size) {
if (newCirculars.size < oldCirculars.size) {
circularDao.deleteAll()
}
if (returnNewCirculars) {
val oldCircularsSize =
if (newCirculars.size < oldCirculars.size) 0 else oldCirculars.size
val circularCount = newCirculars.size - oldCircularsSize
onlyNewCirculars = newCirculars.subList(0, circularCount)
}
circularDao.insertAll(newCirculars)
}
}
} catch (exception: IOException) {
return Pair(onlyNewCirculars, false)
}
return Pair(onlyNewCirculars, true)
}
companion object {
@Volatile
private var instance: CircularRepository? = null
fun getInstance(circularDao: CircularDao) =
instance ?: synchronized(this) {
instance ?: CircularRepository(circularDao).also { instance = it }
}
}
}

View File

@@ -32,14 +32,23 @@ import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.MainActivity import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.CircularRepository
import net.underdesk.circolapp.viewmodels.CircularLetterViewModel import net.underdesk.circolapp.viewmodels.CircularLetterViewModel
import net.underdesk.circolapp.viewmodels.CircularLetterViewModelFactory
class CircularLetterFragment : class CircularLetterFragment :
Fragment(), Fragment(),
MainActivity.SearchCallback, MainActivity.SearchCallback,
MainActivity.RefreshCallback { MainActivity.RefreshCallback {
private val circularLetterViewModel by viewModels<CircularLetterViewModel>() private val circularLetterViewModel: CircularLetterViewModel by viewModels {
CircularLetterViewModelFactory(
CircularRepository.getInstance(
AppDatabase.getInstance(requireContext()).circularDao()
)
)
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,

View File

@@ -29,11 +29,20 @@ import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.MainActivity import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.CircularRepository
import net.underdesk.circolapp.viewmodels.FavouritesViewModel import net.underdesk.circolapp.viewmodels.FavouritesViewModel
import net.underdesk.circolapp.viewmodels.FavouritesViewModelFactory
class FavouritesFragment : Fragment(), MainActivity.SearchCallback { class FavouritesFragment : Fragment(), MainActivity.SearchCallback {
private val favouritesViewModel by viewModels<FavouritesViewModel>() private val favouritesViewModel: FavouritesViewModel by viewModels {
FavouritesViewModelFactory(
CircularRepository.getInstance(
AppDatabase.getInstance(requireContext()).circularDao()
)
)
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,

View File

@@ -29,11 +29,20 @@ import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.MainActivity import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R import net.underdesk.circolapp.R
import net.underdesk.circolapp.adapters.CircularLetterAdapter import net.underdesk.circolapp.adapters.CircularLetterAdapter
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.CircularRepository
import net.underdesk.circolapp.viewmodels.RemindersViewModel import net.underdesk.circolapp.viewmodels.RemindersViewModel
import net.underdesk.circolapp.viewmodels.RemindersViewModelFactory
class RemindersFragment : Fragment(), MainActivity.SearchCallback { class RemindersFragment : Fragment(), MainActivity.SearchCallback {
private val remindersViewModel by viewModels<RemindersViewModel>() private val remindersViewModel: RemindersViewModel by viewModels {
RemindersViewModelFactory(
CircularRepository.getInstance(
AppDatabase.getInstance(requireContext()).circularDao()
)
)
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,

View File

@@ -18,17 +18,14 @@
package net.underdesk.circolapp.viewmodels package net.underdesk.circolapp.viewmodels
import android.app.Application
import androidx.lifecycle.* import androidx.lifecycle.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.Circular import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.server.DataFetcher import net.underdesk.circolapp.data.CircularRepository
import java.io.IOException
class CircularLetterViewModel(application: Application) : AndroidViewModel(application) { class CircularLetterViewModel internal constructor(
private val circularRepository: CircularRepository
) : ViewModel() {
init { init {
updateCirculars() updateCirculars()
} }
@@ -36,9 +33,9 @@ class CircularLetterViewModel(application: Application) : AndroidViewModel(appli
val query = MutableLiveData("") val query = MutableLiveData("")
val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input -> val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input ->
if (input == null || input == "") { if (input == null || input == "") {
AppDatabase.getInstance(getApplication()).circularDao().getLiveCirculars() circularRepository.circularDao.getLiveCirculars()
} else { } else {
AppDatabase.getInstance(getApplication()).circularDao().searchCirculars("%$input%") circularRepository.circularDao.searchCirculars("%$input%")
} }
} }
@@ -50,27 +47,13 @@ class CircularLetterViewModel(application: Application) : AndroidViewModel(appli
if (isNotUpdating) { if (isNotUpdating) {
viewModelScope.launch { viewModelScope.launch {
isNotUpdating = false isNotUpdating = false
val fetcher = DataFetcher()
try { if (!circularRepository.updateCirculars(false).second) {
withContext(Dispatchers.IO) {
val newCirculars = fetcher.getCircularsFromServer()
if (newCirculars.size != circulars.value?.size ?: true) {
if (newCirculars.size < circulars.value?.size ?: 0) {
AppDatabase.getInstance(getApplication()).circularDao()
.deleteAll()
}
AppDatabase.getInstance(getApplication()).circularDao()
.insertAll(newCirculars)
}
}
} catch (exception: IOException) {
showMessage.postValue(true) showMessage.postValue(true)
} finally {
isNotUpdating = true
circularsUpdated.postValue(true)
} }
isNotUpdating = true
circularsUpdated.postValue(true)
} }
} }
} }

View File

@@ -0,0 +1,15 @@
package net.underdesk.circolapp.viewmodels
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import net.underdesk.circolapp.data.CircularRepository
class CircularLetterViewModelFactory(
private val circularRepository: CircularRepository
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return CircularLetterViewModel(circularRepository) as T
}
}

View File

@@ -18,21 +18,22 @@
package net.underdesk.circolapp.viewmodels package net.underdesk.circolapp.viewmodels
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import net.underdesk.circolapp.data.AppDatabase import androidx.lifecycle.ViewModel
import net.underdesk.circolapp.data.Circular import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.data.CircularRepository
class FavouritesViewModel(application: Application) : AndroidViewModel(application) { class FavouritesViewModel internal constructor(
private val circularRepository: CircularRepository
) : ViewModel() {
val query = MutableLiveData("") val query = MutableLiveData("")
val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input -> val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input ->
if (input == null || input == "") { if (input == null || input == "") {
AppDatabase.getInstance(getApplication()).circularDao().getFavourites() circularRepository.circularDao.getFavourites()
} else { } else {
AppDatabase.getInstance(getApplication()).circularDao().searchFavourites("%$input%") circularRepository.circularDao.searchFavourites("%$input%")
} }
} }
} }

View File

@@ -0,0 +1,15 @@
package net.underdesk.circolapp.viewmodels
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import net.underdesk.circolapp.data.CircularRepository
class FavouritesViewModelFactory(
private val circularRepository: CircularRepository
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return FavouritesViewModel(circularRepository) as T
}
}

View File

@@ -18,21 +18,22 @@
package net.underdesk.circolapp.viewmodels package net.underdesk.circolapp.viewmodels
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import net.underdesk.circolapp.data.AppDatabase import androidx.lifecycle.ViewModel
import net.underdesk.circolapp.data.Circular import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.data.CircularRepository
class RemindersViewModel(application: Application) : AndroidViewModel(application) { class RemindersViewModel internal constructor(
private val circularRepository: CircularRepository
) : ViewModel() {
val query = MutableLiveData("") val query = MutableLiveData("")
val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input -> val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input ->
if (input == null || input == "") { if (input == null || input == "") {
AppDatabase.getInstance(getApplication()).circularDao().getReminders() circularRepository.circularDao.getReminders()
} else { } else {
AppDatabase.getInstance(getApplication()).circularDao().searchReminders("%$input%") circularRepository.circularDao.searchReminders("%$input%")
} }
} }
} }

View File

@@ -0,0 +1,15 @@
package net.underdesk.circolapp.viewmodels
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import net.underdesk.circolapp.data.CircularRepository
class RemindersViewModelFactory(
private val circularRepository: CircularRepository
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return RemindersViewModel(circularRepository) as T
}
}

View File

@@ -30,15 +30,12 @@ import androidx.core.app.NotificationManagerCompat
import androidx.core.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.work.* import androidx.work.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.MainActivity import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AppDatabase import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.Circular import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.server.DataFetcher import net.underdesk.circolapp.data.CircularRepository
import java.io.IOException
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class PollWork(appContext: Context, workerParams: WorkerParameters) : class PollWork(appContext: Context, workerParams: WorkerParameters) :
@@ -87,66 +84,50 @@ class PollWork(appContext: Context, workerParams: WorkerParameters) :
} }
override suspend fun doWork(): Result = coroutineScope { override suspend fun doWork(): Result = coroutineScope {
val fetcher = DataFetcher() val circularRepository = CircularRepository.getInstance(
AppDatabase.getInstance(applicationContext).circularDao()
)
withContext(Dispatchers.IO) { val result = circularRepository.updateCirculars()
val oldCirculars = if (!result.second)
AppDatabase.getInstance(applicationContext).circularDao().getCirculars() return@coroutineScope Result.retry()
val newCirculars = try {
fetcher.getCircularsFromServer() val newCirculars = result.first
} catch (exception: IOException) {
return@withContext Result.retry() if (newCirculars.isNotEmpty()) {
createNotificationChannel()
val summaryStyle = NotificationCompat.InboxStyle()
.setBigContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setSummaryText(applicationContext.getString(R.string.notification_summary))
for (circular in newCirculars) {
createNotification(circular)
summaryStyle.addLine(circular.name)
} }
if (newCirculars.size != oldCirculars.size) { val summaryNotification =
val oldCircularsSize = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
if (newCirculars.size < oldCirculars.size) 0 else oldCirculars.size .setContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setContentText(
applicationContext.resources.getQuantityString(
R.plurals.notification_summary_text,
newCirculars.size,
newCirculars.size
)
)
.setSmallIcon(R.drawable.ic_notification)
.setStyle(summaryStyle)
.setGroup(CHANNEL_ID)
.setGroupSummary(true)
.build()
withContext(Dispatchers.Main) { with(NotificationManagerCompat.from(applicationContext)) {
createNotificationChannel() notify(-1, summaryNotification)
val summaryStyle = NotificationCompat.InboxStyle()
.setBigContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setSummaryText(applicationContext.getString(R.string.notification_summary))
val circularCount = newCirculars.size - oldCircularsSize
for (i in 0 until circularCount) {
createNotification(newCirculars[i])
summaryStyle.addLine(newCirculars[i].name)
}
val summaryNotification =
NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setContentTitle(applicationContext.getString(R.string.notification_summary_title))
.setContentText(
applicationContext.resources.getQuantityString(
R.plurals.notification_summary_text,
circularCount,
circularCount
)
)
.setSmallIcon(R.drawable.ic_notification)
.setStyle(summaryStyle)
.setGroup(CHANNEL_ID)
.setGroupSummary(true)
.build()
with(NotificationManagerCompat.from(applicationContext)) {
notify(-1, summaryNotification)
}
}
if (newCirculars.size < oldCirculars.size) {
AppDatabase.getInstance(applicationContext).circularDao()
.deleteAll()
}
AppDatabase.getInstance(applicationContext).circularDao()
.insertAll(newCirculars)
} }
Result.success()
} }
Result.success()
} }
private fun createNotification(circular: Circular) { private fun createNotification(circular: Circular) {

View File

@@ -11,7 +11,7 @@ buildscript {
} }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libs_version" classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libs_version"
classpath "org.jlleitschuh.gradle:ktlint-gradle:9.4.0" classpath "org.jlleitschuh.gradle:ktlint-gradle:9.4.0"

View File

@@ -1,6 +1,6 @@
#Tue Sep 01 12:16:30 CEST 2020 #Wed Oct 21 19:00:49 CEST 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip