From f220e15034a09d0a0bbfc4425f7d9d0d706977e5 Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 13 Mar 2023 21:18:52 +0100 Subject: [PATCH] Long overdue refactoring --- .../eu/faircode/email/AdapterMessage.java | 513 ------------------ .../faircode/email/FragmentDialogButtons.java | 137 +++++ .../email/FragmentDialogKeywordAdd.java | 102 ++++ .../email/FragmentDialogKeywordManage.java | 115 ++++ .../email/FragmentDialogLabelsManage.java | 92 ++++ .../faircode/email/FragmentDialogNotes.java | 197 +++++++ .../faircode/email/FragmentDialogPrint.java | 89 +++ 7 files changed, 732 insertions(+), 513 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogButtons.java create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogKeywordAdd.java create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogKeywordManage.java create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogLabelsManage.java create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogNotes.java create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogPrint.java diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index dc5f47341d..ff865eb96b 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -25,7 +25,6 @@ import android.Manifest; import android.animation.Animator; import android.annotation.SuppressLint; import android.annotation.TargetApi; -import android.app.Activity; import android.app.Dialog; import android.app.Notification; import android.app.NotificationChannel; @@ -93,7 +92,6 @@ import android.view.ViewAnimationUtils; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewStub; -import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AccelerateDecelerateInterpolator; @@ -146,7 +144,6 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import androidx.webkit.WebViewFeature; -import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import org.jsoup.nodes.Document; @@ -8523,514 +8520,4 @@ public class AdapterMessage extends RecyclerView.Adapter task = new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - long id = args.getLong("id"); - String notes = args.getString("notes"); - Integer color = args.getInt("color"); - - if ("".equals(notes.trim())) - notes = null; - - if (color == Color.TRANSPARENT) - color = null; - - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - EntityMessage message = db.message().getMessage(id); - if (message == null) - return null; - - db.message().setMessageNotes(message.id, notes, color); - - if (TextUtils.isEmpty(message.msgid)) - return null; - - List messages = - db.message().getMessagesBySimilarity(message.account, message.id, message.msgid, message.hash); - if (messages == null) - return null; - - for (EntityMessage m : messages) - db.message().setMessageNotes(m.id, notes, color); - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - return null; - } - - @Override - protected void onExecuted(Bundle args, Void data) { - WorkerFts.init(context, false); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(getParentFragmentManager(), ex); - } - }; - - AlertDialog.Builder builder = new AlertDialog.Builder(context) - .setView(view) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Bundle args = new Bundle(); - args.putLong("id", id); - args.putString("notes", etNotes.getText().toString()); - args.putInt("color", btnColor.getColor()); - - task.execute(getContext(), getActivity(), args, "message:note"); - } - }) - .setNegativeButton(android.R.string.cancel, null); - - if (!TextUtils.isEmpty(notes)) - builder.setNeutralButton(R.string.title_reset, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Bundle args = new Bundle(); - args.putLong("id", id); - args.putString("notes", ""); - args.putInt("color", Color.TRANSPARENT); - - task.execute(getContext(), getActivity(), args, "message:note"); - } - }); - - return builder.create(); - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - try { - if (resultCode == RESULT_OK && data != null) { - Bundle args = data.getBundleExtra("args"); - int color = args.getInt("color"); - btnColor.setColor(color); - - Context context = getContext(); - if (context != null) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - prefs.edit().putInt("note_color", color).apply(); - } - } - } catch (Throwable ex) { - Log.e(ex); - } - } - } - - public static class FragmentDialogKeywordManage extends FragmentDialogBase { - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - final long id = getArguments().getLong("id"); - - final Context context = getContext(); - final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_keyword_manage, null); - final RecyclerView rvKeyword = dview.findViewById(R.id.rvKeyword); - final FloatingActionButton fabAdd = dview.findViewById(R.id.fabAdd); - final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait); - - rvKeyword.setHasFixedSize(false); - final LinearLayoutManager llm = new LinearLayoutManager(context); - rvKeyword.setLayoutManager(llm); - - final AdapterKeyword adapter = new AdapterKeyword(context, getViewLifecycleOwner()); - rvKeyword.setAdapter(adapter); - - fabAdd.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Bundle args = new Bundle(); - args.putLong("id", id); - - FragmentDialogKeywordAdd fragment = new FragmentDialogKeywordAdd(); - fragment.setArguments(args); - fragment.show(getParentFragmentManager(), "keyword:add"); - } - }); - - pbWait.setVisibility(View.VISIBLE); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - DB db = DB.getInstance(context); - db.message().liveMessageKeywords(id).observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(TupleKeyword.Persisted data) { - if (data == null) - data = new TupleKeyword.Persisted(); - - String global = prefs.getString("global_keywords", null); - if (global != null) { - List available = new ArrayList<>(); - available.addAll(Arrays.asList(global.split(" "))); - if (data.available != null) - available.addAll(Arrays.asList(data.available)); - data.available = available.toArray(new String[0]); - } - - pbWait.setVisibility(View.GONE); - adapter.set(id, TupleKeyword.from(context, data)); - } - }); - - return new AlertDialog.Builder(context) - .setIcon(R.drawable.twotone_label_important_24) - .setTitle(R.string.title_manage_keywords) - .setView(dview) - .setPositiveButton(android.R.string.ok, null) - .create(); - } - - @Override - public void onResume() { - super.onResume(); - Dialog dialog = getDialog(); - dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - //dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - } - } - - public static class FragmentDialogKeywordAdd extends FragmentDialogBase { - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - final long id = getArguments().getLong("id"); - - final Context context = getContext(); - - View view = LayoutInflater.from(context).inflate(R.layout.dialog_keyword_add, null); - final EditText etKeyword = view.findViewById(R.id.etKeyword); - etKeyword.setText(null); - - return new AlertDialog.Builder(context) - .setView(view) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String keyword = MessageHelper.sanitizeKeyword(etKeyword.getText().toString()); - if (!TextUtils.isEmpty(keyword)) { - Bundle args = new Bundle(); - args.putLong("id", id); - args.putString("keyword", keyword); - - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - long id = args.getLong("id"); - String keyword = args.getString("keyword"); - - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - EntityMessage message = db.message().getMessage(id); - if (message == null) - return null; - - EntityOperation.queue(context, message, EntityOperation.KEYWORD, keyword, true); - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - ServiceSynchronize.eval(context, "keyword=" + keyword); - - return null; - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(getParentFragmentManager(), ex); - } - }.execute(getContext(), getActivity(), args, "keyword:add"); - } - } - }) - .setNegativeButton(android.R.string.cancel, null) - .create(); - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - } - } - - public static class FragmentDialogLabelsManage extends FragmentDialogBase { - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - final long id = getArguments().getLong("id"); - String self = getArguments().getString("self"); - String[] labels = getArguments().getStringArray("labels"); - final String[] folders = getArguments().getStringArray("folders"); - - List l = new ArrayList<>(); - if (self != null) - l.add(self); - if (labels != null) - l.addAll(Arrays.asList(labels)); - - boolean[] checked = new boolean[folders.length]; - for (int i = 0; i < folders.length; i++) - if (l.contains(folders[i])) - checked[i] = true; - - return new AlertDialog.Builder(getContext()) - .setIcon(R.drawable.twotone_label_24) - .setTitle(R.string.title_manage_labels) - .setMultiChoiceItems(folders, checked, new DialogInterface.OnMultiChoiceClickListener() { - @Override - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - Bundle args = new Bundle(); - args.putLong("id", id); - args.putString("label", folders[which]); - args.putBoolean("set", isChecked); - - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - long id = args.getLong("id"); - String label = args.getString("label"); - boolean set = args.getBoolean("set"); - - DB db = DB.getInstance(context); - EntityMessage message = db.message().getMessage(id); - if (message == null) - return null; - - EntityOperation.queue(context, message, EntityOperation.LABEL, label, set); - - return null; - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(getParentFragmentManager(), ex); - } - }.execute(FragmentDialogLabelsManage.this, args, "label:set"); - } - }) - .create(); - } - } - - public static class FragmentDialogPrint extends FragmentDialogBase { - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - final Context context = getContext(); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - View dview = LayoutInflater.from(context).inflate(R.layout.dialog_print, null); - CheckBox cbHeader = dview.findViewById(R.id.cbHeader); - CheckBox cbImages = dview.findViewById(R.id.cbImages); - CheckBox cbNotAgain = dview.findViewById(R.id.cbNotAgain); - - cbHeader.setChecked(prefs.getBoolean("print_html_header", true)); - cbHeader.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - prefs.edit().putBoolean("print_html_header", isChecked).apply(); - } - }); - - cbImages.setChecked(prefs.getBoolean("print_html_images", true)); - cbImages.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - prefs.edit().putBoolean("print_html_images", isChecked).apply(); - } - }); - - cbNotAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - prefs.edit().putBoolean("print_html_confirmed", isChecked).apply(); - } - }); - - return new AlertDialog.Builder(getContext()) - .setView(dview) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - sendResult(Activity.RESULT_OK); - } - }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - sendResult(Activity.RESULT_CANCELED); - } - }) - .create(); - } - } - - public static class FragmentDialogButtons extends FragmentDialogBase { - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - final Context context = getContext(); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_buttons, null); - final CheckBox cbSeen = dview.findViewById(R.id.cbSeen); - final CheckBox cbHide = dview.findViewById(R.id.cbHide); - final CheckBox cbImportance = dview.findViewById(R.id.cbImportance); - final CheckBox cbJunk = dview.findViewById(R.id.cbJunk); - final CheckBox cbTrash = dview.findViewById(R.id.cbTrash); - final CheckBox cbArchive = dview.findViewById(R.id.cbArchive); - final CheckBox cbMove = dview.findViewById(R.id.cbMove); - final CheckBox cbCopy = dview.findViewById(R.id.cbCopy); - final CheckBox cbNotes = dview.findViewById(R.id.cbNotes); - final CheckBox cbRule = dview.findViewById(R.id.cbRule); - final CheckBox cbKeywords = dview.findViewById(R.id.cbKeywords); - final CheckBox cbSearch = dview.findViewById(R.id.cbSearch); - final CheckBox cbSearchText = dview.findViewById(R.id.cbSearchText); - final CheckBox cbTranslate = dview.findViewById(R.id.cbTranslate); - final CheckBox cbFullScreen = dview.findViewById(R.id.cbFullScreen); - final CheckBox cbForceLight = dview.findViewById(R.id.cbForceLight); - final CheckBox cbEvent = dview.findViewById(R.id.cbEvent); - final CheckBox cbShare = dview.findViewById(R.id.cbShare); - final CheckBox cbPin = dview.findViewById(R.id.cbPin); - final CheckBox cbPrint = dview.findViewById(R.id.cbPrint); - final CheckBox cbHeaders = dview.findViewById(R.id.cbHeaders); - final CheckBox cbRaw = dview.findViewById(R.id.cbRaw); - final CheckBox cbUnsubscribe = dview.findViewById(R.id.cbUnsubscribe); - - cbTranslate.setVisibility(DeepL.isAvailable(context) ? View.VISIBLE : View.GONE); - cbPin.setVisibility(Shortcuts.can(context) ? View.VISIBLE : View.GONE); - - cbSeen.setChecked(prefs.getBoolean("button_seen", false)); - cbHide.setChecked(prefs.getBoolean("button_hide", false)); - cbImportance.setChecked(prefs.getBoolean("button_importance", false)); - cbJunk.setChecked(prefs.getBoolean("button_junk", true)); - cbTrash.setChecked(prefs.getBoolean("button_trash", true)); - cbArchive.setChecked(prefs.getBoolean("button_archive", true)); - cbMove.setChecked(prefs.getBoolean("button_move", true)); - cbCopy.setChecked(prefs.getBoolean("button_copy", false)); - cbNotes.setChecked(prefs.getBoolean("button_notes", false)); - cbRule.setChecked(prefs.getBoolean("button_rule", false)); - cbKeywords.setChecked(prefs.getBoolean("button_keywords", false)); - cbSearch.setChecked(prefs.getBoolean("button_search", false)); - cbSearchText.setChecked(prefs.getBoolean("button_search_text", false)); - cbTranslate.setChecked(prefs.getBoolean("button_translate", true)); - cbFullScreen.setChecked(prefs.getBoolean("button_full_screen", false)); - cbForceLight.setChecked(prefs.getBoolean("button_force_light", true)); - cbEvent.setChecked(prefs.getBoolean("button_event", false)); - cbShare.setChecked(prefs.getBoolean("button_share", false)); - cbPin.setChecked(prefs.getBoolean("button_pin", false)); - cbPrint.setChecked(prefs.getBoolean("button_print", false)); - cbHeaders.setChecked(prefs.getBoolean("button_headers", false)); - cbRaw.setChecked(prefs.getBoolean("button_raw", false)); - cbUnsubscribe.setChecked(prefs.getBoolean("button_unsubscribe", true)); - - return new AlertDialog.Builder(getContext()) - .setView(dview) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean("button_seen", cbSeen.isChecked()); - editor.putBoolean("button_hide", cbHide.isChecked()); - editor.putBoolean("button_importance", cbImportance.isChecked()); - editor.putBoolean("button_junk", cbJunk.isChecked()); - editor.putBoolean("button_trash", cbTrash.isChecked()); - editor.putBoolean("button_archive", cbArchive.isChecked()); - editor.putBoolean("button_move", cbMove.isChecked()); - editor.putBoolean("button_copy", cbCopy.isChecked()); - editor.putBoolean("button_notes", cbNotes.isChecked()); - editor.putBoolean("button_rule", cbRule.isChecked()); - editor.putBoolean("button_keywords", cbKeywords.isChecked()); - editor.putBoolean("button_search", cbSearch.isChecked()); - editor.putBoolean("button_search_text", cbSearchText.isChecked()); - editor.putBoolean("button_translate", cbTranslate.isChecked()); - editor.putBoolean("button_full_screen", cbFullScreen.isChecked()); - editor.putBoolean("button_force_light", cbForceLight.isChecked()); - editor.putBoolean("button_event", cbEvent.isChecked()); - editor.putBoolean("button_share", cbShare.isChecked()); - editor.putBoolean("button_pin", cbPin.isChecked()); - editor.putBoolean("button_print", cbPrint.isChecked()); - editor.putBoolean("button_headers", cbHeaders.isChecked()); - editor.putBoolean("button_raw", cbRaw.isChecked()); - editor.putBoolean("button_unsubscribe", cbUnsubscribe.isChecked()); - editor.apply(); - sendResult(Activity.RESULT_OK); - } - }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - sendResult(Activity.RESULT_CANCELED); - } - }) - .create(); - } - } } diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java b/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java new file mode 100644 index 0000000000..eb3a6832a6 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogButtons.java @@ -0,0 +1,137 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail 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. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceManager; + +public class FragmentDialogButtons extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Context context = getContext(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_buttons, null); + final CheckBox cbSeen = dview.findViewById(R.id.cbSeen); + final CheckBox cbHide = dview.findViewById(R.id.cbHide); + final CheckBox cbImportance = dview.findViewById(R.id.cbImportance); + final CheckBox cbJunk = dview.findViewById(R.id.cbJunk); + final CheckBox cbTrash = dview.findViewById(R.id.cbTrash); + final CheckBox cbArchive = dview.findViewById(R.id.cbArchive); + final CheckBox cbMove = dview.findViewById(R.id.cbMove); + final CheckBox cbCopy = dview.findViewById(R.id.cbCopy); + final CheckBox cbNotes = dview.findViewById(R.id.cbNotes); + final CheckBox cbRule = dview.findViewById(R.id.cbRule); + final CheckBox cbKeywords = dview.findViewById(R.id.cbKeywords); + final CheckBox cbSearch = dview.findViewById(R.id.cbSearch); + final CheckBox cbSearchText = dview.findViewById(R.id.cbSearchText); + final CheckBox cbTranslate = dview.findViewById(R.id.cbTranslate); + final CheckBox cbFullScreen = dview.findViewById(R.id.cbFullScreen); + final CheckBox cbForceLight = dview.findViewById(R.id.cbForceLight); + final CheckBox cbEvent = dview.findViewById(R.id.cbEvent); + final CheckBox cbShare = dview.findViewById(R.id.cbShare); + final CheckBox cbPin = dview.findViewById(R.id.cbPin); + final CheckBox cbPrint = dview.findViewById(R.id.cbPrint); + final CheckBox cbHeaders = dview.findViewById(R.id.cbHeaders); + final CheckBox cbRaw = dview.findViewById(R.id.cbRaw); + final CheckBox cbUnsubscribe = dview.findViewById(R.id.cbUnsubscribe); + + cbTranslate.setVisibility(DeepL.isAvailable(context) ? View.VISIBLE : View.GONE); + cbPin.setVisibility(Shortcuts.can(context) ? View.VISIBLE : View.GONE); + + cbSeen.setChecked(prefs.getBoolean("button_seen", false)); + cbHide.setChecked(prefs.getBoolean("button_hide", false)); + cbImportance.setChecked(prefs.getBoolean("button_importance", false)); + cbJunk.setChecked(prefs.getBoolean("button_junk", true)); + cbTrash.setChecked(prefs.getBoolean("button_trash", true)); + cbArchive.setChecked(prefs.getBoolean("button_archive", true)); + cbMove.setChecked(prefs.getBoolean("button_move", true)); + cbCopy.setChecked(prefs.getBoolean("button_copy", false)); + cbNotes.setChecked(prefs.getBoolean("button_notes", false)); + cbRule.setChecked(prefs.getBoolean("button_rule", false)); + cbKeywords.setChecked(prefs.getBoolean("button_keywords", false)); + cbSearch.setChecked(prefs.getBoolean("button_search", false)); + cbSearchText.setChecked(prefs.getBoolean("button_search_text", false)); + cbTranslate.setChecked(prefs.getBoolean("button_translate", true)); + cbFullScreen.setChecked(prefs.getBoolean("button_full_screen", false)); + cbForceLight.setChecked(prefs.getBoolean("button_force_light", true)); + cbEvent.setChecked(prefs.getBoolean("button_event", false)); + cbShare.setChecked(prefs.getBoolean("button_share", false)); + cbPin.setChecked(prefs.getBoolean("button_pin", false)); + cbPrint.setChecked(prefs.getBoolean("button_print", false)); + cbHeaders.setChecked(prefs.getBoolean("button_headers", false)); + cbRaw.setChecked(prefs.getBoolean("button_raw", false)); + cbUnsubscribe.setChecked(prefs.getBoolean("button_unsubscribe", true)); + + return new AlertDialog.Builder(getContext()) + .setView(dview) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean("button_seen", cbSeen.isChecked()); + editor.putBoolean("button_hide", cbHide.isChecked()); + editor.putBoolean("button_importance", cbImportance.isChecked()); + editor.putBoolean("button_junk", cbJunk.isChecked()); + editor.putBoolean("button_trash", cbTrash.isChecked()); + editor.putBoolean("button_archive", cbArchive.isChecked()); + editor.putBoolean("button_move", cbMove.isChecked()); + editor.putBoolean("button_copy", cbCopy.isChecked()); + editor.putBoolean("button_notes", cbNotes.isChecked()); + editor.putBoolean("button_rule", cbRule.isChecked()); + editor.putBoolean("button_keywords", cbKeywords.isChecked()); + editor.putBoolean("button_search", cbSearch.isChecked()); + editor.putBoolean("button_search_text", cbSearchText.isChecked()); + editor.putBoolean("button_translate", cbTranslate.isChecked()); + editor.putBoolean("button_full_screen", cbFullScreen.isChecked()); + editor.putBoolean("button_force_light", cbForceLight.isChecked()); + editor.putBoolean("button_event", cbEvent.isChecked()); + editor.putBoolean("button_share", cbShare.isChecked()); + editor.putBoolean("button_pin", cbPin.isChecked()); + editor.putBoolean("button_print", cbPrint.isChecked()); + editor.putBoolean("button_headers", cbHeaders.isChecked()); + editor.putBoolean("button_raw", cbRaw.isChecked()); + editor.putBoolean("button_unsubscribe", cbUnsubscribe.isChecked()); + editor.apply(); + sendResult(Activity.RESULT_OK); + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sendResult(Activity.RESULT_CANCELED); + } + }) + .create(); + } +} diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogKeywordAdd.java b/app/src/main/java/eu/faircode/email/FragmentDialogKeywordAdd.java new file mode 100644 index 0000000000..83d22f394b --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogKeywordAdd.java @@ -0,0 +1,102 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail 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. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; + +public class FragmentDialogKeywordAdd extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final long id = getArguments().getLong("id"); + + final Context context = getContext(); + + View view = LayoutInflater.from(context).inflate(R.layout.dialog_keyword_add, null); + final EditText etKeyword = view.findViewById(R.id.etKeyword); + etKeyword.setText(null); + + return new AlertDialog.Builder(context) + .setView(view) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String keyword = MessageHelper.sanitizeKeyword(etKeyword.getText().toString()); + if (!TextUtils.isEmpty(keyword)) { + Bundle args = new Bundle(); + args.putLong("id", id); + args.putString("keyword", keyword); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long id = args.getLong("id"); + String keyword = args.getString("keyword"); + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + EntityOperation.queue(context, message, EntityOperation.KEYWORD, keyword, true); + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + ServiceSynchronize.eval(context, "keyword=" + keyword); + + return null; + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(getContext(), getActivity(), args, "keyword:add"); + } + } + }) + .setNegativeButton(android.R.string.cancel, null) + .create(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + } +} diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogKeywordManage.java b/app/src/main/java/eu/faircode/email/FragmentDialogKeywordManage.java new file mode 100644 index 0000000000..36870e85db --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogKeywordManage.java @@ -0,0 +1,115 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail 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. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import android.app.Dialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.lifecycle.Observer; +import androidx.preference.PreferenceManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FragmentDialogKeywordManage extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final long id = getArguments().getLong("id"); + + final Context context = getContext(); + final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_keyword_manage, null); + final RecyclerView rvKeyword = dview.findViewById(R.id.rvKeyword); + final FloatingActionButton fabAdd = dview.findViewById(R.id.fabAdd); + final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait); + + rvKeyword.setHasFixedSize(false); + final LinearLayoutManager llm = new LinearLayoutManager(context); + rvKeyword.setLayoutManager(llm); + + final AdapterKeyword adapter = new AdapterKeyword(context, getViewLifecycleOwner()); + rvKeyword.setAdapter(adapter); + + fabAdd.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Bundle args = new Bundle(); + args.putLong("id", id); + + FragmentDialogKeywordAdd fragment = new FragmentDialogKeywordAdd(); + fragment.setArguments(args); + fragment.show(getParentFragmentManager(), "keyword:add"); + } + }); + + pbWait.setVisibility(View.VISIBLE); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + DB db = DB.getInstance(context); + db.message().liveMessageKeywords(id).observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(TupleKeyword.Persisted data) { + if (data == null) + data = new TupleKeyword.Persisted(); + + String global = prefs.getString("global_keywords", null); + if (global != null) { + List available = new ArrayList<>(); + available.addAll(Arrays.asList(global.split(" "))); + if (data.available != null) + available.addAll(Arrays.asList(data.available)); + data.available = available.toArray(new String[0]); + } + + pbWait.setVisibility(View.GONE); + adapter.set(id, TupleKeyword.from(context, data)); + } + }); + + return new AlertDialog.Builder(context) + .setIcon(R.drawable.twotone_label_important_24) + .setTitle(R.string.title_manage_keywords) + .setView(dview) + .setPositiveButton(android.R.string.ok, null) + .create(); + } + + @Override + public void onResume() { + super.onResume(); + Dialog dialog = getDialog(); + dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + //dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + } +} diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogLabelsManage.java b/app/src/main/java/eu/faircode/email/FragmentDialogLabelsManage.java new file mode 100644 index 0000000000..57e966ea59 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogLabelsManage.java @@ -0,0 +1,92 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail 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. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FragmentDialogLabelsManage extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final long id = getArguments().getLong("id"); + String self = getArguments().getString("self"); + String[] labels = getArguments().getStringArray("labels"); + final String[] folders = getArguments().getStringArray("folders"); + + List l = new ArrayList<>(); + if (self != null) + l.add(self); + if (labels != null) + l.addAll(Arrays.asList(labels)); + + boolean[] checked = new boolean[folders.length]; + for (int i = 0; i < folders.length; i++) + if (l.contains(folders[i])) + checked[i] = true; + + return new AlertDialog.Builder(getContext()) + .setIcon(R.drawable.twotone_label_24) + .setTitle(R.string.title_manage_labels) + .setMultiChoiceItems(folders, checked, new DialogInterface.OnMultiChoiceClickListener() { + @Override + public void onClick(DialogInterface dialog, int which, boolean isChecked) { + Bundle args = new Bundle(); + args.putLong("id", id); + args.putString("label", folders[which]); + args.putBoolean("set", isChecked); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long id = args.getLong("id"); + String label = args.getString("label"); + boolean set = args.getBoolean("set"); + + DB db = DB.getInstance(context); + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + EntityOperation.queue(context, message, EntityOperation.LABEL, label, set); + + return null; + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(FragmentDialogLabelsManage.this, args, "label:set"); + } + }) + .create(); + } +} diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogNotes.java b/app/src/main/java/eu/faircode/email/FragmentDialogNotes.java new file mode 100644 index 0000000000..a8934c8e1b --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogNotes.java @@ -0,0 +1,197 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail 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. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import static android.app.Activity.RESULT_OK; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceManager; + +import java.util.List; + +public class FragmentDialogNotes extends FragmentDialogBase { + private ViewButtonColor btnColor; + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Bundle args = getArguments(); + final long id = args.getLong("id"); + final String notes = args.getString("notes"); + + final Context context = getContext(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + final Integer color = (TextUtils.isEmpty(notes) + ? prefs.getInt("note_color", Color.TRANSPARENT) + : args.getInt("color")); + + View view = LayoutInflater.from(context).inflate(R.layout.dialog_notes, null); + final EditText etNotes = view.findViewById(R.id.etNotes); + btnColor = view.findViewById(R.id.btnColor); + + etNotes.setText(notes); + btnColor.setColor(color); + + etNotes.selectAll(); + + btnColor.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Helper.hideKeyboard(etNotes); + + Bundle args = new Bundle(); + args.putInt("color", btnColor.getColor()); + args.putString("title", getString(R.string.title_color)); + args.putBoolean("reset", true); + + FragmentDialogColor fragment = new FragmentDialogColor(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentDialogNotes.this, 1); + fragment.show(getParentFragmentManager(), "notes:color"); + } + }); + + final SimpleTask task = new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long id = args.getLong("id"); + String notes = args.getString("notes"); + Integer color = args.getInt("color"); + + if ("".equals(notes.trim())) + notes = null; + + if (color == Color.TRANSPARENT) + color = null; + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + db.message().setMessageNotes(message.id, notes, color); + + if (TextUtils.isEmpty(message.msgid)) + return null; + + List messages = + db.message().getMessagesBySimilarity(message.account, message.id, message.msgid, message.hash); + if (messages == null) + return null; + + for (EntityMessage m : messages) + db.message().setMessageNotes(m.id, notes, color); + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return null; + } + + @Override + protected void onExecuted(Bundle args, Void data) { + WorkerFts.init(context, false); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setView(view) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Bundle args = new Bundle(); + args.putLong("id", id); + args.putString("notes", etNotes.getText().toString()); + args.putInt("color", btnColor.getColor()); + + task.execute(getContext(), getActivity(), args, "message:note"); + } + }) + .setNegativeButton(android.R.string.cancel, null); + + if (!TextUtils.isEmpty(notes)) + builder.setNeutralButton(R.string.title_reset, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Bundle args = new Bundle(); + args.putLong("id", id); + args.putString("notes", ""); + args.putInt("color", Color.TRANSPARENT); + + task.execute(getContext(), getActivity(), args, "message:note"); + } + }); + + return builder.create(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + try { + if (resultCode == RESULT_OK && data != null) { + Bundle args = data.getBundleExtra("args"); + int color = args.getInt("color"); + btnColor.setColor(color); + + Context context = getContext(); + if (context != null) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().putInt("note_color", color).apply(); + } + } + } catch (Throwable ex) { + Log.e(ex); + } + } +} diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogPrint.java b/app/src/main/java/eu/faircode/email/FragmentDialogPrint.java new file mode 100644 index 0000000000..af8413b774 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogPrint.java @@ -0,0 +1,89 @@ +package eu.faircode.email; + +/* + This file is part of FairEmail. + + FairEmail is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FairEmail 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. + + You should have received a copy of the GNU General Public License + along with FairEmail. If not, see . + + Copyright 2018-2023 by Marcel Bokhorst (M66B) +*/ + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceManager; + +public class FragmentDialogPrint extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Context context = getContext(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + View dview = LayoutInflater.from(context).inflate(R.layout.dialog_print, null); + CheckBox cbHeader = dview.findViewById(R.id.cbHeader); + CheckBox cbImages = dview.findViewById(R.id.cbImages); + CheckBox cbNotAgain = dview.findViewById(R.id.cbNotAgain); + + cbHeader.setChecked(prefs.getBoolean("print_html_header", true)); + cbHeader.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + prefs.edit().putBoolean("print_html_header", isChecked).apply(); + } + }); + + cbImages.setChecked(prefs.getBoolean("print_html_images", true)); + cbImages.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + prefs.edit().putBoolean("print_html_images", isChecked).apply(); + } + }); + + cbNotAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + prefs.edit().putBoolean("print_html_confirmed", isChecked).apply(); + } + }); + + return new AlertDialog.Builder(getContext()) + .setView(dview) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + sendResult(Activity.RESULT_OK); + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sendResult(Activity.RESULT_CANCELED); + } + }) + .create(); + } +}