mirror of
https://github.com/nextcloud/android.git
synced 2024-11-23 21:55:48 +03:00
Add Two Action Dialog button
Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
parent
34881cebbc
commit
5f99e4379d
7 changed files with 224 additions and 18 deletions
|
@ -104,6 +104,7 @@ import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
|
|||
import com.owncloud.android.ui.dialog.StoragePermissionDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.SyncFileNotEnoughSpaceDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.TwoActionDialogFragment;
|
||||
import com.owncloud.android.ui.fragment.ExtendedListFragment;
|
||||
import com.owncloud.android.ui.fragment.FeatureFragment;
|
||||
import com.owncloud.android.ui.fragment.FileDetailActivitiesFragment;
|
||||
|
@ -269,6 +270,9 @@ abstract class ComponentsModule {
|
|||
@ContributesAndroidInjector
|
||||
abstract ChooseTemplateDialogFragment chooseTemplateDialogFragment();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract TwoActionDialogFragment twoActionDialogFragment();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract AccountRemovalDialog accountRemovalDialog();
|
||||
|
||||
|
|
26
app/src/main/java/com/nextcloud/model/HTTPStatusCodes.kt
Normal file
26
app/src/main/java/com/nextcloud/model/HTTPStatusCodes.kt
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Alper Ozturk
|
||||
* Copyright (C) 2023 Alper Ozturk
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.model
|
||||
|
||||
enum class HTTPStatusCodes(val code: Int) {
|
||||
NOT_FOUND(404)
|
||||
}
|
|
@ -20,7 +20,9 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.nextcloud.client.account.User
|
||||
import com.nextcloud.model.HTTPStatusCodes
|
||||
import com.nextcloud.utils.extensions.getParcelableArgument
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
|
@ -164,7 +166,7 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
startDialog()
|
||||
} else {
|
||||
Log_OC.e(TAG, "ReadFileRemoteOp returned failure with code: " + result.httpCode)
|
||||
showErrorAndFinish()
|
||||
showErrorAndFinish(result.httpCode)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log_OC.e(TAG, "Error when trying to fetch remote file", e)
|
||||
|
@ -203,9 +205,30 @@ class ConflictsResolveActivity : FileActivity(), OnConflictDecisionMadeListener
|
|||
}
|
||||
}
|
||||
|
||||
private fun showErrorAndFinish() {
|
||||
runOnUiThread { Toast.makeText(this, R.string.conflict_dialog_error, Toast.LENGTH_LONG).show() }
|
||||
finish()
|
||||
private fun showErrorAndFinish(code: Int? = null) {
|
||||
val message = parseErrorMessage(code)
|
||||
runOnUiThread {
|
||||
if (code != null) {
|
||||
sendHandleFileExistenceEventBroadcast()
|
||||
} else {
|
||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendHandleFileExistenceEventBroadcast() {
|
||||
val intent = Intent(UploadListActivity.HANDLE_FILE_EXISTENCE_RECEIVER)
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
}
|
||||
|
||||
private fun parseErrorMessage(code: Int?): String {
|
||||
return if (code == HTTPStatusCodes.NOT_FOUND.code) {
|
||||
getString(R.string.uploader_file_not_found_on_server_message)
|
||||
} else {
|
||||
getString(R.string.conflict_dialog_error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,6 +56,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
|||
import com.owncloud.android.operations.CheckCurrentCredentialsOperation;
|
||||
import com.owncloud.android.ui.adapter.UploadListAdapter;
|
||||
import com.owncloud.android.ui.decoration.MediaGridItemDecoration;
|
||||
import com.owncloud.android.ui.dialog.TwoActionDialogFragment;
|
||||
import com.owncloud.android.utils.FilesSyncHelper;
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils;
|
||||
|
||||
|
@ -66,13 +67,13 @@ import androidx.recyclerview.widget.GridLayoutManager;
|
|||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
/**
|
||||
* Activity listing pending, active, and completed uploads. User can delete
|
||||
* completed uploads from view. Content of this list of coming from
|
||||
* {@link UploadsStorageManager}.
|
||||
* Activity listing pending, active, and completed uploads. User can delete completed uploads from view. Content of this
|
||||
* list of coming from {@link UploadsStorageManager}.
|
||||
*/
|
||||
public class UploadListActivity extends FileActivity {
|
||||
public class UploadListActivity extends FileActivity implements TwoActionDialogFragment.TwoActionDialogActionListener {
|
||||
|
||||
private static final String TAG = UploadListActivity.class.getSimpleName();
|
||||
public static final String HANDLE_FILE_EXISTENCE_RECEIVER = "HANDLE_FILE_EXISTENCE_RECEIVER";
|
||||
|
||||
private UploadMessagesReceiver uploadMessagesReceiver;
|
||||
|
||||
|
@ -144,6 +145,44 @@ public class UploadListActivity extends FileActivity {
|
|||
setupDrawer(R.id.nav_uploads);
|
||||
|
||||
setupContent();
|
||||
registerHandleFileExistenceDialogReceiver();
|
||||
}
|
||||
|
||||
private void registerHandleFileExistenceDialogReceiver() {
|
||||
IntentFilter filter = new IntentFilter(HANDLE_FILE_EXISTENCE_RECEIVER);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(handleFileExistenceReceiver, filter);
|
||||
}
|
||||
|
||||
private final BroadcastReceiver handleFileExistenceReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
showHandleFileExistenceDialog();
|
||||
}
|
||||
};
|
||||
|
||||
private void showHandleFileExistenceDialog() {
|
||||
TwoActionDialogFragment dialog = TwoActionDialogFragment.Companion.newInstance(R.string.uploader_handle_not_existed_file_dialog_title,
|
||||
R.string.uploader_handle_not_existed_file_dialog_message,
|
||||
R.string.common_cancel,
|
||||
R.string.common_ok,
|
||||
this);
|
||||
dialog.show(this.getSupportFragmentManager(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void positiveAction() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void negativeAction() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(handleFileExistenceReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void setupContent() {
|
||||
|
@ -178,6 +217,7 @@ public class UploadListActivity extends FileActivity {
|
|||
swipeListRefreshLayout.setOnRefreshListener(this::refresh);
|
||||
|
||||
loadItems();
|
||||
|
||||
}
|
||||
|
||||
private void loadItems() {
|
||||
|
@ -327,14 +367,14 @@ public class UploadListActivity extends FileActivity {
|
|||
if (mUploaderBinder == null) {
|
||||
mUploaderBinder = (FileUploaderBinder) service;
|
||||
Log_OC.d(TAG, "UploadListActivity connected to Upload service. component: " +
|
||||
component + " service: " + service);
|
||||
component + " service: " + service);
|
||||
} else {
|
||||
Log_OC.d(TAG, "mUploaderBinder already set. mUploaderBinder: " +
|
||||
mUploaderBinder + " service:" + service);
|
||||
mUploaderBinder + " service:" + service);
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(TAG, "UploadListActivity not connected to Upload service. component: " +
|
||||
component + " service: " + service);
|
||||
component + " service: " + service);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -503,9 +503,9 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
OCUpload item,
|
||||
String status) {
|
||||
String remotePath = item.getRemotePath();
|
||||
OCFile ocFile = storageManager.getFileByEncryptedRemotePath(remotePath);
|
||||
OCFile localFile = storageManager.getFileByEncryptedRemotePath(remotePath);
|
||||
|
||||
if (ocFile == null) {
|
||||
if (localFile == null) {
|
||||
// Remote file doesn't exist, try to refresh folder
|
||||
OCFile folder = storageManager.getFileByEncryptedRemotePath(new File(remotePath).getParent() + "/");
|
||||
|
||||
|
@ -517,8 +517,8 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
// Destination folder doesn't exist anymore
|
||||
}
|
||||
|
||||
if (ocFile != null) {
|
||||
this.openConflictActivity(ocFile, item);
|
||||
if (localFile != null) {
|
||||
this.openConflictActivity(localFile, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -533,10 +533,10 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
|
|||
holder.binding.uploadStatus.setText(status);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
OCFile file = storageManager.getFileByEncryptedRemotePath(remotePath);
|
||||
OCFile fileOnServer = storageManager.getFileByEncryptedRemotePath(remotePath);
|
||||
|
||||
if (file != null) {
|
||||
openConflictActivity(file, item);
|
||||
if (fileOnServer != null) {
|
||||
openConflictActivity(fileOnServer, item);
|
||||
} else {
|
||||
displayFileNotFoundError(holder.itemView, context);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Alper Ozturk
|
||||
* Copyright (C) 2023 Alper Ozturk
|
||||
* Copyright (C) 2023 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.ui.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.nextcloud.client.di.Injectable
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils
|
||||
import javax.inject.Inject
|
||||
|
||||
class TwoActionDialogFragment(val listener: TwoActionDialogActionListener) : DialogFragment(), Injectable {
|
||||
|
||||
@Inject
|
||||
lateinit var viewThemeUtils: ViewThemeUtils
|
||||
|
||||
interface TwoActionDialogActionListener {
|
||||
fun positiveAction()
|
||||
fun negativeAction()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val titleArgument = "titleArgument"
|
||||
const val messageArgument = "messageArgument"
|
||||
const val negativeButtonArgument = "negativeButtonArgument"
|
||||
const val positiveButtonArgument = "positiveButtonArgument"
|
||||
|
||||
fun newInstance(
|
||||
titleId: Int,
|
||||
messageId: Int?,
|
||||
negativeButtonTextId: Int,
|
||||
positiveButtonTextId: Int,
|
||||
listener: TwoActionDialogActionListener
|
||||
): TwoActionDialogFragment {
|
||||
return TwoActionDialogFragment(listener).apply {
|
||||
arguments = Bundle().apply {
|
||||
putInt(titleArgument, titleId)
|
||||
messageId?.let { putInt(messageArgument, it) }
|
||||
putInt(positiveButtonArgument, positiveButtonTextId)
|
||||
putInt(negativeButtonArgument, negativeButtonTextId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val title = requireContext().getString(requireArguments().getInt(titleArgument))
|
||||
val messageId: Int? = arguments?.getInt(messageArgument)
|
||||
val positiveButtonText = requireContext().getString(requireArguments().getInt(positiveButtonArgument))
|
||||
val negativeButtonText = requireContext().getString(requireArguments().getInt(negativeButtonArgument))
|
||||
|
||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(title)
|
||||
.setNegativeButton(negativeButtonText) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
listener.negativeAction()
|
||||
}
|
||||
.setPositiveButton(positiveButtonText) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
listener.positiveAction()
|
||||
}
|
||||
|
||||
messageId?.let {
|
||||
builder.setMessage(requireContext().getString(messageId))
|
||||
}
|
||||
|
||||
viewThemeUtils.dialog.colorMaterialAlertDialogBackground(requireContext(), builder)
|
||||
|
||||
return builder.create()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
val alertDialog = dialog as AlertDialog?
|
||||
alertDialog?.let {
|
||||
val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton?
|
||||
if (positiveButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryTonal(positiveButton)
|
||||
}
|
||||
|
||||
val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton?
|
||||
if (negativeButton != null) {
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(negativeButton)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -912,6 +912,9 @@
|
|||
<string name="failed_to_start_editor">Failed to start editor</string>
|
||||
<string name="create_rich_workspace">Add folder info</string>
|
||||
<string name="creates_rich_workspace">creates folder info</string>
|
||||
<string name="uploader_handle_not_existed_file_dialog_title">File Not Found</string>
|
||||
<string name="uploader_handle_not_existed_file_dialog_message">This file does not longer exist in server still want to upload?</string>
|
||||
<string name="uploader_file_not_found_on_server_message">We couldnt locate the file on server. Another user may have deleted the file</string>
|
||||
<string name="uploader_file_not_found_message">File not found. Are you sure this file exist or conflict not solved before?</string>
|
||||
<string name="uploader_upload_failed_sync_conflict_error">File upload conflict</string>
|
||||
<string name="uploader_upload_failed_sync_conflict_error_content">Pick which version to keep of %1$s</string>
|
||||
|
|
Loading…
Reference in a new issue