Skip to content

Commit 79aa2fc

Browse files
authored
Merge pull request #720 from rivaldi8/bug-544-confirm-irreversible-actions
Bugfix 544: Add dialog with extra checkbox for irreversible actions Fixes #544
2 parents c161118 + 2b0e03e commit 79aa2fc

8 files changed

Lines changed: 205 additions & 54 deletions

File tree

app/src/main/java/org/gnucash/android/ui/settings/BookManagerFragment.java

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.gnucash.android.db.adapter.TransactionsDbAdapter;
5555
import org.gnucash.android.ui.account.AccountsActivity;
5656
import org.gnucash.android.ui.common.Refreshable;
57+
import org.gnucash.android.ui.settings.dialog.DeleteBookConfirmationDialog;
5758
import org.gnucash.android.util.BookUtils;
5859
import org.gnucash.android.util.PreferencesHelper;
5960

@@ -199,30 +200,8 @@ public boolean onMenuItemClick(MenuItem item) {
199200
case R.id.ctx_menu_sync_book:
200201
//TODO implement sync
201202
return false;
202-
case R.id.ctx_menu_delete_book: {
203-
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
204-
dialogBuilder.setTitle(getString(R.string.title_confirm_delete_book))
205-
.setIcon(R.drawable.ic_close_black_24dp)
206-
.setMessage(getString(R.string.msg_all_book_data_will_be_deleted));
207-
dialogBuilder.setPositiveButton(getString(R.string.btn_delete_book), new DialogInterface.OnClickListener() {
208-
@Override
209-
public void onClick(DialogInterface dialog, int which) {
210-
BooksDbAdapter.getInstance().deleteBook(bookUID);
211-
refresh();
212-
}
213-
});
214-
dialogBuilder.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
215-
@Override
216-
public void onClick(DialogInterface dialog, int which) {
217-
dialog.dismiss();
218-
}
219-
});
220-
AlertDialog dialog = dialogBuilder.create();
221-
dialog.show(); //must be called before you can access buttons
222-
dialog.getButton(AlertDialog.BUTTON_POSITIVE)
223-
.setTextColor(ContextCompat.getColor(context, R.color.account_red));
224-
}
225-
return true;
203+
case R.id.ctx_menu_delete_book:
204+
return handleMenuDeleteBook(bookUID);
226205
default:
227206
return true;
228207
}
@@ -238,6 +217,13 @@ public void onClick(DialogInterface dialog, int which) {
238217
});
239218
}
240219

220+
private boolean handleMenuDeleteBook(final String bookUID) {
221+
DeleteBookConfirmationDialog dialog = DeleteBookConfirmationDialog.newInstance(bookUID);
222+
dialog.show(getFragmentManager(), "delete_book");
223+
dialog.setTargetFragment(BookManagerFragment.this, 0);
224+
return true;
225+
}
226+
241227
/**
242228
* Opens a dialog for renaming a book
243229
* @param bookName Current name of the book

app/src/main/java/org/gnucash/android/ui/settings/dialog/DeleteAllAccountsConfirmationDialog.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,10 @@
1616

1717
package org.gnucash.android.ui.settings.dialog;
1818

19-
import android.annotation.TargetApi;
20-
import android.app.AlertDialog;
2119
import android.app.Dialog;
2220
import android.content.Context;
2321
import android.content.DialogInterface;
2422
import android.os.Bundle;
25-
import android.support.v4.app.DialogFragment;
2623
import android.widget.Toast;
2724

2825
import org.gnucash.android.R;
@@ -36,7 +33,7 @@
3633
*
3734
* @author Ngewi Fet <ngewif@gmail.com>
3835
*/
39-
public class DeleteAllAccountsConfirmationDialog extends DialogFragment {
36+
public class DeleteAllAccountsConfirmationDialog extends DoubleConfirmationDialog {
4037

4138
public static DeleteAllAccountsConfirmationDialog newInstance() {
4239
DeleteAllAccountsConfirmationDialog frag = new DeleteAllAccountsConfirmationDialog();
@@ -45,7 +42,7 @@ public static DeleteAllAccountsConfirmationDialog newInstance() {
4542

4643
@Override
4744
public Dialog onCreateDialog(Bundle savedInstanceState) {
48-
return new AlertDialog.Builder(getActivity())
45+
return getDialogBuilder()
4946
.setIcon(android.R.drawable.ic_delete)
5047
.setTitle(R.string.title_confirm_delete).setMessage(R.string.confirm_delete_all_accounts)
5148
.setPositiveButton(R.string.alert_dialog_ok_delete,
@@ -59,13 +56,6 @@ public void onClick(DialogInterface dialog, int whichButton) {
5956
}
6057
}
6158
)
62-
.setNegativeButton(R.string.alert_dialog_cancel,
63-
new DialogInterface.OnClickListener() {
64-
public void onClick(DialogInterface dialog, int whichButton) {
65-
dismiss();
66-
}
67-
}
68-
)
6959
.create();
7060
}
7161
}

app/src/main/java/org/gnucash/android/ui/settings/dialog/DeleteAllTransactionsConfirmationDialog.java

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@
1616
*/
1717
package org.gnucash.android.ui.settings.dialog;
1818

19-
import android.app.AlertDialog;
2019
import android.app.Dialog;
2120
import android.content.Context;
2221
import android.content.DialogInterface;
2322
import android.os.Bundle;
2423
import android.support.annotation.NonNull;
25-
import android.support.v4.app.DialogFragment;
2624
import android.util.Log;
2725
import android.widget.Toast;
2826

@@ -44,7 +42,7 @@
4442
* @author ngewif <ngewif@gmail.com>
4543
* @author Yongxin Wang <fefe.wyx@gmail.com>
4644
*/
47-
public class DeleteAllTransactionsConfirmationDialog extends DialogFragment {
45+
public class DeleteAllTransactionsConfirmationDialog extends DoubleConfirmationDialog {
4846

4947
public static DeleteAllTransactionsConfirmationDialog newInstance() {
5048
DeleteAllTransactionsConfirmationDialog frag = new DeleteAllTransactionsConfirmationDialog();
@@ -53,7 +51,7 @@ public static DeleteAllTransactionsConfirmationDialog newInstance() {
5351

5452
@Override
5553
@NonNull public Dialog onCreateDialog(Bundle savedInstanceState) {
56-
return new AlertDialog.Builder(getActivity())
54+
return getDialogBuilder()
5755
.setIcon(android.R.drawable.ic_delete)
5856
.setTitle(R.string.title_confirm_delete).setMessage(R.string.msg_delete_all_transactions_confirmation)
5957
.setPositiveButton(R.string.alert_dialog_ok_delete,
@@ -80,19 +78,6 @@ public void onClick(DialogInterface dialog, int whichButton) {
8078
}
8179
}
8280

83-
)
84-
.
85-
86-
setNegativeButton(R.string.alert_dialog_cancel,
87-
new DialogInterface.OnClickListener() {
88-
public void onClick(DialogInterface dialog, int whichButton) {
89-
dismiss();
90-
}
91-
}
92-
93-
)
94-
.
95-
96-
create();
81+
).create();
9782
}
9883
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2017 Àlex Magaz Graça <alexandre.magaz@gmail.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.gnucash.android.ui.settings.dialog;
18+
19+
import android.app.Dialog;
20+
import android.content.DialogInterface;
21+
import android.os.Bundle;
22+
import android.support.annotation.NonNull;
23+
24+
import org.gnucash.android.R;
25+
import org.gnucash.android.db.adapter.BooksDbAdapter;
26+
import org.gnucash.android.ui.common.Refreshable;
27+
28+
/**
29+
* Confirmation dialog for deleting a book.
30+
*
31+
* @author Àlex Magaz <alexandre.magaz@gmail.com>
32+
*/
33+
public class DeleteBookConfirmationDialog extends DoubleConfirmationDialog {
34+
@NonNull
35+
public static DeleteBookConfirmationDialog newInstance(String bookUID) {
36+
DeleteBookConfirmationDialog frag = new DeleteBookConfirmationDialog();
37+
Bundle args = new Bundle();
38+
args.putString("bookUID", bookUID);
39+
frag.setArguments(args);
40+
return frag;
41+
}
42+
43+
@NonNull
44+
@Override
45+
public Dialog onCreateDialog(Bundle savedInstanceState) {
46+
return getDialogBuilder()
47+
.setTitle(R.string.title_confirm_delete_book)
48+
.setIcon(R.drawable.ic_close_black_24dp)
49+
.setMessage(R.string.msg_all_book_data_will_be_deleted)
50+
.setPositiveButton(R.string.btn_delete_book, new DialogInterface.OnClickListener() {
51+
@SuppressWarnings("ConstantConditions")
52+
@Override
53+
public void onClick(DialogInterface dialogInterface, int which) {
54+
final String bookUID = getArguments().getString("bookUID");
55+
BooksDbAdapter.getInstance().deleteBook(bookUID);
56+
((Refreshable) getTargetFragment()).refresh();
57+
}
58+
})
59+
.create();
60+
}
61+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2017 Àlex Magaz Graça <alexandre.magaz@gmail.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.gnucash.android.ui.settings.dialog;
18+
19+
import android.content.DialogInterface;
20+
import android.support.annotation.NonNull;
21+
import android.support.v4.app.DialogFragment;
22+
import android.support.v7.app.AlertDialog;
23+
import android.widget.CheckBox;
24+
import android.widget.CompoundButton;
25+
26+
import org.gnucash.android.R;
27+
28+
/**
29+
* Confirmation dialog with additional checkbox to confirm the action.
30+
*
31+
* <p>It's meant to avoid the user confirming irreversible actions by
32+
* mistake. The positive button to confirm the action is only enabled
33+
* when the checkbox is checked.</p>
34+
*
35+
* <p>Extend this class and override onCreateDialog to finish setting
36+
* up the dialog. See getDialogBuilder().</p>
37+
*
38+
* @author Àlex Magaz <alexandre.magaz@gmail.com>
39+
*/
40+
public abstract class DoubleConfirmationDialog extends DialogFragment {
41+
/**
42+
* Returns the dialog builder with the defaults for a double confirmation
43+
* dialog already set up.
44+
*
45+
* <p>Call it from onCreateDialog to finish setting up the dialog.
46+
* At least the following should be set:</p>
47+
*
48+
* <ul>
49+
* <li>The title.</li>
50+
* <li>The positive button.</li>
51+
* </ul>
52+
*
53+
* @return AlertDialog.Builder with the defaults for a double confirmation
54+
* dialog already set up.
55+
*/
56+
@NonNull
57+
protected AlertDialog.Builder getDialogBuilder() {
58+
return new AlertDialog.Builder(getActivity())
59+
.setView(R.layout.dialog_double_confirm)
60+
.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
61+
@Override
62+
public void onClick(DialogInterface dialog, int which) {
63+
onNegativeButton();
64+
}
65+
});
66+
}
67+
68+
@Override
69+
public void onStart() {
70+
super.onStart();
71+
if (getDialog() != null) {
72+
((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
73+
setUpConfirmCheckBox();
74+
}
75+
}
76+
77+
@SuppressWarnings("ConstantConditions")
78+
private void setUpConfirmCheckBox() {
79+
final AlertDialog dialog = (AlertDialog) getDialog();
80+
CheckBox confirmCheckBox = dialog.findViewById(R.id.checkbox_confirm);
81+
confirmCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
82+
@Override
83+
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
84+
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(b);
85+
}
86+
});
87+
}
88+
89+
/**
90+
* Called when the negative button is pressed.
91+
*
92+
* <p>By default it just dismisses the dialog.</p>
93+
*/
94+
protected void onNegativeButton() {
95+
getDialog().dismiss();
96+
}
97+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright (c) 2017 Ngewi Fet <ngewif@gmail.com>
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
18+
xmlns:tools="http://schemas.android.com/tools"
19+
android:layout_width="match_parent"
20+
android:layout_height="wrap_content"
21+
android:orientation="vertical"
22+
android:padding="@dimen/dialog_padding" >
23+
24+
<CheckBox
25+
android:id="@+id/checkbox_confirm"
26+
android:layout_width="wrap_content"
27+
android:layout_height="wrap_content"
28+
android:text="@string/yes_sure"/>
29+
</LinearLayout>

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,4 +462,5 @@
462462
<string name="label_select_destination_after_export">Select the destination after export is complete</string>
463463
<string name="label_dropbox_export_destination">Export to \'/Apps/GnuCash Android/\' folder on Dropbox</string>
464464
<string name="title_section_preferences">Preferences</string>
465+
<string name="yes_sure">Yes, I\'m sure</string>
465466
</resources>

app/src/test/java/org/gnucash/android/test/unit/model/TransactionTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public void settingUID_shouldSetTransactionUidOfSplits(){
8080
@Test
8181
public void testCreateAutoBalanceSplit() {
8282
Transaction transactionCredit = new Transaction("Transaction with more credit");
83+
transactionCredit.setCommodity(Commodity.getInstance("EUR"));
8384
Split creditSplit = new Split(new Money("1", "EUR"), "test-account");
8485
creditSplit.setType(TransactionType.CREDIT);
8586
transactionCredit.addSplit(creditSplit);
@@ -93,6 +94,7 @@ public void testCreateAutoBalanceSplit() {
9394

9495

9596
Transaction transactionDebit = new Transaction("Transaction with more debit");
97+
transactionDebit.setCommodity(Commodity.getInstance("EUR"));
9698
Split debitSplit = new Split(new Money("1", "EUR"), "test-account");
9799
debitSplit.setType(TransactionType.DEBIT);
98100
transactionDebit.addSplit(debitSplit);

0 commit comments

Comments
 (0)