mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Add an option to update the library automatically after a specified time and an option to update only non completed mangas. Other minor changes.
This commit is contained in:
		| @@ -44,7 +44,7 @@ public final class NetworkHelper { | ||||
|             } catch (Throwable e) { | ||||
|                 return Observable.error(e); | ||||
|             } | ||||
|         }).retry(2); | ||||
|         }).retry(1); | ||||
|     } | ||||
|  | ||||
|     public Observable<String> mapResponseToString(final Response response) { | ||||
| @@ -74,7 +74,7 @@ public final class NetworkHelper { | ||||
|             } catch (Throwable e) { | ||||
|                 return Observable.error(e); | ||||
|             } | ||||
|         }).retry(2); | ||||
|         }).retry(1); | ||||
|     } | ||||
|  | ||||
|     public Observable<Response> getProgressResponse(final String url, final Headers headers, final ProgressListener listener) { | ||||
|   | ||||
| @@ -97,6 +97,10 @@ public class PreferencesHelper { | ||||
|         return rxPrefs.getInteger(getKey(R.string.pref_library_columns_landscape_key), 0); | ||||
|     } | ||||
|  | ||||
|     public boolean updateOnlyNonCompleted() { | ||||
|         return prefs.getBoolean(getKey(R.string.pref_update_only_non_completed_key), false); | ||||
|     } | ||||
|  | ||||
|     public Preference<Integer> imageDecoder() { | ||||
|         return rxPrefs.getInteger(getKey(R.string.pref_image_decoder_key), 0); | ||||
|     } | ||||
| @@ -148,4 +152,9 @@ public class PreferencesHelper { | ||||
|         return rxPrefs.getInteger(getKey(R.string.pref_download_slots_key), 1); | ||||
|     } | ||||
|  | ||||
|     public static int getLibraryUpdateInterval(Context context) { | ||||
|         return PreferenceManager.getDefaultSharedPreferences(context).getInt( | ||||
|                 context.getString(R.string.pref_library_update_interval_key), 0); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,62 @@ | ||||
| package eu.kanade.mangafeed.data.sync; | ||||
|  | ||||
| import android.app.AlarmManager; | ||||
| import android.app.PendingIntent; | ||||
| import android.content.BroadcastReceiver; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.os.SystemClock; | ||||
|  | ||||
| import eu.kanade.mangafeed.data.preference.PreferencesHelper; | ||||
| import timber.log.Timber; | ||||
|  | ||||
| public class LibraryUpdateAlarm extends BroadcastReceiver { | ||||
|  | ||||
|     public static final String LIBRARY_UPDATE_ACTION = "eu.kanade.UPDATE_LIBRARY"; | ||||
|  | ||||
|     public static void startAlarm(Context context) { | ||||
|         startAlarm(context, PreferencesHelper.getLibraryUpdateInterval(context)); | ||||
|     } | ||||
|  | ||||
|     public static void startAlarm(Context context, int intervalInHours) { | ||||
|         stopAlarm(context); | ||||
|         if (intervalInHours == 0) | ||||
|             return; | ||||
|  | ||||
|         int intervalInMillis = intervalInHours * 60 * 60 * 1000; | ||||
|         long nextRun = SystemClock.elapsedRealtime() + intervalInMillis; | ||||
|  | ||||
|         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|         PendingIntent pendingIntent = getPendingIntent(context); | ||||
|         alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, | ||||
|                 nextRun, intervalInMillis, pendingIntent); | ||||
|  | ||||
|         Timber.i("Alarm set. Library will update on " + nextRun); | ||||
|     } | ||||
|  | ||||
|     public static void stopAlarm(Context context) { | ||||
|         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); | ||||
|         PendingIntent pendingIntent = getPendingIntent(context); | ||||
|         alarmManager.cancel(pendingIntent); | ||||
|     } | ||||
|  | ||||
|     private static PendingIntent getPendingIntent(Context context) { | ||||
|         Intent intent = new Intent(context, LibraryUpdateAlarm.class); | ||||
|         intent.setAction(LIBRARY_UPDATE_ACTION); | ||||
|         return PendingIntent.getBroadcast(context, 0, intent, 0); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onReceive(Context context, Intent intent) { | ||||
|         if (intent.getAction() == null) | ||||
|             return; | ||||
|  | ||||
|         if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { | ||||
|             startAlarm(context); | ||||
|         } else if (intent.getAction().equals(LIBRARY_UPDATE_ACTION)) { | ||||
|             LibraryUpdateService.start(context); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -17,6 +17,7 @@ import eu.kanade.mangafeed.BuildConfig; | ||||
| import eu.kanade.mangafeed.R; | ||||
| import eu.kanade.mangafeed.data.database.DatabaseHelper; | ||||
| import eu.kanade.mangafeed.data.database.models.Manga; | ||||
| import eu.kanade.mangafeed.data.preference.PreferencesHelper; | ||||
| import eu.kanade.mangafeed.data.source.SourceManager; | ||||
| import eu.kanade.mangafeed.util.AndroidComponentUtil; | ||||
| import eu.kanade.mangafeed.util.NetworkUtil; | ||||
| @@ -31,16 +32,23 @@ public class LibraryUpdateService extends Service { | ||||
|  | ||||
|     @Inject DatabaseHelper db; | ||||
|     @Inject SourceManager sourceManager; | ||||
|     @Inject PreferencesHelper preferences; | ||||
|  | ||||
|     private Subscription updateSubscription; | ||||
|     private Subscription subscription; | ||||
|  | ||||
|     public static final int UPDATE_NOTIFICATION_ID = 1; | ||||
|  | ||||
|     public static Intent getStartIntent(Context context) { | ||||
|     public static void start(Context context) { | ||||
|         if (!isRunning(context)) { | ||||
|             context.startService(getStartIntent(context)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static Intent getStartIntent(Context context) { | ||||
|         return new Intent(context, LibraryUpdateService.class); | ||||
|     } | ||||
|  | ||||
|     public static boolean isRunning(Context context) { | ||||
|     private static boolean isRunning(Context context) { | ||||
|         return AndroidComponentUtil.isServiceRunning(context, LibraryUpdateService.class); | ||||
|     } | ||||
|  | ||||
| @@ -52,8 +60,10 @@ public class LibraryUpdateService extends Service { | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         if (updateSubscription != null) | ||||
|             updateSubscription.unsubscribe(); | ||||
|         if (subscription != null) | ||||
|             subscription.unsubscribe(); | ||||
|         // Reset the alarm | ||||
|         LibraryUpdateAlarm.startAlarm(this); | ||||
|         super.onDestroy(); | ||||
|     } | ||||
|  | ||||
| @@ -68,44 +78,56 @@ public class LibraryUpdateService extends Service { | ||||
|             return START_NOT_STICKY; | ||||
|         } | ||||
|  | ||||
|         Observable.fromCallable(() -> db.getFavoriteMangas().executeAsBlocking()) | ||||
|         subscription = Observable.fromCallable(() -> db.getFavoriteMangas().executeAsBlocking()) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .subscribe(mangas -> { | ||||
|                     startUpdating(mangas, startId); | ||||
|                 }); | ||||
|                 .flatMap(this::updateLibrary) | ||||
|                 .subscribe(next -> {}, | ||||
|                         error -> { | ||||
|                             NotificationUtil.create(this, UPDATE_NOTIFICATION_ID, | ||||
|                                     getString(R.string.notification_update_error), ""); | ||||
|                             stopSelf(startId); | ||||
|                         }, () -> { | ||||
|                             Timber.i("Library updated"); | ||||
|                             stopSelf(startId); | ||||
|                         }); | ||||
|  | ||||
|         return START_STICKY; | ||||
|     } | ||||
|  | ||||
|     private void startUpdating(final List<Manga> mangas, final int startId) { | ||||
|     private Observable<MangaUpdate> updateLibrary(List<Manga> allLibraryMangas) { | ||||
|         final AtomicInteger count = new AtomicInteger(0); | ||||
|         final List<MangaUpdate> updates = new ArrayList<>(); | ||||
|         final List<Manga> failedUpdates = new ArrayList<>(); | ||||
|  | ||||
|         List<MangaUpdate> updates = new ArrayList<>(); | ||||
|         final List<Manga> mangas = !preferences.updateOnlyNonCompleted() ? allLibraryMangas : | ||||
|             Observable.from(allLibraryMangas) | ||||
|                     .filter(manga -> manga.status != Manga.COMPLETED) | ||||
|                     .toList().toBlocking().single(); | ||||
|  | ||||
|         updateSubscription = Observable.from(mangas) | ||||
|                 .doOnNext(manga -> { | ||||
|                     NotificationUtil.create(this, UPDATE_NOTIFICATION_ID, | ||||
|                             getString(R.string.notification_progress, | ||||
|                                     count.incrementAndGet(), mangas.size()), manga.title); | ||||
|                 }) | ||||
|                 .concatMap(manga -> sourceManager.get(manga.source) | ||||
|                                 .pullChaptersFromNetwork(manga.url) | ||||
|                                 .flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters)) | ||||
|                                 .filter(result -> result.getNumberOfRowsInserted() > 0) | ||||
|                                 .flatMap(result -> Observable.just(new MangaUpdate(manga, result)))) | ||||
|                 .subscribe(update -> { | ||||
|                     updates.add(update); | ||||
|                 }, error -> { | ||||
|                     Timber.e("Error syncing"); | ||||
|                     stopSelf(startId); | ||||
|                 }, () -> { | ||||
|                     NotificationUtil.createBigText(this, UPDATE_NOTIFICATION_ID, | ||||
|                             getString(R.string.notification_completed), getUpdatedMangas(updates)); | ||||
|                     stopSelf(startId); | ||||
|                 }); | ||||
|         return Observable.from(mangas) | ||||
|                 .doOnNext(manga -> NotificationUtil.create(this, UPDATE_NOTIFICATION_ID, | ||||
|                         getString(R.string.notification_update_progress, | ||||
|                                 count.incrementAndGet(), mangas.size()), manga.title)) | ||||
|                 .concatMap(manga -> updateManga(manga) | ||||
|                         .onErrorReturn(error -> { | ||||
|                             failedUpdates.add(manga); | ||||
|                             return new PostResult(0, 0, 0); | ||||
|                         }) | ||||
|                         .filter(result -> result.getNumberOfRowsInserted() > 0) | ||||
|                         .map(result -> new MangaUpdate(manga, result))) | ||||
|                 .doOnNext(updates::add) | ||||
|                 .doOnCompleted(() -> NotificationUtil.createBigText(this, UPDATE_NOTIFICATION_ID, | ||||
|                         getString(R.string.notification_update_completed), | ||||
|                         getUpdatedMangas(updates, failedUpdates))); | ||||
|     } | ||||
|  | ||||
|     private String getUpdatedMangas(List<MangaUpdate> updates) { | ||||
|     private Observable<PostResult> updateManga(Manga manga) { | ||||
|         return sourceManager.get(manga.source) | ||||
|                 .pullChaptersFromNetwork(manga.url) | ||||
|                 .flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters)); | ||||
|     } | ||||
|  | ||||
|     private String getUpdatedMangas(List<MangaUpdate> updates, List<Manga> failedUpdates) { | ||||
|         final StringBuilder result = new StringBuilder(); | ||||
|         if (updates.isEmpty()) { | ||||
|             result.append(getString(R.string.notification_no_new_chapters)).append("\n"); | ||||
| @@ -116,6 +138,13 @@ public class LibraryUpdateService extends Service { | ||||
|                 result.append("\n").append(update.getManga().title); | ||||
|             } | ||||
|         } | ||||
|         if (!failedUpdates.isEmpty()) { | ||||
|             result.append("\n"); | ||||
|             result.append(getString(R.string.notification_manga_update_failed)); | ||||
|             for (Manga manga : failedUpdates) { | ||||
|                 result.append("\n").append(manga.title); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return result.toString(); | ||||
|     } | ||||
|   | ||||
| @@ -105,10 +105,7 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter> | ||||
|     public boolean onOptionsItemSelected(MenuItem item) { | ||||
|         switch (item.getItemId()) { | ||||
|             case R.id.action_refresh: | ||||
|                 if (!LibraryUpdateService.isRunning(getActivity())) { | ||||
|                     Intent intent = LibraryUpdateService.getStartIntent(getActivity()); | ||||
|                     getActivity().startService(intent); | ||||
|                 } | ||||
|                 LibraryUpdateService.start(getActivity()); | ||||
|                 return true; | ||||
|             case R.id.action_edit_categories: | ||||
|                 onEditCategories(); | ||||
|   | ||||
| @@ -7,12 +7,12 @@ import android.view.ViewGroup; | ||||
|  | ||||
| import eu.kanade.mangafeed.R; | ||||
| import eu.kanade.mangafeed.data.preference.PreferencesHelper; | ||||
| import eu.kanade.mangafeed.data.sync.LibraryUpdateAlarm; | ||||
| import eu.kanade.mangafeed.ui.setting.preference.IntListPreference; | ||||
| import eu.kanade.mangafeed.ui.setting.preference.LibraryColumnsDialog; | ||||
|  | ||||
| public class SettingsGeneralFragment extends SettingsNestedFragment { | ||||
|  | ||||
|     private LibraryColumnsDialog columnsDialog; | ||||
|  | ||||
|     public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) { | ||||
|         SettingsNestedFragment fragment = new SettingsGeneralFragment(); | ||||
|         fragment.setArgs(resourcePreference, resourceTitle); | ||||
| @@ -25,11 +25,19 @@ public class SettingsGeneralFragment extends SettingsNestedFragment { | ||||
|  | ||||
|         PreferencesHelper preferences = getSettingsActivity().preferences; | ||||
|  | ||||
|         columnsDialog = (LibraryColumnsDialog) findPreference( | ||||
|         LibraryColumnsDialog columnsDialog = (LibraryColumnsDialog) findPreference( | ||||
|                 getString(R.string.pref_library_columns_dialog_key)); | ||||
|  | ||||
|         columnsDialog.setPreferencesHelper(preferences); | ||||
|  | ||||
|         IntListPreference updateInterval = (IntListPreference) findPreference( | ||||
|                 getString(R.string.pref_library_update_interval_key)); | ||||
|  | ||||
|         updateInterval.setOnPreferenceChangeListener((preference, newValue) -> { | ||||
|             LibraryUpdateAlarm.startAlarm(getActivity(), Integer.parseInt((String) newValue)); | ||||
|             return true; | ||||
|         }); | ||||
|  | ||||
|         return view; | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user