Update last chapter read in MAL when reaching the last page

This commit is contained in:
inorichi 2015-11-27 00:51:18 +01:00
parent e1a14be2bd
commit 9db81b1832
12 changed files with 183 additions and 20 deletions

View file

@ -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">

View file

@ -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);
}

View file

@ -26,4 +26,12 @@ public class ChapterSyncManager {
return services;
}
public BaseChapterSync getSyncService(int id) {
switch (id) {
case MYANIMELIST:
return myAnimeList;
}
return null;
}
}

View file

@ -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());

View file

@ -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();
}));
}
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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();

View file

@ -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;
});

View file

@ -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;
});

View file

@ -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;
}
}

View file

@ -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 (pageList == null)
return;
// Cache page list for online chapters to allow a faster reopen
if (!isDownloaded)
source.savePageList(chapter.url, pageList);
saveChapterProgress();
// 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);