Compare commits

...

7 Commits

@ -78,7 +78,7 @@ This app starts a foreground service with a low-priority status bar notification
All pro features are convenience or advanced features.
* Account/identity/folder colors
* Account/identity/folder colors/avatars
* Colored stars
* Notification settings (sounds) per account/folder/sender (requires Android 8 Oreo)
* Configurable notification actions

@ -89,7 +89,7 @@ This app starts a foreground service with a low-priority status bar notification
All pro features are convenience or advanced features.
* Account/identity/folder colors
* Account/identity/folder colors/avatars
* Colored stars ([instructions](https://m66b.github.io/FairEmail/#faq107))
* Notification settings (sounds) per account/folder/sender (requires Android 8 Oreo) ([instructions](https://m66b.github.io/FairEmail/#faq145))
* Configurable notification actions

@ -190,6 +190,10 @@ public class AI {
HtmlHelper.truncate(d, MAX_SUMMARIZE_TEXT_SIZE);
String body = d.body().text().trim();
if (TextUtils.isEmpty(body))
return null;
String templatePrompt = null;
if (template > 0L) {
DB db = DB.getInstance(context);
@ -212,17 +216,13 @@ public class AI {
new OpenAI.Content[]{new OpenAI.Content(OpenAI.CONTENT_TEXT,
templatePrompt == null ? defaultPrompt : templatePrompt)}));
if (!TextUtils.isEmpty(message.subject))
input.add(new OpenAI.Message(OpenAI.USER,
new OpenAI.Content[]{new OpenAI.Content(OpenAI.CONTENT_TEXT, message.subject)}));
if (multimodal) {
SpannableStringBuilder ssb = HtmlHelper.fromDocument(context, d, null, null);
input.add(new OpenAI.Message(OpenAI.USER,
OpenAI.Content.get(ssb, message.id, context)));
} else
input.add(new OpenAI.Message(OpenAI.USER, new OpenAI.Content[]{
new OpenAI.Content(OpenAI.CONTENT_TEXT, d.text())}));
new OpenAI.Content(OpenAI.CONTENT_TEXT, body)}));
OpenAI.Message[] completions =
OpenAI.completeChat(context, model, input.toArray(new OpenAI.Message[0]), temperature, 1);
@ -239,12 +239,8 @@ public class AI {
float temperature = prefs.getFloat("gemini_temperature", Gemini.DEFAULT_TEMPERATURE);
String defaultPrompt = prefs.getString("gemini_summarize", Gemini.DEFAULT_SUMMARY_PROMPT);
String body = d.text();
List<String> texts = new ArrayList<>();
texts.add(templatePrompt == null ? defaultPrompt : templatePrompt);
if (!TextUtils.isEmpty(message.subject))
texts.add(message.subject);
if (!TextUtils.isEmpty(body))
texts.add(body);
Gemini.Message content = new Gemini.Message(Gemini.USER, texts.toArray(new String[0]));

@ -89,6 +89,7 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
private LifecycleOwner owner;
private LayoutInflater inflater;
private boolean pro;
private int dp24;
private int colorStripeWidth;
private int colorWarning;
@ -217,7 +218,7 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
vwColor.setBackgroundColor(account.color == null ? Color.TRANSPARENT : account.color);
vwColor.setVisibility(ActivityBilling.isPro(context) ? View.VISIBLE : View.INVISIBLE);
if (account.avatar == null)
if (account.avatar == null || !pro)
ivAvatar.setVisibility(hasAvatars ? View.INVISIBLE : View.GONE);
else {
Bundle args = new Bundle();
@ -962,6 +963,7 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
this.owner = parentFragment.getViewLifecycleOwner();
this.inflater = LayoutInflater.from(context);
this.pro = ActivityBilling.isPro(context);
this.dp24 = Helper.dp2pixels(context, 24);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
@ -1011,11 +1013,12 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, filtered), false);
hasAvatars = false;
for (TupleAccountFolder account : accounts)
if (account.avatar != null) {
hasAvatars = true;
break;
}
if (pro)
for (TupleAccountFolder account : accounts)
if (account.avatar != null) {
hasAvatars = true;
break;
}
items = filtered;

@ -1488,6 +1488,10 @@ public class EmailProvider implements Parcelable {
});
}
public boolean isSecure() {
return (score >= 20); // Autoconfig or better
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Server) {

@ -1584,7 +1584,8 @@ public class EntityRule {
try {
Spanned summary = AI.getSummaryText(context, message, -1L);
message.preview = (summary == null ? null : summary.toString().trim());
if (summary != null)
message.preview = summary.toString().trim();
} catch (Throwable ex) {
message.error = Log.formatThrowable(ex);
db.message().setMessageError(message.id, message.error);

@ -2057,8 +2057,14 @@ public class FragmentAccount extends FragmentBase {
}
private void onImageSelected(Uri uri) {
final Context context = getContext();
if (!ActivityBilling.isPro(context)) {
startActivity(new Intent(context, ActivityBilling.class));
return;
}
try {
final Context context = getContext();
NoStreamException.check(uri, context);
context.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

@ -413,6 +413,15 @@ public class FragmentPop extends FragmentBase {
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Workaround odd focus issue
if (scroll != null)
scroll.requestChildFocus(null, null);
}
private void onSave(boolean should) {
Bundle args = new Bundle();
args.putLong("id", id);
@ -1094,8 +1103,14 @@ public class FragmentPop extends FragmentBase {
}
private void onImageSelected(Uri uri) {
final Context context = getContext();
if (!ActivityBilling.isPro(context)) {
startActivity(new Intent(context, ActivityBilling.class));
return;
}
try {
final Context context = getContext();
NoStreamException.check(uri, context);
context.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

@ -588,7 +588,7 @@ public class FragmentQuickSetup extends FragmentBase {
account.host = provider.imap.host;
account.encryption = aencryption;
account.insecure = BuildConfig.PLAY_STORE_RELEASE;
account.insecure = (BuildConfig.PLAY_STORE_RELEASE && !provider.imap.isSecure());
account.port = provider.imap.port;
account.auth_type = AUTH_TYPE_PASSWORD;
account.user = user;
@ -638,6 +638,7 @@ public class FragmentQuickSetup extends FragmentBase {
identity.host = provider.smtp.host;
identity.encryption = iencryption;
identity.insecure = (BuildConfig.PLAY_STORE_RELEASE && !provider.smtp.isSecure());
identity.port = provider.smtp.port;
identity.auth_type = AUTH_TYPE_PASSWORD;
identity.user = user;

@ -73,6 +73,18 @@
android:textStyle="bold|italic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvIntegrationsInert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_integrations_inert"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?colorWarning"
android:textStyle="italic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvIntegrationsHint" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

@ -878,6 +878,7 @@
<string name="title_advanced_language">Language</string>
<string name="title_advanced_language_system">System</string>
<string name="title_advanced_integrations_hint">The cloud services below are not part of the app. Any payments will go directly to the cloud service and not to the app developer.</string>
<string name="title_advanced_integrations_inert">An integration which isn\'t configured is completely inert. No third-party libraries are being used to prevent tracking and analytics.</string>
<string name="title_advanced_lt">LanguageTool integration</string>
<string name="title_advanced_lt_sentence">Check every sentence</string>
<string name="title_advanced_lt_auto">Check paragraph after a new line</string>

Loading…
Cancel
Save