diff --git a/app/src/main/java/eu/faircode/email/DaoAccount.java b/app/src/main/java/eu/faircode/email/DaoAccount.java index f32bb6e0db..521899180d 100644 --- a/app/src/main/java/eu/faircode/email/DaoAccount.java +++ b/app/src/main/java/eu/faircode/email/DaoAccount.java @@ -70,5 +70,8 @@ public interface DaoAccount { @Query("UPDATE account SET `primary` = 0") void resetPrimary(); + + @Query("DELETE FROM account WHERE id = :id") + void deleteAccount(long id); } diff --git a/app/src/main/java/eu/faircode/email/DaoIdentity.java b/app/src/main/java/eu/faircode/email/DaoIdentity.java index 4c37252177..f59bbd58dd 100644 --- a/app/src/main/java/eu/faircode/email/DaoIdentity.java +++ b/app/src/main/java/eu/faircode/email/DaoIdentity.java @@ -53,4 +53,7 @@ public interface DaoIdentity { @Query("UPDATE identity SET `primary` = 0") void resetPrimary(); + + @Query("DELETE FROM identity WHERE id = :id") + void deleteIdentity(long id); } diff --git a/app/src/main/java/eu/faircode/email/FragmentAccount.java b/app/src/main/java/eu/faircode/email/FragmentAccount.java index 42cc975ea4..e2456888ac 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAccount.java +++ b/app/src/main/java/eu/faircode/email/FragmentAccount.java @@ -21,6 +21,7 @@ package eu.faircode.email; import android.arch.lifecycle.Observer; import android.content.Context; +import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -28,6 +29,7 @@ import android.support.design.widget.TextInputLayout; import android.support.v4.app.LoaderManager; import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.Loader; +import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; @@ -39,6 +41,7 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; +import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.Toast; @@ -48,6 +51,8 @@ import com.sun.mail.imap.IMAPStore; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import javax.mail.Folder; import javax.mail.MessagingException; @@ -66,8 +71,11 @@ public class FragmentAccount extends FragmentEx { private CheckBox cbPrimary; private Button btnSave; private ProgressBar pbCheck; + private ImageButton ibDelete; // TODO: loading spinner + private ExecutorService executor = Executors.newCachedThreadPool(); + @Override @Nullable public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -94,6 +102,7 @@ public class FragmentAccount extends FragmentEx { cbPrimary = view.findViewById(R.id.cbPrimary); btnSave = view.findViewById(R.id.btnSave); pbCheck = view.findViewById(R.id.pbCheck); + ibDelete = view.findViewById(R.id.ibDelete); // Wire controls @@ -144,9 +153,40 @@ public class FragmentAccount extends FragmentEx { } }); + ibDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder + .setMessage(R.string.title_account_delete) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getFragmentManager().popBackStack(); + // TODO: spinner + executor.submit(new Runnable() { + @Override + public void run() { + try { + // To prevent foreign key constraints from triggering + ServiceSynchronize.stop(getContext(), "delete account"); + DB.getInstance(getContext()).account().deleteAccount(id); + ServiceSynchronize.start(getContext()); + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + } + } + }); + } + }) + .setNegativeButton(android.R.string.cancel, null).show(); + } + }); + // Initialize tilPassword.setPasswordVisibilityToggleEnabled(id < 0); pbCheck.setVisibility(View.GONE); + ibDelete.setVisibility(id < 0 ? View.GONE : View.VISIBLE); // Observe DB.getInstance(getContext()).account().liveAccount(id).observe(this, new Observer() { diff --git a/app/src/main/java/eu/faircode/email/FragmentIdentity.java b/app/src/main/java/eu/faircode/email/FragmentIdentity.java index 156ba53a22..906abbcebb 100644 --- a/app/src/main/java/eu/faircode/email/FragmentIdentity.java +++ b/app/src/main/java/eu/faircode/email/FragmentIdentity.java @@ -21,6 +21,7 @@ package eu.faircode.email; import android.arch.lifecycle.Observer; import android.content.Context; +import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -28,6 +29,7 @@ import android.support.design.widget.TextInputLayout; import android.support.v4.app.LoaderManager; import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.Loader; +import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; @@ -41,6 +43,7 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; +import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.Toast; @@ -48,6 +51,8 @@ import android.widget.Toast; import java.util.List; import java.util.Objects; import java.util.Properties; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import javax.mail.Session; import javax.mail.Transport; @@ -68,8 +73,11 @@ public class FragmentIdentity extends FragmentEx { private CheckBox cbPrimary; private Button btnSave; private ProgressBar pbCheck; + private ImageButton ibDelete; // TODO: loading spinner + private ExecutorService executor = Executors.newCachedThreadPool(); + @Override @Nullable public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -99,6 +107,7 @@ public class FragmentIdentity extends FragmentEx { cbPrimary = view.findViewById(R.id.cbPrimary); btnSave = view.findViewById(R.id.btnSave); pbCheck = view.findViewById(R.id.pbCheck); + ibDelete = view.findViewById(R.id.ibDelete); // Wire controls @@ -174,10 +183,38 @@ public class FragmentIdentity extends FragmentEx { } }); + ibDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder + .setMessage(R.string.title_identity_delete) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getFragmentManager().popBackStack(); + // TODO: spinner + executor.submit(new Runnable() { + @Override + public void run() { + try { + DB.getInstance(getContext()).identity().deleteIdentity(id); + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + } + } + }); + } + }) + .setNegativeButton(android.R.string.cancel, null).show(); + } + }); + // Initialize etName.requestFocus(); tilPassword.setPasswordVisibilityToggleEnabled(id < 0); pbCheck.setVisibility(View.GONE); + ibDelete.setVisibility(id < 0 ? View.GONE : View.VISIBLE); // Observer DB.getInstance(getContext()).identity().liveIdentity(id).observe(this, new Observer() { diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 5f6acdf3c6..ce161b5370 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -1254,6 +1254,11 @@ public class ServiceSynchronize extends LifecycleService { ContextCompat.startForegroundService(context, new Intent(context, ServiceSynchronize.class)); } + public static void stop(Context context, String reason) { + Log.i(Helper.TAG, "Stop because of '" + reason + "'"); + context.stopService(new Intent(context, ServiceSynchronize.class)); + } + public static void restart(Context context, String reason) { Log.i(Helper.TAG, "Restart because of '" + reason + "'"); context.stopService(new Intent(context, ServiceSynchronize.class)); diff --git a/app/src/main/res/layout/fragment_account.xml b/app/src/main/res/layout/fragment_account.xml index 6a9b9bb4c7..af292322c5 100644 --- a/app/src/main/res/layout/fragment_account.xml +++ b/app/src/main/res/layout/fragment_account.xml @@ -196,6 +196,14 @@ app:layout_constraintStart_toEndOf="@id/btnSave" app:layout_constraintTop_toTopOf="@id/btnSave" /> + + + + Password missing IDLE not supported Local drafts + Delete this account permanently? + Delete this identity permanently? %1$s (%2$d) Synchronize (receive messages)