From f9a97631f2dbb7cfbd8aa621ab4d4aa3435ee35e Mon Sep 17 00:00:00 2001 From: inorichi Date: Thu, 31 Dec 2015 19:15:24 +0100 Subject: [PATCH] Store total chapters from MAL and automatically set as completed if it's the last chapter. Other minor changes --- .../data/mangasync/services/MyAnimeList.java | 6 + .../mangafeed/ui/library/LibraryFragment.java | 7 +- .../MyAnimeListDialogFragment.java | 127 ++++++++++++++---- .../myanimelist/MyAnimeListFragment.java | 33 +++-- .../myanimelist/MyAnimeListPresenter.java | 12 +- .../drawable-hdpi/ic_clear_grey600_24dp.png | Bin 0 -> 254 bytes .../drawable-ldpi/ic_clear_grey600_24dp.png | Bin 0 -> 231 bytes .../drawable-mdpi/ic_clear_grey600_24dp.png | Bin 0 -> 191 bytes .../drawable-xhdpi/ic_clear_grey600_24dp.png | Bin 0 -> 324 bytes .../drawable-xxhdpi/ic_clear_grey600_24dp.png | Bin 0 -> 411 bytes .../ic_clear_grey600_24dp.png | Bin 0 -> 565 bytes .../res/layout/dialog_myanimelist_search.xml | 46 +++++-- app/src/main/res/values/strings.xml | 1 + 13 files changed, 181 insertions(+), 51 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_clear_grey600_24dp.png create mode 100644 app/src/main/res/drawable-ldpi/ic_clear_grey600_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_clear_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_clear_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_clear_grey600_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_clear_grey600_24dp.png diff --git a/app/src/main/java/eu/kanade/mangafeed/data/mangasync/services/MyAnimeList.java b/app/src/main/java/eu/kanade/mangafeed/data/mangasync/services/MyAnimeList.java index 0f57f3432d..e0bfbcc0f8 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/mangasync/services/MyAnimeList.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/mangasync/services/MyAnimeList.java @@ -110,6 +110,7 @@ public class MyAnimeList extends MangaSyncService { MangaSync manga = MangaSync.create(this); manga.title = entry.select("title").first().text(); manga.remote_id = Integer.parseInt(entry.select("id").first().text()); + manga.total_chapters = Integer.parseInt(entry.select("chapters").first().text()); return manga; }) .toList(); @@ -141,6 +142,8 @@ public class MyAnimeList extends MangaSyncService { // MAL doesn't support score with decimals manga.score = Integer.parseInt( entry.select("my_score").first().text()); + manga.total_chapters = Integer.parseInt( + entry.select("series_chapters").first().text()); return manga; }) .toList(); @@ -155,6 +158,9 @@ public class MyAnimeList extends MangaSyncService { public Observable update(MangaSync manga) { try { + if (manga.total_chapters != 0 && manga.last_chapter_read == manga.total_chapters) { + manga.status = COMPLETED; + } RequestBody payload = getMangaPostPayload(manga); return networkService.postData(getUpdateUrl(manga), payload, headers); } catch (IOException e) { diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java index d1e6c17215..2f8c7dbbf9 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryFragment.java @@ -81,10 +81,15 @@ public class LibraryFragment extends BaseRxFragment @Override public void onDestroyView() { appBar.removeView(tabs); - EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class); super.onDestroyView(); } + @Override + public void onPause() { + EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class); + super.onPause(); + } + @Override public void onSaveInstanceState(Bundle bundle) { activeCategory = viewPager.getCurrentItem(); diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListDialogFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListDialogFragment.java index 714ec92c3f..441d2cd485 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListDialogFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListDialogFragment.java @@ -2,21 +2,29 @@ package eu.kanade.mangafeed.ui.manga.myanimelist; import android.app.Dialog; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.view.LayoutInflater; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; import android.view.View; -import android.widget.Button; import android.widget.EditText; import android.widget.ListView; +import android.widget.ProgressBar; import android.widget.TextView; +import com.afollestad.materialdialogs.MaterialDialog; + import java.util.List; +import java.util.concurrent.TimeUnit; import butterknife.Bind; import butterknife.ButterKnife; import eu.kanade.mangafeed.R; 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.ItemViewHolder; import uk.co.ribot.easyadapter.PositionInfo; @@ -26,61 +34,108 @@ import uk.co.ribot.easyadapter.annotations.ViewId; public class MyAnimeListDialogFragment extends DialogFragment { @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.progress) ProgressBar progressBar; private EasyAdapter adapter; - private MyAnimeListFragment fragment; - private MyAnimeListPresenter presenter; private MangaSync selectedItem; - public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) { - MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment(); - dialog.fragment = parentFragment; - dialog.presenter = parentFragment.getPresenter(); - return dialog; + private Subscription searchSubscription; + + public static MyAnimeListDialogFragment newInstance() { + return new MyAnimeListDialogFragment(); } + @NonNull @Override public Dialog onCreateDialog(Bundle savedState) { - // Inflate and bind view - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.dialog_myanimelist_search, null); - ButterKnife.bind(this, view); + MaterialDialog dialog = new MaterialDialog.Builder(getActivity()) + .customView(R.layout.dialog_myanimelist_search, false) + .positiveText(R.string.button_ok) + .negativeText(R.string.button_cancel) + .onPositive((dialog1, which) -> onPositiveButtonClick()) + .build(); - // Build dialog - 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) -> {}); + ButterKnife.bind(this, dialog.getView()); // Create adapter adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class); searchResults.setAdapter(adapter); // Set listeners - searchButton.setOnClickListener(v -> - presenter.searchManga(searchText.getText().toString())); - searchResults.setOnItemClickListener((parent, viewList, position, id) -> selectedItem = adapter.getItem(position)); // Do an initial search based on the manga's title - presenter.searchManga(presenter.manga.title); - return builder.create(); + if (savedState == null) { + String title = getPresenter().manga.title; + searchText.append(title); + search(title); + } + + return dialog; + } + + @Override + public void onResume() { + super.onResume(); + PublishSubject 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() { if (adapter != null && selectedItem != null) { - presenter.registerManga(selectedItem); + getPresenter().registerManga(selectedItem); } } - public void setResults(List 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 results) { selectedItem = null; + progressBar.setVisibility(View.GONE); + searchResults.setVisibility(View.VISIBLE); 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) public static class ResultViewHolder extends ItemViewHolder { @@ -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) { + + } + } + } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListFragment.java index c2d90f3c5a..e06db7a666 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListFragment.java @@ -33,6 +33,8 @@ public class MyAnimeListFragment extends BaseRxFragment { private DecimalFormat decimalFormat = new DecimalFormat("#.##"); + private final static String SEARCH_FRAGMENT_TAG = "mal_search"; + public static MyAnimeListFragment newInstance() { return new MyAnimeListFragment(); } @@ -53,21 +55,36 @@ public class MyAnimeListFragment extends BaseRxFragment { } } - private void showSearchDialog() { - if (dialog == null) - dialog = MyAnimeListDialogFragment.newInstance(this); + public void setSearchResults(List results) { + findSearchFragmentIfNeeded(); - dialog.show(getActivity().getSupportFragmentManager(), "search"); + if (dialog != null) { + dialog.onSearchResults(results); + } } - public void onSearchResults(List results) { - if (dialog != null) - dialog.setResults(results); + public void setSearchResultsError() { + findSearchFragmentIfNeeded(); + + if (dialog != null) { + dialog.onSearchResultsError(); + } + } + + private void findSearchFragmentIfNeeded() { + if (dialog == null) { + dialog = (MyAnimeListDialogFragment) getChildFragmentManager() + .findFragmentByTag(SEARCH_FRAGMENT_TAG); + } } @OnClick(R.id.myanimelist_title_layout) void onTitleClick() { - showSearchDialog(); + if (dialog == null) + dialog = MyAnimeListDialogFragment.newInstance(); + + getPresenter().restartSearch(); + dialog.show(getChildFragmentManager(), SEARCH_FRAGMENT_TAG); } @OnClick(R.id.myanimelist_status_layout) diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListPresenter.java index c9ca4cb382..a693a9bb05 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/myanimelist/MyAnimeListPresenter.java @@ -2,6 +2,7 @@ package eu.kanade.mangafeed.ui.manga.myanimelist; import android.content.Context; import android.os.Bundle; +import android.text.TextUtils; import javax.inject.Inject; @@ -55,9 +56,10 @@ public class MyAnimeListPresenter extends BasePresenter { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()), (view, results) -> { - view.onSearchResults(results); + view.setSearchResults(results); }, (view, error) -> { Timber.e(error.getMessage()); + view.setSearchResultsError(); }); } @@ -100,10 +102,18 @@ public class MyAnimeListPresenter extends BasePresenter { } public void searchManga(String query) { + if (TextUtils.isEmpty(query) || query.equals(this.query)) + return; + this.query = query; start(GET_SEARCH_RESULTS); } + public void restartSearch() { + this.query = null; + stop(GET_SEARCH_RESULTS); + } + public void registerManga(MangaSync manga) { manga.manga_id = this.manga.id; add(myAnimeList.bind(manga) diff --git a/app/src/main/res/drawable-hdpi/ic_clear_grey600_24dp.png b/app/src/main/res/drawable-hdpi/ic_clear_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..0bf2d14669a0248b198c5cc8a94e2f87b4b43d44 GIT binary patch literal 254 zcmVU#FWSReh9SF(&Cfyzi;;Uf#bpfP?|R;mB;9X z10X$%A+_S7ND61u#rB~B->juQv##3vftUaFr~M|6Om`MPS}IQTXgQu&X%Q~loCIG6#O6ULp literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_clear_grey600_24dp.png b/app/src/main/res/drawable-xhdpi/ic_clear_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..14a842717cd7bf3ba4692f93b15668a2a6988eab GIT binary patch literal 324 zcmV-K0lWT*P)I6yj$5p!N~DR~DN5zPB`QJAQw z{N0uJZ&N=3067GC> z=0F6JFQFMl5}-lFk6rS0000Th<5NMAfF7=_N(&2y2JHOrN)fWWcb-}r4>Z!$6-|Hw6rcbFC_n)U z&=@<}OQH^1Nh@nF&`z#0$cZ4Wq#H9_EhH;vAV?3+a3^h8(369bo}341%YhCr$)-3L zlHNH}>^V>x2{>uaQJ=A%6ej^3+gFB>AddAON^Nx9Q#dOMuIsdrNd4lIAyiW zMxr>S#Z@Pfobqa)W(RgJ2htp*{rFCD;9&hwp5($o8?+qBg@bpD^XK8hVOrQ*PzRDH2O9?n zkgdTWN!}cqw9HUUkd~U!VbWqVx-t$BAiP(GNXv0Rl9uvF7R@=Sj+SQ0u-PC1t>s{aRc#Jnor|F3|;^L002ovPDHLk FV1mQOuvGv6 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_clear_grey600_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_clear_grey600_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..6f9e499f47bc9b5eda9b317127e145d3a9789a0d GIT binary patch literal 565 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%&M7!1%}0#WAGf*4tZwL5B=PS`*C{ zlo~EbKE3VTy#p7oN0k~{>|oG2%&g>l()XNa;xnIn6$<~&nN2un-h8v|xDNv(i+}?% z;l-#`y;0rECs%uSGPBn24RdRSIkx8hF3)>AkF#RK`MOE6jRhy}_m|5n>dO0CJloAV z@6USs$qJmyfBHH7G0Fe0<|sI8^Pj&Fj~UN53qKW_bzrxh(LUx1r?P$D!#TVep8THA zY{8^r|J1WbvEkF@Yfe8~j@23bT-m+T#z~_-u*h_lU&FKKI?FF}JovNcZ^L|s^XKng z_`z}d;2&SVx_^B-^BhjP=V(6WSW3oH-A19GrBx@KABVX)5;d3pDs>$`_gwi zDH?ndKbIOOwlKx6HNb4XgT`Eb^(9aAH}_{WwrGA@*pm6Fv1R3_#Fm$z99uL$E4KVt z8OQlE@emjPiZ#xE)=Rr)JYGNV=epUYEq{ugUhlMgzSr=&;3t31weKIz|9>go{e- - + + android:layout_height="?attr/actionBarSize" + android:gravity="center" + android:paddingLeft="@dimen/margin_left" + android:paddingRight="@dimen/margin_right" + android:orientation="horizontal"> + android:id="@+id/myanimelist_search_field" + android:hint="@string/title_hint" /> -