com.rastating.droidbeard.fragments.ShowFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.rastating.droidbeard.fragments.ShowFragment.java

Source

/*
 DroidBeard - a free, open-source Android app for managing SickBeard
 Copyright (C) 2014-2015 Robert Carr
    
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see http://www.gnu.org/licenses/.
*/

package com.rastating.droidbeard.fragments;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.ActionMode;
import android.view.ContextThemeWrapper;
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.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.rastating.droidbeard.comparators.EpisodeComparator;
import com.rastating.droidbeard.R;
import com.rastating.droidbeard.entities.Episode;
import com.rastating.droidbeard.entities.Season;
import com.rastating.droidbeard.entities.TVShow;
import com.rastating.droidbeard.entities.TVShowSummary;
import com.rastating.droidbeard.net.ApiResponseListener;
import com.rastating.droidbeard.net.DeleteShowTask;
import com.rastating.droidbeard.net.EpisodeSearchTask;
import com.rastating.droidbeard.net.FetchShowTask;
import com.rastating.droidbeard.net.SetEpisodeStatusTask;
import com.rastating.droidbeard.net.SetPausedTask;
import com.rastating.droidbeard.net.SickbeardAsyncTask;
import com.rastating.droidbeard.net.SickbeardTaskPool;
import com.rastating.droidbeard.net.TaskPoolSubscriber;
import com.rastating.droidbeard.ui.CrossFader;
import com.rastating.droidbeard.ui.EpisodeItem;
import com.rastating.droidbeard.ui.EpisodeItemClickListener;
import com.rastating.droidbeard.ui.LoadingAnimation;
import com.rastating.droidbeard.ui.SeasonTable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ShowFragment extends DroidbeardFragment
        implements ApiResponseListener<TVShow>, EpisodeItemClickListener, View.OnClickListener {
    private TVShowSummary mShowSummary;
    private ImageView mBanner;
    private ImageView mLoadingImage;
    private View mDataContainer;
    private TVShow mShow;
    private TextView mAirs;
    private TextView mStatus;
    private TextView mLocation;
    private TextView mQuality;
    private TextView mLanguage;
    private ImageView mLanguageIcon;
    private ImageView mFlattenFolders;
    private ImageView mPaused;
    private ImageView mAirByDate;
    private LinearLayout mSeasonContainer;
    private Button mPauseButton;
    private Button mDeleteButton;

    private SwipeRefreshLayout swipeRefreshLayout;

    private ArrayList<EpisodeItem> mSelectedEpisodes;

    private boolean mDisposingActionMode;
    private ActionMode mActionMode;
    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

        // Called when the action mode is created; startActionMode() was called
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Inflate a menu resource providing context menu items
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.episode_context_menu, menu);
            return true;
        }

        // Called each time the action mode is shown. Always called after onCreateActionMode, but
        // may be called multiple times if the mode is invalidated.
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false; // Return false if nothing is done
        }

        // Called when the user selects a contextual menu item
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
            case 0:
                mode.finish(); // Action picked, so close the CAB
                return true;

            case R.id.set_archived:
            case R.id.set_ignored:
            case R.id.set_skipped:
            case R.id.set_wanted:
                onSetStatusItemSelected(item);
                mode.finish();
                return true;

            case R.id.search:
                onEpisodeSearchItemSelected();
                mode.finish();
                return true;

            default:
                return false;
            }
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mActionMode = null;
            mDisposingActionMode = true;

            for (int i = mSelectedEpisodes.size() - 1; i >= 0 && mSelectedEpisodes.size() > 0; i--) {
                EpisodeItem item = mSelectedEpisodes.get(i);
                item.setChecked(false);
            }

            mSelectedEpisodes.clear();
            mDisposingActionMode = false;
            getActivity().setTheme(R.style.SickBeardTheme);
        }
    };
    private boolean mReturnToUpcomingEpisodes;

    public ShowFragment() {
        mShowSummary = null;
        mSelectedEpisodes = new ArrayList<EpisodeItem>();
    }

    public void setTvShowSummary(TVShowSummary show) {
        mShowSummary = show;
        setTitle(show.getName());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(),
                R.style.SickBeardTheme_LightActionBar);
        LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
        View root = localInflater.inflate(R.layout.fragment_show, container, false);

        swipeRefreshLayout = (SwipeRefreshLayout) root.findViewById(R.id.swipe_refresh_layout);

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {

            @Override
            public void onRefresh() {
                onRefreshButtonPressed();

                swipeRefreshLayout.setRefreshing(true);
            }
        });
        swipeRefreshLayout.setColorSchemeResources(R.color.materialPrimaryDark, R.color.materialPrimary,
                R.color.navigation_list_item_selected, R.color.unaired_episode_background);

        if (savedInstanceState != null) {
            mShowSummary = (TVShowSummary) savedInstanceState.getParcelable("summary");
        }

        // Get references to all required views.
        mBanner = (ImageView) root.findViewById(R.id.banner);
        mLoadingImage = (ImageView) root.findViewById(R.id.loading);
        mDataContainer = root.findViewById(R.id.data);
        mAirs = (TextView) root.findViewById(R.id.airs);
        mStatus = (TextView) root.findViewById(R.id.status);
        mLocation = (TextView) root.findViewById(R.id.location);
        mQuality = (TextView) root.findViewById(R.id.quality);
        mLanguage = (TextView) root.findViewById(R.id.language);
        mLanguageIcon = (ImageView) root.findViewById(R.id.language_icon);
        mFlattenFolders = (ImageView) root.findViewById(R.id.flatten_folders);
        mPaused = (ImageView) root.findViewById(R.id.paused);
        mAirByDate = (ImageView) root.findViewById(R.id.air_by_date);
        mSeasonContainer = (LinearLayout) root.findViewById(R.id.season_container);
        mPauseButton = (Button) root.findViewById(R.id.toggle_pause);
        mDeleteButton = (Button) root.findViewById(R.id.delete);

        mPauseButton.setOnClickListener(this);
        mDeleteButton.setOnClickListener(this);

        mDataContainer.setAlpha(0.0f);
        mLoadingImage.setAlpha(1.0f);
        mLoadingImage.startAnimation(new LoadingAnimation());
        onRefreshButtonPressed();

        return root;
    }

    @Override
    public void onApiRequestFinished(SickbeardAsyncTask sender, TVShow result) {
        if (activityStillExists()) {
            mShow = result;
            if (mShow != null) {
                populateViews();
            }
            new CrossFader(mLoadingImage, mDataContainer, 500).start();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onRefreshButtonPressed() {
        // Start loading animation.
        //mDataContainer.setAlpha(0.0f);
        //mLoadingImage.setAlpha(1.0f);
        //mLoadingImage.startAnimation(new LoadingAnimation());

        // Start fetching the show information.
        FetchShowTask task = new FetchShowTask(getActivity());
        task.addResponseListener(this);
        task.start(mShowSummary.getTvDbId());

        if (swipeRefreshLayout != null) {
            swipeRefreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    swipeRefreshLayout.setRefreshing(false);
                }
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("summary", mShowSummary);
    }

    private void populateViews() {
        if (mShow.getBanner() != null) {
            mBanner.setImageBitmap(mShow.getBanner());
        }

        mAirs.setText(mShow.getAirs() + " on " + mShow.getNetwork());
        mStatus.setText(mShow.getStatus());
        mLocation.setText(mShow.getLocation());
        mQuality.setText(mShow.getQuality());
        mLanguage.setText(mShow.getLanguage().getCode());
        mLanguageIcon.setImageResource(mShow.getLanguage().getIconResId());
        mFlattenFolders.setImageResource(mShow.getFlattenFolders() ? R.drawable.yes16 : R.drawable.no16);
        mAirByDate.setImageResource(mShow.getAirByDate() ? R.drawable.yes16 : R.drawable.no16);

        setupPauseViews(mShow.getPaused());

        mSeasonContainer.removeAllViews();
        List<Season> seasons = mShow.getSeasons();
        if (seasons != null) {
            for (Season season : seasons) {
                SeasonTable table = new SeasonTable(getActivity(), season);
                table.setTitle(season.getTitle());

                List<Episode> episodes = season.getEpisodes();
                Collections.sort(episodes, new EpisodeComparator());
                Collections.reverse(episodes);

                for (Episode episode : episodes) {
                    EpisodeItem item = table.addEpisode(episode);
                    item.setOnItemClickListener(this);
                    item.setOnCreateContextMenuListener(this);
                }

                mSeasonContainer.addView(table);
            }
        }
    }

    private void setupPauseViews(boolean paused) {
        mPaused.setImageResource(paused ? R.drawable.yes16 : R.drawable.no16);
        mPauseButton.setText(paused ? getString(R.string.unpause) : getString(R.string.pause));
    }

    @Override
    public void onItemClick(EpisodeItem item, int seasonNumber, int episodeNumber, String name) {
        if (!mDisposingActionMode) {
            if (item.isChecked()) {
                mSelectedEpisodes.add(item);
            } else {
                mSelectedEpisodes.remove(item);
            }

            if (mActionMode == null && mSelectedEpisodes.size() > 0) {
                getActivity().setTheme(R.style.SickBeardTheme_LightActionBar);
                mActionMode = getActivity().startActionMode(mActionModeCallback);
            } else if (mActionMode != null && mSelectedEpisodes.size() == 0) {
                mActionMode.finish();
            }

            if (mActionMode != null && mSelectedEpisodes.size() > 0) {
                mActionMode.setTitle(String.valueOf(mSelectedEpisodes.size()) + " selected");
            }
        }
    }

    private SetEpisodeStatusTask buildEpisodeStatusTask(SeasonTable seasonTable, EpisodeItem episodeItem,
            long tvdbid, int season, int episode, String status) {
        // Create finals for use in callback...
        final EpisodeItem finalEpisodeItem = episodeItem;
        final SeasonTable finalSeasonTable = seasonTable;
        final int finalEpisode = episode;
        final String finalStatus = status;

        SetEpisodeStatusTask task = new SetEpisodeStatusTask(getActivity(), tvdbid, season, episode);
        task.addResponseListener(new ApiResponseListener<Boolean>() {
            @Override
            public void onApiRequestFinished(SickbeardAsyncTask sender, Boolean result) {
                if (result) {
                    if (finalEpisode > 0) {
                        finalEpisodeItem.setStatus(finalStatus);
                        finalEpisodeItem.setChecked(false);
                    } else {
                        finalSeasonTable.setChecked(false);
                        for (EpisodeItem item : finalSeasonTable.getEpisodeItems()) {
                            item.setStatus(finalStatus);
                            item.setChecked(false);
                        }
                    }
                }
            }
        });

        return task;
    }

    private void onSetStatusItemSelected(MenuItem item) {
        // Group selected episodes into a list of individual episodes and full seasons...
        ArrayList<SeasonTable> selectedSeasons = new ArrayList<SeasonTable>();
        ArrayList<EpisodeItem> selectedEpisodes = new ArrayList<EpisodeItem>();
        for (EpisodeItem episode : mSelectedEpisodes) {
            SeasonTable seasonTable = episode.getSeasonTable();
            if (seasonTable.allEpisodesChecked()) {
                if (!selectedSeasons.contains(seasonTable)) {
                    selectedSeasons.add(seasonTable);
                }
            } else {
                selectedEpisodes.add(episode);
            }
        }

        String status = "";
        if (item.getItemId() == R.id.set_wanted) {
            status = "wanted";
        } else if (item.getItemId() == R.id.set_skipped) {
            status = "skipped";
        } else if (item.getItemId() == R.id.set_ignored) {
            status = "ignored";
        } else {
            status = "archived";
        }

        SickbeardTaskPool<String> pool = new SickbeardTaskPool<String>();

        for (SeasonTable seasonTable : selectedSeasons) {
            Season season = seasonTable.getSeason();
            SetEpisodeStatusTask task = buildEpisodeStatusTask(seasonTable, null, season.getTVDBID(),
                    season.getSeasonNumber(), -1, status);
            pool.addTask(task);
        }

        for (EpisodeItem episodeItem : selectedEpisodes) {
            Episode episode = episodeItem.getEpisode();
            SetEpisodeStatusTask task = buildEpisodeStatusTask(null, episodeItem, episode.getTVDBID(),
                    episode.getSeasonNumber(), episode.getEpisodeNumber(), status);
            pool.addTask(task);
        }

        final ProgressDialog dialog = createProgressDialog("Performing Status Updates", "Please wait...");
        dialog.show();
        pool.setTaskPoolSubscriber(new TaskPoolSubscriber() {
            @Override
            public void executionFinished() {
                dialog.dismiss();
                mSelectedEpisodes.clear();
            }
        });
        pool.start(status);
    }

    private void onEpisodeSearchItemSelected() {
        SickbeardTaskPool<Void> pool = new SickbeardTaskPool<Void>();
        for (EpisodeItem episodeItem : mSelectedEpisodes) {
            Episode episode = episodeItem.getEpisode();
            EpisodeSearchTask task = new EpisodeSearchTask(getActivity(), episode.getTVDBID(),
                    episode.getSeasonNumber(), episode.getEpisodeNumber());
            pool.addTask(task);
        }

        final ProgressDialog dialog = createProgressDialog("Searching for Selected Episodes", "Please wait...");
        dialog.show();
        pool.setTaskPoolSubscriber(new TaskPoolSubscriber() {
            @Override
            public void executionFinished() {
                dialog.dismiss();

                for (int i = mSelectedEpisodes.size() - 1; i >= 0; i--) {
                    EpisodeItem item = mSelectedEpisodes.get(i);
                    item.setChecked(false);
                }

                mSelectedEpisodes.clear();
                onRefreshButtonPressed();
            }
        });
        pool.start();
    }

    private ProgressDialog createProgressDialog(String title, String message) {
        ProgressDialog dialog = new ProgressDialog(getActivity());
        dialog.setTitle(title);
        dialog.setMessage(message);
        dialog.setCancelable(false);
        dialog.setIndeterminate(true);
        return dialog;
    }

    public void setShouldReturnToUpcomingEpisodes(boolean value) {
        mReturnToUpcomingEpisodes = value;
    }

    public boolean shouldReturnToUpcomingEpisodes() {
        return mReturnToUpcomingEpisodes;
    }

    @Override
    public void onClick(View v) {
        if (v == mPauseButton) {
            mShow.setPaused(!mShow.getPaused());
            setupPauseViews(mShow.getPaused());
            new SetPausedTask(ShowFragment.this.getActivity(), mShowSummary.getTvDbId()).start(mShow.getPaused());
        } else if (v == mDeleteButton) {
            new AlertDialog.Builder(ShowFragment.this.getActivity()).setTitle("Confirm")
                    .setMessage("Are you sure you want to delete this show?")
                    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface d, int whichButton) {
                            final ProgressDialog dialog = createProgressDialog("Deleting Show", "Please wait...");
                            dialog.show();

                            DeleteShowTask task = new DeleteShowTask(ShowFragment.this.getActivity());
                            task.addResponseListener(new ApiResponseListener<Boolean>() {
                                @Override
                                public void onApiRequestFinished(SickbeardAsyncTask sender, Boolean result) {
                                    dialog.dismiss();
                                    getMainActivity().displayAndRefreshShowsFragment();
                                }
                            });
                            task.start(mShowSummary.getTvDbId());
                        }
                    }).setNegativeButton("No", null).show();
        }
    }
}