mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 04:53:36 +00:00
[android] Unify custom map server dialog logic and UI
- Add setting icon for custom map server download option. - Extract shared custom map server dialog helper. - Clean up based on reviewers' feedback. Signed-off-by: NoelClick <dev@noel.click>
This commit is contained in:
@@ -13,15 +13,11 @@ import static app.organicmaps.sdk.DownloadResourcesLegacyActivity.nativeStartNex
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
@@ -29,18 +25,16 @@ import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.base.BaseMwmFragmentActivity;
|
||||
import app.organicmaps.dialog.CustomMapServerDialog;
|
||||
import app.organicmaps.downloader.MapManagerHelper;
|
||||
import app.organicmaps.intent.Factory;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
@@ -281,7 +275,11 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
mChbDownloadCountry = findViewById(R.id.chb_download_country);
|
||||
mBtnAdvanced = findViewById(R.id.btn_advanced);
|
||||
|
||||
mBtnAdvanced.setOnClickListener(v -> openCustomServerDialog());
|
||||
mBtnAdvanced.setOnClickListener(v -> {
|
||||
CustomMapServerDialog.show(this, url -> {
|
||||
prepareFilesDownload(false);
|
||||
});
|
||||
});
|
||||
mBtnAdvanced.setEnabled(true);
|
||||
|
||||
mBtnListeners = new View.OnClickListener[BTN_COUNT];
|
||||
@@ -414,56 +412,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void openCustomServerDialog()
|
||||
{
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_custom_map_server, null);
|
||||
TextInputLayout til = dialogView.findViewById(R.id.til_custom_map_server);
|
||||
TextInputEditText edit = dialogView.findViewById(R.id.edit_custom_map_server);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String current = prefs.getString(getString(R.string.pref_custom_map_download_url), "");
|
||||
edit.setText(current);
|
||||
|
||||
MaterialAlertDialogBuilder builder =
|
||||
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
|
||||
.setTitle(R.string.download_resources_custom_url_title)
|
||||
.setMessage(R.string.download_resources_custom_url_message)
|
||||
.setView(dialogView)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.save, null);
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(d -> {
|
||||
Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
ok.setOnClickListener(v -> {
|
||||
String url = edit.getText() != null ? edit.getText().toString().trim() : "";
|
||||
|
||||
if (!url.isEmpty()
|
||||
&& !url.startsWith("http://")
|
||||
&& !url.startsWith("https://")) {
|
||||
til.setError(getString(R.string.download_resources_custom_url_error_scheme));
|
||||
return;
|
||||
}
|
||||
|
||||
til.setError(null);
|
||||
|
||||
prefs.edit()
|
||||
.putString(getString(R.string.pref_custom_map_download_url), url)
|
||||
.apply();
|
||||
|
||||
// Apply to native + reset meta configs
|
||||
Framework.applyCustomMapDownloadUrl(this, url);
|
||||
|
||||
// Recompute total bytes (it can change with another server)
|
||||
prepareFilesDownload(false);
|
||||
|
||||
dialog.dismiss();
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void showErrorDialog(int result)
|
||||
{
|
||||
if (mAlertDialog != null && mAlertDialog.isShowing())
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package app.organicmaps.dialog;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
|
||||
public final class CustomMapServerDialog
|
||||
{
|
||||
public interface OnUrlAppliedListener
|
||||
{
|
||||
void onUrlApplied(@NonNull String url);
|
||||
}
|
||||
|
||||
private CustomMapServerDialog() {}
|
||||
|
||||
public static void show(@NonNull Context context,
|
||||
@Nullable OnUrlAppliedListener listener)
|
||||
{
|
||||
View dialogView = LayoutInflater.from(context)
|
||||
.inflate(R.layout.dialog_custom_map_server, null);
|
||||
TextInputLayout til = dialogView.findViewById(R.id.til_custom_map_server);
|
||||
TextInputEditText edit = dialogView.findViewById(R.id.edit_custom_map_server);
|
||||
|
||||
SharedPreferences prefs =
|
||||
PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String current = prefs.getString(context.getString(R.string.pref_custom_map_download_url), "");
|
||||
edit.setText(current);
|
||||
|
||||
MaterialAlertDialogBuilder builder =
|
||||
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
|
||||
.setTitle(R.string.download_resources_custom_url_title)
|
||||
.setMessage(R.string.download_resources_custom_url_message)
|
||||
.setView(dialogView)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.save, null);
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(dlg -> {
|
||||
Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
ok.setOnClickListener(v -> {
|
||||
String url = edit.getText() != null ? edit.getText().toString().trim() : "";
|
||||
|
||||
if (!url.isEmpty()
|
||||
&& !url.startsWith("http://")
|
||||
&& !url.startsWith("https://"))
|
||||
{
|
||||
til.setError(context.getString(R.string.download_resources_custom_url_error_scheme));
|
||||
return;
|
||||
}
|
||||
|
||||
til.setError(null);
|
||||
|
||||
String normalizedUrl = Framework.normalizeServerUrl(url);
|
||||
|
||||
prefs.edit()
|
||||
.putString(context.getString(R.string.pref_custom_map_download_url), normalizedUrl)
|
||||
.apply();
|
||||
|
||||
// Apply to native
|
||||
Framework.applyCustomMapDownloadUrl(context, normalizedUrl);
|
||||
|
||||
if (listener != null)
|
||||
listener.onUrlApplied(normalizedUrl);
|
||||
|
||||
dialog.dismiss();
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,13 @@ package app.organicmaps.settings;
|
||||
import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
@@ -21,11 +17,10 @@ import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.TwoStatePreference;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.dialog.CustomMapServerDialog;
|
||||
import app.organicmaps.downloader.OnmapDownloader;
|
||||
import app.organicmaps.editor.LanguagesFragment;
|
||||
import app.organicmaps.editor.ProfileActivity;
|
||||
@@ -555,79 +550,25 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
|
||||
String current = prefs.getString(getString(R.string.pref_custom_map_download_url), "");
|
||||
String normalized = current.trim();
|
||||
if (!normalized.isEmpty() && !normalized.endsWith("/"))
|
||||
normalized = normalized + "/";
|
||||
String normalizedUrl = Framework.normalizeServerUrl(current);
|
||||
|
||||
// Initial summary
|
||||
customUrlPref.setSummary(normalized.isEmpty()
|
||||
customUrlPref.setSummary(normalizedUrl.isEmpty()
|
||||
? getString(R.string.download_resources_custom_url_summary_none)
|
||||
: normalized);
|
||||
: normalizedUrl);
|
||||
|
||||
// Sync native
|
||||
Framework.applyCustomMapDownloadUrl(requireContext(), normalized);
|
||||
Framework.applyCustomMapDownloadUrl(requireContext(), normalizedUrl);
|
||||
|
||||
// Show dialog
|
||||
customUrlPref.setOnPreferenceClickListener(preference -> {
|
||||
openCustomServerDialog(customUrlPref);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void openCustomServerDialog(Preference pref)
|
||||
{
|
||||
View dialogView = LayoutInflater.from(requireContext())
|
||||
.inflate(R.layout.dialog_custom_map_server, null);
|
||||
TextInputLayout til = dialogView.findViewById(R.id.til_custom_map_server);
|
||||
TextInputEditText edit = dialogView.findViewById(R.id.edit_custom_map_server);
|
||||
|
||||
SharedPreferences prefs =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
String current = prefs.getString(getString(R.string.pref_custom_map_download_url), "");
|
||||
edit.setText(current);
|
||||
|
||||
MaterialAlertDialogBuilder builder =
|
||||
new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog)
|
||||
.setTitle(R.string.download_resources_custom_url_title)
|
||||
.setMessage(R.string.download_resources_custom_url_message)
|
||||
.setView(dialogView)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.save, null);
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setOnShowListener(dlg -> {
|
||||
Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
ok.setOnClickListener(v -> {
|
||||
String url = edit.getText() != null ? edit.getText().toString().trim() : "";
|
||||
|
||||
if (!url.isEmpty()
|
||||
&& !url.startsWith("http://")
|
||||
&& !url.startsWith("https://")) {
|
||||
til.setError(getString(R.string.download_resources_custom_url_error_scheme));
|
||||
return;
|
||||
}
|
||||
|
||||
til.setError(null);
|
||||
|
||||
if (!url.isEmpty() && !url.endsWith("/"))
|
||||
url = url + "/";
|
||||
|
||||
prefs.edit()
|
||||
.putString(getString(R.string.pref_custom_map_download_url), url)
|
||||
.apply();
|
||||
|
||||
// Apply native
|
||||
Framework.applyCustomMapDownloadUrl(requireContext(), url);
|
||||
|
||||
pref.setSummary(url.isEmpty()
|
||||
CustomMapServerDialog.show(requireContext(), url -> {
|
||||
preference.setSummary(url.isEmpty()
|
||||
? getString(R.string.download_resources_custom_url_summary_none)
|
||||
: url);
|
||||
|
||||
dialog.dismiss();
|
||||
});
|
||||
return true;
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void removePreference(@NonNull String categoryKey, @NonNull Preference preference)
|
||||
|
||||
11
android/app/src/main/res/drawable/ic_cloud_download.xml
Normal file
11
android/app/src/main/res/drawable/ic_cloud_download.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="?colorControlNormal"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="960"
|
||||
android:viewportWidth="960">
|
||||
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M260,800Q169,800 104.5,737Q40,674 40,583Q40,505 87,444Q134,383 210,366Q227,294 295,229Q363,164 440,164Q473,164 496.5,187.5Q520,211 520,244L520,486L584,424L640,480L480,640L320,480L376,424L440,486L440,244Q364,258 322,317.5Q280,377 280,440L260,440Q202,440 161,481Q120,522 120,580Q120,638 161,679Q202,720 260,720L740,720Q782,720 811,691Q840,662 840,620Q840,578 811,549Q782,520 740,520L680,520L680,440Q680,392 658,350.5Q636,309 600,280L600,187Q674,222 717,290.5Q760,359 760,440L760,440L760,440Q829,448 874.5,499.5Q920,551 920,620Q920,695 867.5,747.5Q815,800 740,800L260,800ZM480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442L480,442Q480,442 480,442Q480,442 480,442Z"/>
|
||||
|
||||
</vector>
|
||||
@@ -17,7 +17,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_settings"
|
||||
app:iconTint="?colorOnSurface"
|
||||
app:iconTint="?iconTint"
|
||||
android:contentDescription="@string/download_resources_custom_url_title"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
android:paddingTop="@dimen/margin_base"
|
||||
android:paddingBottom="@dimen/margin_half"
|
||||
android:hint="@string/download_resources_custom_url_title"
|
||||
app:placeholderText="@string/download_resources_custom_url_hint">
|
||||
app:placeholderText="@string/download_resources_custom_url_hint"
|
||||
app:endIconMode="clear_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_custom_map_server"
|
||||
|
||||
@@ -967,13 +967,9 @@
|
||||
<string name="offline_explanation_text">A map needs to be downloaded to view and navigate the area.\nDownload maps for areas you want to travel.</string>
|
||||
<string name="list_description_empty">Edit the list to add a description</string>
|
||||
<!-- Custom Download URL -->
|
||||
<string name="pref_custom_map_download_url_title">Custom Map Server</string>
|
||||
<string name="pref_custom_map_download_url_summary">Override the default map download server used for map downloads. Leave empty to use CoMaps default server.</string>
|
||||
<string name="pref_custom_map_download_url_hint">https://maps.comaps.app/</string>
|
||||
<string name="download_resources_advanced">Advanced…</string>
|
||||
<string name="download_resources_custom_url_title">Custom Map Server</string>
|
||||
<string name="download_resources_custom_url_message">Override the default map download server used for map downloads. Leave empty to use CoMaps default server.</string>
|
||||
<string name="download_resources_custom_url_hint">https://maps.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_hint">https://cdn-fi-1.comaps.app/</string>
|
||||
<string name="download_resources_custom_url_summary_none">Not set</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Please enter a full URL starting with http:// or https:// and ending with /.</string>
|
||||
<string name="download_resources_custom_url_error_scheme">Please enter a full URL starting with https:// and ending with /</string>
|
||||
</resources>
|
||||
|
||||
@@ -214,8 +214,8 @@
|
||||
android:order="2"/>
|
||||
<Preference
|
||||
android:key="@string/pref_custom_map_download_url"
|
||||
android:title="@string/pref_custom_map_download_url_title"
|
||||
android:summary="@string/pref_custom_map_download_url_summary"
|
||||
android:title="@string/download_resources_custom_url_title"
|
||||
app:icon="@drawable/ic_cloud_download"
|
||||
android:order="3" />
|
||||
|
||||
</androidx.preference.PreferenceCategory>
|
||||
|
||||
@@ -124,6 +124,7 @@ dependencies {
|
||||
implementation libs.androidx.lifecycle.process
|
||||
implementation libs.androidx.media
|
||||
implementation libs.androidx.recyclerview
|
||||
implementation libs.androidx.preference
|
||||
implementation libs.android.material
|
||||
|
||||
testImplementation libs.junit
|
||||
|
||||
@@ -42,16 +42,16 @@ using namespace std::placeholders;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unique_ptr<MapFilesDownloader> & LegacyDownloader()
|
||||
{
|
||||
static auto downloader = storage::GetDownloader();
|
||||
return downloader;
|
||||
}
|
||||
std::unique_ptr<MapFilesDownloader> & LegacyDownloader()
|
||||
{
|
||||
static auto downloader = storage::GetDownloader();
|
||||
return downloader;
|
||||
}
|
||||
|
||||
static std::vector<platform::CountryFile> g_filesToDownload;
|
||||
static int g_totalDownloadedBytes;
|
||||
static int g_totalBytesToDownload;
|
||||
static std::shared_ptr<HttpRequest> g_currentRequest;
|
||||
static std::vector<platform::CountryFile> g_filesToDownload;
|
||||
static int g_totalDownloadedBytes;
|
||||
static int g_totalBytesToDownload;
|
||||
static std::shared_ptr<HttpRequest> g_currentRequest;
|
||||
} // namespace
|
||||
|
||||
extern "C"
|
||||
|
||||
@@ -356,14 +356,16 @@ public class Framework
|
||||
|
||||
public static void applyCustomMapDownloadUrl(@NonNull Context context, @Nullable String url)
|
||||
{
|
||||
String normalizedUrl = url != null ? url.trim() : "";
|
||||
|
||||
// Normalize
|
||||
if (!normalizedUrl.isEmpty() && !normalizedUrl.endsWith("/"))
|
||||
normalizedUrl = normalizedUrl + "/";
|
||||
|
||||
nativeSetCustomMapDownloadUrl(normalizedUrl);
|
||||
nativeSetCustomMapDownloadUrl(normalizeServerUrl(url));
|
||||
// Reset the legacy downloader too (world/coasts).
|
||||
app.organicmaps.sdk.DownloadResourcesLegacyActivity.nativeResetMetaConfig();
|
||||
}
|
||||
|
||||
public static String normalizeServerUrl(@Nullable String url)
|
||||
{
|
||||
String out = url != null ? url.trim() : "";
|
||||
if (!out.isEmpty() && !out.endsWith("/"))
|
||||
out = out + "/";
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ package app.organicmaps.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.sdk.bookmarks.data.Icon;
|
||||
import app.organicmaps.sdk.downloader.Android7RootCertificateWorkaround;
|
||||
@@ -27,6 +28,7 @@ import app.organicmaps.sdk.util.SharedPropertiesUtils;
|
||||
import app.organicmaps.sdk.util.StorageUtils;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
import app.organicmaps.sdk.util.log.LogsManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class OrganicMaps implements DefaultLifecycleObserver
|
||||
|
||||
Reference in New Issue
Block a user