Store total chapters from MAL and automatically set as completed if it's the last chapter. Other minor changes

This commit is contained in:
inorichi 2015-12-31 19:15:24 +01:00
parent f26a60f1ba
commit f9a97631f2
13 changed files with 181 additions and 51 deletions

View file

@ -110,6 +110,7 @@ public class MyAnimeList extends MangaSyncService {
MangaSync manga = MangaSync.create(this); MangaSync manga = MangaSync.create(this);
manga.title = entry.select("title").first().text(); manga.title = entry.select("title").first().text();
manga.remote_id = Integer.parseInt(entry.select("id").first().text()); manga.remote_id = Integer.parseInt(entry.select("id").first().text());
manga.total_chapters = Integer.parseInt(entry.select("chapters").first().text());
return manga; return manga;
}) })
.toList(); .toList();
@ -141,6 +142,8 @@ public class MyAnimeList extends MangaSyncService {
// MAL doesn't support score with decimals // MAL doesn't support score with decimals
manga.score = Integer.parseInt( manga.score = Integer.parseInt(
entry.select("my_score").first().text()); entry.select("my_score").first().text());
manga.total_chapters = Integer.parseInt(
entry.select("series_chapters").first().text());
return manga; return manga;
}) })
.toList(); .toList();
@ -155,6 +158,9 @@ public class MyAnimeList extends MangaSyncService {
public Observable<Response> update(MangaSync manga) { public Observable<Response> update(MangaSync manga) {
try { try {
if (manga.total_chapters != 0 && manga.last_chapter_read == manga.total_chapters) {
manga.status = COMPLETED;
}
RequestBody payload = getMangaPostPayload(manga); RequestBody payload = getMangaPostPayload(manga);
return networkService.postData(getUpdateUrl(manga), payload, headers); return networkService.postData(getUpdateUrl(manga), payload, headers);
} catch (IOException e) { } catch (IOException e) {

View file

@ -81,10 +81,15 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
@Override @Override
public void onDestroyView() { public void onDestroyView() {
appBar.removeView(tabs); appBar.removeView(tabs);
EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class);
super.onDestroyView(); super.onDestroyView();
} }
@Override
public void onPause() {
EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class);
super.onPause();
}
@Override @Override
public void onSaveInstanceState(Bundle bundle) { public void onSaveInstanceState(Bundle bundle) {
activeCategory = viewPager.getCurrentItem(); activeCategory = viewPager.getCurrentItem();

View file

@ -2,21 +2,29 @@ package eu.kanade.mangafeed.ui.manga.myanimelist;
import android.app.Dialog; import android.app.Dialog;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.text.Editable;
import android.view.LayoutInflater; import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ListView; import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.database.models.MangaSync; import eu.kanade.mangafeed.data.database.models.MangaSync;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.subjects.PublishSubject;
import uk.co.ribot.easyadapter.EasyAdapter; import uk.co.ribot.easyadapter.EasyAdapter;
import uk.co.ribot.easyadapter.ItemViewHolder; import uk.co.ribot.easyadapter.ItemViewHolder;
import uk.co.ribot.easyadapter.PositionInfo; import uk.co.ribot.easyadapter.PositionInfo;
@ -26,61 +34,108 @@ import uk.co.ribot.easyadapter.annotations.ViewId;
public class MyAnimeListDialogFragment extends DialogFragment { public class MyAnimeListDialogFragment extends DialogFragment {
@Bind(R.id.myanimelist_search_field) EditText searchText; @Bind(R.id.myanimelist_search_field) EditText searchText;
@Bind(R.id.myanimelist_search_button) Button searchButton;
@Bind(R.id.myanimelist_search_results) ListView searchResults; @Bind(R.id.myanimelist_search_results) ListView searchResults;
@Bind(R.id.progress) ProgressBar progressBar;
private EasyAdapter<MangaSync> adapter; private EasyAdapter<MangaSync> adapter;
private MyAnimeListFragment fragment;
private MyAnimeListPresenter presenter;
private MangaSync selectedItem; private MangaSync selectedItem;
public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) { private Subscription searchSubscription;
MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment();
dialog.fragment = parentFragment; public static MyAnimeListDialogFragment newInstance() {
dialog.presenter = parentFragment.getPresenter(); return new MyAnimeListDialogFragment();
return dialog;
} }
@NonNull
@Override @Override
public Dialog onCreateDialog(Bundle savedState) { public Dialog onCreateDialog(Bundle savedState) {
// Inflate and bind view MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
LayoutInflater inflater = getActivity().getLayoutInflater(); .customView(R.layout.dialog_myanimelist_search, false)
View view = inflater.inflate(R.layout.dialog_myanimelist_search, null); .positiveText(R.string.button_ok)
ButterKnife.bind(this, view); .negativeText(R.string.button_cancel)
.onPositive((dialog1, which) -> onPositiveButtonClick())
.build();
// Build dialog ButterKnife.bind(this, dialog.getView());
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view)
.setPositiveButton(R.string.button_ok, (dialog, which) -> onPositiveButtonClick())
.setNegativeButton(R.string.button_cancel, (dialog, which) -> {});
// Create adapter // Create adapter
adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class); adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class);
searchResults.setAdapter(adapter); searchResults.setAdapter(adapter);
// Set listeners // Set listeners
searchButton.setOnClickListener(v ->
presenter.searchManga(searchText.getText().toString()));
searchResults.setOnItemClickListener((parent, viewList, position, id) -> searchResults.setOnItemClickListener((parent, viewList, position, id) ->
selectedItem = adapter.getItem(position)); selectedItem = adapter.getItem(position));
// Do an initial search based on the manga's title // Do an initial search based on the manga's title
presenter.searchManga(presenter.manga.title); if (savedState == null) {
return builder.create(); String title = getPresenter().manga.title;
searchText.append(title);
search(title);
}
return dialog;
}
@Override
public void onResume() {
super.onResume();
PublishSubject<String> querySubject = PublishSubject.create();
searchText.addTextChangedListener(new SimpleTextChangeListener() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
querySubject.onNext(s.toString());
}
});
// Listen to text changes
searchSubscription = querySubject.debounce(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::search);
}
@Override
public void onPause() {
if (searchSubscription != null) {
searchSubscription.unsubscribe();
}
super.onPause();
} }
private void onPositiveButtonClick() { private void onPositiveButtonClick() {
if (adapter != null && selectedItem != null) { if (adapter != null && selectedItem != null) {
presenter.registerManga(selectedItem); getPresenter().registerManga(selectedItem);
} }
} }
public void setResults(List<MangaSync> results) { private void search(String query) {
if (!TextUtils.isEmpty(query)) {
searchResults.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
getPresenter().searchManga(query);
}
}
public void onSearchResults(List<MangaSync> results) {
selectedItem = null; selectedItem = null;
progressBar.setVisibility(View.GONE);
searchResults.setVisibility(View.VISIBLE);
adapter.setItems(results); adapter.setItems(results);
} }
public void onSearchResultsError() {
progressBar.setVisibility(View.GONE);
searchResults.setVisibility(View.VISIBLE);
adapter.getItems().clear();
}
public MyAnimeListFragment getMALFragment() {
return (MyAnimeListFragment) getParentFragment();
}
public MyAnimeListPresenter getPresenter() {
return getMALFragment().getPresenter();
}
@LayoutId(R.layout.dialog_myanimelist_search_item) @LayoutId(R.layout.dialog_myanimelist_search_item)
public static class ResultViewHolder extends ItemViewHolder<MangaSync> { public static class ResultViewHolder extends ItemViewHolder<MangaSync> {
@ -96,4 +151,22 @@ public class MyAnimeListDialogFragment extends DialogFragment {
} }
} }
private static class SimpleTextChangeListener implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
}
} }

View file

@ -33,6 +33,8 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
private DecimalFormat decimalFormat = new DecimalFormat("#.##"); private DecimalFormat decimalFormat = new DecimalFormat("#.##");
private final static String SEARCH_FRAGMENT_TAG = "mal_search";
public static MyAnimeListFragment newInstance() { public static MyAnimeListFragment newInstance() {
return new MyAnimeListFragment(); return new MyAnimeListFragment();
} }
@ -53,21 +55,36 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
} }
} }
private void showSearchDialog() { public void setSearchResults(List<MangaSync> results) {
if (dialog == null) findSearchFragmentIfNeeded();
dialog = MyAnimeListDialogFragment.newInstance(this);
dialog.show(getActivity().getSupportFragmentManager(), "search"); if (dialog != null) {
dialog.onSearchResults(results);
}
} }
public void onSearchResults(List<MangaSync> results) { public void setSearchResultsError() {
if (dialog != null) findSearchFragmentIfNeeded();
dialog.setResults(results);
if (dialog != null) {
dialog.onSearchResultsError();
}
}
private void findSearchFragmentIfNeeded() {
if (dialog == null) {
dialog = (MyAnimeListDialogFragment) getChildFragmentManager()
.findFragmentByTag(SEARCH_FRAGMENT_TAG);
}
} }
@OnClick(R.id.myanimelist_title_layout) @OnClick(R.id.myanimelist_title_layout)
void onTitleClick() { void onTitleClick() {
showSearchDialog(); if (dialog == null)
dialog = MyAnimeListDialogFragment.newInstance();
getPresenter().restartSearch();
dialog.show(getChildFragmentManager(), SEARCH_FRAGMENT_TAG);
} }
@OnClick(R.id.myanimelist_status_layout) @OnClick(R.id.myanimelist_status_layout)

View file

@ -2,6 +2,7 @@ package eu.kanade.mangafeed.ui.manga.myanimelist;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils;
import javax.inject.Inject; import javax.inject.Inject;
@ -55,9 +56,10 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()), .observeOn(AndroidSchedulers.mainThread()),
(view, results) -> { (view, results) -> {
view.onSearchResults(results); view.setSearchResults(results);
}, (view, error) -> { }, (view, error) -> {
Timber.e(error.getMessage()); Timber.e(error.getMessage());
view.setSearchResultsError();
}); });
} }
@ -100,10 +102,18 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
} }
public void searchManga(String query) { public void searchManga(String query) {
if (TextUtils.isEmpty(query) || query.equals(this.query))
return;
this.query = query; this.query = query;
start(GET_SEARCH_RESULTS); start(GET_SEARCH_RESULTS);
} }
public void restartSearch() {
this.query = null;
stop(GET_SEARCH_RESULTS);
}
public void registerManga(MangaSync manga) { public void registerManga(MangaSync manga) {
manga.manga_id = this.manga.id; manga.manga_id = this.manga.id;
add(myAnimeList.bind(manga) add(myAnimeList.bind(manga)

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

View file

@ -1,36 +1,54 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:orientation="vertical"
android:layout_height="match_parent"> android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="?attr/actionBarSize"
android:gravity="center"
android:paddingLeft="@dimen/margin_left"
android:paddingRight="@dimen/margin_right"
android:orientation="horizontal">
<EditText <EditText
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:id="@+id/myanimelist_search_field"/> android:id="@+id/myanimelist_search_field"
android:hint="@string/title_hint" />
<Button <!--
<ImageButton
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/action_search" android:background="@drawable/ic_clear_grey600_24dp"/>
android:id="@+id/myanimelist_search_button"/> -->
</LinearLayout> </LinearLayout>
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingTop="32dp"
android:paddingBottom="32dp"
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone"/>
<ListView <ListView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/myanimelist_search_results" android:id="@+id/myanimelist_search_results"
android:scrollbarStyle="outsideOverlay"
android:divider="@null"
android:dividerHeight="0dp"
android:clipToPadding="false"
android:choiceMode="singleChoice" android:choiceMode="singleChoice"
android:listSelector="@color/list_choice_pressed_bg_light"> android:listSelector="@color/list_choice_pressed_bg_light"
android:visibility="gone"/>
</ListView>
</LinearLayout> </LinearLayout>

View file

@ -141,6 +141,7 @@
<string name="on_hold">On hold</string> <string name="on_hold">On hold</string>
<string name="plan_to_read">Plan to read</string> <string name="plan_to_read">Plan to read</string>
<string name="score">Score</string> <string name="score">Score</string>
<string name="title_hint">Title…</string>
<!-- Reader activity --> <!-- Reader activity -->
<string name="downloading">Downloading…</string> <string name="downloading">Downloading…</string>