mirror of
https://github.com/nextcloud/android.git
synced 2024-11-24 06:05:42 +03:00
Add comments
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
parent
1ef3d299e6
commit
5e50b6cf66
10 changed files with 235 additions and 152 deletions
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public void onOverflowIconClicked(View view) {
|
||||
PopupMenu popup = new PopupMenu(getActivity(), view);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,4 +28,10 @@ public interface VersionListInterface {
|
|||
interface View {
|
||||
void onRestoreClicked(FileVersion fileVersion);
|
||||
}
|
||||
|
||||
interface CommentCallback {
|
||||
void onSuccess();
|
||||
|
||||
void onError(int error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue