com.synox.android.ui.fragment.FileDetailFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.synox.android.ui.fragment.FileDetailFragment.java

Source

/**
 *   ownCloud Android client application
 *
 *   @author Bartek Przybylski
 *   @author David A. Velasco
 *   Copyright (C) 2011  Bartek Przybylski
 *   Copyright (C) 2015 ownCloud Inc.
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2,
 *   as published by the Free Software Foundation.
 *
 *   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.synox.android.ui.fragment;

import android.accounts.Account;
import android.app.DialogFragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.synox.android.R;
import com.synox.android.datamodel.FileDataStorageManager;
import com.synox.android.datamodel.OCFile;
import com.synox.android.files.FileMenuFilter;
import com.synox.android.files.services.FileDownloader.FileDownloaderBinder;
import com.synox.android.files.services.FileUploader.FileUploaderBinder;
import com.synox.android.lib.common.network.OnDatatransferProgressListener;
import com.synox.android.lib.common.utils.Log_OC;
import com.synox.android.ui.activity.FileActivity;
import com.synox.android.ui.activity.FileDisplayActivity;
import com.synox.android.ui.dialog.RemoveFileDialogFragment;
import com.synox.android.ui.dialog.RenameFileDialogFragment;
import com.synox.android.utils.DisplayUtils;
import com.synox.android.utils.MimetypeIconUtil;
import com.synox.android.utils.ThumbnailUtils;

import java.io.File;
import java.lang.ref.WeakReference;

/**
 * This Fragment is used to display the details about a file.
 */
public class FileDetailFragment extends FileFragment implements OnClickListener {

    private int mLayout;
    private View mView;
    private Account mAccount;
    private AppCompatActivity act;

    public ProgressListener mProgressListener;

    private static final String TAG = FileDetailFragment.class.getSimpleName();
    public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";
    public static final String FTAG_RENAME_FILE = "RENAME_FILE_FRAGMENT";

    private static final String ARG_FILE = "FILE";
    private static final String ARG_ACCOUNT = "ACCOUNT";

    /**
     * Public factory method to create new FileDetailFragment instances.
     *
     * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before).
     *
     * @param fileToDetail      An {@link OCFile} to show in the fragment
     * @param account           An ownCloud account; needed to start downloads
     * @return                  New fragment with arguments set
     */
    public static FileDetailFragment newInstance(OCFile fileToDetail, Account account) {
        FileDetailFragment frag = new FileDetailFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_FILE, fileToDetail);
        args.putParcelable(ARG_ACCOUNT, account);
        frag.setArguments(args);
        return frag;
    }

    /**
     * Creates an empty details fragment.
     * 
     * It's necessary to keep a public constructor without parameters; the system uses it when tries
     * to reinstantiate a fragment automatically.
     */
    public FileDetailFragment() {
        super();
        mAccount = null;
        mLayout = R.layout.file_details_empty;
        mProgressListener = null;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        setFile((OCFile) getArguments().getParcelable(ARG_FILE));
        mAccount = getArguments().getParcelable(ARG_ACCOUNT);

        if (savedInstanceState != null) {
            setFile((OCFile) savedInstanceState.getParcelable(FileActivity.EXTRA_FILE));
            mAccount = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT);
        }

        if (getFile() != null && mAccount != null) {
            mLayout = R.layout.file_details_fragment;
        }

        mView = inflater.inflate(mLayout, null);

        if (mLayout == R.layout.file_details_fragment) {
            ProgressBar progressBar = (ProgressBar) mView.findViewById(R.id.fdProgressBar);
            DisplayUtils.colorPreLollipopHorizontalProgressBar(progressBar);
            mProgressListener = new ProgressListener(progressBar);
            mView.findViewById(R.id.fdCancelBtn).setOnClickListener(this);
        }

        act = (AppCompatActivity) getActivity();
        updateFileDetails(false, false);
        return mView;
    }

    /**
     * Detach from list view.
     */
    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(FileActivity.EXTRA_FILE, getFile());
        outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount);
    }

    @Override
    public void onStart() {
        super.onStart();
        listenForTransferProgress();

    }

    @Override
    public void onStop() {
        leaveTransferProgress();
        super.onStop();

    }

    @Override
    public void onResume() {
        super.onResume();
        ((AppCompatActivity) getActivity()).getSupportActionBar().setSubtitle(null);
    }

    @Override
    public View getView() {
        return super.getView() == null ? mView : super.getView();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.file_actions_menu, menu);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        menu.findItem(R.id.action_search).setVisible(false);
        menu.findItem(R.id.action_changeView).setVisible(false);
        super.onPrepareOptionsMenu(menu);

        if (mContainerActivity.getStorageManager() != null) {
            FileMenuFilter mf = new FileMenuFilter(getFile(), mContainerActivity.getStorageManager().getAccount(),
                    mContainerActivity, getActivity());
            mf.filter(menu);
        }

        // additional restriction for this fragment
        MenuItem item = menu.findItem(R.id.action_see_details);
        if (item != null) {
            item.setVisible(false);
            item.setEnabled(false);
        }

        // additional restriction for this fragment
        item = menu.findItem(R.id.action_move);
        if (item != null) {
            item.setVisible(false);
            item.setEnabled(false);
        }

        // additional restriction for this fragment
        item = menu.findItem(R.id.action_copy);
        if (item != null) {
            item.setVisible(false);
            item.setEnabled(false);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_share_file: {
            mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
            return true;
        }
        case R.id.action_open_file_with: {
            mContainerActivity.getFileOperationsHelper().openFile(getFile());
            return true;
        }
        case R.id.action_remove_file: {
            RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
            dialog.show(getFragmentManager(), FTAG_CONFIRMATION);
            return true;
        }
        case R.id.action_rename_file: {
            RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(getFile());
            dialog.show(getFragmentManager(), FTAG_RENAME_FILE);
            return true;
        }
        case R.id.action_cancel_sync: {
            ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile());
            return true;
        }
        case R.id.action_download_file:
        case R.id.action_sync_file: {
            mContainerActivity.getFileOperationsHelper().syncFile(getFile());
            return true;
        }
        case R.id.action_send_file: {
            // Obtain the file
            if (!getFile().isDown()) { // Download the file
                Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded");
                ((FileDisplayActivity) mContainerActivity).startDownloadForSending(getFile());
            } else {
                mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
            }
            return true;
        }
        case R.id.action_favorite_file: {
            mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true);
            return true;
        }
        case R.id.action_unfavorite_file: {
            mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
            return true;
        }
        default:
            return false;
        }
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.fdCancelBtn) {
            ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile());
            getActivity().onBackPressed();
            ((FileDisplayActivity) getActivity()).onRefresh();
        }
    }

    /**
     * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.
     *
     * @return True when the fragment was created with the empty layout.
     */
    public boolean isEmpty() {
        return (mLayout == R.layout.file_details_empty || getFile() == null || mAccount == null);
    }

    /**
     * Use this method to signal this Activity that it shall update its view.
     *
     * @param file : An {@link OCFile}
     */
    public void updateFileDetails(OCFile file, Account ocAccount) {
        setFile(file);
        mAccount = ocAccount;
        updateFileDetails(false, false);
    }

    /**
     * Updates the view with all relevant details about that file.
     * <p/>
     * TODO Remove parameter when the transferring state of files is kept in database.
     *
     * @param transferring Flag signaling if the file should be considered as downloading or uploading,
     *                     although {@link FileDownloaderBinder#isDownloading(Account, OCFile)}  and
     *                     {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.
     * @param refresh      If 'true', try to refresh the whole file from the database
     */
    public void updateFileDetails(boolean transferring, boolean refresh) {
        if (readyToShow()) {
            FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
            if (refresh && storageManager != null) {
                setFile(storageManager.getFileByPath(getFile().getRemotePath()));
            }
            OCFile file = getFile();

            // set file details
            setFilename(file.getFileName());
            setFiletype(file);
            setFilesize(file.getFileLength());

            setTimeModified(file.getModificationTimestamp());

            // configure UI for depending upon local state of the file
            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
            if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file))
                    || (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file))) {
                setButtonsForTransferring();

            } else if (file.isDown()) {

                setButtonsForDown();

            } else {
                // TODO load default preview image; when the local file is removed, the preview
                // remains there
                setButtonsForRemote();
            }
        }
        getView().invalidate();
    }

    /**
     * Checks if the fragment is ready to show details of a OCFile
     *
     * @return 'True' when the fragment is ready to show details of a file
     */
    private boolean readyToShow() {
        return (getFile() != null && mAccount != null && mLayout == R.layout.file_details_fragment);
    }

    /**
     * Updates the filename in view
     *
     * @param filename to set
     */
    private void setFilename(String filename) {
        TextView tv = (TextView) getView().findViewById(R.id.fdFilename);
        if (tv != null) {
            tv.setText(filename);
        }
    }

    /**
     * Updates the MIME type in view
     * @param file : An {@link OCFile}
     */
    private void setFiletype(OCFile file) {
        String mimetype = file.getMimetype();
        TextView tv = (TextView) getView().findViewById(R.id.fdType);
        if (tv != null) {
            // mimetype      MIME type to set
            String printableMimetype = DisplayUtils.convertMIMEtoPrettyPrint(mimetype);
            tv.setText(printableMimetype);
        }

        ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);

        if (iv != null) {
            // Icons and thumbnail utils
            ThumbnailUtils
                    .processThumbnail(mAccount, file, iv,
                            file.isFolder() ? MimetypeIconUtil.getFolderTypeIconId(file)
                                    : MimetypeIconUtil.getFileTypeIconId(file.getMimetype(), file.getFileName()),
                            0, 0);
        }
    }

    /**
     * Updates the file size in view
     *
     * @param filesize in bytes to set
     */
    private void setFilesize(long filesize) {
        TextView tv = (TextView) getView().findViewById(R.id.fdSize);
        if (tv != null) {
            tv.setText(DisplayUtils.bytesToHumanReadable(filesize));
        }
    }

    /**
     * Updates the time that the file was last modified
     *
     * @param milliseconds Unix time to set
     */
    private void setTimeModified(long milliseconds) {
        TextView tv = (TextView) getView().findViewById(R.id.fdModified);
        if (tv != null) {
            tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
        }
    }

    /**
     * Enables or disables buttons for a file being downloaded
     */
    private void setButtonsForTransferring() {
        if (!isEmpty()) {

            // show the progress bar for the transfer
            getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE);
            FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
            FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
            //if (getFile().isDownloading()) {
            if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, getFile())) {
                act.getSupportActionBar().setTitle(getString(R.string.downloader_download_in_progress_ticker));
                act.getSupportActionBar().setSubtitle(null);
            } else {
                if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, getFile())) {
                    act.getSupportActionBar().setTitle(getString(R.string.uploader_upload_in_progress_ticker));
                    act.getSupportActionBar().setSubtitle(null);
                }
            }
        }
    }

    /**
     * Enables or disables buttons for a file locally available
     */
    private void setButtonsForDown() {
        if (!isEmpty()) {
            // hides the progress bar
            getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
        }
    }

    /**
     * Enables or disables buttons for a file not locally available
     */
    private void setButtonsForRemote() {
        if (!isEmpty()) {
            // hides the progress bar
            getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
        }
    }

    public void listenForTransferProgress() {
        if (mProgressListener != null) {
            if (mContainerActivity.getFileDownloaderBinder() != null) {
                mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener,
                        mAccount, getFile());
            }
            if (mContainerActivity.getFileUploaderBinder() != null) {
                mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener,
                        mAccount, getFile());
            }
        }
    }

    public void leaveTransferProgress() {
        if (mProgressListener != null) {
            if (mContainerActivity.getFileDownloaderBinder() != null) {
                mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener,
                        mAccount, getFile());
            }
            if (mContainerActivity.getFileUploaderBinder() != null) {
                mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener,
                        mAccount, getFile());
            }
        }
    }

    /**
     * Helper class responsible for updating the progress bar shown for file uploading or
     * downloading
     */
    private class ProgressListener implements OnDatatransferProgressListener {
        int mLastPercent = 0;
        WeakReference<ProgressBar> mProgressBar = null;

        ProgressListener(ProgressBar progressBar) {
            mProgressBar = new WeakReference<>(progressBar);
        }

        @Override
        public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
                String filename) {
            int percent = (int) (100.0 * ((double) totalTransferredSoFar) / ((double) totalToTransfer));
            if (percent != mLastPercent) {
                ProgressBar pb = mProgressBar.get();
                if (pb != null) {
                    pb.setProgress(percent);
                    pb.postInvalidate();
                }
            }
            mLastPercent = percent;
        }

    }

}