From 3ca6539135a81cf22a496cedc225d2e29673037a Mon Sep 17 00:00:00 2001 From: Matte23 Date: Fri, 23 Oct 2020 16:19:29 +0200 Subject: [PATCH] Update libraries, create CircularRepository.kt --- app/build.gradle | 14 ++- .../circolapp/data/CircularRepository.kt | 51 ++++++++++ .../fragments/CircularLetterFragment.kt | 11 ++- .../circolapp/fragments/FavouritesFragment.kt | 11 ++- .../circolapp/fragments/RemindersFragment.kt | 11 ++- .../viewmodels/CircularLetterViewModel.kt | 37 ++----- .../CircularLetterViewModelFactory.kt | 15 +++ .../viewmodels/FavouritesViewModel.kt | 13 +-- .../viewmodels/FavouritesViewModelFactory.kt | 15 +++ .../viewmodels/RemindersViewModel.kt | 13 +-- .../viewmodels/RemindersViewModelFactory.kt | 15 +++ .../net/underdesk/circolapp/works/PollWork.kt | 97 ++++++++----------- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 14 files changed, 198 insertions(+), 111 deletions(-) create mode 100644 app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt create mode 100644 app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModelFactory.kt create mode 100644 app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModelFactory.kt create mode 100644 app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModelFactory.kt diff --git a/app/build.gradle b/app/build.gradle index 1c2ffa6..89496b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' diff --git a/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt b/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt new file mode 100644 index 0000000..d800f31 --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/data/CircularRepository.kt @@ -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, Boolean> { + var onlyNewCirculars = listOf() + + 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 } + } + } +} diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt index b342a3b..1bf5f2a 100644 --- a/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt +++ b/app/src/main/java/net/underdesk/circolapp/fragments/CircularLetterFragment.kt @@ -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() + private val circularLetterViewModel: CircularLetterViewModel by viewModels { + CircularLetterViewModelFactory( + CircularRepository.getInstance( + AppDatabase.getInstance(requireContext()).circularDao() + ) + ) + } override fun onCreateView( inflater: LayoutInflater, diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt index d52ad0c..1e3e335 100644 --- a/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt +++ b/app/src/main/java/net/underdesk/circolapp/fragments/FavouritesFragment.kt @@ -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() + private val favouritesViewModel: FavouritesViewModel by viewModels { + FavouritesViewModelFactory( + CircularRepository.getInstance( + AppDatabase.getInstance(requireContext()).circularDao() + ) + ) + } override fun onCreateView( inflater: LayoutInflater, diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt index 96368ab..eadc6fa 100644 --- a/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt +++ b/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt @@ -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() + private val remindersViewModel: RemindersViewModel by viewModels { + RemindersViewModelFactory( + CircularRepository.getInstance( + AppDatabase.getInstance(requireContext()).circularDao() + ) + ) + } override fun onCreateView( inflater: LayoutInflater, diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModel.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModel.kt index 9e8fae8..91c3caf 100644 --- a/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModel.kt +++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModel.kt @@ -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> = 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) } } } diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModelFactory.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModelFactory.kt new file mode 100644 index 0000000..d8b5caf --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/CircularLetterViewModelFactory.kt @@ -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 create(modelClass: Class): T { + return CircularLetterViewModel(circularRepository) as T + } +} diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModel.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModel.kt index f45115d..ca1dd83 100644 --- a/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModel.kt +++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModel.kt @@ -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> = 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%") } } } diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModelFactory.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModelFactory.kt new file mode 100644 index 0000000..a1881a0 --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/FavouritesViewModelFactory.kt @@ -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 create(modelClass: Class): T { + return FavouritesViewModel(circularRepository) as T + } +} diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt index c0a1b5e..b95bcc5 100644 --- a/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt +++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt @@ -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> = 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%") } } } diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModelFactory.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModelFactory.kt new file mode 100644 index 0000000..29eca4e --- /dev/null +++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModelFactory.kt @@ -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 create(modelClass: Class): T { + return RemindersViewModel(circularRepository) as T + } +} diff --git a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt index 7386339..1563d46 100644 --- a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt +++ b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt @@ -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) { diff --git a/build.gradle b/build.gradle index 99104ee..fd4800a 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { } } 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 "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libs_version" classpath "org.jlleitschuh.gradle:ktlint-gradle:9.4.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b4008fc..5ee166f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Sep 01 12:16:30 CEST 2020 +#Wed Oct 21 19:00:49 CEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME 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