From 50d6632d0e2211e81bc7efd2fd3b0126671607b2 Mon Sep 17 00:00:00 2001 From: inorichi Date: Sun, 20 Dec 2015 20:10:04 +0100 Subject: [PATCH] Allow to set status, score and last chapter read in MAL. Other minor changes --- app/src/main/AndroidManifest.xml | 3 +- .../data/mangasync/services/MyAnimeList.java | 14 +- .../ui/library/LibraryPresenter.java | 1 - .../myanimelist/MyAnimeListFragment.java | 129 ++++++++++++----- .../myanimelist/MyAnimeListPresenter.java | 65 ++++++--- .../mangafeed/widget/MinMaxNumberPicker.java | 36 +++++ .../main/res/layout/activity_manga_detail.xml | 3 +- .../res/layout/card_myanimelist_personal.xml | 133 ++++++++++++++++++ .../layout/dialog_myanimelist_chapters.xml | 16 +++ .../res/layout/dialog_myanimelist_score.xml | 16 +++ .../res/layout/fragment_manga_chapters.xml | 1 + .../main/res/layout/fragment_myanimelist.xml | 83 ++--------- app/src/main/res/menu/myanimelist.xml | 10 -- app/src/main/res/values/attrs.xml | 5 + app/src/main/res/values/strings.xml | 8 ++ 15 files changed, 370 insertions(+), 153 deletions(-) create mode 100644 app/src/main/java/eu/kanade/mangafeed/widget/MinMaxNumberPicker.java create mode 100644 app/src/main/res/layout/card_myanimelist_personal.xml create mode 100644 app/src/main/res/layout/dialog_myanimelist_chapters.xml create mode 100644 app/src/main/res/layout/dialog_myanimelist_score.xml delete mode 100644 app/src/main/res/menu/myanimelist.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e3b445d48c..65b2a9f11e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,8 +14,7 @@ android:label="@string/app_name" android:theme="@style/AppTheme" > + android:name=".ui.main.MainActivity"> 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 8b4fbca81a..0f57f3432d 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 @@ -20,6 +20,7 @@ import java.util.List; import javax.inject.Inject; import eu.kanade.mangafeed.App; +import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.data.database.models.MangaSync; import eu.kanade.mangafeed.data.mangasync.MangaSyncManager; import eu.kanade.mangafeed.data.mangasync.base.MangaSyncService; @@ -52,7 +53,10 @@ public class MyAnimeList extends MangaSyncService { public static final int DEFAULT_STATUS = READING; public static final int DEFAULT_SCORE = 0; + private Context context; + public MyAnimeList(Context context) { + this.context = context; App.get(context).getComponent().inject(this); String username = preferences.getMangaSyncUsername(this); @@ -228,15 +232,15 @@ public class MyAnimeList extends MangaSyncService { public String getStatus(int status) { switch (status) { case READING: - return "Reading"; + return context.getString(R.string.reading); case COMPLETED: - return "Completed"; + return context.getString(R.string.completed); case ON_HOLD: - return "On hold"; + return context.getString(R.string.on_hold); case DROPPED: - return "Dropped"; + return context.getString(R.string.dropped); case PLAN_TO_READ: - return "Plan to read"; + return context.getString(R.string.plan_to_read); } return ""; } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java index a1c5664f7f..6c58d8daff 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryPresenter.java @@ -29,7 +29,6 @@ public class LibraryPresenter extends BasePresenter { restartableLatestCache(GET_MANGAS, () -> db.getFavoriteMangasWithUnread().createObservable() - .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()), LibraryFragment::onNextMangas); 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 d405e7d8e6..274afaeb20 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 @@ -1,21 +1,21 @@ package eu.kanade.mangafeed.ui.manga.myanimelist; +import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; +import android.widget.NumberPicker; import android.widget.TextView; +import com.afollestad.materialdialogs.MaterialDialog; + import java.text.DecimalFormat; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; +import butterknife.OnClick; import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.data.database.models.MangaSync; import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; @@ -25,10 +25,9 @@ import nucleus.factory.RequiresPresenter; public class MyAnimeListFragment extends BaseRxFragment { @Bind(R.id.myanimelist_title) TextView title; - @Bind(R.id.last_chapter_read) EditText lastChapterRead; - @Bind(R.id.score) TextView score; - @Bind(R.id.status) TextView status; - @Bind(R.id.update_button) Button updateButton; + @Bind(R.id.myanimelist_chapters) TextView chapters; + @Bind(R.id.myanimelist_score) TextView score; + @Bind(R.id.myanimelist_status) TextView status; private MyAnimeListDialogFragment dialog; @@ -38,43 +37,17 @@ public class MyAnimeListFragment extends BaseRxFragment { return new MyAnimeListFragment(); } - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - setHasOptionsMenu(true); - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_myanimelist, container, false); ButterKnife.bind(this, view); - - updateButton.setOnClickListener(v -> getPresenter().updateLastChapter( - Integer.parseInt(lastChapterRead.getText().toString()))); - return view; } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.myanimelist, menu); - super.onCreateOptionsMenu(menu, inflater); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.myanimelist_edit: - showSearchDialog(); - return true; - } - return super.onOptionsItemSelected(item); - } - public void setMangaSync(MangaSync mangaSync) { title.setText(mangaSync.title); - lastChapterRead.setText(mangaSync.last_chapter_read + ""); - score.setText(decimalFormat.format(mangaSync.score)); + chapters.setText(mangaSync.last_chapter_read + ""); + score.setText(mangaSync.score == 0 ? "-" : decimalFormat.format(mangaSync.score)); status.setText(getPresenter().myAnimeList.getStatus(mangaSync.status)); } @@ -89,4 +62,86 @@ public class MyAnimeListFragment extends BaseRxFragment { if (dialog != null) dialog.setResults(results); } + + @OnClick(R.id.myanimelist_title_layout) + void onTitleClick() { + showSearchDialog(); + } + + @OnClick(R.id.myanimelist_status_layout) + void onStatusClick() { + if (getPresenter().mangaSync == null) + return; + + Context ctx = getActivity(); + new MaterialDialog.Builder(ctx) + .title(R.string.status) + .items(getPresenter().getAllStatus(ctx)) + .itemsCallbackSingleChoice(getPresenter().getIndexFromStatus(), + (materialDialog, view, i, charSequence) -> { + getPresenter().setStatus(i); + status.setText("..."); + return true; + }) + .show(); + } + + @OnClick(R.id.myanimelist_chapters_layout) + void onChaptersClick() { + if (getPresenter().mangaSync == null) + return; + + MaterialDialog dialog = new MaterialDialog.Builder(getActivity()) + .title(R.string.chapters) + .customView(R.layout.dialog_myanimelist_chapters, false) + .positiveText(R.string.button_ok) + .negativeText(R.string.button_cancel) + .onPositive((materialDialog, dialogAction) -> { + View view = materialDialog.getCustomView(); + if (view != null) { + NumberPicker np = (NumberPicker) view.findViewById(R.id.chapters_picker); + getPresenter().setLastChapterRead(np.getValue()); + chapters.setText("..."); + } + }) + .show(); + + View view = dialog.getCustomView(); + if (view != null) { + NumberPicker np = (NumberPicker) view.findViewById(R.id.chapters_picker); + // Set initial value + np.setValue(getPresenter().mangaSync.last_chapter_read); + // Don't allow to go from 0 to 9999 + np.setWrapSelectorWheel(false); + } + } + + @OnClick(R.id.myanimelist_score_layout) + void onScoreClick() { + if (getPresenter().mangaSync == null) + return; + + MaterialDialog dialog = new MaterialDialog.Builder(getActivity()) + .title(R.string.score) + .customView(R.layout.dialog_myanimelist_score, false) + .positiveText(R.string.button_ok) + .negativeText(R.string.button_cancel) + .onPositive((materialDialog, dialogAction) -> { + View view = materialDialog.getCustomView(); + if (view != null) { + NumberPicker np = (NumberPicker) view.findViewById(R.id.score_picker); + getPresenter().setScore(np.getValue()); + score.setText("..."); + } + }) + .show(); + + View view = dialog.getCustomView(); + if (view != null) { + NumberPicker np = (NumberPicker) view.findViewById(R.id.score_picker); + // Set initial value + np.setValue((int) getPresenter().mangaSync.score); + } + } + } 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 79d6a7a553..d6eaf297a7 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 @@ -1,19 +1,20 @@ package eu.kanade.mangafeed.ui.manga.myanimelist; +import android.content.Context; import android.os.Bundle; import javax.inject.Inject; +import eu.kanade.mangafeed.R; +import eu.kanade.mangafeed.data.database.DatabaseHelper; +import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.database.models.MangaSync; import eu.kanade.mangafeed.data.mangasync.MangaSyncManager; import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList; -import eu.kanade.mangafeed.data.database.DatabaseHelper; -import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.ToastUtil; import rx.Observable; -import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; import timber.log.Timber; @@ -25,13 +26,11 @@ public class MyAnimeListPresenter extends BasePresenter { protected MyAnimeList myAnimeList; protected Manga manga; - private MangaSync mangaSync; + protected MangaSync mangaSync; private String query; - private Subscription updateSubscription; - - private static final int GET_CHAPTER_SYNC = 1; + private static final int GET_MANGA_SYNC = 1; private static final int GET_SEARCH_RESULTS = 2; @Override @@ -44,7 +43,7 @@ public class MyAnimeListPresenter extends BasePresenter { myAnimeList = syncManager.getMyAnimeList(); - restartableLatestCache(GET_CHAPTER_SYNC, + restartableLatestCache(GET_MANGA_SYNC, () -> db.getMangaSync(manga, myAnimeList).createObservable() .flatMap(Observable::from) .doOnNext(mangaSync -> this.mangaSync = mangaSync) @@ -65,7 +64,7 @@ public class MyAnimeListPresenter extends BasePresenter { } private void onProcessRestart() { - stop(GET_CHAPTER_SYNC); + stop(GET_MANGA_SYNC); stop(GET_SEARCH_RESULTS); } @@ -84,22 +83,19 @@ public class MyAnimeListPresenter extends BasePresenter { @EventBusHook public void onEventMainThread(Manga manga) { this.manga = manga; - start(GET_CHAPTER_SYNC); + start(GET_MANGA_SYNC); } - public void updateLastChapter(int chapterNumber) { - if (updateSubscription != null) - remove(updateSubscription); - - mangaSync.last_chapter_read = chapterNumber; - - add(updateSubscription = myAnimeList.update(mangaSync) + private void updateRemote() { + add(myAnimeList.update(mangaSync) .flatMap(response -> db.insertMangaSync(mangaSync).createObservable()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(response -> {}, + .subscribe(next -> {}, error -> { Timber.e(error.getMessage()); + // Restart on error to set old values + start(GET_MANGA_SYNC); } )); } @@ -114,15 +110,42 @@ public class MyAnimeListPresenter extends BasePresenter { add(myAnimeList.bind(manga) .flatMap(response -> { if (response.isSuccessful()) { - return Observable.just(manga); + return db.insertMangaSync(manga).createObservable(); } - return Observable.error(new Exception("Could not add manga")); + return Observable.error(new Exception("Could not bind manga")); }) - .flatMap(manga2 -> db.insertMangaSync(manga2).createObservable()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(manga2 -> {}, error -> ToastUtil.showShort(getContext(), error.getMessage()))); } + public String[] getAllStatus(Context context) { + return new String[] { + context.getString(R.string.reading), + context.getString(R.string.completed), + context.getString(R.string.on_hold), + context.getString(R.string.dropped), + context.getString(R.string.plan_to_read) + }; + } + + public int getIndexFromStatus() { + return mangaSync.status == 6 ? 4 : mangaSync.status - 1; + } + + public void setStatus(int index) { + mangaSync.status = index == 4 ? 6 : index + 1; + updateRemote(); + } + + public void setScore(int score) { + mangaSync.score = score; + updateRemote(); + } + + public void setLastChapterRead(int chapterNumber) { + mangaSync.last_chapter_read = chapterNumber; + updateRemote(); + } } diff --git a/app/src/main/java/eu/kanade/mangafeed/widget/MinMaxNumberPicker.java b/app/src/main/java/eu/kanade/mangafeed/widget/MinMaxNumberPicker.java new file mode 100644 index 0000000000..2536ad4dfd --- /dev/null +++ b/app/src/main/java/eu/kanade/mangafeed/widget/MinMaxNumberPicker.java @@ -0,0 +1,36 @@ +package eu.kanade.mangafeed.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.widget.NumberPicker; + +import eu.kanade.mangafeed.R; + +public class MinMaxNumberPicker extends NumberPicker{ + + public MinMaxNumberPicker(Context context) { + super(context); + } + + public MinMaxNumberPicker(Context context, AttributeSet attrs) { + super(context, attrs); + processAttributeSet(context, attrs); + } + + public MinMaxNumberPicker(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + processAttributeSet(context, attrs); + } + + private void processAttributeSet(Context context, AttributeSet attrs) { + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MinMaxNumberPicker, 0, 0); + try { + setMinValue(ta.getInt(R.styleable.MinMaxNumberPicker_min, 0)); + setMaxValue(ta.getInt(R.styleable.MinMaxNumberPicker_max, 0)); + } finally { + ta.recycle(); + } + } +} + diff --git a/app/src/main/res/layout/activity_manga_detail.xml b/app/src/main/res/layout/activity_manga_detail.xml index d4a5aadfce..cd094212df 100644 --- a/app/src/main/res/layout/activity_manga_detail.xml +++ b/app/src/main/res/layout/activity_manga_detail.xml @@ -29,7 +29,6 @@ android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="0px" - android:layout_weight="1" - android:background="@color/white" /> + android:layout_weight="1"/> \ No newline at end of file diff --git a/app/src/main/res/layout/card_myanimelist_personal.xml b/app/src/main/res/layout/card_myanimelist_personal.xml new file mode 100644 index 0000000000..e7b93b9585 --- /dev/null +++ b/app/src/main/res/layout/card_myanimelist_personal.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_myanimelist_chapters.xml b/app/src/main/res/layout/dialog_myanimelist_chapters.xml new file mode 100644 index 0000000000..5b3a756527 --- /dev/null +++ b/app/src/main/res/layout/dialog_myanimelist_chapters.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_myanimelist_score.xml b/app/src/main/res/layout/dialog_myanimelist_score.xml new file mode 100644 index 0000000000..e7d7795246 --- /dev/null +++ b/app/src/main/res/layout/dialog_myanimelist_score.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_manga_chapters.xml b/app/src/main/res/layout/fragment_manga_chapters.xml index 3012b3afb9..a0ca1cf342 100644 --- a/app/src/main/res/layout/fragment_manga_chapters.xml +++ b/app/src/main/res/layout/fragment_manga_chapters.xml @@ -19,6 +19,7 @@ android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:descendantFocusability="blocksDescendants" + android:background="@color/white" tools:listitem="@layout/item_chapter"> diff --git a/app/src/main/res/layout/fragment_myanimelist.xml b/app/src/main/res/layout/fragment_myanimelist.xml index 311a08880d..1409e0803b 100644 --- a/app/src/main/res/layout/fragment_myanimelist.xml +++ b/app/src/main/res/layout/fragment_myanimelist.xml @@ -1,84 +1,17 @@ + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="10dp"> - - + - - - - - - - - - - -