Merge remote-tracking branch 'origin/master' into dev

This commit is contained in:
Tobias Kaminsky 2023-12-05 03:36:49 +01:00
commit 398e2f2d16
12 changed files with 329 additions and 267 deletions

View file

@ -21,7 +21,7 @@ jobs:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
- name: set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -21,7 +21,7 @@ jobs:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v3
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
- name: set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
if: ${{ steps.check-secrets.outputs.ok == 'true' }}
with:
distribution: "temurin"

View file

@ -40,7 +40,7 @@ jobs:
~/.android/adb*
key: avd-${{ matrix.api-level }}
- uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
- uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v3
with:
distribution: "temurin"
java-version: 17

View file

@ -20,7 +20,7 @@ jobs:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
with:
distribution: "temurin"
java-version: 17

View file

@ -169,6 +169,9 @@
<receiver
android:name="com.nextcloud.client.jobs.NotificationWork$NotificationReceiver"
android:exported="false" />
<receiver
android:name="com.owncloud.android.files.services.FileUploader$UploadNotificationActionReceiver"
android:exported="false" />
<receiver
android:name="com.nextcloud.client.widget.DashboardWidgetProvider"
android:exported="false">

View file

@ -43,6 +43,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.ThumbnailsCacheManager
import com.owncloud.android.datamodel.UploadsStorageManager
import com.owncloud.android.db.OCUpload
import com.owncloud.android.files.services.FileUploader
import com.owncloud.android.lib.common.OwnCloudAccount
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
@ -197,6 +198,18 @@ class FilesUploadWorker(
* adapted from [com.owncloud.android.files.services.FileUploader.notifyUploadStart]
*/
private fun createNotification(uploadFileOperation: UploadFileOperation) {
val notificationActionIntent = Intent(context, FileUploader.UploadNotificationActionReceiver::class.java)
notificationActionIntent.putExtra(FileUploader.EXTRA_ACCOUNT_NAME, uploadFileOperation.user.accountName)
notificationActionIntent.putExtra(FileUploader.EXTRA_REMOTE_PATH, uploadFileOperation.remotePath)
notificationActionIntent.action = FileUploader.ACTION_CANCEL_BROADCAST
val pendingIntent = PendingIntent.getBroadcast(
context,
SecureRandom().nextInt(),
notificationActionIntent,
PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder
.setOngoing(true)
.setSmallIcon(R.drawable.notification_icon)
@ -209,6 +222,8 @@ class FilesUploadWorker(
uploadFileOperation.fileName
)
)
.clearActions() // to make sure there is only one action
.addAction(R.drawable.ic_action_cancel_grey, context.getString(R.string.common_cancel), pendingIntent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD)
@ -275,6 +290,7 @@ class FilesUploadWorker(
.setAutoCancel(true)
.setOngoing(false)
.setProgress(0, 0, false)
.clearActions()
val content = ErrorMessageAdapter.getErrorCauseMessage(uploadResult, uploadFileOperation, context.resources)

View file

@ -34,6 +34,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
@ -128,6 +129,10 @@ public class FileUploader extends Service
public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO";
public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
public static final String EXTRA_ACCOUNT_NAME = "ACCOUNT_NAME";
public static final String ACTION_CANCEL_BROADCAST = "CANCEL";
public static final String ACTION_PAUSE_BROADCAST = "PAUSE";
private static final int FOREGROUND_SERVICE_ID = 411;
public static final String KEY_FILE = "FILE";
@ -198,11 +203,13 @@ public class FileUploader extends Service
private Notification mNotification;
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private IBinder mBinder;
private static IBinder mBinder;
private OwnCloudClient mUploadClient;
private Account mCurrentAccount;
private FileDataStorageManager mStorageManager;
private SecureRandom secureRandomGenerator = new SecureRandom();
@Inject UserAccountManager accountManager;
@Inject UploadsStorageManager mUploadsStorageManager;
@Inject ConnectivityService connectivityService;
@ -233,6 +240,7 @@ public class FileUploader extends Service
/**
* Service initialization
*/
@SuppressFBWarnings("ST")
@Override
public void onCreate() {
super.onCreate();
@ -280,6 +288,7 @@ public class FileUploader extends Service
/**
* Service clean up
*/
@SuppressFBWarnings("ST")
@Override
public void onDestroy() {
Log_OC.v(TAG, "Destroying service");
@ -708,6 +717,12 @@ public class FileUploader extends Service
*/
private void notifyUploadStart(UploadFileOperation upload) {
// / create status notification with a progress bar
Intent notificationActionIntent = new Intent(getApplicationContext(),UploadNotificationActionReceiver.class);
notificationActionIntent.putExtra(EXTRA_ACCOUNT_NAME,upload.getUser().getAccountName());
notificationActionIntent.putExtra(EXTRA_REMOTE_PATH,upload.getRemotePath());
notificationActionIntent.setAction(ACTION_CANCEL_BROADCAST);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),secureRandomGenerator.nextInt(),notificationActionIntent, PendingIntent.FLAG_IMMUTABLE);
mLastPercent = 0;
mNotificationBuilder = NotificationUtils.newNotificationBuilder(this, viewThemeUtils);
mNotificationBuilder
@ -718,7 +733,10 @@ public class FileUploader extends Service
.setProgress(100, 0, false)
.setContentText(
String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName())
);
)
.clearActions() // to make sure there is only one action
.addAction(R.drawable.ic_action_cancel_grey,getApplicationContext().getString(R.string.common_cancel),pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mNotificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD);
@ -811,7 +829,8 @@ public class FileUploader extends Service
.setContentTitle(getString(tickerId))
.setAutoCancel(true)
.setOngoing(false)
.setProgress(0, 0, false);
.setProgress(0, 0, false)
.clearActions();
content = ErrorMessageAdapter.getErrorCauseMessage(uploadResult, upload, getResources());
@ -859,7 +878,7 @@ public class FileUploader extends Service
mNotificationBuilder.setContentText(content);
if (!uploadResult.isSuccess()) {
mNotificationManager.notify((new SecureRandom()).nextInt(), mNotificationBuilder.build());
mNotificationManager.notify(secureRandomGenerator.nextInt(), mNotificationBuilder.build());
}
}
}
@ -1408,4 +1427,32 @@ public class FileUploader extends Service
mService.stopSelf(msg.arg1);
}
}
/**
* When cancel action in upload notification is pressed, cancel upload of item
*/
public static class UploadNotificationActionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String accountName = intent.getStringExtra(EXTRA_ACCOUNT_NAME);
String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
String action = intent.getAction();
if (ACTION_CANCEL_BROADCAST.equals(action)) {
Log_OC.d(TAG, "Cancel broadcast received for file " + remotePath + " at " + System.currentTimeMillis());
if (accountName == null || remotePath == null) return;
FileUploaderBinder uploadBinder = (FileUploaderBinder) mBinder;
uploadBinder.cancel(accountName, remotePath, null);
}else if(ACTION_PAUSE_BROADCAST.equals(action)){
} else {
Log_OC.d(TAG, "Unknown action to perform as UploadNotificationActionReceiver.");
}
}
}
}

View file

@ -1,257 +0,0 @@
/*
* 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.Context;
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.files.services.NameCollisionPolicy;
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_ID = "CONFLICT_UPLOAD_ID";
/**
* 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 long conflictUploadId;
private OCFile existingFile;
private OCFile newFile;
private int localBehaviour = FileUploader.LOCAL_BEHAVIOUR_FORGET;
protected OnConflictDecisionMadeListener listener;
public static Intent createIntent(OCFile file,
User user,
long conflictUploadId,
Integer flag,
Context context) {
Intent intent = new Intent(context, ConflictsResolveActivity.class);
if (flag != null) {
intent.setFlags(intent.getFlags() | flag);
}
intent.putExtra(EXTRA_FILE, file);
intent.putExtra(EXTRA_USER, user);
intent.putExtra(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId);
return intent;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
conflictUploadId = savedInstanceState.getLong(EXTRA_CONFLICT_UPLOAD_ID);
existingFile = savedInstanceState.getParcelable(EXTRA_EXISTING_FILE);
localBehaviour = savedInstanceState.getInt(EXTRA_LOCAL_BEHAVIOUR);
} else {
conflictUploadId = getIntent().getLongExtra(EXTRA_CONFLICT_UPLOAD_ID, -1);
existingFile = getIntent().getParcelableExtra(EXTRA_EXISTING_FILE);
localBehaviour = getIntent().getIntExtra(EXTRA_LOCAL_BEHAVIOUR, localBehaviour);
}
OCUpload upload = uploadsStorageManager.getUploadById(conflictUploadId);
if (upload != null) {
localBehaviour = upload.getLocalAction();
}
// new file was modified locally in file system
newFile = getFile();
listener = decision -> {
OCFile file = newFile; // local file got changed, so either upload it or replace it again by server
// version
User user = getUser().orElseThrow(RuntimeException::new);
switch (decision) {
case CANCEL:
// nothing to do
break;
case KEEP_LOCAL: // Upload
FileUploader.uploadUpdateFile(
getBaseContext(),
user,
file,
localBehaviour,
NameCollisionPolicy.OVERWRITE
);
uploadsStorageManager.removeUpload(upload);
break;
case KEEP_BOTH: // Upload
FileUploader.uploadUpdateFile(
getBaseContext(),
user,
file,
localBehaviour,
NameCollisionPolicy.RENAME
);
uploadsStorageManager.removeUpload(upload);
break;
case KEEP_SERVER: // Download
if (!shouldDeleteLocal()) {
// Overwrite local file
Intent intent = new Intent(getBaseContext(), FileDownloader.class);
intent.putExtra(FileDownloader.EXTRA_USER, getUser().orElseThrow(RuntimeException::new));
intent.putExtra(FileDownloader.EXTRA_FILE, file);
intent.putExtra(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId);
startService(intent);
} else {
uploadsStorageManager.removeUpload(upload);
}
break;
}
finish();
};
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId);
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();
return;
}
if (newFile == null) {
Log_OC.e(TAG, "No file received");
finish();
return;
}
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 {
Log_OC.e(TAG, "ReadFileRemoteOp returned failure with code: " + result.getHttpCode());
showErrorAndFinish();
}
} catch (Exception e) {
Log_OC.e(TAG, "Error when trying to fetch remote file", e);
showErrorAndFinish();
}
}).start();
} else {
startDialog();
}
}
private void startDialog() {
Optional<User> userOptional = getUser();
if (!userOptional.isPresent()) {
Log_OC.e(TAG, "User not present");
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
Log_OC.e(TAG, "Account was changed, finishing");
showErrorAndFinish();
}
}
private void showErrorAndFinish() {
runOnUiThread(() -> 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;
}
}

View file

@ -0,0 +1,249 @@
/*
* 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.Context
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import com.nextcloud.client.account.User
import com.nextcloud.utils.extensions.getParcelableArgument
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.files.services.NameCollisionPolicy
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
/**
* Wrapper activity which will be launched if keep-in-sync file will be modified by external application.
*/
class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener {
@JvmField
@Inject
var uploadsStorageManager: UploadsStorageManager? = null
private var conflictUploadId: Long = 0
private var existingFile: OCFile? = null
private var newFile: OCFile? = null
private var localBehaviour = FileUploader.LOCAL_BEHAVIOUR_FORGET
@JvmField
var listener: OnConflictDecisionMadeListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getArguments(savedInstanceState)
val upload = uploadsStorageManager?.getUploadById(conflictUploadId)
if (upload != null) {
localBehaviour = upload.localAction
}
// new file was modified locally in file system
newFile = file
setupOnConflictDecisionMadeListener(upload)
}
private fun getArguments(savedInstanceState: Bundle?) {
if (savedInstanceState != null) {
conflictUploadId = savedInstanceState.getLong(EXTRA_CONFLICT_UPLOAD_ID)
existingFile = savedInstanceState.getParcelableArgument(EXTRA_EXISTING_FILE, OCFile::class.java)
localBehaviour = savedInstanceState.getInt(EXTRA_LOCAL_BEHAVIOUR)
} else {
conflictUploadId = intent.getLongExtra(EXTRA_CONFLICT_UPLOAD_ID, -1)
existingFile = intent.getParcelableExtra(EXTRA_EXISTING_FILE)
localBehaviour = intent.getIntExtra(EXTRA_LOCAL_BEHAVIOUR, localBehaviour)
}
}
private fun setupOnConflictDecisionMadeListener(upload: OCUpload?) {
listener = OnConflictDecisionMadeListener { decision: Decision? ->
val file = newFile // local file got changed, so either upload it or replace it again by server
// version
val user = user.orElseThrow { RuntimeException() }
when (decision) {
Decision.CANCEL -> {}
Decision.KEEP_LOCAL -> {
FileUploader.uploadUpdateFile(
baseContext,
user,
file,
localBehaviour,
NameCollisionPolicy.OVERWRITE
)
uploadsStorageManager!!.removeUpload(upload)
}
Decision.KEEP_BOTH -> {
FileUploader.uploadUpdateFile(
baseContext,
user,
file,
localBehaviour,
NameCollisionPolicy.RENAME
)
uploadsStorageManager!!.removeUpload(upload)
}
Decision.KEEP_SERVER -> if (!shouldDeleteLocal()) {
// Overwrite local file
val intent = Intent(baseContext, FileDownloader::class.java)
intent.putExtra(FileDownloader.EXTRA_USER, getUser().orElseThrow { RuntimeException() })
intent.putExtra(FileDownloader.EXTRA_FILE, file)
intent.putExtra(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId)
startService(intent)
} else {
uploadsStorageManager!!.removeUpload(upload)
}
else -> {}
}
finish()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putLong(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId)
outState.putParcelable(EXTRA_EXISTING_FILE, existingFile)
outState.putInt(EXTRA_LOCAL_BEHAVIOUR, localBehaviour)
}
override fun conflictDecisionMade(decision: Decision) {
listener?.conflictDecisionMade(decision)
}
override fun onStart() {
super.onStart()
if (account == null) {
finish()
return
}
if (newFile == null) {
Log_OC.e(TAG, "No file received")
finish()
return
}
if (existingFile == null) {
// fetch info of existing file from server
val operation = ReadFileRemoteOperation(newFile!!.remotePath)
@Suppress("TooGenericExceptionCaught")
Thread {
try {
val result = operation.execute(account, this)
if (result.isSuccess) {
existingFile = FileStorageUtils.fillOCFile(result.data[0] as RemoteFile)
existingFile?.lastSyncDateForProperties = System.currentTimeMillis()
startDialog()
} else {
Log_OC.e(TAG, "ReadFileRemoteOp returned failure with code: " + result.httpCode)
showErrorAndFinish()
}
} catch (e: Exception) {
Log_OC.e(TAG, "Error when trying to fetch remote file", e)
showErrorAndFinish()
}
}.start()
} else {
startDialog()
}
}
private fun startDialog() {
val userOptional = user
if (!userOptional.isPresent) {
Log_OC.e(TAG, "User not present")
showErrorAndFinish()
}
// Check whether the file is contained in the current Account
val prev = supportFragmentManager.findFragmentByTag("conflictDialog")
val fragmentTransaction = supportFragmentManager.beginTransaction()
if (prev != null) {
fragmentTransaction.remove(prev)
}
if (existingFile != null && storageManager.fileExists(newFile!!.remotePath)) {
val dialog = ConflictsResolveDialog.newInstance(
existingFile,
newFile,
userOptional.get()
)
dialog.show(fragmentTransaction, "conflictDialog")
} else {
// Account was changed to a different one - just finish
Log_OC.e(TAG, "Account was changed, finishing")
showErrorAndFinish()
}
}
private fun showErrorAndFinish() {
runOnUiThread { 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 fun shouldDeleteLocal(): Boolean {
return localBehaviour == FileUploader.LOCAL_BEHAVIOUR_DELETE
}
companion object {
/**
* A nullable upload entry that must be removed when and if the conflict is resolved.
*/
const val EXTRA_CONFLICT_UPLOAD_ID = "CONFLICT_UPLOAD_ID"
/**
* Specify the upload local behaviour when there is no CONFLICT_UPLOAD.
*/
const val EXTRA_LOCAL_BEHAVIOUR = "LOCAL_BEHAVIOUR"
const val EXTRA_EXISTING_FILE = "EXISTING_FILE"
private val TAG = ConflictsResolveActivity::class.java.simpleName
@JvmStatic
fun createIntent(
file: OCFile?,
user: User?,
conflictUploadId: Long,
flag: Int?,
context: Context?
): Intent {
val intent = Intent(context, ConflictsResolveActivity::class.java)
if (flag != null) {
intent.flags = intent.flags or flag
}
intent.putExtra(EXTRA_FILE, file)
intent.putExtra(EXTRA_USER, user)
intent.putExtra(EXTRA_CONFLICT_UPLOAD_ID, conflictUploadId)
return intent
}
}
}

View file

@ -650,6 +650,8 @@
<string name="remove_e2e">您可以在此客戶端上本機移除端到端加密</string>
<string name="remove_e2e_message">您可以在此客戶端上移除本機端到端加密。已加密的檔案將會保留在伺服器上,但不會再同步到此電腦。</string>
<string name="remove_fail_msg">刪除失敗</string>
<string name="remove_local_account">移除本機帳號</string>
<string name="remove_local_account_details">從裝置移除帳號並刪除所有本機檔案</string>
<string name="remove_notification_failed">移除通知失敗</string>
<string name="remove_push_notification">移除</string>
<string name="remove_success_msg">已刪除</string>
@ -657,6 +659,8 @@
<string name="rename_local_fail_msg">無法重新命名本機副本,請嘗試不同的名稱</string>
<string name="rename_server_fail_msg">無法重新命名,該名稱已被使用</string>
<string name="request_account_deletion">請求刪除帳號</string>
<string name="request_account_deletion_button">請求刪除</string>
<string name="request_account_deletion_details">請求服務提供者永久刪除帳號</string>
<string name="reshare_not_allowed">不允許重新分享</string>
<string name="resharing_is_not_allowed">不允許重新分享</string>
<string name="resized_image_not_possible_download">沒有可用調整過的圖片。下載完整圖片?</string>