From 82612b64f32827fd153a41f4176d58b942541aab Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 2 Apr 2023 10:28:54 +0200 Subject: [PATCH 01/36] Debug info: added browser info --- app/src/main/java/eu/faircode/email/Log.java | 42 ++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Log.java b/app/src/main/java/eu/faircode/email/Log.java index a5651260af..bf7193f387 100644 --- a/app/src/main/java/eu/faircode/email/Log.java +++ b/app/src/main/java/eu/faircode/email/Log.java @@ -19,6 +19,8 @@ package eu.faircode.email; Copyright 2018-2023 by Marcel Bokhorst (M66B) */ +import static androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION; + import android.app.ActivityManager; import android.app.ApplicationExitInfo; import android.app.Dialog; @@ -38,6 +40,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; +import android.content.pm.ResolveInfo; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationUserState; import android.content.res.Configuration; @@ -155,6 +158,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.TimeZone; @@ -2981,6 +2985,7 @@ public class Log { attachment.id = db.attachment().insertAttachment(attachment); long now = new Date().getTime(); + PackageManager pm = context.getPackageManager(); long size = 0; File file = attachment.getFile(context); @@ -3001,8 +3006,7 @@ public class Log { size += write(os, "\r\n"); try { - PackageInfo pi = context.getPackageManager() - .getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_PERMISSIONS); + PackageInfo pi = pm.getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_PERMISSIONS); for (int i = 0; i < pi.requestedPermissions.length; i++) if (pi.requestedPermissions[i] != null && pi.requestedPermissions[i].startsWith("android.permission.")) { @@ -3048,6 +3052,39 @@ public class Log { size += write(os, "\r\n"); + try { + Intent intent = new Intent(Intent.ACTION_VIEW) + .addCategory(Intent.CATEGORY_BROWSABLE) + .setData(Uri.parse("http://example.com/")); + ResolveInfo main = pm.resolveActivity(intent, 0); + + int flags = (Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? 0 : PackageManager.MATCH_ALL); + intent.setData(Uri.parse("http://example.com")); + List browsers = pm.queryIntentActivities(intent, flags); + + for (ResolveInfo ri : browsers) { + Intent serviceIntent = new Intent(); + serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION); + serviceIntent.setPackage(ri.activityInfo.packageName); + CharSequence label = pm.getApplicationLabel(ri.activityInfo.applicationInfo); + boolean tabs = (pm.resolveService(serviceIntent, 0) != null); + boolean def = (main != null && + Objects.equals(ri.activityInfo.packageName, main.activityInfo.packageName)); + size += write(os, String.format("Browser: %s (%s) tabs=%b default=%b\r\n", + ri.activityInfo.packageName, label, tabs, def)); + } + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + String open_with_pkg = prefs.getString("open_with_pkg", null); + boolean open_with_tabs = prefs.getBoolean("open_with_tabs", true); + size += write(os, String.format("Selected: %s tabs=%b\r\n", + open_with_pkg, open_with_tabs)); + + size += write(os, "\r\n"); + } catch (Throwable ex) { + size += write(os, String.format("%s\r\n", ex)); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { try { DomainVerificationManager dvm = Helper.getSystemService(context, DomainVerificationManager.class); @@ -3210,7 +3247,6 @@ public class Log { } try { - PackageManager pm = context.getPackageManager(); List groups = pm.getAllPermissionGroups(0); groups.add(0, null); // Ungrouped From 1aa1305d34e7b395cd1ac5b2414724f38348b28f Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 3 Apr 2023 08:53:47 +0200 Subject: [PATCH 02/36] POP3: keep extra flagged messages --- app/src/main/java/eu/faircode/email/Core.java | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 28fce6e1b0..9c3531ae00 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -3025,9 +3025,33 @@ class Core { } } + // Index IDs + int flagged = 0; + Map uidlTuple = new HashMap<>(); + Map msgIdTuple = new HashMap<>(); + for (TupleUidl id : ids) { + if (id.ui_flagged && !id.ui_hide) + flagged++; + + if (id.uidl != null) { + if (uidlTuple.containsKey(id.uidl)) + Log.w(account.name + " POP duplicate uidl/msgid=" + id.uidl + "/" + id.msgid); + uidlTuple.put(id.uidl, id); + } + + if (id.msgid != null) { + if (msgIdTuple.containsKey(id.msgid)) + Log.w(account.name + " POP duplicate msgid/uidl=" + id.msgid + "/" + id.uidl); + msgIdTuple.put(id.msgid, id); + } + } + + max = Math.min(max + flagged, imessages.length); + EntityLog.log(context, account.name + " POP" + " device=" + ids.size() + " server=" + imessages.length + + " flagged=" + flagged + " max=" + max + "/" + account.max_messages + " reversed=" + reversed + " last=" + folder.last_sync_count + @@ -3035,24 +3059,6 @@ class Core { " uidl=" + hasUidl); if (sync) { - // Index IDs - Map uidlTuple = new HashMap<>(); - for (TupleUidl id : ids) { - if (id.uidl != null) { - if (uidlTuple.containsKey(id.uidl)) - Log.w(account.name + " POP duplicate uidl/msgid=" + id.uidl + "/" + id.msgid); - uidlTuple.put(id.uidl, id); - } - } - - Map msgIdTuple = new HashMap<>(); - for (TupleUidl id : ids) - if (id.msgid != null) { - if (msgIdTuple.containsKey(id.msgid)) - Log.w(account.name + " POP duplicate msgid/uidl=" + id.msgid + "/" + id.uidl); - msgIdTuple.put(id.msgid, id); - } - // Fetch UIDLs if (hasUidl) { FetchProfile ifetch = new FetchProfile(); @@ -3424,8 +3430,8 @@ class Core { } if (account.max_messages != null && !account.leave_on_device) { - int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages)); - int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + 100); + int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages) + flagged); + int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + flagged + 100); EntityLog.log(context, account.name + " POP" + " cleanup max=" + account.max_messages + "" + " hidden=" + hidden + " deleted=" + deleted); From 30204e3c166f79d3f2cc743b1f04509b10cd9c05 Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 3 Apr 2023 08:54:53 +0200 Subject: [PATCH 03/36] POP3: fixed hidding incorrect messages --- app/src/main/java/eu/faircode/email/Core.java | 4 ++-- app/src/main/java/eu/faircode/email/DaoMessage.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 9c3531ae00..43b78ca36c 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -3430,8 +3430,8 @@ class Core { } if (account.max_messages != null && !account.leave_on_device) { - int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages) + flagged); - int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + flagged + 100); + int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages) + flagged, reversed); + int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + flagged + 100, reversed); EntityLog.log(context, account.name + " POP" + " cleanup max=" + account.max_messages + "" + " hidden=" + hidden + " deleted=" + deleted); diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index f56fba03f7..f59c6ff36c 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -792,9 +792,9 @@ public interface DaoMessage { " AND id NOT IN (" + " SELECT id FROM message" + " WHERE folder = :folder" + - " ORDER BY received DESC" + + " ORDER BY CASE WHEN :reversed THEN -received ELSE received END DESC" + " LIMIT :keep)") - int setMessagesUiHide(long folder, int keep); + int setMessagesUiHide(long folder, int keep, boolean reversed); @Transaction @Query("UPDATE message SET ui_ignored = :ui_ignored WHERE id = :id AND NOT (ui_ignored IS :ui_ignored)") @@ -1018,7 +1018,7 @@ public interface DaoMessage { " AND id NOT IN (" + " SELECT id FROM message" + " WHERE folder = :folder" + - " ORDER BY received DESC" + + " ORDER BY CASE WHEN :reversed THEN -received ELSE received END DESC" + " LIMIT :keep)") - int deleteMessagesKeep(long folder, int keep); + int deleteMessagesKeep(long folder, int keep, boolean reversed); } \ No newline at end of file From f6faf0fecca773d424b9ea442bea3ba5ede95c59 Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 3 Apr 2023 11:01:20 +0200 Subject: [PATCH 04/36] Revert "POP3: fixed hidding incorrect messages" This reverts commit 30204e3c166f79d3f2cc743b1f04509b10cd9c05. --- app/src/main/java/eu/faircode/email/Core.java | 4 ++-- app/src/main/java/eu/faircode/email/DaoMessage.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 43b78ca36c..9c3531ae00 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -3430,8 +3430,8 @@ class Core { } if (account.max_messages != null && !account.leave_on_device) { - int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages) + flagged, reversed); - int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + flagged + 100, reversed); + int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages) + flagged); + int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + flagged + 100); EntityLog.log(context, account.name + " POP" + " cleanup max=" + account.max_messages + "" + " hidden=" + hidden + " deleted=" + deleted); diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index f59c6ff36c..f56fba03f7 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -792,9 +792,9 @@ public interface DaoMessage { " AND id NOT IN (" + " SELECT id FROM message" + " WHERE folder = :folder" + - " ORDER BY CASE WHEN :reversed THEN -received ELSE received END DESC" + + " ORDER BY received DESC" + " LIMIT :keep)") - int setMessagesUiHide(long folder, int keep, boolean reversed); + int setMessagesUiHide(long folder, int keep); @Transaction @Query("UPDATE message SET ui_ignored = :ui_ignored WHERE id = :id AND NOT (ui_ignored IS :ui_ignored)") @@ -1018,7 +1018,7 @@ public interface DaoMessage { " AND id NOT IN (" + " SELECT id FROM message" + " WHERE folder = :folder" + - " ORDER BY CASE WHEN :reversed THEN -received ELSE received END DESC" + + " ORDER BY received DESC" + " LIMIT :keep)") - int deleteMessagesKeep(long folder, int keep, boolean reversed); + int deleteMessagesKeep(long folder, int keep); } \ No newline at end of file From 785e7a5ee787805782d60f9936041d16c5ac099d Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 3 Apr 2023 20:45:22 +0200 Subject: [PATCH 05/36] DNS auto discovery: use priority/weight --- .../java/eu/faircode/email/DnsHelper.java | 21 ++- .../java/eu/faircode/email/EmailProvider.java | 121 +++++++++++------- 2 files changed, 93 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/DnsHelper.java b/app/src/main/java/eu/faircode/email/DnsHelper.java index a8685f23a5..a330c48f2d 100644 --- a/app/src/main/java/eu/faircode/email/DnsHelper.java +++ b/app/src/main/java/eu/faircode/email/DnsHelper.java @@ -210,7 +210,7 @@ public class DnsHelper { result.add(new DnsRecord(soa.getHost().toString(true))); } else if (record instanceof SRVRecord) { SRVRecord srv = (SRVRecord) record; - result.add(new DnsRecord(srv.getTarget().toString(true), srv.getPort())); + result.add(new DnsRecord(srv.getTarget().toString(true), srv.getPort(), srv.getPriority(), srv.getWeight())); } else if (record instanceof TXTRecord) { TXTRecord txt = (TXTRecord) record; for (Object content : txt.getStrings()) { @@ -241,6 +241,9 @@ public class DnsHelper { throw new IllegalArgumentException(record.getClass().getName()); } + for (DnsRecord record : result) + record.query = name; + return result.toArray(new DnsRecord[0]); } catch (TextParseException ex) { Log.e(ex); @@ -283,8 +286,11 @@ public class DnsHelper { } static class DnsRecord { + String query; String name; Integer port; + Integer priority; + Integer weight; DnsRecord(String name) { this.name = name; @@ -294,5 +300,18 @@ public class DnsHelper { this.name = name; this.port = port; } + + DnsRecord(String name, int port, int priority, int weight) { + this.name = name; + this.port = port; + this.priority = priority; + this.weight = weight; + } + + @NonNull + @Override + public String toString() { + return query + "=" + name + ":" + port + " " + priority + "/" + weight; + } } } diff --git a/app/src/main/java/eu/faircode/email/EmailProvider.java b/app/src/main/java/eu/faircode/email/EmailProvider.java index 08769a931d..1f39382ea3 100644 --- a/app/src/main/java/eu/faircode/email/EmailProvider.java +++ b/app/src/main/java/eu/faircode/email/EmailProvider.java @@ -857,56 +857,81 @@ public class EmailProvider implements Parcelable { EmailProvider provider = new EmailProvider(domain); if (discover == Discover.ALL || discover == Discover.IMAP) { - try { - // Identifies an IMAP server where TLS is initiated directly upon connection to the IMAP server. - intf.onStatus("SRV imaps " + domain); - DnsHelper.DnsRecord[] records = DnsHelper.lookup(context, "_imaps._tcp." + domain, "srv"); - if (records.length == 0) - throw new UnknownHostException(domain); - // ... service is not supported at all at a particular domain by setting the target of an SRV RR to "." - provider.imap.score = 50; - provider.imap.host = records[0].name; - provider.imap.port = records[0].port; - provider.imap.starttls = false; - EntityLog.log(context, "_imaps._tcp." + domain + "=" + provider.imap); - } catch (UnknownHostException ignored) { - // Identifies an IMAP server that MAY ... require the MUA to use the "STARTTLS" command - intf.onStatus("SRV imap " + domain); - DnsHelper.DnsRecord[] records = DnsHelper.lookup(context, "_imap._tcp." + domain, "srv"); - if (records.length == 0) - throw new UnknownHostException(domain); - provider.imap.score = 50; - provider.imap.host = records[0].name; - provider.imap.port = records[0].port; - provider.imap.starttls = (provider.imap.port == 143); - EntityLog.log(context, "_imap._tcp." + domain + "=" + provider.imap); - } + intf.onStatus("SRV imap " + domain); + + // Identifies an IMAP server where TLS is initiated directly upon connection to the IMAP server. + List list = new ArrayList<>(); + list.addAll(Arrays.asList(DnsHelper.lookup(context, "_imap._tcp." + domain, "srv"))); + list.addAll(Arrays.asList(DnsHelper.lookup(context, "_imaps._tcp." + domain, "srv"))); + + // ... service is not supported at all at a particular domain by setting the target of an SRV RR to "." + for (DnsHelper.DnsRecord record : new ArrayList<>(list)) + if (TextUtils.isEmpty(record.name) || ".".equals(record.name)) + list.remove(record); + + if (list.size() == 0) + throw new UnknownHostException(domain); + + Collections.sort(list, new Comparator() { + @Override + public int compare(DnsHelper.DnsRecord d1, DnsHelper.DnsRecord d2) { + int p = -Integer.compare(d1.priority, d2.priority); + if (p != 0) + return p; + int w = -Integer.compare(d1.weight, d2.weight); + if (w != 0) + return w; + return -Boolean.compare(d1.query.startsWith("_imaps._tcp."), d2.query.startsWith("_imaps._tcp.")); + } + }); + + DnsHelper.DnsRecord pref = list.get(0); + + provider.imap.score = 50; + provider.imap.host = pref.name; + provider.imap.port = pref.port; + provider.imap.starttls = (!pref.query.startsWith("_imaps._tcp.") && pref.port == 143); + EntityLog.log(context, pref.query + "=" + provider.imap); } - if (discover == Discover.ALL || discover == Discover.SMTP) - try { - // Note that this covers connections both with and without Transport Layer Security (TLS) - intf.onStatus("SRV smtp " + domain); - DnsHelper.DnsRecord[] records = DnsHelper.lookup(context, "_submission._tcp." + domain, "srv"); - if (records.length == 0) - throw new UnknownHostException(domain); - provider.smtp.score = 50; - provider.smtp.host = records[0].name; - provider.smtp.port = records[0].port; - provider.smtp.starttls = (provider.smtp.port == 587); - EntityLog.log(context, "_submission._tcp." + domain + "=" + provider.smtp); - } catch (UnknownHostException ignored) { - // https://tools.ietf.org/html/rfc8314 - intf.onStatus("SRV smtps " + domain); - DnsHelper.DnsRecord[] records = DnsHelper.lookup(context, "_submissions._tcp." + domain, "srv"); - if (records.length == 0) - throw new UnknownHostException(domain); - provider.smtp.score = 50; - provider.smtp.host = records[0].name; - provider.smtp.port = records[0].port; - provider.smtp.starttls = false; - EntityLog.log(context, "_submissions._tcp." + domain + "=" + provider.smtp); - } + if (discover == Discover.ALL || discover == Discover.SMTP) { + intf.onStatus("SRV smtp " + domain); + // https://tools.ietf.org/html/rfc8314 + + List list = new ArrayList<>(); + // Note that this covers connections both with and without Transport Layer Security (TLS) + list.addAll(Arrays.asList(DnsHelper.lookup(context, "_submission._tcp." + domain, "srv"))); + list.addAll(Arrays.asList(DnsHelper.lookup(context, "_submissions._tcp." + domain, "srv"))); + + for (DnsHelper.DnsRecord record : new ArrayList<>(list)) + if (TextUtils.isEmpty(record.name) || ".".equals(record.name)) + list.remove(record); + + if (list.size() == 0) + throw new UnknownHostException(domain); + + Collections.sort(list, new Comparator() { + @Override + public int compare(DnsHelper.DnsRecord d1, DnsHelper.DnsRecord d2) { + int p = -Integer.compare(d1.priority, d2.priority); + if (p != 0) + return p; + int w = -Integer.compare(d1.weight, d2.weight); + if (w != 0) + return w; + // submission is being preferred + return -Boolean.compare(d1.query.startsWith("_submission._tcp."), d2.query.startsWith("_submission._tcp.")); + } + }); + + DnsHelper.DnsRecord pref = list.get(0); + + provider.smtp.score = 50; + provider.smtp.host = pref.name; + provider.smtp.port = pref.port; + provider.smtp.starttls = (!pref.query.startsWith("_submissions._tcp.") && pref.port == 587); + EntityLog.log(context, pref.query + "=" + provider.smtp); + } provider.validate(); From 84c0f8c278c216416af4036cb3cb6996d0a6b921 Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 3 Apr 2023 20:48:19 +0200 Subject: [PATCH 06/36] Improved logging --- app/src/main/java/eu/faircode/email/Core.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index 9c3531ae00..e8a9e95c14 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -3433,8 +3433,10 @@ class Core { int hidden = db.message().setMessagesUiHide(folder.id, Math.abs(account.max_messages) + flagged); int deleted = db.message().deleteMessagesKeep(folder.id, Math.abs(account.max_messages) + flagged + 100); EntityLog.log(context, account.name + " POP" + - " cleanup max=" + account.max_messages + "" + - " hidden=" + hidden + " deleted=" + deleted); + " cleanup max=" + account.max_messages + + " flagged=" + flagged + + " hidden=" + hidden + + " deleted=" + deleted); } folder.last_sync_count = imessages.length; From 4e1ac8c86be512c744a0f8b3d8b3b57df26ca5eb Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 3 Apr 2023 21:47:12 +0200 Subject: [PATCH 07/36] Manual setup navigation --- .../eu/faircode/email/FragmentQuickSetup.java | 21 ++++++++++++++++++- .../main/res/layout/fragment_quick_setup.xml | 14 ++++++++++++- app/src/main/res/values/strings.xml | 1 + 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java b/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java index c9bde5bca3..6cf292aa88 100644 --- a/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java +++ b/app/src/main/java/eu/faircode/email/FragmentQuickSetup.java @@ -49,6 +49,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.Group; import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.Lifecycle; import com.google.android.material.textfield.TextInputLayout; @@ -80,6 +81,7 @@ public class FragmentQuickSetup extends FragmentBase { private TextView tvError; private TextView tvErrorHint; + private Button btnManual; private TextView tvInstructions; private Button btnHelp; private Button btnSupport; @@ -148,6 +150,7 @@ public class FragmentQuickSetup extends FragmentBase { tvError = view.findViewById(R.id.tvError); tvErrorHint = view.findViewById(R.id.tvErrorHint); + btnManual = view.findViewById(R.id.btnManual); tvInstructions = view.findViewById(R.id.tvInstructions); btnHelp = view.findViewById(R.id.btnHelp); btnSupport = view.findViewById(R.id.btnSupport); @@ -239,6 +242,18 @@ public class FragmentQuickSetup extends FragmentBase { } }); + btnManual.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentBase fragment = new FragmentAccount(); + fragment.setArguments(new Bundle()); + FragmentTransaction fragmentTransaction = getParentFragmentManager().beginTransaction(); + fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("account"); + fragmentTransaction.commit(); + finish(); + } + }); + btnSupport.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -256,6 +271,7 @@ public class FragmentQuickSetup extends FragmentBase { pbSave.setVisibility(View.GONE); tvInstructions.setVisibility(View.GONE); tvInstructions.setMovementMethod(LinkMovementMethod.getInstance()); + btnManual.setVisibility(View.GONE); btnHelp.setVisibility(View.GONE); cbUpdate.setChecked(update); cbUpdate.setVisibility(View.GONE); @@ -294,6 +310,7 @@ public class FragmentQuickSetup extends FragmentBase { pbSave.setVisibility(check ? View.GONE : View.VISIBLE); grpError.setVisibility(View.GONE); tvInstructions.setVisibility(View.GONE); + btnManual.setVisibility(View.GONE); btnHelp.setVisibility(View.GONE); cbUpdate.setVisibility(check ? View.GONE : View.VISIBLE); btnSave.setVisibility(check ? View.GONE : View.VISIBLE); @@ -679,8 +696,10 @@ public class FragmentQuickSetup extends FragmentBase { if (provider != null && provider.appPassword) message += "\n\n" + getString(R.string.title_setup_app_password_hint); tvErrorHint.setText(message); - } else + } else { tvErrorHint.setText(R.string.title_setup_no_settings_hint); + btnManual.setVisibility(View.VISIBLE); + } if (ex instanceof IllegalArgumentException || ex instanceof UnknownHostException) { tvError.setText(ex.getMessage()); diff --git a/app/src/main/res/layout/fragment_quick_setup.xml b/app/src/main/res/layout/fragment_quick_setup.xml index 78075d5222..7e99bb65a6 100644 --- a/app/src/main/res/layout/fragment_quick_setup.xml +++ b/app/src/main/res/layout/fragment_quick_setup.xml @@ -189,6 +189,18 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvError" /> +