diff --git a/FAQ.md b/FAQ.md
index beb002afcb..eed46ff694 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -415,6 +415,7 @@ Anything on this list is in random order and *might* be added in the near future
* [(201) What is certificate transparency?](#faq201)
* [(202) What is DNSSEC and what is DANE?](#faq202)
* [(203) Where is my sent message?](#faq203)
+* [(204) How do I use Gemini?](#faq204)
[I have another question.](#get-support)
@@ -5802,6 +5803,18 @@ Basically, an outgoing message is either in the draft messages folder, the outbo
+
+**(204) How do I use Gemini?**
+
+1. Check if your country [is supported](https://support.google.com/gemini/answer/13575153)
+1. Get an API key via [here](https://ai.google.dev/tutorials/setup)
+1. Enter the API key in the integration settings tab page
+1. Enable Gemini integration in the integration settings tab page
+
+For usage, please see [this FAQ](#faq190)
+
+
+
Get support
🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https%3A%2F%2Fm66b.github.io%2FFairEmail%2F%23get-support)
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java b/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java
index 3c6b5ed641..0ef1e049bd 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsIntegrations.java
@@ -89,6 +89,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
private EditText etGemini;
private TextInputLayout tilGemini;
private EditText etGeminiModel;
+ private ImageButton ibGemini;
private CardView cardVirusTotal;
private CardView cardSend;
@@ -158,6 +159,7 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
etGemini = view.findViewById(R.id.etGemini);
tilGemini = view.findViewById(R.id.tilGemini);
etGeminiModel = view.findViewById(R.id.etGeminiModel);
+ ibGemini = view.findViewById(R.id.ibGemini);
cardVirusTotal = view.findViewById(R.id.cardVirusTotal);
cardSend = view.findViewById(R.id.cardSend);
@@ -604,6 +606,13 @@ public class FragmentOptionsIntegrations extends FragmentBase implements SharedP
}
});
+ ibGemini.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Helper.viewFAQ(v.getContext(), 204);
+ }
+ });
+
// Initialize
FragmentDialogTheme.setBackground(getContext(), view, false);
diff --git a/app/src/main/java/eu/faircode/email/Gemini.java b/app/src/main/java/eu/faircode/email/Gemini.java
index 4f5124d433..f3d06b87db 100644
--- a/app/src/main/java/eu/faircode/email/Gemini.java
+++ b/app/src/main/java/eu/faircode/email/Gemini.java
@@ -64,23 +64,30 @@ public class Gemini {
jpart.put(jtext);
}
- JSONObject jcontent = new JSONObject();
- jcontent.put("parts", jpart);
+ JSONObject jcontent0 = new JSONObject();
+ jcontent0.put("parts", jpart);
JSONArray jcontents = new JSONArray();
- jcontents.put(jcontent);
+ jcontents.put(jcontent0);
JSONObject jrequest = new JSONObject();
jrequest.put("contents", jcontents);
- String path = "models/" + model + ":generateContent";
+ String path = "models/" + Uri.encode(model) + ":generateContent";
JSONObject jresponse = call(context, "POST", path, jrequest);
- return new String[]{jresponse.getJSONArray("candidates")
- .getJSONObject(0)
- .getJSONObject("content")
- .getJSONArray("parts")
- .getJSONObject(0)
- .getString("text")};
+ JSONArray jcandidates = jresponse.optJSONArray("candidates");
+ if (jcandidates == null || jcandidates.length() < 1)
+ throw new IOException("candidates missing");
+ JSONObject jcontent = jcandidates.getJSONObject(0).optJSONObject("content");
+ if (jcontent == null)
+ throw new IOException("content missing");
+ JSONArray jparts = jcontent.optJSONArray("parts");
+ if (jparts == null || jparts.length() < 1)
+ throw new IOException("parts missing");
+ JSONObject jtext = jparts.getJSONObject(0);
+ if (!jtext.has("text"))
+ throw new IOException("text missing");
+ return new String[]{jtext.getString("text")};
}
private static String getUri(Context context) {
diff --git a/app/src/main/res/layout/fragment_options_integrations.xml b/app/src/main/res/layout/fragment_options_integrations.xml
index 3348733fa4..f4e2e80252 100644
--- a/app/src/main/res/layout/fragment_options_integrations.xml
+++ b/app/src/main/res/layout/fragment_options_integrations.xml
@@ -727,6 +727,18 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvGeminiModel" />
+
+