123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /**
- * ownCloud Android client application
- *
- * @author Bartek Przybylski
- * @author David A. Velasco Copyright (C) 2012 Bartek Przybylski Copyright (C) 2016 ownCloud Inc.
- * <p>
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation.
- * <p>
- * 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.
- * <p/>
- * You should have received a copy of the GNU General Public License along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- */
- package com.owncloud.android.ui.activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.widget.Toast;
- import com.nextcloud.client.account.User;
- import com.nextcloud.java.util.Optional;
- import com.owncloud.android.R;
- import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.datamodel.UploadsStorageManager;
- import com.owncloud.android.db.OCUpload;
- import com.owncloud.android.files.services.FileDownloader;
- import com.owncloud.android.files.services.FileUploader;
- import com.owncloud.android.lib.common.operations.RemoteOperationResult;
- import com.owncloud.android.lib.common.utils.Log_OC;
- import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation;
- import com.owncloud.android.lib.resources.files.model.RemoteFile;
- import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
- import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision;
- import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener;
- import com.owncloud.android.utils.FileStorageUtils;
- import javax.inject.Inject;
- import androidx.annotation.NonNull;
- import androidx.fragment.app.Fragment;
- import androidx.fragment.app.FragmentTransaction;
- /**
- * Wrapper activity which will be launched if keep-in-sync file will be modified by external
- * application.
- */
- public class ConflictsResolveActivity extends FileActivity implements OnConflictDecisionMadeListener {
- /**
- * A nullable upload entry that must be removed when and if the conflict is resolved.
- */
- public static final String EXTRA_CONFLICT_UPLOAD = "CONFLICT_UPLOAD";
- /**
- * Specify the upload local behaviour when there is no CONFLICT_UPLOAD.
- */
- public static final String EXTRA_LOCAL_BEHAVIOUR = "LOCAL_BEHAVIOUR";
- public static final String EXTRA_EXISTING_FILE = "EXISTING_FILE";
- private static final String TAG = ConflictsResolveActivity.class.getSimpleName();
- @Inject UploadsStorageManager uploadsStorageManager;
- private OCUpload conflictUpload;
- private OCFile existingFile;
- private OCFile newFile;
- private int localBehaviour = FileUploader.LOCAL_BEHAVIOUR_FORGET;
- protected OnConflictDecisionMadeListener listener;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null) {
- conflictUpload = savedInstanceState.getParcelable(EXTRA_CONFLICT_UPLOAD);
- existingFile = savedInstanceState.getParcelable(EXTRA_EXISTING_FILE);
- localBehaviour = savedInstanceState.getInt(EXTRA_LOCAL_BEHAVIOUR);
- } else {
- conflictUpload = getIntent().getParcelableExtra(EXTRA_CONFLICT_UPLOAD);
- existingFile = getIntent().getParcelableExtra(EXTRA_EXISTING_FILE);
- localBehaviour = getIntent().getIntExtra(EXTRA_LOCAL_BEHAVIOUR, localBehaviour);
- }
- if (conflictUpload != null) {
- localBehaviour = conflictUpload.getLocalAction();
- }
- // new file was modified locally in file system
- newFile = getFile();
- listener = new OnConflictDecisionMadeListener() {
- @Override
- public void conflictDecisionMade(Decision decision) {
- OCFile file = newFile; // local file got changed, so either upload it or replace it again by server
- // version
- switch (decision) {
- case CANCEL:
- // nothing to do
- break;
- case KEEP_LOCAL: // Upload
- FileUploader.uploadUpdateFile(
- getBaseContext(),
- getAccount(),
- file,
- localBehaviour,
- FileUploader.NameCollisionPolicy.OVERWRITE
- );
- if (conflictUpload != null) {
- uploadsStorageManager.removeUpload(conflictUpload);
- }
- break;
- case KEEP_BOTH: // Upload
- FileUploader.uploadUpdateFile(
- getBaseContext(),
- getAccount(),
- file,
- localBehaviour,
- FileUploader.NameCollisionPolicy.RENAME
- );
- if (conflictUpload != null) {
- uploadsStorageManager.removeUpload(conflictUpload);
- }
- break;
- case KEEP_SERVER: // Download
- if (!shouldDeleteLocal()) {
- // Overwrite local file
- Intent intent = new Intent(getBaseContext(), FileDownloader.class);
- intent.putExtra(FileDownloader.EXTRA_ACCOUNT, getAccount());
- intent.putExtra(FileDownloader.EXTRA_FILE, file);
- if (conflictUpload != null) {
- intent.putExtra(FileDownloader.EXTRA_CONFLICT_UPLOAD, conflictUpload);
- }
- startService(intent);
- }
- break;
- }
- finish();
- }
- };
- }
- @Override
- protected void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putParcelable(EXTRA_CONFLICT_UPLOAD, conflictUpload);
- outState.putParcelable(EXTRA_EXISTING_FILE, existingFile);
- outState.putInt(EXTRA_LOCAL_BEHAVIOUR, localBehaviour);
- }
- @Override
- public void conflictDecisionMade(Decision decision) {
- listener.conflictDecisionMade(decision);
- }
- @Override
- protected void onStart() {
- super.onStart();
- if (getAccount() == null) {
- finish();
- }
- if (newFile == null) {
- Log_OC.e(TAG, "No file received");
- finish();
- }
- if (existingFile == null) {
- // fetch info of existing file from server
- ReadFileRemoteOperation operation = new ReadFileRemoteOperation(newFile.getRemotePath());
- new Thread(() -> {
- try {
- RemoteOperationResult result = operation.execute(getAccount(), this);
- if (result.isSuccess()) {
- existingFile = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0));
- existingFile.setLastSyncDateForProperties(System.currentTimeMillis());
- startDialog();
- } else {
- showErrorAndFinish();
- }
- } catch (Exception e) {
- showErrorAndFinish();
- }
- }).start();
- } else {
- startDialog();
- }
- }
- private void startDialog() {
- Optional<User> userOptional = getUser();
- if (!userOptional.isPresent()) {
- showErrorAndFinish();
- }
- // Check whether the file is contained in the current Account
- Fragment prev = getSupportFragmentManager().findFragmentByTag("conflictDialog");
- FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
- if (prev != null) {
- fragmentTransaction.remove(prev);
- }
- if (existingFile != null && getStorageManager().fileExists(newFile.getRemotePath())) {
- ConflictsResolveDialog dialog = ConflictsResolveDialog.newInstance(existingFile,
- newFile,
- userOptional.get());
- dialog.show(fragmentTransaction, "conflictDialog");
- } else {
- // Account was changed to a different one - just finish
- showErrorAndFinish();
- }
- }
- private void showErrorAndFinish() {
- Toast.makeText(this, R.string.conflict_dialog_error, Toast.LENGTH_LONG).show();
- finish();
- }
- /**
- * @return whether the local version of the files is to be deleted.
- */
- private boolean shouldDeleteLocal() {
- return localBehaviour == FileUploader.LOCAL_BEHAVIOUR_DELETE;
- }
- }
|