From e5152aa947b4bfc6f2a49961786025a52b02c817 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Tue, 17 Nov 2020 13:12:29 +0200 Subject: [PATCH] Clean up UI and code --- .../res/layout/enough_space_warning_card.xml | 62 +++ OsmAnd/res/layout/fragment_import.xml | 36 +- .../layout/list_item_description_header.xml | 14 +- .../layout/profile_data_list_item_group.xml | 32 +- OsmAnd/res/values/sizes.xml | 2 + OsmAnd/res/values/strings.xml | 41 +- OsmAnd/src/net/osmand/AndroidUtils.java | 8 + .../plus/download/DownloadActivity.java | 41 +- .../plus/download/ReloadIndexesTask.java | 49 ++ .../settings/backend/ExportSettingsType.java | 24 +- .../backend/backup/SettingsHelper.java | 48 +- .../settings/fragments/ExportDataObject.java | 4 +- .../ExportImportSettingsAdapter.java | 499 +++++++++++------- .../fragments/ExportSettingsAdapter.java | 337 ++++++++++++ .../fragments/ExportSettingsFragment.java | 66 ++- .../fragments/ImportSettingsFragment.java | 92 ++-- .../settings/fragments/ReloadIndexesTack.java | 37 -- 17 files changed, 1023 insertions(+), 369 deletions(-) create mode 100644 OsmAnd/res/layout/enough_space_warning_card.xml create mode 100644 OsmAnd/src/net/osmand/plus/download/ReloadIndexesTask.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java delete mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/ReloadIndexesTack.java diff --git a/OsmAnd/res/layout/enough_space_warning_card.xml b/OsmAnd/res/layout/enough_space_warning_card.xml new file mode 100644 index 0000000000..a39076eb99 --- /dev/null +++ b/OsmAnd/res/layout/enough_space_warning_card.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_import.xml b/OsmAnd/res/layout/fragment_import.xml index e9852ea58d..ef83bba63d 100644 --- a/OsmAnd/res/layout/fragment_import.xml +++ b/OsmAnd/res/layout/fragment_import.xml @@ -21,46 +21,49 @@ + android:paddingBottom="@dimen/bottom_sheet_title_padding_bottom" + android:visibility="invisible" + tools:visibility="visible"> @@ -78,26 +82,32 @@ android:layout_height="match_parent" /> diff --git a/OsmAnd/res/layout/list_item_description_header.xml b/OsmAnd/res/layout/list_item_description_header.xml index f27db51731..9ff915193d 100644 --- a/OsmAnd/res/layout/list_item_description_header.xml +++ b/OsmAnd/res/layout/list_item_description_header.xml @@ -10,15 +10,25 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/bg_color" + android:lineSpacingMultiplier="@dimen/line_spacing_multiplier_description" android:paddingStart="@dimen/content_padding" android:paddingTop="@dimen/list_header_settings_top_margin" android:paddingEnd="@dimen/content_padding" - android:lineSpacingMultiplier="@dimen/line_spacing_multiplier_description" android:paddingBottom="@dimen/list_header_settings_top_margin" android:textColor="?android:textColorPrimary" android:textSize="@dimen/default_list_text_size" tools:text="@string/select_data_to_import" /> - + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/profile_data_list_item_group.xml b/OsmAnd/res/layout/profile_data_list_item_group.xml index 6cf421ff8a..99bb29511b 100644 --- a/OsmAnd/res/layout/profile_data_list_item_group.xml +++ b/OsmAnd/res/layout/profile_data_list_item_group.xml @@ -14,12 +14,12 @@ @@ -48,16 +48,20 @@ android:id="@+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:letterSpacing="@dimen/text_button_letter_spacing" android:textColor="?android:textColorPrimary" android:textSize="@dimen/default_list_text_size" + osmand:lineHeight="@dimen/default_title_line_height" tools:text="Quick actions" /> @@ -66,8 +70,8 @@ android:id="@+id/vertical_divider" android:layout_width="1dp" android:layout_height="match_parent" - android:layout_marginTop="@dimen/content_padding" - android:layout_marginBottom="@dimen/content_padding" + android:layout_marginTop="@dimen/setting_profile_item_switch_margin" + android:layout_marginBottom="@dimen/setting_profile_item_switch_margin" android:background="?attr/list_divider" /> 23sp 15sp 15sp + 24sp + 20sp 13sp 13sp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 9dee5100fe..6b382d13af 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,10 +11,15 @@ Thx - Hardy --> + There is not enough space + OsmAnd is needed %1$s to export a file. Your device only has %2$s free. You can free up space on the device, or skip some items from export. Needed for import Select the data to be exported to the file. Approximate file size Resources + Motorboat + Kayak + Search history I already have an account Create new account Photos are provided by open data project OpenPlaceReviews.org. In order to upload your photos you need to sign up on website. @@ -23,10 +28,10 @@ You can log in using the safe OAuth method or use your login and password. Comment OSM Note Close OSM Note - Trackable means that the trace will not show up in any public listings but trackpoints from it will still be available through the public GPS API with timestamps. Other users will only be able to download processed trackpoints from your trace which can\'t be associated with you directly. - Identifiable means that the trace will be shown publicly in Your GPS traces and in public GPS trace listings, i.e. other users will be able to download the raw trace and associate it with your username. Data served via the trackpoints API will reference your original trace page. Timestamps of the trace points are available through the public GPS API. - Private means that the trace will not show up in any public listings, but trackpoints from it will still be available through the public GPS API without timestamps but will not be chronologically ordered. - Public means that the trace will be shown publicly in Your GPS traces and in public GPS trace listings. Data served via the API does not reference your trace page. Timestamps of the trace points are not available through the public GPS API, and the points are not chronologically ordered. However, other users are still able to download the raw trace from the public trace list and any timestamps contained within. + \"Trackable\" means the trace does not show up in any public listings, but processed trackpoints with timestamps from it (that can\'t be associated with you directly) do through downloads from the public GPS API. + \"Identifiable\" means that the trace will be shown publicly in Your GPS traces and in public GPS trace listings, i.e. other users will be able to download the raw trace and associate it with your username. Public timestamped tracepoint data from the GPS API served via the trackpoints API will reference your original trace page. + \"Private\" means the trace does not show up in any public listings, but trackpoints from it in unchronological order are available through the public GPS API without timestamps. + \"Public\" means the trace is shown publicly in your GPS traces and in public GPS trace listings, and in the public trace list with timestamps in raw form. Data served via the API does not reference your trace page. Tracepoint timestamps are not available through the public GPS API, and tracepoints are not chronologically ordered. Enter tags separated by comma. Send GPX file to OpenStreetMap Markers history @@ -78,13 +83,13 @@ Payment will be charged to your AppGallery account at the confirmation of purchase.\n\nSubscription automatically renews unless it is canceled before the renewal date. Your account will be charged for renewal period (month/three month/year) only on the renewal date.\n\nYou can manage and cancel your subscriptions by going to your AppGallery settings. Subscription charged per selected period. Cancel it on AppGallery at any time. Thank you for purchasing \'Contour lines\' - Start/finish icons + Start and finish icons Name: A – Z Name: Z – A Last modified • Updated "Plan a route" function: allows using different navigation types per segment and the inclusion of tracks\n\n - • New "Appearance" menu for tracks: select color, thickness, display direction arrows, start/finish icons\n\n + • New "Appearance" menu for tracks: select color, thickness, display direction arrows, start and finish icons\n\n • Improved visibility of bicycle nodes.\n\n • Tracks are now tappable, have context menu with basic info.\n\n • Improved "Search" algorithms\n\n @@ -104,11 +109,11 @@ System default Resume trip recording Pause trip recording - Specify the logging interval for the general track recording (enabled via the Trip recording widget on the map). + Specify the logging interval for the general track recording (turned on via the \'Trip recording\' widget on the map). Will pause track logging when the app is killed (via recent apps). (OsmAnd background indication disappears from the Android notification bar.) REC %s track files selected - File name + Filename Only the route line will be saved, the waypoints will be deleted. Simplified track Change route type after @@ -270,11 +275,11 @@ The action button switches between selected profiles. Back to editing Restore default items order - Add / Edit Favorite + Add or edit favorite Parking positions - Create / Edit POI + Create or edit POI Button showing or hiding public transport on the map. - Show/hide public transport + Show or hide public transport Show public transport Hide public transport @@ -376,7 +381,7 @@ A button to show or hide terrain layer on the map. Show terrain Hide terrain - Show / hide terrain + Show or hide terrain Slopes %1$s of %2$s The route will be recalculated if the distance from the route to the current location is more than selected value. @@ -561,7 +566,7 @@ Clear %1$s? Revert Track saved - File name is empty + Empty filename Estimates arrival time for unknown road types, and limits speed for all roads (may affect routing) White Swap %1$s and %2$s @@ -1173,7 +1178,7 @@ Adds initial stop Move destination up, and create it Show closed notes - Show/hide OSM notes on the map. + Show or hide OSM notes on the map. GPX - suitable for export to JOSM or other OSM editors. OSC - suitable for export to OSM. GPX file @@ -1335,7 +1340,7 @@ Save the points either as route points or as a line. Select navigation profile Please add at least one point. - GPX file name: + GPX filename: Show on map after saving Browse the map and add points Measure distance @@ -3826,7 +3831,7 @@ Number of contributors Number of edits Report for - File name contains illegal character + Illegal character in filename Quick action Action %d Screen %d @@ -3948,9 +3953,9 @@ No cobblestone or sett Avoids cobblestone and sett Add at least one item to the list in the \'Quick action\' settings - Alpine/downhill ski + Alpine and downhill skiing Slopes for alpine or downhill skiing and access to ski lifts. - Cross country/nordic ski + Cross country and nordic skiing Trails for nordic or cross-country skiing. Ski touring Routes for ski touring. diff --git a/OsmAnd/src/net/osmand/AndroidUtils.java b/OsmAnd/src/net/osmand/AndroidUtils.java index 40ea9cfb98..af0d934083 100644 --- a/OsmAnd/src/net/osmand/AndroidUtils.java +++ b/OsmAnd/src/net/osmand/AndroidUtils.java @@ -788,6 +788,14 @@ public class AndroidUtils { return result; } + public static long getAvailableSpace(@Nullable File dir) { + if (dir != null && dir.canRead()) { + StatFs fs = new StatFs(dir.getAbsolutePath()); + return fs.getAvailableBlocksLong() * fs.getBlockSize(); + } + return -1; + } + public static float getFreeSpaceGb(File dir) { if (dir.canRead()) { StatFs fs = new StatFs(dir.getAbsolutePath()); diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java index 3ebd06b4b4..52bb44bf5f 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java @@ -22,7 +22,6 @@ import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.Space; import android.widget.TextView; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -36,7 +35,6 @@ import androidx.fragment.app.FragmentActivity; import androidx.viewpager.widget.ViewPager; import net.osmand.AndroidUtils; -import net.osmand.IProgress; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.access.AccessibilityAssistant; @@ -45,7 +43,6 @@ import net.osmand.data.PointDescription; import net.osmand.map.WorldRegion; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.LocalIndexInfo; @@ -64,6 +61,8 @@ import net.osmand.plus.helpers.FileNameTranslationHelper; import net.osmand.plus.inapp.InAppPurchaseHelper; import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.download.ReloadIndexesTask.ReloadIndexesListener; import net.osmand.plus.srtmplugin.SRTMPlugin; import net.osmand.plus.views.controls.PagerSlidingTabStrip; import net.osmand.util.Algorithms; @@ -389,8 +388,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo return !Version.isPaidVersion(application) || application.getSettings().SHOULD_SHOW_FREE_VERSION_BANNER.get(); } - - + public static class FreeVersionBanner { private final View freeVersionBanner; private final View freeVersionBannerTitle; @@ -441,7 +439,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo freeVersionBanner.setVisibility(View.VISIBLE); downloadsLeftProgressBar.setMax(DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS); freeVersionDescriptionTextView.setText(ctx.getString(R.string.free_version_message, - DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS +"" )); + DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS + "")); LinearLayout marksLinearLayout = (LinearLayout) freeVersionBanner.findViewById(R.id.marksLinearLayout); Space spaceView = new Space(ctx); @@ -493,6 +491,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo freeVersionBannerTitle.setVisibility(View.VISIBLE); } } + private void updateAvailableDownloads() { int activeTasks = ctx.getDownloadThread().getCountedDownloads(); OsmandSettings settings = ctx.getMyApplication().getSettings(); @@ -570,36 +569,26 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo } } - @SuppressLint("StaticFieldLeak") public void reloadLocalIndexes() { - AsyncTask> task = new AsyncTask>() { + final OsmandApplication app = (OsmandApplication) getApplication(); + ReloadIndexesTask reloadIndexesTask = new ReloadIndexesTask(app, new ReloadIndexesListener() { @Override - protected void onPreExecute() { - super.onPreExecute(); + public void reloadIndexesStarted() { setSupportProgressBarIndeterminateVisibility(true); } @Override - protected List doInBackground(Void... params) { - return getMyApplication().getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, - new ArrayList() - ); - } - - @Override - protected void onPostExecute(List warnings) { + public void reloadIndexesFinished(List warnings) { setSupportProgressBarIndeterminateVisibility(false); - if (!warnings.isEmpty()) { - Toast.makeText(DownloadActivity.this, AndroidUtils.formatWarnings(warnings).toString(), Toast.LENGTH_LONG).show(); + if (!Algorithms.isEmpty(warnings)) { + app.showToastMessage(AndroidUtils.formatWarnings(warnings).toString()); } newDownloadIndexes(); } - }; - task.executeOnExecutor(singleThreadExecutor); + }); + reloadIndexesTask.executeOnExecutor(singleThreadExecutor); } - - public void setDownloadItem(WorldRegion region, String targetFileName) { if (downloadItem == null) { downloadItem = region; @@ -666,8 +655,8 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo int percent = 0; if (dir.canRead()) { StatFs fs = new StatFs(dir.getAbsolutePath()); - size = AndroidUtils.formatSize(activity, ((long)fs.getAvailableBlocks()) * fs.getBlockSize()); - percent = 100 - (int)((long)fs.getAvailableBlocks() * 100 / fs.getBlockCount()); + size = AndroidUtils.formatSize(activity, ((long) fs.getAvailableBlocks()) * fs.getBlockSize()); + percent = 100 - (int) ((long) fs.getAvailableBlocks() * 100 / fs.getBlockCount()); } sizeProgress.setIndeterminate(false); sizeProgress.setProgress(percent); diff --git a/OsmAnd/src/net/osmand/plus/download/ReloadIndexesTask.java b/OsmAnd/src/net/osmand/plus/download/ReloadIndexesTask.java new file mode 100644 index 0000000000..873d73b671 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/download/ReloadIndexesTask.java @@ -0,0 +1,49 @@ +package net.osmand.plus.download; + +import android.os.AsyncTask; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.IProgress; +import net.osmand.plus.OsmandApplication; + +import java.util.ArrayList; +import java.util.List; + +public class ReloadIndexesTask extends AsyncTask> { + + private final OsmandApplication app; + private final ReloadIndexesListener listener; + + public ReloadIndexesTask(@NonNull OsmandApplication app, @Nullable ReloadIndexesListener listener) { + this.app = app; + this.listener = listener; + } + + @Override + protected void onPreExecute() { + if (listener != null) { + listener.reloadIndexesStarted(); + } + } + + @Override + protected List doInBackground(Void... params) { + return app.getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, new ArrayList()); + } + + @Override + protected void onPostExecute(List warnings) { + if (listener != null) { + listener.reloadIndexesFinished(warnings); + } + } + + public interface ReloadIndexesListener { + + void reloadIndexesStarted(); + + void reloadIndexesFinished(List warnings); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java b/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java index 10e392d0cc..bf86c42ee6 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/ExportSettingsType.java @@ -7,23 +7,24 @@ import net.osmand.plus.R; public enum ExportSettingsType { PROFILE(R.string.shared_string_profiles, R.drawable.ic_action_manage_profiles), + GLOBAL(R.string.general_settings_2, R.drawable.ic_action_settings), QUICK_ACTIONS(R.string.configure_screen_quick_action, R.drawable.ic_quick_action), POI_TYPES(R.string.poi_dialog_poi_type, R.drawable.ic_action_info_dark), - MAP_SOURCES(R.string.quick_action_map_source_title, R.drawable.ic_map), - CUSTOM_RENDER_STYLE(R.string.shared_string_rendering_style, R.drawable.ic_action_map_style), - CUSTOM_ROUTING(R.string.shared_string_routing, R.drawable.ic_action_route_distance), + SEARCH_HISTORY(R.string.shared_string_search_history, R.drawable.ic_action_history), AVOID_ROADS(R.string.avoid_road, R.drawable.ic_action_alert), + FAVORITES(R.string.shared_string_favorites, R.drawable.ic_action_favorite), TRACKS(R.string.shared_string_tracks, R.drawable.ic_action_route_distance), - MULTIMEDIA_NOTES(R.string.audionotes_plugin_name, R.drawable.ic_action_photo_dark), - GLOBAL(R.string.general_settings_2, R.drawable.ic_action_settings), OSM_NOTES(R.string.osm_notes, R.drawable.ic_action_openstreetmap_logo), OSM_EDITS(R.string.osm_edits, R.drawable.ic_action_openstreetmap_logo), - OFFLINE_MAPS(R.string.shared_string_maps, R.drawable.ic_map), - FAVORITES(R.string.shared_string_favorites, R.drawable.ic_action_favorite), - TTS_VOICE(R.string.local_indexes_cat_tts, R.drawable.ic_action_volume_up), - VOICE(R.string.local_indexes_cat_voice, R.drawable.ic_action_volume_up), + MULTIMEDIA_NOTES(R.string.audionotes_plugin_name, R.drawable.ic_grouped_by_type), ACTIVE_MARKERS(R.string.map_markers, R.drawable.ic_action_flag), - HISTORY_MARKERS(R.string.markers_history, R.drawable.ic_action_flag); + HISTORY_MARKERS(R.string.markers_history, R.drawable.ic_action_flag), + CUSTOM_RENDER_STYLE(R.string.shared_string_rendering_style, R.drawable.ic_action_map_style), + CUSTOM_ROUTING(R.string.shared_string_routing, R.drawable.ic_action_route_distance), + MAP_SOURCES(R.string.quick_action_map_source_title, R.drawable.ic_map), + OFFLINE_MAPS(R.string.shared_string_maps, R.drawable.ic_map), + TTS_VOICE(R.string.local_indexes_cat_tts, R.drawable.ic_action_volume_up), + VOICE(R.string.local_indexes_cat_voice, R.drawable.ic_action_volume_up); @StringRes private final int titleId; @@ -46,7 +47,8 @@ public enum ExportSettingsType { } public boolean isSettingsCategory() { - return this == PROFILE || this == GLOBAL || this == QUICK_ACTIONS || this == POI_TYPES; + return this == PROFILE || this == GLOBAL || this == QUICK_ACTIONS || this == POI_TYPES + || this == SEARCH_HISTORY || this == AVOID_ROADS; } public boolean isMyPlacesCategory() { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java index 3a0cbe8a61..910ac66ab3 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/SettingsHelper.java @@ -29,6 +29,8 @@ import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.helpers.FileNameTranslationHelper; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXInfo; +import net.osmand.plus.helpers.SearchHistoryHelper; +import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.osmedit.OpenstreetmapPoint; @@ -504,12 +506,15 @@ public class SettingsHelper { List resourcesItems = getResourcesItems(); if (!settingsItems.isEmpty()) { + sortExportSettingsObjects(settingsItems); dataList.put(ExportSettingsCategory.SETTINGS, settingsItems); } if (!myPlacesItems.isEmpty()) { + sortExportSettingsObjects(myPlacesItems); dataList.put(ExportSettingsCategory.MY_PLACES, myPlacesItems); } if (!resourcesItems.isEmpty()) { + sortExportSettingsObjects(resourcesItems); dataList.put(ExportSettingsCategory.RESOURCES, resourcesItems); } @@ -537,7 +542,14 @@ public class SettingsHelper { if (!poiList.isEmpty()) { settingsItems.add(new ExportDataObject(ExportSettingsType.POI_TYPES, poiList)); } - + List historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false); + if (!historyEntries.isEmpty()) { + settingsItems.add(new ExportDataObject(ExportSettingsType.SEARCH_HISTORY, historyEntries)); + } + Map impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); + if (!impassableRoads.isEmpty()) { + settingsItems.add(new ExportDataObject(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()))); + } return settingsItems; } @@ -653,10 +665,6 @@ public class SettingsHelper { if (!files.isEmpty()) { resourcesItems.add(new ExportDataObject(ExportSettingsType.VOICE, files)); } - Map impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); - if (!impassableRoads.isEmpty()) { - resourcesItems.add(new ExportDataObject(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()))); - } return resourcesItems; } @@ -699,6 +707,7 @@ public class SettingsHelper { List osmEditsPointList = new ArrayList<>(); List markersGroups = new ArrayList<>(); List markersHistoryGroups = new ArrayList<>(); + List historyEntries = new ArrayList<>(); for (Object object : data) { if (object instanceof QuickAction) { @@ -730,6 +739,8 @@ public class SettingsHelper { } else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) { markersHistoryGroups.add((MapMarkersGroup) object); } + } else if (object instanceof HistoryEntry) { + historyEntries.add((HistoryEntry) object); } } if (!quickActions.isEmpty()) { @@ -775,6 +786,9 @@ public class SettingsHelper { } settingsItems.add(new HistoryMarkersSettingsItem(app, mapMarkers)); } + if (!historyEntries.isEmpty()) { + settingsItems.add(new SearchHistorySettingsItem(app, historyEntries)); + } return settingsItems; } @@ -797,12 +811,15 @@ public class SettingsHelper { } } if (!settingsItems.isEmpty()) { + sortExportSettingsObjects(settingsItems); exportMap.put(ExportSettingsCategory.SETTINGS, settingsItems); } if (!myPlacesItems.isEmpty()) { + sortExportSettingsObjects(myPlacesItems); exportMap.put(ExportSettingsCategory.MY_PLACES, myPlacesItems); } if (!resourcesItems.isEmpty()) { + sortExportSettingsObjects(resourcesItems); exportMap.put(ExportSettingsCategory.RESOURCES, resourcesItems); } @@ -829,6 +846,7 @@ public class SettingsHelper { List favoriteGroups = new ArrayList<>(); List markersGroups = new ArrayList<>(); List markersHistoryGroups = new ArrayList<>(); + List historyEntries = new ArrayList<>(); for (SettingsItem item : settingsItems) { switch (item.getType()) { @@ -916,6 +934,10 @@ public class SettingsHelper { HistoryMarkersSettingsItem historyMarkersSettingsItem = (HistoryMarkersSettingsItem) item; markersHistoryGroups.add(historyMarkersSettingsItem.getMarkersGroup()); break; + case SEARCH_HISTORY: + SearchHistorySettingsItem searchHistorySettingsItem = (SearchHistorySettingsItem) item; + historyEntries.addAll(searchHistorySettingsItem.getItems()); + break; default: break; } @@ -972,9 +994,12 @@ public class SettingsHelper { if (!markersGroups.isEmpty()) { settingsToOperate.put(ExportSettingsType.ACTIVE_MARKERS, markersGroups); } - if (!markersGroups.isEmpty()) { + if (!markersHistoryGroups.isEmpty()) { settingsToOperate.put(ExportSettingsType.HISTORY_MARKERS, markersHistoryGroups); } + if (!historyEntries.isEmpty()) { + settingsToOperate.put(ExportSettingsType.SEARCH_HISTORY, historyEntries); + } return settingsToOperate; } @@ -991,4 +1016,15 @@ public class SettingsHelper { } }); } + + private static void sortExportSettingsObjects(List items) { + Collections.sort(items, new Comparator() { + @Override + public int compare(ExportDataObject lhs, ExportDataObject rhs) { + int order1 = lhs.getType().ordinal(); + int order2 = rhs.getType().ordinal(); + return (order1 < order2) ? -1 : ((order1 == order2) ? 0 : 1); + } + }); + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportDataObject.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportDataObject.java index 11cb9a79b6..e8ede12a77 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportDataObject.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportDataObject.java @@ -1,5 +1,7 @@ package net.osmand.plus.settings.fragments; +import androidx.annotation.NonNull; + import net.osmand.plus.settings.backend.ExportSettingsType; import java.util.List; @@ -9,7 +11,7 @@ public class ExportDataObject { private ExportSettingsType type; private List items; - public ExportDataObject(ExportSettingsType type, List items) { + public ExportDataObject(@NonNull ExportSettingsType type, @NonNull List items) { this.type = type; this.items = items; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java index 24df2f294f..2643b5230d 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java @@ -4,6 +4,8 @@ import android.content.res.ColorStateList; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -11,16 +13,33 @@ import androidx.core.content.ContextCompat; import androidx.core.widget.CompoundButtonCompat; import net.osmand.AndroidUtils; +import net.osmand.IndexConstants; import net.osmand.PlatformUtil; +import net.osmand.map.ITileSource; +import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; -import net.osmand.plus.helpers.AndroidUiHelper; -import net.osmand.plus.helpers.FontCache; -import net.osmand.plus.settings.backend.ExportSettingsCategory; +import net.osmand.plus.audionotes.AudioVideoNotesPlugin; +import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; +import net.osmand.plus.helpers.FileNameTranslationHelper; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry; +import net.osmand.plus.osmedit.OpenstreetmapPoint; +import net.osmand.plus.osmedit.OsmEditingPlugin; +import net.osmand.plus.osmedit.OsmNotesPoint; +import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.profiles.ProfileIconColors; +import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources; +import net.osmand.plus.quickaction.QuickAction; +import net.osmand.plus.render.RenderingIcons; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; +import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; +import net.osmand.util.Algorithms; import net.osmand.view.ThreeStateCheckbox; import org.apache.commons.logging.Log; @@ -29,10 +48,11 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import static net.osmand.plus.settings.backend.ExportSettingsType.OFFLINE_MAPS; +import static net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; import static net.osmand.view.ThreeStateCheckbox.State.CHECKED; import static net.osmand.view.ThreeStateCheckbox.State.MISC; import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; @@ -40,94 +60,91 @@ import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { private static final Log LOG = PlatformUtil.getLog(ExportImportSettingsAdapter.class.getName()); + private OsmandApplication app; + private UiUtilities uiUtilities; + private List data; + private Map> itemsMap; + private List itemsTypes; + private boolean nightMode; + private boolean importState; + private int activeColorRes; + private int secondaryColorRes; - private final OsmandApplication app; - private final UiUtilities uiUtilities; - - private List itemsTypes = new ArrayList<>(); - private Map> selectedItemsMap = new HashMap<>(); - private Map> itemsMap = new LinkedHashMap<>(); - - private final OnItemSelectedListener listener; - - private final LayoutInflater themedInflater; - - private final boolean nightMode; - private final int activeColorRes; - private final int secondaryColorRes; - - ExportImportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) { + ExportImportSettingsAdapter(OsmandApplication app, boolean nightMode, boolean importState) { this.app = app; - this.listener = listener; this.nightMode = nightMode; + this.importState = importState; + this.itemsMap = new HashMap<>(); + this.itemsTypes = new ArrayList<>(); + this.data = new ArrayList<>(); uiUtilities = app.getUIUtilities(); - themedInflater = UiUtilities.getInflater(app, nightMode); - activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; - secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light; + activeColorRes = nightMode + ? R.color.icon_color_active_dark + : R.color.icon_color_active_light; + secondaryColorRes = nightMode + ? R.color.icon_color_secondary_dark + : R.color.icon_color_secondary_light; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View group = convertView; if (group == null) { - group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); + group = inflater.inflate(R.layout.profile_data_list_item_group, parent, false); } - final ExportSettingsCategory category = itemsTypes.get(groupPosition); - final List items = itemsMap.get(category); - String title = app.getString(category.getTitleId()); + boolean isLastGroup = groupPosition == getGroupCount() - 1; + final ExportSettingsType type = itemsTypes.get(groupPosition); + TextView titleTv = group.findViewById(R.id.title_tv); - titleTv.setText(UiUtilities.createCustomFontSpannable(FontCache.getRobotoMedium(app), title, title)); - TextView subTextTv = group.findViewById(R.id.sub_text_tv); - subTextTv.setText(getCategoryDescr(category)); - - int selectedTypes = 0; - for (int i = 0; i < items.size(); i++) { - ExportDataObject object = items.get(i); - if (selectedItemsMap.containsKey(object.getType())) { - selectedTypes++; - } - } final ThreeStateCheckbox checkBox = group.findViewById(R.id.check_box); - if (selectedTypes == 0) { - checkBox.setState(UNCHECKED); + FrameLayout checkBoxContainer = group.findViewById(R.id.check_box_container); + ImageView expandIv = group.findViewById(R.id.explist_indicator); + View lineDivider = group.findViewById(R.id.divider); + View cardTopDivider = group.findViewById(R.id.card_top_divider); + View cardBottomDivider = group.findViewById(R.id.card_bottom_divider); + + titleTv.setText(getGroupTitle(type)); + lineDivider.setVisibility(importState || isExpanded || isLastGroup ? View.GONE : View.VISIBLE); + cardTopDivider.setVisibility(importState ? View.VISIBLE : View.GONE); + cardBottomDivider.setVisibility(importState && !isExpanded ? View.VISIBLE : View.GONE); + + final List listItems = itemsMap.get(type); + subTextTv.setText(getSelectedItemsAmount(listItems, type)); + + if (data.containsAll(listItems)) { + checkBox.setState(CHECKED); } else { - checkBox.setState(selectedTypes == items.size() ? CHECKED : MISC); + boolean contains = false; + for (Object object : listItems) { + if (data.contains(object)) { + contains = true; + break; + } + } + checkBox.setState(contains ? MISC : UNCHECKED); } int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); - - group.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() { + checkBoxContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { checkBox.performClick(); - boolean selected = checkBox.getState() == CHECKED; - if (selected) { - for (ExportDataObject object : items) { - if (!selectedItemsMap.containsKey(object.getType())) { - selectedItemsMap.put(object.getType(), (List) object.getItems()); + if (checkBox.getState() == CHECKED) { + for (Object object : listItems) { + if (!data.contains(object)) { + data.add(object); } } - } else { - for (ExportDataObject object : items) { - selectedItemsMap.remove(object.getType()); - } - } - if (listener != null) { - listener.onCategorySelected(category, selected); + data.removeAll(listItems); } notifyDataSetChanged(); } }); - adjustIndicator(app, groupPosition, isExpanded, group, nightMode); - AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded); - AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true); - AndroidUiHelper.updateVisibility(group.findViewById(R.id.vertical_divider), false); - AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_bottom_divider), !isExpanded); - return group; } @@ -135,57 +152,172 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { View child = convertView; if (child == null) { - child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); + LayoutInflater inflater = UiUtilities.getInflater(app, nightMode); + child = inflater.inflate(R.layout.profile_data_list_item_child, parent, false); } - final ExportDataObject currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); - List selectedItems = selectedItemsMap.get(currentItem.getType()); + final Object currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); - TextView titleTv = child.findViewById(R.id.title_tv); - titleTv.setText(currentItem.getType().getTitleId()); + boolean isLastGroup = groupPosition == getGroupCount() - 1; + boolean itemSelected = data.contains(currentItem); + final ExportSettingsType type = itemsTypes.get(groupPosition); - TextView subTextTv = child.findViewById(R.id.sub_text_tv); - subTextTv.setText(getSelectedTypeDescr(currentItem)); + TextView title = child.findViewById(R.id.title_tv); + TextView subText = child.findViewById(R.id.sub_title_tv); + subText.setVisibility(View.GONE); + final CheckBox checkBox = child.findViewById(R.id.check_box); + ImageView icon = child.findViewById(R.id.icon); + View lineDivider = child.findViewById(R.id.divider); + View cardBottomDivider = child.findViewById(R.id.card_bottom_divider); - ImageView icon = child.findViewById(R.id.explist_indicator); - setupIcon(icon, currentItem.getType().getIconRes(), selectedItems != null); - - final ThreeStateCheckbox checkBox = child.findViewById(R.id.check_box); - if (selectedItems == null) { - checkBox.setState(UNCHECKED); - } else if (selectedItems.containsAll(currentItem.getItems())) { - checkBox.setState(CHECKED); - } else { - boolean contains = false; - for (Object object : currentItem.getItems()) { - if (selectedItems.contains(object)) { - contains = true; - break; - } - } - checkBox.setState(contains ? MISC : UNCHECKED); - } - - int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; + lineDivider.setVisibility(!importState && isLastChild && !isLastGroup ? View.VISIBLE : View.GONE); + cardBottomDivider.setVisibility(importState && isLastChild ? View.VISIBLE : View.GONE); + int checkBoxColor = itemSelected ? activeColorRes : secondaryColorRes; CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); - child.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() { + + checkBox.setChecked(itemSelected); + checkBox.setClickable(false); + child.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - checkBox.performClick(); - boolean selected = checkBox.getState() == CHECKED; - if (selected) { - selectedItemsMap.put(currentItem.getType(), (List) currentItem.getItems()); + if (data.contains(currentItem)) { + data.remove(currentItem); } else { - selectedItemsMap.remove(currentItem.getType()); - } - if (listener != null) { - listener.onTypeSelected(currentItem.getType(), selected); + data.add(currentItem); } notifyDataSetChanged(); } }); - AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild); - + switch (type) { + case PROFILE: + ApplicationModeBean modeBean = (ApplicationModeBean) currentItem; + String profileName = modeBean.userProfileName; + if (Algorithms.isEmpty(profileName)) { + ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); + profileName = app.getString(appMode.getNameKeyResource()); + } + title.setText(profileName); + String routingProfile = ""; + String routingProfileValue = modeBean.routingProfile; + if (!routingProfileValue.isEmpty()) { + try { + routingProfile = app.getString(RoutingProfilesResources.valueOf(routingProfileValue.toUpperCase()).getStringRes()); + routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfile); + } catch (IllegalArgumentException e) { + routingProfile = Algorithms.capitalizeFirstLetterAndLowercase(routingProfileValue); + LOG.error("Error trying to get routing resource for " + routingProfileValue + "\n" + e); + } + } + if (!Algorithms.isEmpty(routingProfile)) { + subText.setText(String.format( + app.getString(R.string.ltr_or_rtl_combine_via_colon), + app.getString(R.string.nav_type_hint), + routingProfile)); + subText.setVisibility(View.VISIBLE); + } + int profileIconRes = AndroidUtils.getDrawableId(app, modeBean.iconName); + ProfileIconColors iconColor = modeBean.iconColor; + icon.setImageDrawable(uiUtilities.getIcon(profileIconRes, iconColor.getColor(nightMode))); + break; + case QUICK_ACTIONS: + title.setText(((QuickAction) currentItem).getName(app.getApplicationContext())); + setupIcon(icon, ((QuickAction) currentItem).getIconRes(), itemSelected); + break; + case POI_TYPES: + title.setText(((PoiUIFilter) currentItem).getName()); + int iconRes = RenderingIcons.getBigIconResourceId(((PoiUIFilter) currentItem).getIconId()); + setupIcon(icon, iconRes != 0 ? iconRes : R.drawable.ic_action_user, itemSelected); + break; + case MAP_SOURCES: + title.setText(((ITileSource) currentItem).getName()); + setupIcon(icon, R.drawable.ic_map, itemSelected); + break; + case CUSTOM_RENDER_STYLE: + String renderName = ((File) currentItem).getName(); + renderName = renderName.replace('_', ' ').replaceAll(IndexConstants.RENDERER_INDEX_EXT, ""); + title.setText(renderName); + setupIcon(icon, R.drawable.ic_action_map_style, itemSelected); + break; + case CUSTOM_ROUTING: + String routingName = ((File) currentItem).getName(); + routingName = routingName.replace('_', ' ').replaceAll(".xml", ""); + title.setText(routingName); + setupIcon(icon, R.drawable.ic_action_route_distance, itemSelected); + break; + case AVOID_ROADS: + AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) currentItem; + title.setText(avoidRoadInfo.name); + setupIcon(icon, R.drawable.ic_action_alert, itemSelected); + break; + case MULTIMEDIA_NOTES: + File file = (File) currentItem; + title.setText(file.getName()); + int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); + if (iconId == -1) { + iconId = R.drawable.ic_action_photo_dark; + } + setupIcon(icon, iconId, itemSelected); + break; + case TRACKS: + String fileName = ((File) currentItem).getName(); + title.setText(GpxUiHelper.getGpxTitle(fileName)); + setupIcon(icon, R.drawable.ic_action_route_distance, itemSelected); + break; + case GLOBAL: + String name = ((GlobalSettingsItem) currentItem).getPublicName(app); + title.setText(name); + setupIcon(icon, R.drawable.ic_action_settings, itemSelected); + break; + case OSM_NOTES: + title.setText(((OsmNotesPoint) currentItem).getText()); + setupIcon(icon, R.drawable.ic_action_osm_note_add, itemSelected); + break; + case OSM_EDITS: + title.setText(OsmEditingPlugin.getTitle((OpenstreetmapPoint) currentItem, app)); + setupIcon(icon, R.drawable.ic_action_info_dark, itemSelected); + break; + case OFFLINE_MAPS: + long size; + if (currentItem instanceof FileSettingsItem) { + FileSettingsItem currentFileItem = (FileSettingsItem) currentItem; + file = currentFileItem.getFile(); + size = currentFileItem.getSize(); + } else { + file = (File) currentItem; + size = file.length(); + } + title.setText(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName())); + FileSubtype subtype = FileSubtype.getSubtypeByPath(app, file.getPath()); + setupIcon(icon, subtype.getIconId(), itemSelected); + subText.setText(AndroidUtils.formatSize(app, size)); + subText.setVisibility(View.VISIBLE); + break; + case FAVORITES: + FavoriteGroup favoriteGroup = (FavoriteGroup) currentItem; + title.setText(favoriteGroup.getDisplayName(app)); + setupIcon(icon, R.drawable.ic_action_favorite, itemSelected); + break; + case TTS_VOICE: + case VOICE: + file = (File) currentItem; + title.setText(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName())); + setupIcon(icon, R.drawable.ic_action_volume_up, itemSelected); + break; + case ACTIVE_MARKERS: + title.setText(R.string.map_markers); + setupIcon(icon, R.drawable.ic_action_flag, itemSelected); + break; + case HISTORY_MARKERS: + title.setText(R.string.markers_history); + setupIcon(icon, R.drawable.ic_action_flag, itemSelected); + break; + case SEARCH_HISTORY: + HistoryEntry historyEntry = (HistoryEntry) currentItem; + title.setText(historyEntry.getName().getName()); + break; + default: + return child; + } return child; } @@ -229,16 +361,80 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { return true; } - private void setupIcon(ImageView icon, int iconRes, boolean itemSelected) { - if (itemSelected) { - int colorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_osmand_light; - icon.setImageDrawable(uiUtilities.getIcon(iconRes, colorRes)); - } else { - icon.setImageDrawable(uiUtilities.getIcon(iconRes, secondaryColorRes)); + private String getSelectedItemsAmount(List listItems, ExportSettingsType type) { + int amount = 0; + long amountSize = 0; + for (Object item : listItems) { + if (data.contains(item)) { + amount++; + if (type == OFFLINE_MAPS) { + if (item instanceof FileSettingsItem) { + amountSize += ((FileSettingsItem) item).getSize(); + } else { + amountSize += ((File) item).length(); + } + } + } + } + String itemsOf = app.getString(R.string.n_items_of_z, String.valueOf(amount), String.valueOf(listItems.size())); + return amountSize == 0 ? itemsOf : app.getString(R.string.ltr_or_rtl_combine_via_bold_point, itemsOf, + AndroidUtils.formatSize(app, amountSize)); + } + + private int getGroupTitle(ExportSettingsType type) { + switch (type) { + case PROFILE: + return R.string.shared_string_profiles; + case QUICK_ACTIONS: + return R.string.configure_screen_quick_action; + case POI_TYPES: + return R.string.poi_dialog_poi_type; + case MAP_SOURCES: + return R.string.quick_action_map_source_title; + case CUSTOM_RENDER_STYLE: + return R.string.shared_string_rendering_style; + case CUSTOM_ROUTING: + return R.string.shared_string_routing; + case AVOID_ROADS: + return R.string.avoid_road; + case TRACKS: + return R.string.shared_string_tracks; + case MULTIMEDIA_NOTES: + return R.string.audionotes_plugin_name; + case GLOBAL: + return R.string.general_settings_2; + case OSM_NOTES: + return R.string.osm_notes; + case OSM_EDITS: + return R.string.osm_edits; + case OFFLINE_MAPS: + return R.string.shared_string_maps; + case FAVORITES: + return R.string.shared_string_favorites; + case TTS_VOICE: + return R.string.local_indexes_cat_tts; + case VOICE: + return R.string.local_indexes_cat_voice; + case ACTIVE_MARKERS: + return R.string.map_markers; + case HISTORY_MARKERS: + return R.string.markers_history; + case SEARCH_HISTORY: + return R.string.shared_string_search_history; + default: + return R.string.access_empty_list; } } - public void updateSettingsList(Map> itemsMap) { + private void setupIcon(ImageView icon, int iconRes, boolean itemSelected) { + if (itemSelected) { + icon.setImageDrawable(uiUtilities.getIcon(iconRes, activeColorRes)); + } else { + icon.setImageDrawable(uiUtilities.getIcon(iconRes, nightMode)); + } + } + + public void updateSettingsList(Map> itemsMap) { this.itemsMap = itemsMap; this.itemsTypes = new ArrayList<>(itemsMap.keySet()); Collections.sort(itemsTypes); @@ -251,90 +447,17 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { notifyDataSetChanged(); } - public List getData() { - List selectedItems = new ArrayList<>(); - for (List items : selectedItemsMap.values()) { - selectedItems.addAll(items); - } - return selectedItems; - } - - private String getCategoryDescr(ExportSettingsCategory category) { - long itemsSize = 0; - int selectedTypes = 0; - List items = itemsMap.get(category); - for (int i = 0; i < items.size(); i++) { - ExportDataObject object = items.get(i); - if (selectedItemsMap.containsKey(object.getType())) { - selectedTypes++; - itemsSize += calculateItemsSize(object.getItems()); + public void selectAll(boolean selectAll) { + data.clear(); + if (selectAll) { + for (List values : itemsMap.values()) { + data.addAll(values); } } - - String description; - if (selectedTypes == 0) { - description = app.getString(R.string.shared_string_none); - } else if (selectedTypes == items.size()) { - description = app.getString(R.string.shared_string_all); - } else { - description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size())); - } - String formattedSize = AndroidUtils.formatSize(app, itemsSize); - return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize); + notifyDataSetChanged(); } - public static long calculateItemsSize(List items) { - long itemsSize = 0; - for (Object item : items) { - if (item instanceof FileSettingsItem) { - itemsSize += ((FileSettingsItem) item).getSize(); - } else if (item instanceof File) { - itemsSize += ((File) item).length(); - } - } - return itemsSize; - } - - private String getSelectedTypeDescr(ExportDataObject dataObject) { - long itemsSize = 0; - int selectedTypes = 0; - - List items = dataObject.getItems(); - List selectedItems = selectedItemsMap.get(dataObject.getType()); - if (selectedItems != null) { - for (int i = 0; i < items.size(); i++) { - Object object = items.get(i); - if (selectedItems.contains(object)) { - selectedTypes++; - if (object instanceof FileSettingsItem) { - itemsSize += ((FileSettingsItem) object).getSize(); - } else if (object instanceof File) { - itemsSize += ((File) object).length(); - } - } - } - } - - String description; - if (selectedTypes == 0) { - description = app.getString(R.string.shared_string_none); - } else if (selectedTypes == items.size()) { - description = app.getString(R.string.shared_string_all); - if (itemsSize == 0) { - description = app.getString(R.string.ltr_or_rtl_combine_via_comma, description, String.valueOf(items.size())); - } - } else { - description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size())); - } - String formattedSize = AndroidUtils.formatSize(app, itemsSize); - return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize); - } - - interface OnItemSelectedListener { - - void onCategorySelected(ExportSettingsCategory type, boolean selected); - - void onTypeSelected(ExportSettingsType type, boolean selected); - + List getData() { + return this.data; } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java new file mode 100644 index 0000000000..82ae93ebc0 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java @@ -0,0 +1,337 @@ +package net.osmand.plus.settings.fragments; + +import android.content.res.ColorStateList; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; +import androidx.core.widget.CompoundButtonCompat; + +import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.helpers.FontCache; +import net.osmand.plus.settings.backend.ExportSettingsCategory; +import net.osmand.plus.settings.backend.ExportSettingsType; +import net.osmand.plus.settings.backend.backup.FileSettingsItem; +import net.osmand.view.ThreeStateCheckbox; + +import org.apache.commons.logging.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static net.osmand.view.ThreeStateCheckbox.State.CHECKED; +import static net.osmand.view.ThreeStateCheckbox.State.MISC; +import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED; + +public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { + + private static final Log LOG = PlatformUtil.getLog(ExportImportSettingsAdapter.class.getName()); + + private final OsmandApplication app; + private final UiUtilities uiUtilities; + + private List itemsTypes = new ArrayList<>(); + private Map> selectedItemsMap = new HashMap<>(); + private Map> itemsMap = new LinkedHashMap<>(); + + private final OnItemSelectedListener listener; + + private final LayoutInflater themedInflater; + + private final boolean nightMode; + private final int activeColorRes; + private final int secondaryColorRes; + + ExportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) { + this.app = app; + this.listener = listener; + this.nightMode = nightMode; + uiUtilities = app.getUIUtilities(); + themedInflater = UiUtilities.getInflater(app, nightMode); + activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; + secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { + View group = convertView; + if (group == null) { + group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); + } + final ExportSettingsCategory category = itemsTypes.get(groupPosition); + final List items = itemsMap.get(category); + + String title = app.getString(category.getTitleId()); + TextView titleTv = group.findViewById(R.id.title_tv); + titleTv.setText(UiUtilities.createCustomFontSpannable(FontCache.getRobotoMedium(app), title, title)); + + TextView subTextTv = group.findViewById(R.id.sub_text_tv); + subTextTv.setText(getCategoryDescr(category)); + + int selectedTypes = 0; + for (int i = 0; i < items.size(); i++) { + ExportDataObject object = items.get(i); + if (selectedItemsMap.containsKey(object.getType())) { + selectedTypes++; + } + } + final ThreeStateCheckbox checkBox = group.findViewById(R.id.check_box); + if (selectedTypes == 0) { + checkBox.setState(UNCHECKED); + } else { + checkBox.setState(selectedTypes == items.size() ? CHECKED : MISC); + } + int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); + + group.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + checkBox.performClick(); + boolean selected = checkBox.getState() == CHECKED; + if (selected) { + for (ExportDataObject object : items) { + if (!selectedItemsMap.containsKey(object.getType())) { + selectedItemsMap.put(object.getType(), object.getItems()); + } + } + } else { + for (ExportDataObject object : items) { + selectedItemsMap.remove(object.getType()); + } + } + if (listener != null) { + listener.onCategorySelected(category, selected); + } + notifyDataSetChanged(); + } + }); + + adjustIndicator(app, groupPosition, isExpanded, group, nightMode); + AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded); + AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true); + AndroidUiHelper.updateVisibility(group.findViewById(R.id.vertical_divider), false); + AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_bottom_divider), !isExpanded); + + return group; + } + + @Override + public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + View child = convertView; + if (child == null) { + child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); + } + final ExportDataObject currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); + List selectedItems = selectedItemsMap.get(currentItem.getType()); + + TextView titleTv = child.findViewById(R.id.title_tv); + titleTv.setText(currentItem.getType().getTitleId()); + + TextView subTextTv = child.findViewById(R.id.sub_text_tv); + subTextTv.setText(getSelectedTypeDescr(currentItem)); + + ImageView icon = child.findViewById(R.id.explist_indicator); + setupIcon(icon, currentItem.getType().getIconRes(), selectedItems != null); + + final ThreeStateCheckbox checkBox = child.findViewById(R.id.check_box); + if (selectedItems == null) { + checkBox.setState(UNCHECKED); + } else if (selectedItems.containsAll(currentItem.getItems())) { + checkBox.setState(CHECKED); + } else { + boolean contains = false; + for (Object object : currentItem.getItems()) { + if (selectedItems.contains(object)) { + contains = true; + break; + } + } + checkBox.setState(contains ? MISC : UNCHECKED); + } + + int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; + CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); + child.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + checkBox.performClick(); + boolean selected = checkBox.getState() == CHECKED; + if (selected) { + selectedItemsMap.put(currentItem.getType(), currentItem.getItems()); + } else { + selectedItemsMap.remove(currentItem.getType()); + } + if (listener != null) { + listener.onTypeSelected(currentItem.getType(), selected); + } + notifyDataSetChanged(); + } + }); + + AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild); + + return child; + } + + @Override + public int getGroupCount() { + return itemsTypes.size(); + } + + @Override + public int getChildrenCount(int i) { + return itemsMap.get(itemsTypes.get(i)).size(); + } + + @Override + public Object getGroup(int i) { + return itemsMap.get(itemsTypes.get(i)); + } + + @Override + public Object getChild(int groupPosition, int childPosition) { + return itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); + } + + @Override + public long getGroupId(int i) { + return i; + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return groupPosition * 10000 + childPosition; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public boolean isChildSelectable(int i, int i1) { + return true; + } + + private void setupIcon(ImageView icon, int iconRes, boolean itemSelected) { + if (itemSelected) { + int colorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_osmand_light; + icon.setImageDrawable(uiUtilities.getIcon(iconRes, colorRes)); + } else { + icon.setImageDrawable(uiUtilities.getIcon(iconRes, secondaryColorRes)); + } + } + + public void updateSettingsList(Map> itemsMap) { + this.itemsMap = itemsMap; + this.itemsTypes = new ArrayList<>(itemsMap.keySet()); + Collections.sort(itemsTypes); + notifyDataSetChanged(); + } + + public void clearSettingsList() { + this.itemsMap.clear(); + this.itemsTypes.clear(); + notifyDataSetChanged(); + } + + public List getData() { + List selectedItems = new ArrayList<>(); + for (List items : selectedItemsMap.values()) { + selectedItems.addAll(items); + } + return selectedItems; + } + + private String getCategoryDescr(ExportSettingsCategory category) { + long itemsSize = 0; + int selectedTypes = 0; + List items = itemsMap.get(category); + for (int i = 0; i < items.size(); i++) { + ExportDataObject object = items.get(i); + if (selectedItemsMap.containsKey(object.getType())) { + selectedTypes++; + itemsSize += calculateItemsSize(object.getItems()); + } + } + String description; + if (selectedTypes == 0) { + description = app.getString(R.string.shared_string_none); + } else if (selectedTypes == items.size()) { + description = app.getString(R.string.shared_string_all); + } else { + description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size())); + } + String formattedSize = AndroidUtils.formatSize(app, itemsSize); + return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize); + } + + public static long calculateItemsSize(List items) { + long itemsSize = 0; + for (Object item : items) { + if (item instanceof FileSettingsItem) { + itemsSize += ((FileSettingsItem) item).getSize(); + } else if (item instanceof File) { + itemsSize += ((File) item).length(); + } + } + return itemsSize; + } + + private String getSelectedTypeDescr(ExportDataObject dataObject) { + long itemsSize = 0; + int selectedTypes = 0; + + List items = dataObject.getItems(); + List selectedItems = selectedItemsMap.get(dataObject.getType()); + if (selectedItems != null) { + for (int i = 0; i < items.size(); i++) { + Object object = items.get(i); + if (selectedItems.contains(object)) { + selectedTypes++; + if (object instanceof FileSettingsItem) { + itemsSize += ((FileSettingsItem) object).getSize(); + } else if (object instanceof File) { + itemsSize += ((File) object).length(); + } + } + } + } + String description; + if (selectedTypes == 0) { + description = app.getString(R.string.shared_string_none); + } else if (selectedTypes == items.size()) { + description = app.getString(R.string.shared_string_all); + if (itemsSize == 0) { + description = app.getString(R.string.ltr_or_rtl_combine_via_comma, description, String.valueOf(items.size())); + } + } else { + description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size())); + } + String formattedSize = AndroidUtils.formatSize(app, itemsSize); + return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize); + } + + interface OnItemSelectedListener { + + void onCategorySelected(ExportSettingsCategory type, boolean selected); + + void onTypeSelected(ExportSettingsType type, boolean selected); + + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java index 79f7159909..f80c225ff2 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java @@ -35,13 +35,14 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ExportSettingsCategory; import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener; import net.osmand.plus.settings.backend.backup.SettingsItem; -import net.osmand.plus.settings.fragments.ExportImportSettingsAdapter.OnItemSelectedListener; +import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; import net.osmand.plus.widgets.TextViewEx; import org.apache.commons.logging.Log; @@ -78,10 +79,15 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem private ApplicationMode appMode; private SettingsExportListener exportListener; - private TextViewEx fileSize; + private View headerShadow; + private View headerDivider; + private View itemsSizeContainer; + private View availableSpaceContainer; + private TextViewEx selectedItemsSize; + private TextViewEx availableSpaceDescr; private LinearLayout buttonsContainer; private ExpandableListView expandableList; - private ExportImportSettingsAdapter adapter; + private ExportSettingsAdapter adapter; private int progressMax; private int progressValue; @@ -127,16 +133,23 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem View root = themedInflater.inflate(R.layout.fragment_import, container, false); AndroidUtils.addStatusBarPadding21v(app, root); - fileSize = root.findViewById(R.id.file_size); + selectedItemsSize = root.findViewById(R.id.file_size); + itemsSizeContainer = root.findViewById(R.id.file_size_container); expandableList = root.findViewById(R.id.list); buttonsContainer = root.findViewById(R.id.buttons_container); Toolbar toolbar = root.findViewById(R.id.toolbar); setupToolbar(toolbar); ViewCompat.setNestedScrollingEnabled(expandableList, true); + View header = themedInflater.inflate(R.layout.list_item_description_header, null); + headerDivider = header.findViewById(R.id.divider); + headerShadow = header.findViewById(R.id.card_bottom_divider); expandableList.addHeaderView(header); + availableSpaceContainer = inflater.inflate(R.layout.enough_space_warning_card, null); + availableSpaceDescr = availableSpaceContainer.findViewById(R.id.warning_descr); + TextViewEx continueBtn = root.findViewById(R.id.continue_button); continueBtn.setOnClickListener(new View.OnClickListener() { @Override @@ -161,7 +174,7 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem } }); - adapter = new ExportImportSettingsAdapter(app, this, nightMode); + adapter = new ExportSettingsAdapter(app, this, nightMode); adapter.updateSettingsList(dataList); expandableList.setAdapter(adapter); @@ -169,6 +182,7 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem toolbarLayout.setTitle(getString(R.string.shared_string_export)); TextView description = header.findViewById(R.id.description); description.setText(R.string.select_data_to_export); + updateAvailableSpace(); return root; } @@ -235,20 +249,50 @@ public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItem }); } - private void updateFileSize() { - long itemsSize = ExportImportSettingsAdapter.calculateItemsSize(adapter.getData()); - String size = itemsSize != 0 ? AndroidUtils.formatSize(app, itemsSize) : ""; - fileSize.setText(size); + private void updateAvailableSpace() { + long calculatedSize = ExportSettingsAdapter.calculateItemsSize(adapter.getData()); + if (calculatedSize != 0) { + String itemsSize = AndroidUtils.formatSize(app, calculatedSize); + selectedItemsSize.setText(itemsSize); + + File dir = app.getAppPath("").getParentFile(); + long availableSizeBytes = AndroidUtils.getAvailableSpace(dir); + if (calculatedSize > availableSizeBytes) { + String availableSize = AndroidUtils.formatSize(app, availableSizeBytes); + availableSpaceDescr.setText(getString(R.string.export_not_enough_space_descr, itemsSize, availableSize)); + updateWarningHeaderVisibility(true); + } else { + updateWarningHeaderVisibility(false); + } + itemsSizeContainer.setVisibility(View.VISIBLE); + } else { + updateWarningHeaderVisibility(false); + itemsSizeContainer.setVisibility(View.INVISIBLE); + } + } + + private void updateWarningHeaderVisibility(boolean visible) { + if (visible) { + if (expandableList.getHeaderViewsCount() < 2) { + expandableList.addHeaderView(availableSpaceContainer); + } + AndroidUiHelper.updateVisibility(headerShadow, false); + AndroidUiHelper.updateVisibility(headerDivider, true); + } else { + expandableList.removeHeaderView(availableSpaceContainer); + AndroidUiHelper.updateVisibility(headerShadow, true); + AndroidUiHelper.updateVisibility(headerDivider, false); + } } @Override public void onCategorySelected(ExportSettingsCategory type, boolean selected) { - updateFileSize(); + updateAvailableSpace(); } @Override public void onTypeSelected(ExportSettingsType type, boolean selected) { - updateFileSize(); + updateAvailableSpace(); } private void prepareFile() { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java index aaed2edcb5..816d5517dc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java @@ -22,13 +22,13 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; import androidx.core.view.ViewCompat; import androidx.fragment.app.FragmentManager; import com.google.android.material.appbar.CollapsingToolbarLayout; import net.osmand.AndroidUtils; +import net.osmand.IProgress; import net.osmand.PlatformUtil; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager.TileSourceTemplate; @@ -49,7 +49,6 @@ import net.osmand.plus.osmedit.OsmNotesPoint; import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; -import net.osmand.plus.settings.backend.ExportSettingsCategory; import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.AvoidRoadsSettingsItem; import net.osmand.plus.settings.backend.backup.FavoritesSettingsItem; @@ -69,44 +68,37 @@ import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportAsyncTask; import net.osmand.plus.settings.backend.backup.SettingsHelper.ImportType; import net.osmand.plus.settings.backend.backup.SettingsItem; import net.osmand.plus.settings.backend.backup.SettingsItemType; -import net.osmand.plus.settings.fragments.ExportImportSettingsAdapter.OnItemSelectedListener; import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.io.File; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItemSelectedListener { +public class ImportSettingsFragment extends BaseOsmAndFragment { public static final String TAG = ImportSettingsFragment.class.getSimpleName(); public static final Log LOG = PlatformUtil.getLog(ImportSettingsFragment.class.getSimpleName()); - - protected static final String IMPORT_SETTINGS_TAG = "import_settings_tag"; private static final String DUPLICATES_START_TIME_KEY = "duplicates_start_time"; private static final long MIN_DELAY_TIME_MS = 500; - + static final String IMPORT_SETTINGS_TAG = "import_settings_tag"; private OsmandApplication app; - - private File file; - private SettingsHelper settingsHelper; - private List settingsItems; - private Map> dataList; - private ExportImportSettingsAdapter adapter; private ExpandableListView expandableList; private TextView description; + private List settingsItems; + private File file; + private boolean allSelected; + private boolean nightMode; private LinearLayout buttonsContainer; private ProgressBar progressBar; - private TextViewEx fileSize; - private TextViewEx fileSizeDescr; private CollapsingToolbarLayout toolbarLayout; - - private boolean nightMode; + private SettingsHelper settingsHelper; private long duplicateStartTime; public static void showInstance(@NonNull FragmentManager fm, @NonNull List settingsItems, @NonNull File file) { @@ -143,13 +135,10 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem View root = inflater.inflate(R.layout.fragment_import, container, false); Toolbar toolbar = root.findViewById(R.id.toolbar); TextViewEx continueBtn = root.findViewById(R.id.continue_button); - fileSize = root.findViewById(R.id.file_size); toolbarLayout = root.findViewById(R.id.toolbar_layout); expandableList = root.findViewById(R.id.list); buttonsContainer = root.findViewById(R.id.buttons_container); progressBar = root.findViewById(R.id.progress_bar); - fileSizeDescr = root.findViewById(R.id.file_size_descr); - fileSizeDescr.setText(R.string.file_size_needed_for_import); setupToolbar(toolbar); ViewCompat.setNestedScrollingEnabled(expandableList, true); View header = inflater.inflate(R.layout.list_item_description_header, null); @@ -210,10 +199,10 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem } } - adapter = new ExportImportSettingsAdapter(app, this, nightMode); - Map> itemsMap = new HashMap<>(); + adapter = new ExportImportSettingsAdapter(app, nightMode, true); + Map> itemsMap = new HashMap<>(); if (settingsItems != null) { - itemsMap = SettingsHelper.getSettingsToOperateByCategory(settingsItems, false); + itemsMap = SettingsHelper.getSettingsToOperate(settingsItems, false); adapter.updateSettingsList(itemsMap); } expandableList.setAdapter(adapter); @@ -227,7 +216,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem } else { toolbarLayout.setTitle(getString(R.string.shared_string_import)); } - if (itemsMap.size() == 1 && itemsMap.containsKey(ExportSettingsCategory.SETTINGS)) { + if (itemsMap.size() == 1 && itemsMap.containsKey(ExportSettingsType.PROFILE)) { expandableList.expandGroup(0); } } @@ -238,6 +227,15 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem outState.putLong(DUPLICATES_START_TIME_KEY, duplicateStartTime); } + @Override + public void onResume() { + super.onResume(); + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + ((MapActivity) activity).closeDrawer(); + } + } + private void updateUi(int toolbarTitleRes, int descriptionRes) { if (file != null) { String fileName = file.getName(); @@ -290,6 +288,31 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem } } + private static class ReloadIndexesTack extends AsyncTask { + + private final WeakReference mapActivityRef; + private final OsmandApplication app; + + ReloadIndexesTack(@NonNull MapActivity mapActivity) { + this.mapActivityRef = new WeakReference<>(mapActivity); + this.app = mapActivity.getMyApplication(); + } + + @Override + protected Void doInBackground(Void[] params) { + app.getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, new ArrayList()); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + mapActivity.refreshMap(); + } + } + } + private SettingsHelper.CheckDuplicatesListener getDuplicatesListener() { return new SettingsHelper.CheckDuplicatesListener() { @Override @@ -519,8 +542,9 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem } private void setupToolbar(Toolbar toolbar) { - int color = ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light); - toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, color)); + toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, nightMode + ? getResources().getColor(R.color.active_buttons_and_links_text_dark) + : getResources().getColor(R.color.active_buttons_and_links_text_light))); toolbar.setNavigationContentDescription(R.string.shared_string_close); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override @@ -533,20 +557,4 @@ public class ImportSettingsFragment extends BaseOsmAndFragment implements OnItem public void setFile(File file) { this.file = file; } - - private void updateFileSize() { - long itemsSize = ExportImportSettingsAdapter.calculateItemsSize(adapter.getData()); - String size = itemsSize != 0 ? AndroidUtils.formatSize(app, itemsSize) : ""; - fileSize.setText(size); - } - - @Override - public void onCategorySelected(ExportSettingsCategory type, boolean selected) { - updateFileSize(); - } - - @Override - public void onTypeSelected(ExportSettingsType type, boolean selected) { - updateFileSize(); - } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ReloadIndexesTack.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ReloadIndexesTack.java deleted file mode 100644 index d5776a7f45..0000000000 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ReloadIndexesTack.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.osmand.plus.settings.fragments; - -import android.os.AsyncTask; - -import androidx.annotation.NonNull; - -import net.osmand.IProgress; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.activities.MapActivity; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -class ReloadIndexesTack extends AsyncTask { - - private final WeakReference mapActivityRef; - private final OsmandApplication app; - - ReloadIndexesTack(@NonNull MapActivity mapActivity) { - this.mapActivityRef = new WeakReference<>(mapActivity); - this.app = mapActivity.getMyApplication(); - } - - @Override - protected Void doInBackground(Void[] params) { - app.getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, new ArrayList()); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - MapActivity mapActivity = mapActivityRef.get(); - if (mapActivity != null) { - mapActivity.refreshMap(); - } - } -}