Merge remote-tracking branch 'origin/master' into slope_hillshade_ui

# Conflicts:
#	OsmAnd/res/values/strings.xml
This commit is contained in:
veliymolfar 2020-03-06 11:55:42 +02:00
commit ca9e8eea2c
14 changed files with 415 additions and 172 deletions

View file

@ -11,6 +11,10 @@
Thx - Hardy
-->
<string name="restore_all_profile_settings_descr">All profile settings will be restored to their original state after creating/importing this profile.</string>
<string name="restore_all_profile_settings">Restore all profile settings?</string>
<string name="saving_new_profile">Saving new profile</string>
<string name="profile_backup_failed">Could not back up profile.</string>
<string name="shared_string_hillshade">Hillshade</string>
<string name="terrain_empty_state_text">Turn on to view the layer with shading relief or a map of the slope of the slopes. \n\nYou can find out why such cards are needed and how they work on our website</string>
<string name="shared_string_legend">Legend</string>

View file

@ -163,6 +163,13 @@ public class AndroidUtils {
return intent.resolveActivity(context.getPackageManager()) != null;
}
public static boolean isActivityNotDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= 17) {
return !activity.isFinishing() && !activity.isDestroyed();
}
return !activity.isFinishing();
}
public static Spannable replaceCharsWithIcon(String text, Drawable icon, String[] chars) {
Spannable spannable = new SpannableString(text);
for (String entry : chars) {

View file

@ -2,7 +2,6 @@ package net.osmand.plus;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
@ -103,6 +102,7 @@ public class SettingsHelper {
private boolean importSuspended;
private boolean collectOnly;
private ImportAsyncTask importTask;
private Map<File, ExportAsyncTask> exportAsyncTasks = new HashMap<>();
public interface SettingsImportListener {
void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List<SettingsItem> items);
@ -1805,7 +1805,6 @@ public class SettingsHelper {
private File file;
private String latestChanges;
private boolean askBeforeImport;
private int version;
private SettingsImportListener listener;
@ -1815,13 +1814,11 @@ public class SettingsHelper {
private SettingsItem currentItem;
private AlertDialog dialog;
ImportAsyncTask(@NonNull File settingsFile, String latestChanges, int version, boolean askBeforeImport,
@Nullable SettingsImportListener listener) {
ImportAsyncTask(@NonNull File settingsFile, String latestChanges, int version, @Nullable SettingsImportListener listener) {
this.file = settingsFile;
this.listener = listener;
this.latestChanges = latestChanges;
this.version = version;
this.askBeforeImport = askBeforeImport;
importer = new SettingsImporter(app);
collectOnly = true;
}
@ -1869,12 +1866,10 @@ public class SettingsHelper {
}
if (collectOnly) {
listener.onSettingsImportFinished(true, false, this.items);
} else {
if (items != null && items.size() > 0) {
} else if (items != null && items.size() > 0) {
processNextItem();
}
}
}
private void processNextItem() {
if (activity == null) {
@ -1937,6 +1932,17 @@ public class SettingsHelper {
return this.importTask.getFile();
}
public boolean isFileExporting(File file) {
return exportAsyncTasks.containsKey(file);
}
public void updateExportListener(File file, SettingsExportListener listener) {
ExportAsyncTask exportAsyncTask = exportAsyncTasks.get(file);
if (exportAsyncTask != null) {
exportAsyncTask.listener = listener;
}
}
@SuppressLint("StaticFieldLeak")
private class ImportItemsAsyncTask extends AsyncTask<Void, Void, Boolean> {
@ -1988,7 +1994,6 @@ public class SettingsHelper {
private SettingsExporter exporter;
private File file;
private SettingsExportListener listener;
private ProgressDialog progress;
ExportAsyncTask(@NonNull File settingsFile,
@Nullable SettingsExportListener listener,
@ -2001,14 +2006,6 @@ public class SettingsHelper {
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
if (activity != null) {
progress = ProgressDialog.show(activity, app.getString(R.string.export_profile), app.getString(R.string.shared_string_preparing));
}
}
@Override
protected Boolean doInBackground(Void... voids) {
try {
@ -2024,29 +2021,26 @@ public class SettingsHelper {
@Override
protected void onPostExecute(Boolean success) {
if (activity != null) {
progress.dismiss();
exportAsyncTasks.remove(file);
if (listener != null) {
listener.onSettingsExportFinished(file, success);
}
}
}
}
public void importSettings(@NonNull File settingsFile, String latestChanges, int version,
boolean askBeforeImport, @Nullable SettingsImportListener listener) {
new ImportAsyncTask(settingsFile, latestChanges, version, askBeforeImport, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
public void importSettings(@NonNull File settingsFile, String latestChanges, int version, @Nullable SettingsImportListener listener) {
new ImportAsyncTask(settingsFile, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void importSettings(@NonNull File settingsFile, @NonNull List<SettingsItem> items, String latestChanges, int version, @Nullable SettingsImportListener listener) {
new ImportAsyncTask(settingsFile, items, latestChanges, version, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void exportSettings(@NonNull File fileDir, @NonNull String fileName,
@Nullable SettingsExportListener listener,
@NonNull List<SettingsItem> items) {
new ExportAsyncTask(new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT), listener, items)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener, @NonNull List<SettingsItem> items) {
File file = new File(fileDir, fileName + OSMAND_SETTINGS_FILE_EXT);
ExportAsyncTask exportAsyncTask = new ExportAsyncTask(file, listener, items);
exportAsyncTasks.put(file, exportAsyncTask);
exportAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void exportSettings(@NonNull File fileDir, @NonNull String fileName, @Nullable SettingsExportListener listener,

View file

@ -192,7 +192,7 @@ public class ImportHelper {
} else if (fileName != null && fileName.endsWith(IndexConstants.SQLITE_EXT)) {
handleSqliteTileImport(intentUri, fileName);
} else if (fileName != null && fileName.endsWith(OSMAND_SETTINGS_FILE_EXT)) {
handleOsmAndSettingsImport(intentUri, fileName, extras, true, null);
handleOsmAndSettingsImport(intentUri, fileName, extras, null);
} else if (fileName != null && fileName.endsWith(ROUTING_AND_RENDERING_FILE_EXT)) {
handleXmlFileImport(intentUri, fileName);
} else {
@ -252,7 +252,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
handleResult(result, fileName, save, useImportDir, false);
@ -324,7 +324,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(final GPXFile result) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
@ -362,7 +362,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
Toast.makeText(activity, R.string.fav_imported_sucessfully, Toast.LENGTH_LONG)
@ -435,7 +435,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
handleResult(result, name, save, useImportDir, false);
@ -483,7 +483,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(GPXFile result) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
handleResult(result, name, save, useImportDir, false);
@ -515,7 +515,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(String message) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
Toast.makeText(app, message, Toast.LENGTH_SHORT).show();
@ -596,7 +596,7 @@ public class ImportHelper {
@Override
protected void onPostExecute(String error) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
if (error == null) {
@ -616,7 +616,7 @@ public class ImportHelper {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void chooseFileToImport(final ImportType importType, final boolean askBeforeImport, final CallbackWithObject callback) {
public void chooseFileToImport(final ImportType importType, final CallbackWithObject callback) {
final MapActivity mapActivity = getMapActivity();
if (mapActivity == null) {
return;
@ -654,7 +654,7 @@ public class ImportHelper {
if (fileName.endsWith(importType.getExtension())) {
if (importType.equals(ImportType.SETTINGS)) {
handleOsmAndSettingsImport(data, fileName, resultData.getExtras(), askBeforeImport, callback);
handleOsmAndSettingsImport(data, fileName, resultData.getExtras(), callback);
} else if (importType.equals(ImportType.ROUTING)){
handleRoutingFileImport(data, fileName, callback);
}
@ -705,7 +705,7 @@ public class ImportHelper {
loadRoutingFiles(app, new AppInitializer.LoadRoutingFilesCallback() {
@Override
public void onRoutingFilesLoaded() {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
RoutingConfiguration.Builder builder = app.getCustomRoutingConfig(mFileName);
@ -720,7 +720,7 @@ public class ImportHelper {
}
});
} else {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
app.showShortToastMessage(app.getString(R.string.file_import_error, mFileName, error));
@ -743,19 +743,19 @@ public class ImportHelper {
}
}
private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras, boolean askBeforeImport, CallbackWithObject<List<SettingsHelper.SettingsItem>> callback) {
private void handleOsmAndSettingsImport(Uri intentUri, String fileName, Bundle extras, CallbackWithObject<List<SettingsHelper.SettingsItem>> callback) {
if (extras != null && extras.containsKey(SettingsHelper.SETTINGS_VERSION_KEY) && extras.containsKey(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY)) {
int version = extras.getInt(SettingsHelper.SETTINGS_VERSION_KEY, -1);
String latestChanges = extras.getString(SettingsHelper.SETTINGS_LATEST_CHANGES_KEY);
handleOsmAndSettingsImport(intentUri, fileName, latestChanges, version, askBeforeImport, callback);
handleOsmAndSettingsImport(intentUri, fileName, latestChanges, version, callback);
} else {
handleOsmAndSettingsImport(intentUri, fileName, null, -1, askBeforeImport, callback);
handleOsmAndSettingsImport(intentUri, fileName, null, -1, callback);
}
}
@SuppressLint("StaticFieldLeak")
private void handleOsmAndSettingsImport(final Uri uri, final String name, final String latestChanges, final int version,
final boolean askBeforeImport, final CallbackWithObject<List<SettingsHelper.SettingsItem>> callback) {
final CallbackWithObject<List<SettingsHelper.SettingsItem>> callback) {
final AsyncTask<Void, Void, String> settingsImportTask = new AsyncTask<Void, Void, String>() {
ProgressDialog progress;
@ -780,10 +780,10 @@ public class ImportHelper {
File tempDir = app.getAppPath(IndexConstants.TEMP_DIR);
final File file = new File(tempDir, name);
if (error == null && file.exists()) {
app.getSettingsHelper().importSettings(file, latestChanges, version, askBeforeImport, new SettingsImportListener() {
app.getSettingsHelper().importSettings(file, latestChanges, version, new SettingsImportListener() {
@Override
public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List<SettingsHelper.SettingsItem> items) {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
if (succeed) {
@ -797,7 +797,7 @@ public class ImportHelper {
}
});
} else {
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
app.showShortToastMessage(app.getString(R.string.file_import_error, name, error));
@ -820,13 +820,6 @@ public class ImportHelper {
}
}
private boolean isActivityNotDestroyed(Activity activity) {
if (Build.VERSION.SDK_INT >= 17) {
return !activity.isFinishing() && !activity.isDestroyed();
}
return !activity.isFinishing();
}
private void handleXmlFileImport(final Uri intentUri, final String fileName) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@ -923,7 +916,7 @@ public class ImportHelper {
} else {
app.showShortToastMessage(app.getString(R.string.file_import_error, mFileName, error));
}
if (isActivityNotDestroyed(activity)) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
}

View file

@ -12,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.data.LatLon;
@ -204,8 +205,11 @@ public class DestinationReachedMenuFragment extends Fragment {
public void dismissMenu() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null && !mapActivity.isActivityDestroyed()) {
mapActivity.getSupportFragmentManager().popBackStack();
if (mapActivity != null) {
FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
if (!fragmentManager.isStateSaved()) {
fragmentManager.popBackStack();
}
}
}

View file

@ -18,6 +18,7 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.github.ksoichiro.android.observablescrollview.ObservableListView;
import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
@ -252,7 +253,10 @@ public class MapMultiSelectionMenuFragment extends Fragment implements MultiSele
if (menu.getMapActivity().getContextMenu().isVisible()) {
menu.getMapActivity().getContextMenu().hide();
} else {
menu.getMapActivity().getSupportFragmentManager().popBackStack();
FragmentManager fragmentManager = menu.getMapActivity().getSupportFragmentManager();
if (!fragmentManager.isStateSaved()) {
fragmentManager.popBackStack();
}
}
}
}

View file

@ -161,8 +161,7 @@ public class SelectProfileBottomSheetDialogFragment extends BasePreferenceBottom
if (mapActivity == null) {
return;
}
mapActivity.getImportHelper().chooseFileToImport(ROUTING, false,
new CallbackWithObject<RoutingConfiguration.Builder>() {
mapActivity.getImportHelper().chooseFileToImport(ROUTING, new CallbackWithObject<RoutingConfiguration.Builder>() {
@Override
public boolean processResult(RoutingConfiguration.Builder builder) {
refreshView();

View file

@ -1,5 +1,6 @@
package net.osmand.plus.search;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
@ -171,8 +172,9 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
public void onDismiss(DialogInterface dialog) {
if (editMode) {
QuickSearchDialogFragment quickSearchDialogFragment = getQuickSearchDialogFragment();
if (quickSearchDialogFragment != null) {
getMyApplication().getSearchUICore().refreshCustomPoiFilters();
OsmandApplication app = getMyApplication();
if (app != null && quickSearchDialogFragment != null) {
app.getSearchUICore().refreshCustomPoiFilters();
quickSearchDialogFragment.replaceQueryWithUiFilter(filter, "");
quickSearchDialogFragment.reloadCategories();
}
@ -314,25 +316,16 @@ public class QuickSearchCustomPoiFragment extends DialogFragment {
}
}
@SuppressLint("SetTextI18n")
private void saveFilter() {
helper.editPoiFilter(filter);
if (!editMode) {
Context ctx = getContext();
if (ctx != null) {
if (filter.isEmpty()) {
bottomBarShadow.setVisibility(View.GONE);
bottomBar.setVisibility(View.GONE);
} else {
barTitle.setText(getContext().getString(R.string.selected_categories) + ": " + filter
.getAcceptedTypesCount());
bottomBarShadow.setVisibility(View.VISIBLE);
bottomBar.setVisibility(View.VISIBLE);
}
} else {
if (filter.isEmpty()) {
bottomBarShadow.setVisibility(View.GONE);
bottomBar.setVisibility(View.GONE);
} else {
barTitle.setText(getContext().getString(R.string.selected_categories) + ": " + filter
.getAcceptedTypesCount());
barTitle.setText(ctx.getString(R.string.selected_categories) + ": " + filter.getAcceptedTypesCount());
bottomBarShadow.setVisibility(View.VISIBLE);
bottomBar.setVisibility(View.VISIBLE);
}

View file

@ -29,11 +29,13 @@ import androidx.preference.PreferenceGroupAdapter;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.SettingsHelper;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
@ -166,11 +168,42 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
@Override
public void resetAppModePrefs(ApplicationMode appMode) {
if (appMode != null) {
if (appMode.isCustomProfile()) {
File file = getBackupFileForCustomMode(app, appMode.getStringKey());
if (file.exists()) {
restoreCustomModeFromFile(file);
}
} else {
app.getSettings().resetPreferencesForProfile(appMode);
app.showToastMessage(R.string.profile_prefs_reset_successful);
updateCopiedOrResetPrefs();
}
}
}
private void restoreCustomModeFromFile(final File file) {
app.getSettingsHelper().importSettings(file, "", 1, new SettingsHelper.SettingsImportListener() {
@Override
public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List<SettingsHelper.SettingsItem> items) {
if (succeed) {
for (SettingsHelper.SettingsItem item : items) {
item.setShouldReplace(true);
}
importBackupSettingsItems(file, items);
}
}
});
}
private void importBackupSettingsItems(File file, List<SettingsHelper.SettingsItem> items) {
app.getSettingsHelper().importSettings(file, items, "", 1, new SettingsHelper.SettingsImportListener() {
@Override
public void onSettingsImportFinished(boolean succeed, boolean empty, @NonNull List<SettingsHelper.SettingsItem> items) {
app.showToastMessage(R.string.profile_prefs_reset_successful);
updateCopiedOrResetPrefs();
}
});
}
private void updateCopiedOrResetPrefs() {
MapActivity mapActivity = getMapActivity();
@ -304,7 +337,8 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
private void setupResetToDefaultPref() {
Preference resetToDefault = findPreference(RESET_TO_DEFAULT);
if (getSelectedAppMode().isCustomProfile()) {
ApplicationMode mode = getSelectedAppMode();
if (mode.isCustomProfile() && !getBackupFileForCustomMode(app, mode.getStringKey()).exists()) {
resetToDefault.setVisible(false);
} else {
resetToDefault.setIcon(app.getUIUtilities().getIcon(R.drawable.ic_action_reset_to_default_dark,
@ -324,22 +358,6 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
isNightMode() ? R.color.active_color_primary_dark : R.color.active_color_primary_light));
}
private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) {
try {
Context ctx = requireContext();
final Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.exported_osmand_profile, profile.toHumanString()));
sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file));
sendIntent.setType("*/*");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(sendIntent);
} catch (Exception e) {
app.showToastMessage(R.string.export_profile_failed);
LOG.error("Share profile error", e);
}
}
private void setupOsmandPluginsPref(PreferenceCategory preferenceCategory) {
Context ctx = getContext();
if (ctx == null) {
@ -443,4 +461,14 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
}
}
}
public static File getBackupFileForCustomMode(OsmandApplication app, String appModeKey) {
String fileName = appModeKey + IndexConstants.OSMAND_SETTINGS_FILE_EXT;
File backupDir = app.getAppPath(IndexConstants.BACKUP_INDEX_DIR);
if (!backupDir.exists()) {
backupDir.mkdirs();
}
return new File(backupDir, fileName);
}
}

View file

@ -1,5 +1,6 @@
package net.osmand.plus.settings;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
@ -16,6 +17,7 @@ import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
@ -52,29 +54,41 @@ import java.util.Set;
public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
private static final Log LOG = PlatformUtil.getLog(ExportProfileBottomSheet.class);
public static final String TAG = ExportProfileBottomSheet.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(ExportProfileBottomSheet.class);
private static final String INCLUDE_ADDITIONAL_DATA_KEY = "INCLUDE_ADDITIONAL_DATA_KEY";
private boolean includeAdditionalData = false;
private static final String EXPORTING_PROFILE_KEY = "exporting_profile_key";
private OsmandApplication app;
private ApplicationMode profile;
private List<AdditionalDataWrapper> dataList = new ArrayList<>();
private ExportImportSettingsAdapter adapter;
private SettingsHelper.SettingsExportListener exportListener;
private ProgressDialog progress;
private boolean includeAdditionalData = false;
private boolean exportingProfile = false;
@Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY);
}
super.onCreate(savedInstanceState);
app = requiredMyApplication();
profile = getAppMode();
dataList = getAdditionalData();
if (savedInstanceState != null) {
includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY);
exportingProfile = savedInstanceState.getBoolean(EXPORTING_PROFILE_KEY);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData);
outState.putBoolean(EXPORTING_PROFILE_KEY, exportingProfile);
}
@Override
@ -85,8 +99,6 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
}
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
profile = getAppMode();
int profileColor = profile.getIconColorInfo().getColor(nightMode);
int colorNoAlpha = ContextCompat.getColor(context, profileColor);
@ -187,6 +199,21 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
return true;
}
@Override
public void onResume() {
super.onResume();
checkExportingFile();
}
@Override
public void onPause() {
super.onPause();
if (exportingProfile) {
File file = getExportFile();
app.getSettingsHelper().updateExportListener(file, null);
}
}
private List<AdditionalDataWrapper> getAdditionalData() {
List<AdditionalDataWrapper> dataList = new ArrayList<>();
@ -303,22 +330,81 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
private void prepareFile() {
if (app != null) {
File tempDir = app.getAppPath(IndexConstants.TEMP_DIR);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
exportingProfile = true;
showExportProgressDialog();
File tempDir = getTempDir();
String fileName = profile.toHumanString();
app.getSettingsHelper().exportSettings(tempDir, fileName, new SettingsHelper.SettingsExportListener() {
app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), prepareSettingsItemsForExport());
}
}
private void showExportProgressDialog() {
Context context = getContext();
if (context == null) {
return;
}
if (progress != null) {
progress.dismiss();
}
progress = new ProgressDialog(context);
progress.setTitle(app.getString(R.string.export_profile));
progress.setMessage(app.getString(R.string.shared_string_preparing));
progress.setCancelable(false);
progress.show();
}
private SettingsHelper.SettingsExportListener getSettingsExportListener() {
if (exportListener == null) {
exportListener = new SettingsHelper.SettingsExportListener() {
@Override
public void onSettingsExportFinished(@NonNull File file, boolean succeed) {
dismissExportProgressDialog();
exportingProfile = false;
if (succeed) {
shareProfile(file, profile);
} else {
app.showToastMessage(R.string.export_profile_failed);
}
}
}, prepareSettingsItemsForExport());
};
}
return exportListener;
}
private void checkExportingFile() {
if (exportingProfile) {
File file = getExportFile();
boolean fileExporting = app.getSettingsHelper().isFileExporting(file);
if (fileExporting) {
showExportProgressDialog();
app.getSettingsHelper().updateExportListener(file, getSettingsExportListener());
} else if (file.exists()) {
dismissExportProgressDialog();
shareProfile(file, profile);
}
}
}
private void dismissExportProgressDialog() {
FragmentActivity activity = getActivity();
if (progress != null && activity != null && AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
}
private File getExportFile() {
File tempDir = getTempDir();
String fileName = profile.toHumanString();
return new File(tempDir, fileName + IndexConstants.OSMAND_SETTINGS_FILE_EXT);
}
private File getTempDir() {
File tempDir = app.getAppPath(IndexConstants.TEMP_DIR);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
return tempDir;
}
private void shareProfile(@NonNull File file, @NonNull ApplicationMode profile) {

View file

@ -129,7 +129,7 @@ public class MainSettingsFragment extends BaseSettingsFragment {
} else if (IMPORT_PROFILE.equals(prefId)) {
final MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.getImportHelper().chooseFileToImport(SETTINGS, false, new CallbackWithObject<List<SettingsItem>>() {
mapActivity.getImportHelper().chooseFileToImport(SETTINGS, new CallbackWithObject<List<SettingsItem>>() {
@Override
public boolean processResult(List<SettingsItem> result) {

View file

@ -2,6 +2,7 @@ package net.osmand.plus.settings;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Matrix;
@ -22,19 +23,23 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import net.osmand.AndroidUtils;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.R;
import net.osmand.plus.SettingsHelper;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.profiles.LocationIcon;
@ -49,6 +54,7 @@ import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
@ -64,6 +70,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
private static final Log LOG = PlatformUtil.getLog(ProfileAppearanceFragment.class);
public static final String TAG = ProfileAppearanceFragment.class.getName();
private static final String MASTER_PROFILE = "master_profile";
private static final String PROFILE_NAME = "profile_name";
private static final String SELECT_COLOR = "select_color";
@ -75,16 +82,22 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
private static final String SELECT_NAV_ICON = "select_nav_icon";
private static final String NAV_ICON_ITEMS = "nav_icon_items";
public static final String PROFILE_NAME_KEY = "profile_name_key";
public static final String PROFILE_STRINGKEY_KEY = "profile_stringkey_key";
public static final String PROFILE_ICON_RES_KEY = "profile_icon_res_key";
public static final String PROFILE_COLOR_KEY = "profile_color_key";
public static final String PROFILE_PARENT_KEY = "profile_parent_key";
public static final String PROFILE_LOCATION_ICON_KEY = "profile_location_icon_key";
public static final String PROFILE_NAVIGATION_ICON_KEY = "profile_navigation_icon_key";
public static final String BASE_PROFILE_FOR_NEW = "base_profile_for_new";
public static final String IS_BASE_PROFILE_IMPORTED = "is_base_profile_imported";
private static final String PROFILE_NAME_KEY = "profile_name_key";
private static final String PROFILE_STRINGKEY_KEY = "profile_stringkey_key";
private static final String PROFILE_ICON_RES_KEY = "profile_icon_res_key";
private static final String PROFILE_COLOR_KEY = "profile_color_key";
private static final String PROFILE_PARENT_KEY = "profile_parent_key";
private static final String PROFILE_LOCATION_ICON_KEY = "profile_location_icon_key";
private static final String PROFILE_NAVIGATION_ICON_KEY = "profile_navigation_icon_key";
private static final String BASE_PROFILE_FOR_NEW = "base_profile_for_new";
private static final String IS_BASE_PROFILE_IMPORTED = "is_base_profile_imported";
private static final String IS_NEW_PROFILE_KEY = "is_new_profile_key";
private SelectProfileBottomSheetDialogFragment.SelectProfileListener parentProfileListener;
private SettingsHelper.SettingsExportListener exportListener;
private ProgressDialog progress;
private EditText baseProfileName;
private ApplicationProfileObject profile;
private ApplicationProfileObject changedProfile;
@ -134,9 +147,9 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
changedProfile.routeService = profile.routeService;
changedProfile.locationIcon = profile.locationIcon;
changedProfile.navigationIcon = profile.navigationIcon;
}
isNewProfile = ApplicationMode.valueOfStringKey(changedProfile.stringKey, null) == null;
}
}
public void setupAppProfileObjectFromAppMode(ApplicationMode baseModeForNewProfile) {
profile.stringKey = baseModeForNewProfile.getStringKey();
@ -242,17 +255,8 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
public void onClick(View v) {
if (getActivity() != null) {
hideKeyboard();
if (isChanged()) {
if (saveProfile()) {
profile = changedProfile;
if (isNewProfile) {
ProfileAppearanceFragment.this.dismiss();
BaseSettingsFragment.showInstance(getMapActivity(), SettingsScreenType.CONFIGURE_PROFILE,
ApplicationMode.valueOfStringKey(changedProfile.stringKey, null));
} else {
getActivity().onBackPressed();
}
}
if (isChanged() && checkProfileName()) {
saveProfile();
}
}
}
@ -279,6 +283,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
if (changedProfile.parent != null) {
outState.putString(PROFILE_PARENT_KEY, changedProfile.parent.getStringKey());
}
outState.putBoolean(IS_NEW_PROFILE_KEY, isNewProfile);
outState.putBoolean(IS_BASE_PROFILE_IMPORTED, isBaseProfileImported);
outState.putSerializable(PROFILE_LOCATION_ICON_KEY, changedProfile.locationIcon);
outState.putSerializable(PROFILE_NAVIGATION_ICON_KEY, changedProfile.navigationIcon);
@ -294,6 +299,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
isBaseProfileImported = savedInstanceState.getBoolean(IS_BASE_PROFILE_IMPORTED);
changedProfile.locationIcon = (LocationIcon) savedInstanceState.getSerializable(PROFILE_LOCATION_ICON_KEY);
changedProfile.navigationIcon = (NavigationIcon) savedInstanceState.getSerializable(PROFILE_NAVIGATION_ICON_KEY);
isNewProfile = savedInstanceState.getBoolean(IS_NEW_PROFILE_KEY);
}
@Override
@ -416,6 +422,24 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
}
}
@Override
public void onResume() {
super.onResume();
checkSavingProfile();
}
@Override
public void onPause() {
super.onPause();
if (isNewProfile) {
File file = ConfigureProfileFragment.getBackupFileForCustomMode(app, changedProfile.stringKey);
boolean fileExporting = app.getSettingsHelper().isFileExporting(file);
if (fileExporting) {
app.getSettingsHelper().updateExportListener(file, null);
}
}
}
private View createColorItemView(final ProfileIconColors colorRes, ViewGroup rootView) {
FrameLayout colorItemView = (FrameLayout) UiUtilities.getInflater(getContext(), isNightMode())
.inflate(R.layout.preference_circle_item, rootView, false);
@ -639,7 +663,25 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
return parentProfileListener;
}
void updateParentProfile(String profileKey, boolean isBaseProfileImported) {
private SettingsHelper.SettingsExportListener getSettingsExportListener() {
if (exportListener == null) {
exportListener = new SettingsHelper.SettingsExportListener() {
@Override
public void onSettingsExportFinished(@NonNull File file, boolean succeed) {
dismissProfileSavingDialog();
if (succeed) {
customProfileSaved();
} else {
app.showToastMessage(R.string.profile_backup_failed);
}
}
};
}
return exportListener;
}
private void updateParentProfile(String profileKey, boolean isBaseProfileImported) {
deleteImportedProfile();
setupBaseProfileView(profileKey);
changedProfile.parent = ApplicationMode.valueOfStringKey(profileKey, ApplicationMode.DEFAULT);
@ -653,16 +695,55 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
baseProfileName.setText(Algorithms.capitalizeFirstLetter(mode.toHumanString()));
}
private boolean saveProfile() {
if (changedProfile.name.trim().isEmpty()) {
if (getActivity() != null) {
createWarningDialog(getActivity(),
R.string.profile_alert_need_profile_name_title, R.string.profile_alert_need_profile_name_msg, R.string.shared_string_dismiss).show();
private boolean checkProfileName() {
if (Algorithms.isBlank(changedProfile.name)) {
Activity activity = getActivity();
if (activity != null) {
createWarningDialog(activity, R.string.profile_alert_need_profile_name_title,
R.string.profile_alert_need_profile_name_msg, R.string.shared_string_dismiss).show();
}
return false;
}
return true;
}
private void saveProfile() {
if (isNewProfile) {
DialogInterface.OnShowListener showListener = new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
ApplicationMode mode = saveNewProfile();
saveProfileBackup(mode);
}
});
}
};
showNewProfileSavingDialog(showListener);
} else {
ApplicationMode mode = getSelectedAppMode();
mode.setParentAppMode(changedProfile.parent);
mode.setIconResName(ProfileIcons.getResStringByResId(changedProfile.iconRes));
mode.setUserProfileName(changedProfile.name.trim());
mode.setRoutingProfile(changedProfile.routingProfile);
mode.setRouteService(changedProfile.routeService);
mode.setIconColor(changedProfile.color);
mode.setLocationIcon(changedProfile.locationIcon);
mode.setNavigationIcon(changedProfile.navigationIcon);
FragmentActivity activity = getActivity();
if (activity != null) {
activity.onBackPressed();
}
}
}
private ApplicationMode saveNewProfile() {
changedProfile.stringKey = getUniqueStringKey(changedProfile.parent);
ApplicationMode.ApplicationModeBuilder builder = ApplicationMode
.createCustomMode(changedProfile.parent, changedProfile.stringKey, app)
.setIconResName(ProfileIcons.getResStringByResId(changedProfile.iconRes))
@ -678,18 +759,62 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment {
if (!ApplicationMode.values(app).contains(mode)) {
ApplicationMode.changeProfileAvailability(mode, true, app);
}
} else {
ApplicationMode mode = getSelectedAppMode();
mode.setParentAppMode(changedProfile.parent);
mode.setIconResName(ProfileIcons.getResStringByResId(changedProfile.iconRes));
mode.setUserProfileName(changedProfile.name.trim());
mode.setRoutingProfile(changedProfile.routingProfile);
mode.setRouteService(changedProfile.routeService);
mode.setIconColor(changedProfile.color);
mode.setLocationIcon(changedProfile.locationIcon);
mode.setNavigationIcon(changedProfile.navigationIcon);
return mode;
}
private void saveProfileBackup(ApplicationMode mode) {
if (app != null) {
File tempDir = app.getAppPath(IndexConstants.BACKUP_INDEX_DIR);
if (!tempDir.exists()) {
tempDir.mkdirs();
}
app.getSettingsHelper().exportSettings(tempDir, mode.getStringKey(),
getSettingsExportListener(), new SettingsHelper.ProfileSettingsItem(app, mode));
}
}
private void showNewProfileSavingDialog(@Nullable DialogInterface.OnShowListener showListener) {
if (progress != null) {
progress.dismiss();
}
progress = new ProgressDialog(getContext());
progress.setMessage(getString(R.string.saving_new_profile));
progress.setCancelable(false);
progress.setOnShowListener(showListener);
progress.show();
}
private void checkSavingProfile() {
if (isNewProfile) {
File file = ConfigureProfileFragment.getBackupFileForCustomMode(app, changedProfile.stringKey);
boolean fileExporting = app.getSettingsHelper().isFileExporting(file);
if (fileExporting) {
showNewProfileSavingDialog(null);
app.getSettingsHelper().updateExportListener(file, getSettingsExportListener());
} else if (file.exists()) {
dismissProfileSavingDialog();
customProfileSaved();
}
}
}
private void dismissProfileSavingDialog() {
FragmentActivity activity = getActivity();
if (progress != null && activity != null && AndroidUtils.isActivityNotDestroyed(activity)) {
progress.dismiss();
}
}
private void customProfileSaved() {
FragmentActivity activity = getActivity();
if (activity != null) {
FragmentManager fragmentManager = activity.getSupportFragmentManager();
if (!fragmentManager.isStateSaved()) {
fragmentManager.popBackStack();
BaseSettingsFragment.showInstance(activity, SettingsScreenType.CONFIGURE_PROFILE,
ApplicationMode.valueOfStringKey(changedProfile.stringKey, null));
}
}
return true;
}
private String getUniqueStringKey(ApplicationMode mode) {

View file

@ -213,7 +213,7 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment {
if (ctx == null) {
return;
}
AlertDialog.Builder bld = new AlertDialog.Builder(ctx);
AlertDialog.Builder bld = new AlertDialog.Builder(UiUtilities.getThemedContext(ctx, isNightMode()));
bld.setMessage(R.string.confirm_usage_speed_cameras);
bld.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {

View file

@ -32,9 +32,12 @@ public class ResetProfilePrefsBottomSheet extends BasePreferenceBottomSheet {
return;
}
items.add(new TitleItem(getString(R.string.reset_all_profile_settings)));
ApplicationMode mode = getAppMode();
boolean customProfile = mode.isCustomProfile();
String title = getString(customProfile ? R.string.restore_all_profile_settings : R.string.reset_all_profile_settings);
items.add(new TitleItem(title));
int profileColor = mode.getIconColorInfo().getColor(nightMode);
int colorNoAlpha = ContextCompat.getColor(ctx, profileColor);
@ -53,12 +56,15 @@ public class ResetProfilePrefsBottomSheet extends BasePreferenceBottomSheet {
.create();
items.add(profileItem);
StringBuilder description = new StringBuilder(getString(R.string.reset_confirmation_descr, getString(R.string.shared_string_reset)));
description.append("\n\n");
description.append(getString(R.string.reset_all_profile_settings_descr));
String restoreDescr = getString(customProfile ? R.string.shared_string_restore : R.string.shared_string_reset);
String description = getString(customProfile ? R.string.restore_all_profile_settings_descr : R.string.reset_all_profile_settings_descr);
StringBuilder stringBuilder = new StringBuilder(description);
stringBuilder.append("\n\n");
stringBuilder.append(getString(R.string.reset_confirmation_descr, restoreDescr));
BaseBottomSheetItem resetAllSettings = new BottomSheetItemWithDescription.Builder()
.setDescription(description)
.setDescription(stringBuilder)
.setLayoutId(R.layout.bottom_sheet_item_pref_info)
.create();
items.add(resetAllSettings);
@ -66,7 +72,7 @@ public class ResetProfilePrefsBottomSheet extends BasePreferenceBottomSheet {
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_reset;
return getAppMode().isCustomProfile() ? R.string.shared_string_restore : R.string.shared_string_reset;
}
@Override