Merge pull request #10285 from osmandapp/export_ui_fixes

Export UI Items
This commit is contained in:
vshcherb 2020-11-27 13:24:05 +01:00 committed by GitHub
commit 3074e8a79f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 308 additions and 88 deletions

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item>
<objectAnimator
android:propertyName="elevation"
android:valueTo="@dimen/design_appbar_elevation"
android:valueType="floatType" />
</item>
</selector>

View file

@ -33,7 +33,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="2"
android:textAppearance="@style/TextAppearance.ListItemTitle" android:textAppearance="@style/TextAppearance.ListItemTitle"
tools:text="Some title"/> tools:text="Some title"/>

View file

@ -36,6 +36,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing" android:letterSpacing="@dimen/text_button_letter_spacing"
android:paddingBottom="@dimen/measurement_tool_menu_title_padding_bottom"
android:text="@string/export_not_enough_space" android:text="@string/export_not_enough_space"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" android:textSize="@dimen/default_list_text_size"

View file

@ -23,16 +23,22 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:background="?attr/bg_color"
android:gravity="center"
android:minHeight="@dimen/bottom_sheet_title_height"
android:orientation="vertical"> android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/buttons_shadow"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_top_shadow_height"
android:layout_gravity="bottom"
android:src="@drawable/shadow" />
<include layout="@layout/divider" /> <include layout="@layout/divider" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:minHeight="@dimen/measurement_tool_controls_height"
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout
@ -82,6 +88,7 @@
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<LinearLayout <LinearLayout
android:id="@+id/continue_button_container"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding_half" android:layout_marginLeft="@dimen/content_padding_half"
@ -104,7 +111,8 @@
android:id="@+id/appbar" android:id="@+id/appbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@android:color/transparent"> android:background="@android:color/transparent"
android:stateListAnimator="@animator/appbar_always_elevated">
<com.google.android.material.appbar.CollapsingToolbarLayout <com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout" android:id="@+id/toolbar_layout"

View file

@ -18,6 +18,7 @@
android:background="?attr/bg_color"> android:background="?attr/bg_color">
<LinearLayout <LinearLayout
android:id="@+id/item_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
@ -30,9 +31,7 @@
android:layout_width="@dimen/standard_icon_size" android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size" android:layout_height="@dimen/standard_icon_size"
android:layout_marginLeft="@dimen/content_padding" android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/bottom_sheet_icon_margin"
android:layout_marginRight="@dimen/content_padding" android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/bottom_sheet_icon_margin"
osmand:srcCompat="@drawable/ic_action_arrow_down" /> osmand:srcCompat="@drawable/ic_action_arrow_down" />
<LinearLayout <LinearLayout
@ -48,6 +47,7 @@
android:id="@+id/title_tv" android:id="@+id/title_tv"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/subHeaderPadding"
android:letterSpacing="@dimen/text_button_letter_spacing" android:letterSpacing="@dimen/text_button_letter_spacing"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size" android:textSize="@dimen/default_list_text_size"
@ -69,9 +69,7 @@
<View <View
android:id="@+id/vertical_divider" android:id="@+id/vertical_divider"
android:layout_width="1dp" android:layout_width="1dp"
android:layout_height="match_parent" android:layout_height="@dimen/dialog_button_height"
android:layout_marginTop="@dimen/setting_profile_item_switch_margin"
android:layout_marginBottom="@dimen/setting_profile_item_switch_margin"
android:background="?attr/list_divider" /> android:background="?attr/list_divider" />
<FrameLayout <FrameLayout
@ -79,6 +77,8 @@
style="@style/Widget.AppCompat.Toolbar.Button.Navigation" style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/acceptable_touch_radius" android:layout_width="@dimen/acceptable_touch_radius"
android:layout_height="@dimen/acceptable_touch_radius" android:layout_height="@dimen/acceptable_touch_radius"
android:layout_marginStart="@dimen/content_padding_small"
android:layout_marginLeft="@dimen/content_padding_small"
android:layout_marginEnd="@dimen/text_margin_small" android:layout_marginEnd="@dimen/text_margin_small"
android:layout_marginRight="@dimen/text_margin_small"> android:layout_marginRight="@dimen/text_margin_small">

View file

@ -397,6 +397,7 @@
<dimen name="setting_list_item_small_height">42dp</dimen> <dimen name="setting_list_item_small_height">42dp</dimen>
<dimen name="setting_select_icon_button_height">128dp</dimen> <dimen name="setting_select_icon_button_height">128dp</dimen>
<dimen name="setting_select_icon_button_width">164dp</dimen> <dimen name="setting_select_icon_button_width">164dp</dimen>
<dimen name="setting_list_item_group_height">68dp</dimen>
<dimen name="slider_thumb_size">6dp</dimen> <dimen name="slider_thumb_size">6dp</dimen>
<dimen name="slider_thumb_halo_size">12dp</dimen> <dimen name="slider_thumb_halo_size">12dp</dimen>

View file

@ -11,6 +11,7 @@
Thx - Hardy Thx - Hardy
--> -->
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>
<string name="add_photos_descr">OsmAnd shows photos from several sources:\nOpenPlaceReviews - POI photos;\nMapillary - street-level imagery;\nWeb / Wikimedia - POI photos specified in OpenStreetMap data.</string> <string name="add_photos_descr">OsmAnd shows photos from several sources:\nOpenPlaceReviews - POI photos;\nMapillary - street-level imagery;\nWeb / Wikimedia - POI photos specified in OpenStreetMap data.</string>
<string name="use_dev_url">Use dev.openstreetmap.org</string> <string name="use_dev_url">Use dev.openstreetmap.org</string>
<string name="use_dev_url_descr">Switch to use "dev.openstreetmap.org" instead of "openstreetmap.org" to testing uploading OSM Note / POI / GPX.</string> <string name="use_dev_url_descr">Switch to use "dev.openstreetmap.org" instead of "openstreetmap.org" to testing uploading OSM Note / POI / GPX.</string>

View file

@ -10,7 +10,6 @@ public enum ExportSettingsType {
GLOBAL(R.string.general_settings_2, R.drawable.ic_action_settings), GLOBAL(R.string.general_settings_2, R.drawable.ic_action_settings),
QUICK_ACTIONS(R.string.configure_screen_quick_action, R.drawable.ic_quick_action), 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), POI_TYPES(R.string.poi_dialog_poi_type, R.drawable.ic_action_info_dark),
SEARCH_HISTORY(R.string.shared_string_search_history, R.drawable.ic_action_history),
AVOID_ROADS(R.string.avoid_road, R.drawable.ic_action_alert), AVOID_ROADS(R.string.avoid_road, R.drawable.ic_action_alert),
FAVORITES(R.string.shared_string_favorites, R.drawable.ic_action_favorite), FAVORITES(R.string.shared_string_favorites, R.drawable.ic_action_favorite),
TRACKS(R.string.shared_string_tracks, R.drawable.ic_action_route_distance), TRACKS(R.string.shared_string_tracks, R.drawable.ic_action_route_distance),
@ -19,6 +18,7 @@ public enum ExportSettingsType {
MULTIMEDIA_NOTES(R.string.audionotes_plugin_name, R.drawable.ic_grouped_by_type), MULTIMEDIA_NOTES(R.string.audionotes_plugin_name, R.drawable.ic_grouped_by_type),
ACTIVE_MARKERS(R.string.map_markers, R.drawable.ic_action_flag), 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),
SEARCH_HISTORY(R.string.shared_string_search_history, R.drawable.ic_action_history),
CUSTOM_RENDER_STYLE(R.string.shared_string_rendering_style, R.drawable.ic_action_map_style), 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), 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), MAP_SOURCES(R.string.quick_action_map_source_title, R.drawable.ic_map),
@ -48,12 +48,13 @@ public enum ExportSettingsType {
public boolean isSettingsCategory() { 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; || this == AVOID_ROADS;
} }
public boolean isMyPlacesCategory() { public boolean isMyPlacesCategory() {
return this == FAVORITES || this == TRACKS || this == OSM_EDITS || this == OSM_NOTES return this == FAVORITES || this == TRACKS || this == OSM_EDITS || this == OSM_NOTES
|| this == MULTIMEDIA_NOTES || this == ACTIVE_MARKERS || this == HISTORY_MARKERS; || this == MULTIMEDIA_NOTES || this == ACTIVE_MARKERS || this == HISTORY_MARKERS
|| this == SEARCH_HISTORY;
} }
public boolean isResourcesCategory() { public boolean isResourcesCategory() {

View file

@ -19,6 +19,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
public class FileSettingsItem extends StreamSettingsItem { public class FileSettingsItem extends StreamSettingsItem {
@ -131,6 +132,7 @@ public class FileSettingsItem extends StreamSettingsItem {
private final File appPath; private final File appPath;
protected FileSubtype subtype; protected FileSubtype subtype;
private long size; private long size;
private long lastModified;
public FileSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException { public FileSettingsItem(@NonNull OsmandApplication app, @NonNull File file) throws IllegalArgumentException {
super(app, file.getPath().replace(app.getAppPath(null).getPath(), "")); super(app, file.getPath().replace(app.getAppPath(null).getPath(), ""));
@ -222,6 +224,14 @@ public class FileSettingsItem extends StreamSettingsItem {
this.size = size; this.size = size;
} }
public long getLastModified() {
return lastModified;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
@NonNull @NonNull
public File getFile() { public File getFile() {
return file; return file;
@ -292,6 +302,9 @@ public class FileSettingsItem extends StreamSettingsItem {
} finally { } finally {
Algorithms.closeStream(output); Algorithms.closeStream(output);
} }
if (lastModified != -1) {
dest.setLastModified(lastModified);
}
} }
}; };
} }
@ -306,7 +319,14 @@ public class FileSettingsItem extends StreamSettingsItem {
warnings.add(app.getString(R.string.settings_item_read_error, file.getName())); warnings.add(app.getString(R.string.settings_item_read_error, file.getName()));
SettingsHelper.LOG.error("Failed to set input stream from file: " + file.getName(), e); SettingsHelper.LOG.error("Failed to set input stream from file: " + file.getName(), e);
} }
return super.getWriter(); return new StreamSettingsItemWriter(this) {
@Override
public ZipEntry createNewEntry(String fileName) {
ZipEntry entry = super.createNewEntry(fileName);
entry.setTime(file.lastModified());
return entry;
}
};
} else { } else {
return new StreamSettingsItemWriter(this) { return new StreamSettingsItemWriter(this) {

View file

@ -539,10 +539,6 @@ public class SettingsHelper {
if (!poiList.isEmpty()) { if (!poiList.isEmpty()) {
settingsItems.put(ExportSettingsType.POI_TYPES, poiList); settingsItems.put(ExportSettingsType.POI_TYPES, poiList);
} }
List<HistoryEntry> historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false);
if (!historyEntries.isEmpty()) {
settingsItems.put(ExportSettingsType.SEARCH_HISTORY, historyEntries);
}
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
if (!impassableRoads.isEmpty()) { if (!impassableRoads.isEmpty()) {
settingsItems.put(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values())); settingsItems.put(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()));
@ -611,6 +607,10 @@ public class SettingsHelper {
markersGroup.setMarkers(markersHistory); markersGroup.setMarkers(markersHistory);
myPlacesItems.put(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup)); myPlacesItems.put(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup));
} }
List<HistoryEntry> historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false);
if (!historyEntries.isEmpty()) {
myPlacesItems.put(ExportSettingsType.SEARCH_HISTORY, historyEntries);
}
return myPlacesItems; return myPlacesItems;
} }
@ -829,10 +829,10 @@ public class SettingsHelper {
List<File> routingFilesList = new ArrayList<>(); List<File> routingFilesList = new ArrayList<>();
List<File> renderFilesList = new ArrayList<>(); List<File> renderFilesList = new ArrayList<>();
List<File> multimediaFilesList = new ArrayList<>(); List<File> multimediaFilesList = new ArrayList<>();
List<File> tracksFilesList = new ArrayList<>();
List<File> ttsVoiceFilesList = new ArrayList<>(); List<File> ttsVoiceFilesList = new ArrayList<>();
List<File> voiceFilesList = new ArrayList<>(); List<File> voiceFilesList = new ArrayList<>();
List<FileSettingsItem> mapFilesList = new ArrayList<>(); List<FileSettingsItem> mapFilesList = new ArrayList<>();
List<FileSettingsItem> tracksFilesList = new ArrayList<>();
List<AvoidRoadInfo> avoidRoads = new ArrayList<>(); List<AvoidRoadInfo> avoidRoads = new ArrayList<>();
List<GlobalSettingsItem> globalSettingsItems = new ArrayList<>(); List<GlobalSettingsItem> globalSettingsItems = new ArrayList<>();
List<OsmNotesPoint> notesPointList = new ArrayList<>(); List<OsmNotesPoint> notesPointList = new ArrayList<>();
@ -856,7 +856,7 @@ public class SettingsHelper {
} else if (fileItem.getSubtype() == FileSubtype.MULTIMEDIA_NOTES) { } else if (fileItem.getSubtype() == FileSubtype.MULTIMEDIA_NOTES) {
multimediaFilesList.add(fileItem.getFile()); multimediaFilesList.add(fileItem.getFile());
} else if (fileItem.getSubtype() == FileSubtype.GPX) { } else if (fileItem.getSubtype() == FileSubtype.GPX) {
tracksFilesList.add(fileItem.getFile()); tracksFilesList.add(fileItem);
} else if (fileItem.getSubtype().isMap()) { } else if (fileItem.getSubtype().isMap()) {
mapFilesList.add(fileItem); mapFilesList.add(fileItem);
} else if (fileItem.getSubtype() == FileSubtype.TTS_VOICE) { } else if (fileItem.getSubtype() == FileSubtype.TTS_VOICE) {

View file

@ -60,7 +60,7 @@ class SettingsImporter {
try { try {
SettingsItemsFactory itemsFactory = new SettingsItemsFactory(app, itemsJson); SettingsItemsFactory itemsFactory = new SettingsItemsFactory(app, itemsJson);
List<SettingsItem> settingsItemList = itemsFactory.getItems(); List<SettingsItem> settingsItemList = itemsFactory.getItems();
getFilesSize(file, settingsItemList); updateFilesInfo(file, settingsItemList);
items.addAll(settingsItemList); items.addAll(settingsItemList);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
SettingsHelper.LOG.error("Error parsing items: " + itemsJson, e); SettingsHelper.LOG.error("Error parsing items: " + itemsJson, e);
@ -81,7 +81,7 @@ class SettingsImporter {
return items; return items;
} }
private void getFilesSize(@NonNull File file, List<SettingsItem> settingsItemList) throws IOException { private void updateFilesInfo(@NonNull File file, List<SettingsItem> settingsItemList) throws IOException {
ZipFile zipfile = new ZipFile(file.getPath()); ZipFile zipfile = new ZipFile(file.getPath());
Enumeration<? extends ZipEntry> zipEnum = zipfile.entries(); Enumeration<? extends ZipEntry> zipEnum = zipfile.entries();
while (zipEnum.hasMoreElements()) { while (zipEnum.hasMoreElements()) {
@ -90,7 +90,9 @@ class SettingsImporter {
for (SettingsItem settingsItem : settingsItemList) { for (SettingsItem settingsItem : settingsItemList) {
if (settingsItem instanceof FileSettingsItem if (settingsItem instanceof FileSettingsItem
&& zipEntry.getName().equals(settingsItem.getFileName())) { && zipEntry.getName().equals(settingsItem.getFileName())) {
((FileSettingsItem) settingsItem).setSize(size); FileSettingsItem fileSettingsItem = (FileSettingsItem) settingsItem;
fileSettingsItem.setSize(size);
fileSettingsItem.setLastModified(zipEntry.getTime());
break; break;
} }
} }

View file

@ -22,9 +22,13 @@ public abstract class SettingsItemWriter<T extends SettingsItem> {
public abstract boolean writeToStream(@NonNull OutputStream outputStream) throws IOException; public abstract boolean writeToStream(@NonNull OutputStream outputStream) throws IOException;
public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException { public void writeEntry(String fileName, @NonNull ZipOutputStream zos) throws IOException {
ZipEntry entry = new ZipEntry(fileName); ZipEntry entry = createNewEntry(fileName);
zos.putNextEntry(entry); zos.putNextEntry(entry);
writeToStream(zos); writeToStream(zos);
zos.closeEntry(); zos.closeEntry();
} }
public ZipEntry createNewEntry(String fileName) {
return new ZipEntry(fileName);
}
} }

View file

@ -2,15 +2,14 @@ package net.osmand.plus.settings.fragments;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ExpandableListView; import android.widget.ExpandableListView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -31,6 +30,7 @@ import net.osmand.plus.settings.backend.ExportSettingsCategory;
import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener;
import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -60,6 +60,7 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem
protected ExpandableListView expandableList; protected ExpandableListView expandableList;
protected ExportSettingsAdapter adapter; protected ExportSettingsAdapter adapter;
protected boolean exportMode;
protected boolean nightMode; protected boolean nightMode;
private boolean wasDrawerDisabled; private boolean wasDrawerDisabled;
@ -73,6 +74,17 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
app = requireMyApplication(); app = requireMyApplication();
nightMode = !app.getSettings().isLightContent(); nightMode = !app.getSettings().isLightContent();
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (hasSelectedData()) {
showExitDialog();
} else {
dismissFragment();
}
}
});
} }
@Nullable @Nullable
@ -101,26 +113,15 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem
continueBtn = root.findViewById(R.id.continue_button); continueBtn = root.findViewById(R.id.continue_button);
UiUtilities.setupDialogButton(nightMode, continueBtn, DialogButtonType.PRIMARY, getString(R.string.shared_string_continue)); UiUtilities.setupDialogButton(nightMode, continueBtn, DialogButtonType.PRIMARY, getString(R.string.shared_string_continue));
continueBtn.setOnClickListener(new View.OnClickListener() { root.findViewById(R.id.continue_button_container).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
onContinueButtonClickAction(); if (expandableList.getHeaderViewsCount() <= 1) {
} if (hasSelectedData()) {
}); onContinueButtonClickAction();
ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver();
treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (buttonsContainer != null) {
ViewTreeObserver vts = buttonsContainer.getViewTreeObserver();
int height = buttonsContainer.getMeasuredHeight();
expandableList.setPadding(0, 0, 0, height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
vts.removeOnGlobalLayoutListener(this);
} else {
vts.removeGlobalOnLayoutListener(this);
} }
} else {
expandableList.smoothScrollToPosition(0);
} }
} }
}); });
@ -185,7 +186,11 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem
toolbar.setNavigationOnClickListener(new View.OnClickListener() { toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
showExitDialog(); if (hasSelectedData()) {
showExitDialog();
} else {
dismissFragment();
}
} }
}); });
} }
@ -204,16 +209,25 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem
continueBtn.setEnabled(false); continueBtn.setEnabled(false);
} else { } else {
updateWarningHeaderVisibility(false); updateWarningHeaderVisibility(false);
continueBtn.setEnabled(adapter.hasSelectedData()); continueBtn.setEnabled(hasSelectedData());
} }
itemsSizeContainer.setVisibility(View.VISIBLE); itemsSizeContainer.setVisibility(View.VISIBLE);
} else { } else {
updateWarningHeaderVisibility(false); updateWarningHeaderVisibility(false);
itemsSizeContainer.setVisibility(View.INVISIBLE); itemsSizeContainer.setVisibility(View.INVISIBLE);
continueBtn.setEnabled(adapter.hasSelectedData()); continueBtn.setEnabled(hasSelectedData());
} }
} }
public boolean hasSelectedData() {
for (List<?> items : selectedItemsMap.values()) {
if (!Algorithms.isEmpty(items)) {
return true;
}
}
return false;
}
private void updateWarningHeaderVisibility(boolean visible) { private void updateWarningHeaderVisibility(boolean visible) {
if (visible) { if (visible) {
if (expandableList.getHeaderViewsCount() < 2) { if (expandableList.getHeaderViewsCount() < 2) {
@ -255,13 +269,24 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem
updateAvailableSpace(); updateAvailableSpace();
} }
protected List<Object> getItemsForType(ExportSettingsType type) {
for (SettingsCategoryItems categoryItems : dataList.values()) {
if (categoryItems.getTypes().contains(type)) {
return (List<Object>) categoryItems.getItemsForType(type);
}
}
return null;
}
protected List<Object> getSelectedItemsForType(ExportSettingsType type) {
return (List<Object>) selectedItemsMap.get(type);
}
@Override @Override
public void onTypeClicked(ExportSettingsCategory category, ExportSettingsType type) { public void onTypeClicked(ExportSettingsType type) {
FragmentManager fragmentManager = getFragmentManager(); FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null && type != ExportSettingsType.GLOBAL && type != ExportSettingsType.SEARCH_HISTORY) { if (fragmentManager != null && type != ExportSettingsType.GLOBAL && type != ExportSettingsType.SEARCH_HISTORY) {
List<Object> items = (List<Object>) dataList.get(category).getItemsForType(type); ExportItemsBottomSheet.showInstance(fragmentManager, type, this, exportMode);
List<Object> selectedItems = (List<Object>) selectedItemsMap.get(type);
ExportItemsBottomSheet.showInstance(type, selectedItems, items, fragmentManager, this);
} }
} }
} }

View file

@ -14,11 +14,15 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.map.ITileSource; import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager.TileSourceTemplate; import net.osmand.map.TileSourceManager.TileSourceTemplate;
import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup;
import net.osmand.plus.GPXDatabase.GpxDataItem;
import net.osmand.plus.GpxDbHelper.GpxDataItemCallback;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.SQLiteTileSource;
@ -28,6 +32,7 @@ import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
@ -47,6 +52,7 @@ import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem;
import net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype;
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; import net.osmand.plus.settings.backend.backup.GlobalSettingsItem;
import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -67,18 +73,43 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
public static final String TAG = ExportItemsBottomSheet.class.getSimpleName(); public static final String TAG = ExportItemsBottomSheet.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(ExportItemsBottomSheet.class); private static final Log LOG = PlatformUtil.getLog(ExportItemsBottomSheet.class);
private static final String SETTINGS_TYPE_KEY = "settings_type_key";
private static final String EXPORT_MODE_KEY = "export_mode_key";
private OsmandApplication app; private OsmandApplication app;
private UiUtilities uiUtilities; private UiUtilities uiUtilities;
private ExportSettingsType type; private ExportSettingsType type;
private List<Object> allItems; private final List<Object> allItems = new ArrayList<>();
private List<Object> selectedItems = new ArrayList<>(); private final List<Object> selectedItems = new ArrayList<>();
private TextView selectedSize; private TextView selectedSize;
private ThreeStateCheckbox checkBox; private ThreeStateCheckbox checkBox;
private int activeColorRes; private int activeColorRes;
private int secondaryColorRes; private int secondaryColorRes;
private boolean exportMode;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
exportMode = savedInstanceState.getBoolean(EXPORT_MODE_KEY);
type = ExportSettingsType.valueOf(savedInstanceState.getString(SETTINGS_TYPE_KEY));
}
Fragment target = getTargetFragment();
if (target instanceof BaseSettingsListFragment) {
BaseSettingsListFragment fragment = (BaseSettingsListFragment) target;
List<Object> items = fragment.getItemsForType(type);
if (items != null) {
allItems.addAll(items);
}
List<Object> selectedItemsForType = fragment.getSelectedItemsForType(type);
if (selectedItemsForType != null) {
selectedItems.addAll(selectedItemsForType);
}
}
}
@Override @Override
public void createMenuItems(Bundle savedInstanceState) { public void createMenuItems(Bundle savedInstanceState) {
@ -111,11 +142,18 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
}) })
.setTag(object); .setTag(object);
setupBottomSheetItem(builder, object); setupBottomSheetItem(builder, object);
item[0] = (BottomSheetItemWithCompoundButton) builder.create(); item[0] = builder.create();
items.add(item[0]); items.add(item[0]);
} }
} }
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(EXPORT_MODE_KEY, exportMode);
outState.putString(SETTINGS_TYPE_KEY, type.name());
}
private BaseBottomSheetItem createTitleItem() { private BaseBottomSheetItem createTitleItem() {
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode); LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
View view = themedInflater.inflate(R.layout.settings_group_title, null); View view = themedInflater.inflate(R.layout.settings_group_title, null);
@ -153,7 +191,30 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes; int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor))); CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
selectedSize.setText(getString(R.string.ltr_or_rtl_combine_via_slash, selectedItems.size(), allItems.size())); String description;
if (type == ExportSettingsType.OFFLINE_MAPS && !selectedItems.isEmpty()) {
String size = AndroidUtils.formatSize(app, calculateSelectedItemsSize());
String selected = getString(R.string.ltr_or_rtl_combine_via_slash, selectedItems.size(), allItems.size());
description = getString(R.string.ltr_or_rtl_combine_via_comma, selected, size);
} else {
description = getString(R.string.ltr_or_rtl_combine_via_slash, selectedItems.size(), allItems.size());
}
selectedSize.setText(description);
}
private long calculateSelectedItemsSize() {
long itemsSize = 0;
for (int i = 0; i < allItems.size(); i++) {
Object object = allItems.get(i);
if (selectedItems.contains(object)) {
if (object instanceof FileSettingsItem) {
itemsSize += ((FileSettingsItem) object).getSize();
} else if (object instanceof File) {
itemsSize += ((File) object).length();
}
}
}
return itemsSize;
} }
private void updateItems(boolean checked) { private void updateItems(boolean checked) {
@ -184,15 +245,13 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
dismiss(); dismiss();
} }
public static void showInstance(@NonNull ExportSettingsType type, List<Object> selectedItems, List<?> allItems, @NonNull FragmentManager fm, @Nullable Fragment target) { public static void showInstance(@NonNull FragmentManager fm, @NonNull ExportSettingsType type,
@NonNull BaseSettingsListFragment target, boolean exportMode) {
try { try {
if (!fm.isStateSaved() && fm.findFragmentByTag(TAG) == null) { if (!fm.isStateSaved() && fm.findFragmentByTag(TAG) == null) {
ExportItemsBottomSheet fragment = new ExportItemsBottomSheet(); ExportItemsBottomSheet fragment = new ExportItemsBottomSheet();
fragment.type = type; fragment.type = type;
fragment.allItems = (List<Object>) allItems; fragment.exportMode = exportMode;
if (selectedItems != null) {
fragment.selectedItems.addAll(selectedItems);
}
fragment.setTargetFragment(target, 0); fragment.setTargetFragment(target, 0);
fragment.show(fm, TAG); fragment.show(fm, TAG);
} }
@ -211,7 +270,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
return null; return null;
} }
private void setupBottomSheetItem(BottomSheetItemWithCompoundButton.Builder builder, Object object) { private void setupBottomSheetItem(Builder builder, Object object) {
if (object instanceof ApplicationModeBean) { if (object instanceof ApplicationModeBean) {
ApplicationModeBean modeBean = (ApplicationModeBean) object; ApplicationModeBean modeBean = (ApplicationModeBean) object;
String profileName = modeBean.userProfileName; String profileName = modeBean.userProfileName;
@ -254,10 +313,11 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
builder.setTitle(tileSource.getName()); builder.setTitle(tileSource.getName());
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_map, activeColorRes));
} else if (object instanceof File) { } else if (object instanceof File) {
setupBottomSheetItemForFile(builder, (File) object); File file = (File) object;
setupBottomSheetItemForFile(builder, file, file.lastModified(), file.length());
} else if (object instanceof FileSettingsItem) { } else if (object instanceof FileSettingsItem) {
FileSettingsItem fileSettingsItem = (FileSettingsItem) object; FileSettingsItem item = (FileSettingsItem) object;
setupBottomSheetItemForFile(builder, fileSettingsItem.getFile()); setupBottomSheetItemForFile(builder, item.getFile(), item.getLastModified(), item.getSize());
} else if (object instanceof AvoidRoadInfo) { } else if (object instanceof AvoidRoadInfo) {
AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object; AvoidRoadInfo avoidRoadInfo = (AvoidRoadInfo) object;
builder.setTitle(avoidRoadInfo.name); builder.setTitle(avoidRoadInfo.name);
@ -275,6 +335,9 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
builder.setTitle(group.getDisplayName(app)); builder.setTitle(group.getDisplayName(app));
int color = group.getColor() == 0 ? ContextCompat.getColor(app, R.color.color_favorite) : group.getColor(); int color = group.getColor() == 0 ? ContextCompat.getColor(app, R.color.color_favorite) : group.getColor();
builder.setIcon(uiUtilities.getPaintedIcon(R.drawable.ic_action_folder, color)); builder.setIcon(uiUtilities.getPaintedIcon(R.drawable.ic_action_folder, color));
int points = group.getPoints().size();
String itemsDescr = getString(R.string.shared_string_gpx_points);
builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, points));
} else if (object instanceof GlobalSettingsItem) { } else if (object instanceof GlobalSettingsItem) {
GlobalSettingsItem globalSettingsItem = (GlobalSettingsItem) object; GlobalSettingsItem globalSettingsItem = (GlobalSettingsItem) object;
builder.setTitle(globalSettingsItem.getPublicName(app)); builder.setTitle(globalSettingsItem.getPublicName(app));
@ -285,9 +348,12 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
builder.setTitle(getString(R.string.map_markers)); builder.setTitle(getString(R.string.map_markers));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_flag, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_flag, activeColorRes));
} else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) { } else if (ExportSettingsType.HISTORY_MARKERS.name().equals(markersGroup.getId())) {
builder.setTitle(getString(R.string.map_markers)); builder.setTitle(getString(R.string.markers_history));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes));
} }
int selectedMarkers = markersGroup.getMarkers().size();
String itemsDescr = getString(R.string.shared_string_items);
builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, selectedMarkers));
} else if (object instanceof HistoryEntry) { } else if (object instanceof HistoryEntry) {
HistoryEntry historyEntry = (HistoryEntry) object; HistoryEntry historyEntry = (HistoryEntry) object;
builder.setTitle(historyEntry.getName().getName()); builder.setTitle(historyEntry.getName().getName());
@ -295,8 +361,8 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
} }
} }
private void setupBottomSheetItemForFile(Builder builder, File file) { private void setupBottomSheetItemForFile(Builder builder, File file, long lastModified, long size) {
FileSettingsItem.FileSubtype fileSubtype = FileSettingsItem.FileSubtype.getSubtypeByPath(app, file.getPath()); FileSubtype fileSubtype = FileSubtype.getSubtypeByPath(app, file.getPath());
builder.setTitle(file.getName()); builder.setTitle(file.getName());
if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) { if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) {
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_map_style, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_map_style, activeColorRes));
@ -304,6 +370,8 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) { } else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) {
builder.setTitle(GpxUiHelper.getGpxTitle(file.getName())); builder.setTitle(GpxUiHelper.getGpxTitle(file.getName()));
builder.setTag(file);
builder.setDescription(getTrackDescr(file, lastModified, size));
builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes));
} else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) { } else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) {
int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file);
@ -316,6 +384,85 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment {
|| fileSubtype == FileSettingsItem.FileSubtype.VOICE) { || fileSubtype == FileSettingsItem.FileSubtype.VOICE) {
builder.setTitle(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName())); builder.setTitle(FileNameTranslationHelper.getFileNameWithRegion(app, file.getName()));
builder.setIcon(uiUtilities.getIcon(fileSubtype.getIconId(), activeColorRes)); builder.setIcon(uiUtilities.getIcon(fileSubtype.getIconId(), activeColorRes));
if (fileSubtype.isMap()) {
String mapDescription = getMapDescription(file);
String formattedSize = AndroidUtils.formatSize(app, size);
if (mapDescription != null) {
builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_star, mapDescription, formattedSize));
} else {
builder.setDescription(formattedSize);
}
}
} }
} }
private final GpxDataItemCallback gpxDataItemCallback = new GpxDataItemCallback() {
@Override
public boolean isCancelled() {
return false;
}
@Override
public void onGpxDataItemReady(GpxDataItem item) {
for (BaseBottomSheetItem bottomSheetItem : items) {
if (Algorithms.objectEquals(item.getFile(), bottomSheetItem.getTag())) {
((BottomSheetItemWithDescription) bottomSheetItem).setDescription(getTrackDescrForDataItem(item));
break;
}
}
}
};
private String getTrackDescr(@NonNull File file, long lastModified, long size) {
String folder = "";
File parent = file.getParentFile();
if (parent != null) {
folder = Algorithms.capitalizeFirstLetter(parent.getName());
}
if (exportMode) {
GpxDataItem dataItem = getDataItem(file, gpxDataItemCallback);
if (dataItem != null) {
return getTrackDescrForDataItem(dataItem);
}
} else {
String date = OsmAndFormatter.getFormattedDate(app, lastModified);
String formattedSize = AndroidUtils.formatSize(app, size);
String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, date);
return getString(R.string.ltr_or_rtl_combine_via_comma, descr, formattedSize);
}
return null;
}
private String getTrackDescrForDataItem(@NonNull GpxDataItem dataItem) {
GPXTrackAnalysis analysis = dataItem.getAnalysis();
if (analysis != null) {
File parent = dataItem.getFile().getParentFile();
String folder = Algorithms.capitalizeFirstLetter(parent.getName());
String dist = OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app);
String points = analysis.wptPoints + " " + getString(R.string.shared_string_gpx_points).toLowerCase();
String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, dist);
return getString(R.string.ltr_or_rtl_combine_via_comma, descr, points);
}
return null;
}
private GpxDataItem getDataItem(File file, @Nullable GpxDataItemCallback callback) {
return app.getGpxDbHelper().getItem(file, callback);
}
private String getMapDescription(File file) {
if (file.isDirectory() || file.getName().endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT)) {
return getString(R.string.online_map);
} else if (file.getName().endsWith(IndexConstants.BINARY_ROAD_MAP_INDEX_EXT)) {
return getString(R.string.download_roads_only_item);
} else if (file.getName().endsWith(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT)) {
return getString(R.string.download_wikipedia_maps);
} else if (file.getName().endsWith(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)) {
return getString(R.string.download_srtm_maps);
} else if (file.getName().endsWith(IndexConstants.BINARY_MAP_INDEX_EXT)) {
return getString(R.string.download_regular_maps);
}
return null;
}
} }

View file

@ -18,6 +18,7 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.FontCache; import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.mapmarkers.MapMarkersGroup;
import net.osmand.plus.settings.backend.ExportSettingsCategory; import net.osmand.plus.settings.backend.ExportSettingsCategory;
import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.FileSettingsItem; import net.osmand.plus.settings.backend.backup.FileSettingsItem;
@ -54,6 +55,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
private final boolean nightMode; private final boolean nightMode;
private final int activeColorRes; private final int activeColorRes;
private final int secondaryColorRes; private final int secondaryColorRes;
private final int groupViewHeight;
private final int childViewHeight;
private final int listBottomPadding;
ExportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) { ExportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) {
this.app = app; this.app = app;
@ -63,6 +67,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
themedInflater = UiUtilities.getInflater(app, nightMode); themedInflater = UiUtilities.getInflater(app, nightMode);
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_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; secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
groupViewHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_group_height);
childViewHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_large_height);
listBottomPadding = app.getResources().getDimensionPixelSize(R.dimen.fab_recycler_view_padding_bottom);
} }
@Override @Override
@ -70,6 +77,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
View group = convertView; View group = convertView;
if (group == null) { if (group == null) {
group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false);
group.findViewById(R.id.item_container).setMinimumHeight(groupViewHeight);
} }
final ExportSettingsCategory category = itemsTypes.get(groupPosition); final ExportSettingsCategory category = itemsTypes.get(groupPosition);
final SettingsCategoryItems items = itemsMap.get(category); final SettingsCategoryItems items = itemsMap.get(category);
@ -108,6 +116,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
} }
}); });
boolean addPadding = !isExpanded && groupPosition == getGroupCount() - 1;
group.setPadding(0, 0, 0, addPadding ? listBottomPadding : 0);
adjustIndicator(app, groupPosition, isExpanded, group, nightMode); adjustIndicator(app, groupPosition, isExpanded, group, nightMode);
AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded); AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded);
AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true); AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true);
@ -122,6 +133,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
View child = convertView; View child = convertView;
if (child == null) { if (child == null) {
child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false);
child.findViewById(R.id.item_container).setMinimumHeight(childViewHeight);
} }
final ExportSettingsCategory category = itemsTypes.get(groupPosition); final ExportSettingsCategory category = itemsTypes.get(groupPosition);
final SettingsCategoryItems categoryItems = itemsMap.get(category); final SettingsCategoryItems categoryItems = itemsMap.get(category);
@ -157,7 +169,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (listener != null) { if (listener != null) {
listener.onTypeClicked(category, type); listener.onTypeClicked(type);
} }
} }
}); });
@ -174,7 +186,8 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
notifyDataSetChanged(); notifyDataSetChanged();
} }
}); });
boolean addPadding = isLastChild && groupPosition == getGroupCount() - 1;
child.setPadding(0, 0, 0, addPadding ? listBottomPadding : 0);
AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild); AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild);
return child; return child;
@ -247,10 +260,6 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
notifyDataSetChanged(); notifyDataSetChanged();
} }
public boolean hasSelectedData() {
return !selectedItemsMap.isEmpty();
}
public List<? super Object> getData() { public List<? super Object> getData() {
List<Object> selectedItems = new ArrayList<>(); List<Object> selectedItems = new ArrayList<>();
for (List<?> items : selectedItemsMap.values()) { for (List<?> items : selectedItemsMap.values()) {
@ -307,6 +316,10 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
itemsSize += ((FileSettingsItem) object).getSize(); itemsSize += ((FileSettingsItem) object).getSize();
} else if (object instanceof File) { } else if (object instanceof File) {
itemsSize += ((File) object).length(); itemsSize += ((File) object).length();
} else if (object instanceof MapMarkersGroup) {
int selectedMarkers = ((MapMarkersGroup) object).getMarkers().size();
String itemsDescr = app.getString(R.string.shared_string_items);
return app.getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, selectedMarkers);
} }
} }
} }
@ -332,7 +345,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
void onCategorySelected(ExportSettingsCategory type, boolean selected); void onCategorySelected(ExportSettingsCategory type, boolean selected);
void onTypeClicked(ExportSettingsCategory category, ExportSettingsType type); void onTypeClicked(ExportSettingsType type);
} }
} }

View file

@ -11,7 +11,6 @@ import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@ -76,14 +75,8 @@ public class ExportSettingsFragment extends BaseSettingsListFragment {
progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY); progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY);
progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY);
} }
exportMode = true;
dataList = app.getSettingsHelper().getAdditionalData(globalExport); dataList = app.getSettingsHelper().getAdditionalData(globalExport);
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
showExitDialog();
}
});
} }
@Nullable @Nullable

View file

@ -12,7 +12,6 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -101,13 +100,8 @@ public class ImportSettingsFragment extends BaseSettingsListFragment {
if (savedInstanceState != null) { if (savedInstanceState != null) {
duplicateStartTime = savedInstanceState.getLong(DUPLICATES_START_TIME_KEY); duplicateStartTime = savedInstanceState.getLong(DUPLICATES_START_TIME_KEY);
} }
exportMode = false;
settingsHelper = app.getSettingsHelper(); settingsHelper = app.getSettingsHelper();
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
showExitDialog();
}
});
ImportAsyncTask importTask = settingsHelper.getImportTask(); ImportAsyncTask importTask = settingsHelper.getImportTask();
if (importTask != null) { if (importTask != null) {