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

Add comments

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tobiasKaminsky 6 жил өмнө
parent
commit
5e50b6cf66

+ 112 - 0
src/main/java/com/owncloud/android/operations/CommentFileOperation.java

@@ -0,0 +1,112 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud GmbH.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.operations;
+
+import android.util.Log;
+
+import com.google.gson.GsonBuilder;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.operations.common.SyncOperation;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Restore a {@link com.owncloud.android.lib.resources.files.FileVersion}.
+ */
+public class CommentFileOperation extends SyncOperation {
+
+    private static final String TAG = CommentFileOperation.class.getSimpleName();
+    private static final int POST_READ_TIMEOUT = 30000;
+    private static final int POST_CONNECTION_TIMEOUT = 5000;
+
+    private static final String ACTOR_ID = "actorId";
+    private static final String ACTOR_TYPE = "actorType";
+    private static final String ACTOR_TYPE_VALUE = "users";
+    private static final String VERB = "verb";
+    private static final String VERB_VALUE = "comment";
+    private static final String MESSAGE = "message";
+
+    private String message;
+    private String fileId;
+    private String userId;
+
+    /**
+     * Constructor
+     *
+     * @param message Comment to store
+     * @param userId  userId to access correct dav endpoint
+     */
+    public CommentFileOperation(String message, String fileId, String userId) {
+        this.message = message;
+        this.fileId = fileId;
+        this.userId = userId;
+    }
+
+    /**
+     * Performs the operation.
+     *
+     * @param client Client object to communicate with the remote ownCloud server.
+     */
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+
+        RemoteOperationResult result;
+        try {
+            String url = client.getNewWebdavUri(false) + "/comments/files/" + fileId;
+            PostMethod postMethod = new PostMethod(url);
+            postMethod.addRequestHeader("Content-type", "application/json");
+
+            Map<String, String> values = new HashMap<>();
+            values.put(ACTOR_ID, userId);
+            values.put(ACTOR_TYPE, ACTOR_TYPE_VALUE);
+            values.put(VERB, VERB_VALUE);
+            values.put(MESSAGE, message);
+
+            String json = new GsonBuilder().create().toJson(values, Map.class);
+
+            postMethod.setRequestEntity(new StringRequestEntity(json));
+
+            int status = client.executeMethod(postMethod, POST_READ_TIMEOUT, POST_CONNECTION_TIMEOUT);
+
+            result = new RemoteOperationResult(isSuccess(status), postMethod);
+
+            client.exhaustResponse(postMethod.getResponseBodyAsStream());
+        } catch (IOException e) {
+            result = new RemoteOperationResult(e);
+            Log.e(TAG, "Post comment to file with id " + fileId + " failed: " + result.getLogMessage(), e);
+        }
+
+        return result;
+    }
+
+    private boolean isSuccess(int status) {
+        return status == HttpStatus.SC_CREATED;
+    }
+}

+ 0 - 1
src/main/java/com/owncloud/android/ui/activity/ToolbarActivity.java

@@ -36,7 +36,6 @@ import android.widget.ProgressBar;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.utils.ThemeUtils;
 
 /**

+ 0 - 18
src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java

@@ -50,7 +50,6 @@ import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
 import com.owncloud.android.ui.fragment.util.SharingMenuHelper;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ThemeUtils;
-import com.owncloud.android.utils.DisplayUtils;
 
 import java.security.NoSuchAlgorithmException;
 import java.util.List;
@@ -378,23 +377,6 @@ public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.UserVi
         }
     }
 
-    @Override
-    public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
-        if (callContext instanceof ImageView) {
-            ImageView iv = (ImageView) callContext;
-            iv.setImageDrawable(avatarDrawable);
-        }
-    }
-
-    @Override
-    public boolean shouldCallGeneratedCallback(String tag, Object callContext) {
-        if (callContext instanceof ImageView) {
-            ImageView iv = (ImageView) callContext;
-            return String.valueOf(iv.getTag()).equals(tag);
-        }
-        return false;
-    }
-
     public interface ShareeListAdapterListener {
         /**
          * unshare with given sharee {@link OCShare}.

+ 79 - 0
src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java

@@ -30,6 +30,7 @@ import android.os.AsyncTask;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.design.widget.Snackbar;
+import android.support.design.widget.TextInputEditText;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.widget.SwipeRefreshLayout;
@@ -38,6 +39,7 @@ import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
@@ -59,6 +61,7 @@ import com.owncloud.android.lib.resources.files.FileVersion;
 import com.owncloud.android.lib.resources.files.ReadFileVersionsOperation;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+import com.owncloud.android.operations.CommentFileOperation;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.adapter.ActivityAndVersionListAdapter;
@@ -115,6 +118,12 @@ public class FileDetailActivitiesFragment extends Fragment implements ActivityLi
     @BindView(android.R.id.list)
     public RecyclerView recyclerView;
 
+    @BindView(R.id.submitComment)
+    public Button submitComment;
+
+    @BindView(R.id.commentInputField)
+    public TextInputEditText commentInput;
+
     @BindString(R.string.activities_no_results_headline)
     public String noResultsHeadline;
 
@@ -165,10 +174,30 @@ public class FileDetailActivitiesFragment extends Fragment implements ActivityLi
         userId = accountManager.getUserData(account,
                 com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
 
+        submitComment.setOnClickListener((l) -> submitComment(new VersionListInterface.CommentCallback() {
+
+            @Override
+            public void onSuccess() {
+                commentInput.getText().clear();
+                fetchAndSetData(null);
+            }
+
+            @Override
+            public void onError(int error) {
+                Snackbar.make(recyclerView, error, Snackbar.LENGTH_LONG).show();
+            }
+        }));
 
         return view;
     }
 
+    private void submitComment(VersionListInterface.CommentCallback callback) {
+        String message = commentInput.getText().toString();
+        new RestoreFileVersionTask.SubmitCommentTask(message, userId, file.getLocalId(), callback, ownCloudClient)
+                .execute();
+
+    }
+
     private void onRefreshListLayout(SwipeRefreshLayout refreshLayout) {
         setLoadingMessage();
         if (refreshLayout != null && refreshLayout.isRefreshing()) {
@@ -379,6 +408,17 @@ public class FileDetailActivitiesFragment extends Fragment implements ActivityLi
         // TODO implement activity click
     }
 
+    @Override
+    public void onSuccess(String message) {
+        Snackbar.make(recyclerView, message, Snackbar.LENGTH_LONG).show();
+        fetchAndSetData(null);
+    }
+
+    @Override
+    public void onSuccess() {
+        fetchAndSetData(null);
+    }
+
     @Override
     public void onSaveInstanceState(@NonNull Bundle outState) {
         super.onSaveInstanceState(outState);
@@ -391,4 +431,43 @@ public class FileDetailActivitiesFragment extends Fragment implements ActivityLi
     public void onRestoreClicked(FileVersion fileVersion) {
         operationsHelper.restoreFileVersion(fileVersion, userId);
     }
+
+    private static class SubmitCommentTask extends AsyncTask<Void, Void, Boolean> {
+
+        private String message;
+        private String userId;
+        private String fileId;
+        private VersionListInterface.CommentCallback callback;
+        private OwnCloudClient client;
+
+        private SubmitCommentTask(String message, String userId, String fileId,
+                                  VersionListInterface.CommentCallback callback, OwnCloudClient client) {
+            this.message = message;
+            this.userId = userId;
+            this.fileId = fileId;
+            this.callback = callback;
+            this.client = client;
+        }
+
+        @Override
+        protected Boolean doInBackground(Void... voids) {
+            CommentFileOperation commentFileOperation = new CommentFileOperation(message, fileId, userId);
+
+            RemoteOperationResult result = commentFileOperation.execute(client);
+
+            return result.isSuccess();
+        }
+
+        @Override
+        protected void onPostExecute(Boolean success) {
+            super.onPostExecute(success);
+
+            if (success) {
+                callback.onSuccess();
+            } else {
+                callback.onError(R.string.error_comment_file);
+
+            }
+        }
+    }
 }

+ 1 - 120
src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -28,7 +28,6 @@ import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.design.widget.Snackbar;
 import android.support.design.widget.TabLayout;
 import android.support.v4.view.ViewPager;
 import android.view.LayoutInflater;
@@ -39,7 +38,6 @@ import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.PopupMenu;
 import android.widget.ProgressBar;
 import android.widget.TextView;
@@ -68,7 +66,6 @@ import java.lang.ref.WeakReference;
 
 import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.Optional;
 import butterknife.Unbinder;
 
 /**
@@ -126,60 +123,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
     private ToolbarActivity activity;
     private int activeTab;
 
-    @Nullable @BindView(R.id.fdProgressBlock)
-    View downloadProgressContainer;
-
-    @Nullable @BindView(R.id.fdCancelBtn)
-    ImageButton cancelButton;
-
-    @Nullable @BindView(R.id.fdProgressBar)
-    ProgressBar progressBar;
-
-    @Nullable @BindView(R.id.fdProgressText)
-    TextView progressText;
-
-    @Nullable @BindView(R.id.fdFilename)
-    TextView fileName;
-
-    @Nullable @BindView(R.id.fdSize)
-    TextView fileSize;
-
-    @Nullable @BindView(R.id.fdModified)
-    TextView fileModifiedTimestamp;
-
-    @Nullable @BindView(R.id.fdFavorite)
-    ImageView favoriteIcon;
-
-    @Nullable @BindView(R.id.overflow_menu)
-    ImageView overflowMenu;
-
-    @Nullable @BindView(R.id.tab_layout)
-    TabLayout tabLayout;
-
-    @Nullable @BindView(R.id.pager)
-    ViewPager viewPager;
-
-    @Nullable @BindView(R.id.empty_list_view_text)
-    protected TextView emptyContentMessage;
-
-    @Nullable @BindView(R.id.empty_list_view_headline)
-    protected TextView emptyContentHeadline;
-
-    @Nullable @BindView(R.id.empty_list_icon)
-    protected ImageView emptyContentIcon;
-
-    @Nullable @BindView(R.id.empty_list_progress)
-    protected ProgressBar emptyProgressBar;
-
-    private int layout;
-    private View view;
-    private boolean previewLoaded;
-    private Account account;
-    private Unbinder unbinder;
-
-    public ProgressListener progressListener;
-    private ToolbarActivity activity;
-
     /**
      * Public factory method to create new FileDetailFragment instances.
      *
@@ -306,72 +249,10 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
             cancelButton.setOnClickListener(this);
             favoriteIcon.setOnClickListener(this);
             overflowMenu.setOnClickListener(this);
-            cancelButton.setOnClickListener(this);
-            favoriteIcon.setOnClickListener(this);
-            overflowMenu.setOnClickListener(this);
-            // TODO use whenever we switch to use glide for preview images
-            /*
-            if (MimeTypeUtil.isImage(getFile())) {
-                setHeaderImage();
-            }
-             */
-            updateFileDetails(false, false);
-        } else {
-            emptyContentMessage.setText(R.string.filedetails_select_file);
-            emptyContentMessage.setVisibility(View.VISIBLE);
-            emptyContentHeadline.setText(R.string.common_error);
-            emptyContentIcon.setImageDrawable(getContext().getResources().getDrawable(R.drawable.ic_alert_octagon));
-            emptyContentIcon.setVisibility(View.VISIBLE);
-            emptyProgressBar.setVisibility(View.GONE);
-        }
-    }
-    // TODO use whenever we switch to use glide for preview images
-    /*
-    private void setHeaderImage() {
-        if (mContainerActivity.getStorageManager().getCapability(account.name)
-                .getServerBackground() != null && previewImage != null) {
-
-            String background = mContainerActivity.getStorageManager().getCapability(account.name).getServerBackground();
-
-            int primaryColor = ThemeUtils.primaryColor(account, getContext());
-
-            if (URLUtil.isValidUrl(background)) {
-                // background image
-                SimpleTarget target = new SimpleTarget<Drawable>() {
-                    @Override
-                    public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
-                        Drawable[] drawables = {new ColorDrawable(primaryColor), resource};
-                        LayerDrawable layerDrawable = new LayerDrawable(drawables);
-                        previewImage.setImageDrawable(layerDrawable);
-                        previewImage.setVisibility(View.VISIBLE);
-                        ((ToolbarActivity) getActivity()).getSupportActionBar().setTitle(null);
-                        ((ToolbarActivity) getActivity()).getSupportActionBar().setBackgroundDrawable(null);
-                        toolbarProgressBar.setVisibility(View.GONE);
-                        previewLoaded = true;
-                    }
 
-                    @Override
-                    public void onLoadFailed(Exception e, Drawable errorDrawable) {
-                        previewImage.setVisibility(View.GONE);
-                        toolbarProgressBar.setVisibility(View.VISIBLE);
-                    }
-                };
-
-                Glide.with(this)
-                        .load(background)
-                        .centerCrop()
-                        .placeholder(R.drawable.background)
-                        .error(R.drawable.background)
-                        .crossFade()
-                        .into(target);
-            } else {
-                // hide image
-                previewImage.setVisibility(View.GONE);
-                toolbarProgressBar.setVisibility(View.VISIBLE);
-            }
+            updateFileDetails(false, false);
         }
     }
-    */
 
     public void onOverflowIconClicked(View view) {
         PopupMenu popup = new PopupMenu(getActivity(), view);

+ 1 - 1
src/main/java/com/owncloud/android/ui/fragment/FileFragment.java

@@ -60,7 +60,7 @@ public class FileFragment extends Fragment {
         super.onCreate(savedInstanceState);
 
         Bundle bundle = getArguments();
-        setFile((OCFile) bundle.getParcelable(EXTRA_FILE));
+        setFile(bundle.getParcelable(EXTRA_FILE));
     }
 
     /**

+ 6 - 0
src/main/java/com/owncloud/android/ui/interfaces/VersionListInterface.java

@@ -28,4 +28,10 @@ public interface VersionListInterface {
     interface View {
         void onRestoreClicked(FileVersion fileVersion);
     }
+
+    interface CommentCallback {
+        void onSuccess();
+
+        void onError(int error);
+    }
 }

+ 2 - 0
src/main/java/com/owncloud/android/utils/BitmapUtils.java

@@ -34,7 +34,9 @@ import com.owncloud.android.lib.common.utils.Log_OC;
 
 import org.apache.commons.codec.binary.Hex;
 
+import java.io.UnsupportedEncodingException;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.Locale;
 
 /**

+ 32 - 12
src/main/res/layout/file_details_activities_fragment.xml

@@ -18,36 +18,56 @@
   License along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <android.support.design.widget.TextInputEditText
+            android:id="@+id/commentInputField"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:hint="@string/new_comment"/>
+
+        <Button
+            android:id="@+id/submitComment"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="→"/>
+    </LinearLayout>
 
     <android.support.v4.widget.SwipeRefreshLayout
-        android:footerDividersEnabled="false"
         android:id="@+id/swipe_containing_list"
-        android:layout_height="match_parent"
         android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:footerDividersEnabled="false"
         android:visibility="visible">
 
         <android.support.v7.widget.RecyclerView
-            android:clipToPadding="false"
             android:id="@android:id/list"
-            android:layout_height="match_parent"
             android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:clipToPadding="false"
             android:scrollbarStyle="outsideOverlay"
             android:scrollbars="vertical"
-            android:visibility="visible" />
+            android:visibility="visible"/>
 
     </android.support.v4.widget.SwipeRefreshLayout>
 
     <android.support.v4.widget.SwipeRefreshLayout
-        android:footerDividersEnabled="false"
         android:id="@+id/swipe_containing_empty"
-        android:layout_height="match_parent"
         android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:footerDividersEnabled="false"
         android:visibility="visible">
 
-        <include layout="@layout/empty_list" />
+        <include layout="@layout/empty_list"/>
     </android.support.v4.widget.SwipeRefreshLayout>
 
-</FrameLayout>
+</LinearLayout>

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

@@ -799,6 +799,8 @@
     <string name="whats_new_device_credentials_content">Use anything like a pattern, password, pin or your fingerprint to keep your data safe.</string>
     <string name="restore">Restore file</string>
     <string name="new_version_was_created">New version was created</string>
+    <string name="new_comment">New comment…</string>
+    <string name="error_comment_file">Error commenting file</string>
     <string name="file_version_restored_successfully">Successfully restored file version.</string>
     <string name="file_version_restored_error">Error restoring file version!</string>
     <string name="outdated_server">The server has reached end of life, please upgrade!</string>