diff --git a/app/src/main/java/eu/faircode/email/AI.java b/app/src/main/java/eu/faircode/email/AI.java
index 46e709e33d..570abce6bd 100644
--- a/app/src/main/java/eu/faircode/email/AI.java
+++ b/app/src/main/java/eu/faircode/email/AI.java
@@ -151,7 +151,7 @@ public class AI {
return context.getString(R.string.title_summarize);
}
- static Spanned getSummaryText(Context context, EntityMessage message, long template) throws JSONException, IOException {
+ static Spanned getSummaryText(Context context, EntityMessage message, long template, String prompt) throws JSONException, IOException {
File file = message.getFile(context);
if (!file.exists())
return null;
@@ -171,8 +171,8 @@ public class AI {
if (TextUtils.isEmpty(body))
return null;
- String templatePrompt = null;
- if (template > 0L) {
+ String templatePrompt = prompt;
+ if (templatePrompt == null && template > 0L) {
DB db = DB.getInstance(context);
EntityAnswer t = db.answer().getAnswer(template);
if (t != null) {
diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java
index f0e84ba15f..55c597e850 100644
--- a/app/src/main/java/eu/faircode/email/AdapterMessage.java
+++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java
@@ -4665,7 +4665,7 @@ public class AdapterMessage extends RecyclerView.Adapter.
+
+ Copyright 2018-2025 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.os.Bundle;
+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 FragmentDialogPrompt extends FragmentDialogBase {
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+ final Context context = getContext();
+
+ View view = LayoutInflater.from(context).inflate(R.layout.dialog_prompt, null);
+ final EditText etPrompt = view.findViewById(R.id.etPrompt);
+
+ etPrompt.setText(null);
+
+ 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 = getArguments();
+ args.putString("prompt", etPrompt.getText().toString());
+ sendResult(RESULT_OK);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null);
+
+ return builder.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/FragmentDialogSummarize.java b/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java
index b81f25bb8b..31a5e02e41 100644
--- a/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java
+++ b/app/src/main/java/eu/faircode/email/FragmentDialogSummarize.java
@@ -94,37 +94,41 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
Bundle args = getArguments();
long template = args.getLong("template");
+ String prompt = args.getString("prompt");
+
+ if (prompt == null)
+ if (template <= 0)
+ tvCaption.setText(AI.getSummarizePrompt(context));
+ else {
+ tvCaption.setText(null);
+ new SimpleTask() {
+ @Override
+ protected String onExecute(Context context, Bundle args) throws Throwable {
+ long template = args.getLong("template");
+
+ DB db = DB.getInstance(context);
+ EntityAnswer prompt = db.answer().getAnswer(template);
+ if (prompt == null)
+ return null;
+
+ Document doc = JsoupEx.parse(prompt.getData(context, null).getHtml());
+ Spanned spanned = HtmlHelper.fromDocument(context, doc, null, null);
+ return spanned.toString();
+ }
- if (template <= 0)
- tvCaption.setText(AI.getSummarizePrompt(context));
- else {
- tvCaption.setText(null);
- new SimpleTask() {
- @Override
- protected String onExecute(Context context, Bundle args) throws Throwable {
- long template = args.getLong("template");
-
- DB db = DB.getInstance(context);
- EntityAnswer prompt = db.answer().getAnswer(template);
- if (prompt == null)
- return null;
-
- Document doc = JsoupEx.parse(prompt.getData(context, null).getHtml());
- Spanned spanned = HtmlHelper.fromDocument(context, doc, null, null);
- return spanned.toString();
- }
-
- @Override
- protected void onExecuted(Bundle args, String prompt) {
- tvCaption.setText(prompt);
- }
+ @Override
+ protected void onExecuted(Bundle args, String prompt) {
+ tvCaption.setText(prompt);
+ }
- @Override
- protected void onException(Bundle args, Throwable ex) {
- Log.unexpectedError(getParentFragmentManager(), ex);
- }
- }.execute(this, args, "ai:prompt");
- }
+ @Override
+ protected void onException(Bundle args, Throwable ex) {
+ Log.unexpectedError(getParentFragmentManager(), ex);
+ }
+ }.execute(this, args, "ai:prompt");
+ }
+ else
+ tvCaption.setText(prompt);
tvFrom.setText(args.getString("from"));
tvSubject.setText(args.getString("subject"));
@@ -155,7 +159,7 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
return null;
long start = new Date().getTime();
- Spanned summary = AI.getSummaryText(context, message, template);
+ Spanned summary = AI.getSummaryText(context, message, template, prompt);
args.putLong("elapsed", new Date().getTime() - start);
return summary;
@@ -184,9 +188,9 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
return builder.create();
}
- public static void summarize(EntityMessage message, FragmentManager fm, View anchor, LifecycleOwner owner) {
- if (anchor == null) {
- summarize(message, fm, null);
+ public static void summarize(EntityMessage message, FragmentManager fm, View anchor, LifecycleOwner owner, String prompt) {
+ if (anchor == null || prompt != null) {
+ summarize(message, fm, null, prompt);
return;
}
@@ -202,7 +206,7 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
@Override
protected void onExecuted(Bundle args, List prompts) {
if (prompts == null || prompts.isEmpty())
- summarize(message, fm, null);
+ summarize(message, fm, null, prompt);
else {
PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(context, owner, anchor);
@@ -224,7 +228,7 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
@Override
public boolean onMenuItemClick(MenuItem item) {
long id = item.getIntent().getLongExtra("id", -1L);
- summarize(message, fm, id);
+ summarize(message, fm, id, prompt);
return true;
}
});
@@ -240,12 +244,13 @@ public class FragmentDialogSummarize extends FragmentDialogBase {
}.execute(context, owner, new Bundle(), "AI:select");
}
- private static void summarize(EntityMessage message, FragmentManager fm, Long template) {
+ private static void summarize(EntityMessage message, FragmentManager fm, Long template, String prompt) {
Bundle args = new Bundle();
args.putLong("id", message.id);
args.putString("from", MessageHelper.formatAddresses(message.from));
args.putString("subject", message.subject);
args.putLong("template", template == null ? -1L : template);
+ args.putString("prompt", prompt);
FragmentDialogSummarize fragment = new FragmentDialogSummarize();
fragment.setArguments(args);
diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java
index 69ca48b5c5..c1620b7796 100644
--- a/app/src/main/java/eu/faircode/email/FragmentMessages.java
+++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java
@@ -456,6 +456,7 @@ public class FragmentMessages extends FragmentBase
static final int REQUEST_EDIT_SUBJECT = 30;
private static final int REQUEST_ANSWER_SETTINGS = 31;
private static final int REQUEST_DESELECT = 32;
+ static final int REQUEST_PROMPT = 33;
static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW";
static final String ACTION_VERIFYDECRYPT = BuildConfig.APPLICATION_ID + ".VERIFYDECRYPT";
@@ -1660,7 +1661,7 @@ public class FragmentMessages extends FragmentBase
if (result == null || result.single == null || !result.single.content)
return;
- FragmentDialogSummarize.summarize(result.single, getParentFragmentManager(), ibSummarize, getViewLifecycleOwner());
+ FragmentDialogSummarize.summarize(result.single, getParentFragmentManager(), ibSummarize, getViewLifecycleOwner(), null);
}
});
@@ -3818,7 +3819,7 @@ public class FragmentMessages extends FragmentBase
private void onSwipeSummarize(final @NonNull TupleMessageEx message) {
final Context context = getContext();
if (AI.isAvailable(context))
- FragmentDialogSummarize.summarize(message, getParentFragmentManager(), null, getViewLifecycleOwner());
+ FragmentDialogSummarize.summarize(message, getParentFragmentManager(), null, getViewLifecycleOwner(), null);
else
context.startActivity(new Intent(context, ActivitySetup.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
@@ -9661,6 +9662,10 @@ public class FragmentMessages extends FragmentBase
if (selectionTracker != null)
selectionTracker.clearSelection();
break;
+ case REQUEST_PROMPT:
+ if (resultCode == RESULT_OK)
+ onActionSummarize(data.getBundleExtra("args"));
+ break;
}
} catch (Throwable ex) {
Log.e(ex);
@@ -11191,6 +11196,29 @@ public class FragmentMessages extends FragmentBase
}.execute(this, args, "edit:subject");
}
+ private void onActionSummarize(Bundle args) {
+ new SimpleTask() {
+ @Override
+ protected EntityMessage onExecute(Context context, Bundle args) throws Throwable {
+ long id = args.getLong("id");
+ DB db = DB.getInstance(context);
+ return db.message().getMessage(id);
+ }
+
+ @Override
+ protected void onExecuted(Bundle args, EntityMessage message) {
+ if (message == null)
+ return;
+ FragmentDialogSummarize.summarize(message, getParentFragmentManager(), null, getViewLifecycleOwner(), args.getString("prompt"));
+ }
+
+ @Override
+ protected void onException(Bundle args, Throwable ex) {
+ Log.unexpectedError(getParentFragmentManager(), ex);
+ }
+ }.execute(this, args, "prompt");
+ }
+
private void onMoveAskAcross(final ArrayList result) {
boolean across = false;
for (MessageTarget target : result)
diff --git a/app/src/main/res/layout/dialog_prompt.xml b/app/src/main/res/layout/dialog_prompt.xml
new file mode 100644
index 0000000000..062dad5917
--- /dev/null
+++ b/app/src/main/res/layout/dialog_prompt.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file