diff --git a/src/main/java/com/owncloud/android/operations/CommentFileOperation.java b/src/main/java/com/owncloud/android/operations/CommentFileOperation.java new file mode 100644 index 000000000000..3a6f6758b4b1 --- /dev/null +++ b/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 . + */ + +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 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; + } +} diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java index a4f5fca1f548..f0f6fa6ccc8a 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java @@ -26,8 +26,11 @@ import android.accounts.OperationCanceledException; import android.content.Context; import android.graphics.PorterDuff; +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; @@ -57,6 +60,7 @@ 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; @@ -71,6 +75,7 @@ import butterknife.BindString; import butterknife.BindView; import butterknife.ButterKnife; +import butterknife.OnClick; import butterknife.Unbinder; public class FileDetailActivitiesFragment extends Fragment implements ActivityListInterface, VersionListInterface.View { @@ -113,14 +118,19 @@ public class FileDetailActivitiesFragment extends Fragment implements ActivityLi @BindView(android.R.id.list) public RecyclerView recyclerView; + @BindView(R.id.commentInputField) + public TextInputEditText commentInput; + @BindString(R.string.activities_no_results_headline) public String noResultsHeadline; @BindString(R.string.activities_no_results_message) public String noResultsMessage; + private boolean restoreFileVersionSupported; private String userId; private FileOperationsHelper operationsHelper; + private VersionListInterface.CommentCallback callback; public static FileDetailActivitiesFragment newInstance(OCFile file, Account account) { FileDetailActivitiesFragment fragment = new FileDetailActivitiesFragment(); @@ -154,19 +164,43 @@ public View onCreateView(@NonNull LayoutInflater inflater, fetchAndSetData(null); - swipeListRefreshLayout.setOnRefreshListener( - () -> onRefreshListLayout(swipeListRefreshLayout)); - swipeEmptyListRefreshLayout.setOnRefreshListener( - () -> onRefreshListLayout(swipeEmptyListRefreshLayout)); + swipeListRefreshLayout.setOnRefreshListener(() -> onRefreshListLayout(swipeListRefreshLayout)); + swipeEmptyListRefreshLayout.setOnRefreshListener(() -> onRefreshListLayout(swipeEmptyListRefreshLayout)); AccountManager accountManager = AccountManager.get(getContext()); userId = accountManager.getUserData(account, com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID); + callback = 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(); + } + }; + + commentInput.getBackground().setColorFilter( + ThemeUtils.primaryAccentColor(getContext()), + PorterDuff.Mode.SRC_ATOP + ); return view; } + @OnClick(R.id.submitComment) + public void submitComment() { + if (commentInput.getText().toString().trim().length() > 0) { + new SubmitCommentTask(commentInput.getText().toString(), userId, file.getLocalId(), + callback, ownCloudClient).execute(); + } + } + private void onRefreshListLayout(SwipeRefreshLayout refreshLayout) { setLoadingMessage(); if (refreshLayout != null && refreshLayout.isRefreshing()) { @@ -389,4 +423,43 @@ public void onSaveInstanceState(@NonNull Bundle outState) { public void onRestoreClicked(FileVersion fileVersion) { operationsHelper.restoreFileVersion(fileVersion, userId); } -} + + private static class SubmitCommentTask extends AsyncTask { + + 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); + + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileFragment.java index 4eeb0d9b2d82..f0d00ea4606d 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/FileFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/FileFragment.java @@ -60,7 +60,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = getArguments(); - setFile((OCFile) bundle.getParcelable(EXTRA_FILE)); + setFile(bundle.getParcelable(EXTRA_FILE)); } /** diff --git a/src/main/java/com/owncloud/android/ui/interfaces/VersionListInterface.java b/src/main/java/com/owncloud/android/ui/interfaces/VersionListInterface.java index 878b48271475..8236314c7f52 100644 --- a/src/main/java/com/owncloud/android/ui/interfaces/VersionListInterface.java +++ b/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); + } } diff --git a/src/main/res/drawable/ic_send.xml b/src/main/res/drawable/ic_send.xml new file mode 100644 index 000000000000..7f73f57c83dc --- /dev/null +++ b/src/main/res/drawable/ic_send.xml @@ -0,0 +1,25 @@ + + + + diff --git a/src/main/res/layout/file_details_activities_fragment.xml b/src/main/res/layout/file_details_activities_fragment.xml index ca619eecbf38..fbc965769e5e 100644 --- a/src/main/res/layout/file_details_activities_fragment.xml +++ b/src/main/res/layout/file_details_activities_fragment.xml @@ -18,36 +18,69 @@ License along with this program. If not, see . --> - + + + + + + + + + android:visibility="visible"/> - + - + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 8e3e2c3aa810..ed000f77823c 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -799,6 +799,8 @@ Use anything like a pattern, password, pin or your fingerprint to keep your data safe. Restore file New version was created + New comment… + Error commenting file Successfully restored file version. Error restoring file version! The server has reached end of life, please upgrade!