Jelajahi Sumber

Merge pull request #5593 from nextcloud/fix-synced-folder-dialog-click

Synced folder dialog: fix summary click event intercepting parent
Tobias Kaminsky 4 tahun lalu
induk
melakukan
969c0d3916

+ 1 - 1
src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java

@@ -78,7 +78,7 @@ import butterknife.BindView;
 import butterknife.ButterKnife;
 
 /**
- * This Adapter populates a ListView with following types of uploads: pending,active, completed. Filtering possible.
+ * This Adapter populates a ListView with following types of uploads: pending, active, completed. Filtering possible.
  */
 public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedViewHolder> {
     private static final String TAG = UploadListAdapter.class.getSimpleName();

+ 9 - 31
src/main/java/com/owncloud/android/ui/dialog/LocalStoragePathPickerDialogFragment.java

@@ -23,7 +23,6 @@ package com.owncloud.android.ui.dialog;
 import android.annotation.SuppressLint;
 import android.app.Dialog;
 import android.content.DialogInterface;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.view.LayoutInflater;
@@ -139,48 +138,27 @@ public class LocalStoragePathPickerDialogFragment extends DialogFragment
     private List<StoragePathItem> getPathList() {
         List<StoragePathItem> storagePathItems = new ArrayList<>();
 
-        addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_image_grey600,
-                                                          getString(R.string.storage_pictures),
-                                                          Environment.getExternalStoragePublicDirectory(
-                                                              Environment.DIRECTORY_PICTURES).getAbsolutePath()));
-        addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_camera, getString(R.string.storage_camera),
-                                                          Environment.getExternalStoragePublicDirectory(
-                                                              Environment.DIRECTORY_DCIM).getAbsolutePath()));
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_document_grey600,
-                                                              getString(R.string.storage_documents),
-                                                              Environment.getExternalStoragePublicDirectory(
-                                                                  Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()));
+        for (FileStorageUtils.StandardDirectory standardDirectory : FileStorageUtils.StandardDirectory.getStandardDirectories()) {
+            addIfExists(storagePathItems, standardDirectory.getIcon(), getString(standardDirectory.getDisplayName()),
+                Environment.getExternalStoragePublicDirectory(standardDirectory.getName()).getAbsolutePath());
         }
-        addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_download_grey600,
-                                                          getString(R.string.storage_downloads),
-                                                          Environment.getExternalStoragePublicDirectory(
-                                                              Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()));
-        addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_movie_grey600,
-                                                          getString(R.string.storage_movies),
-                                                          Environment.getExternalStoragePublicDirectory(
-                                                              Environment.DIRECTORY_MOVIES).getAbsolutePath()));
-        addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_music_grey600,
-                                                          getString(R.string.storage_music),
-                                                          Environment.getExternalStoragePublicDirectory(
-                                                              Environment.DIRECTORY_MUSIC).getAbsolutePath()));
 
         String sdCard = getString(R.string.storage_internal_storage);
         for (String dir : FileStorageUtils.getStorageDirectories(requireActivity())) {
             if (internalStoragePaths.contains(dir)) {
-                addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_sd_grey600, sdCard, dir));
+                addIfExists(storagePathItems, R.drawable.ic_sd_grey600, sdCard, dir);
             } else {
-                addIfExists(storagePathItems, new StoragePathItem(R.drawable.ic_sd_grey600, new File(dir).getName(), dir));
+                addIfExists(storagePathItems, R.drawable.ic_sd_grey600, new File(dir).getName(), dir);
             }
         }
 
         return storagePathItems;
     }
 
-    private void addIfExists(List<StoragePathItem> storagePathItems, StoragePathItem item) {
-        File path = new File(item.getPath());
-        if (path.exists() && path.canRead()) {
-            storagePathItems.add(item);
+    private void addIfExists(List<StoragePathItem> storagePathItems, int icon, String name, String path) {
+        File file = new File(path);
+        if (file.exists() && file.canRead()) {
+            storagePathItems.add(new StoragePathItem(icon, name, path));
         }
     }
 

+ 15 - 27
src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java

@@ -46,6 +46,7 @@ import com.owncloud.android.ui.activity.FolderPickerActivity;
 import com.owncloud.android.ui.activity.UploadFilesActivity;
 import com.owncloud.android.ui.dialog.parcel.SyncedFolderParcelable;
 import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.ThemeUtils;
 
 import java.io.File;
@@ -218,7 +219,10 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment {
                                     mSyncedFolder.getLocalPath()),
                             mSyncedFolder.getFolderName(),
                             new StyleSpan(Typeface.BOLD)));
-            mLocalFolderSummary.setText(mSyncedFolder.getLocalPath());
+            mLocalFolderSummary.setText(FileStorageUtils.pathToUserFriendlyDisplay(
+                mSyncedFolder.getLocalPath(),
+                getActivity(),
+                getResources()));
         } else {
             mLocalFolderSummary.setText(R.string.choose_local_folder);
         }
@@ -272,11 +276,11 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment {
      * to the underlying activity since the picker is an activity and the result can't get passed to the dialog
      * fragment directly.
      *
-     * @param path the remote path to be set
+     * @param path the local path to be set
      */
     public void setLocalFolderSummary(String path) {
         mSyncedFolder.setLocalPath(path);
-        mLocalFolderSummary.setText(path);
+        mLocalFolderSummary.setText(FileStorageUtils.pathToUserFriendlyDisplay(path, getActivity(), getResources()));
         mLocalFolderPath.setText(
                 DisplayUtils.createTextWithSpan(
                         String.format(
@@ -409,32 +413,16 @@ public class SyncedFolderPreferencesDialogFragment extends DialogFragment {
                     }
                 });
 
-        view.findViewById(R.id.remote_folder_container).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
-                getActivity().startActivityForResult(action, REQUEST_CODE__SELECT_REMOTE_FOLDER);
-            }
-        });
-
-        mRemoteFolderSummary.setOnClickListener(textView -> {
-            mRemoteFolderSummary.setEllipsize(null);
-            mRemoteFolderSummary.setMaxLines(Integer.MAX_VALUE);
-        });
-
-        view.findViewById(R.id.local_folder_container).setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent action = new Intent(getActivity(), UploadFilesActivity.class);
-                action.putExtra(UploadFilesActivity.KEY_LOCAL_FOLDER_PICKER_MODE, true);
-                action.putExtra(REQUEST_CODE_KEY, REQUEST_CODE__SELECT_LOCAL_FOLDER);
-                getActivity().startActivityForResult(action, REQUEST_CODE__SELECT_LOCAL_FOLDER);
-            }
+        view.findViewById(R.id.remote_folder_container).setOnClickListener(v -> {
+            Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+            getActivity().startActivityForResult(action, REQUEST_CODE__SELECT_REMOTE_FOLDER);
         });
 
-        mLocalFolderSummary.setOnClickListener(textView -> {
-            mLocalFolderSummary.setEllipsize(null);
-            mLocalFolderSummary.setMaxLines(Integer.MAX_VALUE);
+        view.findViewById(R.id.local_folder_container).setOnClickListener(v -> {
+            Intent action = new Intent(getActivity(), UploadFilesActivity.class);
+            action.putExtra(UploadFilesActivity.KEY_LOCAL_FOLDER_PICKER_MODE, true);
+            action.putExtra(REQUEST_CODE_KEY, REQUEST_CODE__SELECT_LOCAL_FOLDER);
+            getActivity().startActivityForResult(action, REQUEST_CODE__SELECT_LOCAL_FOLDER);
         });
 
         view.findViewById(R.id.sync_enabled).setOnClickListener(new OnClickListener() {

+ 138 - 0
src/main/java/com/owncloud/android/utils/FileStorageUtils.java

@@ -25,6 +25,7 @@ import android.annotation.TargetApi;
 import android.app.Activity;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Environment;
@@ -33,6 +34,7 @@ import android.util.Log;
 import android.webkit.MimeTypeMap;
 
 import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -48,12 +50,16 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.TimeZone;
 
+import javax.annotation.Nullable;
+
 import androidx.core.app.ActivityCompat;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
@@ -535,6 +541,47 @@ public final class FileStorageUtils {
         return rv;
     }
 
+    /**
+     * Update the local path summary display. If a special directory is recognized, it is replaced by its name.
+     *
+     * Example: /storage/emulated/0/Movies -> Internal Storage / Movies
+     * Example: /storage/ABC/non/standard/directory -> ABC /non/standard/directory
+     *
+     * @param path the path to display
+     * @return a user friendly path as defined in examples, or {@param path} if the storage device isn't recognized.
+     */
+    public static String pathToUserFriendlyDisplay(String path, Activity activity, Resources resources) {
+        // Determine storage device (external, sdcard...)
+        String storageDevice = null;
+        for (String storageDirectory : FileStorageUtils.getStorageDirectories(activity)) {
+            if (path.startsWith(storageDirectory)) {
+                storageDevice = storageDirectory;
+                break;
+            }
+        }
+
+        // If storage device was not found, display full path
+        if (storageDevice == null) {
+            return path;
+        }
+
+        // Default to full path without storage device path
+        String storageFolder = path.substring(storageDevice.length() + 1);
+        FileStorageUtils.StandardDirectory standardDirectory = FileStorageUtils.StandardDirectory.fromPath(storageFolder);
+        if (standardDirectory != null) { // Friendly name of standard directory
+            storageFolder = " " + resources.getString(standardDirectory.getDisplayName());
+        }
+
+        // Shorten the storage device to a friendlier display name
+        if (storageDevice.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath())) {
+            storageDevice = resources.getString(R.string.storage_internal_storage);
+        } else {
+            storageDevice = new File(storageDevice).getName();
+        }
+
+        return resources.getString(R.string.local_folder_friendly_path, storageDevice, storageFolder);
+    }
+
     /**
      * Taken from https://github.com/TeamAmaze/AmazeFileManager/blob/d11e0d2874c6067910e58e059859431a31ad6aee/app/src
      * /main/java/com/amaze/filemanager/activities/superclasses/PermissionsActivity.java#L47 on
@@ -582,4 +629,95 @@ public final class FileStorageUtils {
     private static boolean canListFiles(File f) {
         return f.canRead() && f.isDirectory();
     }
+
+    /**
+     * Should be converted to an enum when we only support min SDK version for Environment.DIRECTORY_DOCUMENTS
+     */
+    public static class StandardDirectory {
+        public static final StandardDirectory PICTURES = new StandardDirectory(
+            Environment.DIRECTORY_PICTURES,
+            R.string.storage_pictures,
+            R.drawable.ic_image_grey600
+        );
+        public static final StandardDirectory CAMERA = new StandardDirectory(
+            Environment.DIRECTORY_DCIM,
+            R.string.storage_camera,
+            R.drawable.ic_camera
+        );
+
+        public static final StandardDirectory DOCUMENTS;
+
+        static {
+            if (SDK_INT > Build.VERSION_CODES.KITKAT) {
+                DOCUMENTS = new StandardDirectory(
+                    Environment.DIRECTORY_DOCUMENTS,
+                    R.string.storage_documents,
+                    R.drawable.ic_document_grey600
+                );
+            } else {
+                DOCUMENTS = null;
+            }
+        }
+
+        public static final StandardDirectory DOWNLOADS = new StandardDirectory(
+            Environment.DIRECTORY_DOWNLOADS,
+            R.string.storage_downloads,
+            R.drawable.ic_download_grey600
+        );
+        public static final StandardDirectory MOVIES = new StandardDirectory(
+            Environment.DIRECTORY_MOVIES,
+            R.string.storage_movies,
+            R.drawable.ic_movie_grey600
+        );
+        public static final StandardDirectory MUSIC = new StandardDirectory(
+            Environment.DIRECTORY_MUSIC,
+            R.string.storage_music,
+            R.drawable.ic_music_grey600
+        );
+
+        private final String name;
+        private final int displayNameResource;
+        private final int iconResource;
+
+        private StandardDirectory(String name, int displayNameResource, int iconResource) {
+            this.name = name;
+            this.displayNameResource = displayNameResource;
+            this.iconResource = iconResource;
+        }
+
+        public String getName() {
+            return this.name;
+        }
+
+        public int getDisplayName() {
+            return this.displayNameResource;
+        }
+
+        public int getIcon() {
+            return this.iconResource;
+        }
+
+        public static Collection<StandardDirectory> getStandardDirectories() {
+            Collection<StandardDirectory> standardDirectories = new HashSet<>();
+            standardDirectories.add(PICTURES);
+            standardDirectories.add(CAMERA);
+            if (DOCUMENTS != null) {
+                standardDirectories.add(DOCUMENTS);
+            }
+            standardDirectories.add(DOWNLOADS);
+            standardDirectories.add(MOVIES);
+            standardDirectories.add(MUSIC);
+            return standardDirectories;
+        }
+
+        @Nullable
+        public static StandardDirectory fromPath(String path) {
+            for (StandardDirectory directory : getStandardDirectories()) {
+                if (directory.getName().equals(path)) {
+                    return directory;
+                }
+            }
+            return null;
+        }
+    }
 }

+ 0 - 23
src/main/res/drawable/ic_folder_open.xml

@@ -1,23 +0,0 @@
-<!--
-    @author Google LLC
-    Copyright (C) 2018 Google LLC
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="24dp"
-    android:width="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path android:fillColor="#757575" android:pathData="M20,18H4V8H20M20,6H12L10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6Z" />
-</vector>

+ 40 - 88
src/main/res/layout/synced_folders_settings_layout.xml

@@ -82,107 +82,59 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
-            <LinearLayout
+            <RelativeLayout
                 android:id="@+id/local_folder_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:baselineAligned="false">
+                android:layout_weight="1"
+                android:padding="@dimen/standard_padding">
 
-                <RelativeLayout
-                    android:layout_width="0dp"
+                <TextView
+                    android:id="@+id/local_folder_title"
+                    android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:padding="@dimen/standard_padding">
-
-                    <TextView
-                        android:id="@+id/local_folder_title"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:maxLines="2"
-                        android:text="@string/prefs_synced_folders_local_path_title"
-                        android:textAppearance="?attr/textAppearanceListItem" />
-
-                    <TextView
-                        android:id="@+id/local_folder_summary"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_below="@id/local_folder_title"
-                        android:layout_alignStart="@id/local_folder_title"
-                        android:ellipsize="middle"
-                        android:maxLines="2"
-                        android:text="@string/choose_local_folder"
-                        android:textColor="?android:attr/textColorSecondary" />
-                </RelativeLayout>
-
-                <!-- Preference should place its actual preference widget here. -->
-                <LinearLayout
-                    android:id="@+id/local_folder_frame"
-                    android:layout_width="@dimen/synced_folders_control_width"
-                    android:layout_height="match_parent"
-                    android:gravity="center"
-                    android:padding="@dimen/standard_padding">
+                    android:maxLines="2"
+                    android:text="@string/prefs_synced_folders_local_path_title"
+                    android:textAppearance="?attr/textAppearanceListItem" />
 
-                    <ImageView
-                        android:id="@+id/local_folder_icon"
-                        android:layout_width="wrap_content"
-                        android:layout_height="fill_parent"
-                        android:background="@null"
-                        android:contentDescription="@string/folder_icon"
-                        android:padding="@dimen/standard_quarter_padding"
-                        android:src="@drawable/ic_folder_open" />
-                </LinearLayout>
-            </LinearLayout>
+                <TextView
+                    android:id="@+id/local_folder_summary"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_below="@id/local_folder_title"
+                    android:layout_alignStart="@id/local_folder_title"
+                    android:ellipsize="middle"
+                    android:maxLines="2"
+                    android:text="@string/choose_local_folder"
+                    android:textColor="?android:attr/textColorSecondary" />
+            </RelativeLayout>
 
-            <LinearLayout
+            <RelativeLayout
                 android:id="@+id/remote_folder_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:baselineAligned="false">
+                android:layout_weight="1"
+                android:padding="@dimen/standard_padding">
 
-                <RelativeLayout
-                    android:layout_width="0dp"
+                <TextView
+                    android:id="@+id/remote_folder_title"
+                    android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    android:padding="@dimen/standard_padding">
-
-                    <TextView
-                        android:id="@+id/remote_folder_title"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:maxLines="2"
-                        android:text="@string/prefs_synced_folders_remote_path_title"
-                        android:textAppearance="?attr/textAppearanceListItem" />
-
-                    <TextView
-                        android:id="@+id/remote_folder_summary"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_below="@id/remote_folder_title"
-                        android:layout_alignStart="@id/remote_folder_title"
-                        android:ellipsize="middle"
-                        android:maxLines="2"
-                        android:text="@string/choose_remote_folder"
-                        android:textColor="?android:attr/textColorSecondary" />
-                </RelativeLayout>
-
-                <!-- Preference should place its actual preference widget here. -->
-                <LinearLayout
-                    android:id="@+id/remote_folder_frame"
-                    android:layout_width="@dimen/synced_folders_control_width"
-                    android:layout_height="match_parent"
-                    android:gravity="center"
-                    android:padding="@dimen/standard_padding">
+                    android:maxLines="2"
+                    android:text="@string/prefs_synced_folders_remote_path_title"
+                    android:textAppearance="?attr/textAppearanceListItem" />
 
-                    <ImageView
-                        android:id="@+id/remote_folder_icon"
-                        android:layout_width="wrap_content"
-                        android:layout_height="fill_parent"
-                        android:background="@null"
-                        android:contentDescription="@string/folder_icon"
-                        android:padding="@dimen/standard_quarter_padding"
-                        android:src="@drawable/ic_folder_open" />
-                </LinearLayout>
-            </LinearLayout>
+                <TextView
+                    android:id="@+id/remote_folder_summary"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_below="@id/remote_folder_title"
+                    android:layout_alignStart="@id/remote_folder_title"
+                    android:ellipsize="middle"
+                    android:maxLines="2"
+                    android:text="@string/choose_remote_folder"
+                    android:textColor="?android:attr/textColorSecondary" />
+            </RelativeLayout>
 
             <LinearLayout
                 android:id="@+id/setting_instant_upload_on_wifi_container"

+ 0 - 1
src/main/res/layout/upload_list_item.xml

@@ -112,7 +112,6 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:maxLines="1"
-            android:text="@string/auth_username"
             android:textColor="@color/list_item_lastmod_and_filesize_text"
             android:textSize="@dimen/upload_list_item_text_size" />
 

+ 1 - 2
src/main/res/values/strings.xml

@@ -68,7 +68,6 @@
 
     <string name="auth_host_url">Server address https://…</string>
     <string name="auth_username">Username</string>
-    <string name="auth_password">Password</string>
     <string name="sync_string_files">Files</string>
     <string name="uploader_btn_upload_text">Upload</string>
     <string name="uploader_btn_alternative_text">Choose</string>
@@ -541,6 +540,7 @@
     <string name="copy_to">Copy to…</string>
     <string name="choose_remote_folder">Choose remote folder…</string>
     <string name="choose_local_folder">Choose local folder…</string>
+    <string name="local_folder_friendly_path">%1$s /%2$s</string>
     <string name="synced_folders_loading_folders">Loading folders…</string>
     <string name="synced_folders_no_results">No media folders found</string>
     <plurals name="synced_folders_show_hidden_folders">
@@ -676,7 +676,6 @@
     <string name="prefs_category_dev">Dev</string>
     <string name="dev_version_no_information_available">No info available.</string>
     <string name="dev_version_no_new_version_available">No new version available.</string>
-    <string name="folder_icon">Folder icon</string>
     <string name="dev_version_new_version_available">New version available</string>
     <string name="version_dev_download">Download</string>