Update last chapter read in MAL when reaching the last page
This commit is contained in:
parent
e1a14be2bd
commit
9db81b1832
12 changed files with 183 additions and 20 deletions
|
@ -46,6 +46,9 @@
|
|||
<service android:name=".data.download.DownloadService"
|
||||
android:exported="false"/>
|
||||
|
||||
<service android:name=".data.chaptersync.UpdateChapterSyncService"
|
||||
android:exported="false"/>
|
||||
|
||||
<receiver
|
||||
android:name=".data.sync.LibraryUpdateService$SyncOnConnectionAvailable"
|
||||
android:enabled="false">
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package eu.kanade.mangafeed.data.chaptersync;
|
||||
|
||||
import com.squareup.okhttp.Response;
|
||||
|
||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
||||
import rx.Observable;
|
||||
|
||||
public abstract class BaseChapterSync {
|
||||
|
@ -13,4 +16,6 @@ public abstract class BaseChapterSync {
|
|||
public abstract Observable<Boolean> login(String username, String password);
|
||||
|
||||
public abstract boolean isLogged();
|
||||
|
||||
public abstract Observable<Response> update(ChapterSync chapter);
|
||||
}
|
||||
|
|
|
@ -26,4 +26,12 @@ public class ChapterSyncManager {
|
|||
return services;
|
||||
}
|
||||
|
||||
public BaseChapterSync getSyncService(int id) {
|
||||
switch (id) {
|
||||
case MYANIMELIST:
|
||||
return myAnimeList;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ public class MyAnimeList extends BaseChapterSync {
|
|||
.map(entry -> {
|
||||
ChapterSync chapter = ChapterSync.create(this);
|
||||
chapter.title = entry.select("title").first().text();
|
||||
chapter.remote_id = Long.parseLong(entry.select("id").first().text());
|
||||
chapter.remote_id = Integer.parseInt(entry.select("id").first().text());
|
||||
return chapter;
|
||||
})
|
||||
.toList();
|
||||
|
@ -111,7 +111,7 @@ public class MyAnimeList extends BaseChapterSync {
|
|||
.map(entry -> {
|
||||
ChapterSync chapter = ChapterSync.create(this);
|
||||
chapter.title = entry.select("series_title").first().text();
|
||||
chapter.remote_id = Long.parseLong(
|
||||
chapter.remote_id = Integer.parseInt(
|
||||
entry.select("series_mangadb_id").first().text());
|
||||
chapter.last_chapter_read = Integer.parseInt(
|
||||
entry.select("my_read_chapters").first().text());
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package eu.kanade.mangafeed.data.chaptersync;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
||||
import eu.kanade.mangafeed.data.network.NetworkHelper;
|
||||
import eu.kanade.mangafeed.event.UpdateChapterSyncEvent;
|
||||
import eu.kanade.mangafeed.util.EventBusHook;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
import rx.subscriptions.CompositeSubscription;
|
||||
|
||||
public class UpdateChapterSyncService extends Service {
|
||||
|
||||
@Inject ChapterSyncManager syncManager;
|
||||
@Inject NetworkHelper networkManager;
|
||||
@Inject DatabaseHelper db;
|
||||
|
||||
private CompositeSubscription subscriptions;
|
||||
|
||||
public static void start(Context context) {
|
||||
context.startService(new Intent(context, UpdateChapterSyncService.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
App.get(this).getComponent().inject(this);
|
||||
subscriptions = new CompositeSubscription();
|
||||
EventBus.getDefault().registerSticky(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
subscriptions.unsubscribe();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@EventBusHook
|
||||
public void onEventMainThread(UpdateChapterSyncEvent event) {
|
||||
updateLastChapteRead(event.getChapterSync());
|
||||
}
|
||||
|
||||
private void updateLastChapteRead(ChapterSync chapterSync) {
|
||||
BaseChapterSync sync = syncManager.getSyncService(chapterSync.sync_id);
|
||||
|
||||
subscriptions.add(sync.update(chapterSync)
|
||||
.flatMap(response -> db.insertChapterSync(chapterSync).createObservable())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
stopSelf();
|
||||
}, error -> {
|
||||
stopSelf();
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
|
@ -16,10 +16,10 @@ public class ChapterSync {
|
|||
public long manga_id;
|
||||
|
||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_SYNC_ID)
|
||||
public long sync_id;
|
||||
public int sync_id;
|
||||
|
||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_REMOTE_ID)
|
||||
public long remote_id;
|
||||
public int remote_id;
|
||||
|
||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_TITLE)
|
||||
public String title;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package eu.kanade.mangafeed.event;
|
||||
|
||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
||||
|
||||
public class UpdateChapterSyncEvent {
|
||||
|
||||
private ChapterSync chapterSync;
|
||||
|
||||
public UpdateChapterSyncEvent(ChapterSync chapterSync) {
|
||||
this.chapterSync = chapterSync;
|
||||
}
|
||||
|
||||
public ChapterSync getChapterSync() {
|
||||
return chapterSync;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import javax.inject.Singleton;
|
|||
|
||||
import dagger.Component;
|
||||
import eu.kanade.mangafeed.data.chaptersync.MyAnimeList;
|
||||
import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService;
|
||||
import eu.kanade.mangafeed.data.download.DownloadService;
|
||||
import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
|
||||
import eu.kanade.mangafeed.injection.module.AppModule;
|
||||
|
@ -55,6 +56,7 @@ public interface AppComponent {
|
|||
|
||||
void inject(LibraryUpdateService libraryUpdateService);
|
||||
void inject(DownloadService downloadService);
|
||||
void inject(UpdateChapterSyncService updateChapterSyncService);
|
||||
|
||||
Application application();
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.os.Bundle;
|
|||
import android.support.annotation.NonNull;
|
||||
|
||||
import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import nucleus.factory.PresenterFactory;
|
||||
import nucleus.factory.ReflectionPresenterFactory;
|
||||
import nucleus.presenter.Presenter;
|
||||
|
@ -60,7 +60,9 @@ public abstract class BaseRxActivity<P extends Presenter> extends BaseActivity i
|
|||
final PresenterFactory<P> superFactory = getPresenterFactory();
|
||||
setPresenterFactory(() -> {
|
||||
P presenter = superFactory.createPresenter();
|
||||
((App)getApplication()).getComponentReflection().inject(presenter);
|
||||
App app = (App) getApplication();
|
||||
app.getComponentReflection().inject(presenter);
|
||||
((BasePresenter)presenter).setContext(app.getApplicationContext());
|
||||
return presenter;
|
||||
});
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.mangafeed.ui.base.fragment;
|
|||
import android.os.Bundle;
|
||||
|
||||
import eu.kanade.mangafeed.App;
|
||||
import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import nucleus.factory.PresenterFactory;
|
||||
import nucleus.factory.ReflectionPresenterFactory;
|
||||
import nucleus.presenter.Presenter;
|
||||
|
@ -57,7 +57,9 @@ public abstract class BaseRxFragment<P extends Presenter> extends BaseFragment i
|
|||
final PresenterFactory<P> superFactory = getPresenterFactory();
|
||||
setPresenterFactory(() -> {
|
||||
P presenter = superFactory.createPresenter();
|
||||
((App)getActivity().getApplication()).getComponentReflection().inject(presenter);
|
||||
App app = (App) getActivity().getApplication();
|
||||
app.getComponentReflection().inject(presenter);
|
||||
((BasePresenter)presenter).setContext(app.getApplicationContext());
|
||||
return presenter;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package eu.kanade.mangafeed.ui.base.presenter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
|
@ -10,6 +11,8 @@ import nucleus.view.ViewWithPresenter;
|
|||
|
||||
public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
||||
|
||||
private Context context;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
@ -33,4 +36,13 @@ public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
|||
public void unregisterForEvents() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
public void setContext(Context applicationContext) {
|
||||
context = applicationContext;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,8 +8,12 @@ import java.util.List;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
||||
import eu.kanade.mangafeed.data.chaptersync.MyAnimeList;
|
||||
import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService;
|
||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||
import eu.kanade.mangafeed.data.database.models.Chapter;
|
||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||
import eu.kanade.mangafeed.data.download.DownloadManager;
|
||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||
|
@ -17,6 +21,7 @@ import eu.kanade.mangafeed.data.source.base.Source;
|
|||
import eu.kanade.mangafeed.data.source.model.Page;
|
||||
import eu.kanade.mangafeed.event.RetryPageEvent;
|
||||
import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
|
||||
import eu.kanade.mangafeed.event.UpdateChapterSyncEvent;
|
||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||
import eu.kanade.mangafeed.util.EventBusHook;
|
||||
import icepick.State;
|
||||
|
@ -32,6 +37,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
|||
@Inject PreferencesHelper prefs;
|
||||
@Inject DatabaseHelper db;
|
||||
@Inject DownloadManager downloadManager;
|
||||
@Inject ChapterSyncManager syncManager;
|
||||
|
||||
private Source source;
|
||||
private Manga manga;
|
||||
|
@ -135,10 +141,47 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
|||
}
|
||||
|
||||
private void onChapterChange() {
|
||||
if (pageList != null) {
|
||||
if (!isDownloaded)
|
||||
source.savePageList(chapter.url, pageList);
|
||||
saveChapterProgress();
|
||||
if (pageList == null)
|
||||
return;
|
||||
|
||||
// Cache page list for online chapters to allow a faster reopen
|
||||
if (!isDownloaded)
|
||||
source.savePageList(chapter.url, pageList);
|
||||
|
||||
// Save current progress of the chapter. Mark as read if the chapter is finished
|
||||
// and update progress in remote services (like MyAnimeList)
|
||||
chapter.last_page_read = currentPage;
|
||||
if (isChapterFinished()) {
|
||||
chapter.read = true;
|
||||
updateChapterSyncLastChapterRead();
|
||||
}
|
||||
db.insertChapter(chapter).executeAsBlocking();
|
||||
}
|
||||
|
||||
private boolean isChapterFinished() {
|
||||
return !chapter.read && currentPage == pageList.size() - 1;
|
||||
}
|
||||
|
||||
private void updateChapterSyncLastChapterRead() {
|
||||
// TODO don't use MAL methods for possible alternatives to MAL
|
||||
MyAnimeList mal = syncManager.getMyAnimeList();
|
||||
|
||||
if (!mal.isLogged())
|
||||
return;
|
||||
|
||||
List<ChapterSync> result = db.getChapterSync(manga, mal).executeAsBlocking();
|
||||
if (result.isEmpty())
|
||||
return;
|
||||
|
||||
ChapterSync chapterSync = result.get(0);
|
||||
|
||||
int lastChapterReadLocal = (int) Math.floor(chapter.chapter_number);
|
||||
int lastChapterReadRemote = chapterSync.last_chapter_read;
|
||||
|
||||
if (lastChapterReadLocal > lastChapterReadRemote) {
|
||||
chapterSync.last_chapter_read = lastChapterReadLocal;
|
||||
EventBus.getDefault().postSticky(new UpdateChapterSyncEvent(chapterSync));
|
||||
UpdateChapterSyncService.start(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,14 +229,6 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
|||
this.currentPage = currentPage;
|
||||
}
|
||||
|
||||
private void saveChapterProgress() {
|
||||
chapter.last_page_read = currentPage;
|
||||
if (currentPage == pageList.size() - 1) {
|
||||
chapter.read = true;
|
||||
}
|
||||
db.insertChapter(chapter).executeAsBlocking();
|
||||
}
|
||||
|
||||
private void getAdjacentChapters() {
|
||||
if (nextChapterSubscription != null)
|
||||
remove(nextChapterSubscription);
|
||||
|
|
Reference in a new issue