mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-22 23:21:49 +01:00
Select categories for global update
This commit is contained in:
parent
7c3cd10696
commit
91829b0e7d
@ -59,6 +59,15 @@
|
|||||||
<service android:name=".data.mangasync.UpdateMangaSyncService"
|
<service android:name=".data.mangasync.UpdateMangaSyncService"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".data.library.LibraryUpdateTrigger"
|
||||||
|
android:exported="true"
|
||||||
|
android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".data.updater.UpdateCheckerService"
|
android:name=".data.updater.UpdateCheckerService"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
@ -73,34 +82,10 @@
|
|||||||
|
|
||||||
<receiver android:name=".data.updater.UpdateNotificationReceiver"/>
|
<receiver android:name=".data.updater.UpdateNotificationReceiver"/>
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".data.library.LibraryUpdateService$SyncOnConnectionAvailable"
|
|
||||||
android:enabled="false">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".data.library.LibraryUpdateService$SyncOnPowerConnected"
|
|
||||||
android:enabled="false">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".data.library.LibraryUpdateService$CancelUpdateReceiver">
|
android:name=".data.library.LibraryUpdateService$CancelUpdateReceiver">
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".data.library.LibraryUpdateAlarm">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
|
||||||
<action android:name="eu.kanade.UPDATE_LIBRARY" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="eu.kanade.tachiyomi.data.glide.AppGlideModule"
|
android:name="eu.kanade.tachiyomi.data.glide.AppGlideModule"
|
||||||
android:value="GlideModule" />
|
android:value="GlideModule" />
|
||||||
|
@ -8,8 +8,6 @@ import android.content.Intent
|
|||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.support.v4.app.NotificationCompat
|
import android.support.v4.app.NotificationCompat
|
||||||
import com.github.pwittchen.reactivenetwork.library.ConnectivityStatus
|
|
||||||
import com.github.pwittchen.reactivenetwork.library.ReactiveNetwork
|
|
||||||
import eu.kanade.tachiyomi.Constants
|
import eu.kanade.tachiyomi.Constants
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
@ -17,10 +15,14 @@ import eu.kanade.tachiyomi.data.database.models.Category
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.source.SourceManager
|
import eu.kanade.tachiyomi.data.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.data.source.online.OnlineSource
|
import eu.kanade.tachiyomi.data.source.online.OnlineSource
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.util.*
|
import eu.kanade.tachiyomi.util.AndroidComponentUtil
|
||||||
|
import eu.kanade.tachiyomi.util.notification
|
||||||
|
import eu.kanade.tachiyomi.util.notificationManager
|
||||||
|
import eu.kanade.tachiyomi.util.syncChaptersWithSource
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
@ -97,7 +99,7 @@ class LibraryUpdateService : Service() {
|
|||||||
*
|
*
|
||||||
* @param context the application context.
|
* @param context the application context.
|
||||||
* @param isManual whether the update has been manually triggered.
|
* @param isManual whether the update has been manually triggered.
|
||||||
* @param category a specific category to update, or null for all in the library.
|
* @param category a specific category to update, or null for global update.
|
||||||
*/
|
*/
|
||||||
fun start(context: Context, isManual: Boolean = false, category: Category? = null) {
|
fun start(context: Context, isManual: Boolean = false, category: Category? = null) {
|
||||||
if (!isRunning(context)) {
|
if (!isRunning(context)) {
|
||||||
@ -156,45 +158,7 @@ class LibraryUpdateService : Service() {
|
|||||||
* @return the start value of the command.
|
* @return the start value of the command.
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
if (intent == null) return Service.START_NOT_STICKY
|
||||||
// Get connectivity status
|
|
||||||
val connection = ReactiveNetwork().getConnectivityStatus(this, true)
|
|
||||||
|
|
||||||
// Get library update restrictions
|
|
||||||
val restrictions = preferences.libraryUpdateRestriction()
|
|
||||||
|
|
||||||
// Check if users updates library manual
|
|
||||||
val isManualUpdate = intent?.getBooleanExtra(UPDATE_IS_MANUAL, false) ?: false
|
|
||||||
|
|
||||||
// Whether to cancel the update.
|
|
||||||
var cancelUpdate = false
|
|
||||||
|
|
||||||
// Check if device has internet connection
|
|
||||||
// Check if device has wifi connection if only wifi is enabled
|
|
||||||
if (connection == ConnectivityStatus.OFFLINE || (!isManualUpdate && "wifi" in restrictions
|
|
||||||
&& connection != ConnectivityStatus.WIFI_CONNECTED_HAS_INTERNET)) {
|
|
||||||
|
|
||||||
if (isManualUpdate) {
|
|
||||||
toast(R.string.notification_no_connection_title)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable library update when connection available
|
|
||||||
AndroidComponentUtil.toggleComponent(this, SyncOnConnectionAvailable::class.java, true)
|
|
||||||
cancelUpdate = true
|
|
||||||
}
|
|
||||||
if (!isManualUpdate && "ac" in restrictions && !DeviceUtil.isPowerConnected(this)) {
|
|
||||||
AndroidComponentUtil.toggleComponent(this, SyncOnPowerConnected::class.java, true)
|
|
||||||
cancelUpdate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancelUpdate) {
|
|
||||||
stopSelf(startId)
|
|
||||||
return Service.START_NOT_STICKY
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop enabled components.
|
|
||||||
AndroidComponentUtil.toggleComponent(this, SyncOnConnectionAvailable::class.java, false)
|
|
||||||
AndroidComponentUtil.toggleComponent(this, SyncOnPowerConnected::class.java, false)
|
|
||||||
|
|
||||||
// Unsubscribe from any previous subscription if needed.
|
// Unsubscribe from any previous subscription if needed.
|
||||||
subscription?.unsubscribe()
|
subscription?.unsubscribe()
|
||||||
@ -202,15 +166,17 @@ class LibraryUpdateService : Service() {
|
|||||||
// Update favorite manga. Destroy service when completed or in case of an error.
|
// Update favorite manga. Destroy service when completed or in case of an error.
|
||||||
subscription = Observable.defer { updateMangaList(getMangaToUpdate(intent)) }
|
subscription = Observable.defer { updateMangaList(getMangaToUpdate(intent)) }
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe({},
|
.subscribe({
|
||||||
{
|
}, {
|
||||||
showNotification(getString(R.string.notification_update_error), "")
|
showNotification(getString(R.string.notification_update_error), "")
|
||||||
stopSelf(startId)
|
LibraryUpdateTrigger.setupTask(this)
|
||||||
}, {
|
stopSelf(startId)
|
||||||
|
}, {
|
||||||
|
LibraryUpdateTrigger.setupTask(this)
|
||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
})
|
})
|
||||||
|
|
||||||
return Service.START_STICKY
|
return Service.START_REDELIVER_INTENT
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -219,19 +185,26 @@ class LibraryUpdateService : Service() {
|
|||||||
* @param intent the update intent.
|
* @param intent the update intent.
|
||||||
* @return a list of manga to update
|
* @return a list of manga to update
|
||||||
*/
|
*/
|
||||||
fun getMangaToUpdate(intent: Intent?): List<Manga> {
|
fun getMangaToUpdate(intent: Intent): List<Manga> {
|
||||||
val categoryId = intent?.getIntExtra(UPDATE_CATEGORY, -1) ?: -1
|
val categoryId = intent.getIntExtra(UPDATE_CATEGORY, -1)
|
||||||
|
|
||||||
var toUpdate = if (categoryId != -1)
|
var listToUpdate = if (categoryId != -1)
|
||||||
db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId }
|
db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId }
|
||||||
else
|
else {
|
||||||
db.getFavoriteMangas().executeAsBlocking()
|
val categoriesToUpdate = preferences.libraryUpdateCategories().getOrDefault().map { it.toInt() }
|
||||||
|
if (categoriesToUpdate.isNotEmpty())
|
||||||
if (preferences.updateOnlyNonCompleted()) {
|
db.getLibraryMangas().executeAsBlocking()
|
||||||
toUpdate = toUpdate.filter { it.status != Manga.COMPLETED }
|
.filter { it.category in categoriesToUpdate }
|
||||||
|
.distinctBy { it.id }
|
||||||
|
else
|
||||||
|
db.getFavoriteMangas().executeAsBlocking().distinctBy { it.id }
|
||||||
}
|
}
|
||||||
|
|
||||||
return toUpdate
|
if (preferences.updateOnlyNonCompleted()) {
|
||||||
|
listToUpdate = listToUpdate.filter { it.status != Manga.COMPLETED }
|
||||||
|
}
|
||||||
|
|
||||||
|
return listToUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -410,41 +383,6 @@ class LibraryUpdateService : Service() {
|
|||||||
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that triggers the library to update when a connection is available. It receives
|
|
||||||
* network changes.
|
|
||||||
*/
|
|
||||||
class SyncOnConnectionAvailable : BroadcastReceiver() {
|
|
||||||
/**
|
|
||||||
* Method called when a network change occurs.
|
|
||||||
*
|
|
||||||
* @param context the application context.
|
|
||||||
* @param intent the intent received.
|
|
||||||
*/
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
if (DeviceUtil.isNetworkConnected(context)) {
|
|
||||||
AndroidComponentUtil.toggleComponent(context, this.javaClass, false)
|
|
||||||
start(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that triggers the library to update when connected to power.
|
|
||||||
*/
|
|
||||||
class SyncOnPowerConnected: BroadcastReceiver() {
|
|
||||||
/**
|
|
||||||
* Method called when AC is connected.
|
|
||||||
*
|
|
||||||
* @param context the application context.
|
|
||||||
* @param intent the intent received.
|
|
||||||
*/
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
AndroidComponentUtil.toggleComponent(context, this.javaClass, false)
|
|
||||||
start(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that stops updating the library.
|
* Class that stops updating the library.
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package eu.kanade.tachiyomi.data.library
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.google.android.gms.gcm.*
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
class LibraryUpdateTrigger : GcmTaskService() {
|
||||||
|
|
||||||
|
override fun onInitializeTasks() {
|
||||||
|
setupTask(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRunTask(params: TaskParams): Int {
|
||||||
|
LibraryUpdateService.start(this)
|
||||||
|
return GcmNetworkManager.RESULT_SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun setupTask(context: Context) {
|
||||||
|
val preferences = Injekt.get<PreferencesHelper>()
|
||||||
|
val interval = preferences.libraryUpdateInterval().getOrDefault()
|
||||||
|
if (interval > 0) {
|
||||||
|
val restrictions = preferences.libraryUpdateRestriction()
|
||||||
|
val acRestriction = "ac" in restrictions
|
||||||
|
val wifiRestriction = if ("wifi" in restrictions)
|
||||||
|
Task.NETWORK_STATE_UNMETERED
|
||||||
|
else
|
||||||
|
Task.NETWORK_STATE_ANY
|
||||||
|
|
||||||
|
val task = PeriodicTask.Builder()
|
||||||
|
.setService(LibraryUpdateTrigger::class.java)
|
||||||
|
.setTag("Library periodic update")
|
||||||
|
.setPeriod(interval * 60 * 60L)
|
||||||
|
.setFlex(5 * 60)
|
||||||
|
.setRequiredNetwork(wifiRestriction)
|
||||||
|
.setRequiresCharging(acRestriction)
|
||||||
|
.setUpdateCurrent(true)
|
||||||
|
.setPersisted(true)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
GcmNetworkManager.getInstance(context).schedule(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelTask(context: Context) {
|
||||||
|
GcmNetworkManager.getInstance(context).cancelAllTasks(LibraryUpdateTrigger::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -74,6 +74,8 @@ class PreferenceKeys(context: Context) {
|
|||||||
|
|
||||||
val libraryUpdateRestriction = context.getString(R.string.pref_library_update_restriction_key)
|
val libraryUpdateRestriction = context.getString(R.string.pref_library_update_restriction_key)
|
||||||
|
|
||||||
|
val libraryUpdateCategories = context.getString(R.string.pref_library_update_categories_key)
|
||||||
|
|
||||||
val filterDownloaded = context.getString(R.string.pref_filter_downloaded_key)
|
val filterDownloaded = context.getString(R.string.pref_filter_downloaded_key)
|
||||||
|
|
||||||
val filterUnread = context.getString(R.string.pref_filter_unread_key)
|
val filterUnread = context.getString(R.string.pref_filter_unread_key)
|
||||||
|
@ -124,6 +124,8 @@ class PreferencesHelper(context: Context) {
|
|||||||
|
|
||||||
fun libraryUpdateRestriction() = prefs.getStringSet(keys.libraryUpdateRestriction, emptySet())
|
fun libraryUpdateRestriction() = prefs.getStringSet(keys.libraryUpdateRestriction, emptySet())
|
||||||
|
|
||||||
|
fun libraryUpdateCategories() = rxPrefs.getStringSet(keys.libraryUpdateCategories, emptySet())
|
||||||
|
|
||||||
fun libraryAsList() = rxPrefs.getBoolean(keys.libraryAsList, false)
|
fun libraryAsList() = rxPrefs.getBoolean(keys.libraryAsList, false)
|
||||||
|
|
||||||
fun filterDownloaded() = rxPrefs.getBoolean(keys.filterDownloaded, false)
|
fun filterDownloaded() = rxPrefs.getBoolean(keys.filterDownloaded, false)
|
||||||
|
@ -6,7 +6,8 @@ import android.support.v7.preference.PreferenceFragmentCompat
|
|||||||
import android.support.v7.preference.XpPreferenceFragment
|
import android.support.v7.preference.XpPreferenceFragment
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateAlarm
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateTrigger
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.util.plusAssign
|
import eu.kanade.tachiyomi.util.plusAssign
|
||||||
import eu.kanade.tachiyomi.widget.preference.IntListPreference
|
import eu.kanade.tachiyomi.widget.preference.IntListPreference
|
||||||
@ -14,6 +15,7 @@ import eu.kanade.tachiyomi.widget.preference.LibraryColumnsDialog
|
|||||||
import eu.kanade.tachiyomi.widget.preference.SimpleDialogPreference
|
import eu.kanade.tachiyomi.widget.preference.SimpleDialogPreference
|
||||||
import net.xpece.android.support.preference.MultiSelectListPreference
|
import net.xpece.android.support.preference.MultiSelectListPreference
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class SettingsGeneralFragment : SettingsFragment(),
|
class SettingsGeneralFragment : SettingsFragment(),
|
||||||
@ -30,6 +32,8 @@ class SettingsGeneralFragment : SettingsFragment(),
|
|||||||
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
private val db: DatabaseHelper by injectLazy()
|
||||||
|
|
||||||
|
|
||||||
val columnsPreference by lazy {
|
val columnsPreference by lazy {
|
||||||
findPreference(getString(R.string.pref_library_columns_dialog_key)) as SimpleDialogPreference
|
findPreference(getString(R.string.pref_library_columns_dialog_key)) as SimpleDialogPreference
|
||||||
@ -47,6 +51,10 @@ class SettingsGeneralFragment : SettingsFragment(),
|
|||||||
findPreference(getString(R.string.pref_theme_key)) as IntListPreference
|
findPreference(getString(R.string.pref_theme_key)) as IntListPreference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val categoryUpdate by lazy {
|
||||||
|
findPreference(getString(R.string.pref_library_update_categories_key)) as MultiSelectListPreference
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedState: Bundle?) {
|
override fun onViewCreated(view: View, savedState: Bundle?) {
|
||||||
super.onViewCreated(view, savedState)
|
super.onViewCreated(view, savedState)
|
||||||
|
|
||||||
@ -60,10 +68,30 @@ class SettingsGeneralFragment : SettingsFragment(),
|
|||||||
.subscribe { updateColumnsSummary(it.first, it.second) }
|
.subscribe { updateColumnsSummary(it.first, it.second) }
|
||||||
|
|
||||||
updateInterval.setOnPreferenceChangeListener { preference, newValue ->
|
updateInterval.setOnPreferenceChangeListener { preference, newValue ->
|
||||||
LibraryUpdateAlarm.startAlarm(activity, (newValue as String).toInt())
|
val enabled = (newValue as String).toInt() > 0
|
||||||
|
if (enabled)
|
||||||
|
LibraryUpdateTrigger.setupTask(context)
|
||||||
|
else
|
||||||
|
LibraryUpdateTrigger.cancelTask(context)
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val dbCategories = db.getCategories().executeAsBlocking()
|
||||||
|
categoryUpdate.apply {
|
||||||
|
entries = dbCategories.map { it.name }.toTypedArray()
|
||||||
|
entryValues = dbCategories.map { it.id.toString() }.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriptions += preferences.libraryUpdateCategories().asObservable()
|
||||||
|
.subscribe {
|
||||||
|
Timber.e(it.joinToString())
|
||||||
|
categoryUpdate.summary = it
|
||||||
|
.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
|
||||||
|
.sortedBy { it.order }
|
||||||
|
.joinToString { it.name }
|
||||||
|
}
|
||||||
|
|
||||||
themePreference.setOnPreferenceChangeListener { preference, newValue ->
|
themePreference.setOnPreferenceChangeListener { preference, newValue ->
|
||||||
(activity as SettingsActivity).parentFlags = SettingsActivity.FLAG_THEME_CHANGED
|
(activity as SettingsActivity).parentFlags = SettingsActivity.FLAG_THEME_CHANGED
|
||||||
activity.recreate()
|
activity.recreate()
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
<string name="pref_library_columns_portrait_key">pref_library_columns_portrait_key</string>
|
<string name="pref_library_columns_portrait_key">pref_library_columns_portrait_key</string>
|
||||||
<string name="pref_library_columns_landscape_key">pref_library_columns_landscape_key</string>
|
<string name="pref_library_columns_landscape_key">pref_library_columns_landscape_key</string>
|
||||||
<string name="pref_library_update_interval_key">pref_library_update_interval_key</string>
|
<string name="pref_library_update_interval_key">pref_library_update_interval_key</string>
|
||||||
|
<string name="pref_library_update_categories_key">library_update_categories</string>
|
||||||
<string name="pref_update_only_non_completed_key">pref_update_only_non_completed_key</string>
|
<string name="pref_update_only_non_completed_key">pref_update_only_non_completed_key</string>
|
||||||
<string name="pref_auto_update_manga_sync_key">pref_auto_update_manga_sync_key</string>
|
<string name="pref_auto_update_manga_sync_key">pref_auto_update_manga_sync_key</string>
|
||||||
<string name="pref_ask_update_manga_sync_key">pref_ask_update_manga_sync_key</string>
|
<string name="pref_ask_update_manga_sync_key">pref_ask_update_manga_sync_key</string>
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
<string name="update_12hour">Every 12 hours</string>
|
<string name="update_12hour">Every 12 hours</string>
|
||||||
<string name="update_24hour">Daily</string>
|
<string name="update_24hour">Daily</string>
|
||||||
<string name="update_48hour">Every 2 days</string>
|
<string name="update_48hour">Every 2 days</string>
|
||||||
|
<string name="pref_library_update_categories">Categories to include in global update</string>
|
||||||
<string name="pref_library_update_restriction">Library update restrictions</string>
|
<string name="pref_library_update_restriction">Library update restrictions</string>
|
||||||
<string name="pref_library_update_restriction_summary">Update only when the conditions are met</string>
|
<string name="pref_library_update_restriction_summary">Update only when the conditions are met</string>
|
||||||
<string name="wifi">Wi-Fi</string>
|
<string name="wifi">Wi-Fi</string>
|
||||||
|
@ -36,6 +36,10 @@
|
|||||||
android:summary="%s"
|
android:summary="%s"
|
||||||
android:title="@string/pref_library_update_interval"/>
|
android:title="@string/pref_library_update_interval"/>
|
||||||
|
|
||||||
|
<MultiSelectListPreference
|
||||||
|
android:key="@string/pref_library_update_categories_key"
|
||||||
|
android:title="@string/pref_library_update_categories"/>
|
||||||
|
|
||||||
<MultiSelectListPreference
|
<MultiSelectListPreference
|
||||||
android:entries="@array/library_update_restrictions"
|
android:entries="@array/library_update_restrictions"
|
||||||
android:entryValues="@array/library_update_restrictions_values"
|
android:entryValues="@array/library_update_restrictions_values"
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.library
|
|
||||||
|
|
||||||
import android.app.AlarmManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.SystemClock
|
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
|
||||||
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.mockito.Mockito.spy
|
|
||||||
import org.robolectric.Shadows.shadowOf
|
|
||||||
import org.robolectric.annotation.Config
|
|
||||||
import org.robolectric.shadows.ShadowAlarmManager
|
|
||||||
import org.robolectric.shadows.ShadowApplication
|
|
||||||
|
|
||||||
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
|
|
||||||
@RunWith(CustomRobolectricGradleTestRunner::class)
|
|
||||||
class LibraryUpdateAlarmTest {
|
|
||||||
|
|
||||||
lateinit var app: ShadowApplication
|
|
||||||
lateinit var context: Context
|
|
||||||
lateinit var alarmManager: ShadowAlarmManager
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
app = ShadowApplication.getInstance()
|
|
||||||
context = spy(app.applicationContext)
|
|
||||||
|
|
||||||
alarmManager = shadowOf(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testLibraryIntentHandling() {
|
|
||||||
val intent = Intent(LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION)
|
|
||||||
assertThat(app.hasReceiverForIntent(intent)).isTrue()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testAlarmIsNotStarted() {
|
|
||||||
assertThat(alarmManager.nextScheduledAlarm).isNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testAlarmIsNotStartedWhenBootReceivedAndSettingZero() {
|
|
||||||
val alarm = LibraryUpdateAlarm()
|
|
||||||
alarm.onReceive(context, Intent(Intent.ACTION_BOOT_COMPLETED))
|
|
||||||
|
|
||||||
assertThat(alarmManager.nextScheduledAlarm).isNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testAlarmIsStartedWhenBootReceivedAndSettingNotZero() {
|
|
||||||
val prefs = PreferencesHelper(context)
|
|
||||||
prefs.libraryUpdateInterval().set(1)
|
|
||||||
|
|
||||||
val alarm = LibraryUpdateAlarm()
|
|
||||||
alarm.onReceive(context, Intent(Intent.ACTION_BOOT_COMPLETED))
|
|
||||||
|
|
||||||
assertThat(alarmManager.nextScheduledAlarm).isNotNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testOnlyOneAlarmExists() {
|
|
||||||
val prefs = PreferencesHelper(context)
|
|
||||||
prefs.libraryUpdateInterval().set(1)
|
|
||||||
|
|
||||||
LibraryUpdateAlarm.startAlarm(context)
|
|
||||||
LibraryUpdateAlarm.startAlarm(context)
|
|
||||||
LibraryUpdateAlarm.startAlarm(context)
|
|
||||||
|
|
||||||
assertThat(alarmManager.scheduledAlarms).hasSize(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testLibraryWillBeUpdatedWhenAlarmFired() {
|
|
||||||
val prefs = PreferencesHelper(context)
|
|
||||||
prefs.libraryUpdateInterval().set(1)
|
|
||||||
|
|
||||||
val expectedIntent = Intent(context, LibraryUpdateAlarm::class.java)
|
|
||||||
expectedIntent.action = LibraryUpdateAlarm.LIBRARY_UPDATE_ACTION
|
|
||||||
|
|
||||||
LibraryUpdateAlarm.startAlarm(context)
|
|
||||||
|
|
||||||
val scheduledAlarm = alarmManager.nextScheduledAlarm
|
|
||||||
val pendingIntent = shadowOf(scheduledAlarm.operation)
|
|
||||||
assertThat(pendingIntent.isBroadcastIntent).isTrue()
|
|
||||||
assertThat(pendingIntent.savedIntents).hasSize(1)
|
|
||||||
assertThat(expectedIntent.component).isEqualTo(pendingIntent.savedIntents[0].component)
|
|
||||||
assertThat(expectedIntent.action).isEqualTo(pendingIntent.savedIntents[0].action)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testReceiverDoesntReactToNullActions() {
|
|
||||||
val prefs = PreferencesHelper(context)
|
|
||||||
prefs.libraryUpdateInterval().set(1)
|
|
||||||
|
|
||||||
val intent = Intent(context, LibraryUpdateService::class.java)
|
|
||||||
|
|
||||||
val alarm = LibraryUpdateAlarm()
|
|
||||||
alarm.onReceive(context, Intent())
|
|
||||||
|
|
||||||
assertThat(app.nextStartedService).isNotEqualTo(intent)
|
|
||||||
assertThat(alarmManager.scheduledAlarms).hasSize(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testAlarmFiresCloseToDesiredTime() {
|
|
||||||
val hours = 2
|
|
||||||
LibraryUpdateAlarm.startAlarm(context, hours)
|
|
||||||
|
|
||||||
val shouldRunAt = SystemClock.elapsedRealtime() + hours * 60 * 60 * 1000
|
|
||||||
|
|
||||||
// Margin error of 3 seconds
|
|
||||||
assertThat(alarmManager.nextScheduledAlarm.triggerAtTime)
|
|
||||||
.isGreaterThan(shouldRunAt - 3000)
|
|
||||||
.isLessThan(shouldRunAt + 3000)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.library
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
|
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
|
||||||
@ -93,7 +94,8 @@ class LibraryUpdateServiceTest {
|
|||||||
`when`(source.fetchChapterList(favManga[1])).thenReturn(Observable.error<List<Chapter>>(Exception()))
|
`when`(source.fetchChapterList(favManga[1])).thenReturn(Observable.error<List<Chapter>>(Exception()))
|
||||||
`when`(source.fetchChapterList(favManga[2])).thenReturn(Observable.just(chapters3))
|
`when`(source.fetchChapterList(favManga[2])).thenReturn(Observable.just(chapters3))
|
||||||
|
|
||||||
service.updateMangaList(service.getMangaToUpdate(null)).subscribe()
|
val intent = Intent()
|
||||||
|
service.updateMangaList(service.getMangaToUpdate(intent)).subscribe()
|
||||||
|
|
||||||
// There are 3 network attempts and 2 insertions (1 request failed)
|
// There are 3 network attempts and 2 insertions (1 request failed)
|
||||||
assertThat(service.db.getChapters(favManga[0]).executeAsBlocking()).hasSize(2)
|
assertThat(service.db.getChapters(favManga[0]).executeAsBlocking()).hasSize(2)
|
||||||
|
Loading…
Reference in New Issue
Block a user