Use dialog fragments to check/delete rules

This commit is contained in:
M66B 2019-07-01 15:25:31 +02:00
parent ce159b1776
commit 9325eb98ba
2 changed files with 155 additions and 133 deletions

View File

@ -26,7 +26,6 @@ import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
@ -41,7 +40,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class AdapterRuleMatch extends RecyclerView.Adapter<AdapterRuleMatch.ViewHolder> { public class AdapterRuleMatch extends RecyclerView.Adapter<AdapterRuleMatch.ViewHolder> {
private Fragment parentFragment;
private Context context; private Context context;
private LifecycleOwner owner; private LifecycleOwner owner;
private LayoutInflater inflater; private LayoutInflater inflater;
@ -75,10 +73,9 @@ public class AdapterRuleMatch extends RecyclerView.Adapter<AdapterRuleMatch.View
} }
} }
AdapterRuleMatch(Fragment parentFragment) { AdapterRuleMatch(Context context, LifecycleOwner owner) {
this.parentFragment = parentFragment; this.context = context;
this.context = parentFragment.getContext(); this.owner = owner;
this.owner = parentFragment.getViewLifecycleOwner();
this.inflater = LayoutInflater.from(context); this.inflater = LayoutInflater.from(context);
setHasStableIds(true); setHasStableIds(true);
@ -87,7 +84,6 @@ public class AdapterRuleMatch extends RecyclerView.Adapter<AdapterRuleMatch.View
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroyed() { public void onDestroyed() {
Log.i(AdapterRuleMatch.this + " parent destroyed"); Log.i(AdapterRuleMatch.this + " parent destroyed");
AdapterRuleMatch.this.parentFragment = null;
AdapterRuleMatch.this.context = null; AdapterRuleMatch.this.context = null;
AdapterRuleMatch.this.owner = null; AdapterRuleMatch.this.owner = null;
} }

View File

@ -19,8 +19,8 @@ package eu.faircode.email;
Copyright 2018-2019 by Marcel Bokhorst (M66B) Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/ */
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Color; import android.graphics.Color;
@ -48,8 +48,10 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.Group; import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.DialogFragment;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -137,6 +139,7 @@ public class FragmentRule extends FragmentBase {
private static final int REQUEST_SENDER = 1; private static final int REQUEST_SENDER = 1;
private static final int REQUEST_RECIPIENT = 2; private static final int REQUEST_RECIPIENT = 2;
private static final int REQUEST_COLOR = 3; private static final int REQUEST_COLOR = 3;
private final static int REQUEST_DELETE = 4;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -293,7 +296,7 @@ public class FragmentRule extends FragmentBase {
tvActionRemark.setVisibility(View.GONE); tvActionRemark.setVisibility(View.GONE);
setColor(color); onSelectColor(color);
btnColor.setOnClickListener(new View.OnClickListener() { btnColor.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -307,7 +310,7 @@ public class FragmentRule extends FragmentBase {
ibColorDefault.setOnClickListener(new View.OnClickListener() { ibColorDefault.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
setColor(Color.TRANSPARENT); onSelectColor(Color.TRANSPARENT);
} }
}); });
@ -323,7 +326,7 @@ public class FragmentRule extends FragmentBase {
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) { switch (menuItem.getItemId()) {
case R.id.action_delete: case R.id.action_delete:
onActionTrash(); onActionDelete();
return true; return true;
case R.id.action_check: case R.id.action_check:
onActionCheck(); onActionCheck();
@ -418,11 +421,11 @@ public class FragmentRule extends FragmentBase {
switch (requestCode) { switch (requestCode) {
case REQUEST_SENDER: case REQUEST_SENDER:
if (resultCode == RESULT_OK && data != null) if (resultCode == RESULT_OK && data != null)
handlePickContact(data, true); onPickContact(data, true);
break; break;
case REQUEST_RECIPIENT: case REQUEST_RECIPIENT:
if (resultCode == RESULT_OK && data != null) if (resultCode == RESULT_OK && data != null)
handlePickContact(data, true); onPickContact(data, true);
break; break;
case REQUEST_COLOR: case REQUEST_COLOR:
if (resultCode == RESULT_OK && data != null) { if (resultCode == RESULT_OK && data != null) {
@ -433,13 +436,17 @@ public class FragmentRule extends FragmentBase {
} }
Bundle args = data.getBundleExtra("args"); Bundle args = data.getBundleExtra("args");
setColor(args.getInt("color")); onSelectColor(args.getInt("color"));
} }
break; break;
case REQUEST_DELETE:
if (resultCode == RESULT_OK)
onDelete();
break;
} }
} }
private void handlePickContact(Intent data, boolean sender) { private void onPickContact(Intent data, boolean sender) {
Uri uri = data.getData(); Uri uri = data.getData();
if (uri == null) return; if (uri == null) return;
try (Cursor cursor = getContext().getContentResolver().query(uri, try (Cursor cursor = getContext().getContentResolver().query(uri,
@ -458,6 +465,49 @@ public class FragmentRule extends FragmentBase {
} }
} }
private void onSelectColor(int color) {
this.color = color;
GradientDrawable border = new GradientDrawable();
border.setColor(color);
border.setStroke(1, Helper.resolveColor(getContext(), R.attr.colorSeparator));
vwColor.setBackground(border);
}
private void onDelete() {
Bundle args = new Bundle();
args.putLong("id", id);
new SimpleTask<Void>() {
@Override
protected void onPreExecute(Bundle args) {
Helper.setViewsEnabled(view, false);
}
@Override
protected void onPostExecute(Bundle args) {
Helper.setViewsEnabled(view, true);
}
@Override
protected Void onExecute(Context context, Bundle args) {
long id = args.getLong("id");
DB.getInstance(context).rule().deleteRule(id);
return null;
}
@Override
protected void onExecuted(Bundle args, Void data) {
finish();
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getFragmentManager(), ex);
}
}.execute(FragmentRule.this, args, "rule:delete");
}
private void loadRule() { private void loadRule() {
Bundle rargs = new Bundle(); Bundle rargs = new Bundle();
rargs.putLong("id", id); rargs.putLong("id", id);
@ -514,7 +564,7 @@ public class FragmentRule extends FragmentBase {
break; break;
case EntityRule.TYPE_FLAG: case EntityRule.TYPE_FLAG:
setColor(jaction.isNull("color") ? Color.TRANSPARENT : jaction.getInt("color")); onSelectColor(jaction.isNull("color") ? Color.TRANSPARENT : jaction.getInt("color"));
break; break;
case EntityRule.TYPE_MOVE: case EntityRule.TYPE_MOVE:
@ -576,47 +626,23 @@ public class FragmentRule extends FragmentBase {
}.execute(FragmentRule.this, rargs, "rule:get"); }.execute(FragmentRule.this, rargs, "rule:get");
} }
private void onActionTrash() { private void showActionParameters(int type) {
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner()) grpSnooze.setVisibility(type == EntityRule.TYPE_SNOOZE ? View.VISIBLE : View.GONE);
.setMessage(R.string.title_ask_delete_rule) grpFlag.setVisibility(type == EntityRule.TYPE_FLAG ? View.VISIBLE : View.GONE);
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { grpMove.setVisibility(type == EntityRule.TYPE_MOVE || type == EntityRule.TYPE_COPY ? View.VISIBLE : View.GONE);
@Override grpMoveProp.setVisibility(type == EntityRule.TYPE_MOVE ? View.VISIBLE : View.GONE);
public void onClick(DialogInterface dialog, int which) { grpAnswer.setVisibility(type == EntityRule.TYPE_ANSWER ? View.VISIBLE : View.GONE);
Bundle args = new Bundle(); grpAutomation.setVisibility(type == EntityRule.TYPE_AUTOMATION ? View.VISIBLE : View.GONE);
args.putLong("id", id); }
new SimpleTask<Void>() { private void onActionDelete() {
@Override Bundle args = new Bundle();
protected void onPreExecute(Bundle args) { args.putString("question", getString(R.string.title_ask_delete_rule));
Helper.setViewsEnabled(view, false);
}
@Override FragmentDialogAsk fragment = new FragmentDialogAsk();
protected void onPostExecute(Bundle args) { fragment.setArguments(args);
Helper.setViewsEnabled(view, true); fragment.setTargetFragment(FragmentRule.this, REQUEST_DELETE);
} fragment.show(getFragmentManager(), "answer:delete");
@Override
protected Void onExecute(Context context, Bundle args) {
long id = args.getLong("id");
DB.getInstance(context).rule().deleteRule(id);
return null;
}
@Override
protected void onExecuted(Bundle args, Void data) {
finish();
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getFragmentManager(), ex);
}
}.execute(FragmentRule.this, args, "rule:delete");
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
} }
private void onActionCheck() { private void onActionCheck() {
@ -629,71 +655,14 @@ public class FragmentRule extends FragmentBase {
return; return;
} }
final View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_rule_match, null);
final TextView tvNoMessages = dview.findViewById(R.id.tvNoMessages);
final RecyclerView rvMessage = dview.findViewById(R.id.rvMessage);
final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait);
rvMessage.setHasFixedSize(false);
LinearLayoutManager llm = new LinearLayoutManager(getContext());
rvMessage.setLayoutManager(llm);
final AdapterRuleMatch adapter = new AdapterRuleMatch(this);
rvMessage.setAdapter(adapter);
tvNoMessages.setVisibility(View.GONE);
rvMessage.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
new DialogBuilderLifecycle(getContext(), getViewLifecycleOwner())
.setTitle(R.string.title_rule_matched)
.setView(dview)
.show();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("folder", folder); args.putLong("folder", folder);
args.putString("condition", jcondition.toString()); args.putString("condition", jcondition.toString());
new SimpleTask<List<EntityMessage>>() { FragmentDialogCheck fragment = new FragmentDialogCheck();
@Override fragment.setArguments(args);
protected List<EntityMessage> onExecute(Context context, Bundle args) throws Throwable { fragment.show(getFragmentManager(), "rule:check");
long fid = args.getLong("folder");
EntityRule rule = new EntityRule();
rule.condition = args.getString("condition");
List<EntityMessage> matching = new ArrayList<>();
DB db = DB.getInstance(context);
List<Long> ids = db.message().getMessageIdsByFolder(fid);
for (long id : ids) {
EntityMessage message = db.message().getMessage(id);
if (rule.matches(context, message, null))
matching.add(message);
if (matching.size() >= MAX_CHECK)
break;
}
return matching;
}
@Override
protected void onExecuted(Bundle args, List<EntityMessage> messages) {
adapter.set(messages);
pbWait.setVisibility(View.GONE);
if (messages.size() > 0)
rvMessage.setVisibility(View.VISIBLE);
else
tvNoMessages.setVisibility(View.VISIBLE);
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getFragmentManager(), ex);
}
}.execute(this, args, "rule:check");
} catch (JSONException ex) { } catch (JSONException ex) {
Log.e(ex); Log.e(ex);
} }
@ -800,24 +769,6 @@ public class FragmentRule extends FragmentBase {
} }
} }
private void showActionParameters(int type) {
grpSnooze.setVisibility(type == EntityRule.TYPE_SNOOZE ? View.VISIBLE : View.GONE);
grpFlag.setVisibility(type == EntityRule.TYPE_FLAG ? View.VISIBLE : View.GONE);
grpMove.setVisibility(type == EntityRule.TYPE_MOVE || type == EntityRule.TYPE_COPY ? View.VISIBLE : View.GONE);
grpMoveProp.setVisibility(type == EntityRule.TYPE_MOVE ? View.VISIBLE : View.GONE);
grpAnswer.setVisibility(type == EntityRule.TYPE_ANSWER ? View.VISIBLE : View.GONE);
grpAutomation.setVisibility(type == EntityRule.TYPE_AUTOMATION ? View.VISIBLE : View.GONE);
}
private void setColor(int color) {
this.color = color;
GradientDrawable border = new GradientDrawable();
border.setColor(color);
border.setStroke(1, Helper.resolveColor(getContext(), R.attr.colorSeparator));
vwColor.setBackground(border);
}
private JSONObject getCondition() throws JSONException { private JSONObject getCondition() throws JSONException {
JSONObject jcondition = new JSONObject(); JSONObject jcondition = new JSONObject();
@ -916,4 +867,79 @@ public class FragmentRule extends FragmentBase {
return name; return name;
} }
} }
public static class FragmentDialogCheck extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
long folder = getArguments().getLong("folder");
String condition = getArguments().getString("condition");
final View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_rule_match, null);
final TextView tvNoMessages = dview.findViewById(R.id.tvNoMessages);
final RecyclerView rvMessage = dview.findViewById(R.id.rvMessage);
final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait);
rvMessage.setHasFixedSize(false);
LinearLayoutManager llm = new LinearLayoutManager(getContext());
rvMessage.setLayoutManager(llm);
final AdapterRuleMatch adapter = new AdapterRuleMatch(getContext(), getActivity());
rvMessage.setAdapter(adapter);
tvNoMessages.setVisibility(View.GONE);
rvMessage.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
Bundle args = new Bundle();
args.putLong("folder", folder);
args.putString("condition", condition);
new SimpleTask<List<EntityMessage>>() {
@Override
protected List<EntityMessage> onExecute(Context context, Bundle args) throws Throwable {
long fid = args.getLong("folder");
EntityRule rule = new EntityRule();
rule.condition = args.getString("condition");
List<EntityMessage> matching = new ArrayList<>();
DB db = DB.getInstance(context);
List<Long> ids = db.message().getMessageIdsByFolder(fid);
for (long id : ids) {
EntityMessage message = db.message().getMessage(id);
if (rule.matches(context, message, null))
matching.add(message);
if (matching.size() >= MAX_CHECK)
break;
}
return matching;
}
@Override
protected void onExecuted(Bundle args, List<EntityMessage> messages) {
adapter.set(messages);
pbWait.setVisibility(View.GONE);
if (messages.size() > 0)
rvMessage.setVisibility(View.VISIBLE);
else
tvNoMessages.setVisibility(View.VISIBLE);
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getFragmentManager(), ex);
}
}.execute(getContext(), getActivity(), args, "rule:check");
return new AlertDialog.Builder(getContext())
.setTitle(R.string.title_rule_matched)
.setView(dview)
.create();
}
}
} }