Merge pull request #150 from NoodleMage/comments

Improved comments
This commit is contained in:
inorichi 2016-02-16 20:41:45 +01:00
commit 5ac7f7057a
2 changed files with 173 additions and 40 deletions

View file

@ -21,82 +21,163 @@ import eu.kanade.tachiyomi.data.source.base.Source;
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment; import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
import nucleus.factory.RequiresPresenter; import nucleus.factory.RequiresPresenter;
/**
* Fragment that shows manga information.
* Uses R.layout.fragment_manga_info.
* UI related actions should be called from here.
*/
@RequiresPresenter(MangaInfoPresenter.class) @RequiresPresenter(MangaInfoPresenter.class)
public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> { public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
/**
* SwipeRefreshLayout showing refresh status
*/
@Bind(R.id.swipe_refresh) SwipeRefreshLayout swipeRefresh; @Bind(R.id.swipe_refresh) SwipeRefreshLayout swipeRefresh;
/**
* TextView containing artist information.
*/
@Bind(R.id.manga_artist) TextView artist; @Bind(R.id.manga_artist) TextView artist;
/**
* TextView containing author information.
*/
@Bind(R.id.manga_author) TextView author; @Bind(R.id.manga_author) TextView author;
/**
* TextView containing chapter count.
*/
@Bind(R.id.manga_chapters) TextView chapterCount; @Bind(R.id.manga_chapters) TextView chapterCount;
/**
* TextView containing genres.
*/
@Bind(R.id.manga_genres) TextView genres; @Bind(R.id.manga_genres) TextView genres;
/**
* TextView containing status (ongoing, finished).
*/
@Bind(R.id.manga_status) TextView status; @Bind(R.id.manga_status) TextView status;
/**
* TextView containing source.
*/
@Bind(R.id.manga_source) TextView source; @Bind(R.id.manga_source) TextView source;
/**
* TextView containing manga summary.
*/
@Bind(R.id.manga_summary) TextView description; @Bind(R.id.manga_summary) TextView description;
/**
* ImageView of cover.
*/
@Bind(R.id.manga_cover) ImageView cover; @Bind(R.id.manga_cover) ImageView cover;
/**
* ImageView containing manga cover shown as blurred backdrop.
*/
@Bind(R.id.backdrop) ImageView backdrop; @Bind(R.id.backdrop) ImageView backdrop;
/**
* FAB anchored to bottom of top view used to (add / remove) manga (to / from) library.
*/
@Bind(R.id.fab_favorite) FloatingActionButton fabFavorite; @Bind(R.id.fab_favorite) FloatingActionButton fabFavorite;
/**
* Create new instance of MangaInfoFragment.
*
* @return MangaInfoFragment.
*/
public static MangaInfoFragment newInstance() { public static MangaInfoFragment newInstance() {
return new MangaInfoFragment(); return new MangaInfoFragment();
} }
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setHasOptionsMenu(true);
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
// Inflate the layout for this fragment // Inflate the layout for this fragment.
View view = inflater.inflate(R.layout.fragment_manga_info, container, false); View view = inflater.inflate(R.layout.fragment_manga_info, container, false);
// Bind layout objects.
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
// Set onclickListener to toggle favorite when FAB clicked.
fabFavorite.setOnClickListener(v -> getPresenter().toggleFavorite()); fabFavorite.setOnClickListener(v -> getPresenter().toggleFavorite());
// Set SwipeRefresh to refresh manga data.
swipeRefresh.setOnRefreshListener(this::fetchMangaFromSource); swipeRefresh.setOnRefreshListener(this::fetchMangaFromSource);
return view; return view;
} }
/**
* Check if manga is initialized.
* If true update view with manga information,
* if false fetch manga information
*
* @param manga manga object containing information about manga.
* @param source the source of the manga.
*/
public void onNextManga(Manga manga, Source source) { public void onNextManga(Manga manga, Source source) {
if (manga.initialized) { if (manga.initialized) {
// Update view.
setMangaInfo(manga, source); setMangaInfo(manga, source);
} else { } else {
// Initialize manga // Initialize manga.
fetchMangaFromSource(); fetchMangaFromSource();
} }
} }
/** /**
* Set the info of the manga * Update the view with manga information.
* *
* @param manga manga object containing information about manga * @param manga manga object containing information about manga.
* @param mangaSource the source of the manga * @param mangaSource the source of the manga.
*/ */
private void setMangaInfo(Manga manga, Source mangaSource) { private void setMangaInfo(Manga manga, Source mangaSource) {
// Update artist TextView.
artist.setText(manga.artist); artist.setText(manga.artist);
// Update author TextView.
author.setText(manga.author); author.setText(manga.author);
// If manga source is known update source TextView.
if (mangaSource != null) { if (mangaSource != null) {
source.setText(mangaSource.getName()); source.setText(mangaSource.getName());
} }
// Update genres TextView.
genres.setText(manga.genre); genres.setText(manga.genre);
// Update status TextView.
status.setText(manga.getStatus(getActivity())); status.setText(manga.getStatus(getActivity()));
// Update description TextView.
description.setText(manga.description); description.setText(manga.description);
// Set the favorite drawable to the correct one.
setFavoriteDrawable(manga.favorite); setFavoriteDrawable(manga.favorite);
// Initialize CoverCache and Glide headers to retrieve cover information.
CoverCache coverCache = getPresenter().coverCache; CoverCache coverCache = getPresenter().coverCache;
LazyHeaders headers = getPresenter().source.getGlideHeaders(); LazyHeaders headers = getPresenter().source.getGlideHeaders();
if (manga.thumbnail_url != null && cover.getDrawable() == null) {
// Check if thumbnail_url is given.
if (manga.thumbnail_url != null) {
// Check if cover is already drawn.
if (cover.getDrawable() == null) {
// If manga is in library then (download / save) (from / to) local cache if available,
// else download from network.
if (manga.favorite) { if (manga.favorite) {
coverCache.saveOrLoadFromCache(cover, manga.thumbnail_url, headers); coverCache.saveOrLoadFromCache(cover, manga.thumbnail_url, headers);
} else { } else {
coverCache.loadFromNetwork(cover, manga.thumbnail_url, headers); coverCache.loadFromNetwork(cover, manga.thumbnail_url, headers);
} }
} }
if (manga.thumbnail_url != null && backdrop.getDrawable() == null) { // Check if backdrop is already drawn.
if (backdrop.getDrawable() == null) {
// If manga is in library then (download / save) (from / to) local cache if available,
// else download from network.
if (manga.favorite) { if (manga.favorite) {
coverCache.saveOrLoadFromCache(backdrop, manga.thumbnail_url, headers); coverCache.saveOrLoadFromCache(backdrop, manga.thumbnail_url, headers);
} else { } else {
@ -104,31 +185,59 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
} }
} }
} }
}
/**
* Update chapter count TextView.
*
* @param count number of chapters.
*/
public void setChapterCount(int count) { public void setChapterCount(int count) {
chapterCount.setText(String.valueOf(count)); chapterCount.setText(String.valueOf(count));
} }
/**
* Update FAB with correct drawable.
*
* @param isFavorite determines if manga is favorite or not.
*/
private void setFavoriteDrawable(boolean isFavorite) { private void setFavoriteDrawable(boolean isFavorite) {
// Set the Favorite drawable to the correct one.
// Border drawable if false, filled drawable if true.
fabFavorite.setImageDrawable(ContextCompat.getDrawable(getContext(), isFavorite ? fabFavorite.setImageDrawable(ContextCompat.getDrawable(getContext(), isFavorite ?
R.drawable.ic_bookmark_white_24dp : R.drawable.ic_bookmark_white_24dp :
R.drawable.ic_bookmark_border_white_24dp)); R.drawable.ic_bookmark_border_white_24dp));
} }
/**
* Start fetching manga information from source.
*/
private void fetchMangaFromSource() { private void fetchMangaFromSource() {
setRefreshing(true); setRefreshing(true);
// Call presenter and start fetching manga information
getPresenter().fetchMangaFromSource(); getPresenter().fetchMangaFromSource();
} }
/**
* Update swipeRefresh to stop showing refresh in progress spinner.
*/
public void onFetchMangaDone() { public void onFetchMangaDone() {
setRefreshing(false); setRefreshing(false);
} }
/**
* Update swipeRefresh to start showing refresh in progress spinner.
*/
public void onFetchMangaError() { public void onFetchMangaError() {
setRefreshing(false); setRefreshing(false);
} }
/**
* Set swipeRefresh status.
*
* @param value status of manga fetch.
*/
private void setRefreshing(boolean value) { private void setRefreshing(boolean value) {
swipeRefresh.setRefreshing(value); swipeRefresh.setRefreshing(value);
} }

View file

@ -19,42 +19,55 @@ import rx.Observable;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
/**
* Presenter of MangaInfoFragment.
* Contains information and data for fragment.
* Observable updates should be called from here.
*/
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> { public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
/** /**
* The id of the restartable. * The id of the restartable.
*/ */
private static final int GET_MANGA = 1; private static final int GET_MANGA = 1;
/** /**
* The id of the restartable. * The id of the restartable.
*/ */
private static final int GET_CHAPTER_COUNT = 2; private static final int GET_CHAPTER_COUNT = 2;
/** /**
* The id of the restartable. * The id of the restartable.
*/ */
private static final int FETCH_MANGA_INFO = 3; private static final int FETCH_MANGA_INFO = 3;
/** /**
* Source information * Source information.
*/ */
protected Source source; protected Source source;
/** /**
* Used to connect to database * Used to connect to database.
*/ */
@Inject DatabaseHelper db; @Inject DatabaseHelper db;
/** /**
* Used to connect to different manga sources * Used to connect to different manga sources.
*/ */
@Inject SourceManager sourceManager; @Inject SourceManager sourceManager;
/** /**
* Used to connect to cache * Used to connect to cache.
*/ */
@Inject CoverCache coverCache; @Inject CoverCache coverCache;
/** /**
* Selected manga information * Selected manga information.
*/ */
private Manga manga; private Manga manga;
/** /**
* Count of chapters * Count of chapters.
*/ */
private int count = -1; private int count = -1;
@ -62,23 +75,23 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
protected void onCreate(Bundle savedState) { protected void onCreate(Bundle savedState) {
super.onCreate(savedState); super.onCreate(savedState);
// Notify the view a manga is available or has changed // Notify the view a manga is available or has changed.
startableLatestCache(GET_MANGA, startableLatestCache(GET_MANGA,
() -> Observable.just(manga), () -> Observable.just(manga),
(view, manga) -> view.onNextManga(manga, source)); (view, manga) -> view.onNextManga(manga, source));
// Update chapter count // Update chapter count.
startableLatestCache(GET_CHAPTER_COUNT, startableLatestCache(GET_CHAPTER_COUNT,
() -> Observable.just(count), () -> Observable.just(count),
MangaInfoFragment::setChapterCount); MangaInfoFragment::setChapterCount);
// Fetch manga info from source // Fetch manga info from source.
startableFirst(FETCH_MANGA_INFO, startableFirst(FETCH_MANGA_INFO,
this::fetchMangaObs, this::fetchMangaObs,
(view, manga) -> view.onFetchMangaDone(), (view, manga) -> view.onFetchMangaDone(),
(view, error) -> view.onFetchMangaError()); (view, error) -> view.onFetchMangaError());
// Listen for events // Listen for events.
registerForEvents(); registerForEvents();
} }
@ -99,12 +112,13 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
public void onEvent(ChapterCountEvent event) { public void onEvent(ChapterCountEvent event) {
if (count != event.getCount()) { if (count != event.getCount()) {
count = event.getCount(); count = event.getCount();
// Update chapter count
start(GET_CHAPTER_COUNT); start(GET_CHAPTER_COUNT);
} }
} }
/** /**
* Fetch manga info from source * Fetch manga information from source.
*/ */
public void fetchMangaFromSource() { public void fetchMangaFromSource() {
if (isUnsubscribed(FETCH_MANGA_INFO)) { if (isUnsubscribed(FETCH_MANGA_INFO)) {
@ -112,6 +126,11 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
} }
} }
/**
* Fetch manga information from source.
*
* @return manga information.
*/
private Observable<Manga> fetchMangaObs() { private Observable<Manga> fetchMangaObs() {
return source.pullMangaFromNetwork(manga.url) return source.pullMangaFromNetwork(manga.url)
.flatMap(networkManga -> { .flatMap(networkManga -> {
@ -124,6 +143,9 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
.doOnNext(manga -> refreshManga()); .doOnNext(manga -> refreshManga());
} }
/**
* Update favorite status of manga, (removes / adds) manga (to / from) library.
*/
public void toggleFavorite() { public void toggleFavorite() {
manga.favorite = !manga.favorite; manga.favorite = !manga.favorite;
onMangaFavoriteChange(manga.favorite); onMangaFavoriteChange(manga.favorite);
@ -132,7 +154,11 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
} }
/**
* (Removes / Saves) cover depending on favorite status.
*
* @param isFavorite determines if manga is favorite or not.
*/
private void onMangaFavoriteChange(boolean isFavorite) { private void onMangaFavoriteChange(boolean isFavorite) {
if (isFavorite) { if (isFavorite) {
coverCache.save(manga.thumbnail_url, source.getGlideHeaders()); coverCache.save(manga.thumbnail_url, source.getGlideHeaders());
@ -141,12 +167,10 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
} }
} }
public Manga getManga() { /**
return manga; * Refresh MangaInfo view.
} */
private void refreshManga() {
// Used to refresh the view
protected void refreshManga() {
start(GET_MANGA); start(GET_MANGA);
} }