mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Rewrite the chapter insertion method. Create a wakelock until the library updates. Move custom preferences to widget package.
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| package eu.kanade.mangafeed.data.database; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.util.Pair; | ||||
|  | ||||
| import com.pushtorefresh.storio.Queries; | ||||
| import com.pushtorefresh.storio.sqlite.StorIOSQLite; | ||||
| @@ -12,11 +13,11 @@ import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects; | ||||
| import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetObject; | ||||
| import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutCollectionOfObjects; | ||||
| import com.pushtorefresh.storio.sqlite.operations.put.PreparedPutObject; | ||||
| import com.pushtorefresh.storio.sqlite.operations.put.PutResults; | ||||
| import com.pushtorefresh.storio.sqlite.queries.DeleteQuery; | ||||
| import com.pushtorefresh.storio.sqlite.queries.Query; | ||||
| import com.pushtorefresh.storio.sqlite.queries.RawQuery; | ||||
|  | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| import eu.kanade.mangafeed.data.database.models.Category; | ||||
| @@ -37,7 +38,6 @@ import eu.kanade.mangafeed.data.database.tables.MangaSyncTable; | ||||
| import eu.kanade.mangafeed.data.database.tables.MangaTable; | ||||
| import eu.kanade.mangafeed.data.mangasync.base.MangaSyncService; | ||||
| import eu.kanade.mangafeed.util.ChapterRecognition; | ||||
| import eu.kanade.mangafeed.util.PostResult; | ||||
| import rx.Observable; | ||||
|  | ||||
| public class DatabaseHelper { | ||||
| @@ -246,37 +246,46 @@ public class DatabaseHelper { | ||||
|     } | ||||
|  | ||||
|     // Add new chapters or delete if the source deletes them | ||||
|     public Observable<PostResult> insertOrRemoveChapters(Manga manga, List<Chapter> chapters) { | ||||
|         for (Chapter chapter : chapters) { | ||||
|             chapter.manga_id = manga.id; | ||||
|         } | ||||
|     public Observable<Pair<Integer, Integer>> insertOrRemoveChapters(Manga manga, List<Chapter> sourceChapters) { | ||||
|         List<Chapter> dbChapters = getChapters(manga).executeAsBlocking(); | ||||
|  | ||||
|         Observable<List<Chapter>> chapterList = Observable.create(subscriber -> { | ||||
|             subscriber.onNext(getChapters(manga).executeAsBlocking()); | ||||
|             subscriber.onCompleted(); | ||||
|         Observable<List<Chapter>> newChapters = Observable.from(sourceChapters) | ||||
|                 .filter(c -> !dbChapters.contains(c)) | ||||
|                 .doOnNext(c -> { | ||||
|                     c.manga_id = manga.id; | ||||
|                     c.date_fetch = new Date().getTime(); | ||||
|                     ChapterRecognition.parseChapterNumber(c, manga); | ||||
|                 }) | ||||
|                 .toList(); | ||||
|  | ||||
|         Observable<List<Chapter>> deletedChapters = Observable.from(dbChapters) | ||||
|                 .filter(c -> !sourceChapters.contains(c)) | ||||
|                 .toList(); | ||||
|  | ||||
|         return Observable.zip(newChapters, deletedChapters, (toAdd, toDelete) -> { | ||||
|             int added = 0; | ||||
|             int deleted = 0; | ||||
|             db.internal().beginTransaction(); | ||||
|             try { | ||||
|                 if (!toAdd.isEmpty()) { | ||||
|                     // Set the date fetch for new items in reverse order to allow another sorting method. | ||||
|                     // Sources MUST return the chapters from most to less recent, which is common. | ||||
|                     for (int i = toAdd.size() - 1; i >= 0; i--) { | ||||
|                         toAdd.get(i).date_fetch = new Date().getTime(); | ||||
|                     } | ||||
|                     added = insertChapters(toAdd).executeAsBlocking().numberOfInserts(); | ||||
|                 } | ||||
|  | ||||
|                 if (!toDelete.isEmpty()) { | ||||
|                     deleted = deleteChapters(toDelete).executeAsBlocking().results().size(); | ||||
|                 } | ||||
|  | ||||
|                 db.internal().setTransactionSuccessful(); | ||||
|             } finally { | ||||
|                 db.internal().endTransaction(); | ||||
|             } | ||||
|             return Pair.create(added, deleted); | ||||
|         }); | ||||
|  | ||||
|         Observable<Integer> newChaptersObs = chapterList | ||||
|                 .flatMap(dbChapters -> Observable.from(chapters) | ||||
|                         .filter(c -> !dbChapters.contains(c)) | ||||
|                         .map(c -> { | ||||
|                             ChapterRecognition.parseChapterNumber(c, manga); | ||||
|                             return c; | ||||
|                         }) | ||||
|                         .toList() | ||||
|                         .flatMap(newChapters -> insertChapters(newChapters).createObservable()) | ||||
|                         .map(PutResults::numberOfInserts)); | ||||
|  | ||||
|         Observable<Integer> deletedChaptersObs = chapterList | ||||
|                 .flatMap(dbChapters -> Observable.from(dbChapters) | ||||
|                         .filter(c -> !chapters.contains(c)) | ||||
|                         .toList() | ||||
|                         .flatMap(deletedChapters -> deleteChapters(deletedChapters).createObservable()) | ||||
|                         .map(d -> d.results().size())); | ||||
|  | ||||
|         return Observable.zip(newChaptersObs, deletedChaptersObs, | ||||
|                 (insertions, deletions) -> new PostResult(0, insertions, deletions) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public PreparedDeleteObject<Chapter> deleteChapter(Chapter chapter) { | ||||
|   | ||||
| @@ -232,8 +232,6 @@ public class Batoto extends LoginSource { | ||||
|         if (dateElement != null) { | ||||
|             chapter.date_upload = parseDateFromElement(dateElement); | ||||
|         } | ||||
|         chapter.date_fetch = new Date().getTime(); | ||||
|  | ||||
|         return chapter; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,6 @@ import org.jsoup.nodes.Element; | ||||
| import java.text.ParseException; | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
| import java.util.regex.Matcher; | ||||
| @@ -194,8 +193,6 @@ public class Kissmanga extends Source { | ||||
|                 chapter.date_upload = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH).parse(date).getTime(); | ||||
|             } catch (ParseException e) { /* Ignore */ } | ||||
|         } | ||||
|  | ||||
|         chapter.date_fetch = new Date().getTime(); | ||||
|         return chapter; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -174,8 +174,6 @@ public class Mangafox extends Source { | ||||
|         if (dateElement != null) { | ||||
|             chapter.date_upload = parseUpdateFromElement(dateElement); | ||||
|         } | ||||
|         chapter.date_fetch = new Date().getTime(); | ||||
|  | ||||
|         return chapter; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -234,8 +234,6 @@ public class Mangahere extends Source { | ||||
|         if (dateElement != null) { | ||||
|             chapter.date_upload = parseDateFromElement(dateElement); | ||||
|         } | ||||
|         chapter.date_fetch = new Date().getTime(); | ||||
|  | ||||
|         return chapter; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,8 @@ import android.content.BroadcastReceiver; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.os.IBinder; | ||||
| import android.os.PowerManager; | ||||
| import android.util.Pair; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| @@ -22,7 +24,6 @@ import eu.kanade.mangafeed.data.source.SourceManager; | ||||
| import eu.kanade.mangafeed.util.AndroidComponentUtil; | ||||
| import eu.kanade.mangafeed.util.NetworkUtil; | ||||
| import eu.kanade.mangafeed.util.NotificationUtil; | ||||
| import eu.kanade.mangafeed.util.PostResult; | ||||
| import rx.Observable; | ||||
| import rx.Subscription; | ||||
| import rx.schedulers.Schedulers; | ||||
| @@ -34,6 +35,7 @@ public class LibraryUpdateService extends Service { | ||||
|     @Inject SourceManager sourceManager; | ||||
|     @Inject PreferencesHelper preferences; | ||||
|  | ||||
|     private PowerManager.WakeLock wakeLock; | ||||
|     private Subscription subscription; | ||||
|  | ||||
|     public static final int UPDATE_NOTIFICATION_ID = 1; | ||||
| @@ -56,6 +58,7 @@ public class LibraryUpdateService extends Service { | ||||
|     public void onCreate() { | ||||
|         super.onCreate(); | ||||
|         App.get(this).getComponent().inject(this); | ||||
|         createAndAcquireWakeLock(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -64,6 +67,7 @@ public class LibraryUpdateService extends Service { | ||||
|             subscription.unsubscribe(); | ||||
|         // Reset the alarm | ||||
|         LibraryUpdateAlarm.startAlarm(this); | ||||
|         destroyWakeLock(); | ||||
|         super.onDestroy(); | ||||
|     } | ||||
|  | ||||
| @@ -111,17 +115,18 @@ public class LibraryUpdateService extends Service { | ||||
|                 .concatMap(manga -> updateManga(manga) | ||||
|                         .onErrorReturn(error -> { | ||||
|                             failedUpdates.add(manga); | ||||
|                             return new PostResult(0, 0, 0); | ||||
|                             return Pair.create(0, 0); | ||||
|                         }) | ||||
|                         .filter(result -> result.getNumberOfRowsInserted() > 0) | ||||
|                         .map(result -> new MangaUpdate(manga, result))) | ||||
|                         // Filter out mangas without new chapters | ||||
|                         .filter(pair -> pair.first > 0) | ||||
|                         .map(pair -> new MangaUpdate(manga, pair.first))) | ||||
|                 .doOnNext(updates::add) | ||||
|                 .doOnCompleted(() -> NotificationUtil.createBigText(this, UPDATE_NOTIFICATION_ID, | ||||
|                         getString(R.string.notification_update_completed), | ||||
|                         getUpdatedMangas(updates, failedUpdates))); | ||||
|     } | ||||
|  | ||||
|     private Observable<PostResult> updateManga(Manga manga) { | ||||
|     private Observable<Pair<Integer, Integer>> updateManga(Manga manga) { | ||||
|         return sourceManager.get(manga.source) | ||||
|                 .pullChaptersFromNetwork(manga.url) | ||||
|                 .flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters)); | ||||
| @@ -135,7 +140,7 @@ public class LibraryUpdateService extends Service { | ||||
|             result.append(getString(R.string.notification_new_chapters)); | ||||
|  | ||||
|             for (MangaUpdate update : updates) { | ||||
|                 result.append("\n").append(update.getManga().title); | ||||
|                 result.append("\n").append(update.manga.title); | ||||
|             } | ||||
|         } | ||||
|         if (!failedUpdates.isEmpty()) { | ||||
| @@ -154,6 +159,19 @@ public class LibraryUpdateService extends Service { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private void createAndAcquireWakeLock() { | ||||
|         wakeLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock( | ||||
|                 PowerManager.PARTIAL_WAKE_LOCK, "LibraryUpdateService:WakeLock"); | ||||
|         wakeLock.acquire(); | ||||
|     } | ||||
|  | ||||
|     private void destroyWakeLock() { | ||||
|         if (wakeLock != null && wakeLock.isHeld()) { | ||||
|             wakeLock.release(); | ||||
|             wakeLock = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static class SyncOnConnectionAvailable extends BroadcastReceiver { | ||||
|  | ||||
|         @Override | ||||
| @@ -169,20 +187,12 @@ public class LibraryUpdateService extends Service { | ||||
|     } | ||||
|  | ||||
|     private static class MangaUpdate { | ||||
|         private Manga manga; | ||||
|         private PostResult result; | ||||
|         public Manga manga; | ||||
|         public int newChapters; | ||||
|  | ||||
|         public MangaUpdate(Manga manga, PostResult result) { | ||||
|         public MangaUpdate(Manga manga, int newChapters) { | ||||
|             this.manga = manga; | ||||
|             this.result = result; | ||||
|         } | ||||
|  | ||||
|         public Manga getManga() { | ||||
|             return manga; | ||||
|         } | ||||
|  | ||||
|         public PostResult getResult() { | ||||
|             return result; | ||||
|             this.newChapters = newChapters; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package eu.kanade.mangafeed.ui.manga.chapter; | ||||
|  | ||||
| import android.os.Bundle; | ||||
| import android.util.Pair; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -20,7 +21,6 @@ import eu.kanade.mangafeed.event.DownloadChaptersEvent; | ||||
| import eu.kanade.mangafeed.event.ReaderEvent; | ||||
| import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; | ||||
| import eu.kanade.mangafeed.util.EventBusHook; | ||||
| import eu.kanade.mangafeed.util.PostResult; | ||||
| import rx.Observable; | ||||
| import rx.android.schedulers.AndroidSchedulers; | ||||
| import rx.schedulers.Schedulers; | ||||
| @@ -119,7 +119,7 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> { | ||||
|         chaptersSubject.onNext(chapters); | ||||
|     } | ||||
|  | ||||
|     private Observable<PostResult> getOnlineChaptersObs() { | ||||
|     private Observable<Pair<Integer, Integer>> getOnlineChaptersObs() { | ||||
|         return source.pullChaptersFromNetwork(manga.url) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters)) | ||||
|   | ||||
| @@ -16,8 +16,8 @@ import eu.kanade.mangafeed.data.mangasync.base.MangaSyncService; | ||||
| import eu.kanade.mangafeed.data.mangasync.MangaSyncManager; | ||||
| import eu.kanade.mangafeed.data.source.SourceManager; | ||||
| import eu.kanade.mangafeed.data.source.base.Source; | ||||
| import eu.kanade.mangafeed.ui.setting.preference.MangaSyncLoginDialog; | ||||
| import eu.kanade.mangafeed.ui.setting.preference.SourceLoginDialog; | ||||
| import eu.kanade.mangafeed.widget.preference.MangaSyncLoginDialog; | ||||
| import eu.kanade.mangafeed.widget.preference.SourceLoginDialog; | ||||
| import rx.Observable; | ||||
|  | ||||
| public class SettingsAccountsFragment extends SettingsNestedFragment { | ||||
|   | ||||
| @@ -8,8 +8,8 @@ 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; | ||||
| import eu.kanade.mangafeed.widget.preference.IntListPreference; | ||||
| import eu.kanade.mangafeed.widget.preference.LibraryColumnsDialog; | ||||
|  | ||||
| public class SettingsGeneralFragment extends SettingsNestedFragment { | ||||
|  | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| package eu.kanade.mangafeed.util; | ||||
|  | ||||
| import android.support.annotation.Nullable; | ||||
|  | ||||
| public class PostResult { | ||||
|  | ||||
|     @Nullable | ||||
|     private final Integer numberOfRowsUpdated; | ||||
|  | ||||
|     @Nullable | ||||
|     private final Integer numberOfRowsInserted; | ||||
|  | ||||
|     @Nullable | ||||
|     private final Integer numberOfRowsDeleted; | ||||
|  | ||||
|     public PostResult(Integer numberOfRowsUpdated, Integer numberOfRowsInserted, Integer numberOfRowsDeleted) { | ||||
|         this.numberOfRowsUpdated = numberOfRowsUpdated; | ||||
|         this.numberOfRowsInserted = numberOfRowsInserted; | ||||
|         this.numberOfRowsDeleted = numberOfRowsDeleted; | ||||
|     } | ||||
|  | ||||
|     public Integer getNumberOfRowsUpdated() { | ||||
|         return numberOfRowsUpdated; | ||||
|     } | ||||
|  | ||||
|     public Integer getNumberOfRowsInserted() { | ||||
|         return numberOfRowsInserted; | ||||
|     } | ||||
|  | ||||
|     public Integer getNumberOfRowsDeleted() { | ||||
|         return numberOfRowsDeleted; | ||||
|     } | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| package eu.kanade.mangafeed.ui.setting.preference; | ||||
| package eu.kanade.mangafeed.widget.preference; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.preference.ListPreference; | ||||
| @@ -1,4 +1,4 @@ | ||||
| package eu.kanade.mangafeed.ui.setting.preference; | ||||
| package eu.kanade.mangafeed.widget.preference; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.preference.DialogPreference; | ||||
| @@ -1,4 +1,4 @@ | ||||
| package eu.kanade.mangafeed.ui.setting.preference; | ||||
| package eu.kanade.mangafeed.widget.preference; | ||||
| 
 | ||||
| import android.app.AlertDialog; | ||||
| import android.content.Context; | ||||
| @@ -1,4 +1,4 @@ | ||||
| package eu.kanade.mangafeed.ui.setting.preference; | ||||
| package eu.kanade.mangafeed.widget.preference; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.DialogInterface; | ||||
| @@ -1,4 +1,4 @@ | ||||
| package eu.kanade.mangafeed.ui.setting.preference; | ||||
| package eu.kanade.mangafeed.widget.preference; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.DialogInterface; | ||||
		Reference in New Issue
	
	Block a user