Fix chapter recognition. Improve initial requests to fetch chapters from source

This commit is contained in:
inorichi 2015-12-03 13:57:25 +01:00
parent b986309b81
commit 384acb2322
5 changed files with 48 additions and 15 deletions

View file

@ -35,7 +35,6 @@ import eu.kanade.mangafeed.util.EventBusHook;
import eu.kanade.mangafeed.util.ToastUtil; import eu.kanade.mangafeed.util.ToastUtil;
import nucleus.factory.RequiresPresenter; import nucleus.factory.RequiresPresenter;
import rx.Observable; import rx.Observable;
import timber.log.Timber;
@RequiresPresenter(ChaptersPresenter.class) @RequiresPresenter(ChaptersPresenter.class)
public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implements public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implements
@ -84,7 +83,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
setSortIcon(); setSortIcon();
// Init listeners // Init listeners
swipeRefresh.setOnRefreshListener(this::onFetchChapters); swipeRefresh.setOnRefreshListener(this::fetchChapters);
readCb.setOnCheckedChangeListener((arg, isChecked) -> readCb.setOnCheckedChangeListener((arg, isChecked) ->
getPresenter().setReadFilter(isChecked)); getPresenter().setReadFilter(isChecked));
downloadedCb.setOnCheckedChangeListener((v, isChecked) -> downloadedCb.setOnCheckedChangeListener((v, isChecked) ->
@ -127,31 +126,43 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_refresh: case R.id.action_refresh:
onFetchChapters(); fetchChapters();
break; break;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
public void onNextChapters(List<Chapter> chapters) { public void onNextChapters(List<Chapter> chapters) {
if (chapters.isEmpty() && isCatalogueManga()) { // If the list is empty, fetch chapters from source if the conditions are met
swipeRefresh.setRefreshing(true); // We use presenter chapters instead because they are always unfiltered
getPresenter().fetchChaptersFromSource(); if (getPresenter().getChapters().isEmpty())
} initialFetchChapters();
closeActionMode(); closeActionMode();
adapter.setItems(chapters); adapter.setItems(chapters);
} }
public void onFetchChapters() { private void initialFetchChapters() {
// Only fetch if this view is from the catalog and it hasn't requested previously
if (isCatalogueManga() && !getPresenter().hasRequested()) {
fetchChapters();
}
}
public void fetchChapters() {
swipeRefresh.setRefreshing(true); swipeRefresh.setRefreshing(true);
getPresenter().fetchChaptersFromSource(); getPresenter().fetchChaptersFromSource();
} }
public void onFetchChaptersFinish() { public void onFetchChaptersDone() {
swipeRefresh.setRefreshing(false); swipeRefresh.setRefreshing(false);
} }
public void onFetchChaptersError() {
swipeRefresh.setRefreshing(false);
ToastUtil.showShort(getContext(), R.string.fetch_chapters_error);
}
public boolean isCatalogueManga() { public boolean isCatalogueManga() {
return ((MangaActivity) getActivity()).isCatalogueManga(); return ((MangaActivity) getActivity()).isCatalogueManga();
} }

View file

@ -41,6 +41,7 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
private boolean sortOrderAToZ = true; private boolean sortOrderAToZ = true;
private boolean onlyUnread = true; private boolean onlyUnread = true;
private boolean onlyDownloaded; private boolean onlyDownloaded;
private boolean hasRequested;
private PublishSubject<List<Chapter>> chaptersSubject; private PublishSubject<List<Chapter>> chaptersSubject;
@ -60,7 +61,8 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
restartableLatestCache(FETCH_CHAPTERS, restartableLatestCache(FETCH_CHAPTERS,
this::getOnlineChaptersObs, this::getOnlineChaptersObs,
(view, result) -> view.onFetchChaptersFinish() (view, result) -> view.onFetchChaptersDone(),
(view, error) -> view.onFetchChaptersError()
); );
} }
@ -78,8 +80,8 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().removeStickyEvent(ChapterCountEvent.class); EventBus.getDefault().removeStickyEvent(ChapterCountEvent.class);
super.onDestroy();
} }
@EventBusHook @EventBusHook
@ -116,7 +118,8 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
.pullChaptersFromNetwork(manga.url) .pullChaptersFromNetwork(manga.url)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters)) .flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters))
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread())
.doOnNext(r -> hasRequested = true);
} }
private Observable<List<Chapter>> getDbChaptersObs() { private Observable<List<Chapter>> getDbChaptersObs() {
@ -248,4 +251,12 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
return manga; return manga;
} }
public List<Chapter> getChapters() {
return chapters;
}
public boolean hasRequested() {
return hasRequested;
}
} }

View file

@ -10,7 +10,7 @@ import eu.kanade.mangafeed.data.database.models.Manga;
public class ChapterRecognition { public class ChapterRecognition {
private static Pattern p1 = Pattern.compile("ch.?(\\d+[\\.,]?\\d*)"); private static Pattern p1 = Pattern.compile("Ch[^0-9]?\\s*(\\d+[\\.,]?\\d*)");
private static Pattern p2 = Pattern.compile("(\\d+[\\.,]?\\d*)"); private static Pattern p2 = Pattern.compile("(\\d+[\\.,]?\\d*)");
private static Pattern p3 = Pattern.compile("(\\d+[\\.,]?\\d*:)"); private static Pattern p3 = Pattern.compile("(\\d+[\\.,]?\\d*:)");
@ -19,7 +19,7 @@ public class ChapterRecognition {
return; return;
// Remove spaces and convert to lower case // Remove spaces and convert to lower case
String name = replaceIrrelevantCharacters(chapter.name); String name = chapter.name;
Matcher matcher; Matcher matcher;
// Safest option, the chapter has a token prepended // Safest option, the chapter has a token prepended
@ -29,6 +29,8 @@ public class ChapterRecognition {
return; return;
} }
name = replaceIrrelevantCharacters(name);
List<Float> occurences; List<Float> occurences;
// If there's only one number, use it // If there's only one number, use it
@ -71,7 +73,7 @@ public class ChapterRecognition {
Matcher m = p2.matcher(text); Matcher m = p2.matcher(text);
if (m.find()) { if (m.find()) {
try { try {
Float value = Float.parseFloat(m.group()); Float value = Float.parseFloat(m.group(1));
if (!occurences.contains(value)) { if (!occurences.contains(value)) {
occurences.add(value); occurences.add(value);
} }

View file

@ -91,6 +91,7 @@
<string name="chapter_queued">Queued</string> <string name="chapter_queued">Queued</string>
<string name="chapter_downloading">Downloading</string> <string name="chapter_downloading">Downloading</string>
<string name="chapter_error">Error</string> <string name="chapter_error">Error</string>
<string name="fetch_chapters_error">Error while fetching chapters</string>
<!-- Reader activity --> <!-- Reader activity -->
<string name="downloading">Downloading…</string> <string name="downloading">Downloading…</string>

View file

@ -105,4 +105,12 @@ public class ChapterRecognitionTest {
assertThat(c.chapter_number, is(191f)); assertThat(c.chapter_number, is(191f));
} }
@Test
public void testWithKeywordChAtTheEndOfTheManga() {
// It should be 567, not 67 (ch is a keyword to get the chapter number)
Chapter c = createChapter("Bleach 567: Down With Snowwhite");
ChapterRecognition.parseChapterNumber(c, randomManga);
assertThat(c.chapter_number, is(567f));
}
} }