Эх сурвалжийг харах

Error dialogs in Uploader updated, both messages and implementation

David A. Velasco 9 жил өмнө
parent
commit
68b96ce0db

+ 8 - 6
res/values/strings.xml

@@ -62,17 +62,18 @@
     <string name="sync_string_files">Files</string>
     <string name="setup_btn_connect">Connect</string>
     <string name="uploader_btn_upload_text">Upload</string>
-    <string name="uploader_btn_new_folder_text">New folder</string>
     <string name="uploader_top_message">Choose upload folder:</string>
     <string name="uploader_wrn_no_account_title">No account found</string>
     <string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please set up an account first.</string>
     <string name="uploader_wrn_no_account_setup_btn_text">Setup</string>
     <string name="uploader_wrn_no_account_quit_btn_text">Quit</string>
-    <string name="uploader_wrn_no_content_title">No file to upload</string>
-    <string name="uploader_wrn_unknown_content_title">The content can not be uploaded</string>
-    <string name="uploader_wrn_no_content_text">Sorry, the received data does not content any file.</string>
-    <string name="uploader_error_forbidden_content">%1$s is not allowed to access the shared file</string>
-    <string name="uploader_info_uploading">Uploading</string>
+    <string name="uploader_error_title_no_file_to_upload">No file to upload</string>
+    <string name="uploader_error_message_received_piece_of_text">%1$s cannot upload a piece of text as a file.</string>
+    <string name="uploader_error_message_no_file_to_upload">Received data do not include any valid file.</string>
+    <string name="uploader_error_title_file_cannot_be_uploaded">File cannot be uploaded</string>
+    <string name="uploader_error_message_read_permission_not_granted">%1$s is not allowed to read a received file</string>
+    <string name="uploader_error_message_source_file_not_found">File to upload was not found in its location. Please check whether the file exists.</string>
+    <string name="uploader_error_message_source_file_not_copied">An error occurred while copying the file to a temporary folder. Please try to send again.</string>
     <string name="file_list_seconds_ago">seconds ago</string>
     <string name="file_list_empty">Nothing in here. Upload something!</string>
     <string name="file_list_loading">Loading&#8230;</string>
@@ -104,6 +105,7 @@
     <string name="common_save_exit">Save &amp; exit</string>
     <string name="common_error">Error</string>
     <string name="common_loading">Loading &#8230;</string>
+    <string name="common_unknown">unknown</string>
     <string name="common_error_unknown">Unknown error</string>
     <string name="about_title">About</string>
     <string name="change_password">Change password</string>

+ 1 - 1
src/com/owncloud/android/ui/activity/FileActivity.java

@@ -1074,7 +1074,7 @@ public class FileActivity extends AppCompatActivity
     @Override
     public void onFailedSavingCertificate() {
         ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(
-            R.string.ssl_validator_not_saved, new String[]{}, R.string.common_ok, -1, -1
+            R.string.ssl_validator_not_saved, new String[]{}, 0, R.string.common_ok, -1, -1
         );
         dialog.show(getSupportFragmentManager(), DIALOG_CERT_NOT_SAVED);
     }

+ 1 - 1
src/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -398,7 +398,7 @@ public class UploadFilesActivity extends FileActivity implements
                 // to the ownCloud folder instead of copying
                 String[] args = {getString(R.string.app_name)};
                 ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(
-                    R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1,
+                    R.string.upload_query_move_foreign_files, args, 0, R.string.common_yes, -1,
                         R.string.common_no
                 );
                 dialog.setOnConfirmationListener(UploadFilesActivity.this);

+ 105 - 101
src/com/owncloud/android/ui/activity/Uploader.java

@@ -46,7 +46,6 @@ import android.support.v4.app.FragmentTransaction;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AlertDialog.Builder;
-import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -54,7 +53,6 @@ import android.view.View;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.Button;
-import android.widget.EditText;
 import android.widget.ListView;
 import android.widget.Toast;
 
@@ -72,6 +70,7 @@ import com.owncloud.android.operations.RefreshFolderOperation;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.syncadapter.FileSyncAdapter;
 import com.owncloud.android.ui.adapter.UploaderAdapter;
+import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
 import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
 import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.ui.asynctasks.CopyAndUploadContentUrisTask;
@@ -98,6 +97,8 @@ public class Uploader extends FileActivity
 
     private static final String FTAG_TASK_RETAINER_FRAGMENT = "TASK_RETAINER_FRAGMENT";
 
+    private static final String FTAG_ERROR_FRAGMENT = "ERROR_FRAGMENT";
+
     private AccountManager mAccountManager;
     private Stack<String> mParents;
     private ArrayList<Parcelable> mStreamsToUpload;
@@ -110,9 +111,7 @@ public class Uploader extends FileActivity
     private boolean mAccountSelectionShowing;
 
     private final static int DIALOG_NO_ACCOUNT = 0;
-    private final static int DIALOG_NO_STREAM = 2;
-    private final static int DIALOG_MULTIPLE_ACCOUNT = 3;
-    private final static int DIALOG_STREAM_UNKNOWN = 4;
+    private final static int DIALOG_MULTIPLE_ACCOUNT = 1;
 
     private final static int REQUEST_CODE__SETUP_ACCOUNT = REQUEST_CODE__LAST_SHARED + 1;
 
@@ -180,8 +179,17 @@ public class Uploader extends FileActivity
                 }
             }
 
+        } else if (getIntent().getStringExtra(Intent.EXTRA_TEXT) != null) {
+            showErrorDialog(
+                R.string.uploader_error_message_received_piece_of_text,
+                R.string.uploader_error_title_no_file_to_upload
+            );
+
         } else {
-            showDialog(DIALOG_NO_STREAM);
+            showErrorDialog(
+                R.string.uploader_error_message_no_file_to_upload,
+                R.string.uploader_error_title_no_file_to_upload
+            );
         }
 
         super.setAccount(account, savedAccount);
@@ -219,17 +227,6 @@ public class Uploader extends FileActivity
     @Override
     protected Dialog onCreateDialog(final int id) {
         final AlertDialog.Builder builder = new Builder(this);
-        // Create key listener for back button pressed
-        DialogInterface.OnKeyListener onKeyListener = new DialogInterface.OnKeyListener() {
-            @Override
-            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
-                if (keyCode == KeyEvent.KEYCODE_BACK) {
-                    Uploader.super.onBackPressed();
-                    dialog.dismiss();
-                }
-                return true;
-            }
-        };
         switch (id) {
         case DIALOG_NO_ACCOUNT:
             builder.setIcon(R.drawable.ic_warning);
@@ -297,55 +294,11 @@ public class Uploader extends FileActivity
                 }
             });
             return builder.create();
-        case DIALOG_NO_STREAM:
-            builder.setIcon(R.drawable.ic_warning);
-            builder.setTitle(R.string.uploader_wrn_no_content_title);
-            builder.setMessage(R.string.uploader_wrn_no_content_text);
-            builder.setCancelable(false);
-            builder.setNegativeButton(R.string.common_back, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    finish();
-                }
-            });
-            builder.setOnKeyListener(onKeyListener);
-            return builder.create();
-        case DIALOG_STREAM_UNKNOWN:
-            builder.setIcon(android.R.drawable.ic_dialog_alert);
-            builder.setTitle(R.string.uploader_wrn_unknown_content_title);
-            String message = String.format(getString(R.string.uploader_error_forbidden_content),
-                getString(R.string.app_name));
-            builder.setMessage(message);
-            builder.setCancelable(false);
-            builder.setNegativeButton(R.string.common_back, new OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    finish();
-                }
-            });
-            builder.setOnKeyListener(onKeyListener);
-            return builder.create();
         default:
             throw new IllegalArgumentException("Unknown dialog id: " + id);
         }
     }
 
-    class a implements OnClickListener {
-        String mPath;
-        EditText mDirname;
-
-        public a(String path, EditText dirname) {
-            mPath = path;
-            mDirname = dirname;
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            Uploader.this.mUploadPath = mPath + mDirname.getText().toString();
-            uploadFiles();
-        }
-    }
-
     @Override
     public void onBackPressed() {
         if (mParents.size() <= 1) {
@@ -391,12 +344,7 @@ public class Uploader extends FileActivity
                     mUploadPath += p + OCFile.PATH_SEPARATOR;
                 }
                 Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
-
-                try {
-                    uploadFiles();
-                } catch (SecurityException e) {
-                    showDialog(DIALOG_STREAM_UNKNOWN);  // TODO: _FORBIDDEN
-                }
+                uploadFiles();
                 break;
 
             case R.id.uploader_cancel:
@@ -513,7 +461,7 @@ public class Uploader extends FileActivity
 
     private void prepareStreamsToUpload() {
         if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
-            mStreamsToUpload = new ArrayList<Parcelable>();
+            mStreamsToUpload = new ArrayList<>();
             mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
         } else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
             mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
@@ -527,20 +475,20 @@ public class Uploader extends FileActivity
     @SuppressLint("NewApi")
     public void uploadFiles() {
 
-        List<Uri> contentUris = new ArrayList<>();
-        List<String> contentRemotePaths = new ArrayList<>();
+        try {
 
-        for (Parcelable sourceStream : mStreamsToUpload) {
-            Uri sourceUri = (Uri) sourceStream;
-            if (sourceUri == null) {
-                showDialog(DIALOG_NO_STREAM);
+            List<Uri> contentUris = new ArrayList<>();
+            List<String> contentRemotePaths = new ArrayList<>();
 
-            } else {
-                String displayName = UriUtils.getDisplayNameForUri(sourceUri, this);
-                if(displayName == null) {
-                    showDialog(DIALOG_NO_STREAM);   // TODO - different dialog?
+            int schemeFileCounter = 0;
 
-                } else {
+            for (Parcelable sourceStream : mStreamsToUpload) {
+                Uri sourceUri = (Uri) sourceStream;
+                if (sourceUri != null) {
+                    String displayName = UriUtils.getDisplayNameForUri(sourceUri, this);
+                    if (displayName == null) {
+                        displayName = generateDiplayName();
+                    }
                     String remotePath = mUploadPath + displayName;
 
                     if (ContentResolver.SCHEME_CONTENT.equals(sourceUri.getScheme())) {
@@ -550,31 +498,56 @@ public class Uploader extends FileActivity
                     } else if (ContentResolver.SCHEME_FILE.equals(sourceUri.getScheme())) {
                         /// file: uris should point to a local file, should be safe let FileUploader handle them
                         requestUpload(sourceUri.getPath(), remotePath);
-
-                    } else {
-                        showDialog(DIALOG_STREAM_UNKNOWN);
+                        schemeFileCounter++;
                     }
                 }
             }
-        }
 
-        if(!contentUris.isEmpty()) {
-            /// content: uris will be copied to temporary files before calling {@link FileUploader}
-            copyThenUpload(contentUris.toArray(new Uri[contentUris.size()]),
-                contentRemotePaths.toArray(new String[contentRemotePaths.size()]));
-        }
+            if (!contentUris.isEmpty()) {
+                /// content: uris will be copied to temporary files before calling {@link FileUploader}
+                copyThenUpload(contentUris.toArray(new Uri[contentUris.size()]),
+                    contentRemotePaths.toArray(new String[contentRemotePaths.size()]));
+
+            } else if (schemeFileCounter == 0) {
+                showErrorDialog(
+                    R.string.uploader_error_message_no_file_to_upload,
+                    R.string.uploader_error_title_no_file_to_upload
+                );
+
+            } else {
+                finish();
+            }
 
-        // Save the path to shared preferences; even if upload is not possible, user chose the folder
-        SharedPreferences.Editor appPrefs = PreferenceManager
-            .getDefaultSharedPreferences(getApplicationContext()).edit();
-        appPrefs.putString("last_upload_path", mUploadPath);
-        appPrefs.apply();
+        } catch (SecurityException e) {
+            Log_OC.e(TAG, "Permissions fail", e);
+            showErrorDialog(
+                R.string.uploader_error_message_read_permission_not_granted,
+                R.string.uploader_error_title_file_cannot_be_uploaded
+            );
+
+        } catch (Exception e) {
+            Log_OC.e(TAG, "Unexpted error", e);
+            showErrorDialog(
+                R.string.common_error_unknown,
+                R.string.uploader_error_title_file_cannot_be_uploaded
+            );
+
+        } finally {
+            // Save the path to shared preferences; even if upload is not possible, user chose the folder
+            SharedPreferences.Editor appPrefs = PreferenceManager
+                .getDefaultSharedPreferences(getApplicationContext()).edit();
+            appPrefs.putString("last_upload_path", mUploadPath);
+            appPrefs.apply();
 
-        if(contentUris.isEmpty()) {
-            finish();
         }
     }
 
+
+    private String generateDiplayName() {
+        return getString(R.string.common_unknown) +
+            "-" + DisplayUtils.unixTimeToHumanReadable(System.currentTimeMillis());
+    }
+
     /**
      *
      * @param sourceUris        Array of content:// URIs to the files to upload
@@ -830,12 +803,7 @@ public class Uploader extends FileActivity
     @Override
     public void onTmpFilesCopied(ResultCode result) {
         dismissWaitingCopyDialog();
-        if (result != ResultCode.OK) {
-            showDialog(DIALOG_STREAM_UNKNOWN);  // TODO BETTER ERROR DIALOGS!
-
-        } else {
-            finish();
-        }
+        finish();
     }
 
     /**
@@ -864,6 +832,42 @@ public class Uploader extends FileActivity
     }
 
 
+    /**
+     * Show an error dialog, forcing the user to click a single button to exit the activity
+     *
+     * @param messageResId      Resource id of the message to show in the dialog.
+     * @param messageResTitle   Resource id of the title to show in the dialog. 0 to show default alert message.
+     *                          -1 to show no title.
+     */
+    private void showErrorDialog(int messageResId, int messageResTitle) {
+
+        ConfirmationDialogFragment errorDialog = ConfirmationDialogFragment.newInstance(
+            messageResId,
+            new String[]{getString(R.string.app_name)}, // see uploader_error_message_* in strings.xml
+            messageResTitle,
+            R.string.common_back,
+            -1,
+            -1
+        );
+        errorDialog.setCancelable(false);
+        errorDialog.setOnConfirmationListener(
+            new ConfirmationDialogFragment.ConfirmationDialogFragmentListener() {
+                @Override
+                public void onConfirmation(String callerTag) {
+                    finish();
+                }
+
+                @Override
+                public void onNeutral(String callerTag) {}
+
+                @Override
+                public void onCancel(String callerTag) {}
+            }
+        );
+        errorDialog.show(getSupportFragmentManager(), FTAG_ERROR_FRAGMENT);
+    }
+
+
     /**
      * Fragment retaining a background task across configuration changes.
      */

+ 3 - 3
src/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.java

@@ -242,13 +242,13 @@ public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, Result
                 int messageId;
                 switch (result) {
                     case LOCAL_FILE_NOT_FOUND:
-                        messageId = R.string.copy_file_not_found;
+                        messageId = R.string.uploader_error_message_source_file_not_found;
                         break;
                     case LOCAL_STORAGE_NOT_COPIED:
-                        messageId = R.string.copy_file_error;
+                        messageId = R.string.uploader_error_message_source_file_not_copied;
                         break;
                     case FORBIDDEN:
-                        messageId = R.string.uploader_error_forbidden_content;
+                        messageId = R.string.uploader_error_message_read_permission_not_granted;
                         break;
                     default:
                         messageId = R.string.common_error_unknown;

+ 40 - 22
src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java

@@ -27,14 +27,14 @@ import android.os.Bundle;
 import android.support.v4.app.DialogFragment;
 
 import com.owncloud.android.R;
-import com.owncloud.android.lib.common.utils.Log_OC;
 
 
 public class ConfirmationDialogFragment extends DialogFragment {
 
-    public final static String ARG_CONF_RESOURCE_ID = "resource_id";
-    public final static String ARG_CONF_ARGUMENTS = "string_array";
-    
+    public final static String ARG_MESSAGE_RESOURCE_ID = "resource_id";
+    public final static String ARG_MESSAGE_ARGUMENTS = "string_array";
+    private static final String ARG_TITLE_ID = "title_id";
+
     public final static String ARG_POSITIVE_BTN_RES = "positive_btn_res";
     public final static String ARG_NEUTRAL_BTN_RES = "neutral_btn_res";
     public final static String ARG_NEGATIVE_BTN_RES = "negative_btn_res";
@@ -46,18 +46,33 @@ public class ConfirmationDialogFragment extends DialogFragment {
     /**
      * Public factory method to create new ConfirmationDialogFragment instances.
      * 
-     * @param string_id         Resource id for a message to show in the dialog.
-     * @param arguments         Arguments to complete the message, if it's a format string.
-     * @param posBtn            Resource id for the text of the positive button.
-     * @param neuBtn            Resource id for the text of the neutral button.
-     * @param negBtn            Resource id for the text of the negative button.
+     * @param messageResId      Resource id for a message to show in the dialog.
+     * @param messageArguments  Arguments to complete the message, if it's a format string. May be null.
+     * @param titleResId        Resource id for a text to show in the title.
+     *                          0 for default alert title, -1 for no title.
+     * @param posBtn            Resource id for the text of the positive button. -1 for no positive button.
+     * @param neuBtn            Resource id for the text of the neutral button. -1 for no neutral button.
+     * @param negBtn            Resource id for the text of the negative button. -1 for no negative button.
      * @return                  Dialog ready to show.
      */
-    public static ConfirmationDialogFragment newInstance(int string_id, String[] arguments, int posBtn, int neuBtn, int negBtn) {
+    public static ConfirmationDialogFragment newInstance(
+        int messageResId,
+        String[] messageArguments,
+        int titleResId,
+        int posBtn,
+        int neuBtn,
+        int negBtn
+    ) {
+
+        if (messageResId == -1) {
+            throw new IllegalStateException("Calling confirmation dialog without message resource");
+        }
+
         ConfirmationDialogFragment frag = new ConfirmationDialogFragment();
         Bundle args = new Bundle();
-        args.putInt(ARG_CONF_RESOURCE_ID, string_id);
-        args.putStringArray(ARG_CONF_ARGUMENTS, arguments);
+        args.putInt(ARG_MESSAGE_RESOURCE_ID, messageResId);
+        args.putStringArray(ARG_MESSAGE_ARGUMENTS, messageArguments);
+        args.putInt(ARG_TITLE_ID, titleResId);
         args.putInt(ARG_POSITIVE_BTN_RES, posBtn);
         args.putInt(ARG_NEUTRAL_BTN_RES, neuBtn);
         args.putInt(ARG_NEGATIVE_BTN_RES, negBtn);
@@ -71,25 +86,28 @@ public class ConfirmationDialogFragment extends DialogFragment {
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        Object[] confirmationTarget = getArguments().getStringArray(ARG_CONF_ARGUMENTS);
-        int resourceId = getArguments().getInt(ARG_CONF_RESOURCE_ID, -1);
+        Object[] messageArguments = getArguments().getStringArray(ARG_MESSAGE_ARGUMENTS);
+        int messageId = getArguments().getInt(ARG_MESSAGE_RESOURCE_ID, -1);
+        int titleId = getArguments().getInt(ARG_TITLE_ID, -1);
         int posBtn = getArguments().getInt(ARG_POSITIVE_BTN_RES, -1);
         int neuBtn = getArguments().getInt(ARG_NEUTRAL_BTN_RES, -1);
         int negBtn = getArguments().getInt(ARG_NEGATIVE_BTN_RES, -1);
         
-        if (confirmationTarget == null || resourceId == -1) {
-            Log_OC.wtf(getTag(), "Calling confirmation dialog without resource or arguments");
-            return null;
+        if (messageArguments == null) {
+            messageArguments = new String[]{};
         }
 
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.Theme_ownCloud_Dialog)
             .setIcon(R.drawable.ic_warning)
-            .setMessage(String.format(getString(resourceId), confirmationTarget))
-            .setTitle(android.R.string.dialog_alert_title);
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
-            builder.setIconAttribute(android.R.attr.alertDialogIcon);
+            .setIconAttribute(android.R.attr.alertDialogIcon)
+            .setMessage(String.format(getString(messageId), messageArguments));
+
+        if (titleId == 0) {
+            builder.setTitle(android.R.string.dialog_alert_title);
+        } else if (titleId != -1) {
+            builder.setTitle(titleId);
         }
-        
+
         if (posBtn != -1)
             builder.setPositiveButton(posBtn,
                     new DialogInterface.OnClickListener() {

+ 2 - 2
src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java

@@ -62,8 +62,8 @@ implements ConfirmationDialogFragmentListener {
             negBtn = R.string.confirmation_remove_local;
         }
         
-        args.putInt(ARG_CONF_RESOURCE_ID, messageStringId);
-        args.putStringArray(ARG_CONF_ARGUMENTS, new String[]{file.getFileName()});
+        args.putInt(ARG_MESSAGE_RESOURCE_ID, messageStringId);
+        args.putStringArray(ARG_MESSAGE_ARGUMENTS, new String[]{file.getFileName()});
         args.putInt(ARG_POSITIVE_BTN_RES, R.string.common_yes);
         args.putInt(ARG_NEUTRAL_BTN_RES, R.string.common_no);
         args.putInt(ARG_NEGATIVE_BTN_RES, negBtn);