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 "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'com.google.android.material:material:1.3.0-alpha02'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation 'androidx.navigation:navigation-ui:2.3.0'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'com.google.android.material:material:1.3.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation "androidx.work:work-runtime-ktx:2.4.0"
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler: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'
testImplementation 'junit:junit:4.13'
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.R
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.CircularLetterViewModelFactory
class CircularLetterFragment :
Fragment(),
MainActivity.SearchCallback,
MainActivity.RefreshCallback {
private val circularLetterViewModel by viewModels<CircularLetterViewModel>()
private val circularLetterViewModel: CircularLetterViewModel by viewModels {
CircularLetterViewModelFactory(
CircularRepository.getInstance(
AppDatabase.getInstance(requireContext()).circularDao()
)
)
}
override fun onCreateView(
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.R
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.FavouritesViewModelFactory
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(
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.R
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.RemindersViewModelFactory
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(
inflater: LayoutInflater,

View File

@@ -18,17 +18,14 @@
package net.underdesk.circolapp.viewmodels
import android.app.Application
import androidx.lifecycle.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.server.DataFetcher
import java.io.IOException
import net.underdesk.circolapp.data.CircularRepository
class CircularLetterViewModel(application: Application) : AndroidViewModel(application) {
class CircularLetterViewModel internal constructor(
private val circularRepository: CircularRepository
) : ViewModel() {
init {
updateCirculars()
}
@@ -36,9 +33,9 @@ class CircularLetterViewModel(application: Application) : AndroidViewModel(appli
val query = MutableLiveData("")
val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input ->
if (input == null || input == "") {
AppDatabase.getInstance(getApplication()).circularDao().getLiveCirculars()
circularRepository.circularDao.getLiveCirculars()
} else {
AppDatabase.getInstance(getApplication()).circularDao().searchCirculars("%$input%")
circularRepository.circularDao.searchCirculars("%$input%")
}
}
@@ -50,27 +47,13 @@ class CircularLetterViewModel(application: Application) : AndroidViewModel(appli
if (isNotUpdating) {
viewModelScope.launch {
isNotUpdating = false
val fetcher = DataFetcher()
try {
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) {
if (!circularRepository.updateCirculars(false).second) {
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
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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.CircularRepository
class FavouritesViewModel(application: Application) : AndroidViewModel(application) {
class FavouritesViewModel internal constructor(
private val circularRepository: CircularRepository
) : ViewModel() {
val query = MutableLiveData("")
val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input ->
if (input == null || input == "") {
AppDatabase.getInstance(getApplication()).circularDao().getFavourites()
circularRepository.circularDao.getFavourites()
} 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
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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.CircularRepository
class RemindersViewModel(application: Application) : AndroidViewModel(application) {
class RemindersViewModel internal constructor(
private val circularRepository: CircularRepository
) : ViewModel() {
val query = MutableLiveData("")
val circulars: LiveData<List<Circular>> = Transformations.switchMap(query) { input ->
if (input == null || input == "") {
AppDatabase.getInstance(getApplication()).circularDao().getReminders()
circularRepository.circularDao.getReminders()
} 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.preference.PreferenceManager
import androidx.work.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext
import net.underdesk.circolapp.MainActivity
import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.Circular
import net.underdesk.circolapp.server.DataFetcher
import java.io.IOException
import net.underdesk.circolapp.data.CircularRepository
import java.util.concurrent.TimeUnit
class PollWork(appContext: Context, workerParams: WorkerParameters) :
@@ -87,66 +84,50 @@ class PollWork(appContext: Context, workerParams: WorkerParameters) :
}
override suspend fun doWork(): Result = coroutineScope {
val fetcher = DataFetcher()
val circularRepository = CircularRepository.getInstance(
AppDatabase.getInstance(applicationContext).circularDao()
)
withContext(Dispatchers.IO) {
val oldCirculars =
AppDatabase.getInstance(applicationContext).circularDao().getCirculars()
val newCirculars = try {
fetcher.getCircularsFromServer()
} catch (exception: IOException) {
return@withContext Result.retry()
val result = circularRepository.updateCirculars()
if (!result.second)
return@coroutineScope Result.retry()
val newCirculars = result.first
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 oldCircularsSize =
if (newCirculars.size < oldCirculars.size) 0 else oldCirculars.size
val summaryNotification =
NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.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) {
createNotificationChannel()
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)
with(NotificationManagerCompat.from(applicationContext)) {
notify(-1, summaryNotification)
}
Result.success()
}
Result.success()
}
private fun createNotification(circular: Circular) {