mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 06:17:57 +01:00 
			
		
		
		
	Allow to refresh the entire library info (fixing empty covers after restoring backups). Closes #462
This commit is contained in:
		| @@ -71,18 +71,18 @@ class LibraryUpdateService : Service() { | ||||
|     private val notificationId: Int | ||||
|         get() = Constants.NOTIFICATION_LIBRARY_ID | ||||
|  | ||||
|  | ||||
|     companion object { | ||||
|         /** | ||||
|          * Key for manual library update. | ||||
|          */ | ||||
|         const val UPDATE_IS_MANUAL = "is_manual" | ||||
|  | ||||
|         /** | ||||
|          * Key for category to update. | ||||
|          */ | ||||
|         const val UPDATE_CATEGORY = "category" | ||||
|  | ||||
|         /** | ||||
|          * Key for updating the details instead of the chapters. | ||||
|          */ | ||||
|         const val UPDATE_DETAILS = "details" | ||||
|  | ||||
|         /** | ||||
|          * Returns the status of the service. | ||||
|          * | ||||
| @@ -98,13 +98,13 @@ class LibraryUpdateService : Service() { | ||||
|          * running. | ||||
|          * | ||||
|          * @param context the application context. | ||||
|          * @param isManual whether the update has been manually triggered. | ||||
|          * @param category a specific category to update, or null for global update. | ||||
|          * @param details whether to update the details instead of the list of chapters. | ||||
|          */ | ||||
|         fun start(context: Context, isManual: Boolean = false, category: Category? = null) { | ||||
|         fun start(context: Context, category: Category? = null, details: Boolean = false) { | ||||
|             if (!isRunning(context)) { | ||||
|                 val intent = Intent(context, LibraryUpdateService::class.java).apply { | ||||
|                     putExtra(UPDATE_IS_MANUAL, isManual) | ||||
|                     putExtra(UPDATE_DETAILS, details) | ||||
|                     category?.let { putExtra(UPDATE_CATEGORY, it.id) } | ||||
|                 } | ||||
|                 context.startService(intent) | ||||
| @@ -164,7 +164,16 @@ class LibraryUpdateService : Service() { | ||||
|         subscription?.unsubscribe() | ||||
|  | ||||
|         // Update favorite manga. Destroy service when completed or in case of an error. | ||||
|         subscription = Observable.defer { updateMangaList(getMangaToUpdate(intent)) } | ||||
|         subscription = Observable | ||||
|                 .defer { | ||||
|                     val mangaList = getMangaToUpdate(intent) | ||||
|  | ||||
|                     // Update either chapter list or manga details. | ||||
|                     if (!intent.getBooleanExtra(UPDATE_DETAILS, false)) | ||||
|                         updateChapterList(mangaList) | ||||
|                     else | ||||
|                         updateDetails(mangaList) | ||||
|                 } | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .subscribe({ | ||||
|                 }, { | ||||
| @@ -216,7 +225,7 @@ class LibraryUpdateService : Service() { | ||||
|      * @param mangaToUpdate the list to update | ||||
|      * @return an observable delivering the progress of each update. | ||||
|      */ | ||||
|     fun updateMangaList(mangaToUpdate: List<Manga>): Observable<Manga> { | ||||
|     fun updateChapterList(mangaToUpdate: List<Manga>): Observable<Manga> { | ||||
|         // Initialize the variables holding the progress of the updates. | ||||
|         val count = AtomicInteger(0) | ||||
|         val newUpdates = ArrayList<Manga>() | ||||
| @@ -266,6 +275,41 @@ class LibraryUpdateService : Service() { | ||||
|                 .map { syncChaptersWithSource(db, it, manga, source) } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Method that updates the details of the given list of manga. It's called in a background | ||||
|      * thread, so it's safe to do heavy operations or network calls here. | ||||
|      * For each manga it calls [updateManga] and updates the notification showing the current | ||||
|      * progress. | ||||
|      * | ||||
|      * @param mangaToUpdate the list to update | ||||
|      * @return an observable delivering the progress of each update. | ||||
|      */ | ||||
|     fun updateDetails(mangaToUpdate: List<Manga>): Observable<Manga> { | ||||
|         // Initialize the variables holding the progress of the updates. | ||||
|         val count = AtomicInteger(0) | ||||
|  | ||||
|         val cancelIntent = PendingIntent.getBroadcast(this, 0, | ||||
|                 Intent(this, CancelUpdateReceiver::class.java), 0) | ||||
|  | ||||
|         // Emit each manga and update it sequentially. | ||||
|         return Observable.from(mangaToUpdate) | ||||
|                 // Notify manga that will update. | ||||
|                 .doOnNext { showProgressNotification(it, count.andIncrement, mangaToUpdate.size, cancelIntent) } | ||||
|                 // Update the details of the manga. | ||||
|                 .concatMap { manga -> | ||||
|                     val source = sourceManager.get(manga.source) as? OnlineSource | ||||
|                             ?: return@concatMap Observable.empty<Manga>() | ||||
|  | ||||
|                     source.fetchMangaDetails(manga).doOnNext { networkManga -> | ||||
|                         manga.copyFrom(networkManga) | ||||
|                         db.insertManga(manga).executeAsBlocking() | ||||
|                     } | ||||
|                 } | ||||
|                 .doOnCompleted { | ||||
|                     cancelNotification() | ||||
|                 } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the text that will be displayed in the notification when there are new chapters. | ||||
|      * | ||||
|   | ||||
| @@ -101,7 +101,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att | ||||
|         swipe_refresh.setDistanceToTriggerSync((2 * 64 * resources.displayMetrics.density).toInt()) | ||||
|         swipe_refresh.setOnRefreshListener { | ||||
|             if (!LibraryUpdateService.isRunning(context)) { | ||||
|                 LibraryUpdateService.start(context, true, category) | ||||
|                 LibraryUpdateService.start(context, category) | ||||
|                 context.toast(R.string.updating_category) | ||||
|             } | ||||
|             // It can be a very long operation, so we disable swipe refresh and show a toast. | ||||
|   | ||||
| @@ -241,7 +241,7 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback | ||||
|             } | ||||
|             R.id.action_library_display_mode -> swapDisplayMode() | ||||
|             R.id.action_update_library -> { | ||||
|                 LibraryUpdateService.start(activity, true) | ||||
|                 LibraryUpdateService.start(activity) | ||||
|             } | ||||
|             R.id.action_edit_categories -> { | ||||
|                 val intent = CategoryActivity.newIntent(activity) | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import com.afollestad.materialdialogs.MaterialDialog | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.cache.ChapterCache | ||||
| import eu.kanade.tachiyomi.data.database.DatabaseHelper | ||||
| import eu.kanade.tachiyomi.data.library.LibraryUpdateService | ||||
| import eu.kanade.tachiyomi.data.network.NetworkHelper | ||||
| import eu.kanade.tachiyomi.util.plusAssign | ||||
| import eu.kanade.tachiyomi.util.toast | ||||
| @@ -38,6 +39,8 @@ class SettingsAdvancedFragment : SettingsFragment() { | ||||
|  | ||||
|     private val clearCookies by lazy { findPreference(getString(R.string.pref_clear_cookies_key)) } | ||||
|  | ||||
|     private val refreshMetadata by lazy { findPreference(getString(R.string.pref_refresh_library_metadata_key)) } | ||||
|  | ||||
|     override fun onViewCreated(view: View, savedState: Bundle?) { | ||||
|         super.onViewCreated(view, savedState) | ||||
|  | ||||
| @@ -57,6 +60,11 @@ class SettingsAdvancedFragment : SettingsFragment() { | ||||
|             clearDatabase() | ||||
|             true | ||||
|         } | ||||
|  | ||||
|         refreshMetadata.setOnPreferenceClickListener { | ||||
|             LibraryUpdateService.start(context, details = true) | ||||
|             true | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun clearChapterCache() { | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.widget.preference.LibraryColumnsDialog | ||||
| import eu.kanade.tachiyomi.widget.preference.SimpleDialogPreference | ||||
| import net.xpece.android.support.preference.MultiSelectListPreference | ||||
| import rx.Observable | ||||
| import rx.android.schedulers.AndroidSchedulers | ||||
| import uy.kohesive.injekt.injectLazy | ||||
|  | ||||
| class SettingsGeneralFragment : SettingsFragment(), | ||||
| @@ -76,6 +77,15 @@ class SettingsGeneralFragment : SettingsFragment(), | ||||
|             true | ||||
|         } | ||||
|  | ||||
|         updateRestriction.setOnPreferenceChangeListener { preference, newValue -> | ||||
|             // Post to event looper to allow the preference to be updated. | ||||
|             subscriptions += Observable.fromCallable { | ||||
|                 LibraryUpdateTrigger.setupTask(context) | ||||
|             }.subscribeOn(AndroidSchedulers.mainThread()).subscribe() | ||||
|  | ||||
|             true | ||||
|         } | ||||
|  | ||||
|         val dbCategories = db.getCategories().executeAsBlocking() | ||||
|         categoryUpdate.apply { | ||||
|             entries = dbCategories.map { it.name }.toTypedArray() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user