diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogVPN.java b/app/src/main/java/eu/faircode/email/FragmentDialogVPN.java new file mode 100644 index 0000000000..de80f0ff88 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogVPN.java @@ -0,0 +1,62 @@ +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-2024 by Marcel Bokhorst (M66B) +*/ + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.style.RelativeSizeSpan; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.preference.PreferenceManager; + +public class FragmentDialogVPN extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Context context = getContext(); + + SpannableStringBuilder ssb = new SpannableStringBuilderEx(); + ssb.append(context.getString(R.string.title_hint_vpn)); + ssb.append("\n\n"); + int start = ssb.length(); + ssb.append(context.getString(R.string.title_hint_dismiss)); + ssb.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL), start, ssb.length(), 0); + + return new AlertDialog.Builder(context) + .setIcon(R.drawable.twotone_vpn_key_24) + .setTitle(R.string.title_hint_vpn_active) + .setMessage(ssb) + .setPositiveButton(android.R.string.ok, null) + .setNegativeButton(R.string.title_dismiss, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().putBoolean("vpn_reminder", false).apply(); + } + }) + .create(); + } +} diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 6147198823..2e259fa809 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -254,6 +254,7 @@ public class FragmentMessages extends FragmentBase private TextView tvNotifications; private TextView tvBatteryOptimizations; private TextView tvDataSaver; + private TextView tvVpnActive; private TextView tvSupport; private ImageButton ibHintSupport; private ImageButton ibHintSwipe; @@ -282,6 +283,7 @@ public class FragmentMessages extends FragmentBase private Group grpNotifications; private Group grpBatteryOptimizations; private Group grpDataSaver; + private Group grpVpnActive; private Group grpSupport; private Group grpHintSupport; private Group grpHintSwipe; @@ -601,6 +603,7 @@ public class FragmentMessages extends FragmentBase tvNotifications = view.findViewById(R.id.tvNotifications); tvBatteryOptimizations = view.findViewById(R.id.tvBatteryOptimizations); tvDataSaver = view.findViewById(R.id.tvDataSaver); + tvVpnActive = view.findViewById(R.id.tvVpnActive); tvSupport = view.findViewById(R.id.tvSupport); ibHintSupport = view.findViewById(R.id.ibHintSupport); ibHintSwipe = view.findViewById(R.id.ibHintSwipe); @@ -630,6 +633,7 @@ public class FragmentMessages extends FragmentBase grpNotifications = view.findViewById(R.id.grpNotifications); grpBatteryOptimizations = view.findViewById(R.id.grpBatteryOptimizations); grpDataSaver = view.findViewById(R.id.grpDataSaver); + grpVpnActive = view.findViewById(R.id.grpVpnActive); grpSupport = view.findViewById(R.id.grpSupport); grpHintSupport = view.findViewById(R.id.grpHintSupport); grpHintSwipe = view.findViewById(R.id.grpHintSwipe); @@ -715,6 +719,13 @@ public class FragmentMessages extends FragmentBase } }); + tvVpnActive.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + new FragmentDialogVPN().show(getParentFragmentManager(), "vpn"); + } + }); + grpSupport.setVisibility(View.GONE); tvSupport.setOnClickListener(new View.OnClickListener() { @Override @@ -2003,6 +2014,7 @@ public class FragmentMessages extends FragmentBase grpNotifications.setVisibility(View.GONE); grpBatteryOptimizations.setVisibility(View.GONE); grpDataSaver.setVisibility(View.GONE); + grpVpnActive.setVisibility(View.GONE); tvNoEmail.setVisibility(View.GONE); tvNoEmailHint.setVisibility(View.GONE); etSearch.setVisibility(View.GONE); @@ -5646,6 +5658,9 @@ public class FragmentMessages extends FragmentBase ? View.VISIBLE : View.GONE); } + if (grpVpnActive != null && "vpn_reminder".equals(key)) + updateVPN(); + if (grpSupport != null && ("pro".equals(key) || "banner_hidden".equals(key))) { boolean pro = ActivityBilling.isPro(getContext()); @@ -5673,14 +5688,16 @@ public class FragmentMessages extends FragmentBase } private void check() { - getMainHandler().post(new Runnable() { + getMainHandler().post(new RunnableEx("messages:network") { @Override - public void run() { + public void delegate() { if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) return; if (!rvMessage.isComputingLayout()) adapter.checkInternet(); updateAirplaneMode(ConnectionHelper.airplaneMode(getContext())); + + updateVPN(); } }); } @@ -5699,6 +5716,13 @@ public class FragmentMessages extends FragmentBase grpAirplane.setVisibility(on ? View.VISIBLE : View.GONE); } + private void updateVPN() { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + boolean vpn_reminder = prefs.getBoolean("vpn_reminder", true); + grpVpnActive.setVisibility(vpn_reminder && ConnectionHelper.vpnActive(getContext()) + ? View.VISIBLE : View.GONE); + } + private boolean checkRedmiNote() { if (!Helper.isRedmiNote()) return false; diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index 73ed4f8ee0..5974926fde 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -330,7 +330,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc "raw_asked", "all_read_asked", "delete_asked", "cc_bcc", "inline_image_hint", "compose_reference", "send_dialog", "setup_reminder", "was_ignoring", "setup_advanced", - "notifications_reminder", "datasaver_reminder", + "notifications_reminder", "datasaver_reminder", "vpn_reminder", "signature_images_hint", "gmail_checked", "eml_auto_confirm", diff --git a/app/src/main/res/layout/fragment_messages.xml b/app/src/main/res/layout/fragment_messages.xml index 34f71dbcb2..2f8a289a54 100644 --- a/app/src/main/res/layout/fragment_messages.xml +++ b/app/src/main/res/layout/fragment_messages.xml @@ -118,6 +118,32 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvDataSaver" /> + + + + + app:layout_constraintTop_toBottomOf="@+id/vSeparatorVpnActive" /> + + Long press a folder for options, like adding a folder to the navigation menu for quick access To limit battery and network usage not all folders and not all messages will be synchronized by default Airplane mode is on + VPN active No notification permissions Notification permissions are required for (account) alerts too. Notifications for new messages can be turned off in the settings. Battery optimizations still enabled If the data saver is enabled, the app will not be able to sync in the background and connection errors may occur. + E-mail servers often block connections through a VPN. Only the email provider can resolve this. You can dismiss this dialog box to remove the notice. If you have a question or a problem, please use the support menu to get help Swipe left to trash; Swipe right to archive (if available); The swipe actions can be configured in the account settings