com.owncloud.android.ui.fragment.PublicShareDialogFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.owncloud.android.ui.fragment.PublicShareDialogFragment.java

Source

/**
 * ownCloud Android client application
 *
 * @author David A. Velasco
 * @author David Gonzlez Verdugo
 * @author Christian Schabesberger
 * Copyright (C) 2018 ownCloud GmbH.
 *
 * 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.owncloud.android.ui.fragment;

import android.accounts.Account;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.SwitchCompat;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.shares.OCShare;
import com.owncloud.android.lib.resources.status.OCCapability;
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
import com.owncloud.android.utils.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class PublicShareDialogFragment extends DialogFragment {

    private static final String TAG = PublicShareDialogFragment.class.getSimpleName();

    /**
     * The fragment initialization parameters
     */
    private static final String ARG_FILE = "FILE";
    private static final String ARG_SHARE = "SHARE";
    private static final String ARG_ACCOUNT = "ACCOUNT";
    private static final String ARG_DEFAULT_LINK_NAME = "DEFAULT_LINK_NAME";
    private static final String KEY_EXPIRATION_DATE = "EXPIRATION_DATE";

    /**
     * File to share, received as a parameter in construction time
     */
    private OCFile mFile;

    /**
     * Existing share to update. If NULL, the dialog will create a new share for mFile.
     */
    private OCShare mPublicShare;

    /*
     * OC account holding the file to share, received as a parameter in construction time
     */
    private Account mAccount;

    /**
     * Reference to parent listener
     */
    private ShareFragmentListener mListener;

    /**
     * Capabilities of the server
     */
    private OCCapability mCapabilities;

    /**
     * Listener for changes in password switch
     */
    private OnPasswordInteractionListener mOnPasswordInteractionListener;

    /**
     * Listener for changes in expiration date switch
     */
    private OnExpirationDateInteractionListener mOnExpirationDateInteractionListener;

    /**
     * UI elements
     */

    private LinearLayout mNameSelectionLayout;
    private EditText mNameValueEdit;
    private TextView mPasswordLabel;
    private SwitchCompat mPasswordSwitch;
    private EditText mPasswordValueEdit;
    private TextView mExpirationDateLabel;
    private SwitchCompat mExpirationDateSwitch;
    private TextView mExpirationDateExplanationLabel;
    private TextView mExpirationDateValueLabel;
    private TextView mErrorMessageLabel;
    private RadioGroup mPermissionRadioGroup;
    private RadioButton mReadOnlyButton;
    private RadioButton mReadWriteButton;
    private RadioButton mUploadOnlyButton;

    /**
     * Create a new instance of PublicShareDialogFragment, providing fileToShare and account
     * as an argument.
     *
     * Dialog shown this way is intended to CREATE a new public share.
     *
     * @param   fileToShare     File to share with a new public share.
     * @param   account         Account to get capabilities
     */
    public static PublicShareDialogFragment newInstanceToCreate(OCFile fileToShare, Account account,
            String defaultLinkName) {
        PublicShareDialogFragment publicShareDialogFragment = new PublicShareDialogFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_FILE, fileToShare);
        args.putParcelable(ARG_ACCOUNT, account);
        args.putString(ARG_DEFAULT_LINK_NAME, defaultLinkName);

        publicShareDialogFragment.setArguments(args);
        return publicShareDialogFragment;
    }

    /**
     * Update an instance of PublicShareDialogFragment, providing fileToShare, publicShare and
     * account as arguments.
     *
     * Dialog shown this way is intended to UPDATE an existing public share.
     *
     * @param   publicShare           Public share to update.
     */
    public static PublicShareDialogFragment newInstanceToUpdate(OCFile fileToShare, OCShare publicShare,
            Account account) {
        PublicShareDialogFragment publicShareDialogFragment = new PublicShareDialogFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_FILE, fileToShare);
        args.putParcelable(ARG_SHARE, publicShare);
        args.putParcelable(ARG_ACCOUNT, account);
        publicShareDialogFragment.setArguments(args);
        return publicShareDialogFragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            mFile = getArguments().getParcelable(ARG_FILE);
            mAccount = getArguments().getParcelable(ARG_ACCOUNT);
            mPublicShare = getArguments().getParcelable(ARG_SHARE);
        }

        if (mFile == null && mPublicShare == null) {
            throw new IllegalStateException("Both ARG_FILE and ARG_SHARE cannot be NULL");
        }

        setStyle(DialogFragment.STYLE_NO_TITLE, 0);
    }

    private boolean updating() {
        return (mPublicShare != null);
    }

    private boolean isSharedFolder() {
        return ((mFile != null && mFile.isFolder()) || (mPublicShare != null && mPublicShare.isFolder()));
    }

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

        View view = inflater.inflate(R.layout.share_public_dialog, container, false);

        Log_OC.d(TAG, "onCreateView");

        final TextView dialogTitleLabel = view.findViewById(R.id.publicShareDialogTitle);
        mNameSelectionLayout = view.findViewById(R.id.shareViaLinkNameSection);
        mNameValueEdit = view.findViewById(R.id.shareViaLinkNameValue);
        mPasswordLabel = view.findViewById(R.id.shareViaLinkPasswordLabel);
        mPasswordSwitch = view.findViewById(R.id.shareViaLinkPasswordSwitch);
        mPasswordValueEdit = view.findViewById(R.id.shareViaLinkPasswordValue);
        mExpirationDateLabel = view.findViewById(R.id.shareViaLinkExpirationLabel);
        mExpirationDateSwitch = view.findViewById(R.id.shareViaLinkExpirationSwitch);
        mExpirationDateExplanationLabel = view.findViewById(R.id.shareViaLinkExpirationExplanationLabel);
        mErrorMessageLabel = view.findViewById(R.id.public_link_error_message);
        mExpirationDateValueLabel = view.findViewById(R.id.shareViaLinkExpirationValue);
        mPermissionRadioGroup = view.findViewById(R.id.shareViaLinkEditPermissionGroup);
        mReadOnlyButton = view.findViewById(R.id.shareViaLinkEditPermissionReadOnly);
        mReadWriteButton = view.findViewById(R.id.shareViaLinkEditPermissionReadAndWrite);
        mUploadOnlyButton = view.findViewById(R.id.shareViaLinkEditPermissionUploadFiles);

        // Get and set the values saved previous to the screen rotation, if any
        if (savedInstanceState != null) {
            String expirationDate = savedInstanceState.getString(KEY_EXPIRATION_DATE);
            if (expirationDate.length() > 0) {
                mExpirationDateValueLabel.setVisibility(View.VISIBLE);
                mExpirationDateValueLabel.setText(expirationDate);
            }
        }

        if (updating()) {
            dialogTitleLabel.setText(R.string.share_via_link_edit_title);
            mNameValueEdit.setText(mPublicShare.getName());

            switch (mPublicShare.getPermissions()) {
            case (OCShare.CREATE_PERMISSION_FLAG | OCShare.DELETE_PERMISSION_FLAG | OCShare.UPDATE_PERMISSION_FLAG
                    | OCShare.READ_PERMISSION_FLAG):
                mReadWriteButton.setChecked(true);
                break;
            case OCShare.CREATE_PERMISSION_FLAG:
                mUploadOnlyButton.setChecked(true);
                break;
            default:
                mReadOnlyButton.setChecked(true);
            }

            if (mPublicShare.isPasswordProtected()) {

                setPasswordSwitchChecked(true);
                mPasswordValueEdit.setVisibility(View.VISIBLE);
                mPasswordValueEdit.setHint(R.string.share_via_link_default_password);
            }

            if (mPublicShare.getExpirationDate() != 0) {
                setExpirationDateSwitchChecked(true);
                String formattedDate = ExpirationDatePickerDialogFragment.getDateFormat()
                        .format(new Date(mPublicShare.getExpirationDate()));
                mExpirationDateValueLabel.setVisibility(View.VISIBLE);
                mExpirationDateValueLabel.setText(formattedDate);
            }

        } else {
            mNameValueEdit.setText(getArguments().getString(ARG_DEFAULT_LINK_NAME, ""));
        }

        initPasswordListener();
        initExpirationListener();
        initPasswordFocusChangeListener();
        initPasswordToggleListener();

        view.findViewById(R.id.saveButton).setOnClickListener(v -> onSaveShareSetting());

        view.findViewById(R.id.cancelButton).setOnClickListener(v -> dismiss());

        return view;
    }

    private void onSaveShareSetting() {

        // Get data filled by user
        final String publicLinkName = mNameValueEdit.getText().toString();
        String publicLinkPassword = mPasswordValueEdit.getText().toString();
        final long publicLinkExpirationDateInMillis = getExpirationDateValueInMillis();

        final int publicLinkPermissions;
        boolean publicUploadPermission;

        switch (mPermissionRadioGroup.getCheckedRadioButtonId()) {
        case R.id.shareViaLinkEditPermissionUploadFiles:
            publicLinkPermissions = OCShare.CREATE_PERMISSION_FLAG;
            publicUploadPermission = true;
            break;
        case R.id.shareViaLinkEditPermissionReadAndWrite:
            publicLinkPermissions = OCShare.CREATE_PERMISSION_FLAG | OCShare.DELETE_PERMISSION_FLAG
                    | OCShare.UPDATE_PERMISSION_FLAG | OCShare.READ_PERMISSION_FLAG;
            publicUploadPermission = true;
            break;
        case R.id.shareViaLinkEditPermissionReadOnly:
        default:
            publicLinkPermissions = OCShare.READ_PERMISSION_FLAG;
            publicUploadPermission = false;
            break;
        }

        // since the public link permission foo got a bit despagetified in the server somewhere
        // at 10.0.4 we don't need publicUploadPermission there anymore. By setting it to false
        // it will not be sent to the server.

        publicUploadPermission = (mCapabilities.getVersionMayor() >= 10
                && (mCapabilities.getVersionMinor() > 1 || mCapabilities.getVersionMicro() > 3))
                && publicUploadPermission;

        if (!updating()) { // Creating a new public share
            ((FileActivity) getActivity()).getFileOperationsHelper().shareFileViaLink(mFile, publicLinkName,
                    publicLinkPassword, publicLinkExpirationDateInMillis, false, publicLinkPermissions);

        } else { // Updating an existing public share
            if (!mPasswordSwitch.isChecked()) {
                publicLinkPassword = "";
            } else if (mPasswordValueEdit.length() == 0) {
                // User has not added a new password, so do not update it
                publicLinkPassword = null;
            }

            ((FileActivity) getActivity()).getFileOperationsHelper().updateShareViaLink(mPublicShare,
                    publicLinkName, publicLinkPassword, publicLinkExpirationDateInMillis, publicUploadPermission,
                    publicLinkPermissions);
        }
    }

    private void initPasswordFocusChangeListener() {
        mPasswordValueEdit.setOnFocusChangeListener((View v, boolean hasFocus) -> {
            if (v.getId() == R.id.shareViaLinkPasswordValue) {
                onPasswordFocusChanged(hasFocus);
            }
        });
    }

    private void initPasswordToggleListener() {
        mPasswordValueEdit.setOnTouchListener(new RightDrawableOnTouchListener() {
            @Override
            public boolean onDrawableTouch(final MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    onViewPasswordClick();
                }
                return true;
            }
        });
    }

    private abstract static class RightDrawableOnTouchListener implements View.OnTouchListener {

        private int fuzz = 75;

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            Drawable rightDrawable = null;
            if (view instanceof TextView) {
                Drawable[] drawables = ((TextView) view).getCompoundDrawables();
                if (drawables.length > 2) {
                    rightDrawable = drawables[2];
                }
            }
            if (rightDrawable != null) {
                final int x = (int) event.getX();
                final int y = (int) event.getY();
                final Rect bounds = rightDrawable.getBounds();
                if (x >= (view.getRight() - bounds.width() - fuzz)
                        && x <= (view.getRight() - view.getPaddingRight() + fuzz)
                        && y >= (view.getPaddingTop() - fuzz)
                        && y <= (view.getHeight() - view.getPaddingBottom()) + fuzz) {

                    return onDrawableTouch(event);
                }
            }
            return false;
        }

        public abstract boolean onDrawableTouch(final MotionEvent event);
    }

    /**
     * Handles changes in focus on the text input for the password (basic authorization).
     * When (hasFocus), the button to toggle password visibility is shown.
     * When (!hasFocus), the button is made invisible and the password is hidden.
     *
     * @param hasFocus          'True' if focus is received, 'false' if is lost
     */
    private void onPasswordFocusChanged(boolean hasFocus) {
        if (hasFocus) {
            showViewPasswordButton();
        } else {
            hidePassword();
            hidePasswordButton();
        }
    }

    /**
     * Called when the eye icon in the password field is clicked.
     *
     * Toggles the visibility of the password in the field.
     */
    public void onViewPasswordClick() {
        if (getView() != null) {
            if (isPasswordVisible()) {
                hidePassword();
            } else {
                showPassword();
            }
            mPasswordValueEdit.setSelection(mPasswordValueEdit.getSelectionStart(),
                    mPasswordValueEdit.getSelectionEnd());
        }
    }

    private void showViewPasswordButton() {
        int drawable = isPasswordVisible() ? R.drawable.ic_view : R.drawable.ic_hide;
        if (getView() != null) {
            mPasswordValueEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, drawable, 0);
        }
    }

    private boolean isPasswordVisible() {
        return (getView() != null) && ((mPasswordValueEdit.getInputType()
                & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
    }

    private void hidePasswordButton() {
        if (getView() != null) {
            mPasswordValueEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        }
    }

    private void showPassword() {
        if (getView() != null) {
            mPasswordValueEdit.setInputType(InputType.TYPE_CLASS_TEXT
                    | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
            showViewPasswordButton();
        }
    }

    private void hidePassword() {
        if (getView() != null) {
            mPasswordValueEdit.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
                    | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
            showViewPasswordButton();
        }
    }

    private long getExpirationDateValueInMillis() {
        long publicLinkExpirationDateInMillis = -1;
        String expirationDate = mExpirationDateValueLabel.getText().toString();
        if (expirationDate.length() > 0) {
            // Parse expiration date and convert it to milliseconds
            try {
                // remember: format is defined by date picker
                publicLinkExpirationDateInMillis = ExpirationDatePickerDialogFragment.getDateFormat()
                        .parse(expirationDate).getTime();
            } catch (ParseException e) {
                Log_OC.e(TAG, "Error reading expiration date from input field", e);
            }
        }
        return publicLinkExpirationDateInMillis;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log_OC.d(TAG, "onActivityCreated");

        // Load known capabilities of the server from DB
        refreshModelFromStorageManager();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(KEY_EXPIRATION_DATE, mExpirationDateValueLabel.getText().toString());
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (ShareFragmentListener) activity;
        } catch (IllegalStateException e) {
            throw new IllegalStateException(
                    activity.toString() + " must implement OnShareFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    /**
     * Binds listener for user actions that start any update on a password for the public link
     * to the views receiving the user events.
     *
     */
    private void initPasswordListener() {
        mOnPasswordInteractionListener = new OnPasswordInteractionListener();
        mPasswordSwitch.setOnCheckedChangeListener(mOnPasswordInteractionListener);
    }

    /**
     * Listener for user actions that start any update on a password for the public link.
     */
    private class OnPasswordInteractionListener implements CompoundButton.OnCheckedChangeListener {

        /**
         * Called by R.id.shareViaLinkPasswordSwitch to set or clear the password.
         *
         * @param switchView {@link SwitchCompat} toggled by the user, R.id.shareViaLinkPasswordSwitch
         * @param isChecked  New switch state.
         */
        @Override
        public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
            if (isChecked) {
                mPasswordValueEdit.setVisibility(View.VISIBLE);
                mPasswordValueEdit.requestFocus();

                // Show keyboard to fill in the password
                InputMethodManager mgr = (InputMethodManager) getActivity()
                        .getSystemService(Context.INPUT_METHOD_SERVICE);
                mgr.showSoftInput(mPasswordValueEdit, InputMethodManager.SHOW_IMPLICIT);

            } else {
                mPasswordValueEdit.setVisibility(View.GONE);
                mPasswordValueEdit.getText().clear();
            }
        }
    }

    /**
     * Binds listener for user actions that start any update on a expiration date
     * for the public link to the views receiving the user events.
     *
     */
    private void initExpirationListener() {
        mOnExpirationDateInteractionListener = new OnExpirationDateInteractionListener();
        mExpirationDateSwitch.setOnCheckedChangeListener(mOnExpirationDateInteractionListener);
        mExpirationDateLabel.setOnClickListener(mOnExpirationDateInteractionListener);
        mExpirationDateValueLabel.setOnClickListener(mOnExpirationDateInteractionListener);
    }

    /**
     * Listener for user actions that start any update on the expiration date for the public link.
     */
    private class OnExpirationDateInteractionListener implements CompoundButton.OnCheckedChangeListener,
            View.OnClickListener, ExpirationDatePickerDialogFragment.DatePickerFragmentListener {

        /**
         * Called by R.id.shareViaLinkExpirationSwitch to set or clear the expiration date.
         *
         * @param switchView {@link SwitchCompat} toggled by the user, R.id.shareViaLinkExpirationSwitch
         * @param isChecked  New switch state.
         */
        @Override
        public void onCheckedChanged(CompoundButton switchView, boolean isChecked) {
            if (!isResumed()) {
                // very important, setCheched(...) is called automatically during
                // Fragment recreation on device rotations
                return;
            }

            if (isChecked) {
                // Show calendar to set the expiration date
                ExpirationDatePickerDialogFragment dialog = ExpirationDatePickerDialogFragment
                        .newInstance(getExpirationDateValueInMillis(), getImposedExpirationDate());
                dialog.setDatePickerListener(this);
                dialog.show(getActivity().getSupportFragmentManager(),
                        ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG);
            } else {
                mExpirationDateValueLabel.setVisibility(View.INVISIBLE);
                mExpirationDateValueLabel.setText("");
            }
        }

        /**
         * Called by R.id.shareViaLinkExpirationLabel or R.id.shareViaLinkExpirationValue
         * to change the current expiration date.
         *
         * @param expirationView Label or value view touched by the user.
         */
        @Override
        public void onClick(View expirationView) {

            // Show calendar to set the expiration date
            ExpirationDatePickerDialogFragment dialog = ExpirationDatePickerDialogFragment
                    .newInstance(getExpirationDateValueInMillis(), getImposedExpirationDate());
            dialog.setDatePickerListener(this);
            dialog.show(getActivity().getSupportFragmentManager(),
                    ExpirationDatePickerDialogFragment.DATE_PICKER_DIALOG);
        }

        /**
         * Update the selected date for the public link
         *
         * @param date date selected by the user
         */
        @Override
        public void onDateSet(String date) {
            mExpirationDateValueLabel.setVisibility(View.VISIBLE);
            mExpirationDateValueLabel.setText(date);
        }

        @Override
        public void onCancelDatePicker() {

            SwitchCompat expirationToggle = getView().findViewById(R.id.shareViaLinkExpirationSwitch);

            // If the date has not been set yet, uncheck the toggle
            if (expirationToggle.isChecked() && mExpirationDateValueLabel.getText() == "") {
                expirationToggle.setChecked(false);
            }
        }
    }

    /**
     * Get known server capabilities from DB
     *
     * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
     * instance ready to use. If not ready, does nothing.
     */
    public void refreshModelFromStorageManager() {
        if (((FileActivity) mListener).getStorageManager() != null) {
            mCapabilities = ((FileActivity) mListener).getStorageManager().getCapability(mAccount.name);

            updateInputFormAccordingToServerCapabilities();
        }
    }

    /**
     * Updates the UI according to enforcements and allowances set by the server administrator.
     *
     * Includes:
     *  - hide the link name section if multiple public share is not supported, showing the keyboard
     *    to fill in the public share name otherwise
     *  - hide show file listing option
     *  - hide or show the switch to disable the password if it is enforced or not;
     *  - hide or show the switch to disable the expiration date it it is enforced or not;
     *  - show or hide the switch to allow public uploads if it is allowed or not;
     *  - set the default value for expiration date if defined (only if creating a new share).
     */
    private void updateInputFormAccordingToServerCapabilities() {
        final OwnCloudVersion serverVersion = new OwnCloudVersion(mCapabilities.getVersionString());

        // Server version <= 9.x, multiple public sharing not supported
        if (!serverVersion.isMultiplePublicSharingSupported()) {
            mNameSelectionLayout.setVisibility(View.GONE);
        } else {
            getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
                    | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        }

        if (mCapabilities.getFilesSharingPublicUpload().isTrue() && isSharedFolder()) {
            mPermissionRadioGroup.setVisibility(View.VISIBLE);
        }

        // Show file listing option if all the following is true:
        //  - The file to share is a folder
        //  - Upload only is supported by the server version
        //  - Upload only capability is set
        //  - Allow editing capability is set
        if (!(isSharedFolder() && serverVersion.isPublicSharingWriteOnlySupported()
                && mCapabilities.getFilesSharingPublicSupportsUploadOnly().isTrue()
                && mCapabilities.getFilesSharingPublicUpload().isTrue())) {
            mPermissionRadioGroup.setVisibility(View.GONE);
        }

        // Show default date enforced by the server, if any
        if (!updating() && mCapabilities.getFilesSharingPublicExpireDateDays() > 0) {

            setExpirationDateSwitchChecked(true);

            String formattedDate = SimpleDateFormat.getDateInstance().format(
                    DateUtils.addDaysToDate(new Date(), mCapabilities.getFilesSharingPublicExpireDateDays()));

            mExpirationDateValueLabel.setVisibility(View.VISIBLE);

            mExpirationDateValueLabel.setText(formattedDate);
        }

        // Hide expiration date switch if date is enforced to prevent it is removed
        if (mCapabilities.getFilesSharingPublicExpireDateEnforced().isTrue()) {
            mExpirationDateLabel.setText(R.string.share_via_link_expiration_date_enforced_label);
            mExpirationDateSwitch.setVisibility(View.GONE);
            mExpirationDateExplanationLabel.setVisibility(View.VISIBLE);
            mExpirationDateExplanationLabel
                    .setText(getString(R.string.share_via_link_expiration_date_explanation_label,
                            mCapabilities.getFilesSharingPublicExpireDateDays()));
        }

        // hide password switch if password is enforced to prevent it is removed
        if (mCapabilities.getFilesSharingPublicPasswordEnforced().isTrue()) {
            mPasswordLabel.setText(R.string.share_via_link_password_enforced_label);
            mPasswordSwitch.setVisibility(View.GONE);
            mPasswordValueEdit.setVisibility(View.VISIBLE);
        }
    }

    /**
     * Get expiration date imposed by the server, if any
     */
    private long getImposedExpirationDate() {

        if (mCapabilities != null && mCapabilities.getFilesSharingPublicExpireDateEnforced().isTrue()) {

            return DateUtils.addDaysToDate(new Date(), mCapabilities.getFilesSharingPublicExpireDateDays())
                    .getTime();
        }

        return -1;
    }

    /**
     * Show error when creating or updating the public share, if any
     * @param errorMessage
     */
    public void showError(String errorMessage) {
        mErrorMessageLabel.setVisibility(View.VISIBLE);
        mErrorMessageLabel.setText(errorMessage);
    }

    private void setPasswordSwitchChecked(boolean checked) {
        mPasswordSwitch.setOnCheckedChangeListener(null);
        mPasswordSwitch.setChecked(checked);
        mPasswordSwitch.setOnCheckedChangeListener(mOnPasswordInteractionListener);
    }

    private void setExpirationDateSwitchChecked(boolean checked) {
        mExpirationDateSwitch.setOnCheckedChangeListener(null);
        mExpirationDateSwitch.setChecked(checked);
        mExpirationDateSwitch.setOnCheckedChangeListener(mOnExpirationDateInteractionListener);
    }

}