mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2024-11-22 20:36:24 -06:00
Add force sync feature in settings (#643)
This commit is contained in:
parent
3612326628
commit
6a0ce3a58d
@ -154,6 +154,8 @@ dependencies {
|
||||
implementation "androidx.work:work-rxjava2:$work_manager"
|
||||
implementation "androidx.work:work-gcm:$work_manager"
|
||||
|
||||
implementation 'com.github.PaulinaSadowska:RxWorkManagerObservers:1.0.0'
|
||||
|
||||
implementation "androidx.room:room-runtime:$room"
|
||||
implementation "androidx.room:room-rxjava2:$room"
|
||||
implementation "androidx.room:room-ktx:$room"
|
||||
|
@ -5,18 +5,24 @@ import android.os.Build.VERSION_CODES.O
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.BackoffPolicy.EXPONENTIAL
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.Data
|
||||
import androidx.work.ExistingPeriodicWorkPolicy.KEEP
|
||||
import androidx.work.ExistingPeriodicWorkPolicy.REPLACE
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.NetworkType.CONNECTED
|
||||
import androidx.work.NetworkType.UNMETERED
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import com.paulinasadowska.rxworkmanagerobservers.extensions.getWorkInfoByIdObservable
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider.Companion.APP_VERSION_CODE_KEY
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.channels.Channel
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.isHolidays
|
||||
import io.reactivex.Observable
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit.MINUTES
|
||||
@ -42,13 +48,13 @@ class SyncManager @Inject constructor(
|
||||
}
|
||||
|
||||
if (sharedPrefProvider.getLong(APP_VERSION_CODE_KEY, -1L) != appInfo.versionCode.toLong()) {
|
||||
startSyncWorker(true)
|
||||
startPeriodicSyncWorker(true)
|
||||
sharedPrefProvider.putLong(APP_VERSION_CODE_KEY, appInfo.versionCode.toLong(), true)
|
||||
}
|
||||
Timber.i("SyncManager was initialized")
|
||||
}
|
||||
|
||||
fun startSyncWorker(restart: Boolean = false) {
|
||||
fun startPeriodicSyncWorker(restart: Boolean = false) {
|
||||
if (preferencesRepository.isServiceEnabled && !now().isHolidays) {
|
||||
workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
|
||||
PeriodicWorkRequestBuilder<SyncWorker>(preferencesRepository.servicesInterval, MINUTES)
|
||||
@ -61,6 +67,19 @@ class SyncManager @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun startOneTimeSyncWorker(): Observable<WorkInfo> {
|
||||
val work = OneTimeWorkRequestBuilder<SyncWorker>()
|
||||
.setInputData(
|
||||
Data.Builder()
|
||||
.putBoolean("one_time", true)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
|
||||
workManager.enqueueUniqueWork("${SyncWorker::class.java.simpleName}_one_time", ExistingWorkPolicy.REPLACE, work)
|
||||
return workManager.getWorkInfoByIdObservable(work.id)
|
||||
}
|
||||
|
||||
fun stopSyncWorker() {
|
||||
workManager.cancelUniqueWork(SyncWorker::class.java.simpleName)
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package io.github.wulkanowy.services.sync
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.BigTextStyle
|
||||
import androidx.core.app.NotificationCompat.PRIORITY_DEFAULT
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.Data
|
||||
import androidx.work.ListenableWorker
|
||||
import androidx.work.RxWorker
|
||||
import androidx.work.WorkerParameters
|
||||
@ -17,6 +19,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.sdk.exception.FeatureDisabledException
|
||||
import io.github.wulkanowy.services.sync.channels.DebugChannel
|
||||
import io.github.wulkanowy.services.sync.works.Work
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
@ -30,7 +33,8 @@ class SyncWorker @AssistedInject constructor(
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val works: Set<@JvmSuppressWildcards Work>,
|
||||
private val preferencesRepository: PreferencesRepository,
|
||||
private val notificationManager: NotificationManagerCompat
|
||||
private val notificationManager: NotificationManagerCompat,
|
||||
private val appInfo: AppInfo
|
||||
) : RxWorker(appContext, workerParameters) {
|
||||
|
||||
override fun createWork(): Single<Result> {
|
||||
@ -52,8 +56,15 @@ class SyncWorker @AssistedInject constructor(
|
||||
.toSingleDefault(Result.success())
|
||||
.onErrorReturn {
|
||||
Timber.e(it, "There was an error during synchronization")
|
||||
if (it is FeatureDisabledException) Result.success()
|
||||
else Result.retry()
|
||||
when {
|
||||
it is FeatureDisabledException -> Result.success()
|
||||
inputData.getBoolean("one_time", false) -> {
|
||||
Result.failure(Data.Builder()
|
||||
.putString("error", it.toString())
|
||||
.build())
|
||||
}
|
||||
else -> Result.retry()
|
||||
}
|
||||
}
|
||||
.doOnSuccess {
|
||||
if (preferencesRepository.isDebugNotificationEnable) notify(it)
|
||||
@ -64,7 +75,7 @@ class SyncWorker @AssistedInject constructor(
|
||||
private fun notify(result: Result) {
|
||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(applicationContext, DebugChannel.CHANNEL_ID)
|
||||
.setContentTitle("Debug notification")
|
||||
.setSmallIcon(R.drawable.ic_more_settings)
|
||||
.setSmallIcon(R.drawable.ic_stat_push)
|
||||
.setAutoCancel(true)
|
||||
.setColor(applicationContext.getCompatColor(R.color.colorPrimary))
|
||||
.setStyle(BigTextStyle().bigText("${SyncWorker::class.java.simpleName} result: $result"))
|
||||
|
@ -33,7 +33,7 @@ class MainPresenter @Inject constructor(
|
||||
Timber.i("Main view was initialized with $startMenuIndex menu index and $startMenuMoreIndex more index")
|
||||
}
|
||||
|
||||
syncManager.startSyncWorker()
|
||||
syncManager.startPeriodicSyncWorker()
|
||||
analytics.logEvent("app_open", "destination" to initMenu?.name)
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.ui.modules.settings
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.yariksoffice.lingver.Lingver
|
||||
@ -33,11 +34,24 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
|
||||
override val titleStringId get() = R.string.settings_title
|
||||
|
||||
override val syncSuccessString get() = getString(R.string.pref_services_message_sync_success)
|
||||
|
||||
override val syncFailedString get() = getString(R.string.pref_services_message_sync_failed)
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
AndroidSupportInjection.inject(this)
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
findPreference<Preference>(getString(R.string.pref_key_services_force_sync))?.run {
|
||||
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
presenter.onSyncNowClicked()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
presenter.onAttachView(this)
|
||||
@ -61,12 +75,19 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
|
||||
override fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean) {
|
||||
findPreference<Preference>(serviceEnablesKey)?.apply {
|
||||
findPreference<Preference>(serviceEnablesKey)?.run {
|
||||
summary = if (isHolidays) getString(R.string.pref_services_suspended) else ""
|
||||
isEnabled = !isHolidays
|
||||
}
|
||||
}
|
||||
|
||||
override fun setSyncInProgress(inProgress: Boolean) {
|
||||
findPreference<Preference>(getString(R.string.pref_key_services_force_sync))?.run {
|
||||
isEnabled = !inProgress
|
||||
summary = if (inProgress) getString(R.string.pref_services_sync_in_progress) else ""
|
||||
}
|
||||
}
|
||||
|
||||
override fun showError(text: String, error: Throwable) {
|
||||
(activity as? BaseActivity<*>)?.showError(text, error)
|
||||
}
|
||||
@ -87,6 +108,15 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
ErrorDialog.newInstance(error).show(childFragmentManager, error.toString())
|
||||
}
|
||||
|
||||
override fun showForceSyncDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.pref_services_dialog_force_sync_title)
|
||||
.setMessage(R.string.pref_services_dialog_force_sync_summary)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> presenter.onForceSyncDialogSubmit() }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.settings
|
||||
|
||||
import androidx.work.WorkInfo
|
||||
import com.chuckerteam.chucker.api.ChuckerCollector
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
@ -29,6 +30,7 @@ class SettingsPresenter @Inject constructor(
|
||||
super.onAttachView(view)
|
||||
Timber.i("Settings view was initialized")
|
||||
view.setServicesSuspended(preferencesRepository.serviceEnableKey, now().isHolidays)
|
||||
view.initView()
|
||||
}
|
||||
|
||||
fun onSharedPreferenceChanged(key: String) {
|
||||
@ -36,8 +38,8 @@ class SettingsPresenter @Inject constructor(
|
||||
|
||||
with(preferencesRepository) {
|
||||
when (key) {
|
||||
serviceEnableKey -> with(syncManager) { if (isServiceEnabled) startSyncWorker() else stopSyncWorker() }
|
||||
servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startSyncWorker(true)
|
||||
serviceEnableKey -> with(syncManager) { if (isServiceEnabled) startPeriodicSyncWorker() else stopSyncWorker() }
|
||||
servicesIntervalKey, servicesOnlyWifiKey -> syncManager.startPeriodicSyncWorker(true)
|
||||
isDebugNotificationEnableKey -> chuckerCollector.showNotification = isDebugNotificationEnable
|
||||
appThemeKey -> view?.recreateView()
|
||||
appLanguageKey -> view?.run {
|
||||
@ -49,4 +51,25 @@ class SettingsPresenter @Inject constructor(
|
||||
}
|
||||
analytics.logEvent("setting_changed", "name" to key)
|
||||
}
|
||||
|
||||
fun onSyncNowClicked() {
|
||||
view?.showForceSyncDialog()
|
||||
}
|
||||
|
||||
fun onForceSyncDialogSubmit() {
|
||||
view?.run {
|
||||
Timber.i("Setting sync now started")
|
||||
analytics.logEvent("sync_now_started")
|
||||
disposable.add(syncManager.startOneTimeSyncWorker()
|
||||
.doOnSubscribe { setSyncInProgress(true) }
|
||||
.doFinally { setSyncInProgress(false) }
|
||||
.subscribe({ workInfo ->
|
||||
if (workInfo.state == WorkInfo.State.SUCCEEDED) showMessage(syncSuccessString)
|
||||
else if (workInfo.state == WorkInfo.State.FAILED) showError(syncFailedString, Throwable(workInfo.outputData.getString("error")))
|
||||
}, {
|
||||
Timber.e("Sync now failed")
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,19 @@ import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface SettingsView : BaseView {
|
||||
|
||||
val syncSuccessString: String
|
||||
|
||||
val syncFailedString: String
|
||||
|
||||
fun initView()
|
||||
|
||||
fun recreateView()
|
||||
|
||||
fun updateLanguage(langCode: String)
|
||||
|
||||
fun setServicesSuspended(serviceEnablesKey: String, isHolidays: Boolean)
|
||||
|
||||
fun setSyncInProgress(inProgress: Boolean)
|
||||
|
||||
fun showForceSyncDialog()
|
||||
}
|
||||
|
@ -375,6 +375,15 @@
|
||||
<string name="pref_services_suspended">Zawieszona na wakacjach</string>
|
||||
<string name="pref_services_interval">Interwał aktualizacji</string>
|
||||
<string name="pref_services_wifi">Tylko WiFi</string>
|
||||
<string name="pref_services_force_sync">Synchronizuj teraz</string>
|
||||
<string name="pref_services_message_sync_success">Zsynchronizowano!</string>
|
||||
<string name="pref_services_message_sync_failed">Synchronizacja nie powiodła się</string>
|
||||
<string name="pref_services_sync_in_progress">Synchronizacja w trakcie</string>
|
||||
<string name="pref_services_dialog_force_sync_title">Synchronizacja</string>
|
||||
<string name="pref_services_dialog_force_sync_summary">
|
||||
Ręczna synchronizacja nie odświeża widoków w aplikacji.
|
||||
\nAby zobaczyć zsynchronizowane informacje uruchom ponownie aplikację po zsynchronizowaniu.
|
||||
</string>
|
||||
|
||||
<string name="pref_other_header">Inne</string>
|
||||
<string name="pref_other_grade_modifier_plus">Wartość plusa</string>
|
||||
|
@ -11,6 +11,7 @@
|
||||
<string name="pref_key_services_enable">services_enable</string>
|
||||
<string name="pref_key_services_interval">services_interval</string>
|
||||
<string name="pref_key_services_wifi_only">services_disable_wifi_only</string>
|
||||
<string name="pref_key_services_force_sync">services_force_sync</string>
|
||||
<string name="pref_key_notifications_enable">notifications_enable</string>
|
||||
<string name="pref_key_notification_debug">notification_debug</string>
|
||||
<string name="pref_key_grade_modifier_plus">grade_modifier_plus</string>
|
||||
|
@ -360,6 +360,15 @@
|
||||
<string name="pref_services_suspended">Suspended on holidays</string>
|
||||
<string name="pref_services_interval">Updates interval</string>
|
||||
<string name="pref_services_wifi">Wi-Fi only</string>
|
||||
<string name="pref_services_force_sync">Sync now</string>
|
||||
<string name="pref_services_message_sync_success">Synced!</string>
|
||||
<string name="pref_services_message_sync_failed">Sync failed</string>
|
||||
<string name="pref_services_sync_in_progress">Sync in progress</string>
|
||||
<string name="pref_services_dialog_force_sync_title">Synchronization</string>
|
||||
<string name="pref_services_dialog_force_sync_summary">
|
||||
Manual sync doesn\'t refresh app views.
|
||||
\nTo see the synced data relaunch the app after syncing.
|
||||
</string>
|
||||
|
||||
<string name="pref_other_header">Other</string>
|
||||
<string name="pref_other_grade_modifier_plus">Value of the plus</string>
|
||||
|
@ -77,6 +77,10 @@
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="@string/pref_key_services_wifi_only"
|
||||
app:title="@string/pref_services_wifi" />
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
app:title="@string/pref_services_force_sync"
|
||||
app:key="@string/pref_key_services_force_sync" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
app:iconSpaceReserved="false"
|
||||
|
Loading…
Reference in New Issue
Block a user