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 0f57f3432..e0bfbcc0f 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 d1e6c1721..2f8c7dbbf 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 714ec92c3..441d2cd48 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 c2d90f3c5..e06db7a66 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 c9ca4cb38..a693a9bb0 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 000000000..0bf2d1466 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_clear_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-ldpi/ic_clear_grey600_24dp.png b/app/src/main/res/drawable-ldpi/ic_clear_grey600_24dp.png new file mode 100644 index 000000000..856b3646b Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_clear_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_clear_grey600_24dp.png b/app/src/main/res/drawable-mdpi/ic_clear_grey600_24dp.png new file mode 100644 index 000000000..9ec1dd4fe Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_clear_grey600_24dp.png differ 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 000000000..14a842717 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_clear_grey600_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_clear_grey600_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_clear_grey600_24dp.png new file mode 100644 index 000000000..8ecda2471 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_clear_grey600_24dp.png differ 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 000000000..6f9e499f4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_clear_grey600_24dp.png differ diff --git a/app/src/main/res/layout/dialog_myanimelist_search.xml b/app/src/main/res/layout/dialog_myanimelist_search.xml index 70d6b2133..fe5e2f228 100644 --- a/app/src/main/res/layout/dialog_myanimelist_search.xml +++ b/app/src/main/res/layout/dialog_myanimelist_search.xml @@ -1,36 +1,54 @@ - + + 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" /> -